Blog

Spawn of Satan

Or spawn of me, at any rate.

Events in MFoN take place in the form of “Encounters”. There are combat encounters, store encounters, conversation encounters, and so on. Each 32×32 pixel square in the game can potentially contain any number of encounters (it’s the same “grid” on which the players move). Each encounter in each square can have a different chance to appear. For example, some of the Haystacks in the old version had a 10% chance to cause a sneezing fit when entered or searched, and a 0.0001% chance of giving you a Vorpal Needle (a particularly nice item). When checking an area, the game rolls a random number, then goes to get any encounters that have that high a chance. One of the resulting list is picked at random. So if the “roll” was 5.23, you would get a sneezing fit. A roll of 11.777 meant you got nothing, and a roll of 0.0001 or less meant you had a 50/50 chance of getting the Vorpal Needle or a sneezing fit.

With the changes to combat, some new problems came up. Your opponent(s) would need to show up someplace accessible on the screen. The initial solution was to let the combat encounter specify a distance at which the enemy would appear, and let the game find something accessible at that distance from your character, on whatever square he/she triggered the encounter. Unfortunately, “accessible” wasn’t necessarily anywhere close. If you were standing next to a wall, it could put the enemy on the other side of the wall, even though to get to you it would have to step 40 paces.

A prime example is the “Rats in the Garden” quest. It’s a simple kill-the-rats quest, where you’re supposed to hunt down and kill rats infesting the garden. It would make the most sense for them to therefore appear in the garden somewhere, but they were showing up on the other side of the wall, inside the fortified building, or behind the well…usually anywhere except the garden.

So I added Spawn Points. Now I can specify exactly where a particular actor can pop up on a given map. I can give the rats various spawn points in the garden, so that when they spawn, they’ll appear in the garden where it makes sense.

I can do other neat stuff with this too. If you’re walking through a dangerous town, I can have spawn points for difficult-to-reach snipers, which might not be anywhere near you, but could have a clear line of sight. The sneaky possibilities are tantalizing. And the action looks a lot better, too.

Head in the Clouds

There’s something I’ve always wanted to do with Muties, but could never figure out how to do.

I wanted to be able to have some graphics on top of the characters. Like semi-transparent clouds scudding over the characters’ heads, open windows, or maybe some fencing the player visually walks behind. The problem is that once you put a graphic (or any HTML element) in front of another, the one you covered is isolated from the mouse.

Let me give an example: On the screen you have noble Bob, minding his own business. Bob is a 32 x 32 pixel graphic…specifically he’s an image (IMG) tag. That image tag has events for mouseover (“display the tooltip”), mouseout (“hide the tooltip”), and click (“pick Bob to talk to him”). Now we draw a chain-link fence in front of him by adding another image tag that covers Bob, and has an appropriate cross-hatched pattern to it. You can see Bob through the fence, but when you move the mouse over Bob, you’re actually moving it over the chain-link fence covering Bob. While the fence graphic displayed might very well be mostly transparent, the element itself is solid. The fence is getting the mouseover, mouseout, and click events now…not Bob. Now of course you could monitor the mouse coordinates, run a few calculations, and search through elements on the page to find something besides the fence that is in the same place (IE: Bob). But that’s ugly, potentially painful, and certainly messy. Then you have draggable items. You’d have to do that mess to find them, then update their position every time the mouse moved.

But today I had a brainstorm. I added another image, which I dubbed “Clouds”. Then I created a map element, which is used to make an image map. A map tag contains any number of area tags, which define a clickable region on the image to which the map is attached. In my case, I left the map empty.

When an actor (character) or tooltip is added to the map, I know their coordinates. So instead of hooking up a tooltip to the image of the actor (or a blank spacer graphic for raw tooltips), I dynamically create an area element and insert it into the map element. The area element gets the mouse events. The new area event is associated with the actor, so that if the actor is moved, it’s fairly trivial to move the area tag also.

Really that’s all there is to it. The area tag’s mouseover triggers the appropriate tooltip, and the area’s click event triggers the same call the actor click did. To the user, it just seems like they’re clicking on the actor like they were before. But now I have a cloud layer that can contain some interesting effects.

Oh, and to solve the drag and drop problem of items, I cheated. Store items work like loot items now, in that a container appears on the screen, and you click on that to open a window containing the actual items. 🙂

Making the Maps

