6. Quake-C Entity Definition

Part of this information is derived from the DEM file specs 1.0.2 by Uwe Girlich.

In Quake, monsters, players, items, and the level itself are all entities. There are three kind of entities, and you will all encounter them in Quake-C code.

6.1 Types of entities

Static entities

A static entity doesn't interact with the rest of the game. These are flames (progs/flame.mdl), lights, illusionary objects, and the like. It is never be necessary to reference such an entity, so they don't get an entity reference number.

A static entity will be created by the function:

makestatic()
(it causes a spawnstatic message to be sent to every client).
A static entity cannot be removed, once created.

The maximum number of static entities is 127.

Temporary entities

A temporary entity is a short life time entity. For instance, Quake uses these entities for hits on the wall (point-like entities) or for the Thunderbolt flash (line-like entities), gun shots, and anything that is not supposed to last more than one frame.

A temporary entity will be created by sending a valid temporary entity message.
A temporary entity need not be removed, it disapears by itself.

Dynamic entities

A dynamic entity is anything which changes its behaviour or its appearance. These are ammunition boxes, spinning armors, player models and the like.

A dynamic entity will be created by the sequence:

entity = spawn();
setmodel( entity, "progs/entity.mdl" );
setsize( entity, vector_min, vector_max);      
setorigin( entity, position );      
It will have to be removed by the function:
remove( entity );

The maximum number of dynamic entities is 449.

6.2 Definition of entity fields

These are the fields that are available in the entity objects (like self, other). Beware that this is not true object oriented programming: there is no protection when accessing those fields, and no guaranty on the validity of values. So if you put garbage there you will probably crash the game.

You can add custom fields (for instance, to store the ammo count of a new weapon you created) but those fields must not be situated among thoses that are common between Quake-C and Quake.exe. Otherwise, Quake.exe would have to be re-compiled. So those fields must be situated after the fake variable called end_sys_fields, in the field definitions.

Fields shared between Quake.exe and Quake-C

These fields describe the most common entity fields. They are shared between the C code of Quake.exe, and the Quake-C code of PROGS.DAT.

Some of the fields are managed by the C code: you can read their value, but YOU SHOULD NEVER MODIFY THEIR VALUE DIRECTLY (there are special built-in functions for that).

Please only modify those fields that are indicated in boldface.

Technical data

entity  chain;                 // next entity, in a chain list of entities
float   ltime;                 // local time for entity
float   teleport_time;         // to avoid backing up
float   spawnflags;            // see possible values. 

Appearance of entity

float   modelindex;            // index of model, in the precached list
string  classname;             // spawn function

string  model;
The name of the file that contains the entity model.

float   frame; 
This is the index of the currently displayed model frame. Frames must be defined by a $frame construct in the model file, and manipulated in the code as $xxx (where xxx is the name of the frame).

float   skin;
This is the index of the model skin currently displayed. If your model has more than one skin defined, then this value indicates the skin in use. You can change it freely, as long as it remains in a valid range. For instance, it's used by the armor model to show the yellow, red or green skin.

float   effects;
This is a flag that defines the special light effects that the entity is subject to. This can supposedly be used to make an entity glow, or to create a glowing field of dots around it.

Position in 3D

 
vector  origin;                 // position of model
    //  origin_x, origin_y, origin_z
vector  mins;                   // bounding box extents reletive to origin
    //  mins_x, mins_y, mins_z
vector  maxs;                   // bounding box extents reletive to origin
    //  maxs_x, maxs_y, maxs_z
vector  size;                   // maxs - mins
    //  size_x,size_y,size_z
vector  absmin;                 // origin + mins and maxs
    //  absmin_x absmin_y absmin_z
vector  absmax;                 // origin + mins and maxs
    //  absmax_x absmax_y absmax_z
vector  oldorigin;              // old position
vector  angles;                 // = 'pitch_angle yaw_angle flip_angle'

Quirks: setting the angles on a player entity doesn't work.

Situation of the entity

float   waterlevel;             // 0 = not in water, 1 = feet, 2 = waist, 3 = eyes
float   watertype;              // a content value
entity  groundentity;           // indicates that the entity moves on the ground

Since groundentity is used nowhere in progs, it's meaning is just a wild guess from a similar field in messages.

Movement in 3D

vector  velocity;               // = 'speed_x      speed_y    speed_z'
vector  avelocity;              // = 'pitch_speed yaw_speed 0', angle velocity
vector  punchangle;             // temp angle adjust from damage or recoil
float   movetype;               // type of movement
float   yaw_speed;              // rotation speed
float   solid;                  // tell if entity can block the movements.

Monster's Behavior
entity  goalentity;             // Monster's movetarget or enemy
float   ideal_yaw;              // Monster's ideal direction, on paths
float   yaw_speed;              // Monster's yaw speed.
string  target;                 // Target of a monster 
string  targetname;             // name of the target
Automatic Behavior

float   nextthink;              // next time when entity must act
void()  think;                  // function invoked when entity must act
void()  touch;                  // function invoked if entity is touched
void()  use;                    // function invoked if entity is used
void()  blocked;                // function for doors or plats, called when can't push other
vector  movedir;                // mostly for doors, but also used for waterjump
string  message;                // trigger messages
float   sounds;                 // either a cd track number or sound number
string  noise;                  // soudn played on entity noise channel 1
string  noise1;
string  noise2;
string  noise3;                 

Information by Abducted:
When you want an entity to do something specific, after a certain delay (exploding, disapearing, or the like...), you set nextthink to that delay (in seconds), and set think to the function to execute.

Information by Greg Lewis:
It seems that the touch function is called before the field is checked, so you can set this type in the touch function, and it will immediatly be taken into account.

