Blood's .DEM file format (1.10 and above)
Copyright 1997, Monolith Productions.  All Rights Reserved.

08/20/97

THIS IS ALL SUBJECT TO CHANGE.

===============================================================================
WARNING!  WARNING!  WARNING!  WARNING!  WARNING!  WARNING!  WARNING!  WARNING!
===============================================================================

The INPUT structure couuld change, causing the demos to be invalid.  

More often, however, AI or weapon changes cause the recorded actions to 
become 'not the intended action'.  

For example, 1.02 demos that use the Voo-Doo alt-fire were 'broken' in 1.10
when the alt-fire VooDoo action was changed.  Monsters that were previously
killed were now still alive.  This could cause the player to run into them
instead of proceeding safely to the next area, etc.  All further actions
would then be modified as the recorded re-actions of the player are now blindly
responsding to events that don't happen.  The usual result is early death.

===============================================================================

File format:

DEMOHEAHDER
INPUT[nInputCount][nNetPlayers] // set of INPUT for each of the players.

===============================================================================

DEMOHEADER Structure definition

        struct DEMOHEADER
        {
                DWORD           signature;      //'DEM\0x1a'
                BLOODVERSION    nVersion;       // version of Blood that created the demo
                long            nBuild;         // build of Blood that created the demo
                                                // builds are:
                                                // SW, SWCD:   2
                                                // Registered: 3
                                                // Plasma Pak: 4
                long    nInputCount;            // number of INPUT structures recorded
                int     nNetPlayers;            // number of players recorded
                short   nMyConnectIndex;        // the ID of the player
                short   nConnectHead;           // index into connectPoints of Player
                short   connectPoints[MAXPLAYERS];      // IDs of players

                GAMEOPTIONS gameOptions;        // game options used for level
        };


===============================================================================

GAMEOPTIONS Structure definition

struct GAMEOPTIONS
{
        GAMETYPE        nGameType;
        DIFFICULTY      nDifficulty;
        int             nEpisode;
        int             nLevel;
        char            zLevelName[ _MAX_PATH ];
        char            zLevelSong[ _MAX_PATH ];
        int             nTrackNumber;
        char            szSaveGameName[kMaxFileKeyLen];
        char            szUserGameName[kMaxFileKeyLen];
        short           nSaveGameSlot;
        int             picEntry;
        ulong           uMapCRC;
        MONSTERSETTINGS nMonsterSettings;

        ulong           uGameFlags;

        // net game options/data only
        ulong           uNetGameFlags;

        WEAPONSETTINGS  nWeaponSettings;
        ITEMSETTINGS    nItemSettings;
        RESPAWNSETTINGS nRespawnSettings;
        TEAMSETTINGS    nTeamSettings;  // team and cooperative

        int             nMonsterRespawnTime;
        int             nWeaponRespawnTime;
        int             nItemRespawnTime;
        int             nSpecialRespawnTime;
};


===============================================================================

INPUT Structure definition

/***********************************************************************
 * BUTTONFLAGS
 *
 * This structure is packetized and sent to other players. These keys
 * are used frequently during the game. The purpose for separating and
 * keeping this structure small, is to limit the amount of transferred
 * data.
 *
 **********************************************************************/
union BUTTONFLAGS
{
        char                    byte;
        struct
        {
                unsigned jump           : 1;    // player is jumping (once!)
                unsigned crouch         : 1;    // player is crouching
                unsigned shoot          : 1;    // normal attack
                unsigned shoot2         : 1;    // alternate attack
                unsigned lookUp         : 1;    // > glance or aim up/down
                unsigned lookDown       : 1;    // > if glancing then lookCenter is set
        };
};

union KEYFLAGS
{
        short                   word;
        struct
        {
                unsigned action                 : 1;    // open or activate
                unsigned jab                    : 1;    // quick attack
                unsigned prevItem               : 1;    // next inventory item
                unsigned nextItem               : 1;    // prev inventory item
                unsigned useItem                : 1;    // use inventory item
                unsigned prevWeapon             : 1;    // prev useable weapon
                unsigned nextWeapon             : 1;    // next useable weapon
                unsigned holsterWeapon  : 1;    // holster current weapon

                unsigned lookCenter             : 1;    // used for lookUp/lookDown only
                unsigned lookLeft               : 1;    // > glance or aim up/down
                unsigned lookRight              : 1;    // > if glancing then lookCenter is set
                unsigned spin180                : 1;    // spin 180 degrees

                unsigned pause                  : 1;    // pause the game
                unsigned quit                   : 1;    // quit the game
                unsigned restart                : 1;    // restart the level
        };
};

union USEFLAGS
{
        char                    byte;
        struct
        {
                unsigned useBeastVision         : 1;
                unsigned useCrystalBall         : 1;
                unsigned useJumpBoots           : 1;
                unsigned useMedKit                      : 1;
        };
};

union SYNCFLAGS
{
        char                    byte;
        struct
        {
                unsigned buttonChange   : 1;
                unsigned keyChange              : 1;
                unsigned useChange              : 1;
                unsigned weaponChange   : 1;
                unsigned mlookChange    : 1;
                unsigned run                    : 1;    // player is running
        };
};

struct INPUT
{
        SYNCFLAGS       syncFlags;              // always sent: indicates optional fields
        schar           forward;                // always sent
        sshort          turn;                   // always sent
        schar           strafe;                 // always sent

        // optional fields
        BUTTONFLAGS     buttonFlags;
        KEYFLAGS        keyFlags;
        USEFLAGS        useFlags;
        uchar           newWeapon;      // sent as 0 every frame unless changed
        schar           mlook;
};


