/** * 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; }