From 81a26134ca675f8065837a800db93ddda4d49b37 Mon Sep 17 00:00:00 2001 From: BuSheey <6915170+busheezy@users.noreply.github.com> Date: Sat, 12 Sep 2026 04:17:54 -0500 Subject: [PATCH 1/5] fix: exclude SourceTV from warmup player counts --- addons/sourcemod/scripting/TeamManager.sp | 28 ++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/TeamManager.sp b/addons/sourcemod/scripting/TeamManager.sp index 09249e8..1a96953 100644 --- a/addons/sourcemod/scripting/TeamManager.sp +++ b/addons/sourcemod/scripting/TeamManager.sp @@ -172,8 +172,8 @@ public Action OnWarmupTimer(Handle timer) if (g_cvPlayersRatio.FloatValue > 0.0) { - int ClientsConnected = GetClientCount(false); - int ClientsInGame = GetClientCount(true); + int ClientsConnected = GetWarmupPlayerCount(false); + int ClientsInGame = GetWarmupPlayerCount(true); int ClientsNeeded = RoundToCeil(float(ClientsConnected) * g_cvPlayersRatio.FloatValue); ClientsNeeded = ClientsNeeded > MIN_PLAYERS ? ClientsNeeded : MIN_PLAYERS; @@ -199,6 +199,28 @@ public Action OnWarmupTimer(Handle timer) return Plugin_Continue; } +stock int GetWarmupPlayerCount(bool InGameOnly) +{ + int Clients = 0; + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsClientConnected(client) || IsClientSourceTV(client)) + { + continue; + } + + if (InGameOnly && !IsClientInGame(client)) + { + continue; + } + + Clients++; + } + + return Clients; +} + stock void EndWarmUp() { g_iWarmup = 0; @@ -435,4 +457,4 @@ stock void InitStringMap() { g_hEntitiesListToKill.SetValue(sSafeEntitiesToKill[i], true); } -} \ No newline at end of file +} From ed60ab5accbed1968e8eb48027cadddb0836339d Mon Sep 17 00:00:00 2001 From: BuSheey <6915170+busheezy@users.noreply.github.com> Date: Sat, 12 Sep 2026 19:06:34 -0500 Subject: [PATCH 2/5] feat: make spectator warmup counts configurable --- addons/sourcemod/scripting/TeamManager.sp | 24 ++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/TeamManager.sp b/addons/sourcemod/scripting/TeamManager.sp index 1a96953..448fc13 100644 --- a/addons/sourcemod/scripting/TeamManager.sp +++ b/addons/sourcemod/scripting/TeamManager.sp @@ -14,7 +14,7 @@ GlobalForward g_hWarmupEndFwd; -ConVar g_cvWarmup, g_cvWarmuptime, g_cvWarmupMaxTime, g_cvForceTeam, g_cvPlayersRatio, g_cvCleanOnWarmupEnd, g_cvAliveTeamChange; +ConVar g_cvWarmup, g_cvWarmuptime, g_cvWarmupMaxTime, g_cvForceTeam, g_cvPlayersRatio, g_cvExcludeSpectators, g_cvCleanOnWarmupEnd, g_cvAliveTeamChange; ConVar g_cvDynamic, g_cvDynamicRatio, g_cvDynamicTime; bool g_bWarmup = false; @@ -64,6 +64,7 @@ public void OnPluginStart() g_cvWarmupMaxTime = CreateConVar("sm_warmuptime_max", "-1", "Maximum warmup timer [-1 = Disabled]"); g_cvForceTeam = CreateConVar("sm_warmupteam", "1", "Force the player to join the counterterrorist team", 0, true, 0.0, true, 1.0); g_cvPlayersRatio = CreateConVar("sm_warmupratio", "0.60", "Ratio of connected players that need to be in game to start warmup timer.", 0, true, 0.0, true, 1.0); + g_cvExcludeSpectators = CreateConVar("sm_teammanager_warmup_exclude_spectators", "1", "Exclude spectators from warmup player counts. [0 = Disabled | 1 = Enabled]", 0, true, 0.0, true, 1.0); g_cvCleanOnWarmupEnd = CreateConVar("sm_warmup_slay", "0", "Slay all players at the end of the warmup round. [0 = Disabled | 1 = Enabled | 2 = Enabled + Clean temporary entities]", 0, true, 0.0, true, 2.0); g_cvAliveTeamChange = CreateConVar("sm_teammanager_aliveteamchange", "1", "Determines if players are allowed to change teams while they're alive. [0 = Dissalow | 1 = Allow]", 0, true, 0.0, true, 1.0); @@ -215,12 +216,33 @@ stock int GetWarmupPlayerCount(bool InGameOnly) continue; } + if (IsWarmupSpectator(client)) + { + continue; + } + Clients++; } return Clients; } +stock bool IsWarmupSpectator(int client) +{ + if (!g_cvExcludeSpectators.BoolValue) + { + return false; + } + + if (!IsClientInGame(client)) + { + return false; + } + + int Team = GetClientTeam(client); + return Team == CS_TEAM_SPECTATOR; +} + stock void EndWarmUp() { g_iWarmup = 0; From 92fa22756dc5c24983c8c09f8c3b04d648d57480 Mon Sep 17 00:00:00 2001 From: BuSheey <6915170+busheezy@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:59:00 -0500 Subject: [PATCH 3/5] fix: preserve legacy warmup counting behavior --- addons/sourcemod/scripting/TeamManager.sp | 26 +++++++++-------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/addons/sourcemod/scripting/TeamManager.sp b/addons/sourcemod/scripting/TeamManager.sp index 448fc13..3924a1b 100644 --- a/addons/sourcemod/scripting/TeamManager.sp +++ b/addons/sourcemod/scripting/TeamManager.sp @@ -64,7 +64,7 @@ public void OnPluginStart() g_cvWarmupMaxTime = CreateConVar("sm_warmuptime_max", "-1", "Maximum warmup timer [-1 = Disabled]"); g_cvForceTeam = CreateConVar("sm_warmupteam", "1", "Force the player to join the counterterrorist team", 0, true, 0.0, true, 1.0); g_cvPlayersRatio = CreateConVar("sm_warmupratio", "0.60", "Ratio of connected players that need to be in game to start warmup timer.", 0, true, 0.0, true, 1.0); - g_cvExcludeSpectators = CreateConVar("sm_teammanager_warmup_exclude_spectators", "1", "Exclude spectators from warmup player counts. [0 = Disabled | 1 = Enabled]", 0, true, 0.0, true, 1.0); + g_cvExcludeSpectators = CreateConVar("sm_teammanager_warmup_exclude_spectators", "0", "Exclude spectators from warmup player counts. [0 = Disabled | 1 = Enabled]", 0, true, 0.0, true, 1.0); g_cvCleanOnWarmupEnd = CreateConVar("sm_warmup_slay", "0", "Slay all players at the end of the warmup round. [0 = Disabled | 1 = Enabled | 2 = Enabled + Clean temporary entities]", 0, true, 0.0, true, 2.0); g_cvAliveTeamChange = CreateConVar("sm_teammanager_aliveteamchange", "1", "Determines if players are allowed to change teams while they're alive. [0 = Dissalow | 1 = Allow]", 0, true, 0.0, true, 1.0); @@ -173,8 +173,8 @@ public Action OnWarmupTimer(Handle timer) if (g_cvPlayersRatio.FloatValue > 0.0) { - int ClientsConnected = GetWarmupPlayerCount(false); - int ClientsInGame = GetWarmupPlayerCount(true); + int ClientsConnected, ClientsInGame; + GetWarmupPlayerCounts(ClientsConnected, ClientsInGame); int ClientsNeeded = RoundToCeil(float(ClientsConnected) * g_cvPlayersRatio.FloatValue); ClientsNeeded = ClientsNeeded > MIN_PLAYERS ? ClientsNeeded : MIN_PLAYERS; @@ -200,31 +200,25 @@ public Action OnWarmupTimer(Handle timer) return Plugin_Continue; } -stock int GetWarmupPlayerCount(bool InGameOnly) +stock void GetWarmupPlayerCounts(int &ClientsConnected, int &ClientsInGame) { - int Clients = 0; + ClientsConnected = 0; + ClientsInGame = 0; for (int client = 1; client <= MaxClients; client++) { - if (!IsClientConnected(client) || IsClientSourceTV(client)) + if (!IsClientConnected(client) || IsClientSourceTV(client) || IsWarmupSpectator(client)) { continue; } - if (InGameOnly && !IsClientInGame(client)) - { - continue; - } + ClientsConnected++; - if (IsWarmupSpectator(client)) + if (IsClientInGame(client)) { - continue; + ClientsInGame++; } - - Clients++; } - - return Clients; } stock bool IsWarmupSpectator(int client) From 5d54a0a55ce16c4b4085caae81346ce4e8985780 Mon Sep 17 00:00:00 2001 From: Rushaway Date: Fri, 18 Sep 2026 11:33:27 +0200 Subject: [PATCH 4/5] Refactor client counting to exclude spectators Removed the IsWarmupSpectator function and integrated its logic into the main client count loop. Added a check for excluding spectators based on the g_cvExcludeSpectators configuration. --- addons/sourcemod/scripting/TeamManager.sp | 29 +++++++++-------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/addons/sourcemod/scripting/TeamManager.sp b/addons/sourcemod/scripting/TeamManager.sp index e179587..a66830e 100644 --- a/addons/sourcemod/scripting/TeamManager.sp +++ b/addons/sourcemod/scripting/TeamManager.sp @@ -243,36 +243,29 @@ stock void GetWarmupPlayerCounts(int &ClientsConnected, int &ClientsInGame) ClientsConnected = 0; ClientsInGame = 0; + bool excludeSpectators = g_cvExcludeSpectators.BoolValue; + for (int client = 1; client <= MaxClients; client++) { - if (!IsClientConnected(client) || IsClientSourceTV(client) || IsWarmupSpectator(client)) + if (!IsClientConnected(client) || IsClientSourceTV(client)) { continue; } - ClientsConnected++; + bool inGame = IsClientInGame(client); - if (IsClientInGame(client)) + if (excludeSpectators && inGame && GetClientTeam(client) == CS_TEAM_SPECTATOR) { - ClientsInGame++; + continue; } - } -} -stock bool IsWarmupSpectator(int client) -{ - if (!g_cvExcludeSpectators.BoolValue) - { - return false; - } + ClientsConnected++; - if (!IsClientInGame(client)) - { - return false; + if (inGame) + { + ClientsInGame++; + } } - - int Team = GetClientTeam(client); - return Team == CS_TEAM_SPECTATOR; } stock void EndWarmUp() From 4c891957326c80bd5fb3c7444873469458afc2ec Mon Sep 17 00:00:00 2001 From: Rushaway Date: Fri, 18 Sep 2026 11:36:26 +0200 Subject: [PATCH 5/5] Update TeamManager.sp --- addons/sourcemod/scripting/TeamManager.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/TeamManager.sp b/addons/sourcemod/scripting/TeamManager.sp index a66830e..35fe100 100644 --- a/addons/sourcemod/scripting/TeamManager.sp +++ b/addons/sourcemod/scripting/TeamManager.sp @@ -35,7 +35,7 @@ public Plugin myinfo = name = "TeamManager", author = "BotoX + maxime1907, .Rushaway", description = "Adds a warmup round, makes every human a ct and every zombie a t", - version = "2.3.5", + version = "2.3.6", url = "https://github.com/srcdslab/sm-plugin-TeamManager" };