4 .entity spawnqueue_next;
5 .entity spawnqueue_prev;
7 entity spawnqueue_first;
8 entity spawnqueue_last;
10 void Spawnqueue_Insert(entity e)
14 dprint(strcat("Into queue: ", e.netname, "\n"));
15 e.spawnqueue_in = TRUE;
16 e.spawnqueue_prev = spawnqueue_last;
17 e.spawnqueue_next = world;
19 spawnqueue_last.spawnqueue_next = e;
25 void Spawnqueue_Remove(entity e)
29 dprint(strcat("Out of queue: ", e.netname, "\n"));
30 e.spawnqueue_in = FALSE;
31 if(e == spawnqueue_first)
32 spawnqueue_first = e.spawnqueue_next;
33 if(e == spawnqueue_last)
34 spawnqueue_last = e.spawnqueue_prev;
36 e.spawnqueue_prev.spawnqueue_next = e.spawnqueue_next;
38 e.spawnqueue_next.spawnqueue_prev = e.spawnqueue_prev;
39 e.spawnqueue_next = world;
40 e.spawnqueue_prev = world;
43 void Spawnqueue_Unmark(entity e)
48 numspawned = numspawned - 1;
51 void Spawnqueue_Mark(entity e)
56 numspawned = numspawned + 1;
59 float Arena_CheckWinner()
63 if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)
65 Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_OVER);
66 Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_OVER);
67 round_handler_Init(5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
78 if(e.spawned && IS_PLAYER(e))
84 Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_PLAYER_WIN, champion.netname);
85 Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_PLAYER_WIN, champion.netname);
86 UpdateFrags(champion, +1);
90 Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_TIED);
91 Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_TIED);
93 round_handler_Init(5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
97 void Arena_AddChallengers()
100 if(time < 2) // don't force players to spawn so early
103 while(numspawned < maxspawned && spawnqueue_first)
105 self = spawnqueue_first;
107 bprint ("^4", self.netname, "^4 is the next challenger\n");
109 Spawnqueue_Remove(self);
110 Spawnqueue_Mark(self);
112 self.classname = "player";
118 float prev_numspawned;
119 float Arena_CheckPlayers()
121 Arena_AddChallengers();
125 if(prev_numspawned > 0)
126 Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_MISSING_PLAYERS);
127 prev_numspawned = -1;
131 if(prev_numspawned != numspawned && numspawned == 1)
133 if(maxspawned - numspawned > 0)
134 Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_MISSING_PLAYERS, maxspawned - numspawned);
135 prev_numspawned = numspawned;
141 void Arena_RoundStart()
145 e.player_blocked = 0;
148 MUTATOR_HOOKFUNCTION(arena_ClientDisconnect)
150 Spawnqueue_Unmark(self);
151 Spawnqueue_Remove(self);
155 MUTATOR_HOOKFUNCTION(arena_reset_map_players)
157 FOR_EACH_CLIENT(self)
162 self.player_blocked = 1;
165 PutObserverInServer();
170 MUTATOR_HOOKFUNCTION(arena_MakePlayerObserver)
172 if(self.version_mismatch)
174 self.frags = FRAGS_SPECTATOR;
175 Spawnqueue_Unmark(self);
176 Spawnqueue_Remove(self);
180 self.frags = FRAGS_LMS_LOSER;
181 Spawnqueue_Insert(self);
186 MUTATOR_HOOKFUNCTION(arena_PutClientInServer)
189 self.classname = "observer";
193 MUTATOR_HOOKFUNCTION(arena_ClientConnect)
195 self.classname = "observer";
196 Spawnqueue_Insert(self);
200 MUTATOR_HOOKFUNCTION(arena_PlayerSpawn)
202 Spawnqueue_Remove(self);
203 Spawnqueue_Mark(self);
205 self.player_blocked = 1;
209 MUTATOR_HOOKFUNCTION(arena_ForbidPlayerScore_Clear)
214 MUTATOR_HOOKFUNCTION(arena_GiveFragsForKill)
217 frag_score = 0; // score will be given to the champion when the round ends
221 MUTATOR_HOOKFUNCTION(arena_PlayerDies)
223 // put dead players in the spawn queue
225 self.respawn_flags = (RESPAWN_FORCE | RESPAWN_SILENT);
227 self.respawn_flags = RESPAWN_SILENT;
228 Spawnqueue_Unmark(self);
232 MUTATOR_HOOKFUNCTION(arena_SV_StartFrame)
234 if(gameover) return 1;
235 if(time <= game_starttime || !arena_roundbased)
236 Arena_AddChallengers();
240 void arena_Initialize()
242 maxspawned = max(2, autocvar_g_arena_maxspawned);
243 arena_roundbased = autocvar_g_arena_roundbased;
246 round_handler_Spawn(Arena_CheckPlayers, Arena_CheckWinner, Arena_RoundStart);
247 round_handler_Init(5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
251 MUTATOR_DEFINITION(gamemode_arena)
253 MUTATOR_HOOK(ClientDisconnect, arena_ClientDisconnect, CBC_ORDER_ANY);
254 MUTATOR_HOOK(reset_map_players, arena_reset_map_players, CBC_ORDER_ANY);
255 MUTATOR_HOOK(MakePlayerObserver, arena_MakePlayerObserver, CBC_ORDER_ANY);
256 MUTATOR_HOOK(PutClientInServer, arena_PutClientInServer, CBC_ORDER_ANY);
257 MUTATOR_HOOK(ClientConnect, arena_ClientConnect, CBC_ORDER_ANY);
258 MUTATOR_HOOK(PlayerSpawn, arena_PlayerSpawn, CBC_ORDER_ANY);
259 MUTATOR_HOOK(ForbidPlayerScore_Clear, arena_ForbidPlayerScore_Clear, CBC_ORDER_ANY);
260 MUTATOR_HOOK(GiveFragsForKill, arena_GiveFragsForKill, CBC_ORDER_ANY);
261 MUTATOR_HOOK(PlayerDies, arena_PlayerDies, CBC_ORDER_ANY);
262 MUTATOR_HOOK(SV_StartFrame, arena_SV_StartFrame, CBC_ORDER_ANY);
266 if(time > 1) // game loads at time 1
267 error("This is a game type and it cannot be added at runtime.");
273 print("This is a game type and it cannot be removed at runtime.");