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" {