]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/gamemode_ca.qc
Make use of ClientConnect hook in Arena and CA
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_ca.qc
1 void CA_count_alive_players()
2 {
3         entity e;
4         total_players = redalive = bluealive = yellowalive = pinkalive = 0;
5         FOR_EACH_PLAYER(e) {
6                 if(e.team == COLOR_TEAM1)
7                 {
8                         ++total_players;
9                         if (e.health >= 1) ++redalive;
10                 }
11                 else if(e.team == COLOR_TEAM2)
12                 {
13                         ++total_players;
14                         if (e.health >= 1) ++bluealive;
15                 }
16                 else if(e.team == COLOR_TEAM3)
17                 {
18                         ++total_players;
19                         if (e.health >= 1) ++yellowalive;
20                 }
21                 else if(e.team == COLOR_TEAM4)
22                 {
23                         ++total_players;
24                         if (e.health >= 1) ++pinkalive;
25                 }
26         }
27         FOR_EACH_REALCLIENT(e) {
28                 e.redalive_stat = redalive;
29                 e.bluealive_stat = bluealive;
30                 e.yellowalive_stat = yellowalive;
31                 e.pinkalive_stat = pinkalive;
32         }
33 }
34
35 float CA_GetWinnerTeam()
36 {
37         float winner_team;
38         if(redalive >= 1)
39                 winner_team = COLOR_TEAM1;
40         if(bluealive >= 1)
41         {
42                 if(winner_team) return 0;
43                 winner_team = COLOR_TEAM2;
44         }
45         if(yellowalive >= 1)
46         {
47                 if(winner_team) return 0;
48                 winner_team = COLOR_TEAM3;
49         }
50         if(pinkalive >= 1)
51         {
52                 if(winner_team) return 0;
53                 winner_team = COLOR_TEAM4;
54         }
55         if(winner_team)
56                 return winner_team;
57         return -1; // no player left
58 }
59
60 float CA_CheckWinner()
61 {
62         entity e;
63         if(round_handler_GetTimeLeft() <= 0)
64         {
65                 FOR_EACH_REALCLIENT(e)
66                         centerprint(e, "Round over, there's no winner");
67                 bprint("Round over, there's no winner.\n");
68                 allowed_to_spawn = TRUE;
69                 return 1;
70         }
71
72         CA_count_alive_players();
73         if(CA_ALIVE_TEAMS() > 1)
74                 return 0;
75
76         float winner_team;
77         string teamname;
78         winner_team = CA_GetWinnerTeam();
79         if(winner_team > 0)
80         {
81                 teamname = ColoredTeamName(winner_team);
82                 FOR_EACH_REALCLIENT(e)
83                         centerprint(e, strcat(teamname, " wins the round"));
84                 bprint(teamname, " wins the round.\n");
85                 TeamScore_AddToTeam(winner_team, ST_SCORE, +1);
86         }
87         else if(winner_team == -1)
88         {
89                 FOR_EACH_REALCLIENT(e)
90                         centerprint(e, "Round tied");
91                 bprint("Round tied.\n");
92         }
93
94         allowed_to_spawn = TRUE;
95         return 1;
96 }
97
98 void CA_RoundStart()
99 {
100         if(inWarmupStage)
101                 allowed_to_spawn = TRUE;
102         else
103                 allowed_to_spawn = FALSE;
104 }
105
106 float prev_total_players;
107 float CA_CheckTeams()
108 {
109         entity e;
110         allowed_to_spawn = TRUE;
111         CA_count_alive_players();
112         if(CA_ALIVE_TEAMS_OK())
113         {
114                 if(prev_total_players != -1)
115                 {
116                         FOR_EACH_REALCLIENT(e)
117                                 Send_CSQC_Centerprint_Generic_Expire(e, CPID_WAITING_PLAYERS);
118                 }
119                 prev_total_players = -1;
120                 return 1;
121         }
122         if(prev_total_players != total_players)
123         {
124                 string teams_missing;
125                 if(!redalive)   teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM1), ", ");
126                 if(!bluealive)  teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM2), ", ");
127                 if(ca_teams >= 3)
128                 if(!yellowalive)        teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM3), ", ");
129                 if(ca_teams == 4)
130                 if(!pinkalive)  teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM4), ", ");
131                 teams_missing = substring(teams_missing, 0, strlen(teams_missing)-2);
132
133                 FOR_EACH_REALCLIENT(e)
134                         Send_CSQC_Centerprint_Generic(e, CPID_WAITING_PLAYERS, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, 0);
135                 prev_total_players = total_players;
136         }
137         return 0;
138 }
139
140 MUTATOR_HOOKFUNCTION(ca_PlayerSpawn)
141 {
142         self.caplayer = TRUE;
143         return 1;
144 }
145
146 MUTATOR_HOOKFUNCTION(ca_PutClientInServer)
147 {
148         if(clienttype(self) == CLIENTTYPE_BOT)
149                 self.caplayer = TRUE;
150         if(!allowed_to_spawn)
151                 self.classname = "observer";
152         return 1;
153 }
154
155 MUTATOR_HOOKFUNCTION(ca_reset_map_players)
156 {
157         FOR_EACH_CLIENT(self)
158         {
159                 if(self.caplayer)
160                 {
161                         self.classname = "player";
162                         PutClientInServer();
163                 }
164         }
165         return 1;
166 }
167
168 MUTATOR_HOOKFUNCTION(ca_ClientConnect)
169 {
170         self.classname = "observer";
171         return 1;
172 }
173
174 MUTATOR_HOOKFUNCTION(ca_reset_map_global)
175 {
176         allowed_to_spawn = TRUE;
177         return 1;
178 }
179
180 MUTATOR_HOOKFUNCTION(ca_GetTeamCount)
181 {
182         ca_teams = autocvar_g_ca_teams_override;
183         if(ca_teams < 2)
184                 ca_teams = autocvar_g_ca_teams;
185         ca_teams = bound(2, ca_teams, 4);
186         ret_float = ca_teams;
187         return 1;
188 }
189
190 MUTATOR_HOOKFUNCTION(ca_PlayerPreThink)
191 {
192         if(!allowed_to_spawn)
193                 self.stat_respawn_time = 0;
194         return 1;
195 }
196
197 MUTATOR_HOOKFUNCTION(ca_ForbidPlayerScore_Clear)
198 {
199         return 1;
200 }
201
202 MUTATOR_HOOKFUNCTION(ca_MakePlayerObserver)
203 {
204         if(self.caplayer)
205                 self.frags = FRAGS_LMS_LOSER;
206         return 1;
207 }
208
209 MUTATOR_HOOKFUNCTION(ca_ForbidThrowCurrentWeapon)
210 {
211         return 1;
212 }
213
214 void ca_Initialize()
215 {
216         allowed_to_spawn = TRUE;
217
218         round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart, 5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
219
220         addstat(STAT_REDALIVE, AS_INT, redalive_stat);
221         addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
222         addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
223         addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat);
224 }
225
226 MUTATOR_DEFINITION(gamemode_ca)
227 {
228         MUTATOR_HOOK(PlayerSpawn, ca_PlayerSpawn, CBC_ORDER_ANY);
229         MUTATOR_HOOK(PutClientInServer, ca_PutClientInServer, CBC_ORDER_ANY);
230         MUTATOR_HOOK(MakePlayerObserver, ca_MakePlayerObserver, CBC_ORDER_ANY);
231         MUTATOR_HOOK(ClientConnect, ca_ClientConnect, CBC_ORDER_ANY);
232         MUTATOR_HOOK(reset_map_global, ca_reset_map_global, CBC_ORDER_ANY);
233         MUTATOR_HOOK(reset_map_players, ca_reset_map_players, CBC_ORDER_ANY);
234         MUTATOR_HOOK(GetTeamCount, ca_GetTeamCount, CBC_ORDER_EXCLUSIVE);
235         MUTATOR_HOOK(PlayerPreThink, ca_PlayerPreThink, CBC_ORDER_ANY);
236         MUTATOR_HOOK(ForbidPlayerScore_Clear, ca_ForbidPlayerScore_Clear, CBC_ORDER_ANY);
237         MUTATOR_HOOK(ForbidThrowCurrentWeapon, ca_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
238
239         MUTATOR_ONADD
240         {
241                 if(time > 1) // game loads at time 1
242                         error("This is a game type and it cannot be added at runtime.");
243                 ca_Initialize();
244         }
245
246         MUTATOR_ONREMOVE
247         {
248                 error("This is a game type and it cannot be removed at runtime.");
249         }
250
251         return 0;
252 }