Chapter Four: Sprites and Graphical Data Animation Routines Lots of stuff just used for graphics, huh? Well don't get settled just yet because the main course is still to come. :) So far, in flingy.dat, sprites.dat, and images.dat, the variables don't really control too much about how the sprite actually moves around; the DAT files only control very peripheral things that some sprites may not even need. So we're still left with the question: how do you get a simple list of image frames in a GRP to actually move and animate properly when it is controlled in the game? The answer is the iscript.bin, or the "image script" file. The iscript is a (very compact) compilation of many sets of animation scripts or routines. Basically, an animation routine is just a string of commands or "opcodes" that are run in order. For example: -
Play frame 1 When this routine is run, each opcode is executed in order, and then at the end it goes to another line in the script and begins executing further opcodes from there. Think of it as a play script that the sprites follow. To understand how to "safely" edit the iscript.bin (e.g., without messing it up so it won't work), a bit has to be said about its structure. Near the end of the iscript (or, normally at the end of the iscript, it doesn't matter where it is really) is a table of pointers to each set of animation routines. Each Iscript ID (from images.dat) is associated with a particular line in the iscript that determines where this set of animations is located in the file. For example:
Of course all this data is normally compressed, but mnemonically, you get the idea. So depending on what the images.dat Iscript ID is, Starcraft will look up where its set of animation scripts is located in the iscript by looking through this table (correlating the ID with a line number, or offset). Once it finds the set of routines to use, it meets up with another table. This table lists the locations of each specific animation routine in the iscript. Each image usually has several animations, one to play initially when it is created, one to play when it is destroyed, one to play when it moves, one to play when it attacks ground units, one to play when it attacks air units, one to play when it casts spells, and many more. The number of different animations a set has depends on its animation set "type" (which is determined by the first variable in this table). Most units have 14-28 different animations, and thus this table usually has 14-28 different pointers to various locations in the iscript to define where the animation routines actually are. For example:
Etc... This is usually referred to as the animation set header. You will notice that many animation routines are pointing to line 0. While some animation sets to share animation routines (they point to the same one), a line pointing to 0 means that there is no routine for this specific animation in this set (because there is nothing at line 0 :). If you try to access this animation routine (e.g., say you try to make a normal zealot attack an air unit), Starcraft will try to read off the script at line 0 and, since there are no valid opcodes there, it will crash. It is useful to note that 90% of all crashes experienced by any starcraft editor is due to the fact that there is an invalid animation routine executed (Starcraft will always try to execute the animations, but if it meets up with some unknown opcodes, or tries to play frames in an image that don't exist, then it will bomb). So where does that leave us now? Well, once we get to each of those lines, we will find a specific animation routine to run for that specific action. See the example at the top. When Starcraft gets to this point, it will simply execute the opcodes. To summarize and recap from previous sections: this is how animations are called, and basically work: 1) An order is given to the unit (like walk, attack, cast spell, etc.). This is done either by the player (i.e., move) or internally by Starcraft's auto AI (i.e., die, move to location to begin attack, idle) 2) The current animation running for the sprite stops in mid-script (unless it is in an "unbreakable" opcode routine -- in which case it will wait until the unbreakable section is finished; see next section for more information). 3) The unit turns to the direction of its target (if it has one). Flingy.dat controls the turning rate/style. 4) Then it begins the animation associated with the order it got. It will continue with that animation simply following the code along and follow all the "goto" commands it comes to. Usually, one of the gotos will eventually loop the script. And it will continue with this until it gets another order. [A couple notes: Opcode 0x16 (will be labeled mnemonically in the editing programs) will end the animation completely and remove the sprite. When a unit is spawned, it automatically begins its "Initial animation," which, among other things, usually spawns the shadow sprite for the unit.] A final, very important note is to remember that the iscript.bin is a very, very compact and compressed file. There is virtually no room anywhere between animation set headers and the scripts themselves. Thus, one wrong opcode here or there (even if valid) could make headers with the wrong number of offsets, routines run into each other, and a whole morass of crazy things that are certain to mess up many, many animation routines (even if the one you were editing was done correctly). In addition, you can not simply "insert" additional opcodes into the raw animation script. You will note that there are a lot of line pointers in the headers and even in the scripts themselves (goto line...). Thus, if you insert an opcode (or anything) in the middle of the iscript somewhere, it will throw all those pointers off. Thus, generally you will only overwrite current opcodes (making sure not to exceed the animation routine's original length) or add additional routines at the end of the iscript file, since tacking on more stuff at the end won't throw off any pointers above it. This type of "limited" editing will have to do until it is possible to "decompile" the iscript.bin into a more flexible format such as a text file with variable pointers and markers (which can be moved around). Then the script can be "compiled" back into the original iscript format again. * When I say "line" in this section I am not referring to a singular opcode or even a single number for that matter. Each opcode, number, or variable could be made up of one or more "lines." In technical terms, each "line" should be translated to a hexadecimal offset (each line being one byte in length). I use the term line because it is easier to grasp mnemonically. |
Copyright (c) 1999-2000 Jeffrey Pang.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the
Free Software Foundation with no Invariant Sections, with no
Front-Cover Texts, and with no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
[an error occurred while processing this directive]