
#ifndef RECOVERED_GAME_H
#define RECOVERED_GAME_H

#include <float.h>
#include <limits.h>
#include <stdint.h>
#include <stddef.h>
#include "coduo_int32_bits.h"
#include "q_vector_types.h"
#include "q_math.h"

/* NOT_FROM_ORIGINAL_SOURCE: defined host conversion matching an original x87
 * fistp under truncate mode, without introducing an emulated-x87 path. */
static inline int32_t game_compat_int32_from_long_double_trunc(long double value)
{
    if (!(value >= -2147483648.0L && value < 2147483648.0L)) {
        return INT32_MIN;
    }
    return (int32_t)value;
}

/* NOT_FROM_ORIGINAL_SOURCE: float-input convenience form of the defined
 * truncating conversion above. */
static inline int32_t game_compat_int32_from_float_trunc(float value)
{
    return game_compat_int32_from_long_double_trunc((long double)value);
}

#define MAX_GENTITIES 1024u
#define MAX_CLIENTS 64u
#define COM_ERROR_MARKER "\x15"
#define BG_ITEMLIST_SLOT_COUNT 135u /* logical table element count, not byte count */
#define CLIENT_INFO_MODEL_NAME_SIZE 64
#define CLIENT_INFO_ATTACHMENT_COUNT 6
#define BG_ANIM_MAX_LIST_ITEMS 128
#define BG_ANIM_MAX_COMMANDS 8
#define BG_ANIM_MAX_GLOBAL_SCRIPTS 2048
#define ENTITYNUM_WORLD 1022
#define ENTITYNUM_NONE 1023
/* Collision syscalls use signed -1 for "do not exclude an entity"; this is a
 * different domain from the 10-bit ENTITYNUM_NONE network sentinel. */
#define PASS_ENTITY_NONE (-1)
/* SV_GameSendServerCommand maps signed -1 to the broadcast NULL-client path. */
#define SERVER_COMMAND_ALL_CLIENTS (-1)

/* Server entity flags (`gentity_t.svFlags`). */
typedef enum serverEntityFlags_e {
    SVF_NOCLIENT = 0x00000001u,
    SVF_DOBJ_USE_DEFAULT_BOUNDS = 0x00000002u,
    SVF_DOBJ_USE_MODEL_BOUNDS = 0x00000004u,
    SVF_LOOPED_FX = 0x00000008u,
    SVF_OBJECTIVE = 0x00000010u,
    SVF_CAPSULE = 0x00000200u,
    SVF_SINGLECLIENT = 0x00000800u,
    SVF_NOTSINGLECLIENT = 0x00002000u,
    SVF_DOBJ_BOUNDS_MASK =
        SVF_DOBJ_USE_DEFAULT_BOUNDS | SVF_DOBJ_USE_MODEL_BOUNDS,
    SVF_VISIBILITY_BYPASS_MASK = SVF_LOOPED_FX | SVF_OBJECTIVE
} serverEntityFlags_t;

/* Engine cvar flags passed through the game-module registration syscall. */
typedef enum cvarFlags_e {
    CVAR_FLAG_ARCHIVE = 0x00000001u,
    CVAR_FLAG_USERINFO = 0x00000002u,
    CVAR_FLAG_SERVERINFO = 0x00000004u,
    CVAR_FLAG_SYSTEMINFO = 0x00000008u,
    CVAR_FLAG_INIT = 0x00000010u,
    CVAR_FLAG_LATCH = 0x00000020u,
    CVAR_FLAG_ROM = 0x00000040u,
    CVAR_FLAG_USER_CREATED = 0x00000080u,
    CVAR_FLAG_TEMP = 0x00000100u,
    CVAR_FLAG_CHEAT = 0x00000200u,
    CVAR_FLAG_NORESTART = 0x00000400u,
    CVAR_FLAG_SCRIPT_MAKE_SERVERINFO = 0x00000800u,
    CVAR_FLAG_SCRIPT_SETCVAR = 0x00001000u,
    CVAR_FLAG_SCRIPT_SETCVAR_SERVERINFO = 0x00002000u
} cvarFlags_t;

/* Game entity flags (`gentity_t.flags`) and entity-state flags (`gentity_t.s_flags`). */
#define FL_NOCLIENT       0x00001000u
#define FL_SUPPORTS_LINKTO 0x00002000u
#define EF_CAPSULE         0x00000010u
#define EF_NODRAW          0x00000080u

/* Shared client-state record copied by the archived-client-info syscall. This
 * is the same clientState_s/clientState_t layout used by CoDUOMP. */
typedef struct clientState_s {
    int32_t clientNum;
    int32_t team;
    int32_t modelindex;
    int32_t attachModelIndex[6];
    int32_t attachTagIndex[6];
    char name[32];
} clientState_t;

/* CoD:UO packs player vehicle animation state into entity-state offset +0x088. */
#define VEHICLE_ANIM_STATE_POS_SHIFT   0
#define VEHICLE_ANIM_STATE_POS_MASK    0x00000007u
#define VEHICLE_ANIM_STATE_TYPE_SHIFT  3
#define VEHICLE_ANIM_STATE_TYPE_MASK   0x00000038u
#define VEHICLE_ANIM_STATE_MOTION_SHIFT 6
#define VEHICLE_ANIM_STATE_MOTION_MASK  0x000000c0u

/* Shared animation-condition columns. The server and client write the same
 * eleven 64-bit condition rows from the same player/entity state producers;
 * these semantic identities are corroborated across both modules. */
typedef enum bg_anim_condition_index_e {
    ANIM_COND_WEAPON = 0,
    ANIM_COND_WEAPONCLASS = 1,
    ANIM_COND_MOUNTED = 2,
    ANIM_COND_VEHICLE = 3,
    ANIM_COND_VEHICLE_MOTION = 4,
    ANIM_COND_MOVETYPE = 5,
    ANIM_COND_UNDERHAND = 6,
    ANIM_COND_CROUCHING = 7,
    ANIM_COND_FIRING = 8,
    ANIM_COND_WEAPON_POSITION = 9,
    ANIM_COND_STRAFING = 10,
    ANIM_COND_COUNT = 11
} bg_anim_condition_index_t;

/* These identifiers are shared by cgame and game. Their values and ordering
 * are proved by the corresponding initialized string tables in both modules. */
typedef enum bg_anim_condition_mode_e {
    ANIM_CONDMODE_BITMASK = 0,
    ANIM_CONDMODE_EQUAL = 1
} bg_anim_condition_mode_t;

typedef enum bg_anim_state_e {
    ANIM_STATE_RELAXED = 0,
    ANIM_STATE_QUERY = 1,
    ANIM_STATE_ALERT = 2,
    ANIM_STATE_COMBAT = 3,
    ANIM_STATE_COUNT = 4
} bg_anim_state_t;

typedef enum bg_anim_move_type_e {
    ANIM_MT_UNUSED = 0,
    ANIM_MT_IDLE = 1,
    ANIM_MT_IDLECR = 2,
    ANIM_MT_IDLEPRONE = 3,
    ANIM_MT_WALK = 4,
    ANIM_MT_WALKBK = 5,
    ANIM_MT_WALKCR = 6,
    ANIM_MT_WALKCRBK = 7,
    ANIM_MT_WALKPRONE = 8,
    ANIM_MT_WALKPRONEBK = 9,
    ANIM_MT_RUN = 10,
    ANIM_MT_RUNBK = 11,
    ANIM_MT_RUNCR = 12,
    ANIM_MT_RUNCRBK = 13,
    ANIM_MT_TURNRIGHT = 14,
    ANIM_MT_TURNLEFT = 15,
    ANIM_MT_CLIMBUP = 16,
    ANIM_MT_CLIMBDOWN = 17,
    ANIM_MT_COUNT = 18
} bg_anim_move_type_t;

typedef enum bg_anim_body_part_e {
    ANIM_BP_UNUSED = 0,
    ANIM_BP_LEGS = 1,
    ANIM_BP_TORSO = 2,
    ANIM_BP_BOTH = 3,
    ANIM_BP_COUNT = 4
} bg_anim_body_part_t;

typedef enum bg_anim_mounted_e {
    ANIM_MOUNT_UNUSED = 0,
    ANIM_MOUNT_MG42 = 1,
    ANIM_MOUNT_VEHICLE_DRIVER = 2,
    ANIM_MOUNT_VEHICLE_GUNNER = 3,
    ANIM_MOUNT_VEHICLE_PASSENGER_1 = 4,
    ANIM_MOUNT_VEHICLE_PASSENGER_2 = 5,
    ANIM_MOUNT_VEHICLE_PASSENGER_3 = 6,
    ANIM_MOUNT_VEHICLE_PASSENGER_4 = 7,
    ANIM_MOUNT_COUNT = 8
} bg_anim_mounted_t;

typedef enum bg_anim_vehicle_motion_e {
    ANIM_VEHICLE_MOTION_UNUSED = 0,
    ANIM_VEHICLE_MOTION_IDLE = 1,
    ANIM_VEHICLE_MOTION_FORWARD = 2,
    ANIM_VEHICLE_MOTION_REVERSING = 3,
    ANIM_VEHICLE_MOTION_COUNT = 4
} bg_anim_vehicle_motion_t;

typedef enum bg_anim_vehicle_e {
    ANIM_VEHICLE_UNUSED = 0,
    ANIM_VEHICLE_TANK = 1,
    ANIM_VEHICLE_JEEP = 2,
    ANIM_VEHICLE_FLAK88 = 3,
    ANIM_VEHICLE_COUNT = 4
} bg_anim_vehicle_t;

typedef enum bg_anim_weapon_position_e {
    ANIM_WEAPON_POSITION_HIP = 0,
    ANIM_WEAPON_POSITION_ADS = 1,
    ANIM_WEAPON_POSITION_COUNT = 2
} bg_anim_weapon_position_t;

typedef enum bg_anim_strafe_e {
    ANIM_STRAFE_NOT = 0,
    ANIM_STRAFE_LEFT = 1,
    ANIM_STRAFE_RIGHT = 2,
    ANIM_STRAFE_COUNT = 3
} bg_anim_strafe_t;

/* Animation-script event indices. The original bgAnimEventStrings data table
 * supplies this complete ordered domain. BG_AnimScriptEvent addresses all
 * sixteen list slots by this index even though the table's source-level layout
 * partitions them into eventLists[10] followed by scriptLists[6]. */
typedef enum bg_anim_event_e {
    ANIM_EVENT_NONE = -1,
    ANIM_EVENT_PAIN = 0,
    ANIM_EVENT_DEATH = 1,
    ANIM_EVENT_FIRE_WEAPON = 2,
    ANIM_EVENT_JUMP = 3,
    ANIM_EVENT_JUMP_BACK = 4,
    ANIM_EVENT_LAND = 5,
    ANIM_EVENT_DROP_WEAPON = 6,
    ANIM_EVENT_RAISE_WEAPON = 7,
    ANIM_EVENT_CLIMB_MOUNT = 8,
    ANIM_EVENT_CLIMB_DISMOUNT = 9,
    ANIM_EVENT_RELOAD = 10,
    ANIM_EVENT_CROUCH_TO_PRONE = 11,
    ANIM_EVENT_PRONE_TO_CROUCH = 12,
    ANIM_EVENT_MELEE_ATTACK = 13,
    ANIM_EVENT_LMG_DEPLOY = 14,
    ANIM_EVENT_LMG_BREAKDOWN = 15,
    ANIM_EVENT_COUNT = 16
} bg_anim_event_t;

/* Player animation words carry one restart-toggle bit in addition to the
 * animation-table index. This is the same encoding used by cgame. */
#define ANIM_TOGGLEBIT UINT32_C(0x200)

/* Recovered contents bits and composite query masks used by script queries
 * and traces. */
#define MASK_ALL                        0xffffffffu
#define CONTENTS_SOLID                  0x00000001u
#define CONTENTS_TRIGGER_TOUCH_VEHICLE  0x00000008u
#define CONTENTS_WATER                  0x00000020u
#define CONTENTS_BODY                   0x02000000u
#define CONTENTS_TELEFRAG_BLOCKER       0x00000080u
#define CONTENTS_TRIGGER_DAMAGE         0x00400000u
#define CONTENTS_STUCK_ALT              0x04000000u
#define CONTENTS_TRIGGER_TOUCH_CLIENT   0x40000000u
#define MASK_GRENADE_TRACE              0x00000011u
#define MASK_BULLETTRACE                0x02802031u
#define MASK_MOVER_PUSH                 0x02000180u
#define MASK_TRIGGER                    0x405c0008u
#define MASK_CLEAR_VEHICLE_POSITION     0x04000100u

/* Recovered surface flags carried by trace surfaceFlags fields. */
#define SURF_SKY 0x00000004u

/* Recovered configstring ranges touched by script builtins/client fields. */
typedef enum configStringIndex_e {
    CS_AMBIENT = 3,
    CS_TEAM_SCORE_AXIS = 5,
    CS_TEAM_SCORE_ALLIES = 6,
    CS_WIND = 12,
    CS_MOTD = 15,
    CS_GAMESTATE = 21,
    CS_STATUS_ICONS = 22,
    CS_STATUS_ICONS_COUNT = 16,
    CS_HEAD_ICONS = 38,
    CS_HEAD_ICONS_COUNT = 15,
    CS_TAGS = 117,
    CS_TAGS_COUNT = 32,
    CS_MODELS = 405,
    CS_MODELS_COUNT = 256,
    CS_SOUNDS = 661,
    CS_SOUNDS_COUNT = 256,
    CS_EFFECTS = 917,
    CS_EFFECTS_COUNT = 80,
    CS_FX = 997,
    CS_FX_COUNT = 256,
    CS_SHELLSHOCKS = 1253,
    CS_SHELLSHOCKS_COUNT = 16,
    CS_SCRIPTMENUS = 1333,
    CS_SCRIPTMENUS_COUNT = 32,
    CS_HINTSTRINGS = 1365,
    CS_HINTSTRINGS_COUNT = 32,
    CS_LOCALIZED_STRINGS = 1397,
    CS_LOCALIZED_STRINGS_COUNT = 256,
    CS_SHADERS = 1653,
    CS_SHADERS_COUNT = 256
} configStringIndex_t;

typedef int qboolean;
#define qfalse 0
#define qtrue 1

/* Quake III supplies the inherited usercmd_s/usercmd_t identity and the
 * semantic angles/weapon/movement names. CoD:UO reorders them into this exact
 * 0x18-byte record. The engine copies it as six dwords, while its codecs and
 * both PMove implementations access the named flag and movement bytes below;
 * +0x07 and +0x17 are copied-only compiler padding. */
typedef struct usercmd_s {
    int32_t commandTime;                     /* +0x00 */
    uint8_t buttons;                         /* +0x04, primary input flags */
    uint8_t wbuttons;                        /* +0x05, secondary/weapon input flags */
    uint8_t weapon;                          /* +0x06, requested weapon index */
    int32_t angles[3];                       /* +0x08, pitch/yaw/roll command angle words */
    int8_t forwardmove;                      /* +0x14 */
    int8_t rightmove;                        /* +0x15 */
    int8_t upmove;                           /* +0x16 */
} usercmd_t;

typedef struct orientation_s {
    vec3_t origin;
    vec3_t axis[3];
} orientation_t;

typedef struct gentity_s gentity_t;
typedef struct gclient_s gclient_t;
typedef struct playerState_s playerState_t;
typedef struct turret_state_s turret_state_t;
/* Exact retail tag recovered from Mac XModelCreateDefault(XModel_s *). */
typedef struct XModel_s XModel;
typedef struct gitem_s gitem_t;
typedef struct vehicle_state_s vehicle_state_t;
typedef struct vehicleInfo_s vehicleInfo_t;
struct trace_s;

typedef void (*gentity_touch_t)(gentity_t *self, gentity_t *other, int traceMode);
typedef gentity_touch_t entity_touch_t;
typedef void (*gentity_use_t)(gentity_t *self, gentity_t *other,
                              gentity_t *activator);
typedef void (*gentity_mover_reached_t)(gentity_t *self);
typedef void (*gentity_mover_blocked_t)(gentity_t *self, gentity_t *blocked);
typedef void (*gentity_controller_t)(gentity_t *self, uint32_t *partBits);
typedef void (*pm_trace_fn_t)(struct trace_s *results, const float *start,
                              const float *mins, const float *maxs,
                              const float *end, int passEntityNum,
                              int contentMask);
typedef int (*pm_entity_type_fn_t)(int entityNum);

typedef enum vehicle_type_e {
    VEHICLE_TYPE_UNKNOWN = 0,
    VEHICLE_TYPE_4_WHEEL = 1,
    VEHICLE_TYPE_TANK = 2,
    VEHICLE_TYPE_PLANE = 3,
    VEHICLE_TYPE_BOAT = 4,
    VEHICLE_TYPE_ARTILLERY = 5,
    VEHICLE_TYPE_COUNT = 6
} vehicle_type_t;

/* Trajectory type constants recovered from BG_EvaluateTrajectory switch cases. */
typedef enum trType_e {
    TR_STATIONARY = 0,
    TR_INTERPOLATE = 1,
    TR_LINEAR = 2,
    TR_LINEAR_STOP = 3,
    TR_SINE = 4,
    TR_GRAVITY = 5,
    TR_GRAVITY_LOW = 6,
    TR_GRAVITY_FLOAT = 7,
    TR_LINKED = 8,
    TR_ACCELERATE = 9,
    TR_DECCELERATE = 10
} trType_t;

/*
 * Trajectory structure for entity movement.
 * Original source field names: trType, trTime, trDuration, trBase[3], trDelta[3]
 * Used by BG_EvaluateTrajectory and BG_EvaluateTrajectoryDelta.
 * RECOVERED(UO-GAME-UNK-0156): Full struct layout from debug strings and offset analysis.
 * ABI size is 36 bytes (0x024), not 48.
 */
typedef struct trajectory_s {
    trType_t trType;                      /* +0x00, trajectory type */
    int32_t trTime;                       /* +0x04, start time */
    int32_t trDuration;                   /* +0x08, duration for stop/sine trajectories */
    vec3_t trBase;                        /* +0x0c, trajectory base position/angles */
    vec3_t trDelta;                       /* +0x18, velocity/angular velocity */
} trajectory_t;                           /* ABI total size: 36 bytes (0x024) */

/* Shared entity-state discriminator. CoDUOMP's q_shared.h supplies the exact
 * identities through ET_VEHICLE_OWNER_ICON; the game module writes the same
 * values, and G_TempEntity proves the event-entity base at 16. Values 13 and
 * 14 remain unnamed because the binaries expose their behavior but not their
 * original source identities. */
typedef enum entityType_e {
    ET_GENERAL = 0,
    ET_PLAYER = 1,
    ET_PLAYER_CORPSE = 2,
    ET_ITEM = 3,
    ET_MISSILE = 4,
    ET_MOVER = 5,
    ET_PORTAL = 6,
    ET_INVISIBLE = 7,
    ET_SCRIPTMOVER = 8,
    ET_SOUND_BLEND = 9,
    ET_LOOPED_FX = 10,
    ET_TURRET = 11,
    ET_VEHICLE = 12,
    ET_VEHICLE_OWNER_ICON = 15,
    ET_EVENTS = 16
} entityType_t;

/* The stock module carries this complete event-name table contiguously at file
 * offsets 0x997c0..0x9a7b9 and indexes it by the event value. Keep the enum
 * complete so guessed call-site descriptions cannot replace the original
 * source identities again. */
typedef enum entityEvent_e {
    EV_NONE = 0,
    EV_FOOTSTEP_RUN_DEFAULT = 1,
    EV_FOOTSTEP_RUN_BARK = 2,
    EV_FOOTSTEP_RUN_BRICK = 3,
    EV_FOOTSTEP_RUN_CARPET = 4,
    EV_FOOTSTEP_RUN_CLOTH = 5,
    EV_FOOTSTEP_RUN_CONCRETE = 6,
    EV_FOOTSTEP_RUN_DIRT = 7,
    EV_FOOTSTEP_RUN_FLESH = 8,
    EV_FOOTSTEP_RUN_FOLIAGE = 9,
    EV_FOOTSTEP_RUN_GLASS = 10,
    EV_FOOTSTEP_RUN_GRASS = 11,
    EV_FOOTSTEP_RUN_GRAVEL = 12,
    EV_FOOTSTEP_RUN_ICE = 13,
    EV_FOOTSTEP_RUN_METAL = 14,
    EV_FOOTSTEP_RUN_MUD = 15,
    EV_FOOTSTEP_RUN_PAPER = 16,
    EV_FOOTSTEP_RUN_PLASTER = 17,
    EV_FOOTSTEP_RUN_ROCK = 18,
    EV_FOOTSTEP_RUN_SAND = 19,
    EV_FOOTSTEP_RUN_SNOW = 20,
    EV_FOOTSTEP_RUN_WATER = 21,
    EV_FOOTSTEP_RUN_WOOD = 22,
    EV_FOOTSTEP_RUN_ASPHALT = 23,
    EV_FOOTSTEP_WALK_DEFAULT = 24,
    EV_FOOTSTEP_WALK_BARK = 25,
    EV_FOOTSTEP_WALK_BRICK = 26,
    EV_FOOTSTEP_WALK_CARPET = 27,
    EV_FOOTSTEP_WALK_CLOTH = 28,
    EV_FOOTSTEP_WALK_CONCRETE = 29,
    EV_FOOTSTEP_WALK_DIRT = 30,
    EV_FOOTSTEP_WALK_FLESH = 31,
    EV_FOOTSTEP_WALK_FOLIAGE = 32,
    EV_FOOTSTEP_WALK_GLASS = 33,
    EV_FOOTSTEP_WALK_GRASS = 34,
    EV_FOOTSTEP_WALK_GRAVEL = 35,
    EV_FOOTSTEP_WALK_ICE = 36,
    EV_FOOTSTEP_WALK_METAL = 37,
    EV_FOOTSTEP_WALK_MUD = 38,
    EV_FOOTSTEP_WALK_PAPER = 39,
    EV_FOOTSTEP_WALK_PLASTER = 40,
    EV_FOOTSTEP_WALK_ROCK = 41,
    EV_FOOTSTEP_WALK_SAND = 42,
    EV_FOOTSTEP_WALK_SNOW = 43,
    EV_FOOTSTEP_WALK_WATER = 44,
    EV_FOOTSTEP_WALK_WOOD = 45,
    EV_FOOTSTEP_WALK_ASPHALT = 46,
    EV_FOOTSTEP_PRONE_DEFAULT = 47,
    EV_FOOTSTEP_PRONE_BARK = 48,
    EV_FOOTSTEP_PRONE_BRICK = 49,
    EV_FOOTSTEP_PRONE_CARPET = 50,
    EV_FOOTSTEP_PRONE_CLOTH = 51,
    EV_FOOTSTEP_PRONE_CONCRETE = 52,
    EV_FOOTSTEP_PRONE_DIRT = 53,
    EV_FOOTSTEP_PRONE_FLESH = 54,
    EV_FOOTSTEP_PRONE_FOLIAGE = 55,
    EV_FOOTSTEP_PRONE_GLASS = 56,
    EV_FOOTSTEP_PRONE_GRASS = 57,
    EV_FOOTSTEP_PRONE_GRAVEL = 58,
    EV_FOOTSTEP_PRONE_ICE = 59,
    EV_FOOTSTEP_PRONE_METAL = 60,
    EV_FOOTSTEP_PRONE_MUD = 61,
    EV_FOOTSTEP_PRONE_PAPER = 62,
    EV_FOOTSTEP_PRONE_PLASTER = 63,
    EV_FOOTSTEP_PRONE_ROCK = 64,
    EV_FOOTSTEP_PRONE_SAND = 65,
    EV_FOOTSTEP_PRONE_SNOW = 66,
    EV_FOOTSTEP_PRONE_WATER = 67,
    EV_FOOTSTEP_PRONE_WOOD = 68,
    EV_FOOTSTEP_PRONE_ASPHALT = 69,
    EV_JUMP_DEFAULT = 70,
    EV_JUMP_BARK = 71,
    EV_JUMP_BRICK = 72,
    EV_JUMP_CARPET = 73,
    EV_JUMP_CLOTH = 74,
    EV_JUMP_CONCRETE = 75,
    EV_JUMP_DIRT = 76,
    EV_JUMP_FLESH = 77,
    EV_JUMP_FOLIAGE = 78,
    EV_JUMP_GLASS = 79,
    EV_JUMP_GRASS = 80,
    EV_JUMP_GRAVEL = 81,
    EV_JUMP_ICE = 82,
    EV_JUMP_METAL = 83,
    EV_JUMP_MUD = 84,
    EV_JUMP_PAPER = 85,
    EV_JUMP_PLASTER = 86,
    EV_JUMP_ROCK = 87,
    EV_JUMP_SAND = 88,
    EV_JUMP_SNOW = 89,
    EV_JUMP_WATER = 90,
    EV_JUMP_WOOD = 91,
    EV_JUMP_ASPHALT = 92,
    EV_LANDING_DEFAULT = 93,
    EV_LANDING_BARK = 94,
    EV_LANDING_BRICK = 95,
    EV_LANDING_CARPET = 96,
    EV_LANDING_CLOTH = 97,
    EV_LANDING_CONCRETE = 98,
    EV_LANDING_DIRT = 99,
    EV_LANDING_FLESH = 100,
    EV_LANDING_FOLIAGE = 101,
    EV_LANDING_GLASS = 102,
    EV_LANDING_GRASS = 103,
    EV_LANDING_GRAVEL = 104,
    EV_LANDING_ICE = 105,
    EV_LANDING_METAL = 106,
    EV_LANDING_MUD = 107,
    EV_LANDING_PAPER = 108,
    EV_LANDING_PLASTER = 109,
    EV_LANDING_ROCK = 110,
    EV_LANDING_SAND = 111,
    EV_LANDING_SNOW = 112,
    EV_LANDING_WATER = 113,
    EV_LANDING_WOOD = 114,
    EV_LANDING_ASPHALT = 115,
    EV_LANDING_PAIN_DEFAULT = 116,
    EV_LANDING_PAIN_BARK = 117,
    EV_LANDING_PAIN_BRICK = 118,
    EV_LANDING_PAIN_CARPET = 119,
    EV_LANDING_PAIN_CLOTH = 120,
    EV_LANDING_PAIN_CONCRETE = 121,
    EV_LANDING_PAIN_DIRT = 122,
    EV_LANDING_PAIN_FLESH = 123,
    EV_LANDING_PAIN_FOLIAGE = 124,
    EV_LANDING_PAIN_GLASS = 125,
    EV_LANDING_PAIN_GRASS = 126,
    EV_LANDING_PAIN_GRAVEL = 127,
    EV_LANDING_PAIN_ICE = 128,
    EV_LANDING_PAIN_METAL = 129,
    EV_LANDING_PAIN_MUD = 130,
    EV_LANDING_PAIN_PAPER = 131,
    EV_LANDING_PAIN_PLASTER = 132,
    EV_LANDING_PAIN_ROCK = 133,
    EV_LANDING_PAIN_SAND = 134,
    EV_LANDING_PAIN_SNOW = 135,
    EV_LANDING_PAIN_WATER = 136,
    EV_LANDING_PAIN_WOOD = 137,
    EV_LANDING_PAIN_ASPHALT = 138,
    EV_FOLIAGE_SOUND = 139,
    EV_FATIGUE_LAST_SOUND = 140,
    EV_FATIGUE_SOUND = 141,
    EV_STANCE_FORCE_STAND = 142,
    EV_STANCE_FORCE_CROUCH = 143,
    EV_STANCE_FORCE_PRONE = 144,
    EV_STEP_VIEW = 145,
    EV_WATER_TOUCH = 146,
    EV_WATER_LEAVE = 147,
    EV_ITEM_PICKUP = 148,
    EV_ITEM_PICKUP_QUIET = 149,
    EV_AMMO_PICKUP = 150,
    EV_NOAMMO = 151,
    EV_EMPTYCLIP = 152,
    EV_RELOAD = 153,
    EV_RELOAD_FROM_EMPTY = 154,
    EV_RELOAD_START = 155,
    EV_RELOAD_END = 156,
    EV_RAISE_WEAPON = 157,
    EV_PUTAWAY_WEAPON = 158,
    EV_WEAPON_ALT = 159,
    EV_DEPLOY_WEAPON = 160,
    EV_BREAKDOWN_WEAPON = 161,
    EV_PULLBACK_WEAPON = 162,
    EV_FIRE_WEAPON = 163,
    EV_FIRE_WEAPONB = 164,
    EV_FIRE_WEAPONC = 165,
    EV_FIRE_WEAPON_LASTSHOT = 166,
    EV_RECHAMBER_WEAPON = 167,
    EV_EJECT_BRASS = 168,
    EV_MELEE_SWIPE = 169,
    EV_FIRE_MELEE = 170,
    EV_MELEE_HIT = 171,
    EV_MELEE_MISS = 172,
    EV_FIRE_WEAPON_MG42 = 173,
    EV_FIRE_QUADBARREL_1 = 174,
    EV_FIRE_QUADBARREL_2 = 175,
    EV_BULLET_TRACER = 176,
    EV_SOUND_ALIAS = 177,
    EV_BULLET_HIT = 178,
    EV_BULLET_HIT_CLIENT_SMALL = 179,
    EV_BULLET_HIT_CLIENT_LARGE = 180,
    EV_GRENADE_BOUNCE = 181,
    EV_GRENADE_SPOON = 182,
    EV_PROJECTILE_LAUNCH = 183,
    EV_PROJECTILE_INCOMING = 184,
    EV_PROJECTILE_EXPLODE = 185,
    EV_PROJECTILE_EXPLODE_NOMARKS = 186,
    EV_MOLOTOV_EXPLODE = 187,
    EV_MOLOTOV_EXPLODE_NOMARKS = 188,
    EV_RAILTRAIL = 189,
    EV_BULLET = 190,
    EV_PAIN = 191,
    EV_CROUCH_PAIN = 192,
    EV_DEATH = 193,
    EV_DEBUG_LINE = 194,
    EV_PLAY_FX = 195,
    EV_PLAY_FX_DIR = 196,
    EV_PLAY_FX_ON_TAG = 197,
    EV_PLAY_FX_ON_PLAYER = 198,
    EV_STOP_ATTACHED_FX = 199,
    EV_FLAMEBARREL_BOUNCE = 200,
    EV_EARTHQUAKE = 201,
    EV_REMOVE_WEAPON_ATTACHMENTS = 202,
    EV_DROPWEAPON = 203,
    EV_ITEM_RESPAWN = 204,
    EV_ITEM_POP = 205,
    EV_PLAYER_TELEPORT_IN = 206,
    EV_PLAYER_TELEPORT_OUT = 207,
    EV_OVERHEATING = 208,
    EV_OBITUARY = 209,
    EV_GRENADE_SUICIDE = 210
} entityEvent_t;

