ETF Mapping/References
References
editEntity States
editEssentially, each entity has a 'state', as follows:
Invisible | This entity is not triggerable, nor is it visible (although this has some odd side effects, e.g. invisible doors still stop people walking through them). |
Disabled | This entity is not triggerable. |
Inactive | This entity is idle (and can be thought of as 'touchable'). For goalitems, this means 'back at base'. |
Active | This entity is active, and (depending on its settings), will go back to inactive after a set time. For goalitems, this means 'lying on the ground'. |
Carried | This state only applies to goalitems. |
When a player touches an entity and the criteria are passed, it will be triggered to carried (if it's a carryable entity), or active.
Unless forced (see targets), only certain state changes are permitted (note that you cannot change state to the current state (nothing at all will happen):
invisible | disabled | inactive | active | carried | |
invisible | * | * | |||
disabled | * | * | |||
inactive | * | * | * | * | |
active | * | * | |||
carried | * | * |
When an entity changes state, it will trigger any messages or sounds for that state, as well as executing give (only when in carried/active state, depending on whether it can be carried), teamscore (again, only in carried/active) and <state>target (see targets).
An entity can have its state changed a maximum of 5 times (currently) per-frame single frame - this is to prevent infinite loops from hanging the server - but you would be wiser to avoid any situations where this kicks in (since you cannot always be sure what state the entity will end up in, particularly if the limit changes).
Messages
editWhen an entity changes state, messages and sounds can be sent out to various players, optionally with the 'force' flag (prefixing the string with a ~ symbol). The force flag causes messages to be centerprinted and sounds to be global (i.e. no attenuation). Messages can be sent to four different groups: The activator, the activator's team (excluding activator), all players not on the activator's team, or all players.
<state>_message | Send a message to the activator. |
<state>_team_message | Send a message to the activator's teammates. |
<state>_nonteam_message | Send a message to all players not on the activator's team. |
<state>_all_message | Send a message to all players. |
<state>_sound | Play a sound to the activator (currently, plays globally as though ~ was specified). |
<state>_team_sound | Play a sound to the activator's teammates (currently, plays globally as though ~ was specified). |
<state>_nonteam_sound | Play a sound to all players not on the activator's team (currently, plays globally as though ~ was specified). |
<state>_all_sound | Play a sound to all players. |
<state> in the above strings means the state to play on, e.g. active_message. For sounds, currently only sounds everyone can hear (<state>_all_sound) can be played 'unforced' (i.e. fades with distance from the entity).
Additionally, there is another prefix that is not a state. This is the kill prefix. It is used just as the other messages, but useful for o.a. trigger_hurt entities. Example: "kill_all_message" "%n shouldn't have been here." as a keypair on a trigger_hurt will display "Dummy shouldn't have been here." as a deathmessage when the player called Dummy gets killed by the trigger_hurt.
Messages can also contain tokens that are expanded as required. Tokens in UPPERCASE represent the activator (if present). Tokens in lowercase represent the entity itself:
%H | Health |
%A | Armor |
%L | Location (returns 'unknown location' if unable to work it out) |
%D | Location of last death. |
%R | Last reported location (i.e. identical to last %L) |
%T | Team name (e.g. "Red Team", "Blue Team" etc.) |
%C | Team colour (e.g. red, blue etc.) |
%G | Disguise (returns 'not disguised' if not wearing a disguise) |
%N | Name (player name / entity groupname (or one of them) |
%E | State (e.g. "active", "carried" etc.) |
%S | Class (e.g. "soldier", "medic" etc.) |
For example, you could say:
"active_flaginfo" "The ^1RED^* flag has been dropped at $l." // $l is used for locations of the goalitem entity dunno why but it is.
Incidentally, you can use these tokens in communications as well (case does not matter), save that you require $ instead of %. If you want to annoy everyone on the server, just say "Hello $r, I'm $n of the $t." (I wouldn't really recommend it, though). $r is readers name now instead of $n.
Flaginfo
editFlaginfo is sent to players who execute a \flaginfo command. All entities that have a <state>_flaginfo will have that info sent to the client. Normally, it's flags and the like that keep flaginfo, hence the command name. For flags, you'd expect a carried, active, and inactive flaginfo string, e.g.
carried_flaginfo | "%N has the red flag at %L (and only %H health left)" |
active_flaginfo | "The red flag is lying in the field at $l" (note the lowercase and $, there's no carrier!) |
inactive_flaginfo | "The red flag is safe at base" |
Give
editEntities can 'give' bonuses to affected players when set to carried (if a carryable entity) or active (if not). The give string is of the form "give" "stat=value,stat=value,stat=value". The following stats are available:
health | Health |
armor | Armor |
damage | Deal damage to the target |
ammo_shells | Shells |
ammo_nails | Nails |
ammo_rockets | Rockets |
ammo_cells | Cells |
ammo_medikit | Medikit ammo |
ammo_charge | HE Charge |
score | Player score (not teamscore) |
gren1 | Grenade type 1 |
gren2 | Grenade type 2 |
quad | Seconds of quad damage |
regen | Seconds of regen |
flight | Seconds of flight |
battlesuit | Seconds of battlesuit |
invis | Seconds of invisibility (shimmer invis, not agent invis) |
haste | Seconds of haste |
invuln | Seconds of invulnerability |
aqualung | Seconds of aqualung |
ceasefire | Seconds a player is unable to shoot |
gas | Seconds of gas |
stun | Seconds of stun |
flash | Seconds of flash |
tranq | Seconds of tranq |
fire | Amount of fire counters, every counter does a certain amount of burn damage every few seconds |
armortype | Armour type (as a number from 0-100). This is the amount of damage the armour saves you from* |
aclass_shell | If true, give 15% extra protection against shells (otherwise remove) |
aclass_bullet | If true, give 15% extra protection against nailgun / sniper rifle (otherwise remove) |
aclass_explosive | If true, give 15% extra protection against explosions (otherwise remove) |
aclass_shock | If true, give 15% extra protection against emp/electrical attacks (otherwise remove) |
aclass_fire | If true, give 15% extra protection against fire and prevent burning (otherwise remove) |
aclass_all | If true, set all armour classes (otherwise, remove all armour classes) |
If not forced (with a ~ prefix), these values are limited to player maximums. If + or - is prefixed, they're added or removed from existing values rather than set, e.g.
"give" "health=~500,armor=+50,score=+3,quad=10,haste=10,aclass_fire=1"
Would give a player 500 health (no matter their class max), 50 more armour (up to class max), three points, ten seconds of quad and haste (no matter what they had before), and fire-resistant armour.
If armortype is not specified and armour is given (i.e. the player gets more armour than they had before the command), it is automatically assumed that their armour type should be set to the maximum. For their armour type to remain unchanged, put in a key like "armortype=+0".
There are also a set of entity keys that affect the command:
affectteams | Affect the named teams, (e.g. "red,blue") regardless of which team activated this entity |
effectradius | Affect only those players within the specified radius |
holding | Affect only those players holding these goalitems |
notholding | Affect only those players not holding these goalitems |
clientstats | Affect only those matching these clientstats |
Note that the way the criteria work, it first checks affectteams and the affectteam/affectnonteam flags for players to affect, and them limits this based on the lineofsight/environment flags.
Flags
editAn entity's key "flags" can be used to specify a comma-separated list of boolean flags that affect the entity's behavior in multiple areas, as follows. These can be categorised as criteria/effect/command flags:
hideactive (cmd) | Cause the entity to be invisible while active (e.g. for refill goalinfos). |
affectteam (eff) | Cause the 'give' command to affect everyone on the activator's team. |
affectnonteam (eff) | Cause the 'give' command to affect everyone not on the activator's team. |
dropoff (eff) | 'give' values 'drop off' with distance (requires a 'range' key in the entity). |
lineofsight (eff) | Only entities in line of sight will be affected. |
environment (eff) | Only entities in the same environment will be affected. |
shootable (cmd) | Allow shooting the entity to be equivalent to touching it (only for func_doors). |
reversecriteria (cri) | Causes the entity to only be triggered if the criteria are NOT met. |
orclientstats (cri) | Causes the clientstats criteria to be OR instead of AND. |
revealagent (cmd) | If triggered, the activator will lose his disguise. |
showcarry (cmd) | On carryable entities, cause it to be shown above the player, as with CTF flags. |
chargeable (cmd) | Allow HE charging the entity to be equivalent to touching it. |
rotating (cmd) | Cause the model to rotate and bob like an item (only for goalinfo/goalitems). |
noshrink (cmd) | Goal does not grow or shrink when appearing/disappearing. |
nodrop (cmd) | On carryable entities, stop the 'dropflag' command affecting it. |
keepondeath (cmd) | On carryable entities, don't drop on death. |
usegauntlet (cmd) | Entity must be axed instead of touched. |
allowdead (cmd) | Allow dead players to be selected in target_cycle use. |
allowsame (cmd) | Allow same player to be selected in target_cycle use. |
faildirection (cmd) | Forcefield direction field applies to those failing the criteria. |
allowsentrylock (cmd) | Sentry is allowed to lock on through forcefields (bad idea :). |
disguisecriteria (cri) | Criteria work on agent's apparent team/class rather than real. |
Targets
editThe targeting system is what binds all the entities together into something more. When an entity's state changes, it checks for <state>target and then attempts to set each named target to the specified state (default state if not specified is always 'active'). If forced by prefixing the state with a ~ character, criteria (and 'give'/'teamscore') are ignored, e.g.
"carriedtarget" "redalarms,escapedoors=~disabled"
Will cause the alarms to go to active (default if not specified), and forces all escape doors to be disabled, even if they're currently active (i.e. open).
To be targetable, entities must have either a targetname or a groupname key, the differences are as follows:
targetname | Can only hold a single name, affects some entities - e.g. targetname will stop doors opening when players touch them, and teleporters will only look at targetnames for a destination, etc. |
groupname | Can hold any number of names, separated by commas, and will respond to triggers on any of them - this allows much more complex entity interactions. It will not affect entities as having a targetname will. |
Wherever possible, please use groupname instead of targetname - it's much more flexible and less prone to side-effects.
Please note that unforced triggers (i.e. without a ~) will pass the same activator on to the triggered entity (i.e. the player rather than the entity passing the trigger on). Also, the criteria are still check against the activator).
If you find yourself having problems with this, try setting g_mapentDebug to 1 at the console - be warned that you'll get a lot of junk out of this, and it may not help much.
See the Entity States section for more information.
Criteria
editCriteria are checks on whether or not the activator can actually trigger this entity. The following fields apply, as well as some flags:
allowteams | Only the specified teams (e.g. "red,blue") are allowed |
allowclasses | Only the specified classes (e.g. "recon,grenadier,agent") are allowed |
holding | Only players holding all the specified entities (e.g. "redkey1,redkey2") are allowed. |
notholding | Only players not holding all the specified entities (e.g. "redkey1,redkey2") are allowed. |
clientstats | Only players matching the specified clientstats (e.g. "health<50,gren1=0,armour<!") are allowed (see below). |
checkstate | The trigger is only valid if at least one of each named entity is in the specified state, e.g. "redalarms=inactive,redflag=carried"). If you want want to ensure all named entities are in a certain state, simply give each entity a unique group and check those. |
disguisecriteria | Criteria work on agent's apparent team/class rather than real. |
The clientstats value is a list of evaluators build up like this: [keyword][evaluator][value], with the evaluator being '=', '<', '>', '<=' or '>='. The value is an integer or '!' (indicates activators' class maximum) and the keys can be the following: health, armor, ammo_shells, ammo_nails, ammo_rockets, ammo_cells, score, gren1, gren2, quad, regen, flight, battlesuit, invis, haste, ammo_medikit, ammo_charge, invuln, aqualung, gas, stun, flash, tranq, fire, skill.
If the criteria fail (after the reversecriteria flag is applied), the 'failtarget' key will be executed - note that there's no 'wait' on failures, so don't do anything processor intensive.
Map Info
editEach map should be accompanied by a "mapinfo" file, which lives in the maps directory with its map, e.g. maps/etf_map.bsp should be accompanied by a maps/etf_map.mapinfo file.
The mapinfo defines assorted properties describing the map, as well as overriding world-spawn attributes. The file format is something like:
mapinfo { map "etf_map"; // BSP name longname "Mapname"; // Long name for map, general description of it type "etf"; // Game it is for (all etf maps are marked with "etf") gameindices "1,2,3"; // Available gameindices atmosphere "T=RAIN,B=5 10,C=0.5,G=0.5 2,BV=0,GV=0 100,W=1 2,D=300"; // Atmospheric effects gameindexDef 1 { // Gameindex Definition longname "Mapname CTF"; // Long name for this gameindex // Map info (former .mpi) mapinfo "Blablabladebladebla"; // Class limits etc green_limit "0"; yellow_limit "0"; sniper_limit "2"; grenadier_limit "3"; red_soldier_limit "5"; blue_soldier_limit "6"; atmosphere "T=SNOW"; } gameindexDef 2 { longname "Mapname 1-flag CTF"; mapinfo "Blablabladebladebla"; green_limit "0"; yellow_limit "0"; } }
Entries in gameIndexDef blocks override the default entries (which are not associated with any particular gameindex, and apply to all). Note that the gameindices field is required, and will default to "1" if not specified (however many gameIndexDef blocks there are).
map | The name of the map it is associated with (not used, merely for completeness). |
longname | The "human" name of the map. |
mapinfo | A brief description of the map and how it is played. |
type | Should always be "etf". |
gameindices | Should indicate all valid indices. |
minplayers | The minimum number of players recommended on the map. |
maxplayers | The maximum number of players recommended on the map. |
Each map+gameindex combination is treated as a completely separate map in voting lists. Gameindexes should be a single digit from 1 to 9.
Any fields not mentioned here will override worldspawn keys instead (for example atmosphere).
Gameindices
editGameindices make it possible to have multiple scenarios in one map. Basically, all entities with a 'gameindex' key spawn only when the server has g_gameindex set to the same value.
For example, when an entity has "gameindex" "1,2", it will only spawn when g_gameindex (which defaults to 1) is 1 or 2 on the server.
Also, for the server to know which gameindices are allowed for this map, there is a new key for the .arena file. This key is called 'gameindices' and has as value an array of the allowed gameindices. For example "1,2,3", which results in g_gameindex 1, 2 and 3 being valid for this map. If it has a different value during the loading of the map, it defaults to 1.
Custom Infoparms
editQ3F uses the -custinfoparms parameter of q3map 1.1-TA-beta and newer being distributed with GtkRadiant to extend Quake3's shader language.
Current custom infoparms:
particleclip Particles collide with this surface. forcefield Used in combination with the func_forcefield entity to create forcefields. footprints If a client walks over a shader with the footprints parameter set, he leaves a trail of footprints. stone Stone footstep and ricochet sounds. wood Wood footstep and ricochet sounds. seethrough Translucent surface a sentry can track through even if it's solid.
To use these parameters, you need to add a 'custinfoparms.txt' file to your scripts directory (where your shaders live) and execute the bsp stage of the compile process with the additional -custinfoparms command line parameter.
The contents of the textfile used with Q3F:
// Custom Surfaceparms file // Custom Contentsflags { particleclip 0x2000 forcefield 0x4000 } // Custom Surfaceflags { footprints 0x80000 stone 0x100000 wood 0x200000 seethrough 0x400000 }