From 546a09331c55e22e011480d43c1937fd89cd3961 Mon Sep 17 00:00:00 2001 From: Faramour <44729057+Faramour@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:50:29 +0200 Subject: [PATCH] Add low population features to Map Vote System --- cfg/cs2fixes/cs2fixes.cfg | 1 + src/map_votes.cpp | 40 +++++++++++++++++++++++++-------------- src/map_votes.h | 5 +++-- src/playermanager.cpp | 4 ++-- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/cfg/cs2fixes/cs2fixes.cfg b/cfg/cs2fixes/cs2fixes.cfg index 3a7b746b..94046da7 100644 --- a/cfg/cs2fixes/cs2fixes.cfg +++ b/cfg/cs2fixes/cs2fixes.cfg @@ -98,6 +98,7 @@ cs2f_vote_maps_cooldown 6.0 // Default number of hours until a map can be pla cs2f_vote_maps_cooldown_rng 0.0 // Randomness range in both directions to apply to map cooldowns cs2f_vote_max_nominations 10 // Number of nominations to include per vote, out of a maximum of 10 cs2f_vote_max_maps 10 // Number of total maps to include per vote, including nominations, out of a maximum of 10 +cs2f_vote_lowpop_max_count 10 // Maximum amount of players required to enable low population features in map vote system // User preferences settings cs2f_user_prefs_api "" // User Preferences REST API endpoint diff --git a/src/map_votes.cpp b/src/map_votes.cpp index 4847bd6d..d087477e 100644 --- a/src/map_votes.cpp +++ b/src/map_votes.cpp @@ -43,6 +43,7 @@ CConVar g_cvarVoteMapsCooldown("cs2f_vote_maps_cooldown", FCVAR_NONE, "De CConVar g_cvarVoteMapsCooldownRng("cs2f_vote_maps_cooldown_rng", FCVAR_NONE, "Randomness range in both directions to apply to map cooldowns", 0.0f); CConVar g_cvarVoteMaxNominations("cs2f_vote_max_nominations", FCVAR_NONE, "Number of nominations to include per vote, out of a maximum of 10", 10, true, 0, true, 10); CConVar g_cvarVoteMaxMaps("cs2f_vote_max_maps", FCVAR_NONE, "Number of total maps to include per vote, including nominations, out of a maximum of 10", 10, true, 2, true, 10); +CConVar g_cvarVoteLowPopMaxCount("cs2f_vote_lowpop_max_count", FCVAR_NONE, "Maximum amount of players required to enable low population features in map vote system", 10, true, 0, false, 0); CON_COMMAND_CHAT_FLAGS(reload_map_list, "- Reload map list, also reloads current map on completion", ADMFLAG_ROOT) { @@ -168,11 +169,13 @@ CON_COMMAND_CHAT(maplist, "- List the maps in the server") g_pMapVoteSystem->PrintMapList(player); } -bool CMap::IsAvailable() +bool CMap::IsAvailable(int iOnlinePlayers) { auto pThis = shared_from_this(); + if (iOnlinePlayers == -1) + iOnlinePlayers = g_playerManager->GetOnlinePlayerCount(false); - if (GetCooldown()->IsOnCooldown()) + if (GetCooldown()->IsOnCooldown() && iOnlinePlayers > g_cvarVoteLowPopMaxCount.Get()) return false; if (*g_pMapVoteSystem->GetCurrentMap() == *pThis) @@ -181,7 +184,6 @@ bool CMap::IsAvailable() if (!IsEnabled()) return false; - int iOnlinePlayers = g_playerManager->GetOnlinePlayerCount(false); bool bMeetsMaxPlayers = iOnlinePlayers <= GetMaxPlayers(); bool bMeetsMinPlayers = iOnlinePlayers >= GetMinPlayers(); return bMeetsMaxPlayers && bMeetsMinPlayers; @@ -759,7 +761,7 @@ void CMapVoteSystem::AttemptNomination(CCSPlayerController* pController, const c return; } - if (pMap->GetCooldown()->IsOnCooldown()) + if (pMap->GetCooldown()->IsOnCooldown() && iPlayerCount > g_cvarVoteLowPopMaxCount.Get()) { ClientPrint(pController, HUD_PRINTTALK, CHAT_PREFIX "Cannot nominate \x06%s\x01 because it's on a %s cooldown.", pMap->GetName(), pMap->GetCooldownText(false).c_str()); return; @@ -1108,11 +1110,16 @@ bool CMapVoteSystem::WriteMapCooldownsToFile() return true; } -void CMapVoteSystem::ClearInvalidNominations() +void CMapVoteSystem::OnPlayerCountChange() { if (!g_cvarVoteManagerEnable.Get() || m_bIsVoteOngoing || !GetGlobals()) return; + int iOnlinePlayers = g_playerManager->GetOnlinePlayerCount(false); + + if (iOnlinePlayers > m_iSessionMaxPlayerCount) + m_iSessionMaxPlayerCount = iOnlinePlayers; + for (int i = 0; i < GetGlobals()->maxClients; i++) { int iNominatedMapIndex = m_arrPlayerNominations[i]; @@ -1124,7 +1131,7 @@ void CMapVoteSystem::ClearInvalidNominations() auto pMap = GetMapByIndex(iNominatedMapIndex); // Check if nominated map still meets criteria for nomination - if (!pMap->IsAvailable()) + if (!pMap->IsAvailable(iOnlinePlayers)) { ClearPlayerInfo(i); CCSPlayerController* pPlayer = CCSPlayerController::FromSlot(i); @@ -1153,16 +1160,19 @@ void CMapVoteSystem::ApplyGameSettings(const char* pszMapName, uint64 iWorkshopI void CMapVoteSystem::OnLevelShutdown() { - // Put the map on cooldown as we transition to the next map - PutMapOnCooldown(GetCurrentMap()->GetName()); - - // Fully apply pending group cooldowns - for (std::shared_ptr pCooldown : m_vecCooldowns) + if (m_iSessionMaxPlayerCount > g_cvarVoteLowPopMaxCount.Get()) { - if (pCooldown->GetPendingCooldown() > 0.0f) + // Put the map on cooldown as we transition to the next map + PutMapOnCooldown(GetCurrentMap()->GetName()); + + // Fully apply pending group cooldowns + for (std::shared_ptr pCooldown : m_vecCooldowns) { - PutMapOnCooldown(pCooldown->GetMapName(), pCooldown->GetPendingCooldown()); - pCooldown->SetPendingCooldown(0.0f); + if (pCooldown->GetPendingCooldown() > 0.0f) + { + PutMapOnCooldown(pCooldown->GetMapName(), pCooldown->GetPendingCooldown()); + pCooldown->SetPendingCooldown(0.0f); + } } } @@ -1177,6 +1187,8 @@ void CMapVoteSystem::OnLevelShutdown() if (m_timeMapListModified != std::filesystem::last_write_time(szPath)) ReloadMapList(false); } + + m_iSessionMaxPlayerCount = 0; } std::string CMapVoteSystem::ConvertFloatToString(float fValue, int precision) diff --git a/src/map_votes.h b/src/map_votes.h index 178f65cc..935d2624 100644 --- a/src/map_votes.h +++ b/src/map_votes.h @@ -89,7 +89,7 @@ class CMap : public std::enable_shared_from_this std::vector GetGroups() { return m_vecGroups; }; bool HasGroup(std::string strGroup) { return std::find(m_vecGroups.begin(), m_vecGroups.end(), strGroup) != m_vecGroups.end(); }; - bool IsAvailable(); + bool IsAvailable(int iOnlinePlayers = -1); bool Load(); std::shared_ptr GetCooldown(); std::string GetCooldownText(bool bPlural); @@ -206,7 +206,7 @@ class CMapVoteSystem std::shared_ptr GetCurrentMap() { return m_pCurrentMap; } void SetCurrentMap(std::shared_ptr pCurrentMap) { m_pCurrentMap = pCurrentMap; } int GetDownloadQueueSize() { return m_DownloadQueue.size(); } - void ClearInvalidNominations(); + void OnPlayerCountChange(); std::shared_ptr GetForcedNextMap() { return m_pForcedNextMap; } void SetForcedNextMap(std::shared_ptr pForcedNextMap) { m_pForcedNextMap = pForcedNextMap; } std::unordered_map GetNominatedMaps(); @@ -247,6 +247,7 @@ class CMapVoteSystem std::weak_ptr m_pDownloadProgressTimer; std::weak_ptr m_pRateLimitedDownloadTimer; std::vector> m_vecWorkshopDetailsQueries; + int m_iSessionMaxPlayerCount = 0; }; extern CMapVoteSystem* g_pMapVoteSystem; \ No newline at end of file diff --git a/src/playermanager.cpp b/src/playermanager.cpp index ee61cdb2..3bfe9c84 100644 --- a/src/playermanager.cpp +++ b/src/playermanager.cpp @@ -804,7 +804,7 @@ bool CPlayerManager::OnClientConnected(CPlayerSlot slot, uint64 xuid, const char ResetPlayerFlags(slot.Get()); g_pMapVoteSystem->ClearPlayerInfo(slot.Get()); - g_pMapVoteSystem->ClearInvalidNominations(); + g_pMapVoteSystem->OnPlayerCountChange(); return true; } @@ -829,7 +829,7 @@ void CPlayerManager::OnClientDisconnect(CPlayerSlot slot) // One tick delay, to ensure player count decrements CTimer::Create(0.01f, TIMERFLAG_MAP, []() { g_pVoteManager->CheckRTVStatus(); - g_pMapVoteSystem->ClearInvalidNominations(); + g_pMapVoteSystem->OnPlayerCountChange(); return -1.0f; });