diff --git a/mapchooser_extended/scripting/mapchooser_extended_avg.sp b/mapchooser_extended/scripting/mapchooser_extended_avg.sp deleted file mode 100755 index 33e6589..0000000 --- a/mapchooser_extended/scripting/mapchooser_extended_avg.sp +++ /dev/null @@ -1,3271 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * MapChooser Extended - * Creates a map vote at appropriate times, setting sm_nextmap to the winning - * vote. Includes extra options not present in the SourceMod MapChooser - * - * MapChooser Extended (C)2011-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$ - */ - -//#define DEBUG - -#if defined DEBUG - #define assert(%1) if(!(%1)) ThrowError("Debug Assertion Failed"); - #define assert_msg(%1,%2) if(!(%1)) ThrowError(%2); -#else - #define assert(%1) - #define assert_msg(%1,%2) -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma semicolon 1 -#pragma newdecls required - -#define MCE_VERSION "1.3.1" - -enum RoundCounting -{ - RoundCounting_Standard = 0, - RoundCounting_MvM, - RoundCounting_ArmsRace, -} - -// CSGO requires two cvars to get the game type -enum -{ - GameType_Classic = 0, - GameType_GunGame = 1, - GameType_Training = 2, - GameType_Custom = 3, -} - -enum -{ - GunGameMode_ArmsRace = 0, - GunGameMode_Demolition = 1, - GunGameMode_DeathMatch = 2, -} - -public Plugin myinfo = -{ - name = "MapChooser Extended", - author = "Powerlord, Zuko, BotoX and AlliedModders LLC", - description = "Automated Map Voting with Extensions", - version = MCE_VERSION, - url = "" -}; - -/* Valve ConVars */ -ConVar g_Cvar_Winlimit; -ConVar g_Cvar_Maxrounds; -ConVar g_Cvar_Fraglimit; -ConVar g_Cvar_Bonusroundtime; -ConVar g_Cvar_GameType; -ConVar g_Cvar_GameMode; - -/* Plugin ConVars */ -ConVar g_Cvar_StartTime; -ConVar g_Cvar_StartRounds; -ConVar g_Cvar_StartFrags; -ConVar g_Cvar_ExtendTimeStep; -ConVar g_Cvar_ExtendRoundStep; -ConVar g_Cvar_ExtendFragStep; -ConVar g_Cvar_ExcludeMaps; -ConVar g_Cvar_ExcludeMapsTime; -ConVar g_Cvar_IncludeMaps; -ConVar g_Cvar_IncludeMapsReserved; -ConVar g_Cvar_NoVoteMode; -ConVar g_Cvar_Extend; -ConVar g_Cvar_DontChange; -ConVar g_Cvar_EndOfMapVote; -ConVar g_Cvar_VoteDuration; - -Handle g_VoteTimer = INVALID_HANDLE; -Handle g_RetryTimer = INVALID_HANDLE; -Handle g_WarningTimer = INVALID_HANDLE; - -/* Data Handles */ -Handle g_MapList = INVALID_HANDLE; -Handle g_NominateList[MAXPLAYERS + 1]; -Handle g_NominateOwners = INVALID_HANDLE; -StringMap g_OldMapList; -StringMap g_TimeMapList; -Handle g_NextMapList = INVALID_HANDLE; -Handle g_VoteMenu = INVALID_HANDLE; -KeyValues g_Config; - -int g_Extends; -int g_TotalRounds; -bool g_HasVoteStarted; -bool g_WaitingForVote; -bool g_MapVoteCompleted; -bool g_ChangeMapAtRoundEnd; -bool g_ChangeMapInProgress; -bool g_HasIntermissionStarted = false; -bool g_SaveCDOnMapEnd = true; -int g_mapFileSerial = -1; -int g_iPlayerCount_excludeSpec; -int g_iPlayerAFKTime; - - -int g_NominateCount = 0; -int g_NominateReservedCount = 0; -int g_iInterval; -float player_mapvote_worth[MAXPLAYERS + 1]; -char player_mapvote[MAXPLAYERS + 1][PLATFORM_MAX_PATH]; -MapChange g_ChangeTime; - -//check if autismbot -bool is_bot_player[MAXPLAYERS + 1]; - -Handle g_NominationsResetForward = INVALID_HANDLE; -Handle g_MapVoteStartedForward = INVALID_HANDLE; - -/* Mapchooser Extended Plugin ConVars */ - -ConVar g_Cvar_RunOff; -ConVar g_Cvar_RunOffPercent; -ConVar g_Cvar_BlockSlots; -ConVar g_Cvar_MaxRunOffs; -ConVar g_Cvar_StartTimePercent; -ConVar g_Cvar_StartTimePercentEnable; -ConVar g_Cvar_WarningTime; -ConVar g_Cvar_RunOffWarningTime; -ConVar g_Cvar_TimerLocation; -ConVar g_Cvar_ExtendPosition; -ConVar g_Cvar_MarkCustomMaps; -ConVar g_Cvar_RandomizeNominations; -ConVar g_Cvar_HideTimer; -ConVar g_Cvar_NoVoteOption; -ConVar g_Cvar_ShufflePerClient; -ConVar g_Cvar_NoRestrictionTimeframeEnable; -ConVar g_Cvar_NoRestrictionTimeframeMinTime; -ConVar g_Cvar_NoRestrictionTimeframeMaxTime; - -/* Mapchooser Extended Data Handles */ -Handle g_OfficialList = INVALID_HANDLE; - -/* Mapchooser Extended Forwards */ -Handle g_MapVoteWarningStartForward = INVALID_HANDLE; -Handle g_MapVoteWarningTickForward = INVALID_HANDLE; -Handle g_MapVoteStartForward = INVALID_HANDLE; -Handle g_MapVoteEndForward = INVALID_HANDLE; -Handle g_MapVoteRunoffStartForward = INVALID_HANDLE; - -/* Mapchooser Extended Globals */ -int g_RunoffCount = 0; -int g_mapOfficialFileSerial = -1; -char g_GameModName[64]; -bool g_WarningInProgress = false; -bool g_AddNoVote = false; - -RoundCounting g_RoundCounting = RoundCounting_Standard; - -/* Upper bound of how many team there could be */ -#define MAXTEAMS 10 -int g_winCount[MAXTEAMS]; - -bool g_BlockedSlots = false; -int g_ObjectiveEnt = -1; - -enum TimerLocation -{ - TimerLocation_Hint = 0, - TimerLocation_Center = 1, - TimerLocation_Chat = 2, -} - -enum WarningType -{ - WarningType_Vote, - WarningType_Revote, -} - -#define VOTE_EXTEND "##extend##" -#define VOTE_DONTCHANGE "##dontchange##" - -/* Mapchooser Extended Defines */ -#define LINE_ONE "##lineone##" -#define LINE_TWO "##linetwo##" -#define LINE_SPACER "##linespacer##" -#define FAILURE_TIMER_LENGTH 5 - -//call forward to reset all nominations -public void OnPluginEnd() -{ - for (int i = 0; i < MaxClients; i++) - { - int index = FindValueInArray(g_NominateOwners, i); - if (index == -1) continue; - for (int j = 0; j < GetArraySize(g_NominateList[i]); j++) - { - char oldmap[PLATFORM_MAX_PATH]; - Call_StartForward(g_NominationsResetForward); - GetArrayString(g_NominateList[i], j, oldmap, PLATFORM_MAX_PATH); - Call_PushString(oldmap); - Call_PushCell(i); - Call_Finish(); - } - } -} - -public void OnPluginStart() -{ - LoadTranslations("mapchooser_extended.phrases"); - LoadTranslations("basevotes.phrases"); - LoadTranslations("common.phrases"); - - int arraySize = ByteCountToCells(PLATFORM_MAX_PATH); - g_MapList = CreateArray(arraySize); - g_NominateOwners = CreateArray(1); - g_OldMapList = new StringMap(); - g_TimeMapList = new StringMap(); - g_NextMapList = CreateArray(arraySize); - g_OfficialList = CreateArray(arraySize); - - for (int i = 0; i < MaxClients; i++) - { - g_NominateList[i] = CreateArray(arraySize); - if (IsValidClient(i)) - { - OnClientPostAdminCheck(i); - } - } - - GetGameFolderName(g_GameModName, sizeof(g_GameModName)); - - g_Cvar_EndOfMapVote = CreateConVar("mce_endvote", "1", "Specifies if MapChooser should run an end of map vote", _, true, 0.0, true, 1.0); - - g_Cvar_StartTime = CreateConVar("mce_starttime", "10.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0); - g_Cvar_StartRounds = CreateConVar("mce_startround", "2.0", "Specifies when to start the vote based on rounds remaining. Use 0 on DoD:S, CS:S, and TF2 to start vote during bonus round time", _, true, 0.0); - g_Cvar_StartFrags = CreateConVar("mce_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0); - g_Cvar_ExtendTimeStep = CreateConVar("mce_extend_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0); - g_Cvar_ExtendRoundStep = CreateConVar("mce_extend_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 1.0); - g_Cvar_ExtendFragStep = CreateConVar("mce_extend_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0); - g_Cvar_ExcludeMaps = CreateConVar("mce_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0); - g_Cvar_ExcludeMapsTime = CreateConVar("mce_exclude_time", "5h", "Specifies how long in minutes an old map is excluded from the vote."); - g_Cvar_IncludeMaps = CreateConVar("mce_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 9.0); - g_Cvar_IncludeMapsReserved = CreateConVar("mce_include_reserved", "2", "Specifies how many private/random maps to include in the vote.", _, true, 0.0, true, 5.0); - g_Cvar_NoVoteMode = CreateConVar("mce_novote", "1", "Specifies whether or not MapChooser should pick a map if no votes are received.", _, true, 0.0, true, 1.0); - g_Cvar_Extend = CreateConVar("mce_extend", "0", "Number of extensions allowed each map.", _, true, 0.0); - g_Cvar_DontChange = CreateConVar("mce_dontchange", "1", "Specifies if a 'Don't Change option should be added to early votes", _, true, 0.0); - g_Cvar_VoteDuration = CreateConVar("mce_voteduration", "20", "Specifies how long the mapvote should be available for.", _, true, 5.0); - - - ConVar cvar1; - HookConVarChange((cvar1 = CreateConVar("sm_active_players_required", "15", "Amount of players required to be considered active before any restrictions are enabled at all.")), Cvar_playerExcludeSpec); - g_iPlayerCount_excludeSpec = cvar1.IntValue; - delete cvar1; - - ConVar cvar; - HookConVarChange((cvar = CreateConVar("sm_mapchooser_afk_time", "120", "Time in seconds until a player is considered as AFK and therefore excluded from player average")), Cvar_playerAFKTime); - g_iPlayerAFKTime = cvar.IntValue; - delete cvar; - - // MapChooser Extended cvars - CreateConVar("mce_version", MCE_VERSION, "MapChooser Extended Version", FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD); - - g_Cvar_RunOff = CreateConVar("mce_runoff", "1", "Hold run off votes if winning choice has less than a certain percentage of votes", _, true, 0.0, true, 1.0); - g_Cvar_RunOffPercent = CreateConVar("mce_runoffpercent", "50", "If winning choice has less than this percent of votes, hold a runoff", _, true, 0.0, true, 100.0); - g_Cvar_BlockSlots = CreateConVar("mce_blockslots", "0", "Block slots to prevent accidental votes. Only applies when Voice Command style menus are in use.", _, true, 0.0, true, 1.0); - //g_Cvar_BlockSlotsCount = CreateConVar("mce_blockslots_count", "2", "Number of slots to block.", _, true, 1.0, true, 3.0); - g_Cvar_MaxRunOffs = CreateConVar("mce_maxrunoffs", "1", "Number of run off votes allowed each map.", _, true, 0.0); - g_Cvar_StartTimePercent = CreateConVar("mce_start_percent", "35.0", "Specifies when to start the vote based on percents.", _, true, 0.0, true, 100.0); - g_Cvar_StartTimePercentEnable = CreateConVar("mce_start_percent_enable", "0", "Enable or Disable percentage calculations when to start vote.", _, true, 0.0, true, 1.0); - g_Cvar_WarningTime = CreateConVar("mce_warningtime", "15.0", "Warning time in seconds.", _, true, 0.0, true, 60.0); - g_Cvar_RunOffWarningTime = CreateConVar("mce_runoffvotewarningtime", "5.0", "Warning time for runoff vote in seconds.", _, true, 0.0, true, 30.0); - g_Cvar_TimerLocation = CreateConVar("mce_warningtimerlocation", "0", "Location for the warning timer text. 0 is HintBox, 1 is Center text, 2 is Chat. Defaults to HintBox.", _, true, 0.0, true, 2.0); - g_Cvar_MarkCustomMaps = CreateConVar("mce_markcustommaps", "1", "Mark custom maps in the vote list. 0 = Disabled, 1 = Mark with *, 2 = Mark with phrase.", _, true, 0.0, true, 2.0); - g_Cvar_ExtendPosition = CreateConVar("mce_extendposition", "0", "Position of Extend/Dont Change options. 0 = at end, 1 = at start.", _, true, 0.0, true, 1.0); - g_Cvar_RandomizeNominations = CreateConVar("mce_randomizeorder", "0", "Randomize map order?", _, true, 0.0, true, 1.0); - g_Cvar_HideTimer = CreateConVar("mce_hidetimer", "0", "Hide the MapChooser Extended warning timer", _, true, 0.0, true, 1.0); - g_Cvar_NoVoteOption = CreateConVar("mce_addnovote", "1", "Add \"No Vote\" to vote menu?", _, true, 0.0, true, 1.0); - g_Cvar_ShufflePerClient = CreateConVar("mce_shuffle_per_client", "1", "Random shuffle map vote menu per client?", _, true, 0.0, true, 1.0); - g_Cvar_NoRestrictionTimeframeEnable = CreateConVar("mce_no_restriction_timeframe_enable", "1", "Enable timeframe where all nomination restrictions and cooldowns are disabled?", _, true, 0.0, true, 1.0); - g_Cvar_NoRestrictionTimeframeMinTime = CreateConVar("mce_no_restriction_timeframe_mintime", "0100", "Start of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM)", _, true, 0000.0, true, 2359.0); - g_Cvar_NoRestrictionTimeframeMaxTime = CreateConVar("mce_no_restriction_timeframe_maxtime", "0700", "End of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM)", _, true, 0000.0, true, 2359.0); - - RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now."); - RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap "); - - // Mapchooser Extended Commands - RegAdminCmd("mce_reload_maplist", Command_ReloadMaps, ADMFLAG_CHANGEMAP, "mce_reload_maplist - Reload the Official Maplist file."); - - RegConsoleCmd("sm_extends", Command_ExtendsLeft, "sm_extends - Shows how many extends are left on the current map."); - RegConsoleCmd("sm_extendsleft", Command_ExtendsLeft, "sm_extendsleft - Shows how many extends are left on the current map."); - RegConsoleCmd("sm_houravg", Command_hours_average, "Prints in the chat what the current hour average of each player accumulated is."); - RegConsoleCmd("sm_avghour", Command_hours_average, "Prints in the chat what the current hour average of each player accumulated is."); - - g_Cvar_Winlimit = FindConVar("mp_winlimit"); - g_Cvar_Maxrounds = FindConVar("mp_maxrounds"); - g_Cvar_Fraglimit = FindConVar("mp_fraglimit"); - - EngineVersion version = GetEngineVersion(); - - static char mapListPath[PLATFORM_MAX_PATH]; - - BuildPath(Path_SM, mapListPath, PLATFORM_MAX_PATH, "configs/mapchooser_extended/maps/%s.txt", g_GameModName); - SetMapListCompatBind("official", mapListPath); - - switch(version) - { - case Engine_TF2: - { - g_Cvar_Bonusroundtime = FindConVar("mp_bonusroundtime"); - } - - case Engine_CSGO: - { - g_Cvar_GameType = FindConVar("game_type"); - g_Cvar_GameMode = FindConVar("game_mode"); - g_Cvar_Bonusroundtime = FindConVar("mp_round_restart_delay"); - } - - case Engine_DODS: - { - g_Cvar_Bonusroundtime = FindConVar("dod_bonusroundtime"); - } - - case Engine_CSS: - { - g_Cvar_Bonusroundtime = FindConVar("mp_round_restart_delay"); - } - - default: - { - g_Cvar_Bonusroundtime = FindConVar("mp_bonusroundtime"); - } - } - - switch(version) - { - case Engine_TF2: - { - HookEvent("teamplay_restart_round", Event_TFRestartRound); - HookEvent("pve_win_panel", Event_MvMWinPanel); - } - - case Engine_NuclearDawn: - { - HookEvent("round_win", Event_RoundEnd); - } - - case Engine_CSGO: - { - HookEvent("round_end", Event_RoundEnd); - HookEvent("cs_intermission", Event_Intermission); - HookEvent("announce_phase_end", Event_PhaseEnd); - } - - case Engine_DODS: - { - HookEvent("dod_round_win", Event_RoundEnd); - } - - default: - { - HookEvent("round_end", Event_RoundEnd); - } - } - - HookEvent("player_death", Event_PlayerDeath); - - AutoExecConfig(true, "mapchooser_extended"); - - //Change the mp_bonusroundtime max so that we have time to display the vote - //If you display a vote during bonus time good defaults are 17 vote duration and 19 mp_bonustime - SetConVarBounds(g_Cvar_Bonusroundtime, ConVarBound_Upper, true, 30.0); - - g_NominationsResetForward = CreateGlobalForward("OnNominationRemoved", ET_Ignore, Param_String, Param_Cell); - g_MapVoteStartedForward = CreateGlobalForward("OnMapVoteStarted", ET_Ignore); - - //MapChooser Extended Forwards - g_MapVoteStartForward = CreateGlobalForward("OnMapVoteStart", ET_Ignore); // Deprecated - g_MapVoteEndForward = CreateGlobalForward("OnMapVoteEnd", ET_Ignore, Param_String); - g_MapVoteWarningStartForward = CreateGlobalForward("OnMapVoteWarningStart", ET_Ignore); - g_MapVoteWarningTickForward = CreateGlobalForward("OnMapVoteWarningTick", ET_Ignore, Param_Cell); - g_MapVoteRunoffStartForward = CreateGlobalForward("OnMapVoteRunnoffWarningStart", ET_Ignore); - - - InternalRestoreMapCooldowns(); -} - -public void Cvar_playerExcludeSpec(ConVar convar, const char[] oldValue, const char[] newValue) -{ - g_iPlayerCount_excludeSpec = convar.IntValue; -} - -public void Cvar_playerAFKTime(ConVar convar, const char[] oldValue, const char[] newValue) -{ - g_iPlayerAFKTime = convar.IntValue; -} - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - if(LibraryExists("mapchooser")) - { - strcopy(error, err_max, "MapChooser already loaded, aborting."); - return APLRes_Failure; - } - - RegPluginLibrary("mapchooser"); - - MarkNativeAsOptional("GetEngineVersion"); - - CreateNative("NominateMap", Native_NominateMap); - CreateNative("RemoveNominationByMap", Native_RemoveNominationByMap); - CreateNative("RemoveNominationByOwner", Native_RemoveNominationByOwner); - CreateNative("InitiateMapChooserVote", Native_InitiateVote); - CreateNative("CanMapChooserStartVote", Native_CanVoteStart); - CreateNative("HasEndOfMapVoteFinished", Native_CheckVoteDone); - CreateNative("GetExcludeMapList", Native_GetExcludeMapList); - CreateNative("GetNominatedMapList", Native_GetNominatedMapList); - CreateNative("EndOfMapVoteEnabled", Native_EndOfMapVoteEnabled); - - // MapChooser Extended natives - CreateNative("IsMapOfficial", Native_IsMapOfficial); - CreateNative("CanNominate", Native_CanNominate); - CreateNative("ExcludeMap", Native_ExcludeMap); - CreateNative("ExcludeMapTime", Native_ExcludeMapTime); - CreateNative("GetMapCooldown", Native_GetMapCooldown); - CreateNative("GetMapCooldownTime", Native_GetMapCooldownTime); - CreateNative("GetMapMinTime", Native_GetMapMinTime); - CreateNative("GetMapMaxTime", Native_GetMapMaxTime); - CreateNative("GetMapMinPlayers", Native_GetMapMinPlayers); - CreateNative("GetMapMaxPlayers", Native_GetMapMaxPlayers); - CreateNative("GetMapTimeRestriction", Native_GetMapTimeRestriction); - CreateNative("GetMapPlayerRestriction", Native_GetMapPlayerRestriction); - CreateNative("GetMapGroups", Native_GetMapGroups); - CreateNative("GetMapGroupRestriction", Native_GetMapGroupRestriction); - CreateNative("GetMapVIPRestriction", Native_GetMapVIPRestriction); - CreateNative("GetExtendsLeft", Native_GetExtendsLeft); - CreateNative("AreRestrictionsActive", Native_AreRestrictionsActive); - CreateNative("SimulateMapEnd", Native_SimulateMapEnd); - CreateNative("GetAveragePlayerTimeOnServerMapRestriction", Native_GetAveragePlayerTimeOnServerMapRestriction); - - return APLRes_Success; -} - -public void OnMapStart() -{ - ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. - g_iInterval = 0; - static char folder[64]; - GetGameFolderName(folder, sizeof(folder)); - - g_RoundCounting = RoundCounting_Standard; - g_ObjectiveEnt = -1; - - if(strcmp(folder, "tf") == 0 && GameRules_GetProp("m_bPlayingMannVsMachine")) - { - g_RoundCounting = RoundCounting_MvM; - g_ObjectiveEnt = EntIndexToEntRef(FindEntityByClassname(-1, "tf_objective_resource")); - } - else if(strcmp(folder, "csgo") == 0 && GetConVarInt(g_Cvar_GameType) == GameType_GunGame && - GetConVarInt(g_Cvar_GameMode) == GunGameMode_ArmsRace) - { - g_RoundCounting = RoundCounting_ArmsRace; - } - - if(g_Config) - delete g_Config; - - char sConfigFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/mapchooser_extended.cfg"); - if(!FileExists(sConfigFile)) - { - LogMessage("Could not find config: \"%s\"", sConfigFile); - return; - } - LogMessage("Found config: \"%s\"", sConfigFile); - - g_Config = new KeyValues("mapchooser_extended"); - if(!g_Config.ImportFromFile(sConfigFile)) - { - delete g_Config; - LogMessage("ImportFromFile() failed!"); - return; - } - g_Config.Rewind(); - //this does not detect obvioulsy when there is more or less than 15 players active because its the mapstart - // nobody has connected yet. OnMapEnd also does not work for checking this. so no point setting it to false here. - if(InternalAreRestrictionsActive(true)) - g_SaveCDOnMapEnd = true; - else - g_SaveCDOnMapEnd = false; -} - -public void OnConfigsExecuted() -{ - if(ReadMapList(g_MapList, - g_mapFileSerial, - "mapchooser", - MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER) - != INVALID_HANDLE) - - { - if(g_mapFileSerial == -1) - LogError("Unable to create a valid map list."); - } - - - SetupTimeleftTimer(); - - g_TotalRounds = 0; - - g_Extends = 0; - - g_MapVoteCompleted = false; - - g_NominateCount = 0; - g_NominateReservedCount = 0; - for (int i = 0; i < MaxClients; i++) - { - if (g_NominateList[i] != INVALID_HANDLE) - { - ClearArray(g_NominateList[i]); - } - } - - ClearArray(g_NominateOwners); - - for(int i = 0; i < MAXTEAMS; i++) - g_winCount[i] = 0; - - /* Check if mapchooser will attempt to start mapvote during bonus round time */ - if (!GetConVarInt(g_Cvar_StartRounds)) - { - if(!GetConVarInt(g_Cvar_StartTime) && GetConVarFloat(g_Cvar_Bonusroundtime) <= GetConVarFloat(g_Cvar_VoteDuration)) - LogError("Warning - Bonus Round Time shorter than Vote Time. Votes during bonus round may not have time to complete"); - } - - InitializeOfficialMapList(); -} - -public void OnMapEnd() -{ - ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. - g_iInterval = 0; - g_HasVoteStarted = false; - g_WaitingForVote = false; - g_ChangeMapAtRoundEnd = false; - g_ChangeMapInProgress = false; - g_HasIntermissionStarted = false; - - g_VoteTimer = INVALID_HANDLE; - g_RetryTimer = INVALID_HANDLE; - g_WarningTimer = INVALID_HANDLE; - g_RunoffCount = 0; - - - static char map[PLATFORM_MAX_PATH]; - int Cooldown; - - if(g_SaveCDOnMapEnd) - { - GetCurrentMap(map, PLATFORM_MAX_PATH); - Cooldown = InternalGetMapCooldown(map); - g_OldMapList.SetValue(map, Cooldown, true); - - Cooldown = GetTime() + InternalGetMapCooldownTime(map) - RoundToFloor(GetGameTime()); - g_TimeMapList.SetValue(map, Cooldown, true); - } - - StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot(); - for(int i = 0; i < OldMapListSnapshot.Length; i++) - { - OldMapListSnapshot.GetKey(i, map, sizeof(map)); - g_OldMapList.GetValue(map, Cooldown); - - Cooldown--; - if(Cooldown > 0) - g_OldMapList.SetValue(map, Cooldown, true); - else - g_OldMapList.Remove(map); - } - delete OldMapListSnapshot; - - StringMapSnapshot TimeMapListSnapshot = g_TimeMapList.Snapshot(); - for(int i = 0; i < TimeMapListSnapshot.Length; i++) - { - TimeMapListSnapshot.GetKey(i, map, sizeof(map)); - g_TimeMapList.GetValue(map, Cooldown); - - if(Cooldown < GetTime()) - g_TimeMapList.Remove(map); - } - delete OldMapListSnapshot; - - InternalStoreMapCooldowns(); -} - -public void OnClientPutInServer(int client) -{ - if (g_NominateList[client] != INVALID_HANDLE) - { - ClearArray(g_NominateList[client]); - } -} - -public void OnClientDisconnect(int client) -{ - is_bot_player[client] = false; - player_mapvote_worth[client] = 0.0; - Format(player_mapvote[client], 128, ""); - int index = FindValueInArray(g_NominateOwners, client); - - if(index == -1) - return; - - //2023 edit for handling multiple nominations -jenz - for (int i = 0; i < GetArraySize(g_NominateList[client]); i++) - { - Call_StartForward(g_NominationsResetForward); - char oldmap[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[client], i, oldmap, PLATFORM_MAX_PATH); - Call_PushString(oldmap); - Call_PushCell(client); - Call_Finish(); - } - - RemoveFromArray(g_NominateOwners, index); - for (int i = 0; i < GetArraySize(g_NominateList[client]); i++) - { - RemoveFromArray(g_NominateList[client], i); - } - - ClearArray(g_NominateList[client]); - g_NominateCount--; -} - -public Action Command_SetNextmap(int client, int args) -{ - if(args < 1) - { - CReplyToCommand(client, "[MCE] Usage: sm_setnextmap "); - return Plugin_Handled; - } - - static char map[PLATFORM_MAX_PATH]; - GetCmdArg(1, map, PLATFORM_MAX_PATH); - - if(!IsMapValid(map)) - { - CReplyToCommand(client, "[MCE] %t", "Map was not found", map); - return Plugin_Handled; - } - - ShowActivity(client, "%t", "Changed Next Map", map); - LogAction(client, -1, "\"%L\" changed nextmap to \"%s\"", client, map); - - SetNextMap(map); - g_MapVoteCompleted = true; - //checking on MapStart and MapEnd is not good enough. Players are not considered alive and on teams at those points in time. - //therefore instead applying the bool here after the mapvote completed. - if(InternalAreRestrictionsActive(false)) - g_SaveCDOnMapEnd = true; - else - g_SaveCDOnMapEnd = false; - return Plugin_Handled; -} - -public Action Command_ReloadMaps(int client, int args) -{ - InitializeOfficialMapList(); - return Plugin_Handled; -} - -public Action Command_hours_average(int client, int args) -{ - float total_votes = 0.0; - for (int i = 0; i < MaxClients; i++) - { - if (IsValidClient(i) && !is_bot_player[i] && PM_IsPlayerSteam(i)) - { - GetPlayerWorthRTV_(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(), - nominate_worth, - RoundToFloor((nominate_worth/total_votes) * 100), - GetRtvPercentage(client)); - return Plugin_Handled; -} - -public Action Command_ExtendsLeft(int client, int args) -{ - CReplyToCommand(client, "[MCE] Available Extends: %d", GetConVarInt(g_Cvar_Extend) - g_Extends); - return Plugin_Handled; -} - -public void OnMapTimeLeftChanged() -{ - if(GetArraySize(g_MapList)) - { - //LogMessage("Mapchooser_extended_avg OnMapTimeLeftChanged call."); - SetupTimeleftTimer(); - } -} - -void SetupTimeleftTimer() -{ - int time; - if(GetMapTimeLeft(time) && time > 0) - { - int startTime; - if(GetConVarBool(g_Cvar_StartTimePercentEnable)) - { - int timeLimit; - if(GetMapTimeLimit(timeLimit) && timeLimit > 0) - { - startTime = GetConVarInt(g_Cvar_StartTimePercent) * (timeLimit * 60) / 100; - } - } - else - startTime = GetConVarInt(g_Cvar_StartTime) * 60; - - if(time - startTime < 0 && GetConVarBool(g_Cvar_EndOfMapVote) && !g_MapVoteCompleted && !g_HasVoteStarted && !g_WaitingForVote) - { - SetupWarningTimer(WarningType_Vote); - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 2"); - } - else - { - if(g_WarningTimer == INVALID_HANDLE) - { - if(g_VoteTimer != INVALID_HANDLE) - { - KillTimer(g_VoteTimer); - g_VoteTimer = INVALID_HANDLE; - } - - //g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVoteTimer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE); - //LogMessage("Mapchooser_extended_avg g_VoteTimer Timer_StartWarningTimer"); - g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartWarningTimer, _, TIMER_FLAG_NO_MAPCHANGE); - } - } - } -} - -public Action Timer_StartWarningTimer(Handle timer) -{ - g_VoteTimer = INVALID_HANDLE; - - if(!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) - { - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 3"); - SetupWarningTimer(WarningType_Vote); - } - return Plugin_Stop; -} - -public Action Timer_StartMapVote(Handle timer, Handle data) -{ - static int timePassed; - - // This is still necessary because InitiateVote still calls this directly via the retry timer - if(!GetArraySize(g_MapList) || !GetConVarBool(g_Cvar_EndOfMapVote) || g_MapVoteCompleted || g_HasVoteStarted) - { - g_WarningTimer = INVALID_HANDLE; - //LogMessage("Mapchooser_extended_avg Timer_Start MapVote Plugin_Stop"); - return Plugin_Stop; - } - - ResetPack(data); - int warningMaxTime = ReadPackCell(data); - int warningTimeRemaining = warningMaxTime - timePassed; - - char warningPhrase[32]; - ReadPackString(data, warningPhrase, sizeof(warningPhrase)); - - // Tick timer for external plugins - Call_StartForward(g_MapVoteWarningTickForward); - Call_PushCell(warningTimeRemaining); - Call_Finish(); - - if(timePassed == 0 || !GetConVarBool(g_Cvar_HideTimer)) - { - TimerLocation timerLocation = view_as(GetConVarInt(g_Cvar_TimerLocation)); - - switch(timerLocation) - { - case TimerLocation_Center: - { - PrintCenterTextAll("%t", warningPhrase, warningTimeRemaining); - } - - case TimerLocation_Chat: - { - PrintToChatAll("%t", warningPhrase, warningTimeRemaining); - } - - default: - { - PrintHintTextToAll("%t", warningPhrase, warningTimeRemaining); - } - } - } - - //LogMessage("timePassed: %i \n warningMaxTime: %i", timePassed, warningMaxTime); - if(timePassed++ >= warningMaxTime) - { - if(timer == g_RetryTimer) - { - g_WaitingForVote = false; - g_RetryTimer = INVALID_HANDLE; - } - else - g_WarningTimer = INVALID_HANDLE; - - timePassed = 0; - MapChange mapChange = view_as(ReadPackCell(data)); - Handle hndl = view_as(ReadPackCell(data)); - //LogMessage("Mapchooser_extended_avg calling InitiateVote()"); - InitiateVote(mapChange, hndl); - return Plugin_Stop; - } - - return Plugin_Continue; -} - -public void Event_TFRestartRound(Handle event, const char[] name, bool dontBroadcast) -{ - /* Game got restarted - reset our round count tracking */ - g_TotalRounds = 0; -} - -public void Event_MvMWinPanel(Handle event, const char[] name, bool dontBroadcast) -{ - if(GetEventInt(event, "winning_team") == 2) - { - int objectiveEnt = EntRefToEntIndex(g_ObjectiveEnt); - if(objectiveEnt != INVALID_ENT_REFERENCE) - { - g_TotalRounds = GetEntProp(g_ObjectiveEnt, Prop_Send, "m_nMannVsMachineWaveCount"); - CheckMaxRounds(g_TotalRounds); - } - } -} - -public void Event_Intermission(Handle event, const char[] name, bool dontBroadcast) -{ - g_HasIntermissionStarted = true; -} - -public void Event_PhaseEnd(Handle event, const char[] name, bool dontBroadcast) -{ - /* announce_phase_end fires for both half time and the end of the map, but intermission fires first for end of the map. */ - if(g_HasIntermissionStarted) - return; - - /* No intermission yet, so this must be half time. Swap the score counters. */ - int t_score = g_winCount[2]; - g_winCount[2] = g_winCount[3]; - g_winCount[3] = t_score; -} - -public void Event_WeaponRank(Handle event, const char[] name, bool dontBroadcast) -{ - int rank = GetEventInt(event, "weaponrank"); - if(rank > g_TotalRounds) - { - g_TotalRounds = rank; - CheckMaxRounds(g_TotalRounds); - } -} - -/* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */ -public void Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast) -{ - int timeleft; - GetMapTimeLeft(timeleft); - - if(timeleft <= 0 || g_ChangeMapAtRoundEnd) - { - char map[32]; - GetNextMap(map, sizeof(map)); - PrintToChatAll("[MCE] Next Map: %s", map); - PrintToChatAll("[MCE] Next Map: %s", map); - PrintToChatAll("[MCE] Next Map: %s", map); - } - - if(g_RoundCounting == RoundCounting_ArmsRace) - return; - - if(g_ChangeMapAtRoundEnd) - { - g_ChangeMapAtRoundEnd = false; - CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - g_ChangeMapInProgress = true; - } - - int winner; - if(strcmp(name, "round_win") == 0 || strcmp(name, "dod_round_win") == 0) - winner = GetEventInt(event, "team"); // Nuclear Dawn & DoD:S - else - winner = GetEventInt(event, "winner"); - - if(winner == 0 || winner == 1 || !GetConVarBool(g_Cvar_EndOfMapVote)) - return; - - if(winner >= MAXTEAMS) - SetFailState("Mod exceed maximum team count - Please file a bug report."); - - g_TotalRounds++; - - g_winCount[winner]++; - - if(!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted) - { - return; - } - - CheckWinLimit(g_winCount[winner]); - CheckMaxRounds(g_TotalRounds); -} - -public void CheckWinLimit(int winner_score) -{ - int winlimit = GetConVarInt(g_Cvar_Winlimit); - if(winlimit) - { - if(winner_score >= (winlimit - GetConVarInt(g_Cvar_StartRounds))) - { - if(!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) - { - SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 4"); - } - } - } -} - -public void CheckMaxRounds(int roundcount) -{ - int maxrounds = 0; - - if(g_RoundCounting == RoundCounting_ArmsRace) - maxrounds = GameRules_GetProp("m_iNumGunGameProgressiveWeaponsCT"); - else if(g_RoundCounting == RoundCounting_MvM) - maxrounds = GetEntProp(g_ObjectiveEnt, Prop_Send, "m_nMannVsMachineMaxWaveCount"); - else - return; - - if(maxrounds) - { - if(roundcount >= (maxrounds - GetConVarInt(g_Cvar_StartRounds))) - { - if(!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) - { - SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 5"); - } - } - } -} - -public Action Event_PlayerDeath(Handle event, const char[] name, bool dontBroadcast) -{ - if(!GetArraySize(g_MapList) || g_HasVoteStarted) - return Plugin_Continue; - - if(!GetConVarInt(g_Cvar_Fraglimit) || !GetConVarBool(g_Cvar_EndOfMapVote)) - return Plugin_Continue; - - if(g_MapVoteCompleted) - return Plugin_Continue; - - int fragger = GetClientOfUserId(GetEventInt(event, "attacker")); - - if(!fragger) - return Plugin_Continue; - - if(GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags))) - { - if(!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) - { - SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 6"); - } - } - return Plugin_Continue; -} - -public Action Command_Mapvote(int client, int args) -{ - ShowActivity2(client, "[MCE] ", "%t", "Initiated Vote Map"); - - SetupWarningTimer(WarningType_Vote, MapChange_MapEnd, INVALID_HANDLE, true); - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 7"); - - return Plugin_Handled; -} - -public Handle get_most_nominated_maps(bool create_next_vote) -{ - int arraySize = ByteCountToCells(PLATFORM_MAX_PATH); - Handle most_nominated_maps = CreateArray(arraySize); - StringMap sm = new StringMap(); - - for (int i = 0; i < MaxClients; i++) - { - for (int j = 0; j < GetArraySize(g_NominateList[i]); j++) - { - char map_iteration[PLATFORM_MAX_PATH]; - 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); - - //if i is 0 its admin nominated map that must come into the vote. - if (!i) - { - nominate_count_for_particular_map = 1999; - } - else - { - int nominate_worth = RoundToFloor(GetPlayerWorthRTV_boost_(i)); - if (nominate_worth < 1) - { - nominate_worth = 1; - } - nominate_count_for_particular_map += nominate_worth; - } - sm.SetValue(map_iteration, nominate_count_for_particular_map, true); - - if (!create_next_vote) - { - /* Notify Nominations that this map is now free */ - Call_StartForward(g_NominationsResetForward); - Call_PushString(map_iteration); - Call_PushCell(i + 100); //differentiate between all other calls and the call invoked by get_most_nominated_maps() - Call_Finish(); - } - } - } - static char map_[PLATFORM_MAX_PATH]; - - 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++) - { - char picked_map[MAX_NAME_LENGTH]; - GetArrayString(SortedList, i, picked_map, sizeof(picked_map)); - - //2023 edit: respecting that only right amount of maps per group is allowed in vote - int groups_[32]; - int groups[32]; - int groupsfound = InternalGetMapGroups(picked_map, groups, sizeof(groups)); - bool skip_nomination = false; - for (int group = 0; group < groupsfound; group ++) - { - int groupcur = 0; - int groupmax = InternalGetGroupMax(groups[group]); - if (groupmax >= 0) - { - for (int j = 0; j < GetArraySize(most_nominated_maps); j++) - { - //Native_GetMapGroupRestriction - GetArrayString(most_nominated_maps, j, map_, PLATFORM_MAX_PATH); - int tmp = InternalGetMapGroups(map_, groups_, sizeof(groups_)); - if (FindIntInArray(groups_, tmp, groups[group]) != -1) - { - groupcur++; - } - if (groupcur >= groupmax) - { - skip_nomination = true; - break; - } - } - if (skip_nomination) - { - break; - } - } - } - if (skip_nomination) - { - continue; - } - PushArrayString(most_nominated_maps, picked_map); - } - - delete sm; - return most_nominated_maps; -} - -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; -} - -/** - * Starts a new map vote - * - * @param when When the resulting map change should occur. - * @param inputlist Optional list of maps to use for the vote, otherwise an internal list of nominations + random maps will be used. - */ -void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) -{ - g_WaitingForVote = true; - g_WarningInProgress = false; - int MenuRandomShuffleStart = 0; - int MenuRandomShuffleStop = 0; - - // Check if a vote is in progress first - if(IsVoteInProgress()) - { - CPrintToChatAll("[MCE] %t", "Cannot Start Vote", FAILURE_TIMER_LENGTH); - Handle data; - g_RetryTimer = CreateDataTimer(1.0, Timer_StartMapVote, data, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT); - //LogMessage("Mapchooser_extended_avg: called Timer_StartMapVote"); - - /* Mapchooser Extended */ - WritePackCell(data, FAILURE_TIMER_LENGTH); - - if(GetConVarBool(g_Cvar_RunOff) && g_RunoffCount > 0) - WritePackString(data, "Revote Warning"); - else - WritePackString(data, "Vote Warning"); - /* End Mapchooser Extended */ - - WritePackCell(data, view_as(when)); - WritePackCell(data, view_as(inputlist)); - ResetPack(data); - return; - } - - /* If the main map vote has completed (and chosen result) and its currently changing (not a delayed change) we block further attempts */ - if(g_MapVoteCompleted && g_ChangeMapInProgress) - { - //LogMessage("Mapchooser_extended_avg ended here: g_MapVoteCompleted: %i \n g_ChangeMapInProgress: %i", g_MapVoteCompleted, g_ChangeMapInProgress); - return; - } - - CreateNextVote(); - - g_ChangeTime = when; - - ServerCommand("sm_cvar sm_vote_progress_hintbox 0"); //yeah its cheesy but does the job. - g_iInterval = GetConVarInt(g_Cvar_VoteDuration); - CreateTimer(1.0, Timer_Countdown, _, TIMER_REPEAT); - - g_HasVoteStarted = true; - - g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction_End | MenuAction_Display | MenuAction_DisplayItem | MenuAction_VoteCancel); - - g_AddNoVote = GetConVarBool(g_Cvar_NoVoteOption); - - // Block Vote Slots - if(GetConVarBool(g_Cvar_BlockSlots)) - { - Handle radioStyle = GetMenuStyleHandle(MenuStyle_Radio); - - if(GetMenuStyle(g_VoteMenu) == radioStyle) - { - g_BlockedSlots = true; - AddMenuItem(g_VoteMenu, LINE_ONE, "Choose something...", ITEMDRAW_DISABLED); - AddMenuItem(g_VoteMenu, LINE_TWO, "...will ya?", ITEMDRAW_DISABLED); - MenuRandomShuffleStart += 2; - - if(!g_AddNoVote) { - AddMenuItem(g_VoteMenu, LINE_SPACER, "", ITEMDRAW_SPACER); - MenuRandomShuffleStart++; - } - } - else - g_BlockedSlots = false; - } - - if(g_AddNoVote) - SetMenuOptionFlags(g_VoteMenu, MENUFLAG_BUTTON_NOVOTE); - - SetMenuTitle(g_VoteMenu, "Vote Nextmap"); - SetVoteResultCallback(g_VoteMenu, Handler_MapVoteFinished); - - /* Call OnMapVoteStarted() Forward */ -// Call_StartForward(g_MapVoteStartedForward); -// Call_Finish(); - - /** - * TODO: Make a proper decision on when to clear the nominations list. - * Currently it clears when used, and stays if an external list is provided. - * Is this the right thing to do? External lists will probably come from places - * like sm_mapvote from the adminmenu in the future. - */ - - static char map[PLATFORM_MAX_PATH]; - - /* No input given - User our internal nominations and maplist */ - if(inputlist == INVALID_HANDLE) - { - Handle randomizeList = INVALID_HANDLE; - //2023 edit to allow multiple nominations per player - Handle most_nominated_maps = get_most_nominated_maps(false); - - int voteSize = GetVoteSize(0); //voteSize wrong size probably for my for loop - - if(GetConVarBool(g_Cvar_RandomizeNominations)) - randomizeList = CloneArray(most_nominated_maps); - - int nominateCount = GetArraySize(most_nominated_maps); - - - /* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */ - int nominationsToAdd = nominateCount >= voteSize ? voteSize : nominateCount; - - bool extendFirst = GetConVarBool(g_Cvar_ExtendPosition); - - if(extendFirst) { - AddExtendToMenu(g_VoteMenu, when); - MenuRandomShuffleStart++; - } - - for(int i = 0; i < nominationsToAdd; i++) - { - GetArrayString(most_nominated_maps, i, map, PLATFORM_MAX_PATH); - - if(randomizeList == INVALID_HANDLE) - AddMapItem(map); - RemoveStringFromArray(g_NextMapList, map); - } - - - /* There should currently be 'nominationsToAdd' unique maps in the vote */ - - int i = nominationsToAdd; - int count = 0; - int availableMaps = GetArraySize(g_NextMapList); - - if(i < voteSize && availableMaps == 0) - { - if(i == 0) - { - LogError("No maps available for vote."); - return; - } - else - { - LogMessage("Not enough maps to fill map list, reducing map count. Adjust mce_include and mce_exclude to avoid this warning."); - voteSize = i; - } - } - - while(i < voteSize) - { - GetArrayString(g_NextMapList, count, map, PLATFORM_MAX_PATH); - count++; - - if(randomizeList == INVALID_HANDLE) - { - /* Insert the map and increment our count */ - AddMapItem(map); - } - else - PushArrayString(randomizeList, map); - i++; - - //Run out of maps, this will have to do. - if(count >= availableMaps) - break; - } - - if(randomizeList != INVALID_HANDLE) - { - // Fisher-Yates Shuffle - for(int j = GetArraySize(randomizeList) - 1; j >= 1; j--) - { - int k = GetRandomInt(0, j); - SwapArrayItems(randomizeList, j, k); - } - - for(int j = 0; j < GetArraySize(randomizeList); j++) - { - GetArrayString(randomizeList, j, map, PLATFORM_MAX_PATH); - AddMapItem(map); - } - - delete randomizeList; - randomizeList = INVALID_HANDLE; - delete most_nominated_maps; - most_nominated_maps = INVALID_HANDLE; - } - - /* Wipe out our nominations list - Nominations have already been informed of this */ - g_NominateCount = 0; - g_NominateReservedCount = 0; - ClearArray(g_NominateOwners); - for (int j = 0; j < MaxClients; j++) - { - ClearArray(g_NominateList[j]); - } - - if(!extendFirst) { - AddExtendToMenu(g_VoteMenu, when); - MenuRandomShuffleStop++; - } - } - else //We were given a list of maps to start the vote with - { - int size = GetArraySize(inputlist); - - for(int i = 0; i < size; i++) - { - GetArrayString(inputlist, i, map, PLATFORM_MAX_PATH); - - if(IsMapValid(map)) - { - AddMapItem(map); - } - // New in Mapchooser Extended - else if(StrEqual(map, VOTE_DONTCHANGE)) - { - AddMenuItem(g_VoteMenu, VOTE_DONTCHANGE, "Dont Change"); - } - else if(StrEqual(map, VOTE_EXTEND)) - { - AddMenuItem(g_VoteMenu, VOTE_EXTEND, "Extend Map"); - } - } - delete inputlist; - } - - int voteDuration = GetConVarInt(g_Cvar_VoteDuration); - - //SetMenuExitButton(g_VoteMenu, false); - - if(GetVoteSize(0) <= GetMaxPageItems(GetMenuStyle(g_VoteMenu))) - { - //This is necessary to get items 9 and 0 as usable voting items - SetMenuPagination(g_VoteMenu, MENU_NO_PAGINATION); - } - - if(GetConVarInt(g_Cvar_ShufflePerClient)) - MenuShufflePerClient(g_VoteMenu, MenuRandomShuffleStart, GetMenuItemCount(g_VoteMenu) - MenuRandomShuffleStop); - - //VoteMenuToAll(g_VoteMenu, voteDuration); - //2023 excluding nosteamers and autismbots. - - int clients[MAXPLAYERS + 1]; - int count = 0; - //here we pick clients to show the vote to, we dont show it to autismbots and nosteamers. - for (int i = 0; i < MaxClients; i++) - { - player_mapvote_worth[i] = 0.0; - Format(player_mapvote[i], 128, ""); - if (IsValidClient(i) && PM_IsPlayerSteam(i) && !is_bot_player[i]) - { - GetPlayerWorthRTV_(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++; - } - } - VoteMenu(g_VoteMenu, clients, sizeof(clients), voteDuration); - - /* Call OnMapVoteStarted() Forward */ - Call_StartForward(g_MapVoteStartForward); // Deprecated - Call_Finish(); - - Call_StartForward(g_MapVoteStartedForward); - Call_Finish(); - - LogAction(-1, -1, "Voting for next map has started."); - CPrintToChatAll("[MCE] %t", "Nextmap Voting Started"); -} - -public Action Timer_Countdown(Handle timer) -{ - if (g_iInterval <= 0) - return Plugin_Stop; - - float most_voted[3]; - char most_voted_map[3][PLATFORM_MAX_PATH]; - - for (int j = 0; j < 3; j++) - { - float max_count = 0.0; - StringMap sm = new StringMap(); - char picked_map[PLATFORM_MAX_PATH]; - for (int i = 0; i < MaxClients; i++) - { - if (IsValidClient(i) && !StrEqual(player_mapvote[i], "") && !is_bot_player[i] && PM_IsPlayerSteam(i)) - { - if (StrEqual(player_mapvote[i], most_voted_map[0]) || StrEqual(player_mapvote[i], most_voted_map[1]) || - StrEqual(player_mapvote[i], most_voted_map[2])) - { - continue; - } - float value = 0.0; - sm.GetValue(player_mapvote[i], value); - value += player_mapvote_worth[i]; - sm.SetValue(player_mapvote[i], value, true); - if (value >= max_count) - { - max_count = value; - strcopy(picked_map, sizeof(picked_map), player_mapvote[i]); - } - } - } - most_voted[j] = max_count; - Format(most_voted_map[j], PLATFORM_MAX_PATH, picked_map); - delete sm; - } - - float total_votes = 0.0; - float voted_so_far = 0.0; - for (int i = 0; i < MaxClients; i++) - { - if (IsValidClient(i) && !is_bot_player[i] && PM_IsPlayerSteam(i)) - { - total_votes += player_mapvote_worth[i]; - //LogMessage("client: %N player_mapvote_worth i: %f", i, player_mapvote_worth[i]); - if (!StrEqual(player_mapvote[i], "")) - { - voted_so_far += player_mapvote_worth[i]; - } - } - } - //why on earth is %%%s needed for formatting it to show a % lmao. just %s, "%" or %% on their own dont work. - if (strlen(most_voted_map[2]) > 0) - { - //displaying 3 most voted maps - PrintHintTextToAll("Votes: %i/100%%%s, %ds left\n1. %s: (%i%%%s)\n2. %s: (%i%%%s)\n3. %s: (%i%%%s)", RoundToFloor((voted_so_far/total_votes) * 100), - "%", g_iInterval, most_voted_map[0], RoundToFloor((most_voted[0]/total_votes) * 100), "%", most_voted_map[1], RoundToFloor((most_voted[1]/total_votes) * 100), - "%", most_voted_map[2], RoundToFloor((most_voted[2]/total_votes) * 100), "%"); - } - else if (strlen(most_voted_map[1]) > 0) - { - //displaying 2 most voted maps - PrintHintTextToAll("Votes: %i/100%%%s, %ds left\n1. %s: (%i%%%s)\n2. %s: (%i%%%s)", RoundToFloor((voted_so_far/total_votes) * 100), "%", g_iInterval, - most_voted_map[0], RoundToFloor((most_voted[0]/total_votes) * 100), "%", most_voted_map[1], RoundToFloor((most_voted[1]/total_votes) * 100), "%"); - } - else if (strlen(most_voted_map[0]) > 0) - { - //displaying the most voted map - PrintHintTextToAll("Votes: %i/100%%%s, %ds left\n1. %s: (%i%%%s)", RoundToFloor((voted_so_far/total_votes) * 100), - "%", g_iInterval, most_voted_map[0], RoundToFloor((most_voted[0]/total_votes) * 100), "%"); - } - else - { - //displaying just the votecount and vote duration remaining - PrintHintTextToAll("Votes: %i/100%%%s, %ds left", RoundToFloor((voted_so_far/total_votes) * 100), "%", g_iInterval); - } - g_iInterval--; - return Plugin_Continue; -} - -public void Handler_VoteFinishedGeneric(char[] map, - float num_votes, - float map_votes) -{ - Call_StartForward(g_MapVoteEndForward); - Call_PushString(map); - Call_Finish(); - - if(strcmp(map, VOTE_EXTEND, false) == 0) - { - g_Extends++; - int time; - if(GetMapTimeLimit(time)) - { - if(time > 0) - ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60); - } - - int winlimit = GetConVarInt(g_Cvar_Winlimit); - if(winlimit) - SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep)); - - int maxrounds = GetConVarInt(g_Cvar_Maxrounds); - if(maxrounds) - SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep)); - - int fraglimit = GetConVarInt(g_Cvar_Fraglimit); - if(fraglimit) - SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); - - PrintToChatAll("The current map has been extended. (Received %i%s of votes)", RoundToFloor((map_votes /num_votes)*100.0), "%"); - LogAction(-1, -1, "Voting for next map has finished. The current map has been extended."); - CPrintToChatAll("[MCE] Available Extends: %d", GetConVarInt(g_Cvar_Extend) - g_Extends); - - // We extended, so well have to vote again. - g_RunoffCount = 0; - g_HasVoteStarted = false; - SetupTimeleftTimer(); - } - else if(strcmp(map, VOTE_DONTCHANGE, false) == 0) - { - PrintToChatAll("Current map continues! The Vote has spoken! (Received %i%s of votes)", RoundToFloor((map_votes /num_votes)*100.0), "%"); - LogAction(-1, -1, "Voting for next map has finished. 'No Change' was the winner"); - - g_RunoffCount = 0; - g_HasVoteStarted = false; - SetupTimeleftTimer(); - } - else - { - if(g_ChangeTime == MapChange_MapEnd) - { - SetNextMap(map); - } - else if(g_ChangeTime == MapChange_Instant) - { - Handle data; - CreateDataTimer(4.0, Timer_ChangeMap, data); - WritePackString(data, map); - g_ChangeMapInProgress = false; - } - else // MapChange_RoundEnd - { - SetNextMap(map); - g_ChangeMapAtRoundEnd = true; - } - - g_HasVoteStarted = false; - g_MapVoteCompleted = true; - //checking on MapStart and MapEnd is not good enough. Players are not considered alive and on teams at those points in time. - //therefore instead applying the bool here after the mapvote completed. - if(InternalAreRestrictionsActive(false)) - g_SaveCDOnMapEnd = true; - else - g_SaveCDOnMapEnd = false; - - //PrintToChatAll("map: %s", map); - CPrintToChatAll("[MCE] %t", "Nextmap Voting Finished", map, RoundToFloor((map_votes /num_votes)*100.0)); - LogAction(-1, -1, "Voting for next map has finished. Nextmap: %s.", map); - } -} - -public void Handler_MapVoteFinished(Handle menu, - int num_votes, - int num_clients, - const int[][] client_info, - int num_items, - const int[][] item_info) -{ - g_iInterval = 1; //we display it shortly after finishing - ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. - //reweighting votes - StringMap sm = new StringMap(); - for (int i = 0; i < num_clients; i++) - { - int client = client_info[i][0]; - if (IsValidClient(client) && !StrEqual(player_mapvote[client], "")) - { - //default intention is 1-5 votes, just like rtv. - int item_index = client_info[i][VOTEINFO_CLIENT_ITEM]; - static char map[PLATFORM_MAX_PATH]; - for(int j = 0; j < num_items; j++) - { - if (item_info[j][VOTEINFO_ITEM_INDEX] == item_index) - { - GetMapItem(menu, item_info[j][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); - break; - } - } - float value = 0.0; - sm.GetValue(map, value); - - float nominate_worth = GetPlayerWorthRTV_boost_(client); - if (nominate_worth < 1.0) - { - nominate_worth = 1.0; - } - value += nominate_worth; - sm.SetValue(map, value, true); - } - } - - //ordering stringmap by voteweight - float[] weighted_votes = new float[num_items]; - char[][] weighted_maps = new char[num_items][PLATFORM_MAX_PATH]; - for (int i = 0; i < num_items; i++) - { - StringMapSnapshot keys = sm.Snapshot(); - float max_count = 0.0; - char picked_map[PLATFORM_MAX_PATH]; - for (int j = 0; j < keys.Length; j++) - { - int size = keys.KeyBufferSize(j); - char[] buffer = new char[size]; - keys.GetKey(j, buffer, size); - float value = 0.0; - sm.GetValue(buffer, value); - - //first selection has most votes, second selection second most etc etc - if (value >= max_count) - { - max_count = value; - strcopy(picked_map, sizeof(picked_map), buffer); - } - } - sm.Remove(picked_map); - weighted_votes[i] = max_count; - Format(weighted_maps[i], 128, picked_map); - delete keys; - } - delete sm; - - float total_votes = 0.0; - for (int i = 0; i < MaxClients; i++) - { - if (IsValidClient(i) && !is_bot_player[i] && PM_IsPlayerSteam(i)) - { - total_votes += player_mapvote_worth[i]; - } - } - // Implement revote logic - Only run this` block if revotes are enabled and this isn't the last revote' - //LogMessage("Mapchooser_extended_avg Handler_MapVoteFinished."); - int required_percent = GetConVarInt(g_Cvar_RunOffPercent); - int most_voted_map_percentage = RoundToFloor((weighted_votes[0] / total_votes) * 100); - if(GetConVarBool(g_Cvar_RunOff) && g_RunoffCount < GetConVarInt(g_Cvar_MaxRunOffs) && num_items > 1 && - (weighted_votes[0] == weighted_votes[1] || most_voted_map_percentage < required_percent)) - { - //LogMessage("Mapchooser_extended_avg Handler_MapVoteFinished passed check1."); - g_RunoffCount++; - if(weighted_votes[0] == weighted_votes[1]) - { - g_HasVoteStarted = false; - - //Revote is needed - int arraySize = ByteCountToCells(PLATFORM_MAX_PATH); - Handle mapList = CreateArray(arraySize); - - //adding all maps with same amount of votes - for(int i = 0; i < num_items; i++) - { - if(weighted_votes[i] == weighted_votes[0]) - { - PushArrayString(mapList, weighted_maps[i]); - } - else - break; - } - - CPrintToChatAll("[MCE] %t", "Tie Vote", GetArraySize(mapList)); - //LogMessage("Mapchooser_extended_avg reached WarningType_Revote 1"); - SetupWarningTimer(WarningType_Revote, view_as(g_ChangeTime), mapList); - return; - } - else if(most_voted_map_percentage < required_percent) - { - g_HasVoteStarted = false; - - //Revote is needed - int arraySize = ByteCountToCells(PLATFORM_MAX_PATH); - Handle mapList = CreateArray(arraySize); - - PushArrayString(mapList, weighted_maps[0]); - // We allow more than two maps for a revote if they are tied - for(int i = 1; i < num_items; i++) - { - if(GetArraySize(mapList) < 2 || weighted_votes[i] == weighted_votes[i - 1]) - { - PushArrayString(mapList, weighted_maps[i]); - } - else - break; - } - - CPrintToChatAll("[MCE] %t", "Revote Is Needed", required_percent); - //LogMessage("Mapchooser_extended_avg reached WarningType_Revote 2"); - SetupWarningTimer(WarningType_Revote, view_as(g_ChangeTime), mapList); - return; - } - } - - g_WaitingForVote = false; - //LogMessage("Mapchooser_extended_avg no revote needed, continue as normal."); - // No revote needed, continue as normal. - Handler_VoteFinishedGeneric(weighted_maps[0], total_votes, weighted_votes[0]); -} - -public int Handler_MapVoteMenu(Handle menu, MenuAction action, int param1, int param2) -{ - switch(action) - { - case MenuAction_End: - { - g_VoteMenu = INVALID_HANDLE; - delete menu; - } - case MenuAction_Select: - { - char map[PLATFORM_MAX_PATH]; - GetMenuItem(menu, param2, map, PLATFORM_MAX_PATH, _, _, _, param1); - if (StrEqual(map, "##dontchange##")) - { - Format(map, sizeof(map), "Dont change"); - } - else if (StrEqual(map, "##extend##")) - { - Format(map, sizeof(map), "Extend"); - } - Format(player_mapvote[param1], 128, map); - } - case MenuAction_Display: - { - Format(player_mapvote[param1], 128, ""); - static char buffer[255]; - - //displaying to the client how much percent his vote is worth. - float total_votes = 0.0; - for (int i = 0; i < MaxClients; i++) - { - if (IsValidClient(i) && !is_bot_player[i] && PM_IsPlayerSteam(i)) - { - total_votes += player_mapvote_worth[i]; - } - } - //second parameter shows for example 5.0, last parameter is how much percentage of the entire vote the client decides. - Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1, player_mapvote_worth[param1], RoundToFloor((player_mapvote_worth[param1]/total_votes) * 100)); - Handle panel = view_as(param2); - SetPanelTitle(panel, buffer); - //char PannelText[256] = "Warning: The Position of the Maps are different for each Player."; - //DrawPanelText(panel, PannelText); - } - - case MenuAction_DisplayItem: - { - char map[PLATFORM_MAX_PATH]; - char buffer[255]; - int mark = GetConVarInt(g_Cvar_MarkCustomMaps); - - GetMenuItem(menu, param2, map, PLATFORM_MAX_PATH, _, _, _, param1); - if(StrEqual(map, VOTE_EXTEND, false)) - { - Format(buffer, sizeof(buffer), "%T", "Extend Map", param1); - } - else if(StrEqual(map, VOTE_DONTCHANGE, false)) - { - Format(buffer, sizeof(buffer), "%T", "Dont Change", param1); - } - // Mapchooser Extended - else if(StrEqual(map, LINE_ONE, false)) - { - Format(buffer, sizeof(buffer),"%T", "Line One", param1); - } - else if(StrEqual(map, LINE_TWO, false)) - { - Format(buffer, sizeof(buffer),"%T", "Line Two", param1); - } - // Note that the first part is to discard the spacer line - else if(!StrEqual(map, LINE_SPACER, false)) - { - if(mark == 1 && !InternalIsMapOfficial(map)) - { - Format(buffer, sizeof(buffer), "%T", "Custom Marked", param1, map); - } - else if(mark == 2 && !InternalIsMapOfficial(map)) - { - Format(buffer, sizeof(buffer), "%T", "Custom", param1, map); - } - else if(InternalGetMapVIPRestriction(map)) - { - Format(buffer, sizeof(buffer), "%s (%T)", map, "VIP Nomination", param1); - } - } - - if(buffer[0] != '\0') - { - return RedrawMenuItem(buffer); - } - // End Mapchooser Extended - } - - case MenuAction_VoteCancel: - { - // If we receive 0 votes, pick at random. - if(param1 == VoteCancel_NoVotes && GetConVarBool(g_Cvar_NoVoteMode)) - { - int count = GetMenuItemCount(menu); - - int item; - static char map[PLATFORM_MAX_PATH]; - - do - { - int startInt = 0; - if(g_BlockedSlots) - { - if(g_AddNoVote) - { - startInt = 2; - } - else - { - startInt = 3; - } - } - item = GetRandomInt(startInt, count - 1); - - GetMenuItem(menu, item, map, PLATFORM_MAX_PATH, _, _, _, param1); - } - while(strcmp(map, VOTE_EXTEND, false) == 0); - - SetNextMap(map); - g_MapVoteCompleted = true; - } - g_WaitingForVote = false; - g_HasVoteStarted = false; - g_RunoffCount = 0; - g_iInterval = 1; //we display it shortly after finishing - ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. - } - } - return 0; -} - -public Action Timer_ChangeMap(Handle hTimer, Handle dp) -{ - g_ChangeMapInProgress = false; - - char map[PLATFORM_MAX_PATH]; - - if(dp == INVALID_HANDLE) - { - if(!GetNextMap(map, PLATFORM_MAX_PATH)) - { - //No passed map and no set nextmap. fail! - return Plugin_Stop; - } - } - else - { - ResetPack(dp); - ReadPackString(dp, map, PLATFORM_MAX_PATH); - } - - ForceChangeLevel(map, "Map Vote"); - - return Plugin_Stop; -} - -bool RemoveStringFromArray(Handle array, char[] str) -{ - int index = FindStringInArray(array, str); - if(index != -1) - { - RemoveFromArray(array, index); - return true; - } - - return false; -} - -void CreateNextVote() -{ - assert(g_NextMapList) - ClearArray(g_NextMapList); - - static char map[PLATFORM_MAX_PATH]; - Handle tempMaps = CloneArray(g_MapList); - - GetCurrentMap(map, PLATFORM_MAX_PATH); - RemoveStringFromArray(tempMaps, map); - - if(GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps) && InternalAreRestrictionsActive(false)) - { - StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot(); - for(int i = 0; i < OldMapListSnapshot.Length; i++) - { - OldMapListSnapshot.GetKey(i, map, sizeof(map)); - RemoveStringFromArray(tempMaps, map); - } - delete OldMapListSnapshot; - } - - if(InternalAreRestrictionsActive(false)) - { - StringMapSnapshot TimeMapListSnapshot = g_TimeMapList.Snapshot(); - for(int i = 0; i < TimeMapListSnapshot.Length; i++) - { - TimeMapListSnapshot.GetKey(i, map, sizeof(map)); - int Cooldown; - g_TimeMapList.GetValue(map, Cooldown); - - if(Cooldown > GetTime()) - RemoveStringFromArray(tempMaps, map); - } - delete TimeMapListSnapshot; - } - - int voteSize = GetVoteSize(0); - int limit = (voteSize < GetArraySize(tempMaps) ? voteSize : GetArraySize(tempMaps)); - - // group -> number of maps nominated from group - StringMap groupmap = new StringMap(); - char groupstr[8]; - - // populate groupmap with maps from nomination list - static char map_[PLATFORM_MAX_PATH]; - int groups_[32]; - - //2023 edit - Handle most_nominated_maps = get_most_nominated_maps(true); - for(int i = 0; i < GetArraySize(most_nominated_maps); i++) - { - GetArrayString(most_nominated_maps, i, map_, PLATFORM_MAX_PATH); - int groupsfound = InternalGetMapGroups(map_, groups_, sizeof(groups_)); - for(int group = 0; group < groupsfound; group++) - { - IntToString(group, groupstr, sizeof(groupstr)); - int groupcur = 0; - groupmap.GetValue(groupstr, groupcur); - groupcur++; - groupmap.SetValue(groupstr, groupcur, true); - } - } - - // find random maps which honor all restrictions - for(int i = 0; i < limit; i++) - { - int b; - for(int j = 0; j < 1000; j++) - { - b = GetRandomInt(0, GetArraySize(tempMaps) - 1); - GetArrayString(tempMaps, b, map, PLATFORM_MAX_PATH); - - if(!InternalAreRestrictionsActive(false)) - break; - - if(InternalGetMapVIPRestriction(map)) - continue; - - if(InternalGetMapCooldownTime(map) > GetTime()) - continue; - - if(InternalGetMapTimeRestriction(map) != 0) - continue; - - if(InternalGetMapPlayerRestriction(map) != 0) - continue; - - if (InternalGetAveragePlayerHourRestriction(map) != 0) - continue; - - bool okay = true; - - int groups[32]; - int groupsfound = InternalGetMapGroups(map, groups, sizeof(groups)); - for(int group = 0; group < groupsfound; group++) - { - IntToString(group, groupstr, sizeof(groupstr)); - - int groupmax = InternalGetGroupMax(groups[group]); - if(groupmax >= 0) - { - int groupcur = 0; - groupmap.GetValue(groupstr, groupcur); - - if(groupcur >= groupmax) - { - okay = false; - break; - } - - groupcur++; - groupmap.SetValue(groupstr, groupcur, true); - } - } - - if(okay) - break; - } - PushArrayString(g_NextMapList, map); - RemoveFromArray(tempMaps, b); - } - - delete groupmap; - delete tempMaps; -} - -bool CanVoteStart() -{ - if(g_WaitingForVote || g_HasVoteStarted) - return false; - return true; -} - -NominateResult InternalNominateMap(char[] map, int owner) -{ - if(!IsMapValid(map)) - { - return Nominate_InvalidMap; - } - - - /* Look to replace an existing nomination by this client - Nominations made with owner = 0 arent replaced */ - //2023 edit: change clients first nomination out of the clients multiple nominations, make a check if client filled all his nomination slots - //currently hard coded to 3 maps, just add a cvar to replace it with in the future - if(owner && ((FindValueInArray(g_NominateOwners, owner)) != -1) && GetArraySize(g_NominateList[owner]) > 2) - { - char oldmap[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[owner], 0, oldmap, PLATFORM_MAX_PATH); - Call_StartForward(g_NominationsResetForward); - Call_PushString(oldmap); - Call_PushCell(owner); - Call_Finish(); - - RemoveFromArray(g_NominateList[owner], 0); - PushArrayString(g_NominateList[owner], map); - return Nominate_Replaced; - } - - - /* Too many nominated maps. */ - //2023 edit: we dont want this check - /* - if(g_NominateCount >= GetVoteSize(0) && !force) - { - return Nominate_VoteFull; - } - */ - - if (owner != 0 && g_NominateList[owner] != INVALID_HANDLE) - { - for (int j = 0; j < GetArraySize(g_NominateList[owner]); j++) - { - char map_iteration[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[owner], j, map_iteration, PLATFORM_MAX_PATH); - if (StrEqual(map, map_iteration, false)) - { - return Nominate_InvalidMap; - } - } - } - - if (g_NominateList[owner] == INVALID_HANDLE) - { - if (IsClientConnected(owner) && IsClientInGame(owner)) - { - ReplyToCommand(owner, "This should be invalid."); - } - return Nominate_InvalidMap; - } - - PushArrayString(g_NominateList[owner], map); - PushArrayCell(g_NominateOwners, owner); //maybe i only want to do this for the first nomination of each client - if(owner == 0 && g_NominateReservedCount < GetVoteSize(0)) - g_NominateReservedCount++; - else - g_NominateCount++; - - while(GetArraySize(g_NominateList[owner]) > GetVoteSize(0)) - { - char oldmap[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[owner], 0, oldmap, PLATFORM_MAX_PATH); - Call_StartForward(g_NominationsResetForward); - Call_PushString(oldmap); - Call_PushCell(owner); - int owner_ = GetArrayCell(g_NominateOwners, 0); - Call_Finish(); - - RemoveFromArray(g_NominateList[owner], 0); - RemoveFromArray(g_NominateOwners, 0); - if(owner_ == 0) - g_NominateReservedCount--; - else - g_NominateCount--; - } - - return Nominate_Added; -} - -/* Add natives to allow nominate and initiate vote to be call */ - -/* native bool NominateMap(const char[] map, bool force, &NominateError:error); */ -public int Native_NominateMap(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return view_as(InternalNominateMap(map, GetNativeCell(3))); -} - -bool InternalRemoveNominationByMap(char[] map) -{ - for (int client = 0; client < MaxClients; client++) - { - for(int i = 0; i < GetArraySize(g_NominateList[client]); i++) - { - char oldmap[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[client], i, oldmap, PLATFORM_MAX_PATH); - - if(strcmp(map, oldmap, false) == 0) - { - Call_StartForward(g_NominationsResetForward); - Call_PushString(oldmap); - Call_PushCell(client); - Call_Finish(); - - int owner = GetArrayCell(g_NominateOwners, i); - if(owner) - g_NominateCount--; - else - g_NominateReservedCount--; - - RemoveFromArray(g_NominateList[client], i); - RemoveFromArray(g_NominateOwners, i); - - return true; - } - } - } - return false; -} - -/* native bool RemoveNominationByMap(const char[] map); */ -public int Native_RemoveNominationByMap(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return view_as(InternalRemoveNominationByMap(map)); -} - -bool InternalRemoveNominationByOwner(int owner) -{ - int index; - - if(owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1)) - { - char oldmap[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[owner], index, oldmap, PLATFORM_MAX_PATH); - - Call_StartForward(g_NominationsResetForward); - Call_PushString(oldmap); - Call_PushCell(owner); - Call_Finish(); - - RemoveFromArray(g_NominateList[owner], index); - //maybe only do once or change g_NominateOwners - RemoveFromArray(g_NominateOwners, index); - g_NominateCount--; - - return true; - } - - return false; -} - -/* native bool RemoveNominationByOwner(owner); */ -public int Native_RemoveNominationByOwner(Handle plugin, int numParams) -{ - return view_as(InternalRemoveNominationByOwner(GetNativeCell(1))); -} - -/* native InitiateMapChooserVote(); */ -public int Native_InitiateVote(Handle plugin, int numParams) -{ - MapChange when = view_as(GetNativeCell(1)); - Handle inputarray = view_as(GetNativeCell(2)); - - LogAction(-1, -1, "Starting map vote because outside request"); - - SetupWarningTimer(WarningType_Vote, when, inputarray); - //LogMessage("Mapchooser_extended_avg SetupWarningTimer call 1"); - return 0; -} - -public int Native_CanVoteStart(Handle plugin, int numParams) -{ - return CanVoteStart(); -} - -public int Native_CheckVoteDone(Handle plugin, int numParams) -{ - return g_MapVoteCompleted; -} - -public int Native_EndOfMapVoteEnabled(Handle plugin, int numParams) -{ - return GetConVarBool(g_Cvar_EndOfMapVote); -} - -public int Native_GetExcludeMapList(Handle plugin, int numParams) -{ - Handle array = view_as(GetNativeCell(1)); - if(array == INVALID_HANDLE) - return 0; - - static char map[PLATFORM_MAX_PATH]; - StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot(); - for(int i = 0; i < OldMapListSnapshot.Length; i++) - { - OldMapListSnapshot.GetKey(i, map, sizeof(map)); - PushArrayString(array, map); - } - delete OldMapListSnapshot; - return 0; -} - -//GetNominatedMapList -public int Native_GetNominatedMapList(Handle plugin, int numParams) -{ - Handle maparray = view_as(GetNativeCell(1)); - Handle ownerarray = view_as(GetNativeCell(2)); - - if(maparray == INVALID_HANDLE) - return 0; - - static char map[PLATFORM_MAX_PATH]; - for (int client = 0; client < MaxClients; client++) - { - for(int i = 0; i < GetArraySize(g_NominateList[client]); i++) - { - GetArrayString(g_NominateList[client], i, map, PLATFORM_MAX_PATH); - PushArrayString(maparray, map); - - // If the optional parameter for an owner list was passed, then we need to fill that out as well - if(ownerarray != INVALID_HANDLE) - { - //int index = GetArrayCell(g_NominateOwners, i); - PushArrayCell(ownerarray, client); - } - } - } - return 0; -} - -// Functions new to Mapchooser Extended -stock void SetupWarningTimer(WarningType type, MapChange when=MapChange_MapEnd, Handle mapList=INVALID_HANDLE, bool force=false) -{ - if(!GetArraySize(g_MapList) || g_ChangeMapInProgress || g_HasVoteStarted || (!force && ((when == MapChange_MapEnd && !GetConVarBool(g_Cvar_EndOfMapVote)) || g_MapVoteCompleted))) - return; - - bool interrupted = false; - if(g_WarningInProgress && g_WarningTimer != INVALID_HANDLE) - { - interrupted = true; - KillTimer(g_WarningTimer); - } - - g_WarningInProgress = true; - - Handle forwardVote; - Handle cvarTime; - static char translationKey[64]; - - switch(type) - { - case WarningType_Vote: - { - forwardVote = g_MapVoteWarningStartForward; - cvarTime = g_Cvar_WarningTime; - strcopy(translationKey, sizeof(translationKey), "Vote Warning"); - //LogMessage("Mapchooser_extended_avg WarningType_Vote"); - } - - case WarningType_Revote: - { - forwardVote = g_MapVoteRunoffStartForward; - cvarTime = g_Cvar_RunOffWarningTime; - strcopy(translationKey, sizeof(translationKey), "Revote Warning"); - //LogMessage("Mapchooser_extended_avg WarningType_Revote. cvarTime: %i", GetConVarInt(cvarTime)); - } - } - - if(!interrupted) - { - Call_StartForward(forwardVote); - Call_Finish(); - } - - Handle data; - g_WarningTimer = CreateDataTimer(1.0, Timer_StartMapVote, data, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT); - WritePackCell(data, GetConVarInt(cvarTime)); - WritePackString(data, translationKey); - WritePackCell(data, view_as(when)); - WritePackCell(data, view_as(mapList)); - ResetPack(data); -} - -stock void InitializeOfficialMapList() -{ - // If this fails, we want it to have an empty adt_array - if(ReadMapList(g_OfficialList, - g_mapOfficialFileSerial, - "official", - MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_NO_DEFAULT) - != INVALID_HANDLE) - { - LogMessage("Loaded map list for %s.", g_GameModName); - } - // Check if the map list was ever loaded - else if(g_mapOfficialFileSerial == -1) - { - LogMessage("No official map list found for %s. Consider submitting one!", g_GameModName); - } -} - -stock bool IsMapEndVoteAllowed() -{ - if(!GetConVarBool(g_Cvar_EndOfMapVote) || g_MapVoteCompleted || g_HasVoteStarted) - return false; - return true; -} - -public int Native_IsMapOfficial(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalIsMapOfficial(map); -} - -bool InternalIsMapOfficial(const char[] mapname) -{ - int officialMapIndex = FindStringInArray(g_OfficialList, mapname); - return (officialMapIndex > -1); -} - -public int Native_IsWarningTimer(Handle plugin, int numParams) -{ - return g_WarningInProgress; -} - -public int Native_CanNominate(Handle plugin, int numParams) -{ - if(g_HasVoteStarted) - { - return view_as(CanNominate_No_VoteInProgress); - } - - if(g_MapVoteCompleted) - { - return view_as(CanNominate_No_VoteComplete); - } - - if(g_NominateCount >= GetVoteSize()) - { - return view_as(CanNominate_No_VoteFull); - } - - return view_as(CanNominate_Yes); -} - -public int Native_ExcludeMap(Handle plugin, int numParams) -{ - if(!InternalAreRestrictionsActive(false)) - return true; - - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - int Cooldown; - int Mode = GetNativeCell(3); - - if(Mode == 0) - { - Cooldown = InternalGetMapCooldown(map); - } - else if(Mode == 1) - { - Cooldown = GetNativeCell(2); - } - else if(Mode == 2) - { - g_OldMapList.GetValue(map, Cooldown); - int NewCooldown = GetNativeCell(2); - if(NewCooldown > Cooldown) - Cooldown = NewCooldown; - } - - g_OldMapList.SetValue(map, Cooldown, true); - InternalStoreMapCooldowns(); - - return true; -} - -public int Native_ExcludeMapTime(Handle plugin, int numParams) -{ - if(!InternalAreRestrictionsActive(false)) - return true; - - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - int Cooldown; - int Mode = GetNativeCell(3); - - if(Mode == 0) - { - Cooldown = InternalGetMapCooldownTime(map); - } - else if(Mode == 1) - { - Cooldown = GetNativeCell(2); - } - else if(Mode == 2) - { - g_TimeMapList.GetValue(map, Cooldown); - int NewCooldown = GetTime() + GetNativeCell(2); - if(NewCooldown > Cooldown) - Cooldown = GetNativeCell(2); - else - return true; - } - - Cooldown += GetTime(); - g_TimeMapList.SetValue(map, Cooldown, true); - InternalStoreMapCooldowns(); - - return true; -} - -public int Native_GetMapCooldown(Handle plugin, int numParams) -{ - if(!InternalAreRestrictionsActive(false)) - return 0; - - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - int Cooldown = 0; - g_OldMapList.GetValue(map, Cooldown); - - return Cooldown; -} - -public int Native_GetMapCooldownTime(Handle plugin, int numParams) -{ - if(!InternalAreRestrictionsActive(false)) - return 0; - - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - int Cooldown = 0; - g_TimeMapList.GetValue(map, Cooldown); - - return Cooldown; -} - -public int Native_GetMapMinTime(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalGetMapMinTime(map); -} - -public int Native_GetMapMaxTime(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalGetMapMaxTime(map); -} - -public int Native_GetMapMinPlayers(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalGetMapMinPlayers(map); -} - -public int Native_GetMapMaxPlayers(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalGetMapMaxPlayers(map); -} - -public int Native_GetMapTimeRestriction(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalGetMapTimeRestriction(map); -} - -//GetAveragePlayerTimeOnServerMapRestriction -public int Native_GetAveragePlayerTimeOnServerMapRestriction(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - return InternalGetAveragePlayerHourRestriction(map); -} - -stock int InternalGetAveragePlayerHourRestriction(const char[] map) -{ - int players_average_hours = GetAveragePlayerTimeOnServer(); - int MinAverageHours = 0; - if(g_Config && g_Config.JumpToKey(map)) - { - MinAverageHours = g_Config.GetNum("MinHoursAvg", MinAverageHours); - g_Config.Rewind(); - } - //0 means map can be nominated, anything above 0 means more hours are required - if (players_average_hours >= MinAverageHours) - { - return 0; - } - return MinAverageHours - players_average_hours; -} -//GetMapPlayerRestriction -public int Native_GetMapPlayerRestriction(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - return InternalGetMapPlayerRestriction(map); -} - -public int Native_GetMapGroups(Handle plugin, int numParams) -{ - int len; - GetNativeStringLength(1, len); - int size = GetNativeCell(3); - - if(len <= 0) - return -999; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - int[] groups = new int[size]; - int found = InternalGetMapGroups(map, groups, size); - if(found >= 0) - SetNativeArray(2, groups, size); - return found; -} - -//GetMapGroupRestriction -public int Native_GetMapGroupRestriction(Handle plugin, int numParams) -{ - GetNativeCell(2); - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return -999; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - int groups[32]; - int groupsfound = InternalGetMapGroups(map, groups, sizeof(groups)); - - for(int group = 0; group < groupsfound; group ++) - { - int groupcur = 0; - int groupmax = InternalGetGroupMax(groups[group]); - - if(groupmax >= 0) - { - static char map_[PLATFORM_MAX_PATH]; - char kv_map[PLATFORM_MAX_PATH]; - int groups_[32]; - KeyValues kv = CreateKeyValues("cur_groups"); - for (int clienti = 0; clienti < MaxClients; clienti++) - { - for(int i = 0; i < GetArraySize(g_NominateList[clienti]); i++) - { - GetArrayString(g_NominateList[clienti], i, map_, PLATFORM_MAX_PATH); - int tmp = InternalGetMapGroups(map_, groups_, sizeof(groups_)); - kv.GetString(map_, kv_map, sizeof(kv_map), "not_found"); - if(FindIntInArray(groups_, tmp, groups[group]) != -1 && StrEqual(kv_map, "not_found")) - { - groupcur++; - kv.SetString(map_, map_); - } - } - } - delete kv; - } - } - - return -1; -} - -public int Native_GetMapVIPRestriction(Handle plugin, int numParams) -{ - int client = GetNativeCell(2); - int len; - GetNativeStringLength(1, len); - - if(len <= 0) - return false; - - char[] map = new char[len+1]; - GetNativeString(1, map, len+1); - - // Check if client should bypass vip restrictions - if(client >= 1 && client <= MaxClients) - { - // Client has bypass flag, dont return vip restrictions - if(CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_CHEATS)) - return false; - - // Client has vip flag, dont return vip restrictions - if(CheckCommandAccess(client, "sm_nominate_vip", ADMFLAG_CUSTOM1)) - return false; - } - - return InternalGetMapVIPRestriction(map); -} - -public int Native_GetExtendsLeft(Handle plugin, int numParams) -{ - return GetConVarInt(g_Cvar_Extend) - g_Extends; -} - -public int Native_AreRestrictionsActive(Handle plugin, int numParams) -{ - return InternalAreRestrictionsActive(false); -} - -public int Native_SimulateMapEnd(Handle plugin, int numParams) -{ - OnMapEnd(); - return 0; -} - -stock void AddMapItem(const char[] map) -{ - AddMenuItem(g_VoteMenu, map, map); -} - -stock void GetMapItem(Handle menu, int position, char[] map, int mapLen) -{ - GetMenuItem(menu, position, map, mapLen, _, _, _, -1); -} - -stock void AddExtendToMenu(Handle menu, MapChange when) -{ - /* Do we add any special items? */ - // Moved for Mapchooser Extended - - if((when == MapChange_Instant || when == MapChange_RoundEnd) && GetConVarBool(g_Cvar_DontChange)) - { - // Built-in votes doesnt have "Dont Change", send Extend instead - AddMenuItem(menu, VOTE_DONTCHANGE, "Dont Change"); - } - else if(GetConVarBool(g_Cvar_Extend) && g_Extends < GetConVarInt(g_Cvar_Extend)) - { - AddMenuItem(menu, VOTE_EXTEND, "Extend Map"); - } -} - -// 0 = IncludeMaps, 1 = Reserved, 2 = IncludeMaps+Reserved -stock int GetVoteSize(int what=0) -{ - int includeMaps = GetConVarInt(g_Cvar_IncludeMaps); - int includeMapsReserved = GetConVarInt(g_Cvar_IncludeMapsReserved); - - if(what == 0) - return includeMaps; - else if(what == 1) - return includeMapsReserved; - else if(what == 2) - return includeMaps + includeMapsReserved; - - return 0; -} - -stock int InternalGetMapCooldown(const char[] map) -{ - int Cooldown = g_Cvar_ExcludeMaps.IntValue; - - if(g_Config && g_Config.JumpToKey(map)) - { - Cooldown = g_Config.GetNum("Cooldown", Cooldown); - g_Config.Rewind(); - } - - return Cooldown; -} - -stock int InternalGetMapCooldownTime(const char[] map) -{ - char time[16]; - g_Cvar_ExcludeMapsTime.GetString(time, sizeof(time)); - int Cooldown = TimeStrToSeconds(time); - - if(g_Config && g_Config.JumpToKey(map)) - { - g_Config.GetString("CooldownTime", time, sizeof(time), ""); - if(time[0]) - Cooldown = TimeStrToSeconds(time); - - g_Config.Rewind(); - } - - return Cooldown; -} - -stock int InternalGetMapMinTime(const char[] map) -{ - int MinTime = 0; - - if(g_Config && g_Config.JumpToKey(map)) - { - MinTime = g_Config.GetNum("MinTime", MinTime); - g_Config.Rewind(); - } - - return MinTime; -} - -stock int InternalGetMapMaxTime(const char[] map) -{ - int MaxTime = 0; - - if(g_Config && g_Config.JumpToKey(map)) - { - MaxTime = g_Config.GetNum("MaxTime", MaxTime); - g_Config.Rewind(); - } - - return MaxTime; -} - -stock int InternalGetMapMinPlayers(const char[] map) -{ - int MinPlayers = 0; - - if(g_Config && g_Config.JumpToKey(map)) - { - MinPlayers = g_Config.GetNum("MinPlayers", MinPlayers); - g_Config.Rewind(); - } - - return MinPlayers; -} - -stock int InternalGetMapMaxPlayers(const char[] map) -{ - int MaxPlayers = 0; - - if(g_Config && g_Config.JumpToKey(map)) - { - MaxPlayers = g_Config.GetNum("MaxPlayers", MaxPlayers); - g_Config.Rewind(); - } - - return MaxPlayers; -} - -stock int InternalGetMapGroups(const char[] map, int[] groups, int size) -{ - int found = 0; - if(g_Config && g_Config.JumpToKey("_groups")) - { - if(!g_Config.GotoFirstSubKey(false)) - { - g_Config.Rewind(); - return -999; - } - - do - { - char groupstr[8]; - g_Config.GetSectionName(groupstr, sizeof(groupstr)); - int group = StringToInt(groupstr); - if(g_Config.JumpToKey(map, false)) - { - groups[found++] = group; - if(found >= size) - { - g_Config.Rewind(); - return found; - } - g_Config.GoBack(); - } - } while(g_Config.GotoNextKey()); - - g_Config.Rewind(); - } - - return found; -} - -stock int InternalGetGroupMax(int group) -{ - char groupstr[8]; - IntToString(group, groupstr, sizeof(groupstr)); - if(g_Config && g_Config.JumpToKey("_groups")) - { - if(g_Config.JumpToKey(groupstr, false)) - { - int max = g_Config.GetNum("_max", -1); - g_Config.Rewind(); - return max; - } - - g_Config.Rewind(); - } - - return -1; -} - -// 0 = Okay -// >0 = Minutes till Okay -stock int InternalGetMapTimeRestriction(const char[] map) -{ - char sTime[8]; - FormatTime(sTime, sizeof(sTime), "%H%M"); - - int CurTime = StringToInt(sTime); - int MinTime = InternalGetMapMinTime(map); - int MaxTime = InternalGetMapMaxTime(map); - - //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 = (RoundToFloor(float(CurTime / 100)) * 60) + (CurTime % 100); - MinTime = (RoundToFloor(float(MinTime / 100)) * 60) + (MinTime % 100); - MaxTime = (RoundToFloor(float(MaxTime / 100)) * 60) + (MaxTime % 100); - - return MinTime - CurTime; - } - - return 0; -} - -public void OnClientPostAdminCheck(int client) -{ - is_bot_player[client] = false; - player_mapvote_worth[client] = 0.0; - Format(player_mapvote[client], 128, ""); - char auth[50]; - GetClientAuthId(client, AuthId_Engine, auth, sizeof(auth)); - if (StrEqual("[U:1:1221121532]", auth, false) || StrEqual("STEAM_0:0:610560766", auth, false)) - { - is_bot_player[client] = true; - } - if (StrEqual("[U:1:408797742]", auth, false) || StrEqual("STEAM_0:0:204398871", auth, false)) - { - is_bot_player[client] = true; - } - if (StrEqual("[U:1:1036189204]", auth, false) || StrEqual("STEAM_0:0:518094602", auth, false)) - { - is_bot_player[client] = true; - } - if (StrEqual("[U:1:120378081]", auth, false) || StrEqual("STEAM_0:1:60189040", auth, false)) - { - is_bot_player[client] = true; - } -} - -// <0 = Less than MinPlayers -// 0 = Okay -// >0 = More than MaxPlayers -stock int InternalGetMapPlayerRestriction(const char[] map) -{ - //int NumPlayers = GetClientCount(false); - int NumPlayers = 0; - //excluding non connected players, fakeclients, sourceTV, autism bots and nosteamers from player count restriction - for (int client = 1; client <= MaxClients; client++) - { - if (IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client) && !IsClientSourceTV(client) && !is_bot_player[client] - && PM_IsPlayerSteam(client)) - { - NumPlayers++; - } - } - - int MinPlayers = InternalGetMapMinPlayers(map); - int MaxPlayers = InternalGetMapMaxPlayers(map); - - if(MinPlayers && NumPlayers < MinPlayers) - return NumPlayers - MinPlayers; - - if(MaxPlayers && NumPlayers > MaxPlayers) - return NumPlayers - MaxPlayers; - - return 0; -} - -/* -false means we never put the map on cooldown if time range is inside the no map restriction time or -if less than the minimum active players for enabling map restrictions are on the server. - -true means we put maps on Cooldown even if there was no map restrictions because of less than 15 active players (the number is a cvar, its not static) -true still respects the time range with no map restrictions (23:30 to 10:30 right now) and wont apply cooldown there. -*/ -stock bool InternalAreRestrictionsActive(bool skip_player_check) -{ - if (!GetConVarBool(g_Cvar_NoRestrictionTimeframeEnable)) - return true; - - char sTime[8]; - FormatTime(sTime, sizeof(sTime), "%H%M"); - - int CurTime = StringToInt(sTime); - int MinTime = GetConVarInt(g_Cvar_NoRestrictionTimeframeMinTime); - int MaxTime = GetConVarInt(g_Cvar_NoRestrictionTimeframeMaxTime); - - //Wrap around. - CurTime = (CurTime <= MinTime) ? CurTime + 2400 : CurTime; - MaxTime = (MaxTime <= MinTime) ? MaxTime + 2400 : MaxTime; - - if ((MinTime <= CurTime <= MaxTime)) - { - return false; - } - - int ActivePlayerCount = 0; - for (int i = 0; i < MaxClients; i++) - { - if (IsValidClient(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !is_bot_player[i] && GetClientIdleTime(i) < g_iPlayerAFKTime - && (GetClientTeam(i) == CS_TEAM_T || GetClientTeam(i) == CS_TEAM_CT)) - { - ActivePlayerCount++; - } - } - - if (ActivePlayerCount <= g_iPlayerCount_excludeSpec && !skip_player_check) - { - return false; - } - - return true; -} - -stock int FindIntInArray(int[] array, int size, int value) -{ - for(int i = 0; i < size; i++) - { - if(array[i] == value) - return i; - } - - return -1; -} - -stock bool InternalGetMapVIPRestriction(const char[] map) -{ - int VIP = 0; - - if(g_Config && g_Config.JumpToKey(map)) - { - VIP = g_Config.GetNum("VIP", VIP); - g_Config.Rewind(); - } - - return view_as(VIP); -} - -stock void InternalRestoreMapCooldowns() -{ - char sCooldownFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sCooldownFile, sizeof(sCooldownFile), "configs/mapchooser_extended/cooldowns.cfg"); - - if(!FileExists(sCooldownFile)) - { - LogMessage("Could not find cooldown file: \"%s\"", sCooldownFile); - return; - } - - KeyValues Cooldowns = new KeyValues("mapchooser_extended"); - - if(!Cooldowns.ImportFromFile(sCooldownFile)) - { - LogMessage("Unable to load cooldown file: \"%s\"", sCooldownFile); - delete Cooldowns; - return; - } - - if(!Cooldowns.GotoFirstSubKey(true)) - { - LogMessage("Unable to goto first sub key: \"%s\"", sCooldownFile); - delete Cooldowns; - return; - } - - int Cooldown; - char map[PLATFORM_MAX_PATH]; - - do - { - if(!Cooldowns.GetSectionName(map, sizeof(map))) - { - LogMessage("Unable to get section name: \"%s\"", sCooldownFile); - delete Cooldowns; - return; - } - - if((Cooldown = Cooldowns.GetNum("Cooldown", -1)) > 0) - { - LogMessage("Restored cooldown: %s -> %d", map, Cooldown); - g_OldMapList.SetValue(map, Cooldown, true); - } - - if((Cooldown = Cooldowns.GetNum("CooldownTime", -1)) > 0) - { - LogMessage("Restored time cooldown: %s -> %d", map, Cooldown); - g_TimeMapList.SetValue(map, Cooldown, true); - } - } while(Cooldowns.GotoNextKey(true)); - - delete Cooldowns; -} - -stock void InternalStoreMapCooldowns() -{ - char sCooldownFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sCooldownFile, sizeof(sCooldownFile), "configs/mapchooser_extended/cooldowns.cfg"); - - if(!FileExists(sCooldownFile)) - { - LogMessage("Could not find cooldown file: \"%s\"", sCooldownFile); - return; - } - - KeyValues Cooldowns = new KeyValues("mapchooser_extended"); - - int Cooldown; - char map[PLATFORM_MAX_PATH]; - - StringMapSnapshot OldMapListSnapshot = g_OldMapList.Snapshot(); - for(int i = 0; i < OldMapListSnapshot.Length; i++) - { - OldMapListSnapshot.GetKey(i, map, sizeof(map)); - g_OldMapList.GetValue(map, Cooldown); - - if (!Cooldowns.JumpToKey(map, true)) - { - LogMessage("Unable to create/find key: %s", map); - delete OldMapListSnapshot; - delete Cooldowns; - return; - } - - Cooldowns.SetNum("Cooldown", Cooldown); - Cooldowns.Rewind(); - } - delete OldMapListSnapshot; - - StringMapSnapshot TimeMapListSnapshot = g_TimeMapList.Snapshot(); - for(int i = 0; i < TimeMapListSnapshot.Length; i++) - { - TimeMapListSnapshot.GetKey(i, map, sizeof(map)); - g_TimeMapList.GetValue(map, Cooldown); - - if (!Cooldowns.JumpToKey(map, true)) - { - LogMessage("Unable to create/find key: %s", map); - delete TimeMapListSnapshot; - delete Cooldowns; - return; - } - - Cooldowns.SetNum("CooldownTime", Cooldown); - Cooldowns.Rewind(); - } - delete TimeMapListSnapshot; - - if(!Cooldowns.ExportToFile(sCooldownFile)) - { - LogMessage("Unable to export cooldown file: \"%s\"", sCooldownFile); - delete Cooldowns; - return; - } - - delete Cooldowns; -} - -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; -} - -stock bool IsValidClient(int client) -{ - if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client) && !IsClientSourceTV(client)) - return true; - return false; -} diff --git a/mapchooser_extended/scripting/mapchooser_extended_avg_mapend.sp b/mapchooser_extended/scripting/mapchooser_extended_unloze.sp similarity index 93% rename from mapchooser_extended/scripting/mapchooser_extended_avg_mapend.sp rename to mapchooser_extended/scripting/mapchooser_extended_unloze.sp index 341d04f..8f53cb8 100755 --- a/mapchooser_extended/scripting/mapchooser_extended_avg_mapend.sp +++ b/mapchooser_extended/scripting/mapchooser_extended_unloze.sp @@ -137,10 +137,8 @@ bool g_WaitingForVote; bool g_MapVoteCompleted; bool g_ChangeMapInProgress; bool g_HasIntermissionStarted = false; -bool g_RtvInitiated = false; -bool g_bSset_win_map = false; -int g_iNextmapState = 0; //0 = nothing. 1 = rtv succesfull. 2 = admin used setnextmap. 3 = did not extend or used all extends. 4 = vote at end of map is going on. +int g_iNextmapState = 0; //0 = nothing. 1 = rtv succesfull. 2 = admin used setnextmap. 3 = did not extend or used all extends. int g_mapFileSerial = -1; int g_iSkipAllRestrictions; int g_iDontCooldownMap; @@ -243,7 +241,6 @@ public void OnPluginEnd() public void OnPluginStart() { - CreateTimer(1.0, Timer_Countdown1, _, TIMER_REPEAT); LoadTranslations("mapchooser_extended.phrases"); LoadTranslations("basevotes.phrases"); LoadTranslations("common.phrases"); @@ -407,9 +404,6 @@ public void OnPluginStart() HookEvent("player_death", Event_PlayerDeath); - //2026 edit: block cs_win_panel_match from triggering on Intermission so that people dont get stuck with a scoreboard they cant close. - HookEvent("cs_win_panel_match", Event_BlockWinPanel, EventHookMode_Pre); - AutoExecConfig(true, "mapchooser_extended"); //Change the mp_bonusroundtime max so that we have time to display the vote @@ -510,7 +504,6 @@ public Action GetInternalGetCvars(Handle timer) public void OnMapStart() { g_iNextmapState = 0; - g_RtvInitiated = false; CreateTimer(1.0, GetInternalGetCvars); int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; @@ -641,7 +634,6 @@ public void OnMapEnd() { g_first_map_no_cooldown = false; g_iNextmapState = 0; - g_RtvInitiated = false; int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; ServerCommand("sm_cvar mp_chattime %i", total_time); @@ -782,23 +774,6 @@ public void OnMapTimeLeftChanged() void SetupTimeleftTimer() { - if (g_iNextmapState == 0 && GetConVarInt(g_Cvar_Extend) == 0) - { - g_iNextmapState = 3; - //map simply had no extend to begin with. mce_extend 0. - //encap made me notice that maps without extends would still incorrectly do the setup Timeleft Timer() call. - } - - if (g_iNextmapState != 0) - { - if (g_VoteTimer != INVALID_HANDLE) - { - KillTimer(g_VoteTimer); - g_VoteTimer = INVALID_HANDLE; - } - return; //all extends were used or map was not extended or rtv was succesfull or admin set nextmap - } - int time; if(GetMapTimeLeft(time) && time > 0) { @@ -911,10 +886,6 @@ public Action Timer_StartMapVote(Handle timer, Handle data) MapChange mapChange = view_as(ReadPackCell(data)); Handle hndl = view_as(ReadPackCell(data)); //LogMessage("Mapchooser_extended_avg calling InitiateVote()"); - if (mapChange == MapChange_MapEnd && GetConVarInt(g_Cvar_Extend) - g_Extends < 1) - { - return Plugin_Stop; //feature where normal map changes does not happen if we ran out of extends, instead end of map does the actual real vote. - } InitiateVote(mapChange, hndl); return Plugin_Stop; } @@ -972,12 +943,6 @@ public Action CS_OnTerminateRound(float &delay, CSRoundEndReason &reason) { int timeleft; GetMapTimeLeft(timeleft); - //cases that can happen: - //0 timeleft and admin did setnextmap. - //0 timeleft and rtv already picked a map. (round_end event forces the nextmap) - //0 timeleft and all extends used or map was not extended. (we do the map vote at map end) - //0 timeleft and rtv is ongoing still - //yeah sure why not just do it on every round end anyways. if (GetClientCount(false) > g_iDontCooldownMap && !g_first_map_no_cooldown) { @@ -992,68 +957,16 @@ public Action CS_OnTerminateRound(float &delay, CSRoundEndReason &reason) SetSharedCooldowns(map); } - if (timeleft <= 0 && g_RtvInitiated && g_iNextmapState < 4) //last round was terminated, rtv is going on and we did not set g_i Nextmapstate yet. - { - - //extra time in case of rtv, rtv run-off (there is no dont change option here as we already used all extends or people voted dont extend) - int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; - g_iNextmapState = 4; //rtv vote going on already, so lets not repeat that. - CreateTimer(1.0, unfreeze_players, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - //extending the map allows players to run around instead of being frozen. should just be careful about it running into edicts limits - - CreateTimer(float(total_time + 10), Timer_fall_back_map_switch, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - delay = float(total_time); - return Plugin_Changed; - } - - if (timeleft <= 0 && g_iNextmapState >= 3) //last round was terminated. time for mapvote now. - { - int total_time = (GetConVarInt(g_Cvar_VoteDuration) * 2) + GetConVarInt(g_Cvar_RunOffWarningTime) + 10; - if (g_iNextmapState == 3) - { - if (IsVoteInProgress()) //fucking admins being brain dead doing extend votes right when the map ends. - { - PrintToChatAll("The admin slept on the job again. Should had made that extend vote 2-3 minutes before the timeleft ran out instead of panic extend voting the last second possible."); - CancelVote(); - } - g_iNextmapState = 4; //started vote, so lets not repeat that. - CreateTimer(float(total_time + 10), Timer_fall_back_map_switch, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - //sometimes it will simply happen that theres a mapvote where nobody votes anything. - //have to prevent server from being stuck in those situations with this timer. - - InitiateVote(MapChange_Instant); //feature so mapvote happens at actual mapend - - CreateTimer(1.0, unfreeze_players, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - //extending the map allows players to run around instead of being frozen. should just be careful about it running into edicts limits - } - delay = float(total_time); - return Plugin_Changed; - } - - //when you join the ze server as the first player and theres 0 timeleft and no map was selected the server can get stuck for 2 minutes. //that is rather problematic because it often leads to the very first people connecting wanting to leave again because the game is stuck. if (timeleft < 0 && g_iNextmapState == 0) { - LogMessage("in CS_OnTerminateRound being hard stuck. switching map to default start map. timeleft: %i", timeleft); + //LogMessage("in CS_OnTerminateRound being hard stuck. switching map to default start map. timeleft: %i", timeleft); CreateTimer(1.0, Timer_fall_back_map_switch, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); } return Plugin_Continue; } -public Action unfreeze_players(Handle hTimer, Handle dp) -{ - ServerCommand("sm_testround"); - CreateTimer(1.0, unfreeze_players2, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - return Plugin_Handled; -} - -public Action unfreeze_players2(Handle hTimer, Handle dp) -{ - ServerCommand("sm_extend 20"); //this is not actually meant for extending the map. Its meant to unfreeze players during the mapvote. - return Plugin_Handled; -} - public Action Timer_fall_back_map_switch(Handle hTimer, Handle dp) { static char map[PLATFORM_MAX_PATH]; @@ -1106,7 +1019,7 @@ public void Event_RoundEnd(Handle event, const char[] name, bool dontBroadcast) int timeleft; GetMapTimeLeft(timeleft); - if (g_iNextmapState == 1 || (g_iNextmapState == 2 && timeleft <= 0)) //rtv went through or admin used setnextmap + if (g_iNextmapState == 1 || (g_iNextmapState >= 2 && timeleft <= 0)) //rtv went through or admin used setnextmap or we used all extends. { char map[PLATFORM_MAX_PATH]; GetNextMap(map, sizeof(map)); @@ -1182,11 +1095,6 @@ public void CheckMaxRounds(int roundcount) } } -public Action Event_BlockWinPanel(Event event, const char[] name, bool dontBroadcast) -{ - return Plugin_Handled; -} - public Action Event_PlayerDeath(Handle event, const char[] name, bool dontBroadcast) { if(!GetArraySize(g_MapList) || g_HasVoteStarted) @@ -1377,7 +1285,7 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) WritePackString(data, "Revote Warning"); else { - if (when == MapChange_MapEnd) + if (when == MapChange_MapEnd && g_iNextmapState != 3) //we already used all extends { WritePackString(data, "Vote Warning Extend"); } @@ -1453,7 +1361,8 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) */ static char map[PLATFORM_MAX_PATH]; - if (when == MapChange_MapEnd) //18th september feature idea where a normal mapvote at 3 minutes is between extend or not extend. + //its a vote for extend or dont extend. unless people voted to not extend or all extends were used. + if (when == MapChange_MapEnd && g_iNextmapState != 3) { SetMenuTitle(g_VoteMenu, "Vote Extend"); AddMenuItem(g_VoteMenu, LINE_ONE, "Choose something...", ITEMDRAW_DISABLED); @@ -1633,32 +1542,8 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) PrintToChatAll("[MCE] Voting for next map has started."); } -public Action Timer_Countdown1(Handle timer) -{ - int timeleft; - GetMapTimeLeft(timeleft); - if (timeleft <= 0) - { - if (!g_bSset_win_map) - { - ServerCommand("sm_cvar sv_nowinpanel 1"); //prevents pannel from blocking vote result for mapvotes at mapend. - } - g_bSset_win_map = true; - } - else - { - if (g_bSset_win_map) - { - ServerCommand("sm_cvar sv_nowinpanel 0"); //we display the pannel again. - } - g_bSset_win_map = false; - } - return Plugin_Continue; -} - public Action Timer_Countdown(Handle timer) { - if (g_iInterval <= 0) return Plugin_Stop; @@ -1783,9 +1668,6 @@ public void Handler_VoteFinishedGeneric(char[] map, } else if(strcmp(map, VOTE_DONTCHANGE, false) == 0) { - //dont change option in rtv cannot happen after the last extend was used or after people voting dong extend - //so there is no risk of a mapend rtv having the dont change option possible. - g_RtvInitiated = false; //reset the bool again PrintToChatAll("[MCE] Current map continues! The Vote has spoken! (Received %i/%i of votes)", map_votes, num_votes); LogAction(-1, -1, "Voting for next map has finished. 'No Change' was the winner"); @@ -1797,9 +1679,9 @@ public void Handler_VoteFinishedGeneric(char[] map, { if(g_ChangeTime == MapChange_MapEnd) { - g_iNextmapState = 3; //map was not extended + SetNextMap(map); } - else if(g_ChangeTime == MapChange_Instant) //end of map voting ends up here because we change instantly. + else if(g_ChangeTime == MapChange_Instant) { PrintToChatAll("[MCE] Next Map: %s", map); PrintToChatAll("[MCE] Next Map: %s", map); @@ -1811,32 +1693,21 @@ public void Handler_VoteFinishedGeneric(char[] map, } else // MapChange_RoundEnd { - if (g_iNextmapState == 4 && g_RtvInitiated) //timeleft is 0, the last round was terminated but rtv still on going. go to the rtv map now. - { - PrintToChatAll("[MCE] Next Map: %s", map); - PrintToChatAll("[MCE] Next Map: %s", map); - PrintToChatAll("[MCE] Next Map: %s", map); - Handle data; - CreateDataTimer(4.0, Timer_ChangeMap, data); - WritePackString(data, map); - g_ChangeMapInProgress = false; - } - else - { - g_iNextmapState = 1; //rtv was performed. - SetNextMap(map); - } - g_RtvInitiated = false; + g_iNextmapState = 1; //rtv was performed. + SetNextMap(map); } g_HasVoteStarted = false; g_MapVoteCompleted = true; //PrintToChatAll("map: %s", map); - if (g_ChangeTime == MapChange_MapEnd) + if (g_ChangeTime == MapChange_MapEnd && g_iNextmapState != 3) //if we already indicated that map was not extended we are done. { PrintToChatAll("[MCE] Extend voting finished. The map was not extended. (Received %i/%i of votes)", map_votes, num_votes); g_MapVoteCompleted = false; //this was only the extend or dont extend vote, still need actual mapvote. + g_iNextmapState = 3; //the map was simply not extended + PrintToChatAll("[MCE] Starting next map vote in 10 seconds!"); + CreateTimer(10.0, MapVoteNotextended); } else { @@ -1846,6 +1717,12 @@ public void Handler_VoteFinishedGeneric(char[] map, } } +public Action MapVoteNotextended(Handle timer) +{ + InitiateVote(MapChange_MapEnd); //since the map was not extended its time for next map vote right now. + return Plugin_Handled; +} + public void Handler_MapVoteFinished(Handle menu, int num_votes, int num_clients, @@ -2019,7 +1896,7 @@ public int Handler_MapVoteMenu(Handle menu, MenuAction action, int param1, int p //displaying to the client how much his vote is worth. //second parameter shows for example 5.0, last parameter is how much percentage of the entire vote the client decides. - if (g_ChangeTime == MapChange_MapEnd) + if (g_ChangeTime == MapChange_MapEnd && g_iNextmapState != 3) //if we did not extend or used all extends dont show this. { Format(buffer, sizeof(buffer), "%T", "Vote Extend", param1, GetPlayerWorthRTV_boost_(param1)); } @@ -2463,14 +2340,6 @@ public int Native_InitiateVote(Handle plugin, int numParams) MapChange when = view_as(GetNativeCell(1)); Handle inputarray = view_as(GetNativeCell(2)); - //what is this used for? people care about being able to do rtv even if its the last round - //and even if the rtv should be going on after the last round ending - if (g_iNextmapState == 4) - { - PrintToChatAll("Not doing rtv because end vote already is going on."); - return 0; - } - g_RtvInitiated = true; SetupWarningTimer(WarningType_Vote, when, inputarray); //LogMessage("SetupWarningTimer 9"); //PrintToChatAll("SetupWarningTimer 9"); @@ -2562,7 +2431,7 @@ stock void SetupWarningTimer(WarningType type, MapChange when=MapChange_MapEnd, { forwardVote = g_MapVoteWarningStartForward; cvarTime = g_Cvar_WarningTime; - if (when == MapChange_MapEnd) + if (when == MapChange_MapEnd && g_iNextmapState != 3) { strcopy(translationKey, sizeof(translationKey), "Vote Warning Extend"); }