/*
 * Client think timing and movement constants.
 * RECOVERED(UO-GAME-UNK-0164): Values observed in ClientThink_real decompiler output.
 */
#define CLIENT_THINK_TIME_CLAMP_MAX  200     /* Max milliseconds ahead */
#define CLIENT_THINK_TIME_CLAMP_MIN  -1000   /* Max milliseconds behind */
#define PMOVE_MSEC_MIN               8       /* Minimum pmove_msec */
#define PMOVE_MSEC_MAX               33      /* Maximum pmove_msec */

/* Shared live/dead player movement masks. The only difference is whether
 * CONTENTS_BODY participates in the trace. */
#define MASK_PLAYERSOLID 0x02810011
#define MASK_DEADSOLID   0x00810011

/* Vehicle collision constants */
#define VEHICLE_COLLISION_SPEED_THRESHOLD  200.0f
#define VEHICLE_COLLISION_DAMAGE           10
#define VEHICLE_COLLISION_COOLDOWN_MS      500

/* Shared player-state entity flag and user-command button bits. */
#define PS_EFLAGS_IN_VEHICLE 0x00100000u
#define BUTTON_ACTIVATE      0x00000040u

/* Script VM value/object discriminator. The engine's 19-entry stock type-name
 * table fixes this complete shared domain; Scr_GetPointerType returns the same
 * discriminator for the object referenced by a value of type OBJECT. */
typedef enum scriptValueType_e {
    SCRIPT_VAR_UNDEFINED = 0,
    SCRIPT_VAR_STRING = 1,
    SCRIPT_VAR_LOCALIZED_STRING = 2,
    SCRIPT_VAR_VECTOR = 3,
    SCRIPT_VAR_FLOAT = 4,
    SCRIPT_VAR_INT = 5,
    SCRIPT_VAR_CODEPOS = 6,
    SCRIPT_VAR_OBJECT = 7,
    SCRIPT_VAR_KEY_VALUE = 8,
    SCRIPT_VAR_FUNCTION = 9,
    SCRIPT_VAR_STACK = 10,
    SCRIPT_VAR_ANIMATION = 11,
    SCRIPT_VAR_THREAD = 12,
    SCRIPT_VAR_ENTITY = 13,
    SCRIPT_VAR_STRUCT = 14,
    SCRIPT_VAR_ARRAY = 15,
    SCRIPT_VAR_DEAD_THREAD = 16,
    SCRIPT_VAR_DEAD_ENTITY = 17,
    SCRIPT_VAR_DEAD_OBJECT = 18
} scriptValueType_t;

typedef enum {
    TEAM_FREE = 0,
    TEAM_NONE = TEAM_FREE,
    TEAM_AXIS = 1,
    TEAM_ALLIES = 2,
    TEAM_SPECTATOR = 3
} team_t;

typedef enum {
    SESS_STATE_PLAYING = 0,
    SESS_STATE_DEAD = 1,
    SESS_STATE_SPECTATOR = 2,
    SESS_STATE_INTERMISSION = 3
} sessionState_t;

typedef enum {
    EFFECTIVE_STANCE_STAND = 0,
    EFFECTIVE_STANCE_PRONE = 1,
    EFFECTIVE_STANCE_CROUCH = 2
} effectiveStance_t;

typedef enum {
    SESS_SQUAD_NONE = 0,
    SESS_SQUAD_ALPHA = 1,
    SESS_SQUAD_BRAVO = 2
} sessionSquad_t;

typedef enum {
    SCRIPT_CLIENT_NAME_MODE_AUTO = 0,
    SCRIPT_CLIENT_NAME_MODE_MANUAL = 1
} scriptClientNameMode_t;

typedef enum {
    CON_DISCONNECTED = 0,
    CON_CONNECTING = 1,
    CON_CONNECTED = 2
} clientConnectedState_t;

typedef enum objectiveState_e {
    OBJECTIVE_STATE_EMPTY = 0,
    OBJECTIVE_STATE_ACTIVE = 1,
    OBJECTIVE_STATE_INVISIBLE = 2,
    OBJECTIVE_STATE_CURRENT = 4
} objectiveState_t;

#define PLAYERSTATE_OBJECTIVE_COUNT 16
#define OBJECTIVE_ICON_MAX_LEN 63
#define OBJECTIVE_ENTITY_NONE ENTITYNUM_NONE

typedef struct objective_s {
    objectiveState_t state;                /* +0x00 */
    vec3_t origin;                         /* +0x04 */
    int32_t entityNum;                     /* +0x10 */
    int32_t teamNum;                       /* +0x14: netfield `teamNum` */
    int32_t icon;                          /* +0x18 */
} objective_t;                             /* ABI total size: 0x1c */

typedef enum {
    PM_TYPE_NORMAL = 0,
    PM_TYPE_LINKED = 1,
    PM_TYPE_NOCLIP = 2,
    PM_TYPE_UFO = 3,
    PM_TYPE_SPECTATOR = 4,
    PM_TYPE_INTERMISSION = 5,
    PM_TYPE_DEAD = 6,
    PM_TYPE_LINKED_DEAD = 7,
    PM_TYPE_ANIM_SCRIPT_LIMIT = PM_TYPE_DEAD
} pmType_t;

/* Shared playerState weapon-action discriminator. The names match the client
 * state machine; the game module's stock diagnostic strings independently
 * identify values 0..11. */
typedef enum weaponState_e {
    WEAPON_STATE_IDLE = 0,
    WEAPON_STATE_RAISING = 1,
    WEAPON_STATE_DROPPING = 2,
    WEAPON_STATE_FIRING = 3,
    WEAPON_STATE_RECHAMBERING = 4,
    WEAPON_STATE_RELOADING = 5,
    WEAPON_STATE_RELOADING_INTERRUPT = 6,
    WEAPON_STATE_RELOAD_START = 7,
    WEAPON_STATE_RELOAD_START_INTERRUPT = 8,
    WEAPON_STATE_RELOAD_END = 9,
    WEAPON_STATE_MELEE_WINDUP = 10,
    WEAPON_STATE_MELEE_RELAX = 11,
    WEAPON_STATE_DEPLOYING = 12,
    WEAPON_STATE_BREAKING_DOWN = 13
} weaponState_t;

typedef enum {
    PM_WEAPON_ANIM_IDLE = 0,
    PM_WEAPON_ANIM_FIRE = 2,
    PM_WEAPON_ANIM_FIRE_LASTSHOT = 3,
    PM_WEAPON_ANIM_RAISE_HIP = 4,
    PM_WEAPON_ANIM_ADS_FIRE = 5,
    PM_WEAPON_ANIM_ADS_FIRE_LASTSHOT = 6,
    PM_WEAPON_ANIM_RAISE_ADS = 7,
    PM_WEAPON_ANIM_MELEE = 8,
    PM_WEAPON_ANIM_LOWER = 9,
    PM_WEAPON_ANIM_SWITCH_RAISE = 10,
    PM_WEAPON_ANIM_RELOAD = 11,
    PM_WEAPON_ANIM_RELOAD_EMPTY = 12,
    PM_WEAPON_ANIM_RELOAD_START = 13,
    PM_WEAPON_ANIM_RELOAD_END = 14,
    PM_WEAPON_ANIM_ALT_SWITCH_LOWER = 15,
    PM_WEAPON_ANIM_ALT_SWITCH_RAISE = 16,
    PM_WEAPON_ANIM_SPECIAL_FIRE = 17,
    PM_WEAPON_ANIM_DEPLOYED = 18,
    PM_WEAPON_ANIM_ADS_IN = 19,
    PM_WEAPON_ANIM_ADS_OUT = 20
} pmWeaponAnim_t;

typedef enum {
    WEAPTYPE_BULLET = 0,
    WEAPTYPE_GRENADE = 1,
    WEAPTYPE_PROJECTILE = 2,
    WEAPTYPE_SPOTTER = 3,
    WEAPTYPE_GAS = 4,
    WEAPTYPE_COUNT = 5
} weaponType_t;

/* Parser custom field type 9 writes the stock 11-entry weapon-class string
 * table to +0x080. Its index 3 pointer resolves to the literal "lmg". */
typedef enum {
    WEAPCLASS_RIFLE = 0,
    WEAPCLASS_MG = 1,
    WEAPCLASS_SMG = 2,
    WEAPCLASS_LMG = 3,
    WEAPCLASS_PISTOL = 4,
    WEAPCLASS_GRENADE = 5,
    WEAPCLASS_ROCKETLAUNCHER = 6,
    WEAPCLASS_TURRET = 7,
    WEAPCLASS_SPOTTER = 8,
    WEAPCLASS_NON_PLAYER = 9,
    WEAPCLASS_FLAMETHROWER = 10,
    WEAPCLASS_COUNT = 11
} weaponClass_t;

/* Symbolic values accepted by the original "ammoType" weapon-field parser. */
typedef enum weaponAmmoType_e {
    WEAPON_AMMO_TYPE_SMG = 0,
    WEAPON_AMMO_TYPE_PISTOL = 1,
    WEAPON_AMMO_TYPE_RIFLE = 2,
    WEAPON_AMMO_TYPE_LMG = 3,
    WEAPON_AMMO_TYPE_HMG = 4,
    WEAPON_AMMO_TYPE_UMG = 5,
    WEAPON_AMMO_TYPE_COUNT = 6
} weaponAmmoType_t;

typedef enum {
    WEAPSLOT_NONE = 0,
    WEAPSLOT_PRIMARY_FIRST = 1,
    WEAPSLOT_PRIMARY_SECOND = 2,
    WEAPSLOT_PRIMARY = WEAPSLOT_PRIMARY_FIRST,
    WEAPSLOT_PRIMARYB = WEAPSLOT_PRIMARY_SECOND,
    WEAPSLOT_PRIMARY_LIMIT = 3,
    WEAPSLOT_PISTOL = 3,
    WEAPSLOT_GRENADE = 4,
    WEAPSLOT_SMOKER = 5,
    WEAPSLOT_LAST_DROPPABLE = 7,
    WEAPSLOT_COUNT = 8
} weaponSlot_t;

/*
 * Means of Death (MOD) enumeration.
 * RECOVERED(UO-GAME-UNK-0173): Values observed in G_Damage, G_RadiusDamage,
 * VEH_PlayerDamage, and other damage-related functions.
 */
typedef enum {
    MOD_UNKNOWN = 0,
    MOD_PISTOL_BULLET = 1,
    MOD_RIFLE_BULLET = 2,
    MOD_GRENADE = 3,
    MOD_GRENADE_SPLASH = 4,
    MOD_PROJECTILE = 5,
    MOD_PROJECTILE_SPLASH = 6,
    MOD_MELEE = 7,
    MOD_HEAD_SHOT = 8,
    MOD_MORTAR = 9,
    MOD_MORTAR_SPLASH = 10,
    MOD_DYNAMITE = 11,
    MOD_DYNAMITE_SPLASH = 12,
    MOD_ARTILLERY = 13,
    MOD_ARTILLERY_SPLASH = 14,
    MOD_WATER = 15,
    MOD_CRUSH = 16,
    MOD_CRUSH_TANK = 17,
    MOD_CRUSH_JEEP = 18,
    MOD_TELEFRAG = 19,
    MOD_FALLING = 20,
    MOD_SUICIDE = 21,
    MOD_TRIGGER_HURT = 22,
    MOD_EXPLOSIVE = 23,
    MOD_COLLISION = 24,
    MOD_FLAME = 25,
    MOD_MELEE_BINOCULARS = 26,
    MOD_COUNT = 27,
    MOD_VEHICLE_COLLISION_TYPE1 = MOD_CRUSH_TANK,
    MOD_VEHICLE_COLLISION_TYPE2 = MOD_CRUSH_JEEP,
    MOD_RADIUS_DAMAGE = MOD_EXPLOSIVE,
    MOD_VEHICLE_CRUSH = MOD_SUICIDE
} meansOfDeath_t;

/* Damage flags */
typedef enum damageFlags_e {
    DAMAGE_RADIUS = 1 << 0,          /* Damage from radius explosion */
    DAMAGE_NO_KNOCKBACK = 1 << 1,    /* No knockback applied */
    DAMAGE_HALF_KNOCKBACK = 1 << 2,  /* Reduced knockback */
    DAMAGE_NO_PROTECTION = 1 << 4    /* Bypass protection for forced kills */
} damageFlags_t;

typedef enum hitLocation_e {
    HITLOC_NONE = 0,
    HITLOC_HELMET,
    HITLOC_HEAD,
    HITLOC_NECK,
    HITLOC_TORSO_UPPER,
    HITLOC_TORSO_LOWER,
    HITLOC_RIGHT_ARM_UPPER,
    HITLOC_LEFT_ARM_UPPER,
    HITLOC_RIGHT_ARM_LOWER,
    HITLOC_LEFT_ARM_LOWER,
    HITLOC_RIGHT_HAND,
    HITLOC_LEFT_HAND,
    HITLOC_RIGHT_LEG_UPPER,
    HITLOC_LEFT_LEG_UPPER,
    HITLOC_RIGHT_LEG_LOWER,
    HITLOC_LEFT_LEG_LOWER,
    HITLOC_RIGHT_FOOT,
    HITLOC_LEFT_FOOT,
    HITLOC_GUN,
    HITLOC_COUNT
} hitLocation_t;

/* ---------------------------------------------------------------------------
 * Weapon info structure (weaponInfo_t).
 * Field order and offsets are proved by the original weapon-field parser and
 * consumers across items.c, client_frame.c, animation.c, and weapons.c.
 * Accessed via BG_GetInfoForWeapon() which returns a pointer into a global
 * weapon info array.  Fields accessed through WeaponInfoInt/Float/String
 * helper functions that index by byte offset.
 * Total observed ABI extent: 0x4bc bytes (through ads_fire_delay_out_rate offset 0x4b8).
 * UO-GAME-TASK-0345 checked remaining pad ranges against maintained offset
 * helpers; no additional source access was observed.
 * --------------------------------------------------------------------------- */
typedef struct weaponInfo_s {
    /* --- Identity / names (offset range 0x000-0x00c) --- */
    int32_t weaponIndex;                           /* +0x000, BG_GetWeaponForInfo */
    const char *pickupName;                        /* +0x004 */
    const char *displayName;                       /* +0x008 */
    const char *aiOverlayDescription;              /* +0x00c, weapon key "AIOverlayDescription" */
    const char *gunModel;                          /* +0x010, weapon key "gunModel" */
    const char *handModel;                         /* +0x014, weapon key "handModel" */
    uint8_t reserved018[4];                        /* +0x018; no descriptor or direct access in either original module; retained for ABI. */
    const char *idleAnim;                          /* +0x01c, weapon key "idleAnim" */
    const char *emptyIdleAnim;                     /* +0x020, weapon key "emptyIdleAnim" */
    const char *fireAnim;                          /* +0x024, weapon key "fireAnim" */
    const char *holdFireAnim;                      /* +0x028, weapon key "holdFireAnim" */
    const char *lastShotAnim;                      /* +0x02c, weapon key "lastShotAnim" */
    const char *rechamberAnim;                     /* +0x030, weapon key "rechamberAnim" */
    const char *meleeAnim;                         /* +0x034, weapon key "meleeAnim" */
    const char *reloadAnim;                        /* +0x038, weapon key "reloadAnim" */
    const char *reloadEmptyAnim;                   /* +0x03c, weapon key "reloadEmptyAnim" */
    const char *reloadStartAnim;                   /* +0x040, weapon key "reloadStartAnim" */
    const char *reloadEndAnim;                     /* +0x044, weapon key "reloadEndAnim" */
    const char *raiseAnim;                         /* +0x048, weapon key "raiseAnim" */
    const char *dropAnim;                          /* +0x04c, weapon key "dropAnim" */
    const char *altRaiseAnim;                      /* +0x050, weapon key "altRaiseAnim" */
    const char *altDropAnim;                       /* +0x054, weapon key "altDropAnim" */
    const char *adsFireAnim;                       /* +0x058, weapon key "adsFireAnim" */
    const char *adsLastShotAnim;                   /* +0x05c, weapon key "adsLastShotAnim" */
    const char *adsRechamberAnim;                  /* +0x060, weapon key "adsRechamberAnim" */
    const char *lmgDeployedAnim;                   /* +0x064, weapon key "lmgDeployedAnim";
                                                      also alias "adsDeployedAnim". */
    const char *lmgDeployAnim;                     /* +0x068, weapon key "lmgDeployAnim";
                                                      also alias "adsDeployAnim". */
    const char *lmgBreakdownAnim;                  /* +0x06c, weapon key "lmgBreakdownAnim";
                                                      also alias "adsBreakdownAnim". */
    const char *adsUpAnim;                         /* +0x070, weapon key "adsUpAnim" */
    const char *adsDownAnim;                       /* +0x074, weapon key "adsDownAnim" */
    const char *modeName;                          /* +0x078, weapon key "modeName" */

    /* --- Classification (offset range 0x07c-0x08c) --- */
    weaponType_t weaponType;                       /* +0x07c */
    weaponClass_t weaponClass;                     /* +0x080 */
    int32_t slot;                                  /* +0x084 */
    int32_t stackable;                             /* +0x088 */
    int32_t stance;                                /* +0x08c, parser stance enum; turret use pose */
    weaponAmmoType_t ammoType;                     /* +0x090, literal parser key "ammoType" */
    const char *viewFlashEffect;                   /* +0x094, weapon key "viewFlashEffect" */
    const char *worldFlashEffect;                  /* +0x098, weapon key "worldFlashEffect" */
    const char *pickupSound;                       /* +0x09c, weapon item pickup sound */
    const char *ammoPickupSound;                   /* +0x0a0, weapon key "ammoPickupSound" */
    const char *projectileSound;                   /* +0x0a4, weapon key "projectileSound" */
    const char *pullbackSound;                     /* +0x0a8, weapon key "pullbackSound" */
    const char *fireSound;                         /* +0x0ac, weapon key "fireSound" */
    const char *loopFireSound;                     /* +0x0b0, weapon key "loopFireSound" */
    const char *stopFireSound;                     /* +0x0b4, weapon key "stopFireSound" */
    const char *fireEchoSound;                     /* +0x0b8, weapon key "fireEchoSound" */
    const char *lastShotSound;                     /* +0x0bc, weapon key "lastShotSound" */
    const char *rechamberSound;                    /* +0x0c0, weapon key "rechamberSound" */
    const char *reloadSound;                       /* +0x0c4, weapon key "reloadSound" */
    const char *reloadEmptySound;                  /* +0x0c8, weapon key "reloadEmptySound" */
    const char *reloadStartSound;                  /* +0x0cc, weapon key "reloadStartSound" */
    const char *reloadEndSound;                    /* +0x0d0, weapon key "reloadEndSound" */
    const char *raiseSound;                        /* +0x0d4, weapon key "raiseSound" */
    const char *altSwitchSound;                    /* +0x0d8, weapon key "altSwitchSound" */
    const char *deploySound;                       /* +0x0dc, weapon key "deploySound" */
    const char *breakdownSound;                    /* +0x0e0, weapon key "breakdownSound" */
    const char *putawaySound;                      /* +0x0e4, weapon key "putawaySound" */
    const char *noteTrackSoundA;                   /* +0x0e8, weapon key "noteTrackSoundA" */
    const char *noteTrackSoundB;                   /* +0x0ec, weapon key "noteTrackSoundB" */
    const char *noteTrackSoundC;                   /* +0x0f0, weapon key "noteTrackSoundC" */
    const char *noteTrackSoundD;                   /* +0x0f4, weapon key "noteTrackSoundD" */
    const char *projectileSoundBlend1;             /* +0x0f8, weapon key "projectileSoundBlend1" */
    const char *projectileSoundBlend2;             /* +0x0fc, weapon key "projectileSoundBlend2" */
    const char *shellEjectEffect;                  /* +0x100, weapon key "shellEjectEffect" */
    const char *lastShotEjectEffect;               /* +0x104, weapon key "lastShotEjectEffect" */
    const char *reticleCenter;                     /* +0x108, weapon key "reticleCenter" */
    const char *reticleSide;                       /* +0x10c, weapon key "reticleSide" */
    int32_t reticleCenterSize;                     /* +0x110, weapon key "reticleCenterSize" */
    int32_t reticleSideSize;                       /* +0x114, weapon key "reticleSideSize" */
    int32_t reticleMinOfs;                         /* +0x118, weapon key "reticleMinOfs" */

    /* --- Stance move offset range (0x11c-0x1c4) --- */
    vec3_t sprintMove;                           /* +0x11c, weapon keys sprintMoveF/R/U */
    vec3_t sprintRot;                            /* +0x128, weapon keys sprintRotP/Y/R */
    vec3_t standMove;                            /* +0x134, weapon keys standMoveF/R/U */
    vec3_t standRot;                             /* +0x140, weapon keys standRotP/Y/R */
    vec3_t duckedOffset;                         /* +0x14c, weapon keys duckedOfsF/R/U */
    vec3_t duckedMove;                           /* +0x158, weapon keys duckedMoveF/R/U */
    vec3_t duckedRot;                            /* +0x164, weapon keys duckedRotP/Y/R */
    vec3_t proneOffset;                          /* +0x170, weapon keys proneOfsF/R/U */
    vec3_t proneMove;                            /* +0x17c, weapon keys proneMoveF/R/U */
    vec3_t proneRot;                             /* +0x188, weapon keys proneRotP/Y/R */
    float moveSmooth;                              /* +0x194, weapon key "posMoveRate" */
    float moveSmoothProne;                         /* +0x198, weapon key "posProneMoveRate" */
    float moveThresholdAlt;                        /* +0x19c, weapon key "sprintMoveMinSpeed" */
    float moveThresholdStand;                      /* +0x1a0, weapon key "standMoveMinSpeed" */
    float moveThresholdCrouch;                     /* +0x1a4, weapon key "duckedMoveMinSpeed" */
    float moveThresholdProne;                      /* +0x1a8, weapon key "proneMoveMinSpeed" */
    float posRotRate;                              /* +0x1ac, weapon key "posRotRate" */
    float posProneRotRate;                         /* +0x1b0, weapon key "posProneRotRate" */
    float sprintRotMinSpeed;                       /* +0x1b4, read by BG_CalculateWeaponPosition_BasePosition_angles; no parser key observed in retail table. */
    float standRotMinSpeed;                        /* +0x1b8, weapon key "standRotMinSpeed" */
    float duckedRotMinSpeed;                       /* +0x1bc, weapon key "duckedRotMinSpeed" */
    float proneRotMinSpeed;                        /* +0x1c0, weapon key "proneRotMinSpeed" */
    const char *scriptClassname;                   /* +0x1c4, weapon key "radiantName" */

    /* --- Model string pointers (offset range 0x1c8-0x1d4) --- */
    const char *worldModel;                        /* +0x1c8 */
    const char *pickupModel;                       /* +0x1cc, weapon key "pickupModel" */
    const char *viewModel;                         /* +0x1d0, weapon key "attachModel" */
    const char *hudIcon;                           /* +0x1d4, weapon key "hudIcon" */
    const char *modeIcon;                          /* +0x1d8, weapon key "modeIcon" */
    const char *ammoIcon;                          /* +0x1dc, weapon key "ammoIcon" */

    /* --- Ammo configuration (offset range 0x1e0-0x204) --- */
    int32_t startAmmo;                             /* +0x1e0 */
    const char *ammoName;                          /* +0x1e4, setup input for ammoIndex */
    int32_t ammoIndex;                             /* +0x1e8 */
    const char *clipName;                          /* +0x1ec, setup input for clipIndex */
    int32_t clipIndex;                             /* +0x1f0, BG_ClipForWeapon */
    int32_t maxAmmo;                               /* +0x1f4, setup table max ammo */
    int32_t clipSize;                              /* +0x1f8 */
    const char *sharedAmmoCapName;                 /* +0x1fc, setup input for sharedAmmoCapIndex */
    int32_t sharedAmmoCapIndex;                    /* +0x200, derived shared-pool table index or -1 */
    int32_t sharedAmmoCap;                         /* +0x204, weapon key "sharedAmmoCap" */

    /* --- Direct damage / grenade touch (offset range 0x208-0x218) --- */
    int32_t flameDamage;                           /* +0x208 */
    int32_t grenadeTouchDamageEnabled;             /* +0x20c, weapon key "takedamage";
                                                      low byte is copied to grenade takeDamage. */
    int32_t damageFalloffMinDamagePercent;         /* +0x210, Damage_Falloff min percent */
    int32_t damageFalloffMinRange;                 /* +0x214, Damage_Falloff min range */
    int32_t damageFalloffMaxRange;                 /* +0x218, Damage_Falloff max range */

    /* --- Melee (offset range 0x21c-0x23c) --- */
    int32_t meleeDamage;                           /* +0x21c, Weapon_Melee / PM_Weapon gate */
    uint8_t reserved220[4];                        /* +0x220; no descriptor or direct access in either original module; retained for ABI. */
    int32_t fireDelay;                             /* +0x224 */
    int32_t meleeWindup;                           /* +0x228 */
    int32_t fireTime;                              /* +0x22c */

    /* --- Raise / lower timing (offset range 0x230-0x268) --- */
    int32_t raiseTime;                             /* +0x230 */
    int32_t raiseInterruptTime;                    /* +0x234 */
    int32_t specialFireDelay;                      /* +0x238 */
    int32_t meleeTime;                             /* +0x23c */
    int32_t reloadTime;                            /* +0x240 */
    int32_t reloadEmptyTime;                       /* +0x244 */
    int32_t reloadAddTime;                         /* +0x248 */
    int32_t reloadStartTime;                       /* +0x24c */
    int32_t reloadStartAddTime;                    /* +0x250 */
    int32_t reloadEndTime;                         /* +0x254 */
    int32_t lowerTime;                             /* +0x258 */
    int32_t switchRaiseTime;                       /* +0x25c */
    int32_t altSwitchLowerTime;                    /* +0x260 */
    int32_t altSwitchRaiseTime;                    /* +0x264 */
    int32_t specialTimeThreshold;                  /* +0x268 */
    float moveSpeedScale;                          /* +0x26c, weapon key "moveSpeedScale" */
    float adsSensitivity;                          /* +0x270, weapon key "adsSensitivity" */
    float adsZoomFov;                              /* +0x274, weapon key "adsZoomFov"; alias "turret_fov" */
    float adsZoomInFrac;                           /* +0x278, weapon key "adsZoomInFrac" */
    float adsZoomOutFrac;                          /* +0x27c, weapon key "adsZoomOutFrac" */
    const char *adsOverlayShader;                  /* +0x280, weapon key "adsOverlayShader" */

    /* --- Viewkick / ADS reduce (offset range 0x284-0x298) --- */
    int32_t overlayReticleAdsReduceGate;           /* +0x284, overlay reticle enum; nonzero ADS viewkick/sway gate */
    float adsOverlayWidth;                         /* +0x288, weapon key "adsOverlayWidth" */
    float adsOverlayHeight;                        /* +0x28c, weapon key "adsOverlayHeight" */
    float adsBobFactor;                            /* +0x290 */
    float adsViewBobScale;                         /* +0x294 */
    float hipSpreadStandMin;                       /* +0x298, weapon key "hipSpreadStandMin" */
    float hipSpreadDucked;                         /* +0x29c, BG_GetMinSpreadForWeapon */
    float hipSpreadProne;                          /* +0x2a0, BG_GetMinSpreadForWeapon */
    float maxSpread;                               /* +0x2a4, weapon keys "hipSpreadMax" / "maxSpread" */
    float aimSpreadDecayRate;                      /* +0x2a8, RECOVERED(UO-GAME-TASK-0276) */
    float fireAimSpreadScale;                      /* +0x2ac */
    float aimSpreadTurnRate;                       /* +0x2b0, RECOVERED(UO-GAME-TASK-0276) */
    float aimSpreadMoveAdd;                        /* +0x2b4, RECOVERED(UO-GAME-TASK-0276) */
    float aimSpreadCrouchScale;                    /* +0x2b8, RECOVERED(UO-GAME-TASK-0276) */
    float aimSpreadProneScale;                     /* +0x2bc, RECOVERED(UO-GAME-TASK-0276) */
    float hipReticleSidePos;                       /* +0x2c0, weapon key "hipReticleSidePos" */

    /* --- ADS timing (offset range 0x2c4-0x2c8) --- */
    int32_t adsInTime;                             /* +0x2c4 */
    int32_t adsOutTime;                            /* +0x2c8 */

    /* --- Idle sway (offset range 0x2cc-0x2d8) --- */
    float idleSwayAds;                             /* +0x2cc */
    float idleSwayHip;                             /* +0x2d0 */
    float idleSwayCrouchScale;                     /* +0x2d4 */
    float idleSwayProneScale;                      /* +0x2d8 */

    /* --- Hip recoil envelope (offset range 0x2dc-0x2f8) --- */
    float gunMaxPitch;                             /* +0x2dc, weapon key "gunMaxPitch" */
    float gunMaxYaw;                               /* +0x2e0, weapon key "gunMaxYaw" */
    float swayMaxAngle;                            /* +0x2e4, weapon key "swayMaxAngle" */
    float swayLerpSpeed;                           /* +0x2e8, weapon key "swayLerpSpeed" */
    float swayPitchScale;                          /* +0x2ec, weapon key "swayPitchScale" */
    float swayYawScale;                            /* +0x2f0, weapon key "swayYawScale" */
    float swayHorizScale;                          /* +0x2f4, weapon key "swayHorizScale" */
    float swayVertScale;                           /* +0x2f8, weapon key "swayVertScale" */
    float swayShellShockScale;                     /* +0x2fc, weapon key "swayShellShockScale" */

    /* --- ADS sway (offset range 0x300-0x318) --- */
    float adsSwayMaxAngle;                         /* +0x300, weapon key "adsSwayMaxAngle" */
    float adsSwayLerpSpeed;                        /* +0x304, weapon key "adsSwayLerpSpeed" */
    float adsSwayPitchScale;                       /* +0x308, weapon key "adsSwayPitchScale" */
    float adsSwayYawScale;                         /* +0x30c, weapon key "adsSwayYawScale" */
    float adsSwayHorizScale;                       /* +0x310, weapon key "adsSwayHorizScale" */
    float adsSwayVertScale;                        /* +0x314, weapon key "adsSwayVertScale" */
    int32_t twoHanded;                             /* +0x318, weapon key "twoHanded" */

    /* --- Ricochet / hold / raise (offset range 0x31c-0x34c) --- */
    int32_t ricochet;                              /* +0x31c, weapon key "rifleBullet" */
    int32_t weaponTimeHold;                        /* +0x320, weapon key "semiAuto" */
    int32_t raiseEnabled;                          /* +0x324, weapon key "boltAction" */
    int32_t adsEnabled;                            /* +0x328, weapon key "aimDownSight" */
    int32_t adsRaiseEnabled;                       /* +0x32c, weapon key "rechamberWhileAds" */
    float adsViewErrorMin;                         /* +0x330, weapon key "adsViewErrorMin" */
    float adsViewErrorMax;                         /* +0x334, weapon key "adsViewErrorMax" */
    int32_t specialTimeEnabled;                    /* +0x338, weapon key "cookOffHold" */
    int32_t cloth;                                 /* +0x33c, weapon key "cloth" */
    int32_t clipRequired;                          /* +0x340, weapon key "clipOnly" */
    int32_t wideListIcon;                          /* +0x344, weapon key "wideListIcon" */
    int32_t adsFireDelayEnabled;                   /* +0x348, weapon key "adsFire" */
    int32_t dropDisabled;                          /* +0x34c, weapon key "doNotDrop" */
    const char *killIcon;                          /* +0x350, weapon key "killIcon" */
    int32_t wideKillIcon;                          /* +0x354, weapon key "wideKillIcon" */
    int32_t reloadRequiresAddRoom;                 /* +0x358, weapon key "noPartialReload" */
    int32_t segmentedReload;                       /* +0x35c, weapon key "segmentedReload" */
    int32_t reloadAmmoAdd;                         /* +0x360 */
    int32_t reloadStartAmmoAdd;                    /* +0x364 */
    const char *altWeaponName;                     /* +0x368, setup input for altWeapon */
    int32_t altWeapon;                             /* +0x36c */
    int32_t dropAmmoMin;                           /* +0x370 */
    int32_t dropAmmoMax;                           /* +0x374 */
    int32_t missileSplashRadius;                   /* +0x378, artillery/missile radius */
    int32_t missileSplashDamage;                   /* +0x37c, PM grenade special-fire checks nonzero */
    int32_t missileSplashMinDamage;                /* +0x380, artillery/missile min splash damage */
    int32_t missileSpeed;                          /* +0x384, artillery missile downward speed */
    int32_t missileVerticalSpeed;                  /* +0x388, grenade launcher upward speed */

    /* --- Clip model (offset 0x38c) --- */
    const char *clipModel;                         /* +0x38c */
    int32_t projectileExplosionType;               /* +0x390, parsed grenade/projectile explosion enum */
    const char *projectileExplosionEffect;         /* +0x394, weapon key "projExplosionEffect" */
    const char *projectileExplosionSound;          /* +0x398, weapon key "projExplosionSound" */
    int32_t projectileImpactExplode;               /* +0x39c, weapon key "projImpactExplode" */
    int32_t artilleryBarrageCount;                  /* +0x3a0, barrage FX/shot count */
    int32_t artilleryBarrageSpread;                 /* +0x3a4, barrage random impact radius */
    int32_t artilleryBarrageFirstDelay;             /* +0x3a8, first artillery shell delay */
    int32_t artilleryBarrageDelayMin;               /* +0x3ac, barrage delay min */
    int32_t artilleryBarrageDelayMax;               /* +0x3b0, barrage delay max */
    const char *projectileTrailEffect;             /* +0x3b4, weapon key "projTrailEffect" */
    int32_t projectileDLight;                      /* +0x3b8, weapon key "projectileDLight" */
    float projectileRed;                           /* +0x3bc, weapon key "projectileRed" */
    float projectileGreen;                         /* +0x3c0, weapon key "projectileGreen" */
    float projectileBlue;                          /* +0x3c4, weapon key "projectileBlue" */

    /* --- ADS pitch offset (0x3c8) --- */
    float adsPitchOffset;                          /* +0x3c8 */
    float adsCrosshairInFrac;                      /* +0x3cc, weapon key "adsCrosshairInFrac" */
    float adsCrosshairOutFrac;                     /* +0x3d0, weapon key "adsCrosshairOutFrac" */

    /* --- Fire recoil ADS (offset range 0x3d4-0x3f0) --- */
    float fireRecoilAdsPitchMin;                   /* +0x3d4 */
    float fireRecoilAdsPitchMax;                   /* +0x3d8 */
    float fireRecoilAdsYawMin;                     /* +0x3dc */
    float fireRecoilAdsYawMax;                     /* +0x3e0 */
    float recoilReturnAds;                         /* +0x3e4 */
    float recoilVelocityAds;                       /* +0x3e8 */
    float recoilDampingAds;                        /* +0x3ec */
    float recoilFrictionAds;                       /* +0x3f0 */

    /* --- Fire viewkick ADS (offset range 0x3f4-0x404) --- */
    float fireViewkickAdsPitchMin;                 /* +0x3f4 */
    float fireViewkickAdsPitchMax;                 /* +0x3f8 */
    float fireViewkickAdsYawMin;                   /* +0x3fc */
    float fireViewkickAdsYawMax;                   /* +0x400 */
    float adsViewKickCenterSpeed;                  /* +0x404, weapon key "adsViewKickCenterSpeed" */
    uint8_t reserved408[8];                        /* +0x408..0x40f; no descriptor or direct access in either original module; retained for ABI. */
    float adsSpread;                               /* +0x410, weapon key "adsSpread" */
    float adsSpreadDucked;                         /* +0x414, BG_GetMinSpreadForWeapon */
    float adsSpreadProne;                          /* +0x418, BG_GetMinSpreadForWeapon */

    /* --- Fire recoil hip (offset range 0x41c-0x438) --- */
    float fireRecoilHipPitchMin;                   /* +0x41c */
    float fireRecoilHipPitchMax;                   /* +0x420 */
    float fireRecoilHipYawMin;                     /* +0x424 */
    float fireRecoilHipYawMax;                     /* +0x428 */
    float recoilReturnHip;                         /* +0x42c */
    float recoilVelocityHip;                       /* +0x430 */
    float recoilDampingHip;                        /* +0x434 */
    float recoilFrictionHip;                       /* +0x438 */

    /* --- Fire viewkick hip (offset range 0x43c-0x44c) --- */
    float fireViewkickHipPitchMin;                 /* +0x43c */
    float fireViewkickHipPitchMax;                 /* +0x440 */
    float fireViewkickHipYawMin;                   /* +0x444 */
    float fireViewkickHipYawMax;                   /* +0x448 */
    float hipViewKickCenterSpeed;                  /* +0x44c, weapon key "hipViewKickCenterSpeed" */
    uint8_t reserved450[8];                        /* +0x450..0x457; no descriptor or direct access in either original module; retained for ABI. */
    float aiEffectiveRange;                        /* +0x458, weapon key "aiEffectiveRange" */
    float aiMissRange;                             /* +0x45c, weapon key "aiMissRange" */
    int32_t reloadLoopTime;                        /* +0x460, weapon key "adsReloadTransTime" */
    int32_t adsTransBlendTime;                     /* +0x464, weapon key "adsTransBlendTime" */
    float turretLeftArcDefault;                    /* +0x468, weapon key "leftArc" */
    float turretRightArcDefault;                   /* +0x46c, weapon key "rightArc" */
    float turretTopArcDefault;                     /* +0x470, weapon key "topArc" */
    float turretBottomArcDefault;                  /* +0x474, weapon key "bottomArc" */
    float turretAccuracy;                          /* +0x478, weapon key "accuracy" */
    float turretPitchRate;                         /* +0x47c, weapon key "vertTurnSpeed" */
    float turretYawRate;                           /* +0x480, weapon key "horTurnSpeed" */
    float turretConvergenceTime;                   /* +0x484, weapon key "convergenceTime" */
    float turretMaxRange;                          /* +0x488, weapon key "maxRange" */
    float animHorRotateInc;                        /* +0x48c, weapon key "animHorRotateInc" */
    float turretPlayerSpacing;                     /* +0x490, weapon key "playerPositionDist" */
    const char *hintString;                        /* +0x494, weapon key "useHintString" */
    int32_t hintStringIndex;                       /* +0x498, resolved hintstring configstring index */
    float turretHeatPerShot;                       /* +0x49c, weapon key "fireHeat" */
    float turretHeatDecay;                         /* +0x4a0, weapon key "cooldownRate" */
    float horizViewJitter;                         /* +0x4a4, weapon key "horizViewJitter" */
    float vertViewJitter;                          /* +0x4a8, weapon key "vertViewJitter" */
    float grenadeSplashVehicleDamageScale;         /* +0x4ac, weapon key "vehiclescale";
                                                      positive override for grenade splash
                                                      vehicle damage. */
    const char *script;                            /* +0x4b0, weapon key "script" */

    /* --- ADS fire delay rates (offset range 0x4b4-0x4b8) --- */
    float adsFireDelayRate;                        /* +0x4b4 */
    float adsFireDelayOutRate;                     /* +0x4b8, RECOVERED(UO-GAME-UNK-0276) */
} weaponInfo_t;

