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.
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).
The maximum number of static entities is 127.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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)
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 changesWhen 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).
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?
float frags; // number of frags string netname; // name, in network play float colormap; // colors of shirt and pants float team; // team number float flags; // ?
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.
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.
string killtarget; float light_lev; // not used by game, but parsed by light util float style;
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.
entity oldenemy; // mad at this player before taking damage float speed; // float lefty; // float search_time; // float attack_state; //
float pausetime; entity movetarget;
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
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;
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
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;