Player/Monster stats and damage status

float   deadflag;               // tells if an entity is dead.
float   health;                 // health level
float   max_health;             // players maximum health is stored here
float   takedamage;             // indicates if entity can be damaged
float   dmg_take;               // damage is accumulated through a frame. and sent as one single
float   dmg_save;               // message, so the super shotgun doesn't generate huge messages
entity  dmg_inflictor;          // entity that inflicted the damage (player, monster, missile, door)
Player inventory

float   items;                  // bit flags
float   armortype;              // fraction of damage absorbed by armor
float   armorvalue;             // armor level
float   weapon;                 // one of the IT_SHOTGUN, etc flags
string  weaponmodel;            // entity model for weapon
float   weaponframe;            // frame for weapon model
float   currentammo;            // ammo for current weapon
float   ammo_shells;            // remaining shells
float   ammo_nails;             // remaining nails
float   ammo_rockets;           // remaining rockets and grenades
float   ammo_cells;             // remaining lightning bolts

float   impulse;                // weapon changes
When set to 0, the player's weapon doesn't change. When different from zero, this field is interpreted by the Quake-C impulse command as a request to change weapon (see ImpulseCommand).

Player Fight
entity  owner;                  // Entity that owns this one (missiles, bubbles are owned by the player)
entity  enemy;                  // personal enemy (only for monster entities)
float   button0;                // fire
float   button1;                // use
float   button2;                // jump
vector  view_ofs;               // position of player eye, relative to origin
float   fixangle;               // set to 1 if you want angles to change now
vector  v_angle;                // view or targeting angle for players
float   idealpitch;             // calculated pitch angle for lookup up slopes
entity  aiment;                 // aimed antity?
Deathmatch
float   frags;                  // number of frags
string  netname;                // name, in network play
float   colormap;               // colors of shirt and pants
float   team;                   // team number
float   flags;                  // ?

Fields used only by Quake-C (User defined)

These entity fields are used only by Quake-C programs, and are never referenced by the C code of Quake.exe. So you can do whatever you want with the values, so long as it's compatible with what other Quake-C modules do.

If the fields defined here are not suitable for you, you can define new fields, by adding them at the end of the defintion of fields. As a matter of fact, the number of fields in an entity (hence the size of all the instances of entity objects) is determined by Quake-C: in the PROGS.DAT header, a value named entityfields indicates to Quake.exe the size of the entity object.

Beware however that the more field you add, the more each entity will suck memory. Add just one float (4 bytes) and it will take, in memory, 4 bytes time the number of entity.

The best is to share fields between distinct classes of entities, by reusing the same position for another kind of field. If the Quake C Compiler was a real object-oriented compiler, that would be done very safely by single-inheritance (multiple-inheritance would be a deadly mistake). You will also notice that id software has made quite a lousy usage of most of the fields, defining much more than were actually needed, since they are only used by a few entities.

World fields
string wad;                      // name of WAD file with misc graphics  
string map;                      // name of the map being played
float  worldtype;                // see below

worldtype is 0 for a medieval setting, 1 for metal, and 2 for a base setting.
These fields might soon become global variables, so don't rely too much on them.

Quake Ed fields
string killtarget;
float light_lev;                 // not used by game, but parsed by light util
float style;
Monster Behaviour

Those functions are called when these specific events happen:

void() th_stand;            // when stands iddle
void() th_walk;             // when is walking
void() th_run;              // when is running
void() th_missile;          // when a missile comes
void() th_melee;            // when fighting in melee
void() th_die;              // when dies

void(entity attacker, float damage) th_pain;
That function is executed when the monster takes a certain amount of damage from an attacker (a player, or another monster). Will usually cause the monster to turn against the attacker.

Monster state variables
entity oldenemy;            // mad at this player before taking damage
float  speed;               //
float  lefty;               //
float  search_time;         //
float  attack_state;        //
float   pausetime;
entity  movetarget;
Player Only
float   walkframe;
float   attack_finished;
float   pain_finished;         // time when pain sound is finished
float   invincible_finished;
float   invisible_finished;
float   super_damage_finished;
float   radsuit_finished;
float   invincible_time;       // time when player cease to be invincible
float   invincible_sound;
float   invisible_time;        // time when player cease to be invisible
float   invisible_sound;
float   super_time;            // time when quad shot expires?
float   super_sound;
float   rad_time;
float   fly_sound;
float   axhitme;               // TRUE if hit by axe
float   show_hostile;          // set to time+0.2 whenever a client fires a
                               // weapon or takes damage.  Used to alert
                               // monsters that otherwise would let the player go
float   jump_flag;             // player jump flag
float   swim_flag;             // player swimming sound flag
float   air_finished;          // when time > air_finished, start drowning
float   bubble_count;          // keeps track of the number of bubbles
string  deathtype;             // keeps track of how the player died
Object stuff
string  mdl;                    // model name?
vector  mangle;                 // angle at start. 'pitch roll yaw'
vector  oldorigin;              // only used by secret door
float   t_length;
float   t_width;
Doors
vector  dest;
vector  dest1;
vector  dest2;
float   wait;                   // time from firing to restarting
float   delay;                  // time from activation to firing
entity  trigger_field;          // door's trigger entity
string  noise4;
float   aflag;
float   dmg;                    // damage done by door when hit
Miscellaneous
float   cnt;                    // counter
void()  think1;
vector  finaldest;
vector  finalangle;
//
// triggers
//
float   count;                  // for counting triggers
//
// plats / doors / buttons
//
float   lip;
float   state;
vector  pos1;
vector  pos2;                   // top and bottom positions
float   height;
//
// sounds 
//
float   waitmin;
float   waitmax;
float   distance;
float   volume;