typedef struct weapon_muzzle_s {
    vec3_t forward;                  /* +0x00 */
    vec3_t right;                    /* +0x0c */
    vec3_t up;                       /* +0x18 */
    vec3_t origin;                   /* +0x24 */
    vec3_t extraVector;              /* +0x30 */
    const weaponInfo_t *weaponInfo;    /* +0x3c */
} weapon_muzzle_t;

typedef struct turret_muzzle_s {
    vec3_t forward;
    vec3_t right;
    vec3_t up;
    vec3_t origin;
    vec3_t forwardCopy;
    const weaponInfo_t *weaponInfo;
} turret_muzzle_t;

typedef weapon_muzzle_t command_muzzle_t;
typedef weapon_muzzle_t helper_weapon_muzzle_t;
typedef weapon_muzzle_t vehicle_turret_muzzle_t;

/* Exact source-tree tag recovered from same-generation Mac XAnim symbols. */
typedef struct XAnim_s XAnim;
typedef struct XAnimTree_s XAnimTree;

/* Exact original tag from Mac PEF symbol
 * __as__10scr_anim_sFRC10scr_anim_s. Its assignment body copies the two
 * uint16_t lanes independently; the i386 engine/game boundary uses the same
 * four-byte value. */
typedef struct scr_anim_s {
    uint16_t animIndex;                            /* +0x00 */
    uint16_t treeIndex;                            /* +0x02 */
} scr_anim_t;

enum {
    SCR_ANIM_TREE_INDEX_SHIFT = 16
};

typedef struct bg_runtime_animation_s {
    scr_anim_t anim;                               /* +0x00 */
    int32_t hash;                                  /* +0x04 */
    char name[0x40];                               /* +0x08 */
} bg_runtime_animation_t;                          /* ABI size: 0x48 bytes */

typedef struct bg_indexed_string_s {
    const char *name;                              /* +0x00 */
    int32_t hash;                                  /* +0x04 on i386 */
} bg_indexed_string_t;

typedef struct bg_anim_script_command_s {
    int16_t bodyPart[2];                           /* +0x00, bg_anim_body_part_t values */
    int16_t animIndex[2];                          /* +0x04 */
    int16_t duration[2];                           /* +0x08 */
    const char *soundAliasName;                    /* +0x0c on i386 */
} bg_anim_script_command_t;

typedef struct bg_anim_condition_s {
    int32_t type;                                  /* +0x00, bg_anim_condition_index_t value */
    int32_t value[2];                              /* +0x04 */
} bg_anim_condition_t;                             /* ABI size: 0x0c bytes */

typedef struct bg_anim_condition_type_s {
    int32_t mode;                                  /* +0x00, bg_anim_condition_mode_t value */
    bg_indexed_string_t *values;                   /* +0x04 on i386 */
} bg_anim_condition_type_t;

typedef struct bg_anim_script_s {
    int32_t conditionCount;                        /* +0x00 */
    bg_anim_condition_t conditions[ANIM_COND_COUNT];
                                                    /* +0x04 */
    int32_t commandCount;                          /* +0x88 */
    bg_anim_script_command_t commands[BG_ANIM_MAX_COMMANDS];
                                                    /* +0x8c */
} bg_anim_script_t;

typedef struct bg_anim_script_list_s {
    int32_t count;                                 /* +0x000 */
    /*
     * The i386 binary stores absolute script-pool pointers in these 32-bit
     * slots. The recovered host build keeps the same 0x204 table geometry,
     * but stores table-relative offsets so host pointers are not truncated.
     */
    uint32_t scriptOffsets[BG_ANIM_MAX_LIST_ITEMS];
                                                    /* +0x004 */
} bg_anim_script_list_t;                           /* ABI size: 0x204 bytes */

/* ---------------------------------------------------------------------------
 * HUD element structures.
 *
 * The first 0x7c bytes are copied verbatim into the current/archived client HUD
 * snapshots. The final three dwords are server-side routing/state fields.
 * --------------------------------------------------------------------------- */

/* HUD element type enum */
typedef enum hudElemType_e {
    HE_TYPE_NONE = 0,
    HE_TYPE_TEXT = 1,
    HE_TYPE_VALUE = 2,
    HE_TYPE_SHADER = 3,
    HE_TYPE_TIMER = 4,
    HE_TYPE_TIMER_UP = 5,
    HE_TYPE_TENTHS_TIMER = 6,
    HE_TYPE_TENTHS_TIMER_UP = 7,
    HE_TYPE_CLOCK = 8,
    HE_TYPE_CLOCK_UP = 9
} hudElemType_t;

typedef struct hudElemClientSnapshot_s {
    uint32_t type;                                 /* +0x000 */
    int32_t x;                                     /* +0x004, script integer */
    int32_t y;                                     /* +0x008, script integer */
    float fontScale;                               /* +0x00c */
    uint32_t font;                                 /* +0x010 */
    uint32_t alignX;                               /* +0x014, script field "alignx" */
    uint32_t alignY;                               /* +0x018, script field "aligny" */
    uint32_t color;                                /* +0x01c (RGBA packed) */
    uint32_t fromColor;                            /* +0x020 */
    int32_t fadeStartTime;                         /* +0x024 */
    int32_t fadeTime;                              /* +0x028 */
    int32_t label;                                 /* +0x02c */
    int32_t width;                                 /* +0x030 */
    int32_t height;                                /* +0x034 */
    int32_t materialIndex;                         /* +0x038 */
    int32_t scaleFromWidth;                        /* +0x03c */
    int32_t scaleFromHeight;                       /* +0x040 */
    int32_t scaleStartTime;                        /* +0x044 */
    int32_t scaleTime;                             /* +0x048 */
    int32_t moveFromX;                             /* +0x04c */
    int32_t moveFromY;                             /* +0x050 */
    int32_t moveStartTime;                         /* +0x054 */
    int32_t moveTime;                              /* +0x058 */
    int32_t timerTargetTime;                       /* +0x05c */
    int32_t timerDuration;                         /* +0x060 */
    float value;                                   /* +0x064 */
    int32_t text;                                  /* +0x068 */
    float sort;                                    /* +0x06c */
    float shaderRightTexcoord;                     /* +0x070 */
    float shaderBottomTexcoord;                    /* +0x074 */
    uint32_t unused78;                              /* +0x078, copied in the 0x7c-byte client snapshot but otherwise unused by the original game module, cgame, and CoDUOMP.exe. */
} hudElemClientSnapshot_t;                         /* ABI snapshot size: 0x7c bytes */

typedef struct hudElem_s {
    uint32_t type;                                 /* +0x000 */
    int32_t x;                                     /* +0x004, script integer */
    int32_t y;                                     /* +0x008, script integer */
    float fontScale;                               /* +0x00c */
    uint32_t font;                                 /* +0x010 */
    uint32_t alignX;                               /* +0x014, script field "alignx" */
    uint32_t alignY;                               /* +0x018, script field "aligny" */
    uint32_t color;                                /* +0x01c (RGBA packed) */
    uint32_t fromColor;                            /* +0x020 */
    int32_t fadeStartTime;                         /* +0x024 */
    int32_t fadeTime;                              /* +0x028 */
    int32_t label;                                 /* +0x02c */
    int32_t width;                                 /* +0x030 */
    int32_t height;                                /* +0x034 */
    int32_t materialIndex;                         /* +0x038 */
    int32_t scaleFromWidth;                        /* +0x03c */
    int32_t scaleFromHeight;                       /* +0x040 */
    int32_t scaleStartTime;                        /* +0x044 */
    int32_t scaleTime;                             /* +0x048 */
    int32_t moveFromX;                             /* +0x04c */
    int32_t moveFromY;                             /* +0x050 */
    int32_t moveStartTime;                         /* +0x054 */
    int32_t moveTime;                              /* +0x058 */
    int32_t timerTargetTime;                       /* +0x05c */
    int32_t timerDuration;                         /* +0x060 */
    float value;                                   /* +0x064 */
    int32_t text;                                  /* +0x068 */
    float sort;                                    /* +0x06c */
    float shaderRightTexcoord;                     /* +0x070 */
    float shaderBottomTexcoord;                    /* +0x074 */
    uint32_t unused78;                              /* +0x078, copied to clients but otherwise unused. */
    /* Server-side fields (not included in client snapshot) */
    int32_t clientNum;                             /* +0x07c */
    int32_t team;                                  /* +0x080 */
    int32_t archived;                              /* +0x084 */
} hudElem_t;                                       /* ABI total size: 0x88 bytes */

typedef void (*hudelem_field_callback_t)(hudElem_t *elem, int fieldIndex);
typedef void (*hudelem_method_callback_t)(int elemIndex);

typedef struct hudelem_field_s {
    const char *name;
    size_t offset;
    int32_t type;
    hudelem_field_callback_t setter;
    hudelem_field_callback_t getter;
} hudelem_field_t;

typedef struct hudelem_method_s {
    const char *name;
    hudelem_method_callback_t callback;
} hudelem_method_t;

/* ---------------------------------------------------------------------------
 * BGS player client-info record.
 *
 * This 0x4d0-byte record is passed around as a base pointer with several
 * source-level meanings.  The model/DObj code reads the user/model/tag string
 * view at +0x00c..+0x37f; animation and controller code reads the slot state at
 * +0x380..+0x4c7.  Offset +0x008 is the only known semantic overlap: userinfo
 * code stores a client number there, while moving-loop animation code consumes
 * the same word as a phase seed.
 *
 * The two structs below are intentionally overlay views of the same BGS record,
 * not independent allocations and not evidence of an original C union.
 * --------------------------------------------------------------------------- */
typedef union bg_player_anim_override_u {
    struct {
        float overridePitch;                       /* +0x00, absolute +0x3f4 */
        float overrideAngle;                       /* +0x04, absolute +0x3f8 */
        float overrideRoll;                        /* +0x08, absolute +0x3fc */
    } torsoState;
    struct {
        float pitch;                               /* +0x00, absolute +0x3f4 */
        float yaw;                                 /* +0x04, absolute +0x3f8 */
        float roll;                                /* +0x08, absolute +0x3fc */
    } angles;
} bg_player_anim_override_t;

/* Slot overlay used at clientInfo_t.legsYawAngle/torsoYawAngle.
 * The leading 0x10 bytes are the owning yaw/timer words, so this remains a
 * partial view instead of replacing the shared animation-state struct. */
typedef struct bg_anim_slot_s {
    char owningYawAndTimerPrefix[0x10];            /* +0x00 */
    uint32_t animationWord;                        /* +0x10 */
    /* i386 cached an absolute static-animation pointer here; host builds keep
     * the 0x30 slot geometry by caching a bgAnimStaticTable-relative offset. */
    uint32_t animationOffset;                      /* +0x14 */
    int32_t blendTime;                             /* +0x18 */
    vec3_t lastOrigin;                           /* +0x1c */
    float animRate;                                /* +0x28 */
    int32_t lastUpdateTime;                        /* +0x2c */
} bg_anim_slot_t;

/*
 * CoD extends Quake III's clientInfo_t into the shared BG animation/DObj
 * record. The original game and cgame binaries independently prove the same
 * 0x4d0 stride and every major subregion. A single declaration is used here;
 * the former anim/info overlay structs were reconstruction views, not evidence
 * of an original source union.
 */
typedef struct clientInfo_s {
    /* --- Shared client-info prefix (offset range 0x000-0x37f) --- */
    qboolean infoValid;                            /* +0x000, ClientConnect live/valid slot */
    int32_t pmType;                                /* +0x004, used by animation.c size check */
    int32_t clientNum;                             /* +0x008; moving-loop code also
                                                    * uses it as the per-client phase seed */
    char name[32];
                                                    /* +0x00c */
    int32_t team;                                  /* +0x02c */
    char abiGap_030_03f[0x010];                    /* +0x030..0x03f, size 0x010; game.mp.uo.i386.so has no clientInfo-relative access here. The cgame record uses four client-only HUD/score words at these offsets, but its +0x004 field already has different semantics, so those names are not imported into this server type. */
    char modelName[CLIENT_INFO_MODEL_NAME_SIZE];
                                                    /* +0x040 */
    char attachModelNames[CLIENT_INFO_ATTACHMENT_COUNT]
                         [CLIENT_INFO_MODEL_NAME_SIZE];
                                                    /* +0x080 */
    char attachTagNames[CLIENT_INFO_ATTACHMENT_COUNT]
                       [CLIENT_INFO_MODEL_NAME_SIZE];
                                                    /* +0x200 */

    /* --- Legs animation state (offset 0x380) --- */
    float legsYawAngle;                            /* +0x380,
                                                      (also) */
    qboolean legsYawActive;                        /* +0x384 */
    int32_t legsTimer;                             /* +0x388, legs animation timer */
    uint32_t legsAnim;                             /* +0x38c, legs animation index */

    /* Resolved from macOS binaries */
    uint32_t legsAnimWord;                      /* +0x390 */
    uint32_t legsAnimEntryWord;                     /* +0x394, i386 animScriptItem_t pointer word */
    int32_t legsAnimBlendTime;                  /* +0x398 */
    vec3_t legsMoveOrigin;                    /* +0x39c */
    float legsAnimMoveRate;                     /* +0x3a8 */
    int32_t legsAnimMoveTime;                   /* +0x3ac */

    /* --- Torso animation state (offset 0x3b0) --- */
    float torsoYawAngle;                           /* +0x3b0,
                                                      (also) */
    qboolean torsoYawActive;                       /* +0x3b4 */
    float leanAngle;                               /* +0x3b8 */
    qboolean leanActive;                           /* +0x3bc */
    uint32_t torsoAnimWord;                        /* +0x3c0 */

    /* Resolved from macOS binaries */
    uint32_t torsoAnimEntryWord;                    /* +0x3c4, i386 animScriptItem_t pointer word */
    int32_t torsoAnimBlendTime;                 /* +0x3c8 */
    vec3_t torsoMoveOrigin;                   /* +0x3cc */
    float torsoAnimMoveRate;                    /* +0x3d8 */
    int32_t torsoAnimMoveTime;                  /* +0x3dc */

    /* --- Lean / vehicle / override (offset range 0x3e0-0x407) --- */
    float leanAmount;                              /* +0x3e0 */
    float leanFraction;                            /* +0x3e4 */
    float viewPitch;                               /* +0x3e8, client viewAngles[0] */
    float viewYaw;                                 /* +0x3ec, client viewAngles[1] */
    float viewRoll;                                /* +0x3f0, client viewAngles[2] */
    bg_player_anim_override_t override;            /* +0x3f4, vehicle override angle triplet */
    int32_t torsoTimer;                            /* +0x400 */
    int32_t dobjNeedsUpdate;                       /* +0x404, dirty flag consumed by BG_UpdatePlayerDObj */

    /* --- Controller angles (offset range 0x408-0x460) --- */
    float controllerAngles[6][3];                  /* +0x408 */
    vec3_t localTagAngles;                       /* +0x450 */
    vec3_t localTagOffset;                       /* +0x45c */
    uint32_t conditionWords[ANIM_COND_COUNT][2]; /* +0x468, animation condition-state words */
    int32_t animTransitionTime;                    /* +0x4c0, legs crouch/prone blend extension */

    /* --- Anim tree pointer (i386 offset 0x4c4) --- */
    XAnimTree *animTree;                           /* i386 +0x4c4, engine-owned runtime animation tree */
    int32_t dobjSavedModel;                        /* i386 +0x4c8, BG_UpdatePlayerDObj param_3[0x132] */
    uint8_t dobjVersion;                           /* i386 +0x4cc, BG_UpdatePlayerDObj byte at param_3 + 0x133 */
    char padding4cd[3];                             /* i386 +0x4cd..+0x4cf, record-stride tail padding. */
} clientInfo_t;

/* ---------------------------------------------------------------------------
 * Item structure (gitem_t / item_t).
 * Field order and offsets are proved by the original item table and its
 * consumers.
 * In the original Linux i386 module, sizeof(gitem_t) is
 * 0x30 bytes: seven 4-byte pointer fields plus five int32 fields.
 * This is private module data, not network or disk serialization; typed source
 * indexing must use native sizeof(gitem_t). The i386 decompiler expressions
 * such as `bg_itemlist + index * 0x30` are the 32-bit instance of that C layout.
 * --------------------------------------------------------------------------- */

/* Item type enum */
typedef enum {
    IT_BAD = 0,
    IT_WEAPON = 1,
    IT_AMMO = 2,
    IT_HEALTH = 3
} itemType_t;

struct gitem_s {
    const char *classname;                         /* +0x000 */
    const char *pickupSound;                       /* +0x004 */
    const char *worldModel;                        /* +0x008 */
    const char *iconModel;                         /* +0x00c */
    const char *hudIcon;                           /* +0x010, weapon/item HUD icon path */
    const char *ammoIcon;                          /* +0x014, weapon/item ammo icon path */
    const char *pickupName;                        /* +0x018 */
    int32_t quantity;                              /* +0x01c */
    itemType_t type;                               /* +0x020 */
    int32_t weapon;                                /* +0x024 */
    int32_t ammoIndex;                             /* +0x028 */
    int32_t clipIndex;                             /* +0x02c */
};                                                 /* i386 size checked below */

/* Item spawn flags. Entity/server-state bits use the shared FL_*, EF_*, and
 * SVF_* domains declared above rather than item-specific aliases. */
#define ITEM_SPAWNFLAG_NO_DROP_TO_FLOOR 0x00000001u
#define ITEM_SPAWNFLAG_WEAPON_RESPAWN   0x00000008u

typedef struct DObjModel_s {
    XModel *model;
    const char *tagName;       /* NULL for base model; attach tag for submodels. */
    int16_t negativeModelIndex;
    int16_t reserved_00a;      /* +0x00a, stack-carried ABI halfword; engine traces show stock leaves it unstable. */
    int32_t ignoreCollision;   /* From entity attachIgnoreCollision bitset. */
} DObjModel;

typedef struct DObjAnimMat_s {
    float quat[4];
    float trans[4];
} DObjAnimMat;

typedef struct vehicle_path_node_s {
    uint16_t targetname;                 /* +0x00 */
    uint16_t target;                     /* +0x02 */
    int16_t scriptObjectId;              /* +0x04 */
    uint16_t padding06;                  /* +0x06..+0x07, aligns useNodeAngles. */
    qboolean useNodeAngles;              /* +0x08, info_vehicle_node_rotate flag; binary stores 0/1 and consumers only test nonzero. */
    float speed;                         /* +0x0c */
    float lookAhead;                     /* +0x10 */
    vec3_t origin;                     /* +0x14 */
    vec3_t direction;                  /* +0x20 */
    vec3_t angles;                     /* +0x2c */
    float segmentLength;                 /* +0x38 */
    int16_t nextNodeIndex;               /* +0x3c */
    int16_t previousNodeIndex;           /* +0x3e */
} vehicle_path_node_t;

typedef struct vehicle_path_position_s {
    int16_t nodeIndex;                   /* +0x00 */
    int16_t reachedEnd;                  /* +0x02 */
    float fraction;                      /* +0x04 */
    float speed;                         /* +0x08 */
    float lookAhead;                     /* +0x0c */
    float curveFraction;                 /* +0x10 */
    vec3_t origin;                     /* +0x14 */
    vec3_t currentAngles;              /* +0x20 */
    vec3_t lookAheadOrigin;            /* +0x2c */
    vehicle_path_node_t targetNode;      /* +0x38 */
    vehicle_path_node_t cachedNode;      /* +0x78 */
} vehicle_path_position_t;

/* Stock VEH_Backup copies this exact 0xb8-byte lane from vehicle_state_t+0xb8,
 * and the collision rollback path keeps a second copy at +0x170. Individual
 * physics consumers prove every member through +0xb7. */
typedef struct vehicle_physics_state_s {
    vec3_t origin;                    /* +0x00 */
    vec3_t previousOrigin;            /* +0x0c */
    vec3_t viewClampTargetAngles;      /* +0x18 */
    vec3_t previousAngles;             /* +0x24 */
    vec3_t velocity;                   /* +0x30 */
    vec3_t angularVelocity;            /* +0x3c */
    vec3_t acceleration;               /* +0x48 */
    float steerAngle;                  /* +0x54 */
    vec3_t angularAcceleration;        /* +0x58 */
    vec3_t externalVelocity;           /* +0x64 */
    float wheelVerticalVelocity[6];    /* +0x70 */
    float wheelGroundZ[6];             /* +0x88 */
    float wheelMaterial[6];            /* +0xa0 */
} vehicle_physics_state_t;