A couple of people sworn to secrecy, under pain of death, are beating on the tutorial level right now. That level covers all the basics of moving, fighting, buying, selling, looting, etc. It was also a great test of the new game engine, since a lot of the behavior on that map is not standard and therefore worked out the new scripting system. For example, in combat creatures normally pursue you across the map to fight you, but in the tutorial there’s a training dummy that needs to stay put. Letting people play the tutorial also tests the entire interface and the new client JavaScript engine.

Three glitches have appeared during the tutorial testing, all within the first few minutes:

  1. No store item appeared where it was supposed to. This turned out to be because I forgot to create the store on the live server (oops). When the item still didn’t appear, it took a while to figure out that it was an unapproved item (until items are approved, only admin accounts can see them). I marked it approved and it showed up, and that all worked fine.
  2. No combat showed up where it was supposed to. It didn’t take as long to figure out that the combats needed approval also.
  3. One MySQL query blew up…and it was the kind I hate. You know what I’m talking about: the kind that you wonder how it ever worked in the first place. It was a quick fix.

So really just one actual bug. The rest was forgetfulness and the system working exactly as it should. Since I’m largely working live now, the forgetfulness should be less of a factor.

Speaking of working, here’s the editor in some of its glory:

I had a really nice (and I do mean NICE) browser-based editor. When the size of the maps increased, it was just too much for that editor and I had to write another one. The new one is written in C# and makes extensive use of GDI+, and it generates much better composite graphics than I had ever been able to manage with GD2.

You can see I’m going for a much messier/used look. You can see three characters on the map (not counting the goats), who are the three that I absolutely must have at this point. Not coincidentally, they are all shopkeepers too:

  1. Brother Morales – He’s the monk in the upper-right. He is the librarian, healer, chaplain, and occasional judge. He’s actually pretty low in the Atomic Order, as are all monks stationed to individual compounds and clans. He sells bandages.
  2. Chef Andy – He cooks for the clan. Nothing fancy, but lots of it. Besides cooking he’s also in charge of food production. You can buy hard bread and goat cheese from him.
  3. Mob Barley – Mob runs the still, and sells the resulting booze. He doesn’t contribute much to the clan, but people do like their hooch.

There are certainly going to be other characters, these are just the three in there so far. I have (very) faint hopes of still meeting my self-imposed October 1 deadline for full beta testing, but I can’t say that looks terribly likely. I’m doing all I can on evenings and weekends, but there’s only so much a single person can do. Rest assured it IS still coming, and WILL still be done. With luck, the beta might be pushed back a little but go smoothly enough that the full launch on October 31 still happens.

Back to work!

Tutorials, Actors, and Flexible Shops

The code has gotten pretty stable and I’ve started spending my time writing the tutorial level. It should cover how to use the interface, how to pick perks and add attribute points, using items, how to manage combat, etc.

Tutorial

Right after the player picks the “Ok, so let’s finish…” line, Brother Morris walks down a bit and waits for the player to come down and talk to him again (by clicking on him…see the chat cursor?). That will start the next part of the tutorial.

The tutorial also makes use of a couple of small code features I added recently:

Stores Anywhere

The standard way of handling stores is to draw inventory, security, manager, entrance, and exit squares on a map. I then set up that particular map as a store map (making it a store class), and create a store based on that store class. I can then set up the inventory of that store. When the player selects a store from the market interface, they are actually taken to the map specified by the store’s store class. Maps used this way really can’t be used for anything else.

What I added was a way to set up a different sort of store class. I can now add inventory slots to an otherwise normal map, create a special type of store class from that, and tell the map to draw its inventory. This provides store inventory slots on a normal map…you can purchase items from a normal map without “entering” a store as normal.

This is really nice with the larger maps that I can make now, so the compound you start in can just have an old man in the corner selling a few things, all as part of the bigger picture.

Persistent Actors

Actors (NPCs) have been very static characters. They’ve been defined and programmed, and work exactly the same way for everybody. That includes their location. If you see them standing in a corner of Casa Vista, then they pretty much had to stay there unless I wanted to write a lot of finicky script changes and store bits of data on your character.

Now I can say “Hey, Mr. Actor Person, PERSIST.” That creates a copy of that actor just for your character, with its own data, reputation, and location information. Once the actor has been persisted I can move him around at will and it will stick without me having to jump through any hoops. And since I can also stash any arbitrary data with him, and his scripts are part of him, I can pretty well define his complete set of behavior as a single unit. Spiffy!

That’s enough for now…back to work!

XML vs. Databases for Static Content

