Description of the immutable structs, the structs in q_shared.h that may not be changed by a game module, and some of its related constants.
blurb
/* paste source text here */
This data type is included in trace_t, representing information about a collision against/into a surface (such as a wall). Presumably the detection code is hand-written in assembly for maximum speed. The prefixing "c" reflects the "C version" of this datatype, whereas the "assembly version" may not have a similar definition (perhaps offsets are all hand-coded?).
// plane_t structure // !!! if this is changed, it must be changed in asm code too !!! typedef struct cplane_s { vec3_t normal; float dist; byte type; // for fast side tests: 0,1,2 = axial, 3 = nonaxial byte signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision byte pad[2]; } cplane_t;
This is the data type returned by trap_Trace(). The contained information assists in determining collisions.
// a trace is returned when a box is swept through the world typedef struct { qboolean allsolid; // if true, plane is not valid qboolean startsolid; // if true, the initial point was in a solid area float fraction; // time completed, 1.0 = didn't hit anything vec3_t endpos; // final position cplane_t plane; // surface normal at impact, transformed to world space int surfaceFlags; // surface hit int contents; // contents on other side of surface hit int entityNum; // entity the contacted sirface is a part of } trace_t;
These sets of values are bitmasks indicating a distinct game surface attribute. Trace collisions detected by trap_Trace() determine the surface attributes where the collision ends. The game module may respond to each distinct surface type. XXX: don't know about adding new SURF constants
#define SURF_NODAMAGE 0x1 // never give falling damage #define SURF_SLICK 0x2 // effects game physics #define SURF_SKY 0x4 // lighting from environment map #define SURF_LADDER 0x8 #define SURF_NOIMPACT 0x10 // don't make missile explosions #define SURF_NOMARKS 0x20 // don't leave missile marks #define SURF_FLESH 0x40 // make flesh sounds and effects #define SURF_NODRAW 0x80 // don't generate a drawsurface at all #define SURF_HINT 0x100 // make a primary bsp splitter #define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes #define SURF_NOLIGHTMAP 0x400 // surface doesn't need a lightmap #define SURF_POINTLIGHT 0x800 // generate lighting info at vertexes #define SURF_METALSTEPS 0x1000 // clanking footsteps #define SURF_NOSTEPS 0x2000 // no footstep sounds #define SURF_NONSOLID 0x4000 // don't collide against curves with this set #define SURF_LIGHTFILTER 0x8000 // act as a light filter during q3map -light #define SURF_ALPHASHADOW 0x10000 // do per-pixel light shadow casting in q3map #define SURF_NODLIGHT 0x20000 // don't dlight even if solid (solid lava, skies) #define SURF_DUST 0x40000 // leave a dust trail when walking on this surface
These constants indicate attributes for the "insides" or "volume" of a model (map, player, entity), such as a trigger. In contrast, the SURF_* constants describe the faces (surface) of a model. XXX: significance in bounding boxes?
#define CONTENTS_SOLID 1 // an eye is never valid in a solid #define CONTENTS_LAVA 8 #define CONTENTS_SLIME 16 #define CONTENTS_WATER 32 #define CONTENTS_FOG 64 #define CONTENTS_AREAPORTAL 0x8000 #define CONTENTS_PLAYERCLIP 0x10000 #define CONTENTS_MONSTERCLIP 0x20000 //bot specific contents types #define CONTENTS_TELEPORTER 0x40000 #define CONTENTS_JUMPPAD 0x80000 #define CONTENTS_CLUSTERPORTAL 0x100000 #define CONTENTS_DONOTENTER 0x200000 #define CONTENTS_BOTCLIP 0x400000 #define CONTENTS_MOVER 0x800000 #define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity #define CONTENTS_BODY 0x2000000 // should never be on a brush, only in game #define CONTENTS_CORPSE 0x4000000 #define CONTENTS_DETAIL 0x8000000 // brushes not used for the bsp #define CONTENTS_STRUCTURAL 0x10000000 // brushes used for the bsp #define CONTENTS_TRANSLUCENT 0x20000000 // don't consume surface fragments inside #define CONTENTS_TRIGGER 0x40000000 #define CONTENTS_NODROP 0x80000000 // don't leave bodies or items (death fog, lava)
One copy of this data type resides on the client side for client purposes, and another copy resides on the server for the "true" data. This data type is transmitted over network to a player describing his/her/its state according to the server, that is, the player's "actual state". No other player receives the playerState_t of another player. The server constantly sends these playerState_t packets to their respective players. In a network multiplayer game, the nature of the network introduces delays (ping lag) in the packets. As a result, the client side may utilize movement prediction upon its local copy of the playerState_t information to present a smoother view to the gamer, while waiting for the "true" server's information to arrive. When the server's packet arrives, the client game then attempts to resolve the predicted playerState_t information with the received server's playerState_t information.
typedef struct playerState_s { int commandTime; // cmd->serverTime of last executed command int pm_type; int bobCycle; // for view bobbing and footstep generation int pm_flags; // ducked, jump_held, etc int pm_time; vec3_t origin; vec3_t velocity; int weaponTime; int gravity; int speed; int delta_angles[3]; // add to command angles to get view direction // changed by spawns, rotating objects, and teleporters int groundEntityNum;// ENTITYNUM_NONE = in air int legsTimer; // don't change low priority animations until this runs out int legsAnim; // mask off ANIM_TOGGLEBIT int torsoTimer; // don't change low priority animations until this runs out int torsoAnim; // mask off ANIM_TOGGLEBIT int movementDir; // a number 0 to 7 that represents the reletive angle // of movement to the view angle (axial and diagonals) // when at rest, the value will remain unchanged // used to twist the legs during strafing vec3_t grapplePoint; // location of grapple to pull towards if PMF_GRAPPLE_PULL int eFlags; // copied to entityState_t->eFlags int eventSequence; // pmove generated events int events[MAX_PS_EVENTS]; int eventParms[MAX_PS_EVENTS]; int externalEvent; // events set on player from another source int externalEventParm; int externalEventTime; int clientNum; // ranges from 0 to MAX_CLIENTS-1 int weapon; // copied to entityState_t->weapon int weaponstate; vec3_t viewangles; // for fixed views int viewheight; // damage feedback int damageEvent; // when it changes, latch the other parms int damageYaw; int damagePitch; int damageCount; int stats[MAX_STATS]; int persistant[MAX_PERSISTANT]; // stats that aren't cleared on deat h int powerups[MAX_POWERUPS]; // level.time that the powerup runs out int ammo[MAX_WEAPONS]; int generic1; int loopSound; int jumppad_ent; // jumppad entity hit this frame // not communicated over the net at all int ping; // server to game info for scoreboard int pmove_framecount; // FIXME: don't transmit over the network int jumppad_frame; int entityEventSequence; } playerState_t;
Predictable movement types. Determines what types of movements are allowed and how to react to user movement input. Constants listed for context for playerState_t.pm_type.
typedef enum { PM_NORMAL, // can accelerate and turn PM_NOCLIP, // noclip movement PM_SPECTATOR, // still run into walls PM_DEAD, // no acceleration or turning, but free falling PM_FREEZE, // stuck in place with no control PM_INTERMISSION, // no movement or status bar PM_SPINTERMISSION // no movement or status bar } pmtype_t;
Predictable movement flags. Various bitmasks to indicate additional movement prediction parameters. Listed here for context for playerState_t.pm_flags.
// pmove->pm_flags #define PMF_DUCKED 0x0001 //1 #define PMF_JUMP_HELD 0x0002 //2 // 0x0004 //4 #define PMF_BACKWARDS_JUMP 0x0008 //8 // go into backwards land #define PMF_BACKWARDS_RUN 0x0010 //16 // coast down to backwards run #define PMF_TIME_LAND 0x0020 //32 // pm_time is time before rejump #define PMF_TIME_KNOCKBACK 0x0040 //64 // pm_time is an air-accelerate only time // 0x0080 //128 #define PMF_TIME_WATERJUMP 0x0100 //256 // pm_time is waterjump #define PMF_RESPAWNED 0x0200 //512 // clear after attack and jump buttons come up #define PMF_USE_ITEM_HELD 0x0400 //1024 #define PMF_GRAPPLE_PULL 0x0800 //2048 // pull towards grapple location #define PMF_FOLLOW 0x1000 //4096 // spectate following another player #define PMF_SCOREBOARD 0x2000 //8192 // spectate as a scoreboard #define PMF_INVULEXPAND 0x4000 //16384 // invulnerability sphere set to full size #define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK)
Array of 16 elements. Each array element has a unique game module-defined meaning. Also, only the low 16 bits of each element is transmitted over network. (XXX: expanded to 32 bits since 1.31?)
Elements typically hold values the pertain to one particular life (i.e. until player is fragged). The game module zeroes out the entire stats[] array at each respawn (this action can be modified in the game module).
// player_state->stats[] indexes // NOTE: may not have more than 16 typedef enum { STAT_HEALTH, STAT_HOLDABLE_ITEM, #ifdef MISSIONPACK STAT_PERSISTANT_POWERUP, #endif STAT_WEAPONS, // 16 bit fields STAT_ARMOR, STAT_DEAD_YAW, // look this direction when dead (FIXME: get rid of?) STAT_CLIENTS_READY, // bit mask of clients wishing to exit the i ntermission (FIXME: configstring?) STAT_MAX_HEALTH // health / armor limit, changable by handic ap } statIndex_t;
Values for holdable items for STAT_HOLDABLE_ITEM element of playerState_t.stats[MAX_STATS] field of playerState_t. Holdable items are items a player may carry and optionally use (baseq3 uses +button2 to indicate item use).
typedef enum { HI_NONE, HI_TELEPORTER, HI_MEDKIT, HI_KAMIKAZE, HI_PORTAL, HI_INVULNERABILITY, HI_NUM_HOLDABLE } holdable_t;
Array of 16 elements holding data that persists across deaths. Of particular note, baseq3 already uses 15 elements, leaving only one unused element for a mod. Still, the mod may change the purpose of any element except the first.
// player_state->persistant[] indexes // these fields are the only part of player_state that isn't // cleared on respawn // NOTE: may not have more than 16 typedef enum { PERS_SCORE, // !!! MUST NOT CHANGE, SERVER AND GAME BOTH REFERENCE !!! PERS_HITS, // total points damage inflicted so damage beeps can sound on change PERS_RANK, // player rank or team rank PERS_TEAM, // player team PERS_SPAWN_COUNT, // incremented every respawn PERS_PLAYEREVENTS, // 16 bits that can be flipped for events PERS_ATTACKER, // clientnum of last damage inflicter PERS_ATTACKEE_ARMOR, // health/armor of last person we attacked PERS_KILLED, // count of the number of times you died // player awards tracking PERS_IMPRESSIVE_COUNT, // two railgun hits in a row PERS_EXCELLENT_COUNT, // two successive kills in a short amount of time PERS_DEFEND_COUNT, // defend awards PERS_ASSIST_COUNT, // assist awards PERS_GAUNTLET_FRAG_COUNT, // kills with the guantlet PERS_CAPTURES // captures } persEnum_t;
Values for powerup items for playerState_t.powerups[MAX_POWERUPS] field of playerState_t. Powerups are effective for a limited time, and may be dropped (such as due to fragging) with a partial timer value left.
// NOTE: may not have more than 16 typedef enum { PW_NONE, PW_QUAD, PW_BATTLESUIT, PW_HASTE, PW_INVIS, PW_REGEN, PW_FLIGHT, PW_REDFLAG, PW_BLUEFLAG, PW_NEUTRALFLAG, PW_SCOUT, PW_GUARD, PW_DOUBLER, PW_AMMOREGEN, PW_INVULNERABILITY, PW_NUM_POWERUPS } powerup_t;
These values indicate a weapon. The same values are also used as the index into playerState_t.ammo[MAX_WEAPONS] for the weapon's corresponding ammo count.
typedef enum { WP_NONE, WP_GAUNTLET, WP_MACHINEGUN, WP_SHOTGUN, WP_GRENADE_LAUNCHER, WP_ROCKET_LAUNCHER, WP_LIGHTNING, WP_RAILGUN, WP_PLASMAGUN, WP_BFG, WP_GRAPPLING_HOOK, #ifdef MISSIONPACK WP_NAILGUN, WP_PROX_LAUNCHER, WP_CHAINGUN, #endif WP_NUM_WEAPONS } weapon_t;
If you can imagine trying to compress the gamer's input into a simplified arcade joystick interface, you would have a good idea what usercmd_t is about. The usercmd_t packets travel only from client to server, and is the means by which the server determines the will of the player's avatar in the server's notion of the world. The size of usercmd_t is notably small. This helps to reduce the impact of ping lag, and also helps reduces the total amount of incoming network traffic for the server (all connected clients are sending a usercmd_t).
The construction and transmission of the usercmd_t data occurs inside the client-side Q3 engine, meaning the cgame module cannot directly fabricate the data. The cgame module may still indirectly alter the usercmd_t data by using the various game commands (e.g. "+forward", "+attack", "-gesture"), via trap_SendConsoleCommand().
// usercmd_t is sent to the server each client frame typedef struct usercmd_s { int serverTime; int angles[3]; int buttons; byte weapon; // weapon signed char forwardmove, rightmove, upmove; } usercmd_t;
This data type holds information related to recording the movement of an entity as well as calculating the near-future position (prediction) of the entity. A "trajectory model" is selected, and the parameters to the model recorded in the struct.
typedef struct { trType_t trType; int trTime; int trDuration; // if non 0, trTime + trDuration = stop time vec3_t trBase; vec3_t trDelta; // velocity, etc } trajectory_t;
Set of constants describing a trajectory model (predictable path). Most entities follow a movement pattern that is mostly predictable, until it collides with another entity. Even then, the effects of the collision tends to remain predictable (it explodes, it bounces, it stops, etc.). The server tells the client what movement pattern, or "trajectory model", an entity is using, so that the client can make educated predictions.
typedef enum { TR_STATIONARY, TR_INTERPOLATE, // non-parametric, but interpolate between snapshots TR_LINEAR, TR_LINEAR_STOP, TR_SINE, // value = base + sin( time / duration ) * delta TR_GRAVITY } trType_t;
All entities in the game has an associated entityState_t data. While the game may have up to MAX_GENTITIES (1024) of such data records, each client only receives the entityState_t information of entities within its PVS (Potential Visibility Set), as determined by the Q3 engine. Any client may receive the entityState_t information of any entity, including itself. This receiving is in contrast to playerState_t information, which is only sent to its respective client.
While the comments in the source say structure size does not matter, any changes to this struct in the game module source will have no effect unless the same changes are made in the Q3 engine source. As of the time of this writing, only a select few in the world have such access.
// entityState_t is the information conveyed from the server // in an update message about entities that the client will // need to render in some way // Different eTypes may use the information in different ways // The messages are delta compressed, so it doesn't really matter if // the structure size is fairly large typedef struct entityState_s { int number; // entity index int eType; // entityType_t int eFlags; trajectory_t pos; // for calculating position trajectory_t apos; // for calculating angles int time; int time2; vec3_t origin; vec3_t origin2; vec3_t angles; vec3_t angles2; int otherEntityNum; // shotgun sources, etc int otherEntityNum2; int groundEntityNum; // -1 = in air int constantLight; // r + (g<<8) + (b<<16) + (intensity<<24) int loopSound; // constantly loop this sound int modelindex; int modelindex2; int clientNum; // 0 to (MAX_CLIENTS - 1), for players and corpses int frame; int solid; // for client side prediction, trap_linkentity sets this properly int event; // impulse events -- muzzle flashes, footsteps, etc int eventParm; // for players int powerups; // bit flags int weapon; // determines weapon and flash model, etc int legsAnim; // mask off ANIM_TOGGLEBIT int torsoAnim; // mask off ANIM_TOGGLEBIT int generic1; } entityState_t;
Entity type code. By using such a code, the server assists the client to prepare for rendering. Also, the various fields of entityState_t may take on different meanings for each entity type, which allows for a very hackish form of inherited objects. Or a very complicated union.
These constants are actually defined in bg_public.h, and so the game module may redefine these constants without restriction. The values from baseq3 are presented here to provide a context to entityState_t.eType.
typedef enum { ET_GENERAL, ET_PLAYER, ET_ITEM, ET_MISSILE, ET_MOVER, ET_BEAM, ET_PORTAL, ET_SPEAKER, ET_PUSH_TRIGGER, ET_TELEPORT_TRIGGER, ET_INVISIBLE, ET_GRAPPLE, // grapple hooked on wall ET_TEAM, ET_EVENTS // any of the EV_* events can be added freestanding // by setting eType to ET_EVENTS + eventNum // this avoids having to set eFlags and eventNum } entityType_t;
Entity Flags -- various bitmask flags for an entity. As with entityType_t, these constants are also defined in bg_public.h, and are as redefinable. Placed here for contextual reference to entityState_t.eFlags.
#define EF_DEAD 0x00000001 // don't draw a foe marker over players with EF_DEAD #ifdef MISSIONPACK #define EF_TICKING 0x00000002 // used to make players play the prox mine ticking sound #endif #define EF_TELEPORT_BIT 0x00000004 // toggled every time the origin abruptly changes #define EF_AWARD_EXCELLENT 0x00000008 // draw an excellent sprite #define EF_BOUNCE 0x00000010 // for missiles #define EF_BOUNCE_HALF 0x00000020 // for missiles #define EF_AWARD_GAUNTLET 0x00000040 // draw a gauntlet sprite #define EF_NODRAW 0x00000080 // may have an event, but no model (unspawned items) #define EF_FIRING 0x00000100 // for lightning gun #define EF_KAMIKAZE 0x00000200 #define EF_MOVER_STOP 0x00000400 // will push otherwise #define EF_AWARD_CAP 0x00000800 // draw the capture sprite #define EF_TALK 0x00001000 // draw a talk balloon #define EF_CONNECTION 0x00002000 // draw a connection trouble sprite #define EF_VOTED 0x00004000 // already cast a vote #define EF_AWARD_IMPRESSIVE 0x00008000 // draw an impressive sprite #define EF_AWARD_DEFEND 0x00010000 // draw a defend sprite #define EF_AWARD_ASSIST 0x00020000 // draw a assist sprite #define EF_AWARD_DENIED 0x00040000 // denied #define EF_TEAMVOTED 0x00080000 // already cast a team vote
The entityShared_t struct is not transmitted over network. Still, it is memory space shared by the Q3 engine and game module for certain non-network activity that both the engine and the game module need simultaneous access. One such example is collision detection with trap_Trace(). While the trap's code/contents/meat resides in the Q3 engine, information such as location and sizes of entities need to be available for reading and writing to both the Q3 engine (to detect collisions) and the game module (to move entities around). The entityShared_t struct fills this role of shared memory, while not being network-active.
Though the struct exists in VM memory, the Q3 engine has free reign of reading and writing these fields. Put another way, the values of these fields may at times appear to change "magically". A suitable analogy is I/O ports in systems programming.
typedef struct { entityState_t s; // communicated by server to clients qboolean linked; // qfalse if not in any good cluster int linkcount; int svFlags; // SVF_NOCLIENT, SVF_BROADCAST, etc int singleClient; // only send to this client when SVF_SINGLECLIENT is set qboolean bmodel; // if false, assume an explicit mins / maxs bounding box // only set by trap_SetBrushModel vec3_t mins, maxs; int contents; // CONTENTS_TRIGGER, CONTENTS_SOLID, CONTENTS_BODY, etc // a non-solid entity should set to 0 vec3_t absmin, absmax; // derived from mins/maxs and origin + rotation // currentOrigin will be used for all collision detection and world linking. // it will not necessarily be the same as the trajectory evaluation for the current // time, because each entity must be moved one at a time after time is advanced // to avoid simultanious collision issues vec3_t currentOrigin; vec3_t currentAngles; // when a trace call is made and passEntityNum != ENTITYNUM_NONE, // an ent will be excluded from testing if: // ent->s.number == passEntityNum (don't interact with self) // ent->s.ownerNum = passEntityNum (don't interact with your own missiles) // entity[ent->s.ownerNum].ownerNum = passEntityNum (don't interact with other missiles from owner) int ownerNum; } entityShared_t;
The PVS (Potential Visibility Set) of a location can be thought of as the set of entityState_t updates to properly predict events and entities within view from that location. The server flags fiddle with the set of entityState_t update information.
/ entity->svFlags // the server does not know how to interpret most of the values // in entityStates (level eType), so the game must explicitly flag // special server behaviors #define SVF_NOCLIENT 0x00000001 // don't send entity to clients, even if it has effects #define SVF_BOT 0x00000008 // set if the entity is a bot #define SVF_BROADCAST 0x00000020 // send to all connected clients #define SVF_PORTAL 0x00000040 // merge a second pvs at origin2 into snapshots #define SVF_USE_CURRENT_ORIGIN 0x00000080 // entity->r.currentOrigin instead of entity->s.origin // for link position (missiles and movers) #define SVF_SINGLECLIENT 0x00000100 // only send to a single client
TODO: table of structs, their fields, and modability.
Created 2002.09.14.
Updated 2002.09.20 - plane information (djbob).
Updated 2003.11.10 - massive inject from cyrri.
Updated 2004.07.24 - spelling corrections, fixed syntax errors, grammar adjustments, more cross-reference links, added TOC.
Updated 2011.07.11 - change of contact e-mail.