struct vehicle_state_s {
    /* Remaining gap ranges were checked in UO-GAME-TASK-0345 against
     * vehicle.c offset helpers and left only where no maintained access exists. */
    vehicle_path_position_t pathPosition;/* +0x000, vehicle path-position cursor */
    vec3_t origin;                  /* +0x0b8 */
    vec3_t previousOrigin;          /* +0x0c4, initialized from entity origin */
    vec3_t viewClampTargetAngles;    /* +0x0d0, vehicle angles copied into pmove clamp target */
    vec3_t previousAngles;          /* +0x0dc, initialized from entity angles */
    vec3_t velocity;                /* +0x0e8 */
    vec3_t angularVelocity;         /* +0x0f4 */
    vec3_t acceleration;            /* +0x100 */
    float steerAngle;                  /* +0x10c, 4-wheel steering overlay */
    vec3_t angularAcceleration;      /* +0x110, includes roll/steer velocity overlays */
    vec3_t externalVelocity;         /* +0x11c, includes roll-angle steering overlays */
    float wheelVerticalVelocity[6];     /* +0x128, cleared by suspension solve */
    float wheelGroundZ[6];              /* +0x140, wheel trace/support height */
    float wheelMaterial[6];             /* +0x158, decoded surface material id / ground flags */
    vehicle_physics_state_t previousPhysicsState; /* +0x170, copy of +0x0b8..+0x16f */
    int32_t entityNum;                 /* +0x228, owning vehicle entity number */
    int16_t typeIndex;                /* +0x22c */
    char padding22e[2];               /* +0x22e..+0x22f, aligns slotIndex. */
    int32_t slotIndex;                 /* +0x230, script vehicle slot; VEH_UpdateClient reads the full word */
    int32_t hintStringIndex;           /* +0x234, G_GetHintStringIndex output */
    int16_t pathNodeIndex;             /* +0x238, initialized to -1 */
    char padding23a[2];               /* +0x23a..+0x23b, aligns waitNodeSpeedThreshold. */
    float waitNodeSpeedThreshold;       /* +0x23c, wait-node speed threshold */
    int32_t primaryFireTime;             /* +0x240, dword countdown copied from weaponInfo->fireTime */
    int32_t altFireTime;                 /* +0x244, dword countdown copied from weaponInfo->fireTime */
    int32_t primaryFlashSelector;        /* +0x248, primary turret muzzle flash selector */
    float turretYaw;                    /* +0x24c, also primary turret activity state */
    float turretRoll;                   /* +0x250, also tank/compass active flag */
    int32_t gunnerTurretState;          /* +0x254 */
    int32_t gunnerFireTime;              /* +0x258, dword countdown copied from weaponInfo->fireTime */
    float altHeat;                      /* +0x25c */
    float gunnerHeat;                   /* +0x260 */
    int32_t altOverheating;             /* +0x264 */
    int32_t gunnerOverheating;          /* +0x268 */
    float viewState[7];                /* +0x26c */
    int32_t gunnerEntityNum;           /* +0x288, initialized to ENTITYNUM_NONE */
    float motionControl[6];            /* +0x28c */
    float localForwardAccel;           /* +0x2a4 */
    float localVerticalAccel;          /* +0x2a8 */
    float throttleScalePrevious;       /* +0x2ac */
    float throttleScale;               /* +0x2b0 */
    float brakeScale;                  /* +0x2b4 */
    float scriptedMaxSpeed;            /* +0x2b8 */
    float scriptedAcceleration;        /* +0x2bc */
    int32_t suspensionEnabled;          /* +0x2c0 */
    int32_t soundBlendEntityNums[4];    /* +0x2c4 */
    float idleSoundBlendRepeatDelay;    /* +0x2d4, G_SetSoundBlend repeat delay payload */
    float runSoundBlendRepeatDelay;     /* +0x2d8, G_SetSoundBlend repeat delay payload */
    int32_t altWeaponFireSound;         /* +0x2dc, zero-extended sustained-fire sound alias word */
    int32_t altWeaponStopSound;         /* +0x2e0, zero-extended sustained-fire stop sound alias word */
    int32_t altWeaponSoundTime;         /* +0x2e4 */
    int32_t gunnerWeaponFireSound;      /* +0x2e8, zero-extended sustained-fire sound alias word */
    int32_t gunnerWeaponStopSound;      /* +0x2ec, zero-extended sustained-fire stop sound alias word */
    int32_t gunnerWeaponSoundTime;      /* +0x2f0 */
    int32_t driverTagIndex;             /* +0x2f4 */
    int32_t detachTagIndex;             /* +0x2f8 */
    int32_t popoutTagIndex;             /* +0x2fc */
    int32_t bodyTagIndex;               /* +0x300 */
    int32_t primaryBaseTagIndex;        /* +0x304 */
    int32_t primaryTurretTagIndex;      /* +0x308 */
    int32_t primaryAltTurretTagIndex;   /* +0x30c */
    int32_t gunnerTagIndex;             /* +0x310 */
    int32_t gunnerTurretTagIndex;       /* +0x314 */
    int32_t secondaryBaseTagIndex;      /* +0x318 */
    int32_t chasecamTagIndex;           /* +0x31c */
    int32_t aimDownBarrelTagIndex;      /* +0x320 */
    int32_t primaryFlashTagIndices[4];  /* +0x324 */
    int32_t altFireTagIndices[4];       /* +0x334 */
    int32_t secondaryFlashTagIndices[4];/* +0x344 */
    int32_t wheelTagIndices[6];         /* +0x354 */
    int32_t passengerTagIndices[4];     /* +0x36c, tag_passenger..tag_passenger4 */
    int32_t primaryAimSightTraceResult; /* +0x37c, trap_SightTrace result scratch for VEH_UpdateAim turret_on_vistarget path */
    int32_t animLeftSource;             /* +0x380 */
    int32_t animRightSource;            /* +0x384 */
    int32_t animLeftTime;               /* +0x388 */
    int32_t animRightTime;              /* +0x38c */
    int32_t scriptedDriverEndTime;      /* +0x390 */
    int32_t animLeftTarget;             /* +0x394 */
    int32_t animRightTarget;            /* +0x398 */
    int32_t passengerEntityNums[7];     /* +0x39c, initialized to ENTITYNUM_NONE */
    float collisionSweepFraction;       /* +0x3b8, cached collision sweep fraction */
    int32_t scriptedInputEndTime;       /* +0x3bc */
    int32_t lastInputTime;              /* +0x3c0 */
    float wheelBaseLength;              /* +0x3c4 */
    int32_t collisionNotifyTime;        /* +0x3c8 */
    int32_t collisionSoundTime;         /* +0x3cc */
    int32_t cachedCollisionEntityNum;   /* +0x3d0, cached collision trace entity */
    float cachedCollisionDistance;      /* +0x3d4, cached collision trace distance */
    int32_t lastStableTime;             /* +0x3d8 */
    int32_t lastSolidTime;              /* +0x3dc */
    vec3_t collisionNormal;           /* +0x3e0 */
};

struct vehicleInfo_s {
    char name[0x040];                  /* +0x000, compared by vehicle info lookup */
    int16_t type;                     /* +0x040, VEH_ParseSpecificField writes vehicle type */
    char padding042[2];               /* +0x042..+0x043, aligns steerWheels. */
    int32_t steerWheels;              /* +0x044, vehicle key "steerWheels" */
    int32_t textureScroll;            /* +0x048, vehicle key "texureScroll" */
    int32_t primaryDualFlash;          /* +0x04c, vehicle key "quadBarrel" */
    int32_t bulletDamageEnabled;       /* +0x050 */
    int32_t grenadeDamageEnabled;      /* +0x054 */
    int32_t explosiveDamageEnabled;    /* +0x058 */
    int32_t gunnerSeatEnabled;         /* +0x05c */
    int32_t extraPassengerCount;       /* +0x060 */
    float textureScrollScale;          /* +0x064, vehicle key "texureScrollScale" */
    float maxSpeed;                    /* +0x068, physics speed cap */
    float acceleration;                /* +0x06c, local acceleration clamp */
    float steeringLimit;               /* +0x070, angular clamp */
    float steeringRate;                /* +0x074, angular acceleration clamp */
    float forwardInputScale;           /* +0x078, vehicle input acceleration scale */
    float verticalInputScale;          /* +0x07c, vehicle input acceleration scale */
    float collisionDamageScale;         /* +0x080 */
    float pathSpeed;                    /* +0x084, scaled by vehicle loader */
    float suspensionTravel;             /* +0x088, vehicle key "suspensionTravel"; ground probe depth */
    char turretWeapon[0x040];          /* +0x08c, vehicle spawn primary weapon */
    char turretAltWeapon[0x040];       /* +0x0cc, vehicle spawn alt-turret weapon */
    float primaryYawLimitPos;           /* +0x10c */
    float primaryYawLimitNeg;           /* +0x110 */
    float primaryPitchLimitNeg;         /* +0x114 */
    float primaryPitchLimitPos;         /* +0x118 */
    float primaryTurnRate;              /* +0x11c */
    char turretGunnerWeapon[0x040];    /* +0x120, vehicle spawn gunner weapon */
    float gunnerYawLimitPos;            /* +0x160 */
    float gunnerYawLimitNeg;            /* +0x164 */
    float gunnerPitchLimitNeg;          /* +0x168 */
    float gunnerPitchLimitPos;          /* +0x16c */
    float gunnerTurnRate;               /* +0x170 */
    char soundNames[7][0x040];          /* +0x174, parsed sound alias names */
    uint8_t idleBlendSound0;            /* +0x334 */
    uint8_t idleBlendSound1;            /* +0x335 */
    uint8_t runBlendSound0;             /* +0x336 */
    uint8_t runBlendSound1;             /* +0x337 */
    uint8_t primaryActiveSound;         /* +0x338 */
    uint8_t primaryStopSound;           /* +0x339 */
    uint8_t collisionSound;             /* +0x33a */
    uint8_t hitPersonSound;             /* +0x33b */
    float pathSpeedDenom;               /* +0x33c */
    float damageScaleFront;             /* +0x340 */
    float damageScaleSide;              /* +0x344 */
    float damageScaleRear;              /* +0x348 */
    float damageScaleTop;               /* +0x34c */
    float damageScaleBullet;            /* +0x350 */
    vec3_t collisionMins;             /* +0x354, movement trace bounds */
    vec3_t collisionMaxs;             /* +0x360, movement trace bounds */
    float collisionBoundsSource[6];      /* +0x36c, parser bounds before half-scale */
    float rollInputScale;               /* +0x384 */
    float steeringRollScale;            /* +0x388 */
    float rollLimit;                    /* +0x38c */
    float stepSize;                      /* +0x390, vehicle key "stepsize"; step trace depth */
    float dismountForwardOffset;         /* +0x394 */
    float dismountBackOffset;            /* +0x398 */
    char hintString[0x040];             /* +0x39c */
};

typedef struct entityLinkInfo_s {
    gentity_t *parent;                  /* +0x000 */
    gentity_t *nextChild;               /* +0x004 */
    uint16_t tagStringId;
    uint16_t padding0a;               /* +0x00a..+0x00b, aligns parentTagIndex. */
    int32_t parentTagIndex;
    float relAxis[12];
    float parentRelAxis[3][4];
    /* RECOVERED(UO-GAME-UNK-0002): record size is 0x70; link helper fields are now modeled. */
} entityLinkInfo_t;

typedef union gclient_predictable_event_parms_u {
    int32_t ring[4];                      /* +0x09c, slots at +0x9c/+0xa0/+0xa4/+0xa8 */
    struct {
        int32_t eventParm0;               /* +0x09c */
        int32_t eventParm1;               /* +0x0a0 */
        int32_t eventParm2;               /* +0x0a4 */
        int32_t eventParm3;               /* +0x0a8 */
    } eventParms;
} gclient_predictable_event_parms_t;

typedef union gentity_state_angles2_u {
    float raw[3];                           /* +0x068 */
    struct {
        float x;                            /* +0x068 */
        float y;                            /* +0x06c */
        float z;                            /* +0x070 */
    } vector;
    struct {
        float scale;                        /* +0x068 */
        float radius;                       /* +0x06c */
        float durationMs;                   /* +0x070 */
    } earthquake;
    struct {
        float primaryPitch;                 /* +0x068 */
        float primaryYaw;                   /* +0x06c */
        float gunnerPitch;                  /* +0x070 */
    } vehicleTurret;
    struct {
        float pitch;                        /* +0x068 */
        float yaw;                          /* +0x06c */
        float pitchCarry;                   /* +0x070 */
    } turret;
    struct {
        float cullDistance;                 /* +0x068 */
        float repeatDelayMs;                /* +0x06c */
        float unused70;                     /* +0x070 */
    } loopedFx;
    struct {
        float unused68;                     /* +0x068 */
        float leanAmount;                   /* +0x06c */
        float unused70;                     /* +0x070 */
    } clientInfo;
} gentity_state_angles2_t;

typedef union gentity_anim_payload_u {
    struct {
        int32_t legsAnim;                  /* +0x0d0 */
        int32_t torsoAnim;                 /* +0x0d4 */
    } playerAnim;
    struct {
        int32_t weaponAnim;                /* +0x0d0 */
        int32_t followClient;              /* +0x0d4 */
    } surfaceImpact;
} gentity_anim_payload_t;

#define MAX_TURRETS 32
struct turret_state_s {
    int32_t inUse;                       /* +0x000, fixed turret-state pool slot flag */
    uint32_t flags;                      /* +0x004, client-state refresh flags */
    int32_t fireTimeRemaining;           /* +0x008, client turret shot countdown */
    float topArc;                       /* +0x00c, RECOVERED(UO-GAME-UNK-0101):
                                            script settoparc writes negative clamp */
    float rightArc;                     /* +0x010, RECOVERED(UO-GAME-UNK-0101):
                                            script setrightarc writes negative clamp */
    float bottomArc;                    /* +0x014, RECOVERED(UO-GAME-UNK-0101):
                                            script setbottomarc writes positive clamp */
    float leftArc;                      /* +0x018, RECOVERED(UO-GAME-UNK-0101):
                                            script setleftarc writes positive clamp */
    float restPitch;                    /* +0x01c, turret return-to-rest pitch */
    int32_t useMode;                     /* +0x020, copied weapon-info stance/use pose */
    int32_t stopUseEventType;             /* +0x024, stop-use player event selector */
    int32_t fireSoundTime;               /* +0x028, sustained firing sound countdown */
    vec3_t stopUseOrigin;              /* +0x02c, player return origin on turret exit */
    float restPitchClamp;                /* +0x038, return-to-rest pitch clamp */
    uint8_t sustainedFireLoopSound;       /* +0x03c, clientSound while fireSoundTime runs */
    uint8_t sustainedFireStopSound;       /* +0x03d, one-shot sound when sustained fire ends */
    char padding3e[2];                    /* +0x03e..+0x03f, aligns heat. */
    float heat;                         /* +0x040, RECOVERED(UO-GAME-UNK-0101):
                                            script getturretheat source */
    int32_t overheating;                /* +0x044, RECOVERED(UO-GAME-UNK-0101):
                                            script getturretoverheating source */
};

/*
 * Player-state prefix.
 *
 * The original source shape is preserved: gclient_t starts with playerState_t
 * ps at offset zero, followed by client-session fields.
 */
struct playerState_s {
    int32_t commandTime;                     /* +0x000, original netfield name */
    pmType_t pmType;                         /* +0x004 */
    int32_t bobCycle;                        /* +0x008 */
    uint32_t playerStateFlags;               /* +0x00c */
    int32_t pmTime;                          /* +0x010 */
    vec3_t psOrigin;                       /* +0x014 */
    vec3_t velocity;                       /* +0x020 */
    int32_t weaponTime;                      /* +0x02c */
    int32_t weaponDelay;                     /* +0x030 */
    int32_t grenadeTimeLeft;                 /* +0x034, original netfield name */
    int32_t foliageSoundTime;                /* +0x038, PM_FoliageSounds cooldown timestamp */
    int32_t fatigueSoundTime;                /* +0x03c */
    int32_t gravity;                         /* +0x040 */
    float leanFraction;                      /* +0x044 */
    int32_t speed;                           /* +0x048 */
    int32_t deltaAngles[3];                  /* +0x04c */
    int32_t groundEntityNum;                 /* +0x058 */
    vec3_t ladderNormal;                   /* +0x05c */
    int32_t lastJumpCommandTime;             /* +0x068 */
    float jumpOriginZ;                       /* +0x06c, original netfield fJumpOriginZ */
    int32_t legsTimer;                       /* +0x070 */
    int32_t legsAnim;                        /* +0x074 */
    int32_t torsoTimer;                      /* +0x078 */
    int32_t torsoAnim;                       /* +0x07c */
    int32_t movementDir;                     /* +0x080, original netfield name */
    uint32_t entityStateFlags;               /* +0x084, copied to gentity_t::s_flags */
    int32_t eventIndex;                      /* +0x088 */
    int32_t events[4];                       /* +0x08c */
    gclient_predictable_event_parms_t eventParms; /* +0x09c */
    int32_t lastEventIndex;                  /* +0x0ac */
    uint8_t unused0B0[0x024];                 /* +0x0b0..+0x0d3; copied with the complete state but otherwise unused by game.mp.uo.i386.so, coduo_lnxded, CoDUOMP.exe, and uo_cgame_mp_x86.dll. */
    int32_t psClientNum;                     /* +0x0d4 */
    int32_t currentWeapon;                   /* +0x0d8 */
    weaponState_t weaponState;               /* +0x0dc */
    float adsFraction;                       /* +0x0e0 */
    int32_t viewModelIndex;                  /* +0x0e4, original netfield `viewmodelIndex` */
    vec3_t viewAngles;                     /* +0x0e8 */
    int32_t viewHeightTarget;                /* +0x0f4 */
    float viewHeightCurrent;                 /* +0x0f8 */
    int32_t viewHeightLerpTime;               /* +0x0fc */
    int32_t viewHeightLerpTarget;             /* +0x100 */
    int32_t viewHeightLerpDown;               /* +0x104 */
    float viewHeightLerpPosAdj;               /* +0x108 */
    int32_t damageEvent;                     /* +0x10c */
    int32_t damageYaw;                       /* +0x110 */
    int32_t damagePitch;                     /* +0x114 */
    int32_t damageCount;                     /* +0x118 */
    int32_t health;                          /* +0x11c, live player health */
    int32_t deathYaw;                        /* +0x120 */
    int32_t maxHealth;                       /* +0x124 */
    int32_t identClientNum;                  /* +0x128, crosshair/team-status target */
    int32_t identClientHealth;               /* +0x12c, target health percentage */
    int32_t spawnCount;                      /* +0x130, incremented by ClientSpawn */
    int32_t ammo[128];                       /* +0x134 */
    int32_t clips[128];                      /* +0x334 */
    uint32_t weaponBits[4];                  /* +0x534 */
    uint8_t weaponSlots[8];                  /* +0x544; raw byte slots, weapon-index
                                                consumers use signed byte loads */
    uint32_t weaponRechamberBits[4];         /* +0x54c */
    vec3_t playerMins;                     /* +0x55c */
    vec3_t playerMaxs;                     /* +0x568 */
    int32_t proneViewHeight;                 /* +0x574 */
    int32_t crouchViewHeight;                /* +0x578 */
    int32_t standViewHeight;                 /* +0x57c */
    int32_t deadViewHeight;                  /* +0x580 */
    float walkSpeedScale;                    /* +0x584 */
    float runSpeedScale;                     /* +0x588 */
    float sprintSpeedScale;                  /* +0x58c */
    float proneSpeedScale;                   /* +0x590 */
    float crouchSpeedScale;                  /* +0x594 */
    float strafeSpeedScale;                  /* +0x598 */
    float backSpeedScale;                    /* +0x59c */
    float leanSpeedScale;                    /* +0x5a0 */
    float proneDirection;                    /* +0x5a4 */
    float proneDirectionPitch;               /* +0x5a8 */
    float proneTorsoPitch;                   /* +0x5ac */
    float fatigueScale;                      /* +0x5b0 */
    int32_t lastSprintTime;                  /* +0x5b4 */
    int32_t viewLocked;                      /* +0x5b8, netfield `viewlocked` */
    int32_t viewLockedEntityNum;             /* +0x5bc, netfield `viewlocked_entNum` */
    float friction;                          /* +0x5c0 */
    int32_t serverCursorHint;                /* +0x5c4 */
    int32_t serverCursorHintVal;             /* +0x5c8 */
    int32_t serverCursorHintString;          /* +0x5cc */
    uint8_t unused5D0[0x01c];                 /* +0x5d0..+0x5eb; copied with the complete state but otherwise unused by game.mp.uo.i386.so, coduo_lnxded, CoDUOMP.exe, and uo_cgame_mp_x86.dll. */
    uint32_t cursorHintFlags;                /* +0x5ec */
    uint8_t unused5F0[0x008];                 /* +0x5f0..+0x5f7; copied with the complete state but otherwise unused by all four maintained original binaries. */
    uint16_t cursorHintEntNum;               /* +0x5f8 */
    uint8_t unused5FA[0x006];                 /* +0x5fa..+0x5ff; copied with the complete state but otherwise unused by all four maintained original binaries. */
    int32_t compassFriendInfo;               /* +0x600, netfield `iCompassFriendInfo` */
    int32_t compassTankInfo;                 /* +0x604, netfield `iCompassTankInfo` */
    float torsoHeight;                       /* +0x608, netfield `fTorsoHeight` */
    float torsoPitch;                        /* +0x60c, netfield `fTorsoPitch` */
    float waistPitch;                        /* +0x610, netfield `fWaistPitch` */
    int32_t vehiclePosition;                 /* +0x614 */
    int32_t vehicleType;                     /* +0x618 */
    int32_t vehicleMotion;                   /* +0x61c, two-bit netfield `vehMotion` */
    int32_t oldEventIndex;                   /* +0x620 */
    uint32_t weaponAnim;                     /* +0x624 */
    float aimSpreadScale;                    /* +0x628 */
    union {
        vec3_t externalVelocity;              /* +0x62c */
        struct {
            int32_t index;                   /* +0x62c */
            int32_t time;                    /* +0x630 */
            int32_t duration;                /* +0x634 */
        } shellshock;
    } motionState;                           /* +0x62c */
    objective_t objectives[PLAYERSTATE_OBJECTIVE_COUNT]; /* +0x638 */
    uint8_t hudCurrent[0x1e84];              /* +0x7f8 */
    uint8_t hudArchival[0x1e84];             /* +0x267c */
    int32_t deltaTime;                       /* +0x4500, archived-state time rebase */
};


/*
 * Client structure (gclient_t).
 * Fields are ordered by original binary offset and proved across
 * client_lifecycle.c, script_player.c, items.c, client_frame.c, animation.c,
 * and pmove.c.
 *
 * The original i386 binary stride per client is 0x4734 bytes.
 * Runtime access uses these typed fields; explicit byte access is retained
 * only where the original ABI genuinely exposes a packed or untyped record.
 *
 * The original source shape is preserved here: playerState_t ps is the
 * first member, and client-session fields follow it.
 * UO-GAME-TASK-0345 checked remaining pad ranges against maintained client and
 * vehicle accessors; newly observed vehicle overlays are named below.
 */
struct gclient_s {
    playerState_t ps;                       /* +0x000..+0x4503, original playerState_t ps prefix */

    /* === Session / scoring / configstring (offset range 0x4504-0x455f) === */
    int32_t sessionState;                    /* +0x4504, script-facing sessionstate field */
    int32_t followClient;                    /* +0x4508, RECOVERED(UO-GAME-UNK-0018):
                                                also spawnCount (UO-GAME-UNK-0187) */
    int32_t statusIcon;                      /* +0x450c */
    int32_t archiveTime;                     /* +0x4510, RECOVERED(UO-GAME-UNK-0018) */
    int32_t score;                           /* +0x4514 */
    int32_t deaths;                          /* +0x4518 */
    uint16_t pers;                           /* +0x451c */
    char padding451e[2];                     /* +0x451e..+0x451f, aligns connectedState. */
    int32_t connectedState;                  /* +0x4520 */
    usercmd_t command;                       /* +0x4524..+0x453b, current engine-supplied user command */
    usercmd_t oldPmoveCommand;               /* +0x453c..+0x4550, previous pmove command */
    int32_t complaintDisabled;               /* +0x4554, inactivity exemption;
                                                RECOVERED(UO-GAME-UNK-0024) */
    int32_t predictItems;                    /* +0x4558 */
    int32_t pmoveFixed;                      /* +0x455c, per-client pmove_fixed override used by ClientThink_real */

    /* === Name / handicap / speed (offset range 0x4560-0x459f) === */
    char cleanName[0x20];                    /* +0x4560 */
    int32_t handicap;                        /* +0x4580 */
    int32_t normalMaxHealth;                 /* +0x4584 */
    int32_t maxSpeed;                        /* +0x4588 */
    int32_t enterTime;                       /* +0x458c */
    char abiGap_4590[0x004];                 /* +0x4590, size 0x004; client scoring audit found no maintained access before calledVotes; retained for ABI. */
    int32_t calledVotes;                     /* +0x4594, Cmd_CallVote_f max-called gate */
    char abiGap_4598[0x004];                 /* +0x4598, size 0x004; client complaint audit found no maintained access before complaintCount; retained for ABI. */
    int32_t complaintCount;                  /* +0x459c, RECOVERED(UO-GAME-UNK-0024) */

    /* === Complaint / viewmodel / team (offset range 0x45a0-0x4617) === */
    int32_t pendingComplaintClient;          /* +0x45a0 */
    int32_t pendingComplaintTime;            /* +0x45a4 */
    int32_t viewModelIndex;                  /* +0x45a8, full-width script model index copied
                                                to playerState_t::viewModelIndex;
                                                RESOLVED(UO-GAME-UNK-0097) */
    uint32_t spectateTeamDenyMask;           /* +0x45ac, deny bits read by G_ClientCanSpectateTeam */
    char abiGap_45b0[0x004];                 /* +0x45b0, size 0x004; client team/model audit found no maintained access before sessionSquad; retained for ABI. */
    int16_t sessionSquad;                    /* +0x45b4 */
    char padding45b6[2];                     /* +0x45b6..+0x45b7, aligns clientNum. */
    int32_t clientNum;                       /* +0x45b8 */
    int32_t sessionTeam;                     /* +0x45bc, RECOVERED(UO-GAME-UNK-0024) */
    int32_t baseModelIndex;                  /* +0x45c0 */
    int32_t attachModelIndices[6];           /* +0x45c4 */
    int32_t attachTagIndices[6];             /* +0x45dc */
    char userInfoName[0x20];                 /* +0x45f4 */

    /* === Spectator / buttons / damage (offset range 0x4614-0x469f) === */
    int32_t spectatorActivityState;          /* +0x4614 */
    int32_t archiveClient;                   /* +0x4618 */
    qboolean noclip;                         /* +0x461c, RECOVERED(UO-GAME-UNK-0017) */
    qboolean ufo;                            /* +0x4620, RECOVERED(UO-GAME-UNK-0017) */
    qboolean controlsFrozen;                 /* +0x4624, RESOLVED(UO-GAME-UNK-0006) */
    int32_t lastUsercmdTime;                 /* +0x4628 */
    uint32_t currentButtons;                 /* +0x462c, spectator buttons;
                                                RECOVERED(UO-GAME-UNK-0094) */
    uint32_t oldButtons;                     /* +0x4630 */
    uint32_t latchedButtons;                 /* +0x4634, ~oldButtons & currentButtons */
    uint32_t spectatorWbuttons;              /* +0x4638, spectator weapon buttons /
                                                flame-active flags overlay */
    uint32_t oldWbuttons;                    /* +0x463c */
    uint32_t latchedWbuttons;                /* +0x4640, ~oldWbuttons & spectatorWbuttons */
    vec3_t spectatorSnapshotOrigin;        /* +0x4644, ClientThink_real pre-pmove origin snapshot */
    float spectatorSnapshotAngle0;           /* +0x4650 */
    float spectatorSnapshotAngle1;           /* +0x4654 */
    int32_t damageTaken;                     /* +0x4658 */
    vec3_t damageFrom;                     /* +0x465c */
    int32_t damageFromWorld;                 /* +0x4668 */
    char abiGap_466c_4677[0x00c];            /* +0x466c..0x4677, size 0x00c; client damage/inactivity audit found no maintained access before inactivity timers; retained for ABI. */
    int32_t inactivityTime;                  /* +0x4678 */
    int32_t spectatorInactivityTime;         /* +0x467c */
    int32_t inactivityWarningSent;           /* +0x4680 */
    int32_t spectatorInactivityWarning;      /* +0x4684 */
    char abiGap_4688[0x004];                 /* +0x4688, size 0x004; client vehicle-control audit found no maintained access before vehicleControlTime; retained for ABI. */
    int32_t vehicleControlTime;              /* +0x468c, vehicle link/use timing gate */
    int32_t vehicleDelayIgnoreTime;          /* +0x4690, vehicle re-entry delay override */
    int32_t driverUnlinkRequested;           /* +0x4694, driver requested vehicle exit */

    /* === Damage feedback floats (offset range 0x4698-0x46d4) === */
    float damageAlphaFraction;               /* +0x4698 */
    char abiGap_469c_46a3[0x008];            /* +0x469c..0x46a3, size 0x008; client damage-feedback audit found no maintained access before endFrameTransient46a4; retained for ABI. */
    int32_t endFrameTransient46a4;    /* +0x46a4 */
    char abiGap_46a8_46b7[0x010];            /* +0x46a8..0x46b7, size 0x010; neither game.mp.uo.i386.so nor uo_game_mp_x86.dll contains a gclient-relative access in this range; both resume at lookAtEntity +0x46b8. Quake III's gclient tail does not align here, so no inherited field names are justified. */
    gentity_t *lookAtEntity;                 /* +0x46b8, RESOLVED(UO-GAME-UNK-0009) */
    int32_t nonpvsFriendlyClient;            /* +0x46bc */
    int32_t pingEndTime;                     /* +0x46c0, RECOVERED(UO-GAME-UNK-0096) */
    int32_t nonpvsTankClient;                /* +0x46c4 */
    int32_t damageTime;                      /* +0x46c8 */
    float damageRoll;                        /* +0x46cc */
    float damagePitch;                       /* +0x46d0 */
    vec3_t weaponPreviousViewAngles;       /* +0x46d4, BG_CalculateWeaponPosition_Sway input */
    vec3_t weaponSwayOffsets;              /* +0x46e0, BG_CalculateWeaponPosition_Sway output */
    vec3_t weaponSwayAngles;               /* +0x46ec, weapon angle base pitch/yaw plus spare */

