From f71816f8153c9628617d885e6d9406dacff127dd Mon Sep 17 00:00:00 2001 From: terencehill Date: Tue, 25 Dec 2012 15:23:59 +0100 Subject: [PATCH] Add Clan Arena to the mutator system --- qcsrc/server/arena.qc | 242 ++++----------------------- qcsrc/server/cl_client.qc | 4 +- qcsrc/server/cl_player.qc | 2 +- qcsrc/server/cl_weapons.qc | 2 +- qcsrc/server/command/cmd.qc | 3 +- qcsrc/server/defs.qh | 4 - qcsrc/server/mutators/base.qh | 3 + qcsrc/server/mutators/gamemode_ca.qc | 211 +++++++++++++++++++++++ qcsrc/server/mutators/gamemode_ca.qh | 10 ++ qcsrc/server/mutators/mutators.qh | 1 + qcsrc/server/progs.src | 2 + qcsrc/server/scores.qc | 3 +- qcsrc/server/teamplay.qc | 12 +- 13 files changed, 267 insertions(+), 232 deletions(-) create mode 100644 qcsrc/server/mutators/gamemode_ca.qc create mode 100644 qcsrc/server/mutators/gamemode_ca.qh diff --git a/qcsrc/server/arena.qc b/qcsrc/server/arena.qc index 4f986d138..d31d2f4e7 100644 --- a/qcsrc/server/arena.qc +++ b/qcsrc/server/arena.qc @@ -9,18 +9,11 @@ entity spawnqueue_first; entity spawnqueue_last; entity champion; float warmup; -.float caplayer; void PutObserverInServer(); void PutClientInServer(); float next_round; -float redalive, bluealive, yellowalive, pinkalive; -.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat; -float red_players, blue_players, yellow_players, pink_players; -float total_players; -#define CA_TEAMS() ((red_players > 0) + (blue_players > 0) + (yellow_players > 0) + (pink_players > 0)) -#define CA_TEAMS_OK() (CA_TEAMS() == ca_teams) /** * Resets the state of all clients, items, flags, runes, keys, weapons, waypoints, ... of the map. @@ -40,13 +33,6 @@ void reset_map(float dorespawn) if(autocvar_g_arena_warmup > 0) warmup += autocvar_g_arena_warmup; } - else if(g_ca) - { - warmup = max(time, game_starttime); - if(autocvar_g_ca_warmup > 0) - warmup += autocvar_g_ca_warmup; - allowed_to_spawn = 1; - } else if(g_race || g_cts) race_ReadyRestart(); else MUTATOR_CALLHOOK(reset_map_global); @@ -95,10 +81,6 @@ void reset_map(float dorespawn) else PutObserverInServer(); } - else if(g_ca && self.caplayer) { - self.classname = "player"; - PutClientInServer(); - } else { /* @@ -201,13 +183,7 @@ void Arena_Warmup() if(gameover) { - if(warmup && time < warmup) - { - FOR_EACH_REALCLIENT(e) - Send_CSQC_Centerprint_Generic_Expire(e, CPID_ROUND_STARTING); - warmup = 0; - } - if(champion && g_arena) + if(champion) { FOR_EACH_REALCLIENT(e) centerprint(e, strcat("The Champion is ", champion.netname)); @@ -220,31 +196,9 @@ void Arena_Warmup() f = ceil(warmup - time); - if(g_ca) - { - if(inWarmupStage) - allowed_to_spawn = 1; - else if (warmup == 0) //first warmup or warmup cleared - { - if(CA_TEAMS_OK()) - reset_map(TRUE); - else if(f != roundStartTime_prev) - { - if(roundStartTime_prev & 1) // msg every 2 seconds - if(roundStartTime_prev - f == 1) // block sudden msg - FOR_EACH_REALCLIENT(self) - Send_CSQC_Centerprint_Generic(self, CPID_ROUND_STARTING, "^1Need at least 1 player in each team to play CA", 2, 0); - roundStartTime_prev = f; - } - return; - } - } - if(time < warmup && !inWarmupStage) { - if (g_ca) - allowed_to_spawn = 1; - else if(champion && g_arena) + if(champion) { FOR_EACH_REALCLIENT(e) centerprint(e, strcat("The Champion is ", champion.netname)); @@ -253,11 +207,6 @@ void Arena_Warmup() if(f != roundStartTime_prev) { roundStartTime_prev = f; - if(g_ca && !CA_TEAMS_OK()) { - warmup = 0; - return; - } - if(f == 5) Announce("prepareforbattle"); else if(f == 3) @@ -271,36 +220,24 @@ void Arena_Warmup() Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "Round will start in %d", 1, f); } - if (g_arena) { - FOR_EACH_CLIENT(e) - { - if(e.spawned && e.classname == "player") - e.player_blocked = 1; - } + FOR_EACH_CLIENT(e) + { + if(e.spawned && e.classname == "player") + e.player_blocked = 1; } } else if(f > -1 && f != roundStartTime_prev && !inWarmupStage) { roundStartTime_prev = f; - if(g_ca) { - if(CA_TEAMS_OK()) - allowed_to_spawn = 0; - else - { - warmup = 0; - return; - } - } + Announce("begin"); FOR_EACH_REALCLIENT(e) Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "^1Begin!", 1, 0); - if(g_arena) { - FOR_EACH_CLIENT(e) - { - if(e.player_blocked) - e.player_blocked = 0; - } + FOR_EACH_CLIENT(e) + { + if(e.player_blocked) + e.player_blocked = 0; } } @@ -309,80 +246,6 @@ void Arena_Warmup() champion = world; } -void count_players() -{ - // count amount of players in each team - total_players = red_players = blue_players = yellow_players = pink_players = 0; - FOR_EACH_PLAYER(self) { - if (self.team == COLOR_TEAM1) - { - red_players += 1; - total_players += 1; - } - else if (self.team == COLOR_TEAM2) - { - blue_players += 1; - total_players += 1; - } - else if (self.team == COLOR_TEAM3) - { - yellow_players += 1; - total_players += 1; - } - else if (self.team == COLOR_TEAM4) - { - pink_players += 1; - total_players += 1; - } - } -} - -void count_alive_players() -{ - redalive = bluealive = yellowalive = pinkalive = 0; - FOR_EACH_PLAYER(self) { - if (self.team == COLOR_TEAM1 && self.health >= 1) - redalive += 1; - else if (self.team == COLOR_TEAM2 && self.health >= 1) - bluealive += 1; - else if (self.team == COLOR_TEAM3 && self.health >= 1) - yellowalive += 1; - else if (self.team == COLOR_TEAM4 && self.health >= 1) - pinkalive += 1; - } - FOR_EACH_REALCLIENT(self) { - self.redalive_stat = redalive; - self.bluealive_stat = bluealive; - self.yellowalive_stat = yellowalive; - self.pinkalive_stat = pinkalive; - } -} - -float CA_GetWinnerTeam() -{ - float winner_team; - if(redalive >= 1) - winner_team = COLOR_TEAM1; - if(bluealive >= 1) - { - if(winner_team) return 0; - winner_team = COLOR_TEAM2; - } - if(yellowalive >= 1) - { - if(winner_team) return 0; - winner_team = COLOR_TEAM3; - } - if(pinkalive >= 1) - { - if(winner_team) return 0; - winner_team = COLOR_TEAM4; - } - if(winner_team) - return winner_team; - return -1; // no player left -} - /** * This function finds out whether an arena round is over 1 player is left. * It determines the last player who's still alive and saves it's entity reference @@ -395,82 +258,43 @@ void Spawnqueue_Check() if(time < warmup + 1 || inWarmupStage || intermission_running) return; - if(g_ca) { - float winner_team; - if(allowed_to_spawn) // round is not started yet - return; - if(!next_round) { - winner_team = CA_GetWinnerTeam(); - if(winner_team) { - if(winner_team > 0) { - FOR_EACH_CLIENT(self) - centerprint(self, strcat(ColoredTeamName(winner_team), " wins the round")); - TeamScore_AddToTeam(winner_team, ST_SCORE, +1); - } - else //if(winner_team == -1) // no player left - FOR_EACH_CLIENT(self) centerprint(self, "^7Round tied"); - next_round = -1; - } - else if(time - warmup > autocvar_g_ca_round_timelimit) { - FOR_EACH_CLIENT(self) centerprint(self, "^7Round tied"); - next_round = time + 5; - } - } - else if(next_round == -1) { - // wait for killed players to be put as spectators - if(!CA_TEAMS_OK()) - next_round = time + 5; - } - else if((next_round > 0 && next_round < time)) + //extend next_round if it isn't set yet and only 1 player is spawned + if(!next_round) + if(numspawned < 2) + next_round = time + 3; + + if(!arena_roundbased || (next_round && next_round < time && player_count > 1)) + { + next_round = 0; + + if(arena_roundbased) { - next_round = 0; + champion = find(world, classname, "player"); + while(champion && champion.deadflag) + champion = find(champion, classname, "player"); reset_map(TRUE); } - } else { // arena - //extend next_round if it isn't set yet and only 1 player is spawned - if(!next_round) - if(numspawned < 2) - next_round = time + 3; - if(!arena_roundbased || (next_round && next_round < time && player_count > 1)) + while(numspawned < maxspawned && spawnqueue_first) { - next_round = 0; + self = spawnqueue_first; - if(arena_roundbased) - { - champion = find(world, classname, "player"); - while(champion && champion.deadflag) - champion = find(champion, classname, "player"); - reset_map(TRUE); - } - - while(numspawned < maxspawned && spawnqueue_first) - { - self = spawnqueue_first; - - bprint ("^4", self.netname, "^4 is the next challenger\n"); + bprint ("^4", self.netname, "^4 is the next challenger\n"); - Spawnqueue_Remove(self); - Spawnqueue_Mark(self); + Spawnqueue_Remove(self); + Spawnqueue_Mark(self); - self.classname = "player"; - PutClientInServer(); - } + self.classname = "player"; + PutClientInServer(); } } } void Arena_Main() { - if(!(g_ca || g_arena)) + if(!g_arena) return; - - if(g_ca) - { - count_players(); - count_alive_players(); - } - if(!g_arena || arena_roundbased) + if(arena_roundbased) Arena_Warmup(); Spawnqueue_Check(); } diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 728e62c7a..e4bd68521 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -837,8 +837,6 @@ void PutClientInServer (void) Spawnqueue_Remove(self); Spawnqueue_Mark(self); } - else if(g_ca) - self.caplayer = 1; self.event_damage = PlayerDamage; @@ -2559,7 +2557,7 @@ void PlayerPreThink (void) self.stat_allow_oldnexbeam = autocvar_g_allow_oldnexbeam; self.stat_leadlimit = autocvar_leadlimit; - if(g_arena || (g_ca && !allowed_to_spawn)) + if(g_arena) self.stat_respawn_time = 0; else self.stat_respawn_time = self.respawn_time; diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 3b03f8e95..23294ed4e 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -439,7 +439,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht float valid_damage_for_weaponstats; float excess; - if((g_arena && numspawned < 2) || (g_ca && allowed_to_spawn) && !inWarmupStage) + if((g_arena && numspawned < 2) && !inWarmupStage) return; dh = max(self.health, 0); diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc index 0b12297c7..35b920309 100644 --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@ -374,7 +374,7 @@ void W_WeaponFrame() if (frametime) self.weapon_frametime = frametime; - if(((arena_roundbased || g_ca) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown)) + if(((g_arena && arena_roundbased) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown)) return; if(round_handler_IsActive() && !round_handler_IsRoundStarted()) diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 530646afd..dea46bbcb 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -154,9 +154,8 @@ void ClientCommand_join(float request) { if(nJoinAllowed(self)) { - if(g_ca) { self.caplayer = 1; } if(autocvar_g_campaign) { campaign_bots_may_start = 1; } - + self.classname = "player"; PlayerScore_Clear(self); bprint ("^4", self.netname, "^4 is playing now\n"); diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 0b3d1e752..9313e5aa8 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -58,8 +58,6 @@ float team1_score, team2_score, team3_score, team4_score; float maxclients; -float ca_teams; - // Fields .void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) event_damage; @@ -635,8 +633,6 @@ string deathmessage; .float hagar_load; -float allowed_to_spawn; // boolean variable used by the clan arena code to determine if a player can spawn (after the round has ended) - float serverflags; .float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh index 1f42d3059..2a3eb795e 100644 --- a/qcsrc/server/mutators/base.qh +++ b/qcsrc/server/mutators/base.qh @@ -54,6 +54,9 @@ MUTATOR_HOOKABLE(reset_map_global); MUTATOR_HOOKABLE(reset_map_players); // called in reset_map +MUTATOR_HOOKABLE(ForbidPlayerScore_Clear); + // returns 1 if clearing player score shall not be allowed + MUTATOR_HOOKABLE(ClientDisconnect); // called when a player disconnects diff --git a/qcsrc/server/mutators/gamemode_ca.qc b/qcsrc/server/mutators/gamemode_ca.qc new file mode 100644 index 000000000..03e68c05d --- /dev/null +++ b/qcsrc/server/mutators/gamemode_ca.qc @@ -0,0 +1,211 @@ +void CA_count_alive_players() +{ + entity e; + total_players = redalive = bluealive = yellowalive = pinkalive = 0; + FOR_EACH_PLAYER(e) { + if(e.team == COLOR_TEAM1) + { + ++total_players; + if (e.health >= 1) ++redalive; + } + else if(e.team == COLOR_TEAM2) + { + ++total_players; + if (e.health >= 1) ++bluealive; + } + else if(e.team == COLOR_TEAM3) + { + ++total_players; + if (e.health >= 1) ++yellowalive; + } + else if(e.team == COLOR_TEAM4) + { + ++total_players; + if (e.health >= 1) ++pinkalive; + } + } + FOR_EACH_REALCLIENT(e) { + e.redalive_stat = redalive; + e.bluealive_stat = bluealive; + e.yellowalive_stat = yellowalive; + e.pinkalive_stat = pinkalive; + } +} + +float CA_GetWinnerTeam() +{ + float winner_team; + if(redalive >= 1) + winner_team = COLOR_TEAM1; + if(bluealive >= 1) + { + if(winner_team) return 0; + winner_team = COLOR_TEAM2; + } + if(yellowalive >= 1) + { + if(winner_team) return 0; + winner_team = COLOR_TEAM3; + } + if(pinkalive >= 1) + { + if(winner_team) return 0; + winner_team = COLOR_TEAM4; + } + if(winner_team) + return winner_team; + return -1; // no player left +} + +float CA_CheckWinner() +{ + // TODO round tied if(time - warmup > autocvar_g_ca_round_timelimit + + if(inWarmupStage) + allowed_to_spawn = TRUE; + else + allowed_to_spawn = FALSE; + + CA_count_alive_players(); + if(CA_ALIVE_TEAMS() > 1) + return 0; + + entity e; + float winner_team; + string teamname; + winner_team = CA_GetWinnerTeam(); + if(winner_team > 0) + { + teamname = ColoredTeamName(winner_team); + FOR_EACH_REALCLIENT(e) + centerprint(e, strcat(teamname, " wins the round")); + bprint(teamname, " wins the round.\n"); + TeamScore_AddToTeam(winner_team, ST_SCORE, +1); + } + else if(winner_team == -1) + { + FOR_EACH_REALCLIENT(e) + centerprint(e, "Round tied"); + bprint("Round tied.\n"); + } + + allowed_to_spawn = TRUE; + return 1; +} + +float prev_total_players; +float CA_CheckTeams() +{ + entity e; + allowed_to_spawn = TRUE; + CA_count_alive_players(); + if(CA_ALIVE_TEAMS_OK()) + { + if(prev_total_players != -1) + { + FOR_EACH_REALCLIENT(e) + Send_CSQC_Centerprint_Generic_Expire(e, CPID_WAITING_PLAYERS); + } + prev_total_players = -1; + return 1; + } + if(prev_total_players != total_players) + { + string teams_missing; + if(!redalive) teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM1), ", "); + if(!bluealive) teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM2), ", "); + if(ca_teams >= 3) + if(!yellowalive) teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM3), ", "); + if(ca_teams == 4) + if(!pinkalive) teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM4), ", "); + teams_missing = substring(teams_missing, 0, strlen(teams_missing)-2); + + FOR_EACH_REALCLIENT(e) + Send_CSQC_Centerprint_Generic(e, CPID_WAITING_PLAYERS, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, 0); + prev_total_players = total_players; + } + return 0; +} + +MUTATOR_HOOKFUNCTION(ca_PlayerSpawn) +{ + self.caplayer = TRUE; + return 1; +} + +MUTATOR_HOOKFUNCTION(ca_reset_map_players) +{ + FOR_EACH_CLIENT(self) + { + if(self.caplayer) + { + self.classname = "player"; + PutClientInServer(); + } + } + return 1; +} + +MUTATOR_HOOKFUNCTION(ca_reset_map_global) +{ + allowed_to_spawn = TRUE; + return 1; +} + +MUTATOR_HOOKFUNCTION(ca_GetTeamCount) +{ + ca_teams = autocvar_g_ca_teams_override; + if(ca_teams < 2) + ca_teams = autocvar_g_ca_teams; + ca_teams = bound(2, ca_teams, 4); + ret_float = ca_teams; + return 1; +} + +MUTATOR_HOOKFUNCTION(ca_PlayerPreThink) +{ + if(!allowed_to_spawn) + self.stat_respawn_time = 0; + return 1; +} + +MUTATOR_HOOKFUNCTION(ca_ForbidPlayerScore_Clear) +{ + return 1; +} + +void ca_Initialize() +{ + allowed_to_spawn = TRUE; + + round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, 5, autocvar_g_ca_warmup); + + addstat(STAT_REDALIVE, AS_INT, redalive_stat); + addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat); + addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat); + addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat); +} + +MUTATOR_DEFINITION(gamemode_ca) +{ + MUTATOR_HOOK(PlayerSpawn, ca_PlayerSpawn, CBC_ORDER_ANY); + MUTATOR_HOOK(reset_map_global, ca_reset_map_global, CBC_ORDER_ANY); + MUTATOR_HOOK(reset_map_players, ca_reset_map_players, CBC_ORDER_ANY); + MUTATOR_HOOK(GetTeamCount, ca_GetTeamCount, CBC_ORDER_EXCLUSIVE); + MUTATOR_HOOK(PlayerPreThink, ca_PlayerPreThink, CBC_ORDER_ANY); + MUTATOR_HOOK(ForbidPlayerScore_Clear, ca_ForbidPlayerScore_Clear, CBC_ORDER_ANY); + + MUTATOR_ONADD + { + if(time > 1) // game loads at time 1 + error("This is a game type and it cannot be added at runtime."); + ca_Initialize(); + } + + MUTATOR_ONREMOVE + { + error("This is a game type and it cannot be removed at runtime."); + } + + return 0; +} diff --git a/qcsrc/server/mutators/gamemode_ca.qh b/qcsrc/server/mutators/gamemode_ca.qh new file mode 100644 index 000000000..8d493bb31 --- /dev/null +++ b/qcsrc/server/mutators/gamemode_ca.qh @@ -0,0 +1,10 @@ +.float caplayer; +float total_players; +float redalive, bluealive, yellowalive, pinkalive; +.float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat; +#define CA_ALIVE_TEAMS() ((redalive > 0) + (bluealive > 0) + (yellowalive > 0) + (pinkalive > 0)) +#define CA_ALIVE_TEAMS_OK() (CA_ALIVE_TEAMS() == ca_teams) +float ca_teams; + +float allowed_to_spawn; + diff --git a/qcsrc/server/mutators/mutators.qh b/qcsrc/server/mutators/mutators.qh index 2ac6094d3..df479d9f9 100644 --- a/qcsrc/server/mutators/mutators.qh +++ b/qcsrc/server/mutators/mutators.qh @@ -1,3 +1,4 @@ +MUTATOR_DECLARATION(gamemode_ca); MUTATOR_DECLARATION(gamemode_keyhunt); MUTATOR_DECLARATION(gamemode_freezetag); MUTATOR_DECLARATION(gamemode_keepaway); diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index 23e872df2..b077f2e4d 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -29,6 +29,7 @@ defs.qh // Should rename this, it has fields and globals mutators/base.qh mutators/mutators.qh +mutators/gamemode_ca.qh mutators/gamemode_ctf.qh mutators/gamemode_keyhunt.qh // TODO fix this mutators/gamemode_keepaway.qh @@ -211,6 +212,7 @@ round_handler.qc ../common/explosion_equation.qc mutators/base.qc +mutators/gamemode_ca.qc mutators/gamemode_ctf.qc mutators/gamemode_freezetag.qc mutators/gamemode_keyhunt.qc diff --git a/qcsrc/server/scores.qc b/qcsrc/server/scores.qc index 102dd6a33..8f90cec59 100644 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@ -252,8 +252,9 @@ void PlayerScore_Clear(entity player) if(teamscores_entities_count) return; + if(MUTATOR_CALLHOOK(ForbidPlayerScore_Clear)) return; if(g_lms) return; - if(g_arena || g_ca) return; + if(g_arena) return; if(g_cts) return; // in CTS, you don't lose score by observing if(g_race && g_race_qualifying) return; // in qualifying, you don't lose score by observing diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index 0314104b1..2a82b164f 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -181,15 +181,7 @@ void InitGameplayMode() ActivateTeamplay(); fraglimit_override = autocvar_g_ca_point_limit; leadlimit_override = autocvar_g_ca_point_leadlimit; - allowed_to_spawn = TRUE; - ca_teams = autocvar_g_ca_teams_override; - if(ca_teams < 2) - ca_teams = autocvar_g_ca_teams; - ca_teams = bound(2, ca_teams, 4); - addstat(STAT_REDALIVE, AS_INT, redalive_stat); - addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat); - addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat); - addstat(STAT_PINKALIVE, AS_INT, pinkalive_stat); + MUTATOR_ADD(gamemode_ca); } if(g_keyhunt) { @@ -482,8 +474,6 @@ void CheckAllowedTeams (entity for_whom) // cover anything else by treating it like tdm with no teams spawned if(g_race) dm = race_teams; - else if(g_ca) - dm = ca_teams; else dm = 2; -- 2.39.2