reverted that leaders can skip cooldowns and restrictions for nominating maps. added that mapchooser for casualpool fetches more than original 50 maps in case most of them are actually admin only or deleted. added that cooldown hours are scaled by if a map has a negative impact on the server population

This commit is contained in:
jenz
2026-10-04 20:56:43 +02:00
parent 854da9b615
commit 64bc2be4aa
2 changed files with 109 additions and 24 deletions
@@ -147,6 +147,9 @@ int g_mapFileSerial = -1;
int g_iSkipAllRestrictions; int g_iSkipAllRestrictions;
int g_iDontCooldownMap; int g_iDontCooldownMap;
int g_iMapsFromCasualPool; int g_iMapsFromCasualPool;
int g_iImpactExtraCooldownTime;
float g_avg_net_change;
int g_iInterval; int g_iInterval;
char player_mapvote[MAXPLAYERS + 1][PLATFORM_MAX_PATH]; char player_mapvote[MAXPLAYERS + 1][PLATFORM_MAX_PATH];
@@ -298,6 +301,11 @@ public void OnPluginStart()
g_bCasualPoolFromImpactPlayTime = cvar2_.BoolValue; g_bCasualPoolFromImpactPlayTime = cvar2_.BoolValue;
delete cvar2_; delete cvar2_;
ConVar cvar2_1;
HookConVarChange((cvar2_1 = CreateConVar("mce_impact_extra_cooldown_addition", "100", "How much additional cooldowntime do we apply for negative impact rate. 0 disables the feature.")), Cvar_impact_extra_cooldown);
g_iImpactExtraCooldownTime = cvar2_1.IntValue;
delete cvar2_1;
ConVar cvar1; ConVar cvar1;
HookConVarChange((cvar1 = CreateConVar("mce_skip_map_restrictions_player_count", "15", "Amount of players required for any restrictions are enabled.")), Cvar_playerActiveRequired); HookConVarChange((cvar1 = CreateConVar("mce_skip_map_restrictions_player_count", "15", "Amount of players required for any restrictions are enabled.")), Cvar_playerActiveRequired);
g_iSkipAllRestrictions = cvar1.IntValue; g_iSkipAllRestrictions = cvar1.IntValue;
@@ -330,7 +338,7 @@ public void OnPluginStart()
g_Cvar_NoRestrictionTimeframeEnable = CreateConVar("mce_no_restriction_timeframe_enable", "1", "Enable timeframe where all nomination restrictions and cooldowns are disabled?", _, true, 0.0, true, 1.0); g_Cvar_NoRestrictionTimeframeEnable = CreateConVar("mce_no_restriction_timeframe_enable", "1", "Enable timeframe where all nomination restrictions and cooldowns are disabled?", _, true, 0.0, true, 1.0);
g_Cvar_NoRestrictionTimeframeMinTime = CreateConVar("mce_no_restriction_timeframe_mintime", "0100", "Start of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM)", _, true, 0000.0, true, 2359.0); g_Cvar_NoRestrictionTimeframeMinTime = CreateConVar("mce_no_restriction_timeframe_mintime", "0100", "Start of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM)", _, true, 0000.0, true, 2359.0);
g_Cvar_NoRestrictionTimeframeMaxTime = CreateConVar("mce_no_restriction_timeframe_maxtime", "0700", "End of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM)", _, true, 0000.0, true, 2359.0); g_Cvar_NoRestrictionTimeframeMaxTime = CreateConVar("mce_no_restriction_timeframe_maxtime", "0700", "End of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM)", _, true, 0000.0, true, 2359.0);
g_Cvar_MultipleNominationsTier = CreateConVar("mce_multiple_nominations_tier", "3", "Tier required for having multiple nominations available."); g_Cvar_MultipleNominationsTier = CreateConVar("mce_multiple_nominations_tier", "8", "Tier required for having multiple nominations available.");
RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now."); RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now.");
RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>"); RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>");
@@ -439,8 +447,8 @@ public void OnPluginStart()
g_first_map_no_cooldown = true; g_first_map_no_cooldown = true;
int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; //int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10;
ServerCommand("sm_cvar mp_chattime %i", total_time); //prevents map switching supposedly. //ServerCommand("sm_cvar mp_chattime %i", total_time); //prevents map switching supposedly.
} }
public void Cvar_mapsFromCasualPool(ConVar convar, const char[] oldValue, const char[] newValue) public void Cvar_mapsFromCasualPool(ConVar convar, const char[] oldValue, const char[] newValue)
@@ -448,6 +456,11 @@ public void Cvar_mapsFromCasualPool(ConVar convar, const char[] oldValue, const
g_iMapsFromCasualPool = convar.IntValue; g_iMapsFromCasualPool = convar.IntValue;
} }
public void Cvar_impact_extra_cooldown(ConVar convar, const char[] oldValue, const char[] newValue)
{
g_iImpactExtraCooldownTime = convar.IntValue;
}
public void Cvar_casual_pool_impact_enabled(ConVar convar, const char[] oldValue, const char[] newValue) public void Cvar_casual_pool_impact_enabled(ConVar convar, const char[] oldValue, const char[] newValue)
{ {
g_bCasualPoolFromImpactPlayTime = convar.BoolValue; g_bCasualPoolFromImpactPlayTime = convar.BoolValue;
@@ -529,8 +542,9 @@ public void OnMapStart()
g_iNextmapState = 0; g_iNextmapState = 0;
CreateTimer(1.0, GetInternalGetCvars); CreateTimer(1.0, GetInternalGetCvars);
int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; //int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10;
ServerCommand("sm_cvar mp_chattime %i", total_time); //prevents map switching supposedly. //ServerCommand("sm_cvar mp_chattime %i", total_time); //prevents map switching supposedly.
g_iInterval = 0; g_iInterval = 0;
static char folder[64]; static char folder[64];
GetGameFolderName(folder, sizeof(folder)); GetGameFolderName(folder, sizeof(folder));
@@ -569,14 +583,31 @@ public void OnMapStart()
return; return;
} }
g_Config.Rewind(); g_Config.Rewind();
FillMapsByImpact(0);
char sRequest[256]; char currentmap[256];
FormatEx(sRequest, sizeof(sRequest), "https://playtime-sessions.unloze.com/api/maps/impact?sortBy=impact&direction=desc&offset=0"); GetCurrentMap(currentmap, PLATFORM_MAX_PATH);
HTTPRequest hRequest = new HTTPRequest(sRequest); g_avg_net_change = 0.0;
hRequest.Get(OnTransferComplete, _); GetMapsImpact(currentmap);
} }
public void OnTransferComplete(HTTPResponse response, any s) public void GetMapsImpact(char[] currentmap)
{
char sRequest[512];
FormatEx(sRequest, sizeof(sRequest), "https://playtime-sessions.unloze.com/api/maps/impact?mapName=%s", currentmap);
HTTPRequest hRequest = new HTTPRequest(sRequest);
hRequest.Get(OnTransferComplete1, _);
}
public void FillMapsByImpact(int offset)
{
char sRequest[256];
FormatEx(sRequest, sizeof(sRequest), "https://playtime-sessions.unloze.com/api/maps/impact?sortBy=impact&direction=desc&offset=%i", offset);
HTTPRequest hRequest = new HTTPRequest(sRequest);
hRequest.Get(OnTransferComplete, offset);
}
public void OnTransferComplete(HTTPResponse response, int offset)
{ {
if (response.Status != HTTPStatus_OK || response.Data == null) if (response.Status != HTTPStatus_OK || response.Data == null)
{ {
@@ -594,8 +625,11 @@ public void OnTransferComplete(HTTPResponse response, any s)
} }
ClearArray(g_hTopImpactMaps); ClearArray(g_hTopImpactMaps);
Handle tempMaps = CloneArray(g_MapList);
int count = maps.Length; int count = maps.Length;
char mapName[PLATFORM_MAX_PATH]; char mapName[PLATFORM_MAX_PATH];
int maps_added = 0;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
JSONObject entry = view_as<JSONObject>(maps.Get(i)); JSONObject entry = view_as<JSONObject>(maps.Get(i));
@@ -604,10 +638,46 @@ public void OnTransferComplete(HTTPResponse response, any s)
continue; continue;
} }
entry.GetString("map_name", mapName, sizeof(mapName)); entry.GetString("map_name", mapName, sizeof(mapName));
PushArrayString(g_hTopImpactMaps, mapName); //make sure that the map actually is in the map pool and not admin only or deleted from the server again
if (FindStringInArray(tempMaps, mapName) != -1)
{
PushArrayString(g_hTopImpactMaps, mapName);
maps_added++;
}
delete entry; delete entry;
} }
delete tempMaps;
delete root;
delete maps;
if (maps_added < 45)
{
FillMapsByImpact(offset + 50); //did not get enough maps from the public maplist, set offset to pick the next.
}
}
public void OnTransferComplete1(HTTPResponse response, any i)
{
if (response.Status != HTTPStatus_OK || response.Data == null)
{
LogError("Request-Error: %d", response.Status);
return;
}
JSONObject root = view_as<JSONObject>(response.Data);
JSONArray maps = view_as<JSONArray>(root.Get("maps"));
if (maps == null)
{
delete root;
return;
}
JSONObject entry = view_as<JSONObject>(maps.Get(0));
if (entry != null)
{
g_avg_net_change = entry.GetFloat("avg_net_change");
}
delete entry;
delete root; delete root;
delete maps; delete maps;
} }
@@ -698,8 +768,8 @@ public void OnMapEnd()
{ {
g_first_map_no_cooldown = false; g_first_map_no_cooldown = false;
g_iNextmapState = 0; g_iNextmapState = 0;
int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; //int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10;
ServerCommand("sm_cvar mp_chattime %i", total_time); //ServerCommand("sm_cvar mp_chattime %i", total_time);
g_iInterval = 0; g_iInterval = 0;
g_HasVoteStarted = false; g_HasVoteStarted = false;
@@ -712,22 +782,20 @@ public void OnMapEnd()
g_WarningTimer = INVALID_HANDLE; g_WarningTimer = INVALID_HANDLE;
g_RunoffCount = 0; g_RunoffCount = 0;
static char map[PLATFORM_MAX_PATH];
GetCurrentMap(map, PLATFORM_MAX_PATH);
int Cooldown = InternalGetMapCooldown(map);
//resetting all again so they are added again onmapstart //resetting all again so they are added again onmapstart
StringMapSnapshot CooldownList = g_CooldownList.Snapshot(); StringMapSnapshot CooldownList = g_CooldownList.Snapshot();
for(int i = 0; i < CooldownList.Length; i++) for(int i = 0; i < CooldownList.Length; i++)
{ {
char map[PLATFORM_MAX_PATH];
CooldownList.GetKey(i, map, sizeof(map)); CooldownList.GetKey(i, map, sizeof(map));
g_CooldownList.Remove(map); g_CooldownList.Remove(map);
} }
StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot(); StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot();
for(int i = 0; i < OldMapListSnapshot.Length; i++) for(int i = 0; i < OldMapListSnapshot.Length; i++)
{ {
char map[PLATFORM_MAX_PATH];
int Cooldown = 0;
OldMapListSnapshot.GetKey(i, map, sizeof(map)); OldMapListSnapshot.GetKey(i, map, sizeof(map));
g_OldMapList.GetValue(map, Cooldown); g_OldMapList.GetValue(map, Cooldown);
@@ -737,21 +805,21 @@ public void OnMapEnd()
else else
g_OldMapList.Remove(map); g_OldMapList.Remove(map);
} }
delete OldMapListSnapshot;
StringMapSnapshot TimeMapListSnapshot = g_TimeMapList.Snapshot(); StringMapSnapshot TimeMapListSnapshot = g_TimeMapList.Snapshot();
Cooldown = GetTime() + InternalGetMapCooldownTime(map) - RoundToFloor(GetGameTime());
for(int i = 0; i < TimeMapListSnapshot.Length; i++) for(int i = 0; i < TimeMapListSnapshot.Length; i++)
{ {
char map[PLATFORM_MAX_PATH];
int Cooldown = 0;
TimeMapListSnapshot.GetKey(i, map, sizeof(map)); TimeMapListSnapshot.GetKey(i, map, sizeof(map));
g_TimeMapList.GetValue(map, Cooldown); g_TimeMapList.GetValue(map, Cooldown);
if(Cooldown < GetTime()) if(Cooldown < GetTime())
g_TimeMapList.Remove(map); g_TimeMapList.Remove(map);
} }
delete TimeMapListSnapshot;
delete OldMapListSnapshot; delete OldMapListSnapshot;
delete TimeMapListSnapshot;
InternalStoreMapCooldowns(); InternalStoreMapCooldowns();
} }
@@ -1025,6 +1093,9 @@ public Action CS_OnTerminateRound(float &delay, CSRoundEndReason &reason)
g_OldMapList.SetValue(map, Cooldown, true); g_OldMapList.SetValue(map, Cooldown, true);
Cooldown = GetTime() + InternalGetMapCooldownTime(map) - RoundToFloor(GetGameTime()); Cooldown = GetTime() + InternalGetMapCooldownTime(map) - RoundToFloor(GetGameTime());
//set extra cooldowntime for the map based on the playtime frontend impact for average population loss
Cooldown += additionalCooldownHoursCurrentMap();
g_TimeMapList.SetValue(map, Cooldown, true); g_TimeMapList.SetValue(map, Cooldown, true);
//2026 march 18th: set cooldown on all maps that share a cooldown with this one including itself. //2026 march 18th: set cooldown on all maps that share a cooldown with this one including itself.
SetSharedCooldowns(map); SetSharedCooldowns(map);
@@ -3235,6 +3306,20 @@ stock int InternalGetMapCooldownTime(const char[] map)
return Cooldown; return Cooldown;
} }
public int additionalCooldownHoursCurrentMap()
{
int Cooldown = 0;
//0 == g_iImpactExtraCooldownTime means feature was disabled, so not adding any extra cooldown hours.
// g_avg_net_change < 0 means the map on average has a negative impact on player population
if (g_avg_net_change < 0 && g_iImpactExtraCooldownTime > 0)
{
//map has a negative impact on population and should be punished by additioanl g_iImpactExtraCooldownTime hours.
int extraCooldownHours = RoundToFloor((g_avg_net_change * -1) * g_iImpactExtraCooldownTime);
Cooldown += extraCooldownHours * 60 * 60; //Hours -> minutes -> seconds
}
return Cooldown;
}
stock int InternalGetMapMinTime(const char[] map) stock int InternalGetMapMinTime(const char[] map)
{ {
int MinTime = 0; int MinTime = 0;
@@ -560,8 +560,8 @@ public Action Command_Nominate(int client, int args)
return Plugin_Handled; return Plugin_Handled;
} }
//July 2024 edit: any person who is potential leader can just skip all cooldowns and map restrictions. same for admins. //October 2026: admins can just skip all cooldowns and map restrictions
if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(client)) if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) /* && !Leader_Is(client)*/ )
{ {
bool RestrictionsActive = AreRestrictionsActive(); bool RestrictionsActive = AreRestrictionsActive();
@@ -1158,7 +1158,7 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
return 0; return 0;
} }
if (!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1)) if (!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) /*&& !Leader_Is(param1)*/ )
{ {
if(AreRestrictionsActive() && ( if(AreRestrictionsActive() && (
GetMapCooldownTime(map) > GetTime() || GetMapCooldownTime(map) > GetTime() ||