    /* === Misc late fields (offset range 0x46f8-0x4788) === */
    vec3_t weaponMoveOffset;               /* +0x46f8, BG_CalculateWeaponPosition_BasePosition_angles accumulator */
    float weaponIdleScale;                   /* +0x4704, BG_CalculateWeaponPosition_IdleAngles accumulator */
    vec3_t weaponRecoilAngles;             /* +0x4708, BG_CalculateWeaponPosition_GunRecoil accumulator */
    float fireRecoilVelocity[2];             /* +0x4714, G_PlayerEvent recoil accumulator */
    int32_t weaponRecoilState;               /* +0x471c, ClientThink_real/BG_CalculateWeaponAngles stack context word */
    int32_t flameDamageTime;                 /* +0x4720, RECOVERED(UO-GAME-UNK-0022) */
    int32_t flameDamageInflictor;            /* +0x4724, RECOVERED(UO-GAME-UNK-0022) */
    int32_t lastCollisionDamageTime;         /* +0x4728, vehicle collision damage cooldown */
    int32_t vehicleProneDamageTime;          /* +0x472c, ClientThink_real prone vehicle damage cooldown gate */
    int32_t vehicleExitState;                /* +0x4730, vehicle unlink/exit state */
};

/*
 * Partial gentity view for recovered fields.
 * Offsets are binary offsets, not a complete original source struct.
 * Fields are ordered by original binary offset and proved across entity
 * management, items, missiles, triggers, script methods, and vehicle code.
 * UO-GAME-TASK-0345 checked remaining pad ranges against maintained entity and
 * vehicle accessors; newly observed overlays are named below.
 *
 * Host builds use native pointer widths, so fields after native pointer slots
 * are not a reliable binary-offset view on 64-bit.  Use fixed-offset helpers
 * for byte-exact overlay access that must match the original i386 layout.
 */
struct gentity_s {
    /* === Entity state (offset range 0x000-0x02f) === */
    int32_t s_number;                        /* +0x000, passed to trap_DObjCreate */
    int32_t s_eType;                         /* +0x004 */
    uint32_t s_flags;                        /* +0x008, RECOVERED(UO-GAME-UNK-0021) */
    trajectory_t pos;                        /* +0x00c, position trajectory */
    trajectory_t apos;                       /* +0x030, angular trajectory */

    /* === Client event / move fields (offset range 0x054-0x0db) === */
    int32_t entityStateTime;                 /* +0x054, entity-state time / owner-icon expiry overlay */
    int32_t entityStateTime2;                /* +0x058, entity-state time2 / vehicle ground-depth overlay */
    vec3_t loopedFxForward;                /* +0x05c */
    gentity_state_angles2_t entityStateAngles2; /* +0x068, angles2 / temp-event / turret overlay */
    int32_t vehicleEntityNum;                /* +0x074, temporary-event attacker overlay;
                                                RECOVERED(UO-GAME-UNK-0235) */
    int32_t vehicleSlot;                     /* +0x078, vehicle slot / obituary attacker overlay */
    int32_t groundEntityNum;                 /* +0x07c */
    uint32_t constantLight;                  /* +0x080, packed mover light RGBA */
    int32_t clientSound;                     /* +0x084 */
    int32_t eventParm;                       /* +0x088, temp-event parameter;
                                                BG_PlayerStateToEntityState uses it as vehicle animation state. */
    int32_t itemIndex;                       /* +0x08c */
    int32_t dobjModelIndexCopy;              /* +0x090, ABI_SENSITIVE(UO-GAME-UNK-0002) */
    int32_t clientNum;                       /* +0x094, temporary-event client-number overlay;
                                                RECOVERED(UO-GAME-UNK-0018) */
    int32_t headIcon;                        /* +0x098 */
    int32_t headIconTeam;                    /* +0x09c */
    int32_t abiGap_0a0;                      /* +0x0a0, size 0x004; entity-state audit found no maintained access before tempEffectId; retained for ABI. */
    int32_t tempEffectId;                    /* +0x0a4, temporary-event direction-byte /
                                                effect-id overlay */
    int32_t eventCount;                      /* +0x0a8, RECOVERED(UO-GAME-UNK-0272) */
    int32_t events[4];                       /* +0x0ac, RECOVERED(UO-GAME-UNK-0273) */
    int32_t eventParms[4];                   /* +0x0bc, RECOVERED(UO-GAME-UNK-0274) */
    int32_t entityStateWeapon;               /* +0x0cc, entityState_t::weapon */
    gentity_anim_payload_t entityStateAnim;  /* +0x0d0, player anim / temp-event payload overlay */
    float clientInfoLeanFraction;            /* +0x0d8, player client-info lean fraction;
                                                reused by non-player entity-state contexts */
    int32_t hintStringIndex;                 /* +0x0dc, temporary-event direction-byte overlay;
                                                RECOVERED(UO-GAME-UNK-0100) */

    /* === Hint / cursor / lean (offset range 0x0e0-0x0f7) === */
    int32_t cursorHint;                      /* +0x0e0, RECOVERED(UO-GAME-UNK-0100) */
    int32_t turretOverheatState;             /* +0x0e4, set when turret enters overheating */
    /* Entity angle payload: player lean-angle export, turret saved angles,
     * and vehicle gunner pitch-limit payloads share these three floats. */
    vec3_t entityAngles;                     /* +0x0e8 */
    int32_t linkedState;                     /* +0x0f4 */

    /* === Server flags / linked state (0x0f8-0x107) === */
    uint32_t svFlags;                        /* +0x0f8, server/link flags;
                                                RECOVERED(UO-GAME-UNK-0002) */
    int32_t tempClientNumFc;                 /* +0x0fc */
    int32_t soundTime;                       /* +0x100, RECOVERED(UO-GAME-UNK-0002) */
    int32_t contents;                        /* +0x104, RECOVERED(UO-GAME-UNK-0002) */

    /* === Bounds (offset range 0x108-0x13f) === */
    vec3_t mins;                           /* +0x108 */
    vec3_t maxs;                           /* +0x114 */
    int32_t scriptContents;                  /* +0x120, script-visible contents;
                                                RECOVERED(UO-GAME-UNK-0063) */
    vec3_t absMin;                         /* +0x124 */
    vec3_t absMax;                         /* +0x130, absolute bounds maximum */

    /* === Current origin / angles (offset range 0x13c-0x15f) === */
    vec3_t currentOrigin;                  /* +0x13c, RECOVERED(UO-GAME-UNK-0002) */
    vec3_t currentAngles;                  /* +0x148, RECOVERED(UO-GAME-UNK-0025) */
    int32_t passEntityNum;                   /* +0x154, vehicle-owner overlay */
    int32_t eventTime2;                      /* +0x158, mirrored by G_AddEvent */
    int32_t worldspawnSpawnflagsScratch;     /* +0x15c, SP_worldspawn temporary copy */
    gclient_t *client;                       /* +0x160 */
    vehicle_state_t *vehicle;                /* +0x164, vehicle state owned by script_vehicle entities */
    turret_state_t *turretState;             /* +0x168, RECOVERED(UO-GAME-UNK-0101) */

    /* === Linked / model / flags (0x16c-0x1ab) === */
    uint8_t linked;                          /* +0x16c, linked-state byte;
                                                RECOVERED(UO-GAME-UNK-0016) */
    uint8_t linkedByte16d;                   /* +0x16d */
    uint8_t doorSoundCloseEnd;               /* +0x16e */
    uint8_t doorSoundOpening;                /* +0x16f */
    uint8_t doorSoundClosing;                /* +0x170 */
    uint8_t doorSoundOpenEnd;                /* +0x171 */
    uint8_t doorMovingClientSound;           /* +0x172, copied to clientSound while
                                                binary doors move. */
    uint8_t doorSoundOpenLoop;               /* +0x173 */
    uint8_t doorSoundCloseLoop;              /* +0x174 */
    uint8_t doorSoundLocked;                 /* +0x175 */
    uint8_t doorSoundOpeningQuiet;           /* +0x176 */
    uint8_t doorSoundOpenQuietEnd;           /* +0x177 */
    uint8_t doorSoundClosingQuiet;           /* +0x178 */
    uint8_t doorSoundCloseQuietEnd;          /* +0x179 */
    uint8_t itemSoundAlias;                  /* +0x17a */
    uint8_t clientSpawnStateByte;            /* +0x17b */
    uint8_t clientSpawnResetByte;            /* +0x17c, ClientSpawn clears this byte */
    uint8_t takeDamage;                      /* +0x17d, settakedamage/G_Damage gate;
                                                also reused by movers as an activation flag. */
    uint8_t activeState;                     /* +0x17e, item auto-touch and mover/vehicle active state */
    uint8_t reserved_17f;                    /* +0x17f, size 0x001; gentity state-byte audit found no maintained access between activeState and moverState; retained for ABI. */
    uint8_t moverState;                      /* +0x180 */
    uint8_t modelIndex;                      /* +0x181, G_SetModel / DObj model index */
    uint8_t attachIgnoreCollision;           /* +0x182, AUDITED_DECOMPILER(0x77f6a, 77f6a_script_method_scriptbuiltin_getattachignorecollision.c, VERIFY-DOBJLINK-ATTACHLINK-2026-06-17): attach-ignore collision bitset. */
    uint8_t padding183;                      /* +0x183, aligns scriptClassname. */
    uint16_t scriptClassname;                /* +0x184, script classname string id. */
    char padding186[2];                      /* +0x186..+0x187, aligns spawnflags. */
    int32_t spawnflags;                      /* +0x188, item/spawn entity flags */
    uint32_t flags;                          /* +0x18c, RECOVERED(UO-GAME-UNK-0017) */
    int32_t lastThinkTime;                   /* +0x190, also mirrored by G_AddEvent */
    int32_t skipTypeDispatch;                /* +0x194, timeout frees without type dispatch */
    int32_t unlinkOnTimeout;                 /* +0x198, no-respawn item pickup unlink flag */
    float bounceFactor;                      /* +0x19c, G_BounceItem velocity scale */
    int32_t clipmask;                        /* +0x1a0 */
    int32_t lastFrameNum;                    /* +0x1a4, RECOVERED(UO-GAME-UNK-0148) */
    gentity_t *entityRef;                    /* +0x1a8, RECOVERED(UO-GAME-UNK-0002) */
    gentity_t *targetLocationNext;           /* +0x1ac, target_location link list;
                                                also binary-mover linked trigger sentinel */
    char abiGap_1b0[0x004];                  /* +0x1b0, size 0x004; gentity target-location/mover audit found no maintained access before moverPos1; retained for ABI. */
    vec3_t moverPos1;                      /* +0x1b4, binary mover position 1 /
                                                script mover position linear start */
    vec3_t moverPos2;                      /* +0x1c0, binary mover position 2 /
                                                script mover position decel start */

    /* === Damage point / speed (offset range 0x1cc-0x1ff) === */
    vec3_t damagePoint;                    /* +0x1cc, RECOVERED(UO-GAME-UNK-0179);
                                                also script mover position target. */
    uint16_t targetLocationMessage;          /* +0x1d8, target_location message string id */
    uint16_t padding1da;                     /* +0x1da..+0x1db, aligns dynaSinkEndTime. */
    int32_t dynaSinkEndTime;                 /* +0x1dc, DynaSink free deadline */
    float doorYawOffset;                     /* +0x1e0, func_door_rotating yaw /
                                                script mover angular linear time */
    uint16_t target;                         /* +0x1e4, script target string id */
    uint16_t targetname;                     /* +0x1e6, script_vehicle_node lookup name */
    uint16_t teamName;                       /* +0x1e8, script "team" string */
    char padding1ea[2];                      /* +0x1ea..+0x1eb, aligns the following dword lane. */
    char abiGap_1ec[4];                      /* +0x1ec..+0x1ef; no original game-module access found. */
    float maxSpeed;                          /* +0x1f0, vehicle maximum speed;
                                                also binary/script mover speed float. */
    float doorAltSpeed;                      /* +0x1f4, script mover angular speed */
    vec3_t moverDir;                       /* +0x1f8, script mover angular linear start */
    int32_t moverDuration;                   /* +0x204 */
    int32_t moverAltDuration;                /* +0x208 */

    /* === Think / callbacks (offset range 0x20c-0x22f) === */
    int32_t nextthink;                       /* +0x20c */
    void (*think)(gentity_t *ent);           /* +0x210 */
    gentity_mover_reached_t moverReached;    /* +0x214, script mover reached callback */
    gentity_mover_blocked_t moverBlocked;    /* +0x218, mover blocked callback */
    gentity_touch_t touch;                   /* +0x21c, including item touch callbacks */
    gentity_use_t use;                       /* +0x220, including item use callbacks */
    void (*pain)(gentity_t *ent, gentity_t *attacker, int damage,
                 const float *point, int mod, const float *dir, int hitLocation);
                                             /* +0x224 */
    void (*die)(gentity_t *ent, gentity_t *inflictor, gentity_t *attacker,
                int damage, int mod, int weapon, const float *dir, int hitLocation);
                                             /* +0x228 */
    char abiGap_22c[0x004];                  /* +0x22c, size 0x004; callback audit found no maintained access between die callback and controller; retained for ABI. */
    gentity_controller_t controller;         /* +0x230, DObj controller callback */
    int32_t painEventTime;                   /* +0x234 */
    char abiGap_238_23f[0x008];              /* +0x238..0x23f, size 0x008; pain/health audit found no maintained access before health; retained for ABI. */
    int32_t health;                          /* +0x240, RECOVERED(UO-GAME-UNK-0013) */
    int32_t maxHealth;                       /* +0x244, RECOVERED(UO-GAME-UNK-0002) */
    int32_t damage;                          /* +0x248, missile direct damage */
    int32_t splashDamage;                    /* +0x24c, missile radius max damage */
    int32_t splashMinDamage;                 /* +0x250, missile radius min damage */
    int32_t splashRadius;                    /* +0x254, missile radius */
    int32_t methodOfDeath;                   /* +0x258, missile direct MOD */
    int32_t splashMethodOfDeath;             /* +0x25c, missile radius MOD */

    /* === Health / item data (offset range 0x260-0x29f) === */
    int32_t itemCount;                       /* +0x260 */
    char abiGap_264[0x004];                  /* +0x264, size 0x004; item/death audit found no maintained access before attacker; retained for ABI. */
    gentity_t *attacker;                     /* +0x268, death attacker;
                                                RECOVERED(UO-GAME-UNK-0179) */
    gentity_t *triggerActivator;             /* +0x26c, trigger_multiple activator overlay */
    gentity_t *teamChain;                    /* +0x270 */
    gentity_t *teamMaster;                   /* +0x274 */
    float itemWait;                          /* +0x278, item wait time /
                                                script mover position linear time */
    float itemRandom;                        /* +0x27c, item random time /
                                                script mover angular decel time */
    int32_t enemyScanRadius;                 /* +0x280, miscGunnerEnemyScan radius */
    float concussiveFxEndTime;               /* +0x284, Concussive_fx lifetime deadline;
                                                also trigger_use/static pain delay and
                                                script mover position decel time. */
    char abiGap_288[0x004];                  /* +0x288, size 0x004; item/trigger/mover audit found no maintained access before ownerIconDelaySeconds; retained for ABI. */
    float ownerIconDelaySeconds;             /* +0x28c, script_vehicle_owner_icon delay */
    vec3_t damageDir;                      /* +0x290, RECOVERED(UO-GAME-UNK-0179);
                                                also script mover angular decel start. */
    vec3_t scriptMoverAngleTarget;         /* +0x29c, script mover angular target */
    gitem_t *itemInfo;                       /* +0x2a8, item definition for item entities */
    char abiGap_2ac_2b7[0x00c];              /* +0x2ac..0x2b7, size 0x00c; item/door audit found no maintained access between itemInfo and doorLocked; retained for ABI. */
    int32_t doorLocked;                      /* +0x2b8, RECOVERED(UO-GAME-UNK-0002) */
    float vehiclePrimaryYawClamp;            /* +0x2bc, script vehicle primary yaw clamp */
    float scriptVehiclePrimaryPitchClamp;    /* +0x2c0, "varc" spawn field */
    int32_t missionLevel;                    /* +0x2c4, "missionlevel" spawn field */
    char abiGap_2c8_2cb[0x004];              /* +0x2c8..0x2cb, size 0x004; vehicle/spawner audit found no maintained access before size spawn fields; retained for ABI. */
    int32_t startSize;                       /* +0x2cc, "start_size" spawn field */
    int32_t endSize;                         /* +0x2d0, "end_size" spawn field */
    char abiGap_2d4_2d7[0x004];              /* +0x2d4..0x2d7, size 0x004; vehicle/spawner audit found no maintained access before spawnItem; retained for ABI. */
    uint16_t spawnItem;                      /* +0x2d8, misc_spawner spawnitem key */
    uint16_t padding2da;                     /* +0x2da..+0x2db, aligns droppedClipCount. */

    /* === Dropped item clip (offset 0x2dc) === */
    int32_t droppedClipCount;                /* +0x2dc */
    char abiGap_2e0_2eb[0x00c];              /* +0x2e0..0x2eb, size 0x00c; dropped-item/link audit found no maintained access before track; retained for ABI. */
    uint16_t scriptTrack;                    /* +0x2ec, "track" spawn field string id */
    char padding2ee[2];                      /* +0x2ee..+0x2ef, aligns the following dword lane. */
    char abiGap_2f0[4];                      /* +0x2f0..+0x2f3; no original game-module access found. */

    /* === Link info / children / attach (offset range 0x2f4-0x347) === */
    entityLinkInfo_t *linkInfo;              /* +0x2f4 */
    gentity_t *firstChild;                   /* +0x2f8 */
    uint8_t attachModelIndex[6];             /* +0x2fc */
    uint16_t attachTagIndex[6];              /* +0x302, script string ids */
    char padding30e[2];                      /* +0x30e..+0x30f, aligns validationToken. */
    int32_t validationToken;                 /* +0x310, RECOVERED(UO-GAME-UNK-0136) */
    uint16_t vehicleSpawnName;               /* +0x314, script_vehicle spawn vehicle name */
    char padding316[2];                      /* +0x316..+0x317, aligns vehiclePrimaryDisabled. */
    int32_t vehiclePrimaryDisabled;          /* +0x318, also driver cooldown overlay */
    gentity_t *vehicleOwner;                 /* +0x31c */
    int32_t vehicleReenterTime;              /* +0x320 */
    int32_t lastVehicleEntityNum;            /* +0x324 */
    gentity_t *nextFree;                     /* +0x328, RECOVERED(UO-GAME-UNK-0149) */
    int32_t missileFuseTime;                 /* +0x32c, grenade stored fuse deadline */
    int32_t parentEntityNum;                 /* +0x330, RECOVERED(UO-GAME-UNK-0180) */
    char abiGap_334[0x004];                  /* +0x334, size 0x004; missile/spawnvar audit found no maintained access before saved spawn vars; retained for ABI. */
    int32_t savedSpawnVarCount;              /* +0x338, RECOVERED(UO-GAME-UNK-0121) */
    char **savedSpawnVarPairs;               /* +0x33c, RECOVERED(UO-GAME-UNK-0121) */
    int32_t savedSpawnTextLength;            /* +0x340, RECOVERED(UO-GAME-UNK-0121) */
    char *savedSpawnText;                    /* +0x344, RECOVERED(UO-GAME-UNK-0121) */
    uint8_t dobjDirty;                       /* +0x348 */
    char padding349[3];                      /* +0x349..+0x34b, gentity_t tail padding. */
};

/* NOT_FROM_ORIGINAL_SOURCE: maintained typed predicate over recovered gentity_t fields. */
static inline qboolean game_compat_gentity_can_take_damage(const gentity_t *ent)
{
    return ent->takeDamage != 0 ? qtrue : qfalse;
}

/*
 * Player movement structure (pmove_t).
 * Layout reconstructed from ClientThink_real, Pmove, PmoveSingle, view-angle
 * update, and the movement speed helpers.  ClientThink_real clears ABI size 0x11c bytes,
 * stores six current command words at +0x004..+0x018, six previous command
 * words at +0x01c..+0x030, then fills the callback tail.
 * UO-GAME-TASK-0345 checked remaining pad ranges against maintained pmove
 * accessors; no additional source access was observed.
 */
typedef struct pmove_s {
    playerState_t *ps;                       /* +0x000, playerState_t pointer */
    usercmd_t command;                       /* +0x004, current/substep command */
    usercmd_t oldCommand;                    /* +0x01c, previous command mirror */
    int32_t traceMask;                       /* +0x034, collision trace mask */
    int32_t debugMove;                       /* +0x038, g_debugMove */
    vec3_t viewClampTargetAngles;          /* +0x03c, controlled-vehicle view clamp target */
    vec3_t viewClampMaxDeltas;             /* +0x048, controlled-vehicle clamp delta caps */
    int32_t numtouch;                        /* +0x054, number of entities touched */
    int32_t impactEntityNums[32];            /* +0x058..0x0d7, PM_AddTouchEnt touch list */
    vec3_t mins;                           /* +0x0d8, movement trace bounds */
    vec3_t maxs;                           /* +0x0e4, movement trace bounds */
    uint8_t overheadContents;                /* +0x0f0, overhead point-contents result */
    uint8_t overheadLevel;                   /* +0x0f1, overhead obstruction level */
    char padding0f2[2];                      /* +0x0f2..+0x0f3, aligns horizontalSpeed. */
    float horizontalSpeed;                   /* +0x0f4, PM_FootstepUpdate scratch */
    int32_t pmove_msec_min;                  /* +0x0f8, minimum movement time step */
    int32_t pmove_msec_max;                  /* +0x0fc, maximum movement time step */
    int32_t weaponAnimscriptEnabled;         /* +0x100 */
    void (*trace)(struct trace_s *results, const float *start, const float *mins,
                  const float *maxs, const float *end, int passEntityNum,
                  int traceType);            /* +0x104, primary movement trace */
    void (*trace2)(struct trace_s *results, const float *start, const float *mins,
                   const float *maxs, const float *end, int passEntityNum,
                   int traceType);           /* +0x108, ADS/wall trace */
    void (*trace3)(struct trace_s *results, const float *start, const float *mins,
                   const float *maxs, const float *end, int passEntityNum,
                   int traceType);           /* +0x10c, overhead trace */
    int (*pointContents)(const float *point, int passEntityNum, int contentMask);
                                             /* +0x110, trap_PointContents */
    int (*entityType)(int entityNum);         /* +0x114, G_EntityType */
    int32_t adsInputBlocked;                 /* +0x118, G_IsInMatchTimeout ADS gate */
} pmove_t;

#define GAME_STATIC_ASSERT(name, condition) \
    typedef char game_static_assert_##name[(condition) ? 1 : -1]

#if UINTPTR_MAX == UINT32_MAX
#define GAME_I386_LAYOUT_ASSERT(name, condition) GAME_STATIC_ASSERT(name, condition)
#else
#define GAME_I386_LAYOUT_ASSERT(name, condition) \
    typedef char game_i386_layout_assert_skipped_##name[1]
#endif

#ifndef GAME_REQUIRE_X87_LONG_DOUBLE
#define GAME_REQUIRE_X87_LONG_DOUBLE 1
#endif

#define GAME_HOST_LONG_DOUBLE_IS_X87 \
    (LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384)

#if !GAME_REQUIRE_X87_LONG_DOUBLE && !defined(GAME_ALLOW_NON_EQUIVALENT_LONG_DOUBLE)
#error "GAME_REQUIRE_X87_LONG_DOUBLE=0 is only allowed with GAME_ALLOW_NON_EQUIVALENT_LONG_DOUBLE for explicit non-equivalence analysis builds"
#endif

GAME_STATIC_ASSERT(recovered_char_bit_width, CHAR_BIT == 8);
GAME_STATIC_ASSERT(recovered_int_abi_width, sizeof(int) == 4);
GAME_STATIC_ASSERT(recovered_int32_width, sizeof(int32_t) == 4);
GAME_STATIC_ASSERT(recovered_uint32_width, sizeof(uint32_t) == 4);
GAME_STATIC_ASSERT(recovered_float_radix, FLT_RADIX == 2);
GAME_STATIC_ASSERT(recovered_float_binary32,
                 FLT_MANT_DIG == 24 && FLT_MAX_EXP == 128);
GAME_STATIC_ASSERT(recovered_double_binary64,
                 DBL_MANT_DIG == 53 && DBL_MAX_EXP == 1024);
GAME_STATIC_ASSERT(recovered_long_double_x87_when_required,
                 !GAME_REQUIRE_X87_LONG_DOUBLE || GAME_HOST_LONG_DOUBLE_IS_X87);

GAME_STATIC_ASSERT(client_state_size,
                 sizeof(clientState_t) == 0x5c);
GAME_STATIC_ASSERT(client_state_team_offset,
                 offsetof(clientState_t, team) == 0x04);
GAME_STATIC_ASSERT(orientation_size, sizeof(orientation_t) == 0x30);
GAME_STATIC_ASSERT(orientation_origin_offset,
                 offsetof(orientation_t, origin) == 0x00);
GAME_STATIC_ASSERT(orientation_axis_offset,
                 offsetof(orientation_t, axis) == 0x0c);
GAME_STATIC_ASSERT(player_state_size, sizeof(playerState_t) == 0x4504);
GAME_STATIC_ASSERT(gclient_player_state_offset, offsetof(gclient_t, ps) == 0x000);
GAME_STATIC_ASSERT(gclient_ps_command_time_offset,
                 offsetof(gclient_t, ps.commandTime) == 0x000);
GAME_STATIC_ASSERT(gclient_pmType_offset, offsetof(gclient_t, ps.pmType) == 0x004);
GAME_STATIC_ASSERT(gclient_player_state_flags_offset,
                 offsetof(gclient_t, ps.playerStateFlags) == 0x00c);
GAME_STATIC_ASSERT(gclient_pm_time_offset, offsetof(gclient_t, ps.pmTime) == 0x010);
GAME_STATIC_ASSERT(gclient_weapon_time_offset, offsetof(gclient_t, ps.weaponTime) == 0x02c);
GAME_STATIC_ASSERT(gclient_weapon_delay_offset, offsetof(gclient_t, ps.weaponDelay) == 0x030);
GAME_STATIC_ASSERT(gclient_grenade_time_left_offset,
                 offsetof(gclient_t, ps.grenadeTimeLeft) == 0x034);
GAME_STATIC_ASSERT(gclient_foliage_sound_time_offset,
                 offsetof(gclient_t, ps.foliageSoundTime) == 0x038);
GAME_STATIC_ASSERT(gclient_fatigue_sound_time_offset,
                 offsetof(gclient_t, ps.fatigueSoundTime) == 0x03c);
GAME_STATIC_ASSERT(gclient_gravity_offset, offsetof(gclient_t, ps.gravity) == 0x040);
GAME_STATIC_ASSERT(gclient_lean_fraction_offset, offsetof(gclient_t, ps.leanFraction) == 0x044);
GAME_STATIC_ASSERT(gclient_speed_offset, offsetof(gclient_t, ps.speed) == 0x048);
GAME_STATIC_ASSERT(gclient_origin_offset, offsetof(gclient_t, ps.psOrigin) == 0x014);
GAME_STATIC_ASSERT(gclient_velocity_offset, offsetof(gclient_t, ps.velocity) == 0x020);
GAME_STATIC_ASSERT(gclient_ground_offset, offsetof(gclient_t, ps.groundEntityNum) == 0x058);
GAME_STATIC_ASSERT(gclient_ladder_normal_offset,
                 offsetof(gclient_t, ps.ladderNormal) == 0x05c);
GAME_STATIC_ASSERT(gclient_ladder_normal_y_offset,
                 offsetof(gclient_t, ps.ladderNormal[1]) == 0x060);
GAME_STATIC_ASSERT(gclient_ladder_normal_z_offset,
                 offsetof(gclient_t, ps.ladderNormal[2]) == 0x064);
GAME_STATIC_ASSERT(gclient_movement_dir_offset,
                 offsetof(gclient_t, ps.movementDir) == 0x080);
GAME_STATIC_ASSERT(gclient_entity_state_flags_offset,
                 offsetof(gclient_t, ps.entityStateFlags) == 0x084);
GAME_STATIC_ASSERT(gclient_event_index_offset, offsetof(gclient_t, ps.eventIndex) == 0x088);
GAME_STATIC_ASSERT(gclient_events_offset, offsetof(gclient_t, ps.events) == 0x08c);
GAME_STATIC_ASSERT(gclient_predictable_event_parms_offset,
                 offsetof(gclient_t, ps.eventParms) == 0x09c);
GAME_STATIC_ASSERT(gclient_event_parms_offset,
                 offsetof(gclient_t, ps.eventParms.ring) == 0x09c);
GAME_STATIC_ASSERT(gclient_legs_timer_offset, offsetof(gclient_t, ps.legsTimer) == 0x070);
GAME_STATIC_ASSERT(gclient_legs_anim_offset, offsetof(gclient_t, ps.legsAnim) == 0x074);
GAME_STATIC_ASSERT(gclient_torso_timer_offset, offsetof(gclient_t, ps.torsoTimer) == 0x078);
GAME_STATIC_ASSERT(gclient_torso_anim_offset, offsetof(gclient_t, ps.torsoAnim) == 0x07c);
GAME_STATIC_ASSERT(gclient_ps_client_num_offset, offsetof(gclient_t, ps.psClientNum) == 0x0d4);
GAME_STATIC_ASSERT(gclient_current_weapon_offset, offsetof(gclient_t, ps.currentWeapon) == 0x0d8);
GAME_STATIC_ASSERT(gclient_weapon_state_offset, offsetof(gclient_t, ps.weaponState) == 0x0dc);
GAME_STATIC_ASSERT(gclient_ads_fraction_offset, offsetof(gclient_t, ps.adsFraction) == 0x0e0);
GAME_STATIC_ASSERT(gclient_ps_view_model_index_offset,
                 offsetof(gclient_t, ps.viewModelIndex) == 0x0e4);
