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_GetTimeLeft() <= 0)
65 FOR_EACH_REALCLIENT(e)
66 centerprint(e, "Round over, there's no winner");
67 bprint("Round over, there's no winner\n");
68 round_handler_Init(5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
79 if(e.spawned && e.classname == "player")
85 FOR_EACH_REALCLIENT(e)
86 centerprint(e, strcat("The Champion is ", champion.netname));
87 bprint("The Champion is ", champion.netname, "\n");
88 UpdateFrags(champion, +1);
92 FOR_EACH_REALCLIENT(e)
93 centerprint(e, "Round tied");
94 bprint("Round tied\n");
96 round_handler_Init(5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
100 void Arena_AddChallengers()
104 while(numspawned < maxspawned && spawnqueue_first)
106 self = spawnqueue_first;
108 bprint ("^4", self.netname, "^4 is the next challenger\n");
110 Spawnqueue_Remove(self);
111 Spawnqueue_Mark(self);
113 self.classname = "player";
119 float prev_numspawned;
120 float Arena_CheckPlayers()
124 Arena_AddChallengers();
128 if(prev_numspawned != -1)
130 FOR_EACH_REALCLIENT(e)
131 Send_CSQC_Centerprint_Generic_Expire(e, CPID_WAITING_PLAYERS);
133 prev_numspawned = -1;
137 if(prev_numspawned != numspawned && numspawned == 1)
139 FOR_EACH_REALCLIENT(e)
140 Send_CSQC_Centerprint_Generic(e, CPID_WAITING_PLAYERS, "Waiting for players to join...", -1, 0);
141 prev_numspawned = numspawned;
147 void Arena_RoundStart()
151 e.player_blocked = 0;
154 MUTATOR_HOOKFUNCTION(arena_ClientDisconnect)
156 Spawnqueue_Unmark(self);
157 Spawnqueue_Remove(self);
161 MUTATOR_HOOKFUNCTION(arena_reset_map_players)
163 FOR_EACH_CLIENT(self)
168 self.player_blocked = 1;
171 PutObserverInServer();
176 MUTATOR_HOOKFUNCTION(arena_MakePlayerObserver)
178 if(self.version_mismatch)
180 self.frags = FRAGS_SPECTATOR;
181 Spawnqueue_Unmark(self);
182 Spawnqueue_Remove(self);
186 self.frags = FRAGS_LMS_LOSER;
187 Spawnqueue_Insert(self);
192 MUTATOR_HOOKFUNCTION(arena_PutClientInServer)
195 self.classname = "observer";
199 MUTATOR_HOOKFUNCTION(arena_ClientConnect)
201 self.classname = "observer";
202 Spawnqueue_Insert(self);
206 MUTATOR_HOOKFUNCTION(arena_PlayerSpawn)
208 Spawnqueue_Remove(self);
209 Spawnqueue_Mark(self);
211 self.player_blocked = 1;
215 MUTATOR_HOOKFUNCTION(arena_PlayerPreThink)
217 self.stat_respawn_time = 0;
219 // put dead players in the spawn queue
221 if(self.deadflag && time - self.death_time >= 1.5)
227 MUTATOR_HOOKFUNCTION(arena_ForbidPlayerScore_Clear)
232 MUTATOR_HOOKFUNCTION(arena_GiveFragsForKill)
235 frag_score = 0; // score will be given to the champion when the round ends
239 MUTATOR_HOOKFUNCTION(arena_PlayerDies)
241 Spawnqueue_Unmark(self);
245 MUTATOR_HOOKFUNCTION(arena_SV_StartFrame)
247 if(arena_roundbased) return 1;
248 if(time <= game_starttime) return 1;
249 if(gameover) return 1;
251 Arena_AddChallengers();
255 void arena_Initialize()
257 maxspawned = max(2, autocvar_g_arena_maxspawned);
258 arena_roundbased = autocvar_g_arena_roundbased;
261 round_handler_Spawn(Arena_CheckPlayers, Arena_CheckWinner, Arena_RoundStart);
262 round_handler_Init(5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
266 MUTATOR_DEFINITION(gamemode_arena)
268 MUTATOR_HOOK(ClientDisconnect, arena_ClientDisconnect, CBC_ORDER_ANY);
269 MUTATOR_HOOK(reset_map_players, arena_reset_map_players, CBC_ORDER_ANY);
270 MUTATOR_HOOK(MakePlayerObserver, arena_MakePlayerObserver, CBC_ORDER_ANY);
271 MUTATOR_HOOK(PutClientInServer, arena_PutClientInServer, CBC_ORDER_ANY);
272 MUTATOR_HOOK(ClientConnect, arena_ClientConnect, CBC_ORDER_ANY);
273 MUTATOR_HOOK(PlayerSpawn, arena_PlayerSpawn, CBC_ORDER_ANY);
274 MUTATOR_HOOK(PlayerPreThink, arena_PlayerPreThink, CBC_ORDER_ANY);
275 MUTATOR_HOOK(ForbidPlayerScore_Clear, arena_ForbidPlayerScore_Clear, CBC_ORDER_ANY);
276 MUTATOR_HOOK(GiveFragsForKill, arena_GiveFragsForKill, CBC_ORDER_ANY);
277 MUTATOR_HOOK(PlayerDies, arena_PlayerDies, CBC_ORDER_ANY);
278 MUTATOR_HOOK(SV_StartFrame, arena_SV_StartFrame, CBC_ORDER_ANY);
282 if(time > 1) // game loads at time 1
283 error("This is a game type and it cannot be added at runtime.");
289 print("This is a game type and it cannot be removed at runtime.");