Xonotic
sv_invasion.qc
Go to the documentation of this file.
1 #include "sv_invasion.qh"
2 
8 
9 #include <server/bot/api.qh>
10 #include <server/world.qh>
11 #include <server/teamplay.qh>
12 
19 
22 
23 bool inv_warning_shown; // spammy
24 
26 {
27  if(!IS_PLAYER(actor)) { return; }
28 
29  actor.inv_endreached = true;
30 
31  int plnum = 0;
32  int realplnum = 0;
33  // let's not count bots
35  ++realplnum;
36  if(it.inv_endreached)
37  ++plnum;
38  });
39  if(plnum < ceil(realplnum * min(1, this.count))) // 70% of players
40  return;
41 
42  this.winning = true;
43 }
44 
45 spawnfunc(target_invasion_roundend)
46 {
47  if(!g_invasion) { delete(this); return; }
48 
49  victent_present = true; // a victory entity is present, we don't need to rely on monster count TODO: merge this with the intrusive list (can check empty)
50 
51  if(!this.count) { this.count = 0.7; } // require at least 70% of the players to reach the end before triggering victory
52 
54 
56 }
57 
58 spawnfunc(invasion_wave)
59 {
60  if(!g_invasion) { delete(this); return; }
61 
63 }
64 
65 spawnfunc(invasion_spawnpoint)
66 {
67  if(!g_invasion) { delete(this); return; }
68 
70 }
71 
72 void ClearWinners();
73 
74 // Invasion stage mode winning condition: If the attackers triggered a round end (by fulfilling all objectives)
75 // they win.
77 {
78  WinningConditionHelper(NULL); // set worldstatus
79 
80  int status = WINNING_NO;
81 
83  {
85 
86  int found = 0;
88  {
89  ++found;
90  if(it.winning)
91  {
92  bprint("Invasion: round completed.\n");
93  // winners already set (TODO: teamplay support)
94 
95  status = WINNING_YES;
96  break;
97  }
98  });
99 
100  if(!found)
101  status = WINNING_YES; // just end it? TODO: should warn mapper!
102  }
104  {
105  ClearWinners();
106 
107  int found = 0; // NOTE: this ends the round if no monsters are placed
108  IL_EACH(g_monsters, !(it.spawnflags & MONSTERFLAG_RESPAWNED),
109  {
110  ++found;
111  });
112 
113  if(found <= 0)
114  {
115  FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
116  {
117  it.winning = true;
118  });
119  status = WINNING_YES;
120  }
121  }
122 
123  return status;
124 }
125 
126 Monster invasion_PickMonster(int supermonster_count)
127 {
129 
130  FOREACH(Monsters, it != MON_Null,
131  {
132  if((it.spawnflags & MON_FLAG_HIDDEN) || (it.spawnflags & MONSTER_TYPE_PASSIVE) || (it.spawnflags & MONSTER_TYPE_FLY) || (it.spawnflags & MONSTER_TYPE_SWIM) ||
133  (it.spawnflags & MONSTER_SIZE_QUAKE) || ((it.spawnflags & MON_FLAG_SUPERMONSTER) && supermonster_count >= 1))
134  continue;
135  if(autocvar_g_invasion_zombies_only && !(it.spawnflags & MONSTER_TYPE_UNDEAD))
136  continue;
137  RandomSelection_AddEnt(it, 1, 1);
138  });
139 
141 }
142 
144 {
146 
148  {
149  RandomSelection_AddEnt(it, 1, ((time < it.spawnshieldtime) ? 0.2 : 1)); // give recently used spawnpoints a very low rating
150  it.spawnshieldtime = time + autocvar_g_invasion_spawnpoint_spawn_delay;
151  });
152 
154 }
155 
157 {
158  IL_EACH(g_invasion_waves, it.cnt == wavenum,
159  {
160  return it; // found one
161  });
162 
163  // if no specific one is found, find the last existing wave ent
164  entity best = NULL;
165  IL_EACH(g_invasion_waves, it.cnt <= wavenum,
166  {
167  if(!best || it.cnt > best.cnt)
168  best = it;
169  });
170 
171  return best;
172 }
173 
175 {
176  entity monster;
179 
180  string tospawn = "";
181  if(wave_ent && wave_ent.spawnmob && wave_ent.spawnmob != "")
182  {
184  FOREACH_WORD(wave_ent.spawnmob, true,
185  {
186  RandomSelection_AddString(it, 1, 1);
187  });
188 
190  }
191 
192  if(spawn_point == NULL)
193  {
194  if(!inv_warning_shown)
195  {
196  inv_warning_shown = true;
197  LOG_TRACE("Warning: couldn't find any invasion_spawnpoint spawnpoints, attempting to spawn monsters in random locations");
198  }
199  entity e = spawn();
200  setsize(e, mon.m_mins, mon.m_maxs);
201 
203  monster = spawnmonster(e, tospawn, mon, NULL, NULL, e.origin, false, false, 2);
204  else
205  {
206  delete(e);
207  return;
208  }
209  }
210  else // if spawnmob field falls through (unset), fallback to mon (relying on spawnmonster for that behaviour)
211  monster = spawnmonster(spawn(), ((spawn_point.spawnmob && spawn_point.spawnmob != "") ? spawn_point.spawnmob : tospawn), mon, spawn_point, spawn_point, spawn_point.origin, false, false, 2);
212 
213  if(!monster)
214  return;
215 
216  StatusEffects_remove(STATUSEFFECT_SpawnShield, monster, STATUSEFFECT_REMOVE_NORMAL);
217 
218  if(spawn_point)
219  {
220  if(spawn_point.target_range)
221  monster.target_range = spawn_point.target_range;
222  monster.target2 = spawn_point.target2;
223  }
224 
225  if(teamplay)
226  {
227  if(spawn_point && spawn_point.team && inv_monsters_perteam[spawn_point.team] > 0)
228  monster.team = spawn_point.team;
229  else
230  {
236 
237  monster.team = RandomSelection_chosen_float;
238  }
239 
240  monster_setupcolors(monster);
241 
242  if(monster.sprite)
243  {
244  WaypointSprite_UpdateTeamRadar(monster.sprite, RADARICON_DANGER, ((monster.team) ? Team_ColorRGB(monster.team) : '1 0 0'));
245 
246  monster.sprite.team = 0;
247  monster.sprite.SendFlags |= 1;
248  }
249  }
250 
251  if(monster.monster_attack)
252  IL_REMOVE(g_monster_targets, monster);
253  monster.monster_attack = false; // it's the player's job to kill all the monsters
254 
256  monster.spawnflags |= MONSTERFLAG_MINIBOSS; // last round spawns minibosses
257 }
258 
259 void invasion_SpawnMonsters(int supermonster_count)
260 {
261  Monster chosen_monster = invasion_PickMonster(supermonster_count);
262 
263  invasion_SpawnChosenMonster(chosen_monster);
264 }
265 
267 {
269  {
270  IL_EACH(g_monsters, true,
271  {
272  Monster_Remove(it);
273  });
275 
276  Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER);
277  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER);
279  return 1;
280  }
281 
282  float total_alive_monsters = 0, supermonster_count = 0, red_alive = 0, blue_alive = 0, yellow_alive = 0, pink_alive = 0;
283 
285  {
286  if(it.monsterdef.spawnflags & MON_FLAG_SUPERMONSTER)
287  ++supermonster_count;
288  ++total_alive_monsters;
289 
290  if(teamplay)
291  switch(it.team)
292  {
293  case NUM_TEAM_1: ++red_alive; break;
294  case NUM_TEAM_2: ++blue_alive; break;
295  case NUM_TEAM_3: ++yellow_alive; break;
296  case NUM_TEAM_4: ++pink_alive; break;
297  }
298  });
299 
300  if((total_alive_monsters + inv_numkilled) < inv_maxspawned && inv_maxcurrent < inv_maxspawned)
301  {
302  if(time >= inv_lastcheck)
303  {
304  invasion_SpawnMonsters(supermonster_count);
306  }
307 
308  return 0;
309  }
310 
311  if(inv_numspawned < 1)
312  return 0; // nothing has spawned yet
313 
314  if(teamplay)
315  {
316  if(((red_alive > 0) + (blue_alive > 0) + (yellow_alive > 0) + (pink_alive > 0)) > 1)
317  return 0;
318  }
319  else if(inv_numkilled < inv_maxspawned)
320  return 0;
321 
322  entity winner = NULL;
323  float winning_score = 0, winner_team = 0;
324 
325 
326  if(teamplay)
327  {
328  if(red_alive > 0) { winner_team = NUM_TEAM_1; }
329  if(blue_alive > 0)
330  {
331  if(winner_team) { winner_team = 0; }
332  else { winner_team = NUM_TEAM_2; }
333  }
334  if(yellow_alive > 0)
335  {
336  if(winner_team) { winner_team = 0; }
337  else { winner_team = NUM_TEAM_3; }
338  }
339  if(pink_alive > 0)
340  {
341  if(winner_team) { winner_team = 0; }
342  else { winner_team = NUM_TEAM_4; }
343  }
344  }
345  else
346  {
348  float cs = GameRules_scoring_add(it, KILLS, 0);
349  if(cs > winning_score)
350  {
351  winning_score = cs;
352  winner = it;
353  }
354  });
355  }
356 
357  IL_EACH(g_monsters, true,
358  {
359  Monster_Remove(it);
360  });
362 
363  if(teamplay)
364  {
365  if(winner_team)
366  {
367  Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
368  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
369  }
370  }
371  else if(winner)
372  {
373  Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_PLAYER_WIN, winner.netname);
374  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_PLAYER_WIN, winner.netname);
375  }
376 
378 
379  return 1;
380 }
381 
383 {
384  return true;
385 }
386 
388 {
389  int numplayers = 0;
391  it.player_blocked = false;
392  ++numplayers;
393  });
394 
396  inv_roundcnt += 1; // a limiter to stop crazy counts
397 
398  inv_monsterskill = inv_roundcnt + max(1, numplayers * 0.3);
399 
400  inv_maxcurrent = 0;
401  inv_numspawned = 0;
402  inv_numkilled = 0;
403 
405 
406  if(teamplay)
407  {
413  }
414 }
415 
416 MUTATOR_HOOKFUNCTION(inv, MonsterDies)
417 {
418  entity frag_target = M_ARGV(0, entity);
419  entity frag_attacker = M_ARGV(1, entity);
420 
421  if(!(frag_target.spawnflags & MONSTERFLAG_RESPAWNED))
422  {
424  {
425  inv_numkilled += 1;
426  inv_maxcurrent -= 1;
427  }
428  if(teamplay) { inv_monsters_perteam[frag_target.team] -= 1; }
429 
430  if(IS_PLAYER(frag_attacker))
431  {
432  if(SAME_TEAM(frag_attacker, frag_target)) // in non-teamplay modes, same team = same player, so this works
433  GameRules_scoring_add(frag_attacker, KILLS, -1);
434  else
435  {
436  GameRules_scoring_add(frag_attacker, KILLS, +1);
437  if(teamplay)
438  TeamScore_AddToTeam(frag_attacker.team, ST_INV_KILLS, +1);
439  }
440  }
441  }
442 }
443 
444 MUTATOR_HOOKFUNCTION(inv, MonsterSpawn)
445 {
446  entity mon = M_ARGV(0, entity);
448 
450  return false; // allowed
451 
452  if(!(mon.spawnflags & MONSTERFLAG_SPAWNED))
453  return true;
454 
455  if(!(mon.spawnflags & MONSTERFLAG_RESPAWNED))
456  {
457  inv_numspawned += 1;
458  inv_maxcurrent += 1;
459  }
460 
461  mon.monster_skill = inv_monsterskill;
462 
463  if(mon.monsterdef.spawnflags & MON_FLAG_SUPERMONSTER)
464  Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_INVASION_SUPERMONSTER, mon.monster_name);
465 }
466 
467 MUTATOR_HOOKFUNCTION(inv, SV_StartFrame)
468 {
470  return; // uses map spawned monsters
471 
472  monsters_total = inv_maxspawned; // TODO: make sure numspawned never exceeds maxspawned
474 }
475 
476 MUTATOR_HOOKFUNCTION(inv, PlayerRegen)
477 {
478  // no regeneration in invasion, regardless of the game type
479  return true;
480 }
481 
482 MUTATOR_HOOKFUNCTION(inv, PlayerSpawn)
483 {
484  entity player = M_ARGV(0, entity);
485 
486  if(player.bot_attack)
487  IL_REMOVE(g_bot_targets, player);
488  player.bot_attack = false;
489 }
490 
491 MUTATOR_HOOKFUNCTION(inv, Damage_Calculate)
492 {
493  entity frag_attacker = M_ARGV(1, entity);
494  entity frag_target = M_ARGV(2, entity);
495  float frag_damage = M_ARGV(4, float);
496  vector frag_force = M_ARGV(6, vector);
497 
498  if(IS_PLAYER(frag_attacker) && IS_PLAYER(frag_target) && frag_attacker != frag_target)
499  {
500  frag_damage = 0;
501  frag_force = '0 0 0';
502 
503  M_ARGV(4, float) = frag_damage;
504  M_ARGV(6, vector) = frag_force;
505  }
506 }
507 
508 MUTATOR_HOOKFUNCTION(inv, BotShouldAttack)
509 {
510  entity targ = M_ARGV(1, entity);
511 
512  if(!IS_MONSTER(targ))
513  return true;
514 }
515 
516 MUTATOR_HOOKFUNCTION(inv, SetStartItems)
517 {
519  {
520  start_health = 200;
521  start_armorvalue = 200;
522  }
523 }
524 
525 MUTATOR_HOOKFUNCTION(inv, AccuracyTargetValid)
526 {
527  entity frag_target = M_ARGV(1, entity);
528 
529  if(IS_MONSTER(frag_target))
530  return MUT_ACCADD_INVALID;
531  return MUT_ACCADD_INDIFFERENT;
532 }
533 
534 MUTATOR_HOOKFUNCTION(inv, AllowMobSpawning)
535 {
536  // monster spawning disabled during an invasion
537  M_ARGV(1, string) = "You cannot spawn monsters during an invasion!";
538  return true;
539 }
540 
542 {
544  return false;
545 
546  M_ARGV(0, float) = WinningCondition_Invasion();
547  return true;
548 }
549 
551 {
552  M_ARGV(0, float) = invasion_teams;
553  return true;
554 }
555 
556 MUTATOR_HOOKFUNCTION(inv, AllowMobButcher)
557 {
558  M_ARGV(0, string) = "This command does not work during an invasion!";
559  return true;
560 }
561 
562 void invasion_ScoreRules(int inv_teams)
563 {
565  GameRules_scoring(inv_teams, 0, 0, {
566  if (inv_teams) {
567  field_team(ST_INV_KILLS, "frags", SFL_SORT_PRIO_PRIMARY);
568  }
569  field(SP_KILLS, "frags", ((inv_teams) ? SFL_SORT_PRIO_SECONDARY : SFL_SORT_PRIO_PRIMARY));
570  });
571 }
572 
573 void invasion_DelayedInit(entity this) // Do this check with a delay so we can wait for teams to be set up.
574 {
576  cvar_set("fraglimit", "0");
577 
579  {
581  }
582  else
583  invasion_teams = 0;
584 
585  independent_players = 1; // to disable extra useless scores
586 
588 
590 
592  {
595 
596  inv_roundcnt = 0;
597  inv_maxrounds = 15; // 15?
598  }
599 }
600 
602 {
603  InitializeEntity(NULL, invasion_DelayedInit, INITPRIO_GAMETYPE);
604 }
float inv_roundcnt
Definition: sv_invasion.qh:37
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
void invasion_ScoreRules(int inv_teams)
Definition: sv_invasion.qc:562
#define APP_TEAM_NUM(num, prefix)
Definition: all.qh:85
const int MONSTERFLAG_RESPAWNED
Definition: sv_monsters.qh:92
#define GameRules_scoring(teams, spprio, stprio, fields)
Definition: sv_rules.qh:53
#define IL_EACH(this, cond, body)
const int MON_FLAG_HIDDEN
Definition: monster.qh:16
IntrusiveList g_invasion_waves
Definition: sv_invasion.qh:10
int monsters_total
Definition: sv_monsters.qh:34
entity spawnmonster(entity e, string monster, Monster monster_id, entity spawnedby, entity own, vector orig, bool respwn, bool removeifinvalid, int moveflag)
Definition: sv_spawn.qc:14
const int NUM_TEAM_2
Definition: teams.qh:19
#define IL_CLEAR(this)
Remove all elements.
const int CBC_ORDER_EXCLUSIVE
Definition: base.qh:9
void invasion_SpawnMonsters(int supermonster_count)
Definition: sv_invasion.qc:259
IntrusiveList g_monster_targets
Definition: sv_monsters.qh:147
const int MONSTER_SIZE_QUAKE
Definition: monster.qh:13
string RandomSelection_chosen_string
Definition: random.qh:7
bool g_invasion
Definition: sv_invasion.qh:8
void invasion_Initialize()
Definition: sv_invasion.qc:601
void round_handler_Spawn(bool() canRoundStart_func, bool() canRoundEnd_func, void() roundStart_func)
vector m_mins
hitbox size
Definition: monster.qh:42
void target_invasion_roundend_use(entity this, entity actor, entity trigger)
Definition: sv_invasion.qc:25
float DPCONTENTS_MONSTERCLIP
vector Team_ColorRGB(int teamid)
Definition: teams.qh:76
void SetWinners(.float field, float value)
Definition: world.qc:1407
ERASEABLE void RandomSelection_Init()
Definition: random.qc:4
float TeamScore_AddToTeam(int t, float scorefield, float score)
Adds a score to the given team.
Definition: scores.qc:108
Monster invasion_PickMonster(int supermonster_count)
Definition: sv_invasion.qc:126
const int SFL_SORT_PRIO_SECONDARY
Scoring priority (NOTE: PRIMARY is used for fraglimit)
Definition: scores.qh:126
void ClearWinners()
Definition: world.qc:1422
entity() spawn
float autocvar_g_invasion_spawn_delay
Definition: sv_invasion.qc:18
float autocvar_g_invasion_warmup
Definition: sv_invasion.qc:15
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
#define GameRules_scoring_add(client, fld, value)
Definition: sv_rules.qh:78
float autocvar_g_invasion_round_timelimit
Definition: sv_invasion.qc:13
float DPCONTENTS_SKY
float DPCONTENTS_BOTCLIP
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
#define IS_MONSTER(v)
Definition: utils.qh:21
Effect is being removed by a function, calls regular removal mechanics.
Definition: all.qh:25
bool inv_endreached
Definition: sv_invasion.qc:21
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
Definition: world.qc:1157
float DPCONTENTS_PLAYERCLIP
float autocvar_g_invasion_spawnpoint_spawn_delay
Definition: sv_invasion.qc:14
#define spawn_point(name, color)
float RandomSelection_chosen_float
Definition: random.qh:6
MUTATOR_HOOKFUNCTION(inv, MonsterDies)
Definition: sv_invasion.qc:416
void CheckRules_World()
Definition: world.qc:1593
void GameRules_score_enabled(bool value)
Disabling score disables the "score" column on the scoreboard.
Definition: sv_rules.qc:28
const int MONSTER_TYPE_FLY
Definition: monster.qh:5
int autocvar_g_invasion_monster_count
Definition: sv_invasion.qc:16
#define FOREACH_WORD(words, cond, body)
Definition: iter.qh:33
const int WINNING_YES
Definition: world.qh:136
IntrusiveList g_bot_targets
Definition: api.qh:149
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
ERASEABLE float DistributeEvenly_Get(float weight)
Definition: random.qc:54
void monster_setupcolors(entity this)
Definition: sv_monsters.qc:154
RES_HEALTH
Definition: ent_cs.qc:126
#define RandomSelection_AddEnt(e, weight, priority)
Definition: random.qh:14
bool victent_present
Definition: sv_invasion.qc:20
int monsters_killed
Definition: sv_monsters.qh:35
bool inv_warning_shown
Definition: sv_invasion.qc:23
const int MONSTER_TYPE_UNDEAD
Definition: monster.qh:15
IntrusiveList g_invasion_roundends
Definition: sv_invasion.qh:9
float Q3SURFACEFLAG_SKY
entity invasion_GetWaveEntity(int wavenum)
Definition: sv_invasion.qc:156
const int MONSTERFLAG_MINIBOSS
Definition: sv_monsters.qh:89
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void Invasion_RoundStart()
Definition: sv_invasion.qc:387
bool Invasion_CheckPlayers()
Definition: sv_invasion.qc:382
entity RandomSelection_chosen_ent
Definition: random.qh:5
int WinningCondition_Invasion()
Definition: sv_invasion.qc:76
IntrusiveList g_invasion_spawns
Definition: sv_invasion.qh:11
#define NULL
Definition: post.qh:17
vector m_maxs
hitbox size
Definition: monster.qh:44
float DPCONTENTS_SOLID
void Monster_Remove(entity this)
Definition: sv_monsters.qc:852
bool autocvar_g_invasion_zombies_only
Definition: sv_invasion.qc:17
int autocvar_g_invasion_type
Definition: sv_invasion.qh:6
float invasion_teams
Definition: sv_invasion.qh:43
#define round_handler_GetEndTime()
void invasion_SpawnChosenMonster(Monster mon)
Definition: sv_invasion.qc:174
float inv_maxrounds
Definition: sv_invasion.qh:38
#define SAME_TEAM(a, b)
Definition: teams.qh:239
float teamplay
Definition: progsdefs.qc:31
#define M_ARGV(x, type)
Definition: events.qh:17
#define IS_DEAD(s)
Definition: utils.qh:26
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const int NUM_TEAM_4
Definition: teams.qh:21
float inv_monsters_perteam[17]
Definition: sv_invasion.qh:44
bool independent_players
Definition: client.qh:312
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
#define RandomSelection_AddFloat(f, weight, priority)
Definition: random.qh:15
float DPCONTENTS_BODY
float start_health
Definition: world.qh:98
void InitializeEntity(entity e, void(entity this) func, int order)
Definition: world.qc:2146
float count
Definition: powerups.qc:22
#define LOG_TRACE(...)
Definition: log.qh:81
const int MONSTER_TYPE_PASSIVE
Definition: monster.qh:14
ERASEABLE void DistributeEvenly_Init(float amount, float totalweight)
Definition: random.qc:42
float inv_maxspawned
Definition: sv_invasion.qh:36
const int WINNING_NO
Definition: world.qh:135
const int INV_TYPE_ROUND
Definition: sv_invasion.qh:50
const int MONSTER_TYPE_SWIM
Definition: monster.qh:6
float DPCONTENTS_SLIME
bool Invasion_CheckWinner()
Definition: sv_invasion.qc:266
const int NUM_TEAM_1
Definition: teams.qh:18
#define use
Definition: csprogsdefs.qh:50
best
Definition: all.qh:77
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings...
Definition: teamplay.qc:487
void invasion_DelayedInit(entity this)
Definition: sv_invasion.qc:573
float inv_lastcheck
Definition: sv_invasion.qh:40
float inv_numkilled
Definition: sv_invasion.qh:39
int autocvar_g_invasion_teams
Definition: sv_invasion.qh:5
float DPCONTENTS_DONOTENTER
IntrusiveList g_monsters
Definition: sv_monsters.qh:144
float time
Definition: csprogsdefs.qc:16
float inv_monsterskill
Definition: sv_invasion.qh:46
float start_armorvalue
Definition: world.qh:99
float inv_maxcurrent
Definition: sv_invasion.qh:41
void round_handler_Init(float the_delay, float the_count, float the_round_timelimit)
const float ST_INV_KILLS
Definition: sv_invasion.qh:48
#define FOREACH(list, cond, body)
Definition: iter.qh:19
float winning
Definition: world.qh:134
#define IS_PLAYER(v)
Definition: utils.qh:9
const int INV_TYPE_HUNT
Definition: sv_invasion.qh:51
#define BITS(n)
Definition: bits.qh:9
spawnfunc(target_invasion_roundend)
Definition: sv_invasion.qc:45
const int MON_FLAG_SUPERMONSTER
Definition: monster.qh:8
const int NUM_TEAM_3
Definition: teams.qh:20
void WinningConditionHelper(entity this)
Sets the following results for the current scores entities.
Definition: scores.qc:415
float DPCONTENTS_CORPSE
const int MONSTERFLAG_SPAWNED
Definition: sv_monsters.qh:91
const int INV_TYPE_STAGE
Definition: sv_invasion.qh:52
float DPCONTENTS_LAVA
entity invasion_PickSpawn()
Definition: sv_invasion.qc:143
float inv_numspawned
Definition: sv_invasion.qh:35