GAME_STATIC_ASSERT(gclient_view_angles_offset, offsetof(gclient_t, ps.viewAngles) == 0x0e8);
GAME_STATIC_ASSERT(gclient_view_height_target_offset,
                 offsetof(gclient_t, ps.viewHeightTarget) == 0x0f4);
GAME_STATIC_ASSERT(gclient_view_height_lerp_pos_adj_offset,
                 offsetof(gclient_t, ps.viewHeightLerpPosAdj) == 0x108);
GAME_STATIC_ASSERT(gclient_damage_yaw_offset,
                 offsetof(gclient_t, ps.damageYaw) == 0x110);
GAME_STATIC_ASSERT(gclient_damage_pitch_offset,
                 offsetof(gclient_t, ps.damagePitch) == 0x114);
GAME_STATIC_ASSERT(gclient_player_state_health_offset,
                 offsetof(gclient_t, ps.health) == 0x11c);
GAME_STATIC_ASSERT(gclient_death_yaw_offset, offsetof(gclient_t, ps.deathYaw) == 0x120);
GAME_STATIC_ASSERT(gclient_max_health_offset, offsetof(gclient_t, ps.maxHealth) == 0x124);
GAME_STATIC_ASSERT(gclient_ident_client_num_offset,
                 offsetof(gclient_t, ps.identClientNum) == 0x128);
GAME_STATIC_ASSERT(gclient_ident_client_health_offset,
                 offsetof(gclient_t, ps.identClientHealth) == 0x12c);
GAME_STATIC_ASSERT(gclient_spawn_count_offset,
                 offsetof(gclient_t, ps.spawnCount) == 0x130);
GAME_STATIC_ASSERT(gclient_prone_direction_offset,
                 offsetof(gclient_t, ps.proneDirection) == 0x5a4);
GAME_STATIC_ASSERT(gclient_prone_direction_pitch_offset,
                 offsetof(gclient_t, ps.proneDirectionPitch) == 0x5a8);
GAME_STATIC_ASSERT(gclient_ammo_offset, offsetof(gclient_t, ps.ammo) == 0x134);
GAME_STATIC_ASSERT(gclient_clips_offset, offsetof(gclient_t, ps.clips) == 0x334);
GAME_STATIC_ASSERT(gclient_weapon_bits_offset, offsetof(gclient_t, ps.weaponBits) == 0x534);
GAME_STATIC_ASSERT(gclient_weapon_slots_offset, offsetof(gclient_t, ps.weaponSlots) == 0x544);
GAME_STATIC_ASSERT(gclient_weapon_rechamber_bits_offset,
                 offsetof(gclient_t, ps.weaponRechamberBits) == 0x54c);
GAME_STATIC_ASSERT(gclient_player_mins_offset, offsetof(gclient_t, ps.playerMins) == 0x55c);
GAME_STATIC_ASSERT(gclient_player_mins_z_offset,
                 offsetof(gclient_t, ps.playerMins[2]) == 0x564);
GAME_STATIC_ASSERT(gclient_prone_view_height_offset,
                 offsetof(gclient_t, ps.proneViewHeight) == 0x574);
GAME_STATIC_ASSERT(gclient_crouch_view_height_offset,
                 offsetof(gclient_t, ps.crouchViewHeight) == 0x578);
GAME_STATIC_ASSERT(gclient_stand_view_height_offset,
                 offsetof(gclient_t, ps.standViewHeight) == 0x57c);
GAME_STATIC_ASSERT(gclient_dead_view_height_offset,
                 offsetof(gclient_t, ps.deadViewHeight) == 0x580);
GAME_STATIC_ASSERT(gclient_walk_speed_scale_offset,
                 offsetof(gclient_t, ps.walkSpeedScale) == 0x584);
GAME_STATIC_ASSERT(gclient_run_speed_scale_offset,
                 offsetof(gclient_t, ps.runSpeedScale) == 0x588);
GAME_STATIC_ASSERT(gclient_sprint_speed_scale_offset,
                 offsetof(gclient_t, ps.sprintSpeedScale) == 0x58c);
GAME_STATIC_ASSERT(gclient_prone_speed_scale_offset,
                 offsetof(gclient_t, ps.proneSpeedScale) == 0x590);
GAME_STATIC_ASSERT(gclient_crouch_speed_scale_offset,
                 offsetof(gclient_t, ps.crouchSpeedScale) == 0x594);
GAME_STATIC_ASSERT(gclient_strafe_speed_scale_offset,
                 offsetof(gclient_t, ps.strafeSpeedScale) == 0x598);
GAME_STATIC_ASSERT(gclient_back_speed_scale_offset,
                 offsetof(gclient_t, ps.backSpeedScale) == 0x59c);
GAME_STATIC_ASSERT(gclient_lean_speed_scale_offset,
                 offsetof(gclient_t, ps.leanSpeedScale) == 0x5a0);
GAME_STATIC_ASSERT(gclient_friction_offset,
                 offsetof(gclient_t, ps.friction) == 0x5c0);
GAME_STATIC_ASSERT(gclient_fatigue_scale_offset,
                 offsetof(gclient_t, ps.fatigueScale) == 0x5b0);
GAME_STATIC_ASSERT(gclient_last_sprint_time_offset,
                 offsetof(gclient_t, ps.lastSprintTime) == 0x5b4);
GAME_STATIC_ASSERT(gclient_torso_height_offset, offsetof(gclient_t, ps.torsoHeight) == 0x608);
GAME_STATIC_ASSERT(gclient_torso_pitch_offset, offsetof(gclient_t, ps.torsoPitch) == 0x60c);
GAME_STATIC_ASSERT(gclient_waist_pitch_offset, offsetof(gclient_t, ps.waistPitch) == 0x610);
GAME_STATIC_ASSERT(gclient_weapon_anim_offset,
                 offsetof(gclient_t, ps.weaponAnim) == 0x624);
GAME_STATIC_ASSERT(gclient_motion_state_offset, offsetof(gclient_t, ps.motionState) == 0x62c);
GAME_STATIC_ASSERT(gclient_external_velocity_offset,
                 offsetof(gclient_t, ps.motionState.externalVelocity) == 0x62c);
GAME_STATIC_ASSERT(gclient_shellshock_start_offset,
                 offsetof(gclient_t, ps.motionState.shellshock.time) == 0x630);
GAME_I386_LAYOUT_ASSERT(objective_size, sizeof(objective_t) == 0x1c);
GAME_STATIC_ASSERT(gclient_objectives_offset, offsetof(gclient_t, ps.objectives) == 0x638);
GAME_STATIC_ASSERT(gclient_hud_elems_current_offset,
                 offsetof(gclient_t, ps.hudCurrent) == 0x7f8);
GAME_STATIC_ASSERT(gclient_hud_elems_archived_offset,
                 offsetof(gclient_t, ps.hudArchival) == 0x267c);
GAME_STATIC_ASSERT(gclient_delta_time_offset,
                 offsetof(gclient_t, ps.deltaTime) == 0x4500);
GAME_STATIC_ASSERT(gclient_session_state_offset, offsetof(gclient_t, sessionState) == 0x4504);
GAME_STATIC_ASSERT(gclient_script_follow_client_offset,
                 offsetof(gclient_t, followClient) == 0x4508);
GAME_STATIC_ASSERT(gclient_script_archive_time_offset,
                 offsetof(gclient_t, archiveTime) == 0x4510);
GAME_STATIC_ASSERT(gclient_script_score_offset, offsetof(gclient_t, score) == 0x4514);
GAME_STATIC_ASSERT(gclient_script_deaths_offset, offsetof(gclient_t, deaths) == 0x4518);
GAME_STATIC_ASSERT(gclient_script_pers_offset, offsetof(gclient_t, pers) == 0x451c);
GAME_STATIC_ASSERT(gclient_command_offset, offsetof(gclient_t, command) == 0x4524);
GAME_STATIC_ASSERT(gclient_command_time_offset,
                 offsetof(gclient_t, command.commandTime) == 0x4524);
GAME_STATIC_ASSERT(gclient_command_buttons_offset,
                 offsetof(gclient_t, command.buttons) == 0x4528);
GAME_STATIC_ASSERT(gclient_command_wbuttons_offset,
                 offsetof(gclient_t, command.wbuttons) == 0x4529);
GAME_STATIC_ASSERT(gclient_command_weapon_offset,
                 offsetof(gclient_t, command.weapon) == 0x452a);
GAME_STATIC_ASSERT(gclient_command_angles_offset,
                 offsetof(gclient_t, command.angles) == 0x452c);
GAME_STATIC_ASSERT(gclient_command_forwardmove_offset,
                 offsetof(gclient_t, command.forwardmove) == 0x4538);
GAME_STATIC_ASSERT(gclient_old_pmove_command_offset,
                 offsetof(gclient_t, oldPmoveCommand) == 0x453c);
GAME_STATIC_ASSERT(gclient_complaint_disabled_offset,
                 offsetof(gclient_t, complaintDisabled) == 0x4554);
GAME_STATIC_ASSERT(gclient_predict_items_offset, offsetof(gclient_t, predictItems) == 0x4558);
GAME_STATIC_ASSERT(gclient_pmove_fixed_offset, offsetof(gclient_t, pmoveFixed) == 0x455c);
GAME_STATIC_ASSERT(gclient_clean_name_offset, offsetof(gclient_t, cleanName) == 0x4560);
GAME_STATIC_ASSERT(gclient_script_handicap_offset, offsetof(gclient_t, handicap) == 0x4580);
GAME_STATIC_ASSERT(gclient_script_normal_max_health_offset,
                 offsetof(gclient_t, normalMaxHealth) == 0x4584);
GAME_STATIC_ASSERT(gclient_script_max_speed_offset, offsetof(gclient_t, maxSpeed) == 0x4588);
GAME_STATIC_ASSERT(gclient_called_votes_offset, offsetof(gclient_t, calledVotes) == 0x4594);
GAME_STATIC_ASSERT(gclient_view_model_index_offset, offsetof(gclient_t, viewModelIndex) == 0x45a8);
GAME_STATIC_ASSERT(gclient_session_squad_offset, offsetof(gclient_t, sessionSquad) == 0x45b4);
GAME_STATIC_ASSERT(gclient_client_num_offset, offsetof(gclient_t, clientNum) == 0x45b8);
GAME_STATIC_ASSERT(gclient_session_team_offset, offsetof(gclient_t, sessionTeam) == 0x45bc);
GAME_STATIC_ASSERT(gclient_base_model_index_offset,
                 offsetof(gclient_t, baseModelIndex) == 0x45c0);
GAME_STATIC_ASSERT(gclient_attach_model_indices_offset,
                 offsetof(gclient_t, attachModelIndices) == 0x45c4);
GAME_STATIC_ASSERT(gclient_attach_tag_indices_offset,
                 offsetof(gclient_t, attachTagIndices) == 0x45dc);
GAME_STATIC_ASSERT(gclient_script_userinfo_name_offset,
                 offsetof(gclient_t, userInfoName) == 0x45f4);
GAME_STATIC_ASSERT(gclient_script_no_inactivity_kick_offset,
                 offsetof(gclient_t, spectatorActivityState) == 0x4614);
GAME_STATIC_ASSERT(gclient_archive_client_offset, offsetof(gclient_t, archiveClient) == 0x4618);
GAME_STATIC_ASSERT(gclient_latched_buttons_offset,
                 offsetof(gclient_t, latchedButtons) == 0x4634);
GAME_STATIC_ASSERT(gclient_latched_wbuttons_offset,
                 offsetof(gclient_t, latchedWbuttons) == 0x4640);
GAME_STATIC_ASSERT(gclient_spectator_snapshot_origin_offset,
                 offsetof(gclient_t, spectatorSnapshotOrigin) == 0x4644);
GAME_STATIC_ASSERT(gclient_inactivity_time_offset,
                 offsetof(gclient_t, inactivityTime) == 0x4678);
GAME_STATIC_ASSERT(gclient_spectator_inactivity_time_offset,
                 offsetof(gclient_t, spectatorInactivityTime) == 0x467c);
GAME_STATIC_ASSERT(gclient_inactivity_warning_sent_offset,
                 offsetof(gclient_t, inactivityWarningSent) == 0x4680);
GAME_STATIC_ASSERT(gclient_spectator_inactivity_warning_offset,
                 offsetof(gclient_t, spectatorInactivityWarning) == 0x4684);
GAME_STATIC_ASSERT(gclient_vehicle_control_time_offset,
                 offsetof(gclient_t, vehicleControlTime) == 0x468c);
GAME_STATIC_ASSERT(gclient_vehicle_delay_ignore_time_offset,
                 offsetof(gclient_t, vehicleDelayIgnoreTime) == 0x4690);
GAME_STATIC_ASSERT(gclient_driver_unlink_requested_offset,
                 offsetof(gclient_t, driverUnlinkRequested) == 0x4694);
GAME_STATIC_ASSERT(vehicle_state_type_offset, offsetof(vehicle_state_t, typeIndex) == 0x22c);
GAME_STATIC_ASSERT(vehicle_physics_state_size,
                 sizeof(vehicle_physics_state_t) == 0xb8);
GAME_STATIC_ASSERT(vehicle_physics_state_view_clamp_target_offset,
                 offsetof(vehicle_physics_state_t, viewClampTargetAngles) == 0x18);
GAME_STATIC_ASSERT(vehicle_physics_state_velocity_offset,
                 offsetof(vehicle_physics_state_t, velocity) == 0x30);
GAME_STATIC_ASSERT(vehicle_physics_state_wheel_material_offset,
                 offsetof(vehicle_physics_state_t, wheelMaterial) == 0xa0);
GAME_STATIC_ASSERT(vehicle_state_origin_offset, offsetof(vehicle_state_t, origin) == 0x0b8);
GAME_STATIC_ASSERT(vehicle_state_view_clamp_target_offset,
                 offsetof(vehicle_state_t, viewClampTargetAngles) == 0x0d0);
GAME_STATIC_ASSERT(vehicle_state_velocity_offset, offsetof(vehicle_state_t, velocity) == 0x0e8);
GAME_STATIC_ASSERT(vehicle_state_angular_velocity_offset,
                 offsetof(vehicle_state_t, angularVelocity) == 0x0f4);
GAME_STATIC_ASSERT(vehicle_state_acceleration_offset,
                 offsetof(vehicle_state_t, acceleration) == 0x100);
GAME_STATIC_ASSERT(vehicle_state_steer_angle_offset,
                 offsetof(vehicle_state_t, steerAngle) == 0x10c);
GAME_STATIC_ASSERT(vehicle_state_previous_physics_offset,
                 offsetof(vehicle_state_t, previousPhysicsState) == 0x170);
GAME_STATIC_ASSERT(vehicle_state_entity_num_offset,
                 offsetof(vehicle_state_t, entityNum) == 0x228);
GAME_STATIC_ASSERT(vehicle_state_slot_index_offset,
                 offsetof(vehicle_state_t, slotIndex) == 0x230);
GAME_STATIC_ASSERT(vehicle_state_hint_string_index_offset,
                 offsetof(vehicle_state_t, hintStringIndex) == 0x234);
GAME_STATIC_ASSERT(vehicle_state_wait_node_speed_threshold_offset,
                 offsetof(vehicle_state_t, waitNodeSpeedThreshold) == 0x23c);
GAME_STATIC_ASSERT(vehicle_state_primary_fire_time_offset,
                 offsetof(vehicle_state_t, primaryFireTime) == 0x240);
GAME_STATIC_ASSERT(vehicle_state_alt_fire_time_offset,
                 offsetof(vehicle_state_t, altFireTime) == 0x244);
GAME_STATIC_ASSERT(vehicle_state_primary_flash_selector_offset,
                 offsetof(vehicle_state_t, primaryFlashSelector) == 0x248);
GAME_STATIC_ASSERT(vehicle_state_gunner_turret_state_offset,
                 offsetof(vehicle_state_t, gunnerTurretState) == 0x254);
GAME_STATIC_ASSERT(vehicle_state_gunner_fire_time_offset,
                 offsetof(vehicle_state_t, gunnerFireTime) == 0x258);
GAME_STATIC_ASSERT(vehicle_state_alt_heat_offset,
                 offsetof(vehicle_state_t, altHeat) == 0x25c);
GAME_STATIC_ASSERT(vehicle_state_gunner_heat_offset,
                 offsetof(vehicle_state_t, gunnerHeat) == 0x260);
GAME_STATIC_ASSERT(vehicle_state_alt_overheating_offset,
                 offsetof(vehicle_state_t, altOverheating) == 0x264);
GAME_STATIC_ASSERT(vehicle_state_gunner_overheating_offset,
                 offsetof(vehicle_state_t, gunnerOverheating) == 0x268);
GAME_STATIC_ASSERT(vehicle_state_local_forward_accel_offset,
                 offsetof(vehicle_state_t, localForwardAccel) == 0x2a4);
GAME_STATIC_ASSERT(vehicle_state_sound_blends_offset,
                 offsetof(vehicle_state_t, soundBlendEntityNums) == 0x2c4);
GAME_STATIC_ASSERT(vehicle_state_idle_sound_repeat_delay_offset,
                 offsetof(vehicle_state_t, idleSoundBlendRepeatDelay) == 0x2d4);
GAME_STATIC_ASSERT(vehicle_state_run_sound_repeat_delay_offset,
                 offsetof(vehicle_state_t, runSoundBlendRepeatDelay) == 0x2d8);
GAME_STATIC_ASSERT(vehicle_state_alt_weapon_fire_sound_offset,
                 offsetof(vehicle_state_t, altWeaponFireSound) == 0x2dc);
GAME_STATIC_ASSERT(vehicle_state_alt_weapon_stop_sound_offset,
                 offsetof(vehicle_state_t, altWeaponStopSound) == 0x2e0);
GAME_STATIC_ASSERT(vehicle_state_alt_weapon_sound_time_offset,
                 offsetof(vehicle_state_t, altWeaponSoundTime) == 0x2e4);
GAME_STATIC_ASSERT(vehicle_state_gunner_weapon_fire_sound_offset,
                 offsetof(vehicle_state_t, gunnerWeaponFireSound) == 0x2e8);
GAME_STATIC_ASSERT(vehicle_state_gunner_weapon_stop_sound_offset,
                 offsetof(vehicle_state_t, gunnerWeaponStopSound) == 0x2ec);
GAME_STATIC_ASSERT(vehicle_state_gunner_weapon_sound_time_offset,
                 offsetof(vehicle_state_t, gunnerWeaponSoundTime) == 0x2f0);
GAME_STATIC_ASSERT(vehicle_state_driver_tag_offset,
                 offsetof(vehicle_state_t, driverTagIndex) == 0x2f4);
GAME_STATIC_ASSERT(vehicle_state_detach_tag_offset,
                 offsetof(vehicle_state_t, detachTagIndex) == 0x2f8);
GAME_STATIC_ASSERT(vehicle_state_popout_tag_offset,
                 offsetof(vehicle_state_t, popoutTagIndex) == 0x2fc);
GAME_STATIC_ASSERT(vehicle_state_body_tag_offset,
                 offsetof(vehicle_state_t, bodyTagIndex) == 0x300);
GAME_STATIC_ASSERT(vehicle_state_primary_base_tag_offset,
                 offsetof(vehicle_state_t, primaryBaseTagIndex) == 0x304);
GAME_STATIC_ASSERT(vehicle_state_primary_turret_tag_offset,
                 offsetof(vehicle_state_t, primaryTurretTagIndex) == 0x308);
GAME_STATIC_ASSERT(vehicle_state_primary_alt_turret_tag_offset,
                 offsetof(vehicle_state_t, primaryAltTurretTagIndex) == 0x30c);
GAME_STATIC_ASSERT(vehicle_state_gunner_tag_offset,
                 offsetof(vehicle_state_t, gunnerTagIndex) == 0x310);
GAME_STATIC_ASSERT(vehicle_state_gunner_turret_tag_offset,
                 offsetof(vehicle_state_t, gunnerTurretTagIndex) == 0x314);
GAME_STATIC_ASSERT(vehicle_state_secondary_base_tag_offset,
                 offsetof(vehicle_state_t, secondaryBaseTagIndex) == 0x318);
GAME_STATIC_ASSERT(vehicle_state_primary_flash_tags_offset,
                 offsetof(vehicle_state_t, primaryFlashTagIndices) == 0x324);
GAME_STATIC_ASSERT(vehicle_state_alt_fire_tags_offset,
                 offsetof(vehicle_state_t, altFireTagIndices) == 0x334);
GAME_STATIC_ASSERT(vehicle_state_secondary_flash_tags_offset,
                 offsetof(vehicle_state_t, secondaryFlashTagIndices) == 0x344);
GAME_STATIC_ASSERT(vehicle_state_wheel_tags_offset,
                 offsetof(vehicle_state_t, wheelTagIndices) == 0x354);
GAME_STATIC_ASSERT(vehicle_state_passenger_tags_offset,
                 offsetof(vehicle_state_t, passengerTagIndices) == 0x36c);
GAME_STATIC_ASSERT(vehicle_state_primary_aim_sight_trace_result_offset,
                 offsetof(vehicle_state_t, primaryAimSightTraceResult) == 0x37c);
GAME_STATIC_ASSERT(vehicle_state_scripted_driver_time_offset,
                 offsetof(vehicle_state_t, scriptedDriverEndTime) == 0x390);
GAME_STATIC_ASSERT(vehicle_state_passenger_entity_nums_offset,
                 offsetof(vehicle_state_t, passengerEntityNums) == 0x39c);
GAME_STATIC_ASSERT(vehicle_state_collision_fraction_offset,
                 offsetof(vehicle_state_t, collisionSweepFraction) == 0x3b8);
GAME_STATIC_ASSERT(vehicle_state_last_input_time_offset,
                 offsetof(vehicle_state_t, lastInputTime) == 0x3c0);
GAME_STATIC_ASSERT(vehicle_state_collision_notify_time_offset,
                 offsetof(vehicle_state_t, collisionNotifyTime) == 0x3c8);
GAME_STATIC_ASSERT(vehicle_state_collision_sound_time_offset,
                 offsetof(vehicle_state_t, collisionSoundTime) == 0x3cc);
GAME_STATIC_ASSERT(vehicle_state_collision_entity_offset,
                 offsetof(vehicle_state_t, cachedCollisionEntityNum) == 0x3d0);
GAME_STATIC_ASSERT(vehicle_state_collision_distance_offset,
                 offsetof(vehicle_state_t, cachedCollisionDistance) == 0x3d4);
GAME_STATIC_ASSERT(vehicle_state_last_stable_time_offset,
                 offsetof(vehicle_state_t, lastStableTime) == 0x3d8);
GAME_STATIC_ASSERT(vehicle_state_last_solid_time_offset,
                 offsetof(vehicle_state_t, lastSolidTime) == 0x3dc);
GAME_STATIC_ASSERT(vehicle_state_collision_normal_offset,
                 offsetof(vehicle_state_t, collisionNormal) == 0x3e0);
GAME_STATIC_ASSERT(vehicle_info_type_offset, offsetof(vehicleInfo_t, type) == 0x040);
GAME_STATIC_ASSERT(vehicle_info_steer_wheels_offset,
                 offsetof(vehicleInfo_t, steerWheels) == 0x044);
GAME_STATIC_ASSERT(vehicle_info_texture_scroll_offset,
                 offsetof(vehicleInfo_t, textureScroll) == 0x048);
GAME_STATIC_ASSERT(vehicle_info_primary_dual_flash_offset,
                 offsetof(vehicleInfo_t, primaryDualFlash) == 0x04c);
GAME_STATIC_ASSERT(vehicle_info_bullet_damage_offset,
                 offsetof(vehicleInfo_t, bulletDamageEnabled) == 0x050);
GAME_STATIC_ASSERT(vehicle_info_grenade_damage_offset,
                 offsetof(vehicleInfo_t, grenadeDamageEnabled) == 0x054);
GAME_STATIC_ASSERT(vehicle_info_explosive_damage_offset,
                 offsetof(vehicleInfo_t, explosiveDamageEnabled) == 0x058);
GAME_STATIC_ASSERT(vehicle_info_gunner_seat_offset,
                 offsetof(vehicleInfo_t, gunnerSeatEnabled) == 0x05c);
GAME_STATIC_ASSERT(vehicle_info_extra_passenger_count_offset,
                 offsetof(vehicleInfo_t, extraPassengerCount) == 0x060);
GAME_STATIC_ASSERT(vehicle_info_texture_scroll_scale_offset,
                 offsetof(vehicleInfo_t, textureScrollScale) == 0x064);
GAME_STATIC_ASSERT(vehicle_info_forward_input_scale_offset,
                 offsetof(vehicleInfo_t, forwardInputScale) == 0x078);
GAME_STATIC_ASSERT(vehicle_info_acceleration_offset,
                 offsetof(vehicleInfo_t, acceleration) == 0x06c);
GAME_STATIC_ASSERT(vehicle_info_collision_damage_scale_offset,
                 offsetof(vehicleInfo_t, collisionDamageScale) == 0x080);
GAME_STATIC_ASSERT(vehicle_info_path_speed_offset,
                 offsetof(vehicleInfo_t, pathSpeed) == 0x084);
GAME_STATIC_ASSERT(vehicle_info_suspension_travel_offset,
                 offsetof(vehicleInfo_t, suspensionTravel) == 0x088);
GAME_STATIC_ASSERT(vehicle_info_turret_weapon_offset,
                 offsetof(vehicleInfo_t, turretWeapon) == 0x08c);
GAME_STATIC_ASSERT(vehicle_info_turret_alt_weapon_offset,
                 offsetof(vehicleInfo_t, turretAltWeapon) == 0x0cc);
GAME_STATIC_ASSERT(vehicle_info_primary_turret_limits_offset,
                 offsetof(vehicleInfo_t, primaryYawLimitPos) == 0x10c);
GAME_STATIC_ASSERT(vehicle_info_turret_gunner_weapon_offset,
                 offsetof(vehicleInfo_t, turretGunnerWeapon) == 0x120);
GAME_STATIC_ASSERT(vehicle_info_gunner_turret_limits_offset,
                 offsetof(vehicleInfo_t, gunnerYawLimitPos) == 0x160);
GAME_STATIC_ASSERT(vehicle_info_sound_names_offset,
                 offsetof(vehicleInfo_t, soundNames) == 0x174);
GAME_STATIC_ASSERT(vehicle_info_idle_blend_sound_offset,
                 offsetof(vehicleInfo_t, idleBlendSound0) == 0x334);
GAME_STATIC_ASSERT(vehicle_info_primary_active_sound_offset,
                 offsetof(vehicleInfo_t, primaryActiveSound) == 0x338);
GAME_STATIC_ASSERT(vehicle_info_collision_sound_offset,
                 offsetof(vehicleInfo_t, collisionSound) == 0x33a);
GAME_STATIC_ASSERT(vehicle_info_path_speed_denom_offset,
                 offsetof(vehicleInfo_t, pathSpeedDenom) == 0x33c);
GAME_STATIC_ASSERT(vehicle_info_damage_scale_front_offset,
                 offsetof(vehicleInfo_t, damageScaleFront) == 0x340);
GAME_STATIC_ASSERT(vehicle_info_damage_scale_bullet_offset,
                 offsetof(vehicleInfo_t, damageScaleBullet) == 0x350);
GAME_STATIC_ASSERT(vehicle_info_collision_mins_offset,
                 offsetof(vehicleInfo_t, collisionMins) == 0x354);
GAME_STATIC_ASSERT(vehicle_info_collision_maxs_offset,
                 offsetof(vehicleInfo_t, collisionMaxs) == 0x360);
GAME_STATIC_ASSERT(vehicle_info_collision_bounds_source_offset,
                 offsetof(vehicleInfo_t, collisionBoundsSource) == 0x36c);
GAME_STATIC_ASSERT(vehicle_info_roll_limit_offset,
                 offsetof(vehicleInfo_t, rollLimit) == 0x38c);
GAME_STATIC_ASSERT(vehicle_info_step_size_offset,
                 offsetof(vehicleInfo_t, stepSize) == 0x390);
GAME_STATIC_ASSERT(vehicle_info_dismount_forward_offset,
                 offsetof(vehicleInfo_t, dismountForwardOffset) == 0x394);
GAME_STATIC_ASSERT(vehicle_info_dismount_back_offset,
                 offsetof(vehicleInfo_t, dismountBackOffset) == 0x398);
GAME_STATIC_ASSERT(vehicle_info_hint_string_offset,
                 offsetof(vehicleInfo_t, hintString) == 0x39c);
GAME_STATIC_ASSERT(vehicle_state_size, sizeof(vehicle_state_t) == 0x3ec);
GAME_STATIC_ASSERT(vehicle_info_size,
                 sizeof(vehicleInfo_t) == 0x3dc);
GAME_STATIC_ASSERT(trType_enum_abi_size_must_be_4_bytes_for_trajectory_layout,
                 sizeof(trType_t) == 4);
GAME_STATIC_ASSERT(effective_stance_enum_abi_size,
                 sizeof(effectiveStance_t) == 4);
GAME_STATIC_ASSERT(trajectory_tr_type_offset, offsetof(trajectory_t, trType) == 0x00);
GAME_STATIC_ASSERT(trajectory_tr_duration_offset, offsetof(trajectory_t, trDuration) == 0x08);
GAME_STATIC_ASSERT(trajectory_tr_base_offset, offsetof(trajectory_t, trBase) == 0x0c);
GAME_STATIC_ASSERT(trajectory_tr_delta_offset, offsetof(trajectory_t, trDelta) == 0x18);
GAME_STATIC_ASSERT(trajectory_size, sizeof(trajectory_t) == 0x24);
GAME_STATIC_ASSERT(bg_player_anim_pm_type_offset,
                 offsetof(clientInfo_t, pmType) == 0x004);
