Well, it's update time again, and it's because I have something interesting to talk about. I'm sure I've mentioned my database format plenty of times, even if I've never covered it in great deal. It's a series of nested maps with extra data attached for error-handling, features, and management. The more I use it, the more I've come to both rely on and find new ways it can be helpful. In the last post, I talked about how the shop uses a "simple" scripting system to drive the menus and decision making. Well, the last major feature I need to complete is battles.
With the shops, I discovered an interesting pattern: I can store information as entries in the database, but what if the "shape" is arbitrary? Things like swords and classes have specific needs: a name, price, etc... There is a defined shape they have to have, and they inherit templates specifically to ensure they all have this data! Shops don't quite work in this way. While they have some data that is required, such as graphical information and a name, the menus sequences are more flexible. When I write a shop, I create the sequences and variables in those definitions. A shop is whatever I make it. It has rules to follow and limitations, yes, but many entries are a product of their own definition. So, for battle, a similar conundrum exists: the animations. I could hard-code the different casting and attacking animations, but what if I want to add more later? I'd have to crack open the engine, add a new case, add an entry to the database to flag it, etc... Too much work and disturbingly similar to my failed first attempt at shops. I want a new animation, why can't I define one?
Good question. Why not? Animations are defined in the database:
GML:
weapon = {
speed = 4;
repeat = 2;
animation = "swing0,swing1";
frames = {
$template:template.frame;
swing0 = { battler = { frame = @frame.attack; } sfx = { x = 22; y = -10; sprite = "weaponSprite"; frame = "weaponIndex"; palette = "weaponPalette"; rotate = 270; } }
swing1 = { battler = { frame = @frame.walk; } sfx = { x = -14; y = 1; sprite = "weaponSprite"; frame = "weaponIndex"; palette = "weaponPalette"; } }
}
}
Like shop sequences, the list of frames in an animation is defined by the "animation" entry. And like shops, these frames are looked up in the "frames" table. How many frames are used, what they look like, or what they do is up to the tools available. In this case, each frame consists of two layers: the battler layer and the SFX layer. If a layer is not defined, it isn't drawn. Each layer consists of a sprite index, image index, palette, x, y, and rotate value. In addition to that, values can be hard-coded into the animation itself, or looked up in the battler playing the animation. In the above example, the weapon sprite, index and palette are all retrieved from the cached battler data where as the x and y positions are defined explicitly. And the results?
Coincidentally, the whole reason I started investigating this solution was because of magic. Technically it only has one animation, but I wanted to be able to make new spell-casting animations. Fighting has two animations: with weapons and unarmed, so why does magic have to have only one? Originally only the draw data was stored in an item/spell, and looked up by the animation for display. Why couldn't each weapon and spell define it's own custom animation? Well, like the shops, this opens the door to add new animations that never existed in the game and all without touching the engine. Why
not do that?
Well, isn't that wonderful! Now, I don't know if I've ever talked about this specific aspect of it before, but the databases at this point are pretty huge. Originally it was just a convenience thing: an experiment really, and mostly for localization. Strings were the first thing to get looked up in the database, and this makes it possible to inherit a different language file. By writing a new file, the game displays in a different language. Voila! Of course, it also allows me to add new items, enemies, and spells, but it also allows patching. For example, I can define the original animation and sprite in the rapier, then load a patch to have it look like this instead. Why? Well, my goal of maintaining two separate games: one that stays true to the original, and also allowing me the freedom to make little changes I like, is suddenly more accessible. Much like the color palette of the render, the game has much custom potential. It also, however, opens the game up pretty extensively for modding potential. While that was never my intention, it is yet another interesting effect of having taken this approach. So much of the game is in these external databases now it's possible to rewrite chunks of it with nothing more than notepad. While a patch loader is relatively trivial, it's fair to say that a lot of the game is still very hard-coded. It's not possible to add a new dungeon, for example, with just the files, but it's still an interesting side-effect.
It's fairly evident from the picture above, but I feel it's worth addressing: the battle scene, in my opinion, was awful in the original game. Trying to recreate all of its idiosyncrasies is plenty doable, but I have no desire to. Some of this is from watching Free Enterprise. I have developed some new opinions about UX because of it, and the original battle system is clunky, limiting, and slow. Still, there is some precedent: Final Fantasy 2 uses a similar format. As anyone who has followed my progress knows, I waver and struggle with how accurate this can all be, and most people tell me to improve the game as I see fit. Well, this is the single most dramatic departure. It would be possible to add the original scene later on if it starts to bother me, but this is the direction I'm taking right now.