diff --git a/cfg/cs2fixes/cs2fixes.cfg b/cfg/cs2fixes/cs2fixes.cfg index 3a7b746b..1e7928d0 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_bypass_cd_max_count 0 // Maximum amount of players allowed to enable bypassing map cooldowns // 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..72dd2479 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_cvarVoteBypassCooldownMaxCount("cs2f_vote_bypass_cd_max_count", FCVAR_NONE, "Maximum amount of players allowed to enable bypassing map cooldowns", 0, true, 0, false, 0); CON_COMMAND_CHAT_FLAGS(reload_map_list, "- Reload map list, also reloads current map on completion", ADMFLAG_ROOT) { @@ -1108,11 +1109,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]; @@ -1153,15 +1159,22 @@ 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()); + bool bApplyCooldowns = m_iSessionMaxPlayerCount > g_cvarVoteBypassCooldownMaxCount.Get(); + + if (bApplyCooldowns) + { + // Put the map on cooldown as we transition to the next map + PutMapOnCooldown(GetCurrentMap()->GetName()); + } - // Fully apply pending group cooldowns + // Fully apply or discard pending group cooldowns for (std::shared_ptr pCooldown : m_vecCooldowns) { if (pCooldown->GetPendingCooldown() > 0.0f) { - PutMapOnCooldown(pCooldown->GetMapName(), pCooldown->GetPendingCooldown()); + if (bApplyCooldowns) + PutMapOnCooldown(pCooldown->GetMapName(), pCooldown->GetPendingCooldown()); + pCooldown->SetPendingCooldown(0.0f); } } @@ -1177,6 +1190,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) @@ -1316,6 +1331,11 @@ std::shared_ptr CMapVoteSystem::GetMapCooldown(const char* pszMapName return pCooldown; } +bool CCooldown::IsOnCooldown() +{ + return GetCurrentCooldown() > 0.0f && g_playerManager->GetOnlinePlayerCount(false) > g_cvarVoteBypassCooldownMaxCount.Get(); +} + float CCooldown::GetCurrentCooldown() { time_t timeCurrent = std::time(0); diff --git a/src/map_votes.h b/src/map_votes.h index 178f65cc..ac55efac 100644 --- a/src/map_votes.h +++ b/src/map_votes.h @@ -50,8 +50,8 @@ class CCooldown void SetTimeCooldown(time_t timeCooldown) { m_timeCooldown = timeCooldown; }; float GetPendingCooldown() { return m_fPendingCooldown; }; void SetPendingCooldown(float fPendingCooldown) { m_fPendingCooldown = fPendingCooldown; }; - bool IsOnCooldown() { return GetCurrentCooldown() > 0.0f; } bool IsPending() { return m_fPendingCooldown > 0.0f && m_fPendingCooldown == GetCurrentCooldown(); }; + bool IsOnCooldown(); float GetCurrentCooldown(); private: @@ -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; });