Xonotic
main.qc
Go to the documentation of this file.
1 #include "main.qh"
2 
4 #include <common/constants.qh>
6 #include <common/debug.qh>
7 #include <common/mapinfo.qh>
9 #include <common/util.qh>
10 #include <common/vehicles/all.qh>
11 #include <common/weapons/_all.qh>
13 #include <lib/warpzone/common.qh>
14 #include <lib/warpzone/server.qh>
15 #include <server/anticheat.qh>
16 #include <server/bot/api.qh>
17 #include <server/command/common.qh>
18 #include <server/compat/quake3.qh>
19 #include <server/damage.qh>
20 #include <server/gamelog.qh>
21 #include <server/hook.qh>
22 #include <server/ipban.qh>
23 #include <server/mutators/_mod.qh>
24 #include <server/spawnpoints.qh>
25 #include <server/weapons/common.qh>
27 #include <server/world.qh>
28 
30 {
31  if (this.owner)
32  dropclient(this.owner);
33  delete(this);
34 }
43 {
44  bool scheduled = false;
45  FOREACH_ENTITY_CLASS("dropclient_handler", true,
46  {
47  if(it.owner == this)
48  {
49  scheduled = true;
50  break; // can't use return here, compiler shows a warning
51  }
52  });
53  if (scheduled)
54  return false;
55 
56  entity e = new_pure(dropclient_handler);
58  e.owner = this;
59  e.nextthink = time + 0.1;
60  return true;
61 }
62 
64 {
65  if (this.contents_damagetime >= time)
66  {
67  return;
68  }
69 
71 
72  if (this.flags & FL_PROJECTILE)
73  {
74  if (this.watertype == CONTENT_LAVA)
75  Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
76  else if (this.watertype == CONTENT_SLIME)
77  Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
78  }
79  else
80  {
81  if (STAT(FROZEN, this))
82  {
83  if (this.watertype == CONTENT_LAVA)
84  Damage(this, NULL, NULL, 10000, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
85  else if (this.watertype == CONTENT_SLIME)
86  Damage(this, NULL, NULL, 10000, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
87  }
88  else if (this.watertype == CONTENT_LAVA)
89  {
90  if (this.watersound_finished < time)
91  {
92  this.watersound_finished = time + 0.5;
93  sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
94  }
95  Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
98  }
99  else if (this.watertype == CONTENT_SLIME)
100  {
101  if (this.watersound_finished < time)
102  {
103  this.watersound_finished = time + 0.5;
104  sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
105  }
106  Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
107  }
108  }
109 }
110 
112 {
113  if (this.watertype <= CONTENT_WATER && this.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
114  {
115  if (!(this.flags & FL_INWATER))
116  {
117  this.flags |= FL_INWATER;
118  this.contents_damagetime = 0;
119  }
120 
122  }
123  else
124  {
125  if (this.flags & FL_INWATER)
126  {
127  // play leave water sound
128  this.flags &= ~FL_INWATER;
129  this.contents_damagetime = 0;
130  }
131  }
132 }
133 
135 {
136  if(IS_VEHICLE(this) || (this.flags & FL_PROJECTILE))
137  return; // vehicles and projectiles don't receive fall damage
138  if(!(this.velocity || this.oldvelocity))
139  return; // if the entity hasn't moved and isn't moving, then don't do anything
140 
141  // check for falling damage
142  bool have_hook = false;
143  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
144  {
145  .entity weaponentity = weaponentities[slot];
146  if(this.(weaponentity).hook && this.(weaponentity).hook.state)
147  {
148  have_hook = true;
149  break;
150  }
151  }
152  if(!have_hook)
153  {
154  float dm; // dm is the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
156  dm = fabs(this.oldvelocity.z) - vlen(this.velocity);
157  else
158  dm = vlen(this.oldvelocity) - vlen(this.velocity);
159  if (IS_DEAD(this))
161  else
163  if (dm > 0)
164  {
165  tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
167  Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
168  }
169  }
170 
171  if(autocvar_g_maxspeed > 0 && vdist(this.velocity, >, autocvar_g_maxspeed))
172  Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
173 }
174 
176 {
177  if(game_stopped || time < game_starttime)
178  return;
179 
180  IL_EACH(g_damagedbycontents, it.damagedbycontents,
181  {
182  if (it.move_movetype == MOVETYPE_NOCLIP) continue;
183  CreatureFrame_Liquids(it);
184  CreatureFrame_FallDamage(it);
185  it.oldvelocity = it.velocity;
186  });
187 }
188 
189 void Pause_TryPause(bool ispaused)
190 {
191  int n = 0;
193  if (PHYS_INPUT_BUTTON_CHAT(it) != ispaused) return;
194  ++n;
195  });
196  if (!n) return;
197  setpause(ispaused);
198 }
199 
200 void SV_PausedTic(float elapsedtime)
201 {
202  if (!server_is_dedicated) Pause_TryPause(false);
203 }
204 
205 void dedicated_print(string input)
206 {
207  if (server_is_dedicated) print(input);
208 }
209 
211 {
212  if (e.initialize_entity)
213  {
214  entity ent, prev = NULL;
215  for (ent = initialize_entity_first; ent; )
216  {
217  if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
218  {
219  //print("make_safe_for_remove: getting rid of initializer ", etos(ent), "\n");
220  // skip it in linked list
221  if (prev)
222  {
223  prev.initialize_entity_next = ent.initialize_entity_next;
224  ent = prev.initialize_entity_next;
225  }
226  else
227  {
228  initialize_entity_first = ent.initialize_entity_next;
230  }
231  }
232  else
233  {
234  prev = ent;
235  ent = ent.initialize_entity_next;
236  }
237  }
238  }
239 }
240 
242 {
243  if(e.remove_except_protected_forbidden)
244  error("not allowed to remove this at this point");
245  builtin_remove(e);
246 }
247 
249 {
250  if(e.classname == "spike")
251  error("Removing spikes is forbidden (crylink bug), please report");
252  builtin_remove(e);
253 }
254 
256 {
258  builtin_remove(e);
259 }
260 
261 /*
262 =============
263 StartFrame
264 
265 Called before each frame by the server
266 =============
267 */
268 
270 
272 void systems_update();
273 void sys_phys_update(entity this, float dt);
275 {
276  // TODO: if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
279 
282 
283  delete_fn = remove_unsafely; // not during spawning!
285  servertime = time;
287 
288 #ifdef PROFILING
289  if(time > client_cefc_accumulatortime + 1)
290  {
291  float t = client_cefc_accumulator / (time - client_cefc_accumulatortime);
292  int c_seeing = 0;
293  int c_seen = 0;
294  FOREACH_CLIENT(true, {
295  if(IS_REAL_CLIENT(it))
296  ++c_seeing;
297  if(IS_PLAYER(it))
298  ++c_seen;
299  });
300  LOG_INFO(
301  "CEFC time: ", ftos(t * 1000), "ms; ",
302  "CEFC calls per second: ", ftos(c_seeing * (c_seen - 1) / t), "; ",
303  "CEFC 100% load at: ", ftos(solve_quadratic(t, -t, -1) * '0 1 0')
304  );
305  client_cefc_accumulatortime = time;
306  client_cefc_accumulator = 0;
307  }
308 #endif
309 
310  IL_EACH(g_projectiles, it.csqcprojectile_clientanimate, CSQCProjectile_Check(it));
311 
312  if (RedirectionThink()) return;
313 
314  UncustomizeEntitiesRun();
316 
317  WarpZone_StartFrame();
318 
320  if (sys_frametime <= 0) sys_frametime = 1.0 / 60.0; // somewhat safe fallback
321 
322  if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE)
323  orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout
324 
325  // detect when the pre-game countdown (if any) has ended and the game has started
326  bool game_delay = (time < game_starttime);
327  if (autocvar_sv_eventlog && game_delay_last && !game_delay)
328  GameLogEcho(":startdelay_ended");
329  game_delay_last = game_delay;
330 
333 
334  if (warmup_stage && !game_stopped && warmup_limit > 0 && time - game_starttime >= warmup_limit) {
335  ReadyRestart(true);
336  return;
337  }
338 
339  bot_serverframe();
341  MUTATOR_CALLHOOK(SV_StartFrame);
342 
343  GlobalStats_updateglobal();
344  FOREACH_CLIENT(true, GlobalStats_update(it));
346 }
347 
348 .vector originjitter;
349 .vector anglesjitter;
350 .float anglejitter;
352 .string cvarfilter;
353 
355 {
356  if (this)
357  if (this.gametypefilter != "")
359  {
360  delete(this);
361  return;
362  }
363  if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
364  delete(this);
365  return;
366  }
367 
368  if (q3compat && DoesQ3ARemoveThisEntity(this)) {
369  delete(this);
370  return;
371  }
372 
373  set_movetype(this, this.movetype);
374 
375  if (this.monster_attack) {
376  IL_PUSH(g_monster_targets, this);
377  }
378 
379  // support special -1 and -2 angle from radiant
380  if (this.angles == '0 -1 0') {
381  this.angles = '-90 0 0';
382  } else if (this.angles == '0 -2 0') {
383  this.angles = '+90 0 0';
384  }
385 
386  #define X(out, in) MACRO_BEGIN \
387  if (in != 0) { out = out + (random() * 2 - 1) * in; } \
388  MACRO_END
389  X(this.origin.x, this.originjitter.x); X(this.origin.y, this.originjitter.y); X(this.origin.z, this.originjitter.z);
390  X(this.angles.x, this.anglesjitter.x); X(this.angles.y, this.anglesjitter.y); X(this.angles.z, this.anglesjitter.z);
391  X(this.angles.y, this.anglejitter);
392  #undef X
393 
394  if (MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) {
395  delete(this);
396  return;
397  }
398 }
399 
400 string GetField_fullspawndata(entity e, string f, ...)
401 /* Retrieves the value of a map entity field from fullspawndata
402  * This bypasses field value changes made by the engine,
403  * eg string-to-float and escape sequence substitution.
404  *
405  * Avoids the need to declare fields just to read them once :)
406  *
407  * Returns the last instance of the field to match DarkPlaces behaviour.
408  * Path support: converts \ to / and tests the file if a third (bool, true) arg is passed.
409  * Returns string_null if the entity does not have the field, or the file is not in the VFS.
410  *
411  * FIXME: entities with //comments are not supported.
412  */
413 {
414  string v = string_null;
415 
416  if (!e.fullspawndata)
417  {
418  //LOG_WARNF("^1EDICT %s (classname %s) has no fullspawndata, engine lacks support?", ftos(num_for_edict(e)), e.classname);
419  return v;
420  }
421 
422  if (strstrofs(e.fullspawndata, "//", 0) >= 0)
423  {
424  // tokenize and tokenize_console return early if "//" is reached,
425  // which can leave an odd number of tokens and break key:value pairing.
426  LOG_WARNF("^1EDICT %s fullspawndata contains unsupported //comment^7%s", ftos(num_for_edict(e)), e.fullspawndata);
427  return v;
428  }
429 
430  //print(sprintf("%s(EDICT %s, FIELD %s)\n", __FUNC__, ftos(num_for_edict(e)), f));
431  //print(strcat("FULLSPAWNDATA:", e.fullspawndata, "\n"));
432 
433  // tokenize treats \ as an escape, but tokenize_console returns the required literal
434  for (int t = tokenize_console(e.fullspawndata) - 3; t > 0; t -= 2)
435  {
436  //print(sprintf("\tTOKEN %s:%s\t%s:%s\n", ftos(t), ftos(t + 1), argv(t), argv(t + 1)));
437  if (argv(t) == f)
438  {
439  v = argv(t + 1);
440  break;
441  }
442  }
443 
444  //print(strcat("RESULT: ", v, "\n\n"));
445 
446  if (v && ...(0, bool) == true)
447  {
448  v = strreplace("\\", "/", v);
449  if (whichpack(v) == "")
450  return string_null;
451  }
452 
453  return v;
454 }
455 
457 {
458  // create waypoint links for warpzones
459  entity tracetest_ent = spawn();
460  setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST);
461  tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
462  //for(entity e = warpzone_first; e; e = e.warpzone_next)
463  for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
464  waypoint_spawnforteleporter_wz(e, tracetest_ent);
465  delete(tracetest_ent);
466 }
467 
469 void URI_Get_Callback(float id, float status, string data)
470 {
471  if(url_URI_Get_Callback(id, status, data))
472  {
473  // handled
474  }
475  else if (id == URI_GET_DISCARD)
476  {
477  // discard
478  }
479  else if (id >= URI_GET_CURL && id <= URI_GET_CURL_END)
480  {
481  // sv_cmd curl
482  Curl_URI_Get_Callback(id, status, data);
483  }
484  else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
485  {
486  // online ban list
487  OnlineBanList_URI_Get_Callback(id, status, data);
488  }
489  else if (MUTATOR_CALLHOOK(URI_GetCallback, id, status, data))
490  {
491  // handled by a mutator
492  }
493  else
494  {
495  LOG_INFO("Received HTTP request data for an invalid id ", ftos(id), ".");
496  }
497 }
498 
499 /*
500 ==================
501 main
502 
503 unused but required by the engine
504 ==================
505 */
506 void main ()
507 {
508 
509 }
string cvarfilter
Definition: main.qc:352
void remove_unsafely(entity e)
Definition: main.qc:248
void dedicated_print(string input)
print(), but only print if the server is not local
Definition: main.qc:205
#define IL_EACH(this, cond, body)
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition: player.qh:155
bool autocvar_g_balance_falldamage_onlyvertical
Definition: main.qh:15
float autocvar_g_balance_falldamage_deadminspeed
Definition: main.qh:11
float autocvar_g_balance_contents_playerdamage_lava_burn_time
Definition: main.qh:8
string string_null
Definition: nil.qh:9
const float CONTENT_LAVA
Definition: csprogsdefs.qc:240
bool monster_attack
Definition: sv_monsters.qh:62
int autocvar_g_balance_contents_playerdamage_lava
Definition: main.qh:6
IntrusiveList g_monster_targets
Definition: sv_monsters.qh:147
entity hook
Definition: hook.qh:19
void remove_safely(entity e)
Definition: main.qc:255
ERASEABLE vector solve_quadratic(float a, float b, float c)
ax^2 + bx + c = 0
Definition: math.qh:307
string GetField_fullspawndata(entity e, string f,...)
Definition: main.qc:400
float watertype
Definition: progsdefs.qc:182
float autocvar_g_balance_contents_damagerate
Definition: main.qh:3
float trace_dphitq3surfaceflags
float anglejitter
Definition: main.qc:350
float waterlevel
Definition: progsdefs.qc:181
void dropclient_do(entity this)
Definition: main.qc:29
#define IS_FAKE_CLIENT(v)
Definition: utils.qh:16
int have_team_spawns
Definition: spawnpoints.qh:16
void Curl_URI_Get_Callback(int id, float status, string data)
Definition: generic.qc:31
void remove_except_protected(entity e)
Definition: main.qc:241
IntrusiveList g_damagedbycontents
Definition: damage.qh:155
void PlayerPostThink(entity this)
Definition: client.qc:2651
entity() spawn
prev
Definition: all.qh:66
void StartFrame()
Definition: main.qc:274
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
float autocvar_sys_ticrate
Definition: main.qh:17
Gametype MapInfo_LoadedGametype
Definition: mapinfo.qh:193
void SV_PausedTic(float elapsedtime)
Definition: main.qc:200
float watersound_finished
Definition: main.qh:40
vector maxs
Definition: csprogsdefs.qc:113
void CSQCProjectile_Check(entity e)
float DPCONTENTS_BOTCLIP
bool warmup_stage
Definition: main.qh:103
var void delete_fn(entity e)
float DPCONTENTS_PLAYERCLIP
const int URI_GET_IPBAN_END
Definition: urllib.qh:6
const int CH_PLAYER_SINGLE
Definition: sound.qh:21
origin
Definition: ent_cs.qc:114
string classname
Definition: csprogsdefs.qc:107
bool game_delay_last
Definition: main.qc:269
ERASEABLE float url_URI_Get_Callback(int id, float status, string data)
Definition: urllib.qc:28
vector oldvelocity
Definition: main.qh:38
bool dropclient_schedule(entity this)
Schedules dropclient for a player and returns true; if dropclient is already scheduled (for that play...
Definition: main.qc:42
void CheckRules_World()
Definition: world.qc:1593
void CreatureFrame_FallDamage(entity this)
Definition: main.qc:134
void PlayerPreThink(entity this)
Definition: client.qc:2402
#define DMG_NOWEP
Definition: damage.qh:126
void InitializeEntitiesRun()
Definition: world.qc:2179
entity owner
Definition: main.qh:73
void WarpZone_PostInitialize_Callback()
Definition: main.qc:456
float RedirectionThink()
Definition: world.qc:2349
void waypoint_spawnforteleporter_wz(entity e, entity tracetest_ent)
Definition: waypoints.qc:2031
vector originjitter
Definition: main.qc:348
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
void main()
Definition: main.qc:506
int autocvar_g_balance_contents_playerdamage_lava_burn
Definition: main.qh:7
const int URI_GET_IPBAN
Definition: urllib.qh:5
#define LOG_WARNF(...)
Definition: log.qh:67
bool autocvar_sv_autopause
Definition: main.qc:271
#define FOREACH_ENTITY_CLASS(class, cond, body)
Definition: iter.qh:189
float sys_frametime
Definition: common.qh:57
void CreatureFrame_Liquids(entity this)
Definition: main.qc:111
const int URI_GET_DISCARD
Definition: urllib.qh:4
void SV_OnEntityPreSpawnFunction(entity this)
Definition: main.qc:354
void OnlineBanList_URI_Get_Callback(float id, float status, string data)
Definition: ipban.qc:79
int q3compat
Definition: quake3.qh:3
void CreatureFrame_All()
Definition: main.qc:175
const int URI_GET_CURL
Definition: urllib.qh:7
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
vector mins
Definition: csprogsdefs.qc:113
#define X(out, in)
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
const float CONTENT_SLIME
Definition: csprogsdefs.qc:239
float serverframetime
Definition: main.qh:36
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
IntrusiveList g_players
Definition: client.qh:85
float Q3SURFACEFLAG_NODAMAGE
#define NULL
Definition: post.qh:17
float frametime
Definition: csprogsdefs.qc:17
#define LOG_INFO(...)
Definition: log.qh:70
float isGametypeInFilter(Gametype gt, float tp, float ts, string pattern)
Definition: util.qc:972
float DPCONTENTS_SOLID
const float VOL_BASE
Definition: sound.qh:36
void make_safe_for_remove(entity e)
Definition: main.qc:210
#define strstrofs
Definition: dpextensions.qh:42
void GameLogEcho(string s)
Definition: gamelog.qc:12
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
float teamplay
Definition: progsdefs.qc:31
#define IS_DEAD(s)
Definition: utils.qh:26
const float ATTEN_NORM
Definition: sound.qh:30
bool DoesQ3ARemoveThisEntity(entity this)
Definition: quake3.qc:282
void anticheat_startframe()
Definition: anticheat.qc:224
int autocvar_g_balance_falldamage_maxdamage
Definition: main.qh:13
#define IS_VEHICLE(v)
Definition: utils.qh:22
#define tokenize_console
Definition: dpextensions.qh:24
void bot_serverframe()
Definition: bot.qc:658
void ReadyRestart(bool forceWarmupEnd)
Definition: vote.qc:484
int autocvar_g_balance_contents_playerdamage_slime
Definition: main.qh:9
IntrusiveList g_projectiles
Definition: common.qh:46
float autocvar_g_balance_falldamage_minspeed
Definition: main.qh:14
void sys_phys_update(entity this, float dt)
Definition: physics.qc:11
vector v
Definition: ent_cs.qc:116
float DPCONTENTS_BODY
float flags
Definition: csprogsdefs.qc:129
float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
Definition: damage.qc:1077
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
const float TIMEOUT_LEADTIME
Definition: common.qh:48
const int URI_GET_CURL_END
Definition: urllib.qh:8
void systems_update()
Definition: main.qc:7
float autocvar_g_balance_falldamage_factor
Definition: main.qh:12
entity initialize_entity_first
Definition: world.qh:124
#define autocvar_slowmo
Definition: main.qh:16
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
#define setthink(e, f)
void execute_next_frame()
Definition: util.qc:1612
vector angles
Definition: csprogsdefs.qc:104
vector anglesjitter
Definition: main.qc:349
int autocvar_g_balance_contents_projectiledamage
Definition: main.qh:10
float servertime
Definition: main.qh:36
float movetype
Definition: csprogsdefs.qc:98
#define sound(e, c, s, v, a)
Definition: sound.qh:52
float serverprevtime
Definition: main.qh:180
void Pause_TryPause(bool ispaused)
Definition: main.qc:189
bool autocvar_sv_eventlog
Definition: gamelog.qh:3
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
void CreatureFrame_hotliquids(entity this)
Definition: main.qc:63
float contents_damagetime
Definition: main.qh:45
bool server_is_dedicated
Definition: world.qh:37
void set_movetype(entity this, int mt)
#define IS_PLAYER(v)
Definition: utils.qh:9
void URI_Get_Callback(int id, int status, string data)
engine callback
Definition: main.qc:1342
ERASEABLE bool expr_evaluate(string s)
Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
Definition: cvar.qh:48
float orig_slowmo
Definition: common.qh:58
string gametypefilter
Definition: main.qc:351
float FL_INWATER
Definition: progsdefs.qc:235