From dd7dff56db80649ffa09a17cb1d9794e8cd73312 Mon Sep 17 00:00:00 2001 From: terencehill Date: Fri, 24 May 2024 20:05:02 +0000 Subject: [PATCH] Survival and CA: when the game ends put players who joined after last round start back to spectators. CA: when the game ends put players who switched team during the last round back to previous team. 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 --- .../gamemode/clanarena/sv_clanarena.qc | 10 ++++++ .../gamemode/survival/sv_survival.qc | 6 ++++ qcsrc/server/mutators/events.qh | 3 ++ qcsrc/server/teamplay.qc | 2 ++ qcsrc/server/world.qc | 36 +++++++++++++++++++ qcsrc/server/world.qh | 3 ++ 6 files changed, 60 insertions(+) diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc index 8ee0a6765..3fab3fb3e 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc @@ -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; diff --git a/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc b/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc index cfdc948c0..20bff56b1 100644 --- a/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc +++ b/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc @@ -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; diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index 46fb4ede1..f020ebad8 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -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); diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index 1cfdbf4a0..d6b46b051 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -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; diff --git a/qcsrc/server/world.qc b/qcsrc/server/world.qc index ad40a3895..733faddad 100644 --- a/qcsrc/server/world.qc +++ b/qcsrc/server/world.qc @@ -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 diff --git a/qcsrc/server/world.qh b/qcsrc/server/world.qh index a7301dc79..b5b00e7f9 100644 --- a/qcsrc/server/world.qh +++ b/qcsrc/server/world.qh @@ -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(); -- 2.39.2