]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Survival and CA: when the game ends put players who joined after round start back...
authorterencehill <piuntn@gmail.com>
Mon, 1 Apr 2024 00:23:20 +0000 (02:23 +0200)
committerterencehill <piuntn@gmail.com>
Mon, 1 Apr 2024 10:09:38 +0000 (12:09 +0200)
Forced team switch works even if player would be moved to a larger team and if g_balance_teams and g_balance_teams_prevent_imbalance are enabled

qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc
qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc
qcsrc/server/mutators/events.qh
qcsrc/server/teamplay.qc
qcsrc/server/world.qc
qcsrc/server/world.qh

index 8ee0a676569b8364f931e52b7a976c87d2f858ef..3fab3fb3e07781da879c5c6d23507105f93ee4ca 100644 (file)
@@ -13,6 +13,7 @@ float autocvar_g_ca_start_ammo_plasma = 180;
 float autocvar_g_ca_start_ammo_fuel = 0;
 
 .float ca_damage_counter;
+.int prev_team;
 
 void CA_count_alive_players()
 {
@@ -188,6 +189,8 @@ float CA_CheckWinner()
 void CA_RoundStart()
 {
        allowed_to_spawn = boolean(warmup_stage);
+       if (!warmup_stage)
+               FOREACH_CLIENT(IS_PLAYER(it), it.prev_team = it.team);
 }
 
 bool CA_CheckTeams()
@@ -309,6 +312,7 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_players)
                        INGAME_STATUS_SET(it, INGAME_STATUS_JOINED);
                        PutClientInServer(it);
                }
+               it.prev_team = 0;
        });
        return true;
 }
@@ -319,6 +323,12 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_global)
        return true;
 }
 
+MUTATOR_HOOKFUNCTION(ca, MatchEnd_BeforeScores)
+{
+       MatchEnd_RestoreSpectatorAndTeamStatus(prev_team);
+       return true;
+}
+
 MUTATOR_HOOKFUNCTION(ca, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = ca_teams;
index cfdc948c04748576a07bc9a345cf5ffd12145882..20bff56b1a667899a4948daf208673d05e963ac8 100644 (file)
@@ -323,6 +323,12 @@ MUTATOR_HOOKFUNCTION(surv, reset_map_global)
        return true;
 }
 
+MUTATOR_HOOKFUNCTION(surv, MatchEnd_BeforeScores)
+{
+       MatchEnd_RestoreSpectatorStatus();
+       return true;
+}
+
 entity surv_LastPlayerForTeam(entity this)
 {
        entity last_pl = NULL;
index 46fb4ede17e4cc4fdb67d82ae8149fd4eee31bd9..f020ebad8f95a0ac9bf12312eb1a668b73c16f7e 100644 (file)
@@ -146,6 +146,9 @@ MUTATOR_HOOKABLE(ItemSound, EV_ItemSound);
     /**/
 MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill);
 
+/** called when the match ends, before recording scores */
+MUTATOR_HOOKABLE(MatchEnd_BeforeScores, EV_NO_ARGS);
+
 /** called when the match ends */
 MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
 
index 1cfdbf4a0538da331630210cdfbc92a4ef4333ec..d6b46b0510962f4913a854878540872a7135c4a3 100644 (file)
@@ -889,6 +889,8 @@ void TeamBalance_AutoBalanceBots()
        //if (!(autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance))
        //      return;
 
+       if (intermission_running) return;
+
        entity balance = TeamBalance_CheckAllowedTeams(NULL);
        TeamBalance_GetTeamCounts(balance, NULL);
        int smallest_team_index = 0;
index ad40a389543bcb5698d2abc2a0ddd1068e1f0557..733faddadc86b18aad108771ceb5e53f804987a8 100644 (file)
@@ -1324,6 +1324,40 @@ void DumpStats(float final)
        }
 }
 
+// it should be called by gametypes where players can join a team but have to wait before playing
+// it puts players who joined too late (without being able to play) back to spectators
+// if prev_team_field is not team it also puts players who previously switched team (without being
+// able to play on the new team) back to previous team
+void MatchEnd_RestoreSpectatorAndTeamStatus(.int prev_team_field)
+{
+       bool fix_team = (teamplay && prev_team_field != team);
+       FOREACH_CLIENT(true,
+       {
+               if (!IS_PLAYER(it) && INGAME_JOINING(it))
+               {
+                       INGAME_STATUS_CLEAR(it);
+                       PutObserverInServer(it, true, false);
+                       bprint(playername(it.netname, it.team, false), " has been moved back to spectator");
+                       it.winning = false;
+               }
+               else if (fix_team && INGAME_JOINED(it) && it.(prev_team_field) && it.team != it.(prev_team_field))
+               {
+                       Player_SetForcedTeamIndex(it, TEAM_FORCE_DEFAULT);
+                       if (MoveToTeam(it, Team_TeamToIndex(it.(prev_team_field)), 6))
+                       {
+                               string pl_name = playername(it.netname, it.team, false);
+                               bprint(pl_name, " has been moved back to the ", Team_ColoredFullName(it.team));
+                       }
+                       it.winning = (it.team == WinningConditionHelper_winnerteam);
+               }
+       });
+}
+
+void MatchEnd_RestoreSpectatorStatus()
+{
+       MatchEnd_RestoreSpectatorAndTeamStatus(team);
+}
+
 /*
 go to the next level for deathmatch
 only called if a time or frag limit has expired
@@ -1351,6 +1385,8 @@ void NextLevel()
 
        VoteReset(true);
 
+       MUTATOR_CALLHOOK(MatchEnd_BeforeScores);
+
        DumpStats(true);
 
        // send statistics
index a7301dc799b1fa96bc5a3102d95bc71faa3bd167..b5b00e7f93408ae6f964e477dd2a05cec561c5fb 100644 (file)
@@ -170,3 +170,6 @@ IntrusiveList g_moveables;
 STATIC_INIT(g_moveables) { g_moveables = IL_NEW(); }
 
 bool observe_blocked_if_eliminated = false; // forbids eliminated players from observing
+
+void MatchEnd_RestoreSpectatorAndTeamStatus(.int prev_team_field);
+void MatchEnd_RestoreSpectatorStatus();