added new cooldown system that tracks minutes played into database rows and sets maps on cooldown until they fallen down enough of the listing
This commit is contained in:
parent
01816792ae
commit
f590dcc7d1
@ -108,6 +108,8 @@ native CanNominateResult CanNominate();
|
||||
native bool ExcludeMap(const char[] map, int cooldown = 0, int mode = 0);
|
||||
// Cooldown in seconds
|
||||
native bool ExcludeMapTime(const char[] map, int cooldown = 0, int mode = 0);
|
||||
// cooldown based on mysql table rows listing
|
||||
native bool ExcludeMapListingPriority(const char[] map, int index);
|
||||
|
||||
native int GetMapCooldown(const char[] map);
|
||||
native int GetMapCooldownTime(const char[] map); // in unix time
|
||||
@ -117,6 +119,7 @@ native int GetMapMaxTime(const char[] map);
|
||||
native int GetMapMinPlayers(const char[] map);
|
||||
native int GetMapMaxPlayers(const char[] map);
|
||||
native int GetMapMinHoursAvg(const char[] map);
|
||||
native int GetExcludedMapListingPriority(const char[] map);
|
||||
|
||||
// 0 = Okay
|
||||
// >0 = Minutes till Okay
|
||||
|
||||
195
mapchooser_extended/scripting/map_cooldown_tracker.sp
Normal file
195
mapchooser_extended/scripting/map_cooldown_tracker.sp
Normal file
@ -0,0 +1,195 @@
|
||||
#pragma semicolon 1
|
||||
#define PLUGIN_AUTHOR "jenz"
|
||||
#define PLUGIN_VERSION "1.0"
|
||||
#include <sourcemod>
|
||||
#include <cstrike>
|
||||
#include <mapchooser_extended>
|
||||
|
||||
int g_iPlayerCount_time_track;
|
||||
int g_iTopMapsToMarkWithCooldown;
|
||||
int g_iUnmarkCooldowns;
|
||||
int g_iCurrentPlayerCount;
|
||||
int g_iMapStartTime;
|
||||
Database g_hDatabase;
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "map_tracker_cooldown",
|
||||
author = PLUGIN_AUTHOR,
|
||||
description = "assigns cooldowns on maps and tracks their played time on the server",
|
||||
version = PLUGIN_VERSION,
|
||||
url = "www.unloze.com"
|
||||
};
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
if (!g_hDatabase)
|
||||
{
|
||||
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||
}
|
||||
|
||||
ConVar cvar;
|
||||
HookConVarChange((cvar = CreateConVar("mce_min_players_track_time", "20", "Playercount in full number required for tracking minutes spend on a map.")), Cvar_playersCount);
|
||||
g_iPlayerCount_time_track = cvar.IntValue;
|
||||
delete cvar;
|
||||
|
||||
ConVar cvar1;
|
||||
HookConVarChange((cvar1 = CreateConVar("mce_top_ordered_maps_on_cooldown", "30", "These highest listed maps will receive the cooldown boolean")), Cvar_TopMarkedWithCooldown);
|
||||
g_iTopMapsToMarkWithCooldown = cvar1.IntValue;
|
||||
delete cvar1;
|
||||
|
||||
ConVar cvar2;
|
||||
HookConVarChange((cvar2 = CreateConVar("mce_UnmarkCooldowns", "120", "How far down the list does a map need to be for getting unmarked again")), Cvar_UnmarkedCooldown);
|
||||
g_iUnmarkCooldowns = cvar2.IntValue;
|
||||
delete cvar2;
|
||||
|
||||
g_iCurrentPlayerCount = GetClientCount(false);
|
||||
CreateTimer(30.0, CheckPlayerCount, _, TIMER_REPEAT);
|
||||
}
|
||||
|
||||
public Action CheckPlayerCount(Handle timer)
|
||||
{
|
||||
g_iCurrentPlayerCount = GetClientCount(false);
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
public void Cvar_playersCount(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
g_iPlayerCount_time_track = convar.IntValue;
|
||||
}
|
||||
|
||||
public void Cvar_TopMarkedWithCooldown(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
g_iTopMapsToMarkWithCooldown = convar.IntValue;
|
||||
}
|
||||
|
||||
public void Cvar_UnmarkedCooldown(ConVar convar, const char[] oldValue, const char[] newValue)
|
||||
{
|
||||
g_iUnmarkCooldowns = convar.IntValue;
|
||||
}
|
||||
|
||||
public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
|
||||
{
|
||||
if(!db || strlen(error))
|
||||
{
|
||||
LogError("Database error: %s", error);
|
||||
return;
|
||||
}
|
||||
g_hDatabase = db;
|
||||
UpdateTopListedMapsWithCooldown();
|
||||
}
|
||||
|
||||
public void OnMapStart()
|
||||
{
|
||||
int i_port = GetConVarInt(FindConVar("hostport"));
|
||||
if (i_port != 27019)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_iMapStartTime = GetTime();
|
||||
if (!g_hDatabase)
|
||||
{
|
||||
Database.Connect(SQL_OnDatabaseConnect, "unloze_playtimestats");
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateTopListedMapsWithCooldown();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateTopListedMapsWithCooldown()
|
||||
{
|
||||
//just set every map in top g_iTopMapsToMarkWithCooldown on cooldown
|
||||
char sQuery[512];
|
||||
Format(sQuery, sizeof(sQuery), "update unloze_playtimestats.map_minutes_played set on_cooldown = true where mapname in ( SELECT mapname FROM (select mmp.mapname from unloze_playtimestats.map_minutes_played mmp order by mmp.minutes desc limit %i) as top) and on_cooldown is false", g_iTopMapsToMarkWithCooldown);
|
||||
g_hDatabase.Query(SQL_FinishedQuery1, sQuery, _, DBPrio_Low);
|
||||
}
|
||||
|
||||
public void SQL_FinishedQuery1(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
delete results;
|
||||
if (!db || strlen(error))
|
||||
{
|
||||
LogError("Query error: %s", error);
|
||||
}
|
||||
delete data;
|
||||
UpdateUnmarkCooldown();
|
||||
}
|
||||
|
||||
public void UpdateUnmarkCooldown()
|
||||
{
|
||||
//if map in listing fell below g_iUnmarkCooldowns then set the bool to false again.
|
||||
char sQuery[512];
|
||||
Format(sQuery, sizeof(sQuery), "update unloze_playtimestats.map_minutes_played set on_cooldown = false where mapname not in ( SELECT mapname FROM (select mmp.mapname from unloze_playtimestats.map_minutes_played mmp order by mmp.minutes desc limit %i) as top) and on_cooldown is true", g_iUnmarkCooldowns);
|
||||
g_hDatabase.Query(SQL_FinishedQuery2, sQuery, _, DBPrio_Low);
|
||||
}
|
||||
|
||||
public void SQL_FinishedQuery2(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
delete results;
|
||||
if (!db || strlen(error))
|
||||
{
|
||||
LogError("Query error: %s", error);
|
||||
}
|
||||
delete data;
|
||||
SelectMapsToCooldownForMapChooser();
|
||||
}
|
||||
|
||||
public void SelectMapsToCooldownForMapChooser()
|
||||
{
|
||||
char sQuery[512];
|
||||
Format(sQuery, sizeof(sQuery), "select mapname, map_list_index from (select mapname, ROW_NUMBER() OVER(ORDER BY minutes DESC) as map_list_index, mmp.on_cooldown from unloze_playtimestats.map_minutes_played mmp) as targets where on_cooldown");
|
||||
g_hDatabase.Query(SQL_FinishedQuerySelectMaps, sQuery, _, DBPrio_Low);
|
||||
}
|
||||
|
||||
public void SQL_FinishedQuerySelectMaps(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
if (!db || strlen(error))
|
||||
{
|
||||
LogError("Query error in SQL_FinishedQuerySelectMaps: %s", error);
|
||||
delete results;
|
||||
return;
|
||||
}
|
||||
|
||||
while (results.RowCount && results.FetchRow())
|
||||
{
|
||||
char mapname[256];
|
||||
results.FetchString(0, mapname, sizeof(mapname));
|
||||
int map_list_index = results.FetchInt(1);
|
||||
ExcludeMapListingPriority(mapname, g_iUnmarkCooldowns - map_list_index);
|
||||
}
|
||||
delete results;
|
||||
}
|
||||
|
||||
public void OnMapEnd()
|
||||
{
|
||||
int i_port = GetConVarInt(FindConVar("hostport"));
|
||||
if (i_port != 27019)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (g_iCurrentPlayerCount > g_iPlayerCount_time_track)
|
||||
{
|
||||
int elapsed = GetTime() - g_iMapStartTime;
|
||||
int minutes = RoundToFloor(elapsed / 60.0);
|
||||
LogMessage("minutes: %i", minutes);
|
||||
|
||||
char Mapname[128];
|
||||
GetCurrentMap(Mapname, sizeof(Mapname));
|
||||
|
||||
char sQuery[512];
|
||||
Format(sQuery, sizeof(sQuery), "INSERT INTO `map_minutes_played` (`mapname`, `minutes`, `updated_on`) VALUES ('%s', '%i', NOW()) ON DUPLICATE KEY UPDATE `minutes` = `minutes` + '%i', `updated_on` = NOW()", Mapname, minutes, minutes);
|
||||
g_hDatabase.Query(SQL_FinishedQuery, sQuery, _, DBPrio_Low);
|
||||
}
|
||||
}
|
||||
|
||||
public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, DataPack data)
|
||||
{
|
||||
delete results;
|
||||
if (!db || strlen(error))
|
||||
{
|
||||
LogError("Query error: %s", error);
|
||||
}
|
||||
delete data;
|
||||
}
|
||||
@ -125,6 +125,7 @@ Handle g_MapList = INVALID_HANDLE;
|
||||
Handle g_NominateList[MAXPLAYERS + 1];
|
||||
StringMap g_OldMapList;
|
||||
StringMap g_TimeMapList;
|
||||
StringMap g_CooldownList;
|
||||
Handle g_NextMapList = INVALID_HANDLE;
|
||||
Handle g_VoteMenu = INVALID_HANDLE;
|
||||
KeyValues g_Config;
|
||||
@ -249,6 +250,7 @@ public void OnPluginStart()
|
||||
g_MapList = CreateArray(arraySize);
|
||||
g_OldMapList = new StringMap();
|
||||
g_TimeMapList = new StringMap();
|
||||
g_CooldownList = new StringMap();
|
||||
g_NextMapList = CreateArray(arraySize);
|
||||
g_OfficialList = CreateArray(arraySize);
|
||||
|
||||
@ -485,6 +487,8 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max
|
||||
CreateNative("AreRestrictionsActive", Native_AreRestrictionsActive);
|
||||
CreateNative("SimulateMapEnd", Native_SimulateMapEnd);
|
||||
CreateNative("GetAveragePlayerTimeOnServerMapRestriction", Native_GetAveragePlayerTimeOnServerMapRestriction);
|
||||
CreateNative("ExcludeMapListingPriority", Native_ExcludeMapListingPriority);
|
||||
CreateNative("GetExcludedMapListingPriority", Native_GetExcludedMapListingPriority);
|
||||
|
||||
return APLRes_Success;
|
||||
}
|
||||
@ -648,6 +652,15 @@ public void OnMapEnd()
|
||||
GetCurrentMap(map, PLATFORM_MAX_PATH);
|
||||
int Cooldown = InternalGetMapCooldown(map);
|
||||
|
||||
//resetting all again so they are added again onmapstart
|
||||
StringMapSnapshot CooldownList = g_CooldownList.Snapshot();
|
||||
for(int i = 0; i < CooldownList.Length; i++)
|
||||
{
|
||||
CooldownList.GetKey(i, map, sizeof(map));
|
||||
g_CooldownList.Remove(map);
|
||||
}
|
||||
|
||||
|
||||
StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot();
|
||||
for(int i = 0; i < OldMapListSnapshot.Length; i++)
|
||||
{
|
||||
@ -1038,42 +1051,43 @@ public Action Timer_fall_back_map_switch(Handle hTimer, Handle dp)
|
||||
static char map[PLATFORM_MAX_PATH];
|
||||
Handle tempMaps = CloneArray(g_MapList);
|
||||
|
||||
//if we stop using the casual pool feature we instead just rely on the default map to be used.
|
||||
if (g_iMapsFromCasualPool > 0)
|
||||
{
|
||||
int b;
|
||||
for(int j = 0; j < 1000; j++)
|
||||
{
|
||||
b = GetRandomInt(0, GetArraySize(tempMaps) - 1);
|
||||
GetArrayString(tempMaps, b, map, PLATFORM_MAX_PATH);
|
||||
if(!InternalAreRestrictionsActive())
|
||||
break;
|
||||
|
||||
if (!InternalGetCasualPool(map))
|
||||
//if we stop using the casual pool feature we instead just rely on the default map to be used.
|
||||
if (g_iMapsFromCasualPool > 0 && !InternalGetCasualPool(map))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (InternalGetExcludedMapListingPriority(map) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(InternalGetMapCooldownTime(map) > GetTime())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//found a map from casual pool to force to.
|
||||
|
||||
if(InternalGetMapVIPRestriction(map))
|
||||
continue;
|
||||
|
||||
if(InternalGetMapTimeRestriction(map) != 0)
|
||||
continue;
|
||||
|
||||
if(InternalGetMapPlayerRestriction(map) != 0)
|
||||
continue;
|
||||
|
||||
if (InternalGetAveragePlayerHourRestriction(map) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
ForceChangeLevel(map, "nobody voted at mapvote");
|
||||
}
|
||||
else
|
||||
{
|
||||
char map_line[256];
|
||||
File f = OpenFile("cfg/defaultmap.cfg", "r");
|
||||
if (f != null)
|
||||
{
|
||||
f.ReadLine(map_line, sizeof(map_line));
|
||||
CloseHandle(f);
|
||||
}
|
||||
ReplaceString(map_line, sizeof(map_line), "map ", "");
|
||||
TrimString(map_line);
|
||||
//LogMessage("map_line: %s", map_line);
|
||||
ForceChangeLevel(map_line, "nobody voted at mapvote");
|
||||
}
|
||||
delete tempMaps;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
@ -2193,9 +2207,6 @@ void CreateNextVote()
|
||||
}
|
||||
if (InternalGetMapCooldownTime(map) > GetTime())
|
||||
continue;
|
||||
//requested by keen in september 2024 that we have a pool that is prioritized when taking random maps.
|
||||
//it might be considered micro management which would indeed be bad. i guess this is mostly about pleasing a regular players request
|
||||
//which does not seem too outlandish to make possible.
|
||||
pickedFromCasualPool++;
|
||||
break;
|
||||
}
|
||||
@ -2203,6 +2214,11 @@ void CreateNextVote()
|
||||
if(!InternalAreRestrictionsActive())
|
||||
break;
|
||||
|
||||
if (InternalGetExcludedMapListingPriority(map) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(InternalGetMapCooldownTime(map) > GetTime())
|
||||
continue;
|
||||
|
||||
@ -2639,6 +2655,22 @@ public int Native_ExcludeMap(Handle plugin, int numParams)
|
||||
return true;
|
||||
}
|
||||
|
||||
//ExcludeMapListingPriority
|
||||
public int Native_ExcludeMapListingPriority(Handle plugin, int numParams)
|
||||
{
|
||||
int len;
|
||||
GetNativeStringLength(1, len);
|
||||
|
||||
if(len <= 0)
|
||||
return false;
|
||||
|
||||
char[] map = new char[len+1];
|
||||
GetNativeString(1, map, len+1);
|
||||
int index = GetNativeCell(2);
|
||||
g_CooldownList.SetValue(map, index, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int Native_ExcludeMapTime(Handle plugin, int numParams)
|
||||
{
|
||||
int len;
|
||||
@ -2730,6 +2762,27 @@ public int Native_GetMapCooldownTime(Handle plugin, int numParams)
|
||||
return Cooldown;
|
||||
}
|
||||
|
||||
//GetExcludedMapListingPriority
|
||||
public int Native_GetExcludedMapListingPriority(Handle plugin, int numParams)
|
||||
{
|
||||
int len;
|
||||
GetNativeStringLength(1, len);
|
||||
|
||||
if(len <= 0)
|
||||
return false;
|
||||
|
||||
char[] map = new char[len+1];
|
||||
GetNativeString(1, map, len+1);
|
||||
return InternalGetExcludedMapListingPriority(map);
|
||||
}
|
||||
|
||||
stock int InternalGetExcludedMapListingPriority(const char[] map)
|
||||
{
|
||||
int Index_Cooldown = 0;
|
||||
g_CooldownList.GetValue(map, Index_Cooldown);
|
||||
return Index_Cooldown;
|
||||
}
|
||||
|
||||
public int Native_GetMapMinTime(Handle plugin, int numParams)
|
||||
{
|
||||
int len;
|
||||
@ -3282,9 +3335,6 @@ stock bool InternalAreRestrictionsActive()
|
||||
return false;
|
||||
}
|
||||
|
||||
//if (IsValidClient(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !is_bot_player[i]
|
||||
// && (GetClientTeam(i) == CS_TEAM_T || GetClientTeam(i) == CS_TEAM_CT))
|
||||
|
||||
// a lot more simplified again so its easier to understand.
|
||||
int NumPlayers = GetClientCount(false);
|
||||
if (NumPlayers <= g_iSkipAllRestrictions)
|
||||
|
||||
@ -529,6 +529,13 @@ public Action Command_Nominate(int client, int args)
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
//yeah admins and leaders cant bypass these restrictions, maybe the admins really are the problem sometimes for skipping restrictions.
|
||||
int Index_Cooldown = GetExcludedMapListingPriority(mapname);
|
||||
if (Index_Cooldown > 0)
|
||||
{
|
||||
CPrintToChat(client, "[NE] Map is on Cooldown for being overplayed. List Posistion: %i", Index_Cooldown);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
//July 2024 edit: any person who is potential leader can just skip all cooldowns and map restrictions. same for admins.
|
||||
if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(client))
|
||||
@ -942,6 +949,7 @@ Menu BuildMapMenu(const char[] filter, int client)
|
||||
{
|
||||
if(AreRestrictionsActive() && (
|
||||
GetMapCooldownTime(map) > GetTime() ||
|
||||
GetExcludedMapListingPriority(map) > 0 ||
|
||||
GetMapTimeRestriction(map) ||
|
||||
GetMapPlayerRestriction(map) ||
|
||||
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
||||
@ -1034,6 +1042,12 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
||||
}
|
||||
|
||||
GetClientName(param1, name, MAX_NAME_LENGTH);
|
||||
int Index_Cooldown = GetExcludedMapListingPriority(map);
|
||||
if (Index_Cooldown > 0)
|
||||
{
|
||||
PrintToChat(param1, "[NE] You cant nominate this map right now. Overplayed Position: %i", Index_Cooldown);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1))
|
||||
{
|
||||
@ -1132,6 +1146,11 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
||||
delete MapList;
|
||||
delete OwnerList;
|
||||
|
||||
int Index_Cooldown = GetExcludedMapListingPriority(map);
|
||||
if (Index_Cooldown > 0)
|
||||
{
|
||||
return ITEMDRAW_DISABLED;
|
||||
}
|
||||
if(!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true) && !Leader_Is(param1))
|
||||
{
|
||||
if(AreRestrictionsActive() && (
|
||||
@ -1187,6 +1206,13 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p
|
||||
Format(buffer, sizeof(buffer), "%s (%T)", buffer, "VIP Restriction", param1);
|
||||
}
|
||||
|
||||
int Index_Cooldown = GetExcludedMapListingPriority(map);
|
||||
if (Index_Cooldown > 0)
|
||||
{
|
||||
Format(display, sizeof(display), "%s (Overplayed pos: %i)", map, Index_Cooldown);
|
||||
return RedrawMenuItem(display);
|
||||
}
|
||||
|
||||
int Cooldown = GetMapCooldownTime(map);
|
||||
if(RestrictionsActive && Cooldown > GetTime())
|
||||
{
|
||||
@ -1296,6 +1322,7 @@ public int Handler_AdminMapSelectMenu(Menu menu, MenuAction action, int param1,
|
||||
{
|
||||
if(AreRestrictionsActive() && (
|
||||
GetMapCooldownTime(map) > GetTime() || //this one is fine cause its admin nomination.
|
||||
GetExcludedMapListingPriority(map) > 0 ||
|
||||
GetMapTimeRestriction(map) ||
|
||||
GetMapPlayerRestriction(map) ||
|
||||
GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user