From da62f34a13a4c4349b1983b608c7a84e3bf2cea8 Mon Sep 17 00:00:00 2001 From: "Dr. Jaska" Date: Sun, 16 Oct 2022 19:53:24 +0000 Subject: [PATCH] New opt-in feature for less stalemates in CA when round timer runs out New cvar: `g_ca_prevent_stalemate 0|1` First the amount of players alive in each team is checked, if there is a single highest then that team wins the round. If two teams have the same amount of players then their total health counts are calculated and compared. If there is the same amount of players and total health in the 2 top teams then it's still a stalemate. Code cleanup by z411 --- gamemodes-server.cfg | 1 + .../gamemode/clanarena/sv_clanarena.qc | 101 ++++++++++++++++-- .../gamemode/clanarena/sv_clanarena.qh | 1 - 3 files changed, 93 insertions(+), 10 deletions(-) diff --git a/gamemodes-server.cfg b/gamemodes-server.cfg index a57c8f135..4afd6310f 100644 --- a/gamemodes-server.cfg +++ b/gamemodes-server.cfg @@ -229,6 +229,7 @@ set g_ca_round_timelimit 180 "round time limit in seconds" set g_ca_teams_override 0 set g_ca_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any" set g_ca_teams 0 +set g_ca_prevent_stalemate 0 "when round time ends instead of instant stalemate give round win to the team with most survivors or with the most total health" set g_ca_weaponarena "most" "starting weapons - takes the same options as g_weaponarena" diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc index 7803108c6..d64ce3604 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc @@ -2,6 +2,7 @@ float autocvar_g_ca_damage2score = 100; bool autocvar_g_ca_spectate_enemies; +bool autocvar_g_ca_prevent_stalemate; float autocvar_g_ca_start_health = 200; float autocvar_g_ca_start_armor = 200; @@ -44,22 +45,99 @@ void CA_count_alive_players() void nades_Clear(entity player); +int CA_PreventStalemate() +{ + //LOG_INFO("PreventStalemate running"); + int winnerTeam = 0; + int secondTeam = 0; + + for(int i = 1; i <= AVAILABLE_TEAMS; i++) + { + if(!winnerTeam || Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) > Team_GetNumberOfAlivePlayers(Team_GetTeam(winnerTeam))) + { + secondTeam = winnerTeam; + winnerTeam = Team_IndexToTeam(i); + } + else + { + if(!secondTeam || Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) > Team_GetNumberOfAlivePlayers(Team_GetTeam(secondTeam))) + secondTeam = Team_IndexToTeam(i); + } + } + + if(Team_GetNumberOfAlivePlayers(Team_GetTeam(winnerTeam)) != Team_GetNumberOfAlivePlayers(Team_GetTeam(secondTeam))) + { + LOG_INFOF("Stalemate broken by alive players. Best team: %s%s (%d)^7 - Trailing team: %s%s (%d)", + Team_ColorCode(winnerTeam), Team_ColorName(winnerTeam), Team_GetNumberOfAlivePlayers(Team_GetTeam(winnerTeam)), + Team_ColorCode(secondTeam), Team_ColorName(secondTeam), Team_GetNumberOfAlivePlayers(Team_GetTeam(secondTeam))); + return winnerTeam; + } + + // Equality. Let's check which team has more health now + //LOG_INFO("Equality. Checking health now."); + winnerTeam = 0; + secondTeam = 0; + int winnerTeamHealth = 0; + int secondTeamHealth = 0; + int teamIndex, teamHealth; + + for(int i = 1; i <= AVAILABLE_TEAMS; i++) + { + teamIndex = i; + teamHealth = 0; + + // Add up health for the players in this team + FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it) && it.team == Team_IndexToTeam(teamIndex), + { + if (IS_DEAD(it)) + continue; + teamHealth += GetResource(it, RES_HEALTH) + GetResource(it, RES_ARMOR); + }); + + // Set the winner teams + if(!winnerTeam || teamHealth > winnerTeamHealth) + { + secondTeam = winnerTeam; + secondTeamHealth = winnerTeamHealth; + winnerTeam = Team_IndexToTeam(i); + winnerTeamHealth = teamHealth; + } + else + { + if(!secondTeam || teamHealth > secondTeamHealth) + { + secondTeam = Team_IndexToTeam(i); + secondTeamHealth = teamHealth; + } + } + } + + if(winnerTeamHealth != secondTeamHealth) + { + LOG_INFOF("Stalemate broken by team health. Best team: %s%s (%d)^7 - Trailing team: %s%s (%d)", + Team_ColorCode(winnerTeam), Team_ColorName(winnerTeam), winnerTeamHealth, + Team_ColorCode(secondTeam), Team_ColorName(secondTeam), secondTeamHealth); + return winnerTeam; + } + else + return -2; // Equality. Can't avoid the stalemate. +} + float CA_CheckWinner() { + int winner_team = 0; + if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0) { - Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER); - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER); - FOREACH_CLIENT(IS_PLAYER(it), { nades_Clear(it); }); - - allowed_to_spawn = false; - game_stopped = true; - round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit); - return 1; + if(autocvar_g_ca_prevent_stalemate) + winner_team = CA_PreventStalemate(); + else + winner_team = -2; } CA_count_alive_players(); - int winner_team = Team_GetWinnerAliveTeam(); + if (!winner_team) + winner_team = Team_GetWinnerAliveTeam(); if (!winner_team) return 0; @@ -74,6 +152,11 @@ float CA_CheckWinner() Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_TIED); Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_TIED); } + else if(winner_team == -2) + { + Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER); + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER); + } allowed_to_spawn = false; game_stopped = true; diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh index c7e147a21..da93badef 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh @@ -14,7 +14,6 @@ int autocvar_g_ca_teams_override; float autocvar_g_ca_warmup; string autocvar_g_ca_weaponarena = "most"; - int ca_teams; bool allowed_to_spawn; -- 2.39.2