Animated Effects

Jul 21, 2006 at 5:30 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
I'm leaving for a few weeks today, so I figured I'd dump my latest finding here for anyone who wants to pick away at it.

The animated effects (the "spark" when a shot hits a wall, the sparkles when you hit your head..) are all stored exactly like NPCs and weapons: via assembly and indexed by pointer tables. The pointer table is located at 0x008F8C0 in the EXE (as with any x86 pointers, they're 4 bytes in length.)

Unlike weapons and NPCs, the code behind animated effects is generally much simpler to work with and is a good place to start. Each function is passed (via the stack) a pointer to a structure containing information on the animation. Here's the structure (0x44 bytes in length; missing info is currently unknown.) Each member of the structure is 4 bytes in length.

0x00 InUse (set to 0x00000080 if in use, otherwise can be picked next time the game is looking for a free structure to use.)
0x04 ID (ie, which animation type; used as an index into the pointer table only)
0x08 Direction (as with any other direction... 0 left, 1 up, etc)
0x0C X Position
0x10 Y Position
0x14 X Velocity
0x18 Y Velocity
0x1C ?
0x20 ?
0x24 Frame ID (which frame to display)
0x28 FrameTimer (controls the delay before a frame changes)
0x2C X position offset
0x30 Y position offset
0x34 Bounding rect of the frame to display (Left)
0x38 Bounding rect of the frame to display (Top)
0x3C Bounding rect of the frame to display (Right)
0x40 Bounding rect of the frame to display (Bottom)

It will take a bit of assembly experience to modify these. But if this isn't something you can do, you could always change entries in the pointer table and have different animations substituting the original ones (ie, a puff of smoke when bumping your head on the ceilling.)
 
Jul 21, 2006 at 6:09 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
On further review, 0x08 (Direction) is actually a mode the effect runs. For instance, effect 0x01 is a "fountain" type particle explosion that's blue when 0x08 is 0 and red when it's 1.

0x1C is the effect's state. It's not used often but when it is, it's generally used as a flag to determine wether it's been initialised or not (generally this sets a random X/Y velocity to the particle to be animated.)

This just leaves 0x20... (Edit: Doesn't seem used in the actual animations themselves - it might have some other use elsewhere though, like the ID has.)

Edit 2: Tracing its value in-game reveals zilch. It's always at 0. Either it has some obscure use or it's a dummy variable. I'm under the impression weapons, entities, and animations (possibly other things) are all derived from a certain base "Object" class because they often share the same members. Chances are 0x20 points to a member in the base class which the Animation class never uses.

In short it's PROBABLY safe to use for your own purposes if you write your own animation effects.
 
Jul 31, 2006 at 10:03 PM
Neophyte Member
"Fresh from the Bakery"
Join Date: Jul 28, 2006
Location:
Posts: 8
What are the 'bounding rectangles' for, exactly? I know that seems like it has an obvious answer, but I'm under the assumption that the sprites were loaded as 16x16 blocks, with black as a transparent color, so it wouldn't matter what size they were at all.

Also, is there any particular way that the frame IDs are kept track of, or the code for the effect types (0x08)?
 
Aug 2, 2006 at 6:11 PM
The Bartender
"All your forum are belong to us!"
Join Date: Jun 18, 2006
Location: Montreal, Canada
Posts: 581
Age: 39
The bounding rects serve as a means of holding the actual frame (ie, the coordinates.) Not every effect is 16x16 ("LEVEL UP!" for instance) and the size could theorically vary from one frame to the next (I've never quite seen it happen, and I don't think it does, though.) Either way, DirectX needs a RECT structure to specify what to copy when calling one of its blitting functions, so the game has to keep track of the box.

Also, some sprites are 8x8, and sometimes even irregular sizes. 16x16 is just a convention - it's not always respected if necessary. :p

The code and id are kept track of in... the code and ID. ;) Those offsets are offsets from the base offset of the animation structure in memory, so +08 means 8 bytes into the structure is where the data is stored.

Edit: I might've misunderstood your second question. The frames are created via code. Often they're pushed onto the stack and referenced to and copied into the bounding box directly from the code. Sometimes, it gets calculated on the fly (for instance, the weapon energy sparkle comes to mind, though that one isn't an effect.)

When the animation handler is called, a few parameters are pushed onto the stack. These include the animation ID (which is cross-referenced with a pointer table used to jump to the appropriate code) and the effect type (byte 0x08; this is used directly in the animation's code and is handled differently on a case by case basis.) Essentially the process looks like this...

Function 'x' -> Calls animation handler -> Looks up ID in pointer table -> Calls code for this animation -> Code sets up the animation -> Handler returns -> ... -> Rendering code iterates through every animation "slot" -> Each active "slot" uses its bounding rect to render itself.
 
Top