GAME_STATIC_ASSERT(clientinfo_client_num_anim_offset,
                 offsetof(clientInfo_t, clientNum) == 0x008);
GAME_STATIC_ASSERT(bg_player_anim_name_alias_offset,
                 offsetof(clientInfo_t, name) == 0x00c);
GAME_STATIC_ASSERT(bg_player_anim_team_alias_offset,
                 offsetof(clientInfo_t, team) == 0x02c);
GAME_STATIC_ASSERT(bg_player_anim_base_model_name_alias_offset,
                 offsetof(clientInfo_t, modelName) == 0x040);
GAME_STATIC_ASSERT(bg_player_anim_attach_model_names_alias_offset,
                 offsetof(clientInfo_t, attachModelNames) == 0x080);
GAME_STATIC_ASSERT(bg_player_anim_attach_tag_names_alias_offset,
                 offsetof(clientInfo_t, attachTagNames) == 0x200);
GAME_STATIC_ASSERT(clientinfo_info_valid_offset,
                 offsetof(clientInfo_t, infoValid) == 0x000);
GAME_STATIC_ASSERT(clientinfo_client_num_offset,
                 offsetof(clientInfo_t, clientNum) == 0x008);
GAME_STATIC_ASSERT(clientinfo_attach_tag_names_slot5_tail_offset,
                 offsetof(clientInfo_t, attachTagNames) +
                         5 * CLIENT_INFO_MODEL_NAME_SIZE + 0x3c == 0x37c);
GAME_I386_LAYOUT_ASSERT(clientinfo_dobj_saved_model_offset,
                      offsetof(clientInfo_t, dobjSavedModel) == 0x4c8);
GAME_I386_LAYOUT_ASSERT(clientinfo_dobj_version_offset,
                      offsetof(clientInfo_t, dobjVersion) == 0x4cc);
GAME_STATIC_ASSERT(bg_player_anim_legs_slot_offset,
                 offsetof(clientInfo_t, legsYawAngle) == 0x380);
GAME_STATIC_ASSERT(bg_player_anim_torso_slot_offset,
                 offsetof(clientInfo_t, torsoYawAngle) == 0x3b0);
GAME_STATIC_ASSERT(bg_player_anim_view_pitch_offset,
                 offsetof(clientInfo_t, viewPitch) == 0x3e8);
GAME_STATIC_ASSERT(bg_player_anim_view_yaw_offset,
                 offsetof(clientInfo_t, viewYaw) == 0x3ec);
GAME_STATIC_ASSERT(bg_player_anim_view_roll_offset,
                 offsetof(clientInfo_t, viewRoll) == 0x3f0);
GAME_STATIC_ASSERT(bg_player_anim_legs_timer_offset,
                 offsetof(clientInfo_t, legsTimer) == 0x388);
GAME_STATIC_ASSERT(bg_player_anim_legs_anim_offset,
                 offsetof(clientInfo_t, legsAnim) == 0x38c);
GAME_STATIC_ASSERT(bg_player_anim_override_angle_offset,
                 offsetof(clientInfo_t, override.torsoState.overrideAngle) == 0x3f8);
GAME_STATIC_ASSERT(bg_player_anim_override_pitch_offset,
                 offsetof(clientInfo_t, override.angles.pitch) == 0x3f4);
GAME_STATIC_ASSERT(bg_player_anim_override_yaw_offset,
                 offsetof(clientInfo_t, override.angles.yaw) == 0x3f8);
GAME_STATIC_ASSERT(bg_player_anim_override_roll_offset,
                 offsetof(clientInfo_t, override.angles.roll) == 0x3fc);
GAME_STATIC_ASSERT(bg_player_anim_torso_timer_offset,
                 offsetof(clientInfo_t, torsoTimer) == 0x400);
GAME_STATIC_ASSERT(bg_player_anim_dobj_needs_update_alias_offset,
                 offsetof(clientInfo_t, dobjNeedsUpdate) == 0x404);
GAME_STATIC_ASSERT(bg_player_anim_controller_angles_offset,
                 offsetof(clientInfo_t, controllerAngles) == 0x408);
GAME_STATIC_ASSERT(bg_player_anim_local_tag_angles_offset,
                 offsetof(clientInfo_t, localTagAngles) == 0x450);
GAME_STATIC_ASSERT(bg_player_anim_local_tag_offset,
                 offsetof(clientInfo_t, localTagOffset) == 0x45c);
GAME_STATIC_ASSERT(bg_player_anim_condition_words_offset,
                 offsetof(clientInfo_t, conditionWords) == 0x468);
GAME_STATIC_ASSERT(bg_player_anim_transition_time_offset,
                 offsetof(clientInfo_t, animTransitionTime) == 0x4c0);
GAME_I386_LAYOUT_ASSERT(bg_player_anim_tree_offset,
                      offsetof(clientInfo_t, animTree) == 0x4c4);
GAME_I386_LAYOUT_ASSERT(clientinfo_stride_size,
                      sizeof(clientInfo_t) == 0x04d0u);
GAME_STATIC_ASSERT(dobj_anim_mat_size, sizeof(DObjAnimMat) == 0x20);
GAME_STATIC_ASSERT(dobj_anim_mat_trans_offset,
                 offsetof(DObjAnimMat, trans) == 0x10);
/* Native pointers make the full entity/client ABI assertions meaningful only
 * for an i386-targeted build. Fixed-width subviews above remain checked on all
 * hosts; post-pointer binary access should use explicit offset helpers. */
#if UINTPTR_MAX == 0xffffffffu
GAME_STATIC_ASSERT(dobj_model_size, sizeof(DObjModel) == 0x10);
GAME_STATIC_ASSERT(dobj_model_ignore_collision_offset,
                 offsetof(DObjModel, ignoreCollision) == 0x0c);
GAME_STATIC_ASSERT(entity_link_info_tag_offset,
                 offsetof(entityLinkInfo_t, tagStringId) == 0x08);
GAME_STATIC_ASSERT(entity_link_info_parent_offset,
                 offsetof(entityLinkInfo_t, parent) == 0x00);
GAME_STATIC_ASSERT(entity_link_info_next_child_offset,
                 offsetof(entityLinkInfo_t, nextChild) == 0x04);
GAME_STATIC_ASSERT(entity_link_info_parent_tag_offset,
                 offsetof(entityLinkInfo_t, parentTagIndex) == 0x0c);
GAME_STATIC_ASSERT(entity_link_info_rel_axis_offset,
                 offsetof(entityLinkInfo_t, relAxis) == 0x10);
GAME_STATIC_ASSERT(entity_link_info_offset_column_offset,
                 offsetof(entityLinkInfo_t, relAxis[9]) == 0x34);
GAME_STATIC_ASSERT(entity_link_info_parent_rel_axis_offset,
                 offsetof(entityLinkInfo_t, parentRelAxis) == 0x40);
GAME_STATIC_ASSERT(entity_link_info_size, sizeof(entityLinkInfo_t) == 0x70);
GAME_STATIC_ASSERT(gclient_size, sizeof(gclient_t) == 0x4734u);
GAME_STATIC_ASSERT(hudelem_size, sizeof(hudElem_t) == 0x88);
GAME_STATIC_ASSERT(hudelem_client_snapshot_size,
                 sizeof(hudElemClientSnapshot_t) == 0x7c);
GAME_STATIC_ASSERT(hudelem_x_offset, offsetof(hudElem_t, x) == 0x04);
GAME_STATIC_ASSERT(hudelem_y_offset, offsetof(hudElem_t, y) == 0x08);
GAME_STATIC_ASSERT(hudelem_align_x_offset, offsetof(hudElem_t, alignX) == 0x14);
GAME_STATIC_ASSERT(hudelem_align_y_offset, offsetof(hudElem_t, alignY) == 0x18);
GAME_STATIC_ASSERT(hudelem_color_offset, offsetof(hudElem_t, color) == 0x1c);
GAME_STATIC_ASSERT(hudelem_width_offset, offsetof(hudElem_t, width) == 0x30);
GAME_STATIC_ASSERT(hudelem_height_offset, offsetof(hudElem_t, height) == 0x34);
GAME_STATIC_ASSERT(hudelem_move_from_x_offset,
                 offsetof(hudElem_t, moveFromX) == 0x4c);
GAME_STATIC_ASSERT(hudelem_move_from_y_offset,
                 offsetof(hudElem_t, moveFromY) == 0x50);
GAME_STATIC_ASSERT(hudelem_move_start_time_offset,
                 offsetof(hudElem_t, moveStartTime) == 0x54);
GAME_STATIC_ASSERT(hudelem_move_time_offset,
                 offsetof(hudElem_t, moveTime) == 0x58);
GAME_STATIC_ASSERT(hudelem_text_offset, offsetof(hudElem_t, text) == 0x68);
GAME_STATIC_ASSERT(hudelem_sort_offset, offsetof(hudElem_t, sort) == 0x6c);
GAME_STATIC_ASSERT(hudelem_unused_78_offset,
                 offsetof(hudElem_t, unused78) == 0x78);
GAME_STATIC_ASSERT(hudelem_client_snapshot_unused_78_offset,
                 offsetof(hudElemClientSnapshot_t, unused78) == 0x78);
GAME_STATIC_ASSERT(hudelem_client_num_offset, offsetof(hudElem_t, clientNum) == 0x7c);
GAME_STATIC_ASSERT(hudelem_archived_offset, offsetof(hudElem_t, archived) == 0x84);
GAME_STATIC_ASSERT(gclient_controls_frozen_offset, offsetof(gclient_t, controlsFrozen) == 0x4624);
GAME_STATIC_ASSERT(gclient_look_at_entity_offset, offsetof(gclient_t, lookAtEntity) == 0x46b8);
GAME_STATIC_ASSERT(gclient_cursor_hint_offset, offsetof(gclient_t, ps.serverCursorHint) == 0x5c4);
GAME_STATIC_ASSERT(gclient_cursor_hint_entity_offset,
                 offsetof(gclient_t, ps.cursorHintEntNum) == 0x5f8);
GAME_STATIC_ASSERT(gclient_nonpvs_friendly_info_offset,
                 offsetof(gclient_t, ps.compassFriendInfo) == 0x600);
GAME_STATIC_ASSERT(gclient_nonpvs_tank_info_offset,
                 offsetof(gclient_t, ps.compassTankInfo) == 0x604);
GAME_STATIC_ASSERT(gclient_vehicle_anim_pitch_offset,
                 offsetof(gclient_t, ps.vehicleMotion) == 0x61c);
GAME_STATIC_ASSERT(gclient_spectator_snapshot_angle0_offset,
                 offsetof(gclient_t, spectatorSnapshotAngle0) == 0x4650);
GAME_STATIC_ASSERT(gclient_spectator_snapshot_angle1_offset,
                 offsetof(gclient_t, spectatorSnapshotAngle1) == 0x4654);
GAME_STATIC_ASSERT(gclient_endframe_transient_46a4_offset,
                 offsetof(gclient_t, endFrameTransient46a4) == 0x46a4);
GAME_STATIC_ASSERT(gclient_nonpvs_friendly_client_offset,
                 offsetof(gclient_t, nonpvsFriendlyClient) == 0x46bc);
GAME_STATIC_ASSERT(gclient_ping_end_time_offset, offsetof(gclient_t, pingEndTime) == 0x46c0);
GAME_STATIC_ASSERT(gclient_nonpvs_tank_client_offset,
                 offsetof(gclient_t, nonpvsTankClient) == 0x46c4);
GAME_STATIC_ASSERT(gclient_weapon_previous_view_angles_offset,
                 offsetof(gclient_t, weaponPreviousViewAngles) == 0x46d4);
GAME_STATIC_ASSERT(gclient_weapon_sway_offsets_offset,
                 offsetof(gclient_t, weaponSwayOffsets) == 0x46e0);
GAME_STATIC_ASSERT(gclient_weapon_sway_angles_offset,
                 offsetof(gclient_t, weaponSwayAngles) == 0x46ec);
GAME_STATIC_ASSERT(gclient_weapon_move_offset_offset,
                 offsetof(gclient_t, weaponMoveOffset) == 0x46f8);
GAME_STATIC_ASSERT(gclient_weapon_idle_scale_offset,
                 offsetof(gclient_t, weaponIdleScale) == 0x4704);
GAME_STATIC_ASSERT(gclient_weapon_recoil_angles_offset,
                 offsetof(gclient_t, weaponRecoilAngles) == 0x4708);
GAME_STATIC_ASSERT(gclient_fire_recoil_velocity_offset,
                 offsetof(gclient_t, fireRecoilVelocity) == 0x4714);
GAME_STATIC_ASSERT(gclient_weapon_recoil_state_offset,
                 offsetof(gclient_t, weaponRecoilState) == 0x471c);
GAME_STATIC_ASSERT(gclient_flame_damage_time_offset, offsetof(gclient_t, flameDamageTime) == 0x4720);
GAME_STATIC_ASSERT(gclient_flame_damage_inflictor_offset,
                 offsetof(gclient_t, flameDamageInflictor) == 0x4724);
GAME_STATIC_ASSERT(gclient_vehicle_collision_time_offset,
                 offsetof(gclient_t, lastCollisionDamageTime) == 0x4728);
GAME_STATIC_ASSERT(gclient_vehicle_prone_damage_time_offset,
                 offsetof(gclient_t, vehicleProneDamageTime) == 0x472c);
GAME_STATIC_ASSERT(gclient_connected_state_offset, offsetof(gclient_t, connectedState) == 0x4520);
GAME_STATIC_ASSERT(gclient_current_buttons_offset, offsetof(gclient_t, currentButtons) == 0x462c);
GAME_STATIC_ASSERT(turret_state_in_use_offset, offsetof(turret_state_t, inUse) == 0x000);
GAME_STATIC_ASSERT(turret_state_flags_offset, offsetof(turret_state_t, flags) == 0x004);
GAME_STATIC_ASSERT(turret_state_fire_time_offset,
                 offsetof(turret_state_t, fireTimeRemaining) == 0x008);
GAME_STATIC_ASSERT(turret_state_top_arc_offset, offsetof(turret_state_t, topArc) == 0x00c);
GAME_STATIC_ASSERT(turret_state_rest_pitch_offset, offsetof(turret_state_t, restPitch) == 0x01c);
GAME_STATIC_ASSERT(turret_state_use_mode_offset, offsetof(turret_state_t, useMode) == 0x020);
GAME_STATIC_ASSERT(turret_state_stop_use_event_type_offset,
                 offsetof(turret_state_t, stopUseEventType) == 0x024);
GAME_STATIC_ASSERT(turret_state_fire_sound_time_offset,
                 offsetof(turret_state_t, fireSoundTime) == 0x028);
GAME_STATIC_ASSERT(turret_state_stop_use_origin_offset,
                 offsetof(turret_state_t, stopUseOrigin) == 0x02c);
GAME_STATIC_ASSERT(turret_state_rest_pitch_clamp_offset,
                 offsetof(turret_state_t, restPitchClamp) == 0x038);
GAME_STATIC_ASSERT(turret_state_sustained_fire_loop_sound_offset,
                 offsetof(turret_state_t, sustainedFireLoopSound) == 0x03c);
GAME_STATIC_ASSERT(turret_state_sustained_fire_stop_sound_offset,
                 offsetof(turret_state_t, sustainedFireStopSound) == 0x03d);
GAME_STATIC_ASSERT(turret_state_heat_offset, offsetof(turret_state_t, heat) == 0x040);
GAME_STATIC_ASSERT(turret_state_size,
                 sizeof(turret_state_t) == 0x48);
GAME_STATIC_ASSERT(gentity_mover_reached_offset, offsetof(gentity_t, moverReached) == 0x214);
GAME_STATIC_ASSERT(gentity_mover_blocked_offset, offsetof(gentity_t, moverBlocked) == 0x218);
GAME_STATIC_ASSERT(gentity_touch_offset, offsetof(gentity_t, touch) == 0x21c);
GAME_STATIC_ASSERT(gentity_use_offset, offsetof(gentity_t, use) == 0x220);
GAME_STATIC_ASSERT(gentity_controller_offset, offsetof(gentity_t, controller) == 0x230);
GAME_STATIC_ASSERT(gentity_s_number_offset, offsetof(gentity_t, s_number) == 0x000);
GAME_STATIC_ASSERT(gentity_s_eType_offset, offsetof(gentity_t, s_eType) == 0x004);
GAME_STATIC_ASSERT(gentity_s_flags_offset, offsetof(gentity_t, s_flags) == 0x008);
GAME_STATIC_ASSERT(gentity_pos_offset, offsetof(gentity_t, pos) == 0x00c);
GAME_STATIC_ASSERT(gentity_apos_offset, offsetof(gentity_t, apos) == 0x030);
GAME_STATIC_ASSERT(gentity_current_origin_offset,
                 offsetof(gentity_t, currentOrigin) == 0x13c);
GAME_STATIC_ASSERT(gentity_current_angles_offset,
                 offsetof(gentity_t, currentAngles) == 0x148);
GAME_STATIC_ASSERT(gentity_pass_entity_num_offset,
                 offsetof(gentity_t, passEntityNum) == 0x154);
GAME_STATIC_ASSERT(gentity_client_offset, offsetof(gentity_t, client) == 0x160);
GAME_STATIC_ASSERT(entity_type_player_corpse_value, ET_PLAYER_CORPSE == 2);
GAME_STATIC_ASSERT(entity_type_turret_value, ET_TURRET == 11);
GAME_STATIC_ASSERT(entity_type_vehicle_value, ET_VEHICLE == 12);
GAME_STATIC_ASSERT(gentity_state_time_offset,
                 offsetof(gentity_t, entityStateTime) == 0x054);
GAME_STATIC_ASSERT(gentity_state_time2_offset,
                 offsetof(gentity_t, entityStateTime2) == 0x058);
GAME_STATIC_ASSERT(gentity_state_angles2_offset,
                 offsetof(gentity_t, entityStateAngles2) == 0x068);
GAME_STATIC_ASSERT(gentity_state_angles2_y_offset,
                 offsetof(gentity_t, entityStateAngles2.vector.y) == 0x06c);
GAME_STATIC_ASSERT(gentity_state_angles2_z_offset,
                 offsetof(gentity_t, entityStateAngles2.vector.z) == 0x070);
GAME_STATIC_ASSERT(gentity_angles2_earthquake_scale_offset,
                 offsetof(gentity_t, entityStateAngles2.earthquake.scale) == 0x068);
GAME_STATIC_ASSERT(gentity_angles2_earthquake_radius_offset,
                 offsetof(gentity_t, entityStateAngles2.earthquake.radius) == 0x06c);
GAME_STATIC_ASSERT(gentity_angles2_earthquake_duration_offset,
                 offsetof(gentity_t, entityStateAngles2.earthquake.durationMs) == 0x070);
GAME_STATIC_ASSERT(gentity_angles2_vehicle_primary_pitch_offset,
                 offsetof(gentity_t, entityStateAngles2.vehicleTurret.primaryPitch) == 0x068);
GAME_STATIC_ASSERT(gentity_angles2_vehicle_primary_yaw_offset,
                 offsetof(gentity_t, entityStateAngles2.vehicleTurret.primaryYaw) == 0x06c);
GAME_STATIC_ASSERT(gentity_angles2_vehicle_gunner_pitch_offset,
                 offsetof(gentity_t, entityStateAngles2.vehicleTurret.gunnerPitch) == 0x070);
GAME_STATIC_ASSERT(gentity_angles2_turret_pitch_offset,
                 offsetof(gentity_t, entityStateAngles2.turret.pitch) == 0x068);
GAME_STATIC_ASSERT(gentity_angles2_turret_yaw_offset,
                 offsetof(gentity_t, entityStateAngles2.turret.yaw) == 0x06c);
GAME_STATIC_ASSERT(gentity_angles2_turret_pitch_carry_offset,
                 offsetof(gentity_t, entityStateAngles2.turret.pitchCarry) == 0x070);
GAME_STATIC_ASSERT(gentity_angles2_looped_fx_cull_distance_offset,
                 offsetof(gentity_t, entityStateAngles2.loopedFx.cullDistance) == 0x068);
GAME_STATIC_ASSERT(gentity_angles2_looped_fx_repeat_delay_offset,
                 offsetof(gentity_t, entityStateAngles2.loopedFx.repeatDelayMs) == 0x06c);
GAME_STATIC_ASSERT(gentity_angles2_clientinfo_lean_amount_offset,
                 offsetof(gentity_t, entityStateAngles2.clientInfo.leanAmount) == 0x06c);
GAME_STATIC_ASSERT(gentity_vehicle_slot_offset, offsetof(gentity_t, vehicleSlot) == 0x078);
GAME_STATIC_ASSERT(gentity_ground_entity_num_offset,
                 offsetof(gentity_t, groundEntityNum) == 0x07c);
GAME_STATIC_ASSERT(gentity_sv_flags_offset, offsetof(gentity_t, svFlags) == 0x0f8);
GAME_STATIC_ASSERT(gentity_contents_offset, offsetof(gentity_t, contents) == 0x104);
GAME_STATIC_ASSERT(gentity_script_contents_offset, offsetof(gentity_t, scriptContents) == 0x120);
GAME_STATIC_ASSERT(gentity_client_spawn_state_byte_offset,
                 offsetof(gentity_t, clientSpawnStateByte) == 0x17b);
GAME_STATIC_ASSERT(gentity_client_spawn_reset_byte_offset,
                 offsetof(gentity_t, clientSpawnResetByte) == 0x17c);
GAME_STATIC_ASSERT(gentity_take_damage_offset,
                 offsetof(gentity_t, takeDamage) == 0x17d);
GAME_STATIC_ASSERT(gentity_active_state_offset,
                 offsetof(gentity_t, activeState) == 0x17e);
GAME_STATIC_ASSERT(gentity_reserved_state_byte_offset,
                 offsetof(gentity_t, reserved_17f) == 0x17f);
GAME_STATIC_ASSERT(gentity_turret_overheat_state_offset,
                 offsetof(gentity_t, turretOverheatState) == 0x0e4);
GAME_STATIC_ASSERT(gentity_dobj_model_index_copy_offset,
                 offsetof(gentity_t, dobjModelIndexCopy) == 0x090);
GAME_STATIC_ASSERT(gentity_constant_light_offset,
                 offsetof(gentity_t, constantLight) == 0x080);
GAME_STATIC_ASSERT(gentity_event_parm_offset,
                 offsetof(gentity_t, eventParm) == 0x088);
GAME_STATIC_ASSERT(gentity_events_offset, offsetof(gentity_t, events) == 0x0ac);
GAME_STATIC_ASSERT(gentity_event_parms_offset, offsetof(gentity_t, eventParms) == 0x0bc);
GAME_STATIC_ASSERT(gentity_entity_state_weapon_offset,
                 offsetof(gentity_t, entityStateWeapon) == 0x0cc);
GAME_STATIC_ASSERT(gentity_hint_string_index_offset,
                 offsetof(gentity_t, hintStringIndex) == 0x0dc);
GAME_STATIC_ASSERT(gentity_state_anim_offset,
                 offsetof(gentity_t, entityStateAnim) == 0x0d0);
GAME_STATIC_ASSERT(gentity_state_anim_legs_offset,
                 offsetof(gentity_t, entityStateAnim.playerAnim.legsAnim) == 0x0d0);
GAME_STATIC_ASSERT(gentity_state_anim_torso_offset,
                 offsetof(gentity_t, entityStateAnim.playerAnim.torsoAnim) == 0x0d4);
GAME_STATIC_ASSERT(gentity_clientinfo_lean_fraction_offset,
                 offsetof(gentity_t, clientInfoLeanFraction) == 0x0d8);
GAME_STATIC_ASSERT(gentity_entity_angles_offset,
                 offsetof(gentity_t, entityAngles) == 0x0e8);
GAME_STATIC_ASSERT(gentity_entity_angles_y_offset,
                 offsetof(gentity_t, entityAngles[1]) == 0x0ec);
GAME_STATIC_ASSERT(gentity_entity_angles_z_offset,
                 offsetof(gentity_t, entityAngles[2]) == 0x0f0);
GAME_STATIC_ASSERT(gentity_vehicle_offset, offsetof(gentity_t, vehicle) == 0x164);
GAME_STATIC_ASSERT(gentity_clipmask_offset, offsetof(gentity_t, clipmask) == 0x1a0);
GAME_STATIC_ASSERT(gentity_ref_offset, offsetof(gentity_t, entityRef) == 0x1a8);
GAME_STATIC_ASSERT(gentity_target_location_next_offset,
                 offsetof(gentity_t, targetLocationNext) == 0x1ac);
GAME_STATIC_ASSERT(gentity_event_time2_offset, offsetof(gentity_t, eventTime2) == 0x158);
GAME_STATIC_ASSERT(gentity_worldspawn_spawnflags_scratch_offset,
                 offsetof(gentity_t, worldspawnSpawnflagsScratch) == 0x15c);
GAME_STATIC_ASSERT(gentity_door_sound_opening_offset,
                 offsetof(gentity_t, doorSoundOpening) == 0x16f);
GAME_STATIC_ASSERT(gentity_linked_offset, offsetof(gentity_t, linked) == 0x16c);
GAME_STATIC_ASSERT(gentity_mover_state_offset, offsetof(gentity_t, moverState) == 0x180);
GAME_STATIC_ASSERT(gentity_model_index_offset, offsetof(gentity_t, modelIndex) == 0x181);
GAME_STATIC_ASSERT(gentity_script_classname_offset,
                 offsetof(gentity_t, scriptClassname) == 0x184);
GAME_STATIC_ASSERT(gentity_spawnflags_offset, offsetof(gentity_t, spawnflags) == 0x188);
GAME_STATIC_ASSERT(gentity_flags_offset, offsetof(gentity_t, flags) == 0x18c);
GAME_STATIC_ASSERT(gentity_last_think_time_offset,
                 offsetof(gentity_t, lastThinkTime) == 0x190);
GAME_STATIC_ASSERT(gentity_skip_type_dispatch_offset,
                 offsetof(gentity_t, skipTypeDispatch) == 0x194);
GAME_STATIC_ASSERT(gentity_unlink_on_timeout_offset,
                 offsetof(gentity_t, unlinkOnTimeout) == 0x198);
GAME_STATIC_ASSERT(gentity_bounce_factor_offset,
                 offsetof(gentity_t, bounceFactor) == 0x19c);
GAME_STATIC_ASSERT(gentity_mover_pos1_offset, offsetof(gentity_t, moverPos1) == 0x1b4);
GAME_STATIC_ASSERT(gentity_mover_pos2_offset, offsetof(gentity_t, moverPos2) == 0x1c0);
GAME_STATIC_ASSERT(gentity_dyna_sink_end_time_offset,
                 offsetof(gentity_t, dynaSinkEndTime) == 0x1dc);
GAME_STATIC_ASSERT(gentity_target_location_message_offset,
                 offsetof(gentity_t, targetLocationMessage) == 0x1d8);
GAME_STATIC_ASSERT(gentity_door_yaw_offset, offsetof(gentity_t, doorYawOffset) == 0x1e0);
GAME_STATIC_ASSERT(gentity_target_offset, offsetof(gentity_t, target) == 0x1e4);
GAME_STATIC_ASSERT(gentity_targetname_offset, offsetof(gentity_t, targetname) == 0x1e6);
GAME_STATIC_ASSERT(gentity_team_name_offset,
                 offsetof(gentity_t, teamName) == 0x1e8);
GAME_STATIC_ASSERT(gentity_max_speed_offset, offsetof(gentity_t, maxSpeed) == 0x1f0);
GAME_STATIC_ASSERT(gentity_door_alt_speed_offset, offsetof(gentity_t, doorAltSpeed) == 0x1f4);
GAME_STATIC_ASSERT(gentity_mover_dir_offset, offsetof(gentity_t, moverDir) == 0x1f8);
GAME_STATIC_ASSERT(gentity_mover_duration_offset,
                 offsetof(gentity_t, moverDuration) == 0x204);
GAME_STATIC_ASSERT(gentity_mover_alt_duration_offset,
                 offsetof(gentity_t, moverAltDuration) == 0x208);
GAME_STATIC_ASSERT(gentity_enemy_scan_radius_offset,
                 offsetof(gentity_t, enemyScanRadius) == 0x280);
GAME_STATIC_ASSERT(gentity_team_chain_offset,
                 offsetof(gentity_t, teamChain) == 0x270);
GAME_STATIC_ASSERT(gentity_team_master_offset,
                 offsetof(gentity_t, teamMaster) == 0x274);
GAME_STATIC_ASSERT(gentity_trigger_activator_offset,
                 offsetof(gentity_t, triggerActivator) == 0x26c);
GAME_STATIC_ASSERT(gentity_concussive_fx_end_time_offset,
                 offsetof(gentity_t, concussiveFxEndTime) == 0x284);
GAME_STATIC_ASSERT(gentity_owner_icon_delay_offset,
                 offsetof(gentity_t, ownerIconDelaySeconds) == 0x28c);
GAME_STATIC_ASSERT(gentity_script_mover_angle_target_offset,
                 offsetof(gentity_t, scriptMoverAngleTarget) == 0x29c);
GAME_STATIC_ASSERT(gentity_item_info_offset, offsetof(gentity_t, itemInfo) == 0x2a8);
GAME_STATIC_ASSERT(gentity_vehicle_primary_yaw_clamp_offset,
                 offsetof(gentity_t, vehiclePrimaryYawClamp) == 0x2bc);
GAME_STATIC_ASSERT(gentity_script_vehicle_primary_pitch_clamp_offset,
                 offsetof(gentity_t, scriptVehiclePrimaryPitchClamp) == 0x2c0);
GAME_STATIC_ASSERT(gentity_mission_level_offset,
                 offsetof(gentity_t, missionLevel) == 0x2c4);
GAME_STATIC_ASSERT(gentity_start_size_offset, offsetof(gentity_t, startSize) == 0x2cc);
GAME_STATIC_ASSERT(gentity_end_size_offset, offsetof(gentity_t, endSize) == 0x2d0);
GAME_STATIC_ASSERT(gentity_spawn_item_offset, offsetof(gentity_t, spawnItem) == 0x2d8);
GAME_STATIC_ASSERT(gentity_script_track_offset,
                 offsetof(gentity_t, scriptTrack) == 0x2ec);
