Duke Nukem II Actor Info
The tile arrangement for the Duke Nukem II actors (game characters) is stored in ACTRINFO.MNI in the main NUKEM2.CMP group file. This file describes how to arrange the bare 8×8 tiles found in the corresponding tileset, so that they form a frame belonging to an actor animation.
|UINT16LE iNumActors||Number of actors described in the file|
|UINT16LE iOffset[iNumActors]||Array of UINT16 offsets to the actor info structure (double these values to turn them into byte offsets)|
Following this structure the first actor data should begin. The actor data runs end-to-end, and iOffset should only be required when jumping to a particular actor's offset.
Note that iNumActors is technically the UINT16-offset of the first structure, however if it is treated as such it becomes difficult to find the number of actors described by the file.
|UINT16LE iNumFrames||Number of frames this actor has|
|INT16LE iDrawIndex||Defines when the actor will be drawn to the screen (ignored for actors spawned during gameplay)|
|ACTOR_FRAME frameInfo[iNumFrames]||Structure holding information about the frame|
The iDrawIndex value ranges from -1 to 3. Actors with a lower index will be updated and drawn first, the actors with highest index last. Any value smaller than -1 or greater than 3 is invalid and will prevent the actor from being spawned in a level. Actors with an identical draw index will be drawn in the order that they appear in the level file.
ACTOR_FRAME is defined as:
|INT16LE iHotspotX||X-coord of hotspot (in tiles, can be negative)|
|INT16LE iHotspotY||Y-coord of hotspot (in tiles, can be negative)|
|UINT16LE iHeight||Frame height (in tiles)|
|UINT16LE iWidth||Frame width (in tiles)|
|UINT32LE iDataOffset||Offset into ACTORS.MNI where the tile data starts|
|UINT16LE iPadding1||never used|
|UINT16LE iPadding2||never used|
The hotspot is the location in the image which should appear at the offset given in the map layer. In other words, take the actor location, subtract iHotspotX number of tiles from the X-coordinate, subtract iHotspotY number of tiles from the Y-coordinate, and the actor will appear at the correct location.
The two padding values at the end are inserted to allow the game to calculate the start of the ACTOR_FRAME data for each frame with the same formula:
start = (iOffset[actor] + 8 * frame + 2) * 2
This means the padding values are effectively dummies for the iNumFrames and iDrawIndex values. Even though these padding values could theoretically be omitted for the last frame of each actor entry, they are always present in the original files.
The draw index is only taken into account during level loading. For actors spawned during gameplay, the draw order instead depends on the state of the game's object list. The game uses a fixed-size array to represent actor state at run-time. When an actor is destroyed, its corresponding entry in the list is marked as "free". When a new actor is created, the game uses the first free entry to store the new actor's state. The effect of this is that a newly spawned actor may appear at the beginning of the list or at the end, depending on how many actors have been destroyed so far. And the list position determines the draw order, so the newly spawned actor may appear behind or in front of other actors.
During level loading, the game does multiple passes over the actor list from the level file, only creating the actors matching the current pass' draw index on each pass.
ACTORS.MNI contains some bytes that are not used by any actor frame. These bytes are found at the end of every 64KB block (exactly 65536 bytes) of data. In the original file, no sprite frame is split across these 64KB blocks. The image data is written to the end of the block to fill it up, then the new block is started, containing the entire image data of the sprite's frame.
However, Duke Nukem II seems to be able to handle the image data correctly, even if it is split across two of these blocks. This might have just been a limitation in the original tool that was used to create the ACTORS.MNI file.
Font data format
The data for sprite number 29 is in a slightly different format. Instead of 4 colour planes and a mask plane, the image data for the frames of this sprite only consist of two planes. The frames of this sprite store the big 8*16 pixel font used in the menus. Furthermore, the game is hard-coded to draw this font at 8*16 pixles, i.e. 1 tile wide and 2 tiles high.