A state, also known as a frame via DeHackEd terminology, is a structure used by the Doom engine to define the animation sequences of both actors and weapons, by stringing together instances of the state_t structure in a global array, with each state referring to its next state with an array index. This creates what is known in computer science parlance as a finite state automaton.


The state_t structure in the vanilla game engine defines the following fields:

typedef struct
    spritenum_t sprite;    // Number of the sprite; an index into the sprnames[] array.
    int frame;             // Frame number. 0 corresponds to the letter "A" in a sprite name, and so on.
    int tics;              // Length of time this state lasts, in tics (35 per second in vanilla Doom).
    void (*action) ();     // Function pointer to action to run at the beginning of the state.
    statenum_t nextstate;  // Index of the next animation state in the states[] array
    int misc1;             // Serves as an x offset for weapon animations
    int misc2;             // Serves as a y offset for weapon animations
} state_t;

These fields have become more widely known in the community by their names in DeHackEd, which, in order, are "sprite number", "sprite sub number", "duration", "code pointer", and "next frame".

Special semantics[edit]

The "bright sprite" flag which appears in DeHackEd is actually stored as a bit flag in the frame field, with a value of 32768 (0x8000 in hexadecimal). When this bit is set in a frame number, the engine remembers that fact to make the sprite fullbright, and then removes the 32768 value via a bitwise AND operation (frame & ~32768 in C code) in order to obtain the animation frame number.

A state with duration of zero tics will be invisible during gameplay, as such states immediately pass to their next state before the game continues running. A cycle of such states would deadlock the vanilla game engine by causing an infinite loop; source ports descended from MBF have a cycle detector in the function P_SetMobjState to prevent this from happening.

States with a duration of -1 tics never proceed to their next state. This is typically found at the end of a monster's death sequence.

In DeHackEd it was possible to reassign the "code pointer" or action field to other existing actions, but only if the field already had a non-zero value. The reason for this restriction is that in MS-DOS, binary executable images must be relocatable, meaning that they can be executed with any base address for the process. This requires code in the executable's stub to change the value of all absolute pointers in the program to add in the offset from the image's base address. This is accomplished using a fixed-size "relocation table" that is stored in the header of the executable file - since NULL, or zero, never changes with image relocation, only non-zero pointers have a relocation table entry. Resizing of this table was considered too complex at the time that DeHackEd was created. Source ports which load DeHackEd patches at runtime do not suffer this limitation, even under DOS, as pointers can be freely assigned during execution regardless of their initial values.

If the nextstate field has a value of zero (referred to symbolically as S_NULL in the source code), the object will be removed from the game simulation and its memory will be freed. If a weapon transfers to this zero state, the player will be unable to use his weapons.

The misc1 and misc2 fields are used as offsets by the weapon code, but this feature is actually unused in the released versions of all Doom engine games. The MBF source port allowed these fields to additionally be used as arguments to some of its custom action functions.

Source ports[edit]

Most source ports with content definition languages allow specification of the states of all actors and weapons via those languages. Along with this, various extensions are present, such as numerous additional action functions, some of which accept parameterized values, allowing for custom AI and behaviors not possible with the vanilla game engine.

See also[edit]

External links[edit]