With the new way conversations are handled in Mutant Freaks of Nature, I had to write a new editor to manage them. The conversations are actually structured in a classic tree structure, with each NPC branch leading to any number of potential player responses. The player responses, in turn, can each lead to a single NPC branch, or can jump to another branch anywhere else in the tree.

The original version of the conversation trees were stored in two MySQL tables:


tbl_npc_node
:

npc_node_id parent_response_node node_content
1 0 Hi, my name is Bob!
2 2 Nice to see a friendly face.


tbl_response_node
:

response_node_id parent_npc_node node_content
1 1 Yeah? Who cares?
2 1 Hey, good to meet you.

For the astute among you, yes, it does look like I could have used a single table to store both types. I haven’t included other columns unique to each type of node, however. The conversation the tables above represent would go something like this:

Or the other way…

Not a lot of difference, but it may give you an idea of the structure. The problem was that changing one small piece of the conversation changed a row in the database. This meant a call to the server and database hits every time a piece was changed. The structure also meant that building the tree to work on the conversation as a whole was a pile of recursive queries that had to be reassembled into a tree-like structure and edited.

After fixing yet one more problem with the tree editor, I decided there had to be a better way. I reasoned that there had to be a simpler way to store and edit data with that kind of structure. Sometimes we overlook the simple ways, and make things harder than they need to be. The answer to my dilemma was simple XML:

Here’s an early bit of XML from the Tutorial conversation. All the structure I need is there, and without all the hopping about in tables. To update the conversation, I change the file in my favorite XML editor and upload the whole thing.

The only remaining question is performance. A static file sitting on the server is always more efficient that grabbing it from the database, and that’s the catch here. This works well as long as the XML file isn’t being actively modified by an editor, which is the case with conversations. There is some overhead from reading the XML file and navigating to the correct node, but it’s actually pretty minor compared to nested database calls.

Now that that’s out of the way, it’s back to finishing the tutorial.

Mutant CSS Sprites

“CSS Sprites” are one of those things that’s been around for a little bit, but that I’ve only recently read about. Learning about them inspired a slap-myself-on-the-forehead moment. Why hadn’t I thought of that?

“CSS Sprites” are one of those things that’s been around for a little bit, but that I’ve only recently read about. Learning about them inspired a slap-myself-on-the-forehead moment. Why hadn’t I thought of that?

Mutant Freaks of Nature uses a bunch of little icons in the game. There’s several arrows…for example:

Up-Left Arrow Up Arrow Up-Right Arrow

Just the nine navigation icons are 4,663 bytes. The complete collection of icons used on the new front page of the game counts up to 14,702 bytes. More important than the size is how it clogs up the connection. Each graphic downloaded comes with its own connection between the browser and the server, its own headers, and its own cache management. Also, consider that browsers are generally limited to two connections to a server at the same time. The base set of 22 icons requires a stack of round trips to the server before the page can finish loading, and they aren’t the only things being downloaded.

Wouldn’t it be nice if we could download them all at once? Something like this:

Tile graphic

This contains all 22 icons (14,702 bytes individually), but only weighs 11,260 bytes. And it would be a single download! That would save quite a few headers. Fortunately, CSS gives us a way to manage this.

The typical html for one of the icons is something like this:

CSS can help. We create a style class:

Now we can do this a little differently:

The style makes the image 16×16 pixels and puts the tile graphic in as the background. By default it will be set in the upper-left corner of the image. The result will be the upper-left arrow displayed in the image tag. “blank.png” is needed for Firefox, since if there’s no valid image Firefox will completely hide the image. Of course, with the source of the image being just a placeholder now, maybe we don’t really need the image itself:

Yep, that gets you the same result as the img tag, with one caveat. It won’t “flow” like a series of images will. It can still be positioned absolutely, of course

To get different icons in our sprite, we just shift the position of the background graphic with custom styles, like thus:

That displays the little binoculars as the graphic. The background is moved 16 pixels up and left so that the div is framing the binoculars. The rest of the image is hidden.

And that’s the gist of how it works, except for a Mutation we’ve given it. The game engine automatically does some processing on information returned by the server, so we’ve added a little more to that, resulting in a fancy shorthand for our sprites:

The sx and sy custom attributes are converted into the background-position attribute automagically. It might be worth mentioning that at any point we can modify the sx/xy of an existing icon or graphic with a simple command. We could even put that on a timer

I’ll let you figure out what that might mean. 🙂