Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cfg/cs2fixes/cs2fixes.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 26 additions & 14 deletions src/map_votes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ CConVar<float> g_cvarVoteMapsCooldown("cs2f_vote_maps_cooldown", FCVAR_NONE, "De
CConVar<float> g_cvarVoteMapsCooldownRng("cs2f_vote_maps_cooldown_rng", FCVAR_NONE, "Randomness range in both directions to apply to map cooldowns", 0.0f);
CConVar<int> 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<int> 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<int> 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)
{
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand All @@ -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);
Expand Down Expand Up @@ -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<CCooldown> 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<CCooldown> 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);
}
}
}

Expand All @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions src/map_votes.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class CMap : public std::enable_shared_from_this<CMap>
std::vector<std::string> 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<CCooldown> GetCooldown();
std::string GetCooldownText(bool bPlural);
Expand Down Expand Up @@ -206,7 +206,7 @@ class CMapVoteSystem
std::shared_ptr<CMap> GetCurrentMap() { return m_pCurrentMap; }
void SetCurrentMap(std::shared_ptr<CMap> pCurrentMap) { m_pCurrentMap = pCurrentMap; }
int GetDownloadQueueSize() { return m_DownloadQueue.size(); }
void ClearInvalidNominations();
void OnPlayerCountChange();
std::shared_ptr<CMap> GetForcedNextMap() { return m_pForcedNextMap; }
void SetForcedNextMap(std::shared_ptr<CMap> pForcedNextMap) { m_pForcedNextMap = pForcedNextMap; }
std::unordered_map<int, int> GetNominatedMaps();
Expand Down Expand Up @@ -247,6 +247,7 @@ class CMapVoteSystem
std::weak_ptr<CTimer> m_pDownloadProgressTimer;
std::weak_ptr<CTimer> m_pRateLimitedDownloadTimer;
std::vector<std::shared_ptr<CMapSystemWorkshopDetailsQuery>> m_vecWorkshopDetailsQueries;
int m_iSessionMaxPlayerCount = 0;
};

extern CMapVoteSystem* g_pMapVoteSystem;
4 changes: 2 additions & 2 deletions src/playermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
});

Expand Down