]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/gamemode_arena.qc
Small cleanup, get rid of a redundant check, an unused variable and an outdated comment
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_arena.qc
1 void Spawnqueue_Insert(entity e)
2 {
3         if(e.spawnqueue_in)
4                 return;
5         dprint(strcat("Into queue: ", e.netname, "\n"));
6         e.spawnqueue_in = TRUE;
7         e.spawnqueue_prev = spawnqueue_last;
8         e.spawnqueue_next = world;
9         if(spawnqueue_last)
10                 spawnqueue_last.spawnqueue_next = e;
11         spawnqueue_last = e;
12         if(!spawnqueue_first)
13                 spawnqueue_first = e;
14 }
15
16 void Spawnqueue_Remove(entity e)
17 {
18         if(!e.spawnqueue_in)
19                 return;
20         dprint(strcat("Out of queue: ", e.netname, "\n"));
21         e.spawnqueue_in = FALSE;
22         if(e == spawnqueue_first)
23                 spawnqueue_first = e.spawnqueue_next;
24         if(e == spawnqueue_last)
25                 spawnqueue_last = e.spawnqueue_prev;
26         if(e.spawnqueue_prev)
27                 e.spawnqueue_prev.spawnqueue_next = e.spawnqueue_next;
28         if(e.spawnqueue_next)
29                 e.spawnqueue_next.spawnqueue_prev = e.spawnqueue_prev;
30         e.spawnqueue_next = world;
31         e.spawnqueue_prev = world;
32 }
33
34 void Spawnqueue_Unmark(entity e)
35 {
36         if(!e.spawned)
37                 return;
38         e.spawned = FALSE;
39         numspawned = numspawned - 1;
40 }
41
42 void Spawnqueue_Mark(entity e)
43 {
44         if(e.spawned)
45                 return;
46         e.spawned = TRUE;
47         numspawned = numspawned + 1;
48 }
49
50 float Arena_CheckWinner()
51 {
52         entity e;
53
54         // FIXME do this only once (on round start)
55         FOR_EACH_PLAYER(e)
56                 e.player_blocked = 0;
57
58         if(round_handler_GetTimeLeft() <= 0)
59         {
60                 FOR_EACH_REALCLIENT(e)
61                         centerprint(e, "Round over, there's no winner");
62                 bprint("Round over, there's no winner\n");
63                 return 1;
64         }
65
66         if(numspawned > 1)
67                 return 0;
68
69         entity champion;
70         champion = world;
71         FOR_EACH_CLIENT(e)
72         {
73                 if(e.spawned && e.classname == "player")
74                         champion = e;
75         }
76
77         if(champion)
78         {
79                 FOR_EACH_REALCLIENT(e)
80                         centerprint(e, strcat("The Champion is ", champion.netname));
81                 bprint("The Champion is ", champion.netname, "\n");
82                 UpdateFrags(champion, +1);
83         }
84         else
85         {
86                 FOR_EACH_REALCLIENT(e)
87                         centerprint(e, "Round tied");
88                 bprint("Round tied\n");
89         }
90         return 1;
91 }
92 void Arena_AddChallengers()
93 {
94         entity e;
95         e = self;
96         while(numspawned < maxspawned && spawnqueue_first)
97         {
98                 self = spawnqueue_first;
99
100                 bprint ("^4", self.netname, "^4 is the next challenger\n");
101
102                 Spawnqueue_Remove(self);
103                 Spawnqueue_Mark(self);
104
105                 self.classname = "player";
106                 PutClientInServer();
107         }
108         self = e;
109 }
110
111 float prev_numspawned;
112 float Arena_CheckPlayers()
113 {
114         entity e;
115
116         Arena_AddChallengers();
117
118         if(numspawned >= 2)
119         {
120                 if(prev_numspawned != -1)
121                 {
122                         FOR_EACH_REALCLIENT(e)
123                                 Send_CSQC_Centerprint_Generic_Expire(e, CPID_WAITING_PLAYERS);
124                 }
125                 prev_numspawned = -1;
126                 return 1;
127         }
128
129         if(prev_numspawned != numspawned && numspawned == 1)
130         {
131                 FOR_EACH_REALCLIENT(e)
132                         Send_CSQC_Centerprint_Generic(e, CPID_WAITING_PLAYERS, "Waiting for players to join...", -1, 0);
133                 prev_numspawned = numspawned;
134         }
135
136         return 0;
137 }
138
139 MUTATOR_HOOKFUNCTION(arena_ClientDisconnect)
140 {
141         Spawnqueue_Unmark(self);
142         Spawnqueue_Remove(self);
143         return 1;
144 }
145
146 MUTATOR_HOOKFUNCTION(arena_reset_map_players)
147 {
148         FOR_EACH_CLIENT(self)
149         {
150                 if(self.spawned)
151                 {
152                         PutClientInServer();
153                         self.player_blocked = 1;
154                 }
155                 else
156                         PutObserverInServer();
157         }
158         return 1;
159 }
160
161 MUTATOR_HOOKFUNCTION(arena_MakePlayerObserver)
162 {
163         self.frags = FRAGS_PLAYER;
164         if(self.version_mismatch)
165         {
166                 Spawnqueue_Unmark(self);
167                 Spawnqueue_Remove(self);
168         }
169         else
170                 Spawnqueue_Insert(self);
171         return 1;
172 }
173
174 MUTATOR_HOOKFUNCTION(arena_PutClientInServer)
175 {
176         if(!self.spawned)
177                 self.classname = "observer";
178         return 1;
179 }
180
181 MUTATOR_HOOKFUNCTION(arena_PlayerSpawn)
182 {
183         Spawnqueue_Remove(self);
184         Spawnqueue_Mark(self);
185         if(arena_roundbased)
186                 self.player_blocked = 1;
187         return 1;
188 }
189
190 MUTATOR_HOOKFUNCTION(arena_PlayerPreThink)
191 {
192         self.stat_respawn_time = 0;
193
194         // put dead players in the spawn queue
195         if(arena_roundbased)
196         if(self.deadflag && time - self.death_time >= 1.5)
197                 PutClientInServer();
198
199         return 1;
200 }
201
202 MUTATOR_HOOKFUNCTION(arena_ForbidPlayerScore_Clear)
203 {
204         return 1;
205 }
206
207 MUTATOR_HOOKFUNCTION(arena_GiveFragsForKill)
208 {
209         if(arena_roundbased)
210                 frag_score = 0;
211         return 1;
212 }
213
214 MUTATOR_HOOKFUNCTION(arena_PlayerDies)
215 {
216         Spawnqueue_Unmark(self);
217         return 1;
218 }
219
220 MUTATOR_HOOKFUNCTION(arena_SV_StartFrame)
221 {
222         if(arena_roundbased) return 1;
223         if(time <= game_starttime) return 1;
224         if(gameover) return 1;
225
226         Arena_AddChallengers();
227         return 1;
228 }
229
230 void arena_Initialize()
231 {
232         maxspawned = max(2, autocvar_g_arena_maxspawned);
233         arena_roundbased = autocvar_g_arena_roundbased;
234         if(arena_roundbased)
235                 round_handler_Spawn(Arena_CheckPlayers, Arena_CheckWinner, 5, autocvar_g_arena_warmup, autocvar_g_arena_round_timelimit);
236 }
237
238 MUTATOR_DEFINITION(gamemode_arena)
239 {
240         MUTATOR_HOOK(ClientDisconnect, arena_ClientDisconnect, CBC_ORDER_ANY);
241         MUTATOR_HOOK(reset_map_players, arena_reset_map_players, CBC_ORDER_ANY);
242         MUTATOR_HOOK(MakePlayerObserver, arena_MakePlayerObserver, CBC_ORDER_ANY);
243         MUTATOR_HOOK(PutClientInServer, arena_PutClientInServer, CBC_ORDER_ANY);
244         MUTATOR_HOOK(PlayerSpawn, arena_PlayerSpawn, CBC_ORDER_ANY);
245         MUTATOR_HOOK(PlayerPreThink, arena_PlayerPreThink, CBC_ORDER_ANY);
246         MUTATOR_HOOK(ForbidPlayerScore_Clear, arena_ForbidPlayerScore_Clear, CBC_ORDER_ANY);
247         MUTATOR_HOOK(GiveFragsForKill, arena_GiveFragsForKill, CBC_ORDER_ANY);
248         MUTATOR_HOOK(PlayerDies, arena_PlayerDies, CBC_ORDER_ANY);
249         MUTATOR_HOOK(SV_StartFrame, arena_SV_StartFrame, CBC_ORDER_ANY);
250
251         MUTATOR_ONADD
252         {
253                 if(time > 1) // game loads at time 1
254                         error("This is a game type and it cannot be added at runtime.");
255                 arena_Initialize();
256         }
257
258         MUTATOR_ONREMOVE
259         {
260                 error("This is a game type and it cannot be removed at runtime.");
261         }
262
263         return 0;
264 }