diff --git a/mapchooser_extended/scripting/mapchooser_extended_avg.sp b/mapchooser_extended/scripting/mapchooser_extended_avg.sp
index 9b11154d..8ad1fd3e 100755
--- a/mapchooser_extended/scripting/mapchooser_extended_avg.sp
+++ b/mapchooser_extended/scripting/mapchooser_extended_avg.sp
@@ -715,14 +715,25 @@ public Action Command_hours_average(int client, int args)
if (IsValidClient(i) && !is_bot_player[i] && PM_IsPlayerSteam(i))
{
GetPlayerWorthRTV_(i);
- total_votes += GetPlayerWorthRTV_boost_(i);
+ float nominate_worth = GetPlayerWorthRTV_boost_(i);
+ if (nominate_worth < 1.0)
+ {
+ nominate_worth = 1.0;
+ }
+ total_votes += nominate_worth;
}
}
+ float nominate_worth = GetPlayerWorthRTV_boost_(client);
+ if (nominate_worth < 1.0)
+ {
+ nominate_worth = 1.0;
+ }
+
CReplyToCommand(client, "Average hour count for nominations is: %i \nAverage hour count for mapvote and rtv boost is: %i \nYour mapvote and rtv boost is %0.1f \n(%i%% mapvote) (%i%% rtv)",
GetAveragePlayerTimeOnServer(),
GetAveragePlayerTimeOnServerRTV(),
- GetPlayerWorthRTV_boost_(client),
- RoundToFloor((GetPlayerWorthRTV_boost_(client)/total_votes) * 100),
+ nominate_worth,
+ RoundToFloor((nominate_worth/total_votes) * 100),
GetRtvPercentage(client));
return Plugin_Handled;
}
@@ -1056,7 +1067,13 @@ public Handle get_most_nominated_maps()
GetArrayString(g_NominateList[i], j, map_iteration, PLATFORM_MAX_PATH);
int nominate_count_for_particular_map = 0;
sm.GetValue(map_iteration, nominate_count_for_particular_map);
- nominate_count_for_particular_map++;
+
+ int nominate_worth = RoundToFloor(GetPlayerWorthRTV_boost_(i));
+ if (nominate_worth < 1)
+ {
+ nominate_worth = 1;
+ }
+ nominate_count_for_particular_map += nominate_worth;
//if i is 0 its admin nominated map that must come into the vote.
//if strequal the map was nominated by a leader and most be forced on the vote.
if(!i || StrEqual(map_iteration, MapleaderNominatedMap, false))
@@ -1406,7 +1423,12 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE)
if (IsValidClient(i) && PM_IsPlayerSteam(i) && !is_bot_player[i])
{
GetPlayerWorthRTV_(i);
- player_mapvote_worth[i] = GetPlayerWorthRTV_boost_(i);
+ float nominate_worth = GetPlayerWorthRTV_boost_(i);
+ if (nominate_worth < 1.0)
+ {
+ nominate_worth = 1.0;
+ }
+ player_mapvote_worth[i] = nominate_worth;
clients[count] = i;
count++;
}
@@ -1598,7 +1620,6 @@ public void Handler_MapVoteFinished(Handle menu,
if (IsValidClient(client) && !StrEqual(player_mapvote[client], ""))
{
//default intention is 1-5 votes, just like rtv.
- float vote_ammount = GetPlayerWorthRTV_boost_(client);
int item_index = client_info[i][VOTEINFO_CLIENT_ITEM];
static char map[PLATFORM_MAX_PATH];
for(int j = 0; j < num_items; j++)
@@ -1611,7 +1632,13 @@ public void Handler_MapVoteFinished(Handle menu,
}
float value = 0.0;
sm.GetValue(map, value);
- value += vote_ammount;
+
+ float nominate_worth = GetPlayerWorthRTV_boost_(client);
+ if (nominate_worth < 1.0)
+ {
+ nominate_worth = 1.0;
+ }
+ value += nominate_worth;
sm.SetValue(map, value, true);
}
}
diff --git a/mapchooser_extended/scripting/nominations_extended_avg.sp b/mapchooser_extended/scripting/nominations_extended_avg.sp
new file mode 100755
index 00000000..4c7ddc8c
--- /dev/null
+++ b/mapchooser_extended/scripting/nominations_extended_avg.sp
@@ -0,0 +1,1729 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * Nominations Extended
+ * Allows players to nominate maps for Mapchooser
+ *
+ * Nominations Extended (C)2012-2013 Powerlord (Ross Bemrose)
+ * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#pragma semicolon 1
+#pragma newdecls required
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define MCE_VERSION "1.4.1"
+
+public Plugin myinfo =
+{
+ name = "Map Nominations Extended",
+ author = "Powerlord and AlliedModders LLC",
+ description = "Provides Map Nominations",
+ version = MCE_VERSION,
+ url = "https://forums.alliedmods.net/showthread.php?t=156974"
+};
+
+Handle g_Cvar_ExcludeOld = INVALID_HANDLE;
+Handle g_Cvar_ExcludeCurrent = INVALID_HANDLE;
+
+Handle g_MapList = INVALID_HANDLE;
+Handle g_AdminMapList = INVALID_HANDLE;
+Menu g_MapMenu;
+Menu g_AdminMapMenu;
+int g_mapFileSerial = -1;
+int g_AdminMapFileSerial = -1;
+
+#define MAPSTATUS_ENABLED (1<<0)
+#define MAPSTATUS_DISABLED (1<<1)
+#define MAPSTATUS_EXCLUDE_CURRENT (1<<2)
+#define MAPSTATUS_EXCLUDE_PREVIOUS (1<<3)
+#define MAPSTATUS_EXCLUDE_NOMINATED (1<<4)
+
+Handle g_mapTrie;
+
+// Nominations Extended Convars
+Handle g_Cvar_MarkCustomMaps = INVALID_HANDLE;
+Handle g_Cvar_NominateDelay = INVALID_HANDLE;
+Handle g_Cvar_InitialDelay = INVALID_HANDLE;
+
+// VIP Nomination Convars
+Handle g_Cvar_VIPTimeframe = INVALID_HANDLE;
+Handle g_Cvar_VIPTimeframeMinTime = INVALID_HANDLE;
+Handle g_Cvar_VIPTimeframeMaxTime = INVALID_HANDLE;
+
+int g_Player_NominationDelay[MAXPLAYERS+1];
+int g_NominationDelay;
+int g_iMapleaderWhoNominatedMap = -1;
+char g_cMapLeaderNominatedMap[256];
+
+//clients ignoring maps that are unavailable
+bool g_bClientsIgnoring[MAXPLAYERS + 1];
+Database g_dDatabase;
+
+public void OnPluginStart()
+{
+ LoadTranslations("common.phrases");
+ LoadTranslations("nominations.phrases");
+ LoadTranslations("basetriggers.phrases"); // for Next Map phrase
+ LoadTranslations("mapchooser_extended.phrases");
+
+ int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
+ g_MapList = CreateArray(arraySize);
+ g_AdminMapList = CreateArray(arraySize);
+
+ g_Cvar_ExcludeOld = CreateConVar("sm_nominate_excludeold", "1", "Specifies if the current map should be excluded from the Nominations list", 0, true, 0.00, true, 1.0);
+ g_Cvar_ExcludeCurrent = CreateConVar("sm_nominate_excludecurrent", "1", "Specifies if the MapChooser excluded maps should also be excluded from Nominations", 0, true, 0.00, true, 1.0);
+ g_Cvar_InitialDelay = CreateConVar("sm_nominate_initialdelay", "60.0", "Time in seconds before first Nomination can be made", 0, true, 0.00);
+ g_Cvar_NominateDelay = CreateConVar("sm_nominate_delay", "3.0", "Delay between nominations", 0, true, 0.00, true, 60.00);
+
+ g_Cvar_VIPTimeframe = CreateConVar("sm_nominate_vip_timeframe", "1", "Specifies if the should be a timeframe where only VIPs can nominate maps", 0, true, 0.00, true, 1.0);
+ g_Cvar_VIPTimeframeMinTime = CreateConVar("sm_nominate_vip_timeframe_mintime", "1800", "Start of the timeframe where only VIPs can nominate maps (Format: HHMM)", 0, true, 0000.00, true, 2359.0);
+ g_Cvar_VIPTimeframeMaxTime = CreateConVar("sm_nominate_vip_timeframe_maxtime", "2200", "End of the timeframe where only VIPs can nominate maps (Format: HHMM)", 0, true, 0000.00, true, 2359.0);
+
+ RegConsoleCmd("say", Command_Say);
+ RegConsoleCmd("say_team", Command_Say);
+
+ RegConsoleCmd("sm_nominate", Command_Nominate);
+ RegConsoleCmd("sm_nom", Command_Nominate);
+ RegConsoleCmd("sm_nomlist", Command_NominateList);
+
+ RegAdminCmd("sm_nominate_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate_addmap - Forces a map to be on the next mapvote.");
+ RegAdminCmd("sm_nominate_removemap", Command_Removemap, ADMFLAG_CHANGEMAP, "sm_nominate_removemap - Removes a map from Nominations.");
+
+ RegAdminCmd("sm_nominate_exclude", Command_AddExclude, ADMFLAG_CHANGEMAP, "sm_nominate_exclude [cooldown] [mode]- Forces a map to be inserted into the recently played maps. Effectively blocking the map from being nominated.");
+ RegAdminCmd("sm_nominate_exclude_time", Command_AddExcludeTime, ADMFLAG_CHANGEMAP, "sm_nominate_exclude_time [cooldown] [mode] - Forces a map to be inserted into the recently played maps. Effectively blocking the map from being nominated.");
+
+ // Nominations Extended cvars
+ CreateConVar("ne_version", MCE_VERSION, "Nominations Extended Version", FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD);
+
+ g_mapTrie = CreateTrie();
+
+ //DB
+ if (!g_dDatabase)
+ {
+ //we have too many dbs so i am just re-using racetimercss
+ Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
+ }
+}
+
+public void OnMapStart()
+{
+ Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), "");
+ g_iMapleaderWhoNominatedMap = -1;
+ if (!g_dDatabase)
+ {
+ //we have too many dbs so i am just re-using racetimercss
+ Database.Connect(SQL_OnDatabaseConnect, "racetimercss");
+ }
+}
+
+public void SQL_OnDatabaseConnect(Database db, const char[] error, any data)
+{
+ if(!db || strlen(error))
+ {
+ LogError("Database error: %s", error);
+ return;
+ }
+ g_dDatabase = db;
+}
+
+public void OnClientPostAdminCheck(int client)
+{
+ g_bClientsIgnoring[client] = false;
+ sql_select_hiding_unavailable_maps(client);
+}
+
+public void sql_select_hiding_unavailable_maps(int client)
+{
+ if (!g_dDatabase)
+ {
+ return;
+ }
+ char query[255];
+ char steam_auth[64];
+ GetClientAuthId(client, AuthId_Steam2, steam_auth, sizeof(steam_auth));
+ //we have way too many dbs, just adding this to unloze_race_timer
+ Format(query, sizeof(query), "SELECT is_ignoring FROM `mapchooser_hide_unavailable` where steam_auth = '%s'", steam_auth);
+ g_dDatabase.Query(SQL_OnQueryCompleted_ignoring, query, GetClientSerial(client));
+}
+
+public void SQL_OnQueryCompleted_ignoring(Database db, DBResultSet results, const char[] error, int Serial)
+{
+ if (!db || results == INVALID_HANDLE)
+ {
+ delete results;
+ return;
+ }
+ int client;
+ if ((client = GetClientFromSerial(Serial)) == 0)
+ {
+ delete results;
+ return;
+ }
+ if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
+ {
+ int val = 0;
+ if (results.RowCount && results.FetchRow())
+ {
+ val = results.FetchInt(0);
+ }
+ if (val == 1)
+ {
+ g_bClientsIgnoring[client] = true;
+ }
+ }
+ delete results;
+}
+
+public void sql_insert_update_hiding_unavailable(int client)
+{
+ if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
+ {
+ if (g_bClientsIgnoring[client])
+ {
+ g_bClientsIgnoring[client] = false;
+ }
+ else
+ {
+ g_bClientsIgnoring[client] = true;
+ }
+ char sSID[64];
+ char sQuery[256];
+ GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID));
+ if (!g_dDatabase)
+ {
+ return;
+ }
+ if (StrEqual(sSID, "STEAM_ID_STOP_IGNORING_RETVALS") || StrEqual(sSID, "STEAM_ID_PENDING"))
+ {
+ PrintToChat(client, "Your steam ID is not working, not updating");
+ return;
+ }
+ Format(sQuery, sizeof(sQuery), "INSERT INTO `mapchooser_hide_unavailable` (`steam_auth`, `is_ignoring`) VALUES ('%s', '%i') ON DUPLICATE KEY UPDATE `is_ignoring` = '%i'", sSID, g_bClientsIgnoring[client], g_bClientsIgnoring[client]);
+ DataPack hDataPack = new DataPack();
+ hDataPack.WriteString(sQuery);
+ g_dDatabase.Query(SQL_FinishedQuery, sQuery, hDataPack, DBPrio_Normal);
+ }
+}
+
+public void SQL_FinishedQuery(Database db, DBResultSet results, const char[] error, DataPack data)
+{
+ if (!db || strlen(error))
+ {
+ char sQuery[256];
+ ResetPack(data);
+ data.ReadString(sQuery, sizeof(sQuery));
+ LogError("Query error 3: %s", error);
+ LogError("actual query: %s", sQuery);
+ }
+ delete results;
+ delete data;
+}
+
+public void OnClientDisconnect(int client)
+{
+ g_bClientsIgnoring[client] = false;
+}
+
+public APLRes AskPluginLoad2(Handle hThis, bool bLate, char[] err, int iErrLen)
+{
+ RegPluginLibrary("nominations");
+
+ CreateNative("GetNominationPool", Native_GetNominationPool);
+ CreateNative("PushMapIntoNominationPool", Native_PushMapIntoNominationPool);
+ CreateNative("PushMapsIntoNominationPool", Native_PushMapsIntoNominationPool);
+ CreateNative("RemoveMapFromNominationPool", Native_RemoveMapFromNominationPool);
+ CreateNative("RemoveMapsFromNominationPool", Native_RemoveMapsFromNominationPool);
+ CreateNative("GetMapleaderNominatedMap", Native_GetMapleaderNominatedMap);
+
+ return APLRes_Success;
+}
+
+public void OnAllPluginsLoaded()
+{
+ // This is an MCE cvar... this plugin requires MCE to be loaded. Granted, this plugin SHOULD have an MCE dependency.
+ g_Cvar_MarkCustomMaps = FindConVar("mce_markcustommaps");
+}
+
+public void OnConfigsExecuted()
+{
+ if(ReadMapList(g_MapList,
+ g_mapFileSerial,
+ "nominations",
+ MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER)
+ == INVALID_HANDLE)
+ {
+ if(g_mapFileSerial == -1)
+ {
+ SetFailState("Unable to create a valid map list.");
+ }
+ }
+
+ if(ReadMapList(g_AdminMapList,
+ g_AdminMapFileSerial,
+ "sm_nominate_addmap menu",
+ MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT|MAPLIST_FLAG_MAPSFOLDER)
+ == INVALID_HANDLE)
+ {
+ if(g_AdminMapFileSerial == -1)
+ {
+ SetFailState("Unable to create a valid admin map list.");
+ }
+ }
+ else
+ {
+ for(int i = 0; i < GetArraySize(g_MapList); i++)
+ {
+ static char map[PLATFORM_MAX_PATH];
+ GetArrayString(g_MapList, i, map, sizeof(map));
+
+ int Index = FindStringInArray(g_AdminMapList, map);
+ if(Index != -1)
+ RemoveFromArray(g_AdminMapList, Index);
+ }
+ }
+
+ g_NominationDelay = GetTime() + GetConVarInt(g_Cvar_InitialDelay);
+
+ UpdateMapTrie();
+ UpdateMapMenus();
+}
+
+void UpdateMapMenus()
+{
+ g_MapMenu = BuildMapMenu("", 0);
+ g_AdminMapMenu = BuildAdminMapMenu("");
+}
+
+void UpdateMapTrie()
+{
+ static char map[PLATFORM_MAX_PATH];
+ static char currentMap[PLATFORM_MAX_PATH];
+ ArrayList excludeMaps;
+
+ if(GetConVarBool(g_Cvar_ExcludeOld))
+ {
+ excludeMaps = CreateArray(ByteCountToCells(PLATFORM_MAX_PATH));
+ GetExcludeMapList(excludeMaps);
+ }
+
+ if(GetConVarBool(g_Cvar_ExcludeCurrent))
+ GetCurrentMap(currentMap, sizeof(currentMap));
+
+ ClearTrie(g_mapTrie);
+
+ for(int i = 0; i < GetArraySize(g_MapList); i++)
+ {
+ int status = MAPSTATUS_ENABLED;
+
+ GetArrayString(g_MapList, i, map, sizeof(map));
+
+ if(GetConVarBool(g_Cvar_ExcludeCurrent))
+ {
+ if(StrEqual(map, currentMap))
+ status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_CURRENT;
+ }
+
+ /* Dont bother with this check if the current map check passed */
+ if(GetConVarBool(g_Cvar_ExcludeOld) && status == MAPSTATUS_ENABLED)
+ {
+ if(FindStringInArray(excludeMaps, map) != -1)
+ status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS;
+ }
+
+ SetTrieValue(g_mapTrie, map, status);
+ }
+
+ if(excludeMaps)
+ delete excludeMaps;
+}
+
+public void OnNominationRemoved(const char[] map, int client)
+{
+ int status;
+ /* Is the map in our list? */
+ if(!GetTrieValue(g_mapTrie, map, status))
+ return;
+ int newclient = 0;
+ //just differientiating between if nomination was removed because of starting vote or because of anything else possible.
+ if (client > 100)
+ {
+ newclient = client - 100;
+ }
+ else
+ {
+ newclient = client;
+ }
+ if (newclient == g_iMapleaderWhoNominatedMap && StrEqual(map, g_cMapLeaderNominatedMap, false))
+ {
+ if (client > 100)
+ {
+ CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}nomination {red}%s {white}was forced into the mapvote.", newclient, map);
+ }
+ else
+ {
+ CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}has removed his Mapleader nomination {red}%s", newclient, map);
+ }
+ Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), "");
+ g_iMapleaderWhoNominatedMap = -1;
+ }
+ /* Was the map disabled due to being nominated */
+ if((status & MAPSTATUS_EXCLUDE_NOMINATED) != MAPSTATUS_EXCLUDE_NOMINATED)
+ return;
+ SetTrieValue(g_mapTrie, map, MAPSTATUS_ENABLED);
+}
+
+public Action Command_Addmap(int client, int args)
+{
+ if(args == 0)
+ {
+ AttemptAdminNominate(client);
+ return Plugin_Handled;
+ }
+
+ if(args != 1)
+ {
+ CReplyToCommand(client, "[NE] Usage: sm_nominate_addmap ");
+ return Plugin_Handled;
+ }
+
+ static char mapname[PLATFORM_MAX_PATH];
+ GetCmdArg(1, mapname, sizeof(mapname));
+
+ if(!IsMapValid(mapname))
+ {
+ CReplyToCommand(client, "%t", "Map was not found", mapname);
+ AttemptAdminNominate(client, mapname);
+ return Plugin_Handled;
+ }
+
+ if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) )
+ {
+ bool RestrictionsActive = AreRestrictionsActive();
+
+ int status;
+ if(GetTrieValue(g_mapTrie, mapname, status))
+ {
+ if((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
+ {
+ if((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
+ CPrintToChat(client, "[NE] %t", "Cant Nominate Current Map");
+
+ if(RestrictionsActive && (status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
+ {
+ int Cooldown = GetMapCooldown(mapname);
+ CPrintToChat(client, "[NE] %t (%d)", "Map in Exclude List", Cooldown);
+ }
+
+ if((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
+ CPrintToChat(client, "[NE] %t", "Map Already Nominated");
+
+ return Plugin_Handled;
+ }
+ }
+
+ int Cooldown = GetMapCooldownTime(mapname);
+ if(RestrictionsActive && Cooldown > GetTime())
+ {
+ int Seconds = Cooldown - GetTime();
+ CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60);
+
+ return Plugin_Handled;
+ }
+
+ int TimeRestriction = GetMapTimeRestriction(mapname);
+ if(RestrictionsActive && TimeRestriction)
+ {
+ CPrintToChat(client, "[NE] %t", "Map Nominate Time Error", TimeRestriction / 60, TimeRestriction % 60);
+
+ return Plugin_Handled;
+ }
+
+ int AverageHourRestricted = GetAveragePlayerTimeOnServerMapRestriction(mapname);
+ if (RestrictionsActive && AverageHourRestricted > 0)
+ {
+ PrintToChat(client, "%s requires +%i hours average. Use sm_houravg to check average.", mapname, AverageHourRestricted);
+ return Plugin_Handled;
+ }
+
+ int PlayerRestriction = GetMapPlayerRestriction(mapname);
+ if(RestrictionsActive && PlayerRestriction)
+ {
+ if(PlayerRestriction < 0)
+ CPrintToChat(client, "[NE] %t", "Map Nominate MinPlayers Error", PlayerRestriction * -1);
+ else
+ CPrintToChat(client, "[NE] %t", "Map Nominate MaxPlayers Error", PlayerRestriction);
+
+ return Plugin_Handled;
+ }
+ }
+
+
+ NominateResult result = NominateMap(mapname, true, 0);
+
+ if(result > Nominate_Replaced)
+ {
+ /* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it cant be full */
+ CReplyToCommand(client, "%t", "Map Already In Vote", mapname);
+
+ return Plugin_Handled;
+ }
+
+ SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
+
+ CReplyToCommand(client, "%t", "Map Inserted", mapname);
+ LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname);
+
+ PrintToChatAll("[NE] %N has inserted %s into nominations", client, mapname);
+
+ return Plugin_Handled;
+}
+
+public Action Command_Removemap(int client, int args)
+{
+ if(args == 0 && client > 0)
+ {
+ AttemptAdminRemoveMap(client);
+ return Plugin_Handled;
+ }
+
+ if(args != 1)
+ {
+ CReplyToCommand(client, "[NE] Usage: sm_nominate_removemap ");
+ return Plugin_Handled;
+ }
+
+ static char mapname[PLATFORM_MAX_PATH];
+ GetCmdArg(1, mapname, sizeof(mapname));
+
+ // int status;
+ if(/*!GetTrieValue(g_mapTrie, mapname, status)*/!IsMapValid(mapname))
+ {
+ CReplyToCommand(client, "%t", "Map was not found", mapname);
+ AttemptAdminRemoveMap(client, mapname);
+ return Plugin_Handled;
+ }
+
+ if(!RemoveNominationByMap(mapname))
+ {
+ CReplyToCommand(client, "This map isnt nominated.", mapname);
+
+ return Plugin_Handled;
+ }
+
+ CReplyToCommand(client, "Map '%s' removed from the nominations list.", mapname);
+ LogAction(client, -1, "\"%L\" removed map \"%s\" from nominations.", client, mapname);
+
+ PrintToChatAll("[NE] %N has removed %s from nominations", client, mapname);
+
+ return Plugin_Handled;
+}
+
+public Action Command_AddExclude(int client, int args)
+{
+ if(args < 1)
+ {
+ CReplyToCommand(client, "[NE] Usage: sm_nominate_exclude [cooldown] [mode]");
+ return Plugin_Handled;
+ }
+
+ static char mapname[PLATFORM_MAX_PATH];
+ GetCmdArg(1, mapname, sizeof(mapname));
+
+ int cooldown = 0;
+ int mode = 0;
+ if(args >= 2)
+ {
+ static char buffer[8];
+ GetCmdArg(2, buffer, sizeof(buffer));
+ cooldown = StringToInt(buffer);
+ }
+ if(args >= 3)
+ {
+ static char buffer[8];
+ GetCmdArg(3, buffer, sizeof(buffer));
+ mode = StringToInt(buffer);
+ }
+
+ int status;
+ if(!GetTrieValue(g_mapTrie, mapname, status))
+ {
+ ReplyToCommand(client, "[NE] %t", "Map was not found", mapname);
+ return Plugin_Handled;
+ }
+
+ ShowActivity(client, "Excluded map \"%s\" from nomination", mapname);
+ LogAction(client, -1, "\"%L\" excluded map \"%s\" from nomination", client, mapname);
+
+ SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS);
+
+ // native call to mapchooser_extended
+ ExcludeMap(mapname, cooldown, mode);
+
+ return Plugin_Handled;
+}
+
+public Action Command_AddExcludeTime(int client, int args)
+{
+ if(args < 1)
+ {
+ CReplyToCommand(client, "[NE] Usage: sm_nominate_exclude_time [cooldown] [mode]");
+ return Plugin_Handled;
+ }
+
+ static char mapname[PLATFORM_MAX_PATH];
+ GetCmdArg(1, mapname, sizeof(mapname));
+
+ int cooldown = 0;
+ int mode = 0;
+ if(args >= 2)
+ {
+ static char buffer[16];
+ GetCmdArg(2, buffer, sizeof(buffer));
+ cooldown = TimeStrToSeconds(buffer);
+ }
+ if(args >= 3)
+ {
+ static char buffer[8];
+ GetCmdArg(3, buffer, sizeof(buffer));
+ mode = StringToInt(buffer);
+ }
+
+ int status;
+ if(!GetTrieValue(g_mapTrie, mapname, status))
+ {
+ ReplyToCommand(client, "[NE] %t", "Map was not found", mapname);
+ return Plugin_Handled;
+ }
+
+ ShowActivity(client, "ExcludedTime map \"%s\" from nomination", mapname);
+ LogAction(client, -1, "\"%L\" excludedTime map \"%s\" from nomination", client, mapname);
+
+ // native call to mapchooser_extended
+ ExcludeMapTime(mapname, cooldown, mode);
+
+ return Plugin_Handled;
+}
+
+public Action Command_Say(int client, int args)
+{
+ if(!client)
+ return Plugin_Continue;
+
+ static char text[192];
+ if(!GetCmdArgString(text, sizeof(text)))
+ return Plugin_Continue;
+
+ int startidx = 0;
+ if(text[strlen(text)-1] == '"')
+ {
+ text[strlen(text)-1] = '\0';
+ startidx = 1;
+ }
+
+ ReplySource old = SetCmdReplySource(SM_REPLY_TO_CHAT);
+
+ if(strcmp(text[startidx], "nominate", false) == 0)
+ {
+ if(IsNominateAllowed(client))
+ {
+ if(g_NominationDelay > GetTime())
+ ReplyToCommand(client, "[NE] Nominations will be unlocked in %d seconds", g_NominationDelay - GetTime());
+ else
+ AttemptNominate(client);
+ }
+ }
+
+ SetCmdReplySource(old);
+
+ return Plugin_Continue;
+}
+
+public Action Command_Nominate(int client, int args)
+{
+ if(!client || !IsNominateAllowed(client))
+ return Plugin_Handled;
+
+ if(g_NominationDelay > GetTime())
+ {
+ PrintToChat(client, "[NE] Nominations will be unlocked in %d seconds", g_NominationDelay - GetTime());
+ return Plugin_Handled;
+ }
+
+ if(args == 0)
+ {
+ AttemptNominate(client);
+ return Plugin_Handled;
+ }
+
+ if(g_Player_NominationDelay[client] > GetTime())
+ {
+ PrintToChat(client, "[NE] Please wait %d seconds before you can nominate again", g_Player_NominationDelay[client] - GetTime());
+ return Plugin_Handled;
+ }
+
+ static char mapname[PLATFORM_MAX_PATH];
+ GetCmdArg(1, mapname, sizeof(mapname));
+
+
+ int status;
+ if(!GetTrieValue(g_mapTrie, mapname, status))
+ {
+ //CPrintToChat(client, "%t", "Map was not found", mapname);
+ ReplyToCommand(client, "Map was not found: %s", mapname);
+ AttemptNominate(client, mapname);
+ return Plugin_Handled;
+ }
+
+ bool RestrictionsActive = AreRestrictionsActive();
+
+ if((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
+ {
+ if((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
+ ReplyToCommand(client, "Cant Nominate Current Map.");
+ //CPrintToChat(client, "[NE] %t", "Cant Nominate Current Map");
+
+ if(RestrictionsActive && (status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
+ {
+ int Cooldown = GetMapCooldown(mapname);
+ CPrintToChat(client, "[NE] %t (%d)", "Map in Exclude List", Cooldown);
+ }
+
+ if((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
+ CPrintToChat(client, "[NE] %t", "Map Already Nominated");
+
+ return Plugin_Handled;
+ }
+
+ int mapLeader = Leader_CurrentLeader();
+ //2023 November edit: one map nominated by mapleader will automatically go to the vote.
+ if (client == mapLeader && StrEqual(g_cMapLeaderNominatedMap, ""))
+ {
+ CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}has nominated the map {red}%s{white}. The map will be in the next mapvote.", client, mapname);
+ CPrintToChatAll("{lightblue}If the map is nextmap and the leader wont play it he will be removed from leader access.");
+ Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), mapname);
+ g_iMapleaderWhoNominatedMap = client;
+ }
+ else
+ {
+ int Cooldown = GetMapCooldownTime(mapname);
+ if(RestrictionsActive && Cooldown > GetTime())
+ {
+ int Seconds = Cooldown - GetTime();
+ CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60);
+
+ return Plugin_Handled;
+ }
+
+ bool VIPRestriction = GetMapVIPRestriction(mapname, client);
+ if(RestrictionsActive && VIPRestriction)
+ {
+ CPrintToChat(client, "[NE] %t", "Map Nominate VIP Error");
+
+ return Plugin_Handled;
+ }
+
+ int TimeRestriction = GetMapTimeRestriction(mapname);
+ if(RestrictionsActive && TimeRestriction)
+ {
+ CPrintToChat(client, "[NE] %t", "Map Nominate Time Error", TimeRestriction / 60, TimeRestriction % 60);
+
+ return Plugin_Handled;
+ }
+
+ int AverageHourRestricted = GetAveragePlayerTimeOnServerMapRestriction(mapname);
+ if (RestrictionsActive && AverageHourRestricted > 0)
+ {
+ PrintToChat(client, "%s requires +%i hours average. Use sm_houravg to check average.", mapname, AverageHourRestricted);
+ return Plugin_Handled;
+ }
+
+ int PlayerRestriction = GetMapPlayerRestriction(mapname);
+ if(RestrictionsActive && PlayerRestriction)
+ {
+ if(PlayerRestriction < 0)
+ CPrintToChat(client, "[NE] %t", "Map Nominate MinPlayers Error", PlayerRestriction * -1);
+ else
+ CPrintToChat(client, "[NE] %t", "Map Nominate MaxPlayers Error", PlayerRestriction);
+
+ return Plugin_Handled;
+ }
+ }
+ NominateResult result = NominateMap(mapname, false, client);
+
+ if (result == Nominate_InvalidMap)
+ {
+ //CPrintToChat(client, "[NE] %t", "You already nominated the map ", mapname);
+ ReplyToCommand(client, "You already nominated the map.");
+ return Plugin_Handled;
+ }
+ if(result > Nominate_Replaced)
+ {
+ if(result == Nominate_AlreadyInVote)
+ CPrintToChat(client, "[NE] %t", "Map Already In Vote", mapname);
+ else if(result == Nominate_VoteFull)
+ CPrintToChat(client, "[NE] %t", "Max Nominations");
+
+ return Plugin_Handled;
+ }
+
+ /* Map was nominated! - Disable the menu item and update the trie */
+
+ //SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
+
+ static char name[MAX_NAME_LENGTH];
+ GetClientName(client, name, sizeof(name));
+
+ if(result == Nominate_Added)
+ {
+ int nominate_worth = RoundToFloor(GetPlayerWorthRTV_boost_(client));
+ if (nominate_worth < 1)
+ {
+ nominate_worth = 1;
+ }
+ PrintToChatAll("[NE] %t", "Map Nominated", name, mapname, nominate_worth);
+ }
+ else if(result == Nominate_Replaced)
+ {
+ PrintToChatAll("[NE] %t", "Map Nomination Changed", name, mapname);
+ }
+
+ LogMessage("%s nominated %s", name, mapname);
+
+ g_Player_NominationDelay[client] = GetTime() + GetConVarInt(g_Cvar_NominateDelay);
+
+ return Plugin_Continue;
+}
+
+public Action Command_NominateList(int client, int args)
+{
+ if (client == 0)
+ {
+ int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
+ ArrayList MapList = CreateArray(arraySize);
+ GetNominatedMapList(MapList);
+
+ char aBuf[2048];
+ StrCat(aBuf, sizeof(aBuf), "[NE] Nominated Maps:");
+ static char map[PLATFORM_MAX_PATH];
+ for(int i = 0; i < GetArraySize(MapList); i++)
+ {
+ StrCat(aBuf, sizeof(aBuf), "\n");
+ GetArrayString(MapList, i, map, sizeof(map));
+ StrCat(aBuf, sizeof(aBuf), map);
+ }
+
+ ReplyToCommand(client, aBuf);
+ delete MapList;
+ return Plugin_Handled;
+ }
+
+ Menu NominateListMenu = CreateMenu(Handler_NominateListMenu, MENU_ACTIONS_DEFAULT|MenuAction_DisplayItem);
+
+ if(!PopulateNominateListMenu(NominateListMenu, client))
+ {
+ ReplyToCommand(client, "[NE] No maps have been nominated.");
+ return Plugin_Handled;
+ }
+
+ SetMenuTitle(NominateListMenu, "Nominated Maps", client);
+ DisplayMenu(NominateListMenu, client, MENU_TIME_FOREVER);
+
+ return Plugin_Handled;
+}
+
+public int Handler_NominateListMenu(Menu menu, MenuAction action, int param1, int param2)
+{
+ switch(action)
+ {
+ case MenuAction_End:
+ {
+ delete menu;
+ }
+ }
+
+ return 0;
+}
+
+void AttemptNominate(int client, const char[] filter = "")
+{
+ if(!client)
+ return;
+
+ Menu menu = g_MapMenu;
+ menu = BuildMapMenu(filter, client);
+
+ int mapLeader = Leader_CurrentLeader();
+ if (client == mapLeader && StrEqual(g_cMapLeaderNominatedMap, ""))
+ {
+ SetMenuTitle(menu, "Nominate Map as Mapleader:", client);
+ }
+ else
+ {
+ GetPlayerWorthRTV_(client);
+ int nominate_worth = RoundToFloor(GetPlayerWorthRTV_boost_(client));
+ if (nominate_worth < 1)
+ {
+ nominate_worth = 1;
+ }
+ SetMenuTitle(menu, "%T", "Nominate Title", client, nominate_worth);
+ }
+ DisplayMenu(menu, client, MENU_TIME_FOREVER);
+}
+
+void AttemptAdminNominate(int client, const char[] filter = "")
+{
+ if(!client)
+ return;
+
+ Menu menu = g_AdminMapMenu;
+ if(filter[0])
+ menu = BuildAdminMapMenu(filter);
+
+ SetMenuTitle(menu, "%T", "Nominate Title", client, 999);
+ DisplayMenu(menu, client, MENU_TIME_FOREVER);
+}
+
+void AttemptAdminRemoveMap(int client, const char[] filter = "")
+{
+ if(!client)
+ return;
+
+ Menu AdminRemoveMapMenu = CreateMenu(Handler_AdminRemoveMapMenu, MENU_ACTIONS_DEFAULT|MenuAction_DisplayItem);
+
+ if(!PopulateNominateListMenu(AdminRemoveMapMenu, client, filter))
+ {
+ ReplyToCommand(client, "[NE] No maps have been nominated.");
+ return;
+ }
+
+ SetMenuTitle(AdminRemoveMapMenu, "Remove nomination", client);
+ DisplayMenu(AdminRemoveMapMenu, client, MENU_TIME_FOREVER);
+
+}
+
+int NominateListSortCmp(int index1, int index2, Handle array, Handle hndl)
+{
+ char map1[PLATFORM_MAX_PATH];
+ char map2[PLATFORM_MAX_PATH];
+ GetArrayString(array, index1, map1, sizeof(map1));
+ GetArrayString(array, index2, map2, sizeof(map2));
+
+ int count1, count2;
+
+ StringMap sm = view_as(hndl);
+
+ sm.GetValue(map1, count1);
+ sm.GetValue(map2, count2);
+
+ if (count1 == count2)
+ return 0;
+
+ return count1 > count2 ? -1 : 1;
+}
+
+bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "")
+{
+ int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
+ ArrayList MapList = CreateArray(arraySize);
+ ArrayList OwnerList = CreateArray();
+
+ GetNominatedMapList(MapList, OwnerList);
+ if(!GetArraySize(MapList))
+ {
+ delete MapList;
+ delete OwnerList;
+ return false;
+ }
+
+ StringMap sm = new StringMap();
+ static char map[PLATFORM_MAX_PATH];
+ static char display[PLATFORM_MAX_PATH];
+ for(int i = 0; i < GetArraySize(MapList); i++)
+ {
+ GetArrayString(MapList, i, map, sizeof(map));
+
+ if(!filter[0] || StrContains(map, filter, false) != -1)
+ {
+ //admin nominations must have most votes shrug
+ //this should work assuming that admin map nominations always fill the beginning of MapList uniquely
+ int owner = GetArrayCell(OwnerList, i);
+ int nominate_count_for_particular_map = 0;
+ sm.GetValue(map, nominate_count_for_particular_map);
+ //if its console its admin nomination. if its g_iMapleaderWhoNominatedMap it was map nominated by leader, also has to be correct map out of 3.
+ if(!owner || (owner == g_iMapleaderWhoNominatedMap && StrEqual(map, g_cMapLeaderNominatedMap)))
+ {
+ nominate_count_for_particular_map = 999;
+ }
+ else
+ {
+ int nominate_worth = RoundToFloor(GetPlayerWorthRTV_boost_(owner));
+ if (nominate_worth < 1)
+ {
+ nominate_worth = 1;
+ }
+ nominate_count_for_particular_map += nominate_worth;
+ }
+ sm.SetValue(map, nominate_count_for_particular_map, true);
+ }
+ }
+
+ StringMapSnapshot sm_snapshot = sm.Snapshot();
+ ArrayList SortedList = CreateArray(arraySize);
+
+ for(int i = 0; i < sm_snapshot.Length; i++)
+ {
+ sm_snapshot.GetKey(i, map, sizeof(map));
+ SortedList.PushString(map);
+ }
+
+ SortedList.SortCustom(NominateListSortCmp, sm);
+
+ for(int i = 0; i < GetArraySize(SortedList); i++)
+ {
+ GetArrayString(SortedList, i, map, sizeof(map));
+
+ if(!filter[0] || StrContains(map, filter, false) != -1)
+ {
+ int nominate_count_for_particular_map = 0;
+ sm.GetValue(map, nominate_count_for_particular_map);
+ strcopy(display, sizeof(display), map);
+
+ bool VIPRestriction = GetMapVIPRestriction(map);
+ if((VIPRestriction) && AreRestrictionsActive())
+ Format(display, sizeof(display), "%s (%T)", display, "VIP Nomination", client);
+
+ int owner = GetArrayCell(OwnerList, i);
+ char spelling[8];
+
+ Format(spelling, sizeof(spelling), nominate_count_for_particular_map == 1 ? "Vote" : "Votes");
+
+ if(!owner)
+ Format(display, sizeof(display), "%s (Admin)", display);
+ else if (StrEqual(map, g_cMapLeaderNominatedMap))
+ {
+ char leadername[MAX_NAME_LENGTH];
+ GetClientName(g_iMapleaderWhoNominatedMap, leadername, MAX_NAME_LENGTH);
+ Format(display, sizeof(display), "%s (Mapleader %s)", display, leadername);
+ }
+ else
+ Format(display, sizeof(display), "%s (%i %s)", display, nominate_count_for_particular_map, spelling);
+
+ AddMenuItem(menu, map, display);
+ }
+ }
+
+ delete MapList;
+ delete OwnerList;
+ delete SortedList;
+ delete sm;
+ delete sm_snapshot;
+ return true;
+}
+
+Menu BuildMapMenu(const char[] filter, int client)
+{
+ Menu menu = CreateMenu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem);
+
+ static char map[PLATFORM_MAX_PATH * 2];
+
+ int arraySize = ByteCountToCells(PLATFORM_MAX_PATH);
+ ArrayList MapList = CreateArray(arraySize);
+ ArrayList OwnerList = CreateArray();
+ StringMap sm = new StringMap();
+
+ GetNominatedMapList(MapList, OwnerList);
+ bool nominated_maps = true;
+ if (!GetArraySize(MapList))
+ {
+ nominated_maps = false;
+ }
+
+ if (client != 0 && nominated_maps)
+ {
+ for(int j = 0; j < GetArraySize(MapList); j++)
+ {
+ int owner = GetArrayCell(OwnerList, j);
+ if (client == owner)
+ {
+ GetArrayString(MapList, j, map, sizeof(map));
+ sm.SetValue(map, 1);
+ }
+ }
+ }
+
+ //2023 edit to allow hiding/unhiding unavailable maps
+ char hiding_unavailable_maps[MAX_NAME_LENGTH];
+ if (g_bClientsIgnoring[client])
+ {
+ Format(hiding_unavailable_maps, sizeof(hiding_unavailable_maps), "Show all unavailable maps");
+ }
+ else
+ {
+ Format(hiding_unavailable_maps, sizeof(hiding_unavailable_maps), "Hide all unavailable maps");
+ }
+ AddMenuItem(menu, hiding_unavailable_maps, hiding_unavailable_maps);
+
+ for(int i = 0; i < GetArraySize(g_MapList); i++)
+ {
+ GetArrayString(g_MapList, i, map, sizeof(map));
+
+ if(!filter[0] || StrContains(map, filter, false) != -1)
+ {
+ if (client != 0 && nominated_maps)
+ {
+ int map_present = 0;
+ sm.GetValue(map, map_present);
+ if (map_present == 1)
+ {
+ //PrintToChatAll("client %N here. map: %s", client, map);
+ StrCat(map, sizeof(map), " (Nominated)");
+ }
+ }
+ if (g_bClientsIgnoring[client])
+ {
+ if(AreRestrictionsActive() && (
+ GetMapCooldownTime(map) > GetTime() ||
+ GetMapTimeRestriction(map) ||
+ GetMapPlayerRestriction(map) ||
+ GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
+ GetMapVIPRestriction(map, client)))
+ {
+ continue;
+ }
+ }
+ AddMenuItem(menu, map, map);
+ }
+ }
+
+ delete MapList;
+ delete OwnerList;
+ delete sm;
+
+ SetMenuExitButton(menu, true);
+
+ return menu;
+}
+
+Menu BuildAdminMapMenu(const char[] filter)
+{
+ Menu menu = CreateMenu(Handler_AdminMapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem);
+
+ static char map[PLATFORM_MAX_PATH];
+
+ for(int i = 0; i < GetArraySize(g_AdminMapList); i++)
+ {
+ GetArrayString(g_AdminMapList, i, map, sizeof(map));
+
+ if(!filter[0] || StrContains(map, filter, false) != -1)
+ AddMenuItem(menu, map, map);
+ }
+
+ if(filter[0])
+ {
+ // Search normal maps aswell if filter is specified
+ for(int i = 0; i < GetArraySize(g_MapList); i++)
+ {
+ GetArrayString(g_MapList, i, map, sizeof(map));
+
+ if(!filter[0] || StrContains(map, filter, false) != -1)
+ AddMenuItem(menu, map, map);
+ }
+ }
+
+ SetMenuExitButton(menu, true);
+
+ return menu;
+}
+
+public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int param2)
+{
+ switch(action)
+ {
+ case MenuAction_End:
+ {
+ if (menu != g_MapMenu && menu != null)
+ {
+ delete menu;
+ }
+ }
+ case MenuAction_Select:
+ {
+ //2023-03-22 edit since client sometimes is 0 which fucks up mapchooser
+ if (param1 > 0 && param1 <= MaxClients && IsClientConnected(param1) && IsClientInGame(param1))
+ {
+ if(g_Player_NominationDelay[param1] > GetTime())
+ {
+ PrintToChat(param1, "[NE] Please wait %d seconds before you can nominate again", g_Player_NominationDelay[param1] - GetTime());
+ DisplayMenuAtItem(menu, param1, GetMenuSelectionPosition(), MENU_TIME_FOREVER);
+ return 0;
+ }
+
+ static char map[PLATFORM_MAX_PATH];
+ char name[MAX_NAME_LENGTH];
+ GetMenuItem(menu, param2, map, sizeof(map));
+
+ if (StrEqual(map, "Hide all unavailable maps"))
+ {
+ PrintToChat(param1, "Hiding all unavailable maps from the nomination list");
+ sql_insert_update_hiding_unavailable(param1);
+ return 0;
+ }
+ if (StrEqual(map, "Show all unavailable maps"))
+ {
+ PrintToChat(param1, "Displaying all unavailable maps from the nomination list");
+ sql_insert_update_hiding_unavailable(param1);
+ return 0;
+ }
+
+ GetClientName(param1, name, MAX_NAME_LENGTH);
+
+ int mapLeader = Leader_CurrentLeader();
+ //2023 November edit: one map nominated by mapleader will automatically go to the vote.
+ if (param1 == mapLeader && StrEqual(g_cMapLeaderNominatedMap, ""))
+ {
+ CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}has nominated the map {red}%s{white}. The map will be in the next mapvote.", param1, map);
+ CPrintToChatAll("{lightblue}If the map is nextmap and the leader wont play it he will be removed from leader access.");
+ Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), map);
+ g_iMapleaderWhoNominatedMap = param1;
+ }
+ else if(AreRestrictionsActive() && (
+ GetMapCooldownTime(map) > GetTime() ||
+ GetMapTimeRestriction(map) ||
+ GetMapPlayerRestriction(map) ||
+ GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
+ GetMapVIPRestriction(map, param1)))
+ {
+ PrintToChat(param1, "[NE] You cant nominate this map right now.");
+ return 0;
+ }
+
+ NominateResult result = NominateMap(map, false, param1);
+
+ if (result == Nominate_InvalidMap)
+ {
+ PrintToChat(param1, "[NE] You already nominated the map %s", map);
+ return 0;
+ }
+
+ /* Dont need to check for InvalidMap because the menu did that already */
+ if(result == Nominate_AlreadyInVote)
+ {
+ PrintToChat(param1, "[NE] %t", "Map Already Nominated");
+ return 0;
+ }
+ else if(result == Nominate_VoteFull)
+ {
+ PrintToChat(param1, "[NE] %t", "Max Nominations");
+ return 0;
+ }
+
+ //SetTrieValue(g_mapTrie, map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
+
+ if(result == Nominate_Added)
+ {
+ int nominate_worth = RoundToFloor(GetPlayerWorthRTV_boost_(param1));
+ if (nominate_worth < 1)
+ {
+ nominate_worth = 1;
+ }
+ PrintToChatAll("[NE] %t", "Map Nominated", name, map, nominate_worth);
+ }
+ else if(result == Nominate_Replaced)
+ {
+ PrintToChatAll("[NE] %t", "Map Nomination Changed", name, map);
+ }
+
+ LogMessage("%s nominated %s", name, map);
+ g_Player_NominationDelay[param1] = GetTime() + GetConVarInt(g_Cvar_NominateDelay);
+ }
+ }
+
+ case MenuAction_DrawItem:
+ {
+ static char map[PLATFORM_MAX_PATH];
+ GetMenuItem(menu, param2, map, sizeof(map));
+
+ int status;
+ if(GetTrieValue(g_mapTrie, map, status))
+ {
+ if((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
+ {
+ if((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
+ {
+ return ITEMDRAW_DISABLED;
+ }
+
+ if(AreRestrictionsActive() && (status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
+ {
+ return ITEMDRAW_DISABLED;
+ }
+
+ if((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
+ {
+ return ITEMDRAW_DISABLED;
+ }
+ }
+ }
+
+ int mapLeader = Leader_CurrentLeader();
+ if (param1 == mapLeader && StrEqual(g_cMapLeaderNominatedMap, ""))
+ {
+ return ITEMDRAW_DEFAULT;
+ }
+
+ if(AreRestrictionsActive() && (
+ GetMapCooldownTime(map) > GetTime() ||
+ GetMapTimeRestriction(map) ||
+ GetMapPlayerRestriction(map) ||
+ GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
+ GetMapVIPRestriction(map, param1)))
+ {
+ return ITEMDRAW_DISABLED;
+ }
+
+ return ITEMDRAW_DEFAULT;
+ }
+
+ case MenuAction_DisplayItem:
+ {
+ static char map[PLATFORM_MAX_PATH];
+ GetMenuItem(menu, param2, map, sizeof(map));
+
+ int mark = GetConVarInt(g_Cvar_MarkCustomMaps);
+ bool official;
+
+ static char buffer[100];
+ static char display[150];
+
+ if(mark)
+ official = IsMapOfficial(map);
+
+ if(mark && !official)
+ {
+ switch(mark)
+ {
+ case 1:
+ {
+ Format(buffer, sizeof(buffer), "%T", "Custom Marked", param1, map);
+ }
+
+ case 2:
+ {
+ Format(buffer, sizeof(buffer), "%T", "Custom", param1, map);
+ }
+ }
+ }
+ else
+ strcopy(buffer, sizeof(buffer), map);
+
+ bool RestrictionsActive = AreRestrictionsActive();
+
+ bool VIPRestriction = GetMapVIPRestriction(map);
+ if(RestrictionsActive && VIPRestriction)
+ {
+ Format(buffer, sizeof(buffer), "%s (%T)", buffer, "VIP Restriction", param1);
+ }
+
+ int status;
+ if(GetTrieValue(g_mapTrie, map, status))
+ {
+ if((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED)
+ {
+ if((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT)
+ {
+ Format(display, sizeof(display), "%s (%T)", buffer, "Current Map", param1);
+ return RedrawMenuItem(display);
+ }
+
+ if(RestrictionsActive && (status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS)
+ {
+ int Cooldown = GetMapCooldown(map);
+ Format(display, sizeof(display), "%s (%T %d)", buffer, "Recently Played", param1, Cooldown);
+ return RedrawMenuItem(display);
+ }
+
+ if((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED)
+ {
+ Format(display, sizeof(display), "%s (%T)", buffer, "Nominated", param1);
+ return RedrawMenuItem(display);
+ }
+ }
+ }
+
+ int Cooldown = GetMapCooldownTime(map);
+ if(RestrictionsActive && Cooldown > GetTime())
+ {
+ int Seconds = Cooldown - GetTime();
+ char time[16];
+ CustomFormatTime(Seconds, time, sizeof(time));
+ Format(display, sizeof(display), "%s (%T %s)", buffer, "Recently Played", param1, time);
+ return RedrawMenuItem(display);
+ }
+
+ int TimeRestriction = GetMapTimeRestriction(map);
+ if(RestrictionsActive && TimeRestriction)
+ {
+ Format(display, sizeof(display), "%s (%T)", buffer, "Map Time Restriction", param1, "+", TimeRestriction / 60, TimeRestriction % 60);
+ return RedrawMenuItem(display);
+ }
+
+ int AverageHourRestricted = GetAveragePlayerTimeOnServerMapRestriction(map);
+ if (RestrictionsActive && AverageHourRestricted > 0)
+ {
+ Format(display, sizeof(display), "%s (requires +%i hours average.)", map, AverageHourRestricted);
+ return RedrawMenuItem(display);
+ }
+
+ int PlayerRestriction = GetMapPlayerRestriction(map);
+ if(RestrictionsActive && PlayerRestriction)
+ {
+ if(PlayerRestriction < 0)
+ Format(display, sizeof(display), "%s (%T)", buffer, "Map Player Restriction", param1, "+", PlayerRestriction * -1);
+ else
+ Format(display, sizeof(display), "%s (%T)", buffer, "Map Player Restriction", param1, "-", PlayerRestriction);
+
+ return RedrawMenuItem(display);
+ }
+
+
+ if(RestrictionsActive && VIPRestriction)
+ {
+ return RedrawMenuItem(buffer);
+ }
+
+ if(mark && !official)
+ return RedrawMenuItem(buffer);
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+stock bool IsNominateAllowed(int client)
+{
+ if (BaseComm_IsClientGagged(client))
+ {
+ CReplyToCommand(client, "[NE] You are not allowed to nominate maps while you are gagged.");
+ return false;
+ }
+
+ if (!CheckCommandAccess(client, "sm_tag", ADMFLAG_CUSTOM1))
+ {
+ int VIPTimeRestriction = GetVIPTimeRestriction();
+ if((VIPTimeRestriction) && AreRestrictionsActive())
+ {
+ CReplyToCommand(client, "[NE] During peak hours only VIPs are allowed to nominate maps. Wait for %d hours and %d minutes or buy VIP at Unloze.com to nominate maps again.", VIPTimeRestriction / 60, VIPTimeRestriction % 60);
+ return false;
+ }
+ }
+
+ CanNominateResult result = CanNominate();
+
+ switch(result)
+ {
+ case CanNominate_No_VoteInProgress:
+ {
+ CReplyToCommand(client, "[NE] %t", "Nextmap Voting Started");
+ return false;
+ }
+
+ case CanNominate_No_VoteComplete:
+ {
+ char map[PLATFORM_MAX_PATH];
+ GetNextMap(map, sizeof(map));
+ CReplyToCommand(client, "[NE] %t", "Next Map", map);
+ return false;
+ }
+/*
+ case CanNominate_No_VoteFull:
+ {
+ CReplyToCommand(client, "[NE] %t", "Max Nominations");
+ return false;
+ }
+*/
+ }
+
+ return true;
+}
+
+public int Handler_AdminMapSelectMenu(Menu menu, MenuAction action, int param1, int param2)
+{
+ switch(action)
+ {
+ case MenuAction_End:
+ {
+ if(menu != g_AdminMapMenu)
+ delete menu;
+ }
+ case MenuAction_Select:
+ {
+ static char map[PLATFORM_MAX_PATH];
+ GetMenuItem(menu, param2, map, sizeof(map));
+
+ if(!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true))
+ {
+ if(AreRestrictionsActive() && (
+ GetMapCooldownTime(map) > GetTime() ||
+ GetMapTimeRestriction(map) ||
+ GetMapPlayerRestriction(map) ||
+ GetAveragePlayerTimeOnServerMapRestriction(map) > 0 ||
+ GetMapVIPRestriction(map, param1)))
+ {
+ PrintToChat(param1, "[NE] You cant nominate this map right now.");
+ return 0;
+ }
+ }
+
+ NominateResult result = NominateMap(map, true, 0);
+
+ if(result > Nominate_Replaced)
+ {
+ /* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it cant be full */
+ PrintToChat(param1, "[NE] %t", "Map Already In Vote", map);
+ return 0;
+ }
+
+ SetTrieValue(g_mapTrie, map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED);
+
+ PrintToChat(param1, "[NE] %t", "Map Inserted", map);
+ LogAction(param1, -1, "\"%L\" inserted map \"%s\".", param1, map);
+
+ PrintToChatAll("[NE] %N has inserted %s into nominations", param1, map);
+ }
+
+ case MenuAction_DrawItem:
+ {
+ if(!CheckCommandAccess(param1, "sm_nominate_ignore", ADMFLAG_KICK, true))
+ {
+ return Handler_MapSelectMenu(menu, action, param1, param2);
+ }
+
+ return ITEMDRAW_DEFAULT;
+ }
+
+ case MenuAction_DisplayItem:
+ {
+ return Handler_MapSelectMenu(menu, action, param1, param2);
+ }
+ }
+
+ return 0;
+}
+
+public int Handler_AdminRemoveMapMenu(Menu menu, MenuAction action, int param1, int param2)
+{
+ switch(action)
+ {
+ case MenuAction_End:
+ {
+ delete menu;
+ }
+ case MenuAction_Select:
+ {
+ static char map[PLATFORM_MAX_PATH];
+ GetMenuItem(menu, param2, map, sizeof(map));
+
+ if(!RemoveNominationByMap(map))
+ {
+ CReplyToCommand(param1, "This map isnt nominated.", map);
+ return 0;
+ }
+
+ CReplyToCommand(param1, "Map '%s' removed from the nominations list.", map);
+ LogAction(param1, -1, "\"%L\" removed map \"%s\" from nominations.", param1, map);
+
+ PrintToChatAll("[NE] %N has removed %s from nominations", param1, map);
+ }
+ }
+
+ return 0;
+}
+
+public int Native_GetNominationPool(Handle plugin, int numArgs)
+{
+ SetNativeCellRef(1, g_MapList);
+
+ return 0;
+}
+
+public int Native_PushMapIntoNominationPool(Handle plugin, int numArgs)
+{
+ char map[PLATFORM_MAX_PATH];
+
+ GetNativeString(1, map, PLATFORM_MAX_PATH);
+
+ ShiftArrayUp(g_MapList, 0);
+ SetArrayString(g_MapList, 0, map);
+
+ UpdateMapTrie();
+ UpdateMapMenus();
+
+ return 0;
+}
+
+public int Native_PushMapsIntoNominationPool(Handle plugin, int numArgs)
+{
+ ArrayList maps = GetNativeCell(1);
+
+ for (int i = 0; i < maps.Length; i++)
+ {
+ char map[PLATFORM_MAX_PATH];
+ maps.GetString(i, map, PLATFORM_MAX_PATH);
+
+ if (FindStringInArray(g_MapList, map) == -1)
+ {
+ ShiftArrayUp(g_MapList, 0);
+ SetArrayString(g_MapList, 0, map);
+ }
+ }
+
+ delete maps;
+
+ UpdateMapTrie();
+ UpdateMapMenus();
+
+ return 0;
+}
+
+public int Native_RemoveMapFromNominationPool(Handle plugin, int numArgs)
+{
+ char map[PLATFORM_MAX_PATH];
+
+ GetNativeString(1, map, PLATFORM_MAX_PATH);
+
+ int idx;
+
+ if ((idx = FindStringInArray(g_MapList, map)) != -1)
+ RemoveFromArray(g_MapList, idx);
+
+ UpdateMapTrie();
+ UpdateMapMenus();
+
+ return 0;
+}
+
+public int Native_RemoveMapsFromNominationPool(Handle plugin, int numArgs)
+{
+ ArrayList maps = GetNativeCell(1);
+
+ for (int i = 0; i < maps.Length; i++)
+ {
+ char map[PLATFORM_MAX_PATH];
+ maps.GetString(i, map, PLATFORM_MAX_PATH);
+
+ int idx = -1;
+
+ if ((idx = FindStringInArray(g_MapList, map)) != -1)
+ RemoveFromArray(g_MapList, idx);
+ }
+
+ delete maps;
+
+ UpdateMapTrie();
+ UpdateMapMenus();
+
+ return 0;
+}
+
+public int Native_GetMapleaderNominatedMap(Handle plugin, int numArgs)
+{
+ SetNativeString(1, g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), true);
+ return 0;
+}
+
+stock int GetVIPTimeRestriction()
+{
+ if (!GetConVarBool(g_Cvar_VIPTimeframe))
+ return 0;
+
+ char sTime[8];
+ FormatTime(sTime, sizeof(sTime), "%H%M");
+
+ int CurTime = StringToInt(sTime);
+ int MinTime = GetConVarInt(g_Cvar_VIPTimeframeMinTime);
+ int MaxTime = GetConVarInt(g_Cvar_VIPTimeframeMaxTime);
+
+ //Wrap around.
+ CurTime = (CurTime <= MinTime) ? CurTime + 2400 : CurTime;
+ MaxTime = (MaxTime <= MinTime) ? MaxTime + 2400 : MaxTime;
+
+ if ((MinTime <= CurTime <= MaxTime))
+ {
+ //Wrap around.
+ MinTime = (MinTime <= CurTime) ? MinTime + 2400 : MinTime;
+ MinTime = (MinTime <= MaxTime) ? MinTime + 2400 : MinTime;
+
+ // Convert our time to minutes.
+ CurTime = ((CurTime / 100) * 60) + (CurTime % 100);
+ MinTime = ((MinTime / 100) * 60) + (MinTime % 100);
+ MaxTime = ((MaxTime / 100) * 60) + (MaxTime % 100);
+
+ return MaxTime - CurTime;
+ }
+
+ return 0;
+}
+
+stock void CustomFormatTime(int seconds, char[] buffer, int maxlen)
+{
+ if(seconds <= 60)
+ Format(buffer, maxlen, "%ds", seconds);
+ else if(seconds <= 3600)
+ Format(buffer, maxlen, "%dm", seconds / 60);
+ else if(seconds < 10*3600)
+ Format(buffer, maxlen, "%dh%dm", seconds / 3600, (seconds % 3600) / 60);
+ else
+ Format(buffer, maxlen, "%dh", seconds / 3600);
+}
+
+stock int TimeStrToSeconds(const char[] str)
+{
+ int seconds = 0;
+ int maxlen = strlen(str);
+ for(int i = 0; i < maxlen;)
+ {
+ int val = 0;
+ i += StringToIntEx(str[i], val);
+ if(str[i] == 'h')
+ {
+ val *= 60;
+ i++;
+ }
+ seconds += val * 60;
+ }
+ return seconds;
+}
diff --git a/mapchooser_extended/translations/nominations.phrases.txt b/mapchooser_extended/translations/nominations.phrases.txt
index d5233f9e..690ed770 100644
--- a/mapchooser_extended/translations/nominations.phrases.txt
+++ b/mapchooser_extended/translations/nominations.phrases.txt
@@ -26,23 +26,24 @@
{
"en" "The map you chose has already been nominated."
}
-
- "Map Nominated"
- {
- "#format" "{1:s},{2:s}"
- "en" "{1} has nominated {2}."
- }
+ "Map Nominated"
+ {
+ "#format" "{1:s},{2:s},{3:i}"
+ "en" "{1} has nominated {2} ({3} Nomination Boost)."
+ }
+
"Map Nomination Changed"
{
"#format" "{1:s},{2:s}"
"en" "{1} has changed their nomination to {2}."
}
- "Nominate Title"
- {
- "en" "Nominate Map:"
- }
+ "Nominate Title"
+ {
+ "#format" "{1:i}"
+ "en" "Nominate Map: ({1} Nomination Boost)"
+ }
"Can't Nominate Current Map"
{