GAME_STATIC_ASSERT(gentity_link_info_offset, offsetof(gentity_t, linkInfo) == 0x2f4);
GAME_STATIC_ASSERT(gentity_vehicle_spawn_name_offset,
                 offsetof(gentity_t, vehicleSpawnName) == 0x314);
GAME_STATIC_ASSERT(gentity_vehicle_primary_disabled_offset,
                 offsetof(gentity_t, vehiclePrimaryDisabled) == 0x318);
GAME_STATIC_ASSERT(gentity_vehicle_owner_offset, offsetof(gentity_t, vehicleOwner) == 0x31c);
GAME_STATIC_ASSERT(gentity_vehicle_reenter_time_offset,
                 offsetof(gentity_t, vehicleReenterTime) == 0x320);
GAME_STATIC_ASSERT(gentity_last_vehicle_entity_num_offset,
                 offsetof(gentity_t, lastVehicleEntityNum) == 0x324);
GAME_STATIC_ASSERT(gentity_next_free_offset, offsetof(gentity_t, nextFree) == 0x328);
GAME_STATIC_ASSERT(gentity_missile_fuse_time_offset,
                 offsetof(gentity_t, missileFuseTime) == 0x32c);
GAME_STATIC_ASSERT(gentity_parent_entity_num_offset,
                 offsetof(gentity_t, parentEntityNum) == 0x330);
GAME_STATIC_ASSERT(gentity_nextthink_offset, offsetof(gentity_t, nextthink) == 0x20c);
GAME_STATIC_ASSERT(gentity_think_offset, offsetof(gentity_t, think) == 0x210);
GAME_STATIC_ASSERT(gentity_die_offset, offsetof(gentity_t, die) == 0x228);
GAME_STATIC_ASSERT(gentity_health_offset, offsetof(gentity_t, health) == 0x240);
GAME_STATIC_ASSERT(gentity_damage_offset, offsetof(gentity_t, damage) == 0x248);
GAME_STATIC_ASSERT(gentity_splash_damage_offset,
                 offsetof(gentity_t, splashDamage) == 0x24c);
GAME_STATIC_ASSERT(gentity_splash_min_damage_offset,
                 offsetof(gentity_t, splashMinDamage) == 0x250);
GAME_STATIC_ASSERT(gentity_splash_radius_offset,
                 offsetof(gentity_t, splashRadius) == 0x254);
GAME_STATIC_ASSERT(gentity_method_of_death_offset,
                 offsetof(gentity_t, methodOfDeath) == 0x258);
GAME_STATIC_ASSERT(gentity_splash_method_of_death_offset,
                 offsetof(gentity_t, splashMethodOfDeath) == 0x25c);
GAME_STATIC_ASSERT(gentity_item_count_offset, offsetof(gentity_t, itemCount) == 0x260);
GAME_STATIC_ASSERT(gentity_dropped_clip_count_offset,
                 offsetof(gentity_t, droppedClipCount) == 0x2dc);
GAME_STATIC_ASSERT(gentity_dobj_dirty_offset, offsetof(gentity_t, dobjDirty) == 0x348);
GAME_STATIC_ASSERT(gentity_size, sizeof(gentity_t) == 0x34cu);
GAME_I386_LAYOUT_ASSERT(gitem_classname_offset, offsetof(gitem_t, classname) == 0x000);
GAME_I386_LAYOUT_ASSERT(gitem_pickup_sound_offset,
                      offsetof(gitem_t, pickupSound) == 0x004);
GAME_I386_LAYOUT_ASSERT(gitem_world_model_offset,
                      offsetof(gitem_t, worldModel) == 0x008);
GAME_I386_LAYOUT_ASSERT(gitem_icon_model_offset,
                      offsetof(gitem_t, iconModel) == 0x00c);
GAME_I386_LAYOUT_ASSERT(gitem_hud_icon_offset,
                      offsetof(gitem_t, hudIcon) == 0x010);
GAME_I386_LAYOUT_ASSERT(gitem_ammo_icon_offset,
                      offsetof(gitem_t, ammoIcon) == 0x014);
GAME_I386_LAYOUT_ASSERT(gitem_pickup_name_offset,
                      offsetof(gitem_t, pickupName) == 0x018);
GAME_I386_LAYOUT_ASSERT(gitem_quantity_offset,
                      offsetof(gitem_t, quantity) == 0x01c);
GAME_I386_LAYOUT_ASSERT(gitem_type_offset, offsetof(gitem_t, type) == 0x020);
GAME_I386_LAYOUT_ASSERT(gitem_weapon_offset, offsetof(gitem_t, weapon) == 0x024);
GAME_I386_LAYOUT_ASSERT(gitem_ammo_index_offset,
                      offsetof(gitem_t, ammoIndex) == 0x028);
GAME_I386_LAYOUT_ASSERT(gitem_clip_index_offset,
                      offsetof(gitem_t, clipIndex) == 0x02c);
GAME_I386_LAYOUT_ASSERT(gitem_size, sizeof(gitem_t) == 0x30u);
GAME_STATIC_ASSERT(pmove_command_offset, offsetof(pmove_t, command) == 0x004);
GAME_STATIC_ASSERT(pmove_command_time_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, commandTime) == 0x004);
GAME_STATIC_ASSERT(pmove_buttons_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, buttons) == 0x008);
GAME_STATIC_ASSERT(pmove_wbuttons_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, wbuttons) == 0x009);
GAME_STATIC_ASSERT(pmove_weapon_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, weapon) == 0x00a);
GAME_STATIC_ASSERT(pmove_usercmd_angles_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, angles) == 0x00c);
GAME_STATIC_ASSERT(pmove_usercmd_angle_yaw_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, angles[1]) == 0x010);
GAME_STATIC_ASSERT(pmove_usercmd_angle_roll_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, angles[2]) == 0x014);
GAME_STATIC_ASSERT(pmove_forwardmove_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, forwardmove) == 0x018);
GAME_STATIC_ASSERT(pmove_rightmove_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, rightmove) == 0x019);
GAME_STATIC_ASSERT(pmove_upmove_offset,
                 offsetof(pmove_t, command) + offsetof(usercmd_t, upmove) == 0x01a);
GAME_STATIC_ASSERT(usercmd_size,
                 sizeof(usercmd_t) == 0x018);
GAME_STATIC_ASSERT(pmove_old_command_offset, offsetof(pmove_t, oldCommand) == 0x01c);
GAME_STATIC_ASSERT(pmove_old_usercmd_angles_offset,
                 offsetof(pmove_t, oldCommand.angles) == 0x024);
GAME_STATIC_ASSERT(pmove_old_forwardmove_offset,
                 offsetof(pmove_t, oldCommand.forwardmove) == 0x030);
GAME_STATIC_ASSERT(pmove_trace_mask_offset, offsetof(pmove_t, traceMask) == 0x034);
GAME_STATIC_ASSERT(pmove_debug_move_offset, offsetof(pmove_t, debugMove) == 0x038);
GAME_STATIC_ASSERT(pmove_view_clamp_target_offset,
                 offsetof(pmove_t, viewClampTargetAngles) == 0x03c);
GAME_STATIC_ASSERT(pmove_view_clamp_delta_offset,
                 offsetof(pmove_t, viewClampMaxDeltas) == 0x048);
GAME_STATIC_ASSERT(pmove_numtouch_offset, offsetof(pmove_t, numtouch) == 0x054);
GAME_STATIC_ASSERT(pmove_impact_entity_nums_offset,
                 offsetof(pmove_t, impactEntityNums) == 0x058);
GAME_STATIC_ASSERT(pmove_impact_entity_nums_size,
                 sizeof(((pmove_t *)0)->impactEntityNums) == 0x080);
GAME_STATIC_ASSERT(pmove_trace_offset, offsetof(pmove_t, trace) == 0x104);
GAME_STATIC_ASSERT(pmove_mins_offset, offsetof(pmove_t, mins) == 0x0d8);
GAME_STATIC_ASSERT(pmove_maxs_offset, offsetof(pmove_t, maxs) == 0x0e4);
GAME_STATIC_ASSERT(pmove_overhead_contents_offset, offsetof(pmove_t, overheadContents) == 0x0f0);
GAME_STATIC_ASSERT(pmove_overhead_level_offset, offsetof(pmove_t, overheadLevel) == 0x0f1);
GAME_STATIC_ASSERT(pmove_horizontal_speed_offset, offsetof(pmove_t, horizontalSpeed) == 0x0f4);
GAME_STATIC_ASSERT(pmove_weapon_animscript_enabled_offset,
                 offsetof(pmove_t, weaponAnimscriptEnabled) == 0x100);
GAME_STATIC_ASSERT(pmove_point_contents_offset, offsetof(pmove_t, pointContents) == 0x110);
GAME_STATIC_ASSERT(pmove_entity_type_offset, offsetof(pmove_t, entityType) == 0x114);
GAME_STATIC_ASSERT(pmove_ads_input_blocked_offset, offsetof(pmove_t, adsInputBlocked) == 0x118);
GAME_STATIC_ASSERT(pmove_size, sizeof(pmove_t) == 0x11c);
GAME_STATIC_ASSERT(weaponInfo_weapon_index_offset, offsetof(weaponInfo_t, weaponIndex) == 0x000);
GAME_STATIC_ASSERT(weaponInfo_pickup_name_offset, offsetof(weaponInfo_t, pickupName) == 0x004);
GAME_STATIC_ASSERT(weaponInfo_display_name_offset, offsetof(weaponInfo_t, displayName) == 0x008);
GAME_STATIC_ASSERT(weaponInfo_hand_model_offset, offsetof(weaponInfo_t, handModel) == 0x014);
GAME_STATIC_ASSERT(weaponInfo_mode_name_offset, offsetof(weaponInfo_t, modeName) == 0x078);
GAME_STATIC_ASSERT(weaponInfo_weaponType_offset, offsetof(weaponInfo_t, weaponType) == 0x07c);
GAME_STATIC_ASSERT(weaponInfo_weaponClass_offset, offsetof(weaponInfo_t, weaponClass) == 0x080);
GAME_STATIC_ASSERT(weaponInfo_slot_offset, offsetof(weaponInfo_t, slot) == 0x084);
GAME_STATIC_ASSERT(weaponInfo_stance_offset,
                 offsetof(weaponInfo_t, stance) == 0x08c);
GAME_STATIC_ASSERT(weaponInfo_ammo_type_offset, offsetof(weaponInfo_t, ammoType) == 0x090);
GAME_STATIC_ASSERT(weaponInfo_pickup_sound_offset, offsetof(weaponInfo_t, pickupSound) == 0x09c);
GAME_STATIC_ASSERT(weaponInfo_turret_loop_sound_offset,
                 offsetof(weaponInfo_t, loopFireSound) == 0x0b0);
GAME_STATIC_ASSERT(weaponInfo_turret_stop_sound_offset,
                 offsetof(weaponInfo_t, stopFireSound) == 0x0b4);
GAME_STATIC_ASSERT(weaponInfo_sprint_move_offset,
                 offsetof(weaponInfo_t, sprintMove) == 0x11c);
GAME_STATIC_ASSERT(weaponInfo_sprint_rot_offset,
                 offsetof(weaponInfo_t, sprintRot) == 0x128);
GAME_STATIC_ASSERT(weaponInfo_stand_move_offset,
                 offsetof(weaponInfo_t, standMove) == 0x134);
GAME_STATIC_ASSERT(weaponInfo_stand_rot_offset,
                 offsetof(weaponInfo_t, standRot) == 0x140);
GAME_STATIC_ASSERT(weaponInfo_ducked_move_offset,
                 offsetof(weaponInfo_t, duckedMove) == 0x158);
GAME_STATIC_ASSERT(weaponInfo_ducked_rot_offset,
                 offsetof(weaponInfo_t, duckedRot) == 0x164);
GAME_STATIC_ASSERT(weaponInfo_prone_move_offset,
                 offsetof(weaponInfo_t, proneMove) == 0x17c);
GAME_STATIC_ASSERT(weaponInfo_prone_rot_offset,
                 offsetof(weaponInfo_t, proneRot) == 0x188);
GAME_STATIC_ASSERT(weaponInfo_pos_move_rate_offset,
                 offsetof(weaponInfo_t, moveSmooth) == 0x194);
GAME_STATIC_ASSERT(weaponInfo_pos_prone_move_rate_offset,
                 offsetof(weaponInfo_t, moveSmoothProne) == 0x198);
GAME_STATIC_ASSERT(weaponInfo_pos_rot_rate_offset,
                 offsetof(weaponInfo_t, posRotRate) == 0x1ac);
GAME_STATIC_ASSERT(weaponInfo_pos_prone_rot_rate_offset,
                 offsetof(weaponInfo_t, posProneRotRate) == 0x1b0);
GAME_STATIC_ASSERT(weaponInfo_sprint_rot_min_speed_offset,
                 offsetof(weaponInfo_t, sprintRotMinSpeed) == 0x1b4);
GAME_STATIC_ASSERT(weaponInfo_script_classname_offset,
                 offsetof(weaponInfo_t, scriptClassname) == 0x1c4);
GAME_STATIC_ASSERT(weaponInfo_pickup_model_offset,
                 offsetof(weaponInfo_t, pickupModel) == 0x1cc);
GAME_STATIC_ASSERT(weaponInfo_hud_icon_offset,
                 offsetof(weaponInfo_t, hudIcon) == 0x1d4);
GAME_STATIC_ASSERT(weaponInfo_mode_icon_offset,
                 offsetof(weaponInfo_t, modeIcon) == 0x1d8);
GAME_STATIC_ASSERT(weaponInfo_ammo_icon_offset, offsetof(weaponInfo_t, ammoIcon) == 0x1dc);
GAME_STATIC_ASSERT(weaponInfo_start_ammo_offset, offsetof(weaponInfo_t, startAmmo) == 0x1e0);
GAME_STATIC_ASSERT(weaponInfo_ammo_name_offset, offsetof(weaponInfo_t, ammoName) == 0x1e4);
GAME_STATIC_ASSERT(weaponInfo_ammo_index_offset, offsetof(weaponInfo_t, ammoIndex) == 0x1e8);
GAME_STATIC_ASSERT(weaponInfo_clip_name_offset, offsetof(weaponInfo_t, clipName) == 0x1ec);
GAME_STATIC_ASSERT(weaponInfo_clip_index_offset, offsetof(weaponInfo_t, clipIndex) == 0x1f0);
GAME_STATIC_ASSERT(weaponInfo_ammo_max_offset, offsetof(weaponInfo_t, maxAmmo) == 0x1f4);
GAME_STATIC_ASSERT(weaponInfo_clip_size_offset, offsetof(weaponInfo_t, clipSize) == 0x1f8);
GAME_STATIC_ASSERT(weaponInfo_shared_ammo_cap_name_offset,
                 offsetof(weaponInfo_t, sharedAmmoCapName) == 0x1fc);
GAME_STATIC_ASSERT(weaponInfo_shared_ammo_cap_size_offset,
                 offsetof(weaponInfo_t, sharedAmmoCap) == 0x204);
GAME_STATIC_ASSERT(weaponInfo_flame_damage_offset,
                 offsetof(weaponInfo_t, flameDamage) == 0x208);
GAME_STATIC_ASSERT(weaponInfo_grenade_touch_damage_enabled_offset,
                 offsetof(weaponInfo_t, grenadeTouchDamageEnabled) == 0x20c);
GAME_STATIC_ASSERT(weaponInfo_damage_falloff_min_damage_percent_offset,
                 offsetof(weaponInfo_t, damageFalloffMinDamagePercent) == 0x210);
GAME_STATIC_ASSERT(weaponInfo_damage_falloff_min_range_offset,
                 offsetof(weaponInfo_t, damageFalloffMinRange) == 0x214);
GAME_STATIC_ASSERT(weaponInfo_damage_falloff_max_range_offset,
                 offsetof(weaponInfo_t, damageFalloffMaxRange) == 0x218);
GAME_STATIC_ASSERT(weaponInfo_melee_damage_offset, offsetof(weaponInfo_t, meleeDamage) == 0x21c);
GAME_STATIC_ASSERT(weaponInfo_fire_delay_offset, offsetof(weaponInfo_t, fireDelay) == 0x224);
GAME_STATIC_ASSERT(weaponInfo_reload_time_offset, offsetof(weaponInfo_t, reloadTime) == 0x240);
GAME_STATIC_ASSERT(weaponInfo_movement_speed_scale_offset, offsetof(weaponInfo_t, moveSpeedScale) == 0x26c);
GAME_STATIC_ASSERT(weaponInfo_ads_sensitivity_offset,
                 offsetof(weaponInfo_t, adsSensitivity) == 0x270);
GAME_STATIC_ASSERT(weaponInfo_ads_zoom_fov_offset,
                 offsetof(weaponInfo_t, adsZoomFov) == 0x274);
GAME_STATIC_ASSERT(weaponInfo_aim_spread_decay_rate_offset,
                 offsetof(weaponInfo_t, aimSpreadDecayRate) == 0x2a8);
GAME_STATIC_ASSERT(weaponInfo_fire_aim_spread_scale_offset,
                 offsetof(weaponInfo_t, fireAimSpreadScale) == 0x2ac);
GAME_STATIC_ASSERT(weaponInfo_overlay_reticle_ads_reduce_gate_offset,
                 offsetof(weaponInfo_t, overlayReticleAdsReduceGate) == 0x284);
GAME_STATIC_ASSERT(weaponInfo_aim_spread_turn_rate_offset,
                 offsetof(weaponInfo_t, aimSpreadTurnRate) == 0x2b0);
GAME_STATIC_ASSERT(weaponInfo_aim_spread_move_add_offset,
                 offsetof(weaponInfo_t, aimSpreadMoveAdd) == 0x2b4);
GAME_STATIC_ASSERT(weaponInfo_aim_spread_crouch_scale_offset,
                 offsetof(weaponInfo_t, aimSpreadCrouchScale) == 0x2b8);
GAME_STATIC_ASSERT(weaponInfo_aim_spread_prone_scale_offset,
                 offsetof(weaponInfo_t, aimSpreadProneScale) == 0x2bc);
GAME_STATIC_ASSERT(weaponInfo_ads_in_time_offset, offsetof(weaponInfo_t, adsInTime) == 0x2c4);
GAME_STATIC_ASSERT(weaponInfo_ads_out_time_offset, offsetof(weaponInfo_t, adsOutTime) == 0x2c8);
GAME_STATIC_ASSERT(weaponInfo_sway_max_angle_offset,
                 offsetof(weaponInfo_t, swayMaxAngle) == 0x2e4);
GAME_STATIC_ASSERT(weaponInfo_sway_lerp_speed_offset,
                 offsetof(weaponInfo_t, swayLerpSpeed) == 0x2e8);
GAME_STATIC_ASSERT(weaponInfo_sway_pitch_scale_offset,
                 offsetof(weaponInfo_t, swayPitchScale) == 0x2ec);
GAME_STATIC_ASSERT(weaponInfo_sway_yaw_scale_offset,
                 offsetof(weaponInfo_t, swayYawScale) == 0x2f0);
GAME_STATIC_ASSERT(weaponInfo_sway_horiz_scale_offset,
                 offsetof(weaponInfo_t, swayHorizScale) == 0x2f4);
GAME_STATIC_ASSERT(weaponInfo_sway_vert_scale_offset,
                 offsetof(weaponInfo_t, swayVertScale) == 0x2f8);
GAME_STATIC_ASSERT(weaponInfo_ads_sway_max_angle_offset,
                 offsetof(weaponInfo_t, adsSwayMaxAngle) == 0x300);
GAME_STATIC_ASSERT(weaponInfo_ads_sway_lerp_speed_offset,
                 offsetof(weaponInfo_t, adsSwayLerpSpeed) == 0x304);
GAME_STATIC_ASSERT(weaponInfo_ads_sway_pitch_scale_offset,
                 offsetof(weaponInfo_t, adsSwayPitchScale) == 0x308);
GAME_STATIC_ASSERT(weaponInfo_ads_sway_yaw_scale_offset,
                 offsetof(weaponInfo_t, adsSwayYawScale) == 0x30c);
GAME_STATIC_ASSERT(weaponInfo_ads_sway_horiz_scale_offset,
                 offsetof(weaponInfo_t, adsSwayHorizScale) == 0x310);
GAME_STATIC_ASSERT(weaponInfo_ads_sway_vert_scale_offset,
                 offsetof(weaponInfo_t, adsSwayVertScale) == 0x314);
GAME_STATIC_ASSERT(weaponInfo_two_handed_offset, offsetof(weaponInfo_t, twoHanded) == 0x318);
GAME_STATIC_ASSERT(weaponInfo_weapon_time_hold_offset, offsetof(weaponInfo_t, weaponTimeHold) == 0x320);
GAME_STATIC_ASSERT(weaponInfo_ads_enabled_offset, offsetof(weaponInfo_t, adsEnabled) == 0x328);
GAME_STATIC_ASSERT(weaponInfo_ads_raise_enabled_offset,
                 offsetof(weaponInfo_t, adsRaiseEnabled) == 0x32c);
GAME_STATIC_ASSERT(weaponInfo_ads_fire_delay_enabled_offset,
                 offsetof(weaponInfo_t, adsFireDelayEnabled) == 0x348);
GAME_STATIC_ASSERT(weaponInfo_kill_icon_offset,
                 offsetof(weaponInfo_t, killIcon) == 0x350);
GAME_STATIC_ASSERT(weaponInfo_alt_weapon_name_offset,
                 offsetof(weaponInfo_t, altWeaponName) == 0x368);
GAME_STATIC_ASSERT(weaponInfo_alt_weapon_offset,
                 offsetof(weaponInfo_t, altWeapon) == 0x36c);
GAME_STATIC_ASSERT(weaponInfo_missile_splash_radius_offset,
                 offsetof(weaponInfo_t, missileSplashRadius) == 0x378);
GAME_STATIC_ASSERT(weaponInfo_missile_splash_damage_offset,
                 offsetof(weaponInfo_t, missileSplashDamage) == 0x37c);
GAME_STATIC_ASSERT(weaponInfo_missile_splash_min_damage_offset,
                 offsetof(weaponInfo_t, missileSplashMinDamage) == 0x380);
GAME_STATIC_ASSERT(weaponInfo_missile_speed_offset,
                 offsetof(weaponInfo_t, missileSpeed) == 0x384);
GAME_STATIC_ASSERT(weaponInfo_missile_vertical_speed_offset,
                 offsetof(weaponInfo_t, missileVerticalSpeed) == 0x388);
GAME_STATIC_ASSERT(weaponInfo_clip_model_offset,
                 offsetof(weaponInfo_t, clipModel) == 0x38c);
GAME_STATIC_ASSERT(weaponInfo_projectile_explosion_type_offset,
                 offsetof(weaponInfo_t, projectileExplosionType) == 0x390);
GAME_STATIC_ASSERT(weaponInfo_projectile_explosion_effect_offset,
                 offsetof(weaponInfo_t, projectileExplosionEffect) == 0x394);
GAME_STATIC_ASSERT(weaponInfo_projectile_trail_effect_offset,
                 offsetof(weaponInfo_t, projectileTrailEffect) == 0x3b4);
GAME_STATIC_ASSERT(weaponInfo_artillery_barrage_count_offset,
                 offsetof(weaponInfo_t, artilleryBarrageCount) == 0x3a0);
GAME_STATIC_ASSERT(weaponInfo_artillery_barrage_spread_offset,
                 offsetof(weaponInfo_t, artilleryBarrageSpread) == 0x3a4);
GAME_STATIC_ASSERT(weaponInfo_artillery_barrage_first_delay_offset,
                 offsetof(weaponInfo_t, artilleryBarrageFirstDelay) == 0x3a8);
GAME_STATIC_ASSERT(weaponInfo_artillery_barrage_delay_min_offset,
                 offsetof(weaponInfo_t, artilleryBarrageDelayMin) == 0x3ac);
GAME_STATIC_ASSERT(weaponInfo_artillery_barrage_delay_max_offset,
                 offsetof(weaponInfo_t, artilleryBarrageDelayMax) == 0x3b0);
GAME_STATIC_ASSERT(weaponInfo_reload_loop_time_offset,
                 offsetof(weaponInfo_t, reloadLoopTime) == 0x460);
GAME_STATIC_ASSERT(weaponInfo_ai_effective_range_offset,
                 offsetof(weaponInfo_t, aiEffectiveRange) == 0x458);
GAME_STATIC_ASSERT(weaponInfo_ai_miss_range_offset,
                 offsetof(weaponInfo_t, aiMissRange) == 0x45c);
GAME_STATIC_ASSERT(weaponInfo_turret_left_arc_offset,
                 offsetof(weaponInfo_t, turretLeftArcDefault) == 0x468);
GAME_STATIC_ASSERT(weaponInfo_turret_right_arc_offset,
                 offsetof(weaponInfo_t, turretRightArcDefault) == 0x46c);
GAME_STATIC_ASSERT(weaponInfo_turret_top_arc_offset,
                 offsetof(weaponInfo_t, turretTopArcDefault) == 0x470);
GAME_STATIC_ASSERT(weaponInfo_turret_bottom_arc_offset,
                 offsetof(weaponInfo_t, turretBottomArcDefault) == 0x474);
GAME_STATIC_ASSERT(weaponInfo_turret_pitch_rate_offset,
                 offsetof(weaponInfo_t, turretPitchRate) == 0x47c);
GAME_STATIC_ASSERT(weaponInfo_turret_yaw_rate_offset,
                 offsetof(weaponInfo_t, turretYawRate) == 0x480);
GAME_STATIC_ASSERT(weaponInfo_turret_anim_horizontal_rotate_increment_offset,
                 offsetof(weaponInfo_t, animHorRotateInc) == 0x48c);
GAME_STATIC_ASSERT(weaponInfo_turret_player_spacing_offset,
                 offsetof(weaponInfo_t, turretPlayerSpacing) == 0x490);
GAME_STATIC_ASSERT(weaponInfo_hint_string_offset,
                 offsetof(weaponInfo_t, hintString) == 0x494);
GAME_STATIC_ASSERT(weaponInfo_hint_string_index_offset,
                 offsetof(weaponInfo_t, hintStringIndex) == 0x498);
GAME_STATIC_ASSERT(weaponInfo_turret_heat_per_shot_offset,
                 offsetof(weaponInfo_t, turretHeatPerShot) == 0x49c);
GAME_STATIC_ASSERT(weaponInfo_turret_heat_decay_offset,
                 offsetof(weaponInfo_t, turretHeatDecay) == 0x4a0);
GAME_STATIC_ASSERT(weaponInfo_horizontal_view_jitter_offset,
                 offsetof(weaponInfo_t, horizViewJitter) == 0x4a4);
GAME_STATIC_ASSERT(weaponInfo_vertical_view_jitter_offset,
                 offsetof(weaponInfo_t, vertViewJitter) == 0x4a8);
GAME_STATIC_ASSERT(weaponInfo_grenade_splash_vehicle_damage_scale_offset,
                 offsetof(weaponInfo_t, grenadeSplashVehicleDamageScale) == 0x4ac);
GAME_STATIC_ASSERT(weaponInfo_script_offset, offsetof(weaponInfo_t, script) == 0x4b0);
GAME_STATIC_ASSERT(weaponInfo_adsFireDelayRate_offset, offsetof(weaponInfo_t, adsFireDelayRate) == 0x4b4);
GAME_STATIC_ASSERT(weaponInfo_adsFireDelayOutRate_offset, offsetof(weaponInfo_t, adsFireDelayOutRate) == 0x4b8);
#endif

/* Player-state movement flags */
#define PMF_DUCKED         0x00000001   /* Player is crouching */
#define PMF_JUMP_HELD      0x00000002   /* Jump button is held */
#define PMF_BACKWARDS_RUN  0x00000004   /* Running backwards */
#define PMF_TIME_LAND      0x00000008   /* Landing animation in progress */
#define PMF_TIME_KNOCKBACK 0x00000010   /* Knockback in progress */
#define PMF_RESPAWNED      0x00000020   /* Just respawned this frame */
#define PMF_LADDER         0x00000040   /* On ladder */
#define PMF_NOCLIP         0x00000080   /* Noclip mode */
#define PMF_TIME_WALLJUMP  0x00000100   /* Wall jump in progress */
#define PMF_PRONE          0x00000200   /* Player is prone */
#define PMF_CROUCH         0x00000400   /* Player is crouching */
#define PMF_SPRINT         0x00000800   /* Player is sprinting */
#define PMF_FROZEN         0x00001000   /* Movement frozen */
#define PMF_INTERMISSION   0x00002000   /* In intermission */
#define PMF_FOLLOW         0x00004000   /* Spectating/following */
#define PMF_TIME_LOAD      0x00008000   /* Load weapon animation */
#define PMF_FIRE_HELD      0x00010000   /* Fire button held */
#define PMF_RELOAD_HELD    0x00020000   /* Reload button held */
#define PMF_MELEE_HELD     0x00040000   /* Melee button held */
#define PMF_ADS_HELD       0x00080000   /* Aim down sights held */
#define PMF_LEAN_LEFT      0x00100000   /* Leaning left */
#define PMF_LEAN_RIGHT     0x00200000   /* Leaning right */
#define PMF_LEAN_HELD      0x00400000   /* Lean button held */
#define PMF_PRONE_TRANS    0x00800000   /* Prone transition */
#define PMF_CROUCH_TRANS   0x01000000   /* Crouch transition */
#define PMF_STAND_TRANS    0x02000000   /* Stand transition */
#define PMF_SPRINT_TRANS   0x04000000   /* Sprint transition */
#define PMF_VEHICLE_COLLISION 0x08000000 /* Vehicle collision knockback */

extern gentity_t g_entities[MAX_GENTITIES];
extern gclient_t g_clients[MAX_CLIENTS];

gentity_t *script_object_to_gentity(uint32_t scriptObject);
gentity_t *script_object_to_player(uint32_t scriptObject);

#endif
