2016-01-19 23:57:32 +01:00
/ * *
* 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 < http : //www.gnu.org/licenses/>.
*
* 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 < http : //www.sourcemod.net/license.php>.
*
* Version : $ Id $
* /
//#define DEBUG
# if defined DEBUG
2016-08-11 17:48:20 +02:00
# define assert(%1) if(!(%1)) ThrowError("Debug Assertion Failed");
# define assert_msg(%1,%2) if(!(%1)) ThrowError(%2);
2016-01-19 23:57:32 +01:00
# else
# define assert(%1)
# define assert_msg(%1,%2)
# endif
# include <sourcemod>
# include <mapchooser>
# include "include/mapchooser_extended"
# include <nextmap>
# include <sdktools>
# include <colors>
# undef REQUIRE_PLUGIN
# include <nativevotes>
2016-08-11 17:48:20 +02:00
# define REQUIRE_PLUGIN
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
# pragma semicolon 1
# pragma newdecls required
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
# define MCE_VERSION "1.12.0"
2016-01-19 23:57:32 +01:00
# define NV "nativevotes"
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 ,
}
2016-08-11 17:48:20 +02:00
public Plugin myinfo =
2016-01-19 23:57:32 +01:00
{
name = " MapChooser Extended " ,
author = " Powerlord, Zuko, and AlliedModders LLC " ,
description = " Automated Map Voting with Extensions " ,
version = MCE_VERSION ,
url = " https://forums.alliedmods.net/showthread.php?t=156974 "
} ;
/* Valve ConVars */
2016-08-11 17:48:20 +02:00
ConVar g_Cvar_Winlimit ;
ConVar g_Cvar_Maxrounds ;
ConVar g_Cvar_Fraglimit ;
ConVar g_Cvar_Bonusroundtime ;
ConVar g_Cvar_MatchClinch ;
ConVar g_Cvar_VoteNextLevel ;
ConVar g_Cvar_GameType ;
ConVar g_Cvar_GameMode ;
2016-01-19 23:57:32 +01:00
/* Plugin ConVars */
2016-08-11 17:48:20 +02:00
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_IncludeMaps ;
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 ;
2016-01-19 23:57:32 +01:00
/* Data Handles */
2016-08-11 17:48:20 +02:00
Handle g_MapList = INVALID_HANDLE ;
Handle g_NominateList = INVALID_HANDLE ;
Handle g_NominateOwners = INVALID_HANDLE ;
StringMap g_OldMapList ;
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 ;
int g_mapFileSerial = - 1 ;
int g_NominateCount = 0 ;
MapChange g_ChangeTime ;
Handle g_NominationsResetForward = INVALID_HANDLE ;
Handle g_MapVoteStartedForward = INVALID_HANDLE ;
2016-01-19 23:57:32 +01:00
/* Mapchooser Extended Plugin ConVars */
2016-08-11 17:48:20 +02:00
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_MenuStyle ;
ConVar g_Cvar_TimerLocation ;
ConVar g_Cvar_ExtendPosition ;
ConVar g_Cvar_MarkCustomMaps ;
ConVar g_Cvar_RandomizeNominations ;
ConVar g_Cvar_HideTimer ;
ConVar g_Cvar_NoVoteOption ;
2016-01-19 23:57:32 +01:00
/* Mapchooser Extended Data Handles */
2016-08-11 17:48:20 +02:00
Handle g_OfficialList = INVALID_HANDLE ;
2016-01-19 23:57:32 +01:00
/* Mapchooser Extended Forwards */
2016-08-11 17:48:20 +02:00
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 ;
2016-01-19 23:57:32 +01:00
/* Mapchooser Extended Globals */
2016-08-11 17:48:20 +02:00
int g_RunoffCount = 0 ;
int g_mapOfficialFileSerial = - 1 ;
bool g_NativeVotes = false ;
char g_GameModName [ 64 ] ;
bool g_WarningInProgress = false ;
bool g_AddNoVote = false ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
RoundCounting g_RoundCounting = RoundCounting_Standard ;
2016-01-19 23:57:32 +01:00
/* Upper bound of how many team there could be */
# define MAXTEAMS 10
2016-08-11 17:48:20 +02:00
int g_winCount [ MAXTEAMS ] ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
bool g_BlockedSlots = false ;
int g_ObjectiveEnt = - 1 ;
2016-01-19 23:57:32 +01:00
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
2016-08-11 17:48:20 +02:00
public void OnPluginStart ( )
2016-01-19 23:57:32 +01:00
{
LoadTranslations ( " mapchooser_extended.phrases " ) ;
LoadTranslations ( " basevotes.phrases " ) ;
LoadTranslations ( " common.phrases " ) ;
2016-08-11 17:48:20 +02:00
int arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
2016-01-19 23:57:32 +01:00
g_MapList = CreateArray ( arraySize ) ;
g_NominateList = CreateArray ( arraySize ) ;
g_NominateOwners = CreateArray ( 1 ) ;
2016-08-11 17:48:20 +02:00
g_OldMapList = new StringMap ( ) ;
2016-01-19 23:57:32 +01:00
g_NextMapList = CreateArray ( arraySize ) ;
g_OfficialList = CreateArray ( arraySize ) ;
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_IncludeMaps = CreateConVar ( " mce_include " , " 5 " , " Specifies how many maps to include in the vote. " , _ , true , 2.0 , true , 6.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 ) ;
// 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 " , " 1 " , " 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_MenuStyle = CreateConVar ( " mce_menustyle " , " 0 " , " Menu Style. 0 is the game's default, 1 is the older Valve style that requires you to press Escape to see the menu, 2 is the newer 1-9 button Voice Command style, unavailable in some games. Ignored on TF2 if NativeVotes Plugin is loaded. " , _ , true , 0.0 , true , 2.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/Don't 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 ) ;
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 <map> " ) ;
// Mapchooser Extended Commands
RegAdminCmd ( " mce_reload_maplist " , Command_ReloadMaps , ADMFLAG_CHANGEMAP , " mce_reload_maplist - Reload the Official Maplist file. " ) ;
g_Cvar_Winlimit = FindConVar ( " mp_winlimit " ) ;
g_Cvar_Maxrounds = FindConVar ( " mp_maxrounds " ) ;
g_Cvar_Fraglimit = FindConVar ( " mp_fraglimit " ) ;
2016-08-11 17:48:20 +02:00
EngineVersion version = GetEngineVersion ( ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
static char mapListPath [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
BuildPath ( Path_SM , mapListPath , PLATFORM_MAX_PATH , " configs/mapchooser_extended/maps/%s.txt " , g_GameModName ) ;
SetMapListCompatBind ( " official " , mapListPath ) ;
2016-08-11 17:48:20 +02:00
switch ( version )
2016-01-19 23:57:32 +01:00
{
case Engine_TF2 :
{
g_Cvar_VoteNextLevel = FindConVar ( " sv_vote_issue_nextlevel_allowed " ) ;
g_Cvar_Bonusroundtime = FindConVar ( " mp_bonusroundtime " ) ;
}
case Engine_CSGO :
{
g_Cvar_VoteNextLevel = FindConVar ( " mp_endmatch_votenextmap " ) ;
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 " ) ;
}
}
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Winlimit ! = INVALID_HANDLE | | g_Cvar_Maxrounds ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
switch ( version )
2016-01-19 23:57:32 +01:00
{
case Engine_TF2 :
{
HookEvent ( " teamplay_win_panel " , Event_TeamPlayWinPanel ) ;
HookEvent ( " teamplay_restart_round " , Event_TFRestartRound ) ;
HookEvent ( " arena_win_panel " , Event_TeamPlayWinPanel ) ;
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 ) ;
g_Cvar_MatchClinch = FindConVar ( " mp_match_can_clinch " ) ;
}
case Engine_DODS :
{
HookEvent ( " dod_round_win " , Event_RoundEnd ) ;
}
default :
{
HookEvent ( " round_end " , Event_RoundEnd ) ;
}
}
}
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Fraglimit ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
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
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Bonusroundtime ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
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 ) ;
}
2016-08-11 17:48:20 +02:00
public APLRes AskPluginLoad2 ( Handle myself , bool late , char [ ] error , int err_max )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( LibraryExists ( " mapchooser " ) )
2016-01-19 23:57:32 +01:00
{
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 ) ;
2016-08-11 17:48:20 +02:00
CreateNative ( " GetMapCooldown " , Native_GetMapCooldown ) ;
CreateNative ( " GetMapMinPlayers " , Native_GetMapMinPlayers ) ;
CreateNative ( " GetMapMaxPlayers " , Native_GetMapMaxPlayers ) ;
CreateNative ( " GetMapPlayerRestriction " , Native_GetMapPlayerRestriction ) ;
2016-01-19 23:57:32 +01:00
return APLRes_Success ;
}
2016-08-11 17:48:20 +02:00
public void OnAllPluginsLoaded ( )
2016-01-19 23:57:32 +01:00
{
g_NativeVotes = LibraryExists ( NV ) & & NativeVotes_IsVoteTypeSupported ( NativeVotesType_NextLevelMult ) ;
}
2016-08-11 17:48:20 +02:00
public void OnLibraryAdded ( const char [ ] name )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( StrEqual ( name , NV ) & & NativeVotes_IsVoteTypeSupported ( NativeVotesType_NextLevelMult ) )
2016-01-19 23:57:32 +01:00
g_NativeVotes = true ;
}
2016-08-11 17:48:20 +02:00
public void OnLibraryRemoved ( const char [ ] name )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( StrEqual ( name , NV ) )
2016-01-19 23:57:32 +01:00
g_NativeVotes = false ;
}
2016-08-11 17:48:20 +02:00
public void OnMapStart ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
static char folder [ 64 ] ;
2016-01-19 23:57:32 +01:00
GetGameFolderName ( folder , sizeof ( folder ) ) ;
g_RoundCounting = RoundCounting_Standard ;
g_ObjectiveEnt = - 1 ;
2016-08-11 17:48:20 +02:00
if ( strcmp ( folder , " tf " ) = = 0 & & GameRules_GetProp ( " m_bPlayingMannVsMachine " ) )
2016-01-19 23:57:32 +01:00
{
g_RoundCounting = RoundCounting_MvM ;
g_ObjectiveEnt = EntIndexToEntRef ( FindEntityByClassname ( - 1 , " tf_objective_resource " ) ) ;
}
2016-08-11 17:48:20 +02:00
else if ( strcmp ( folder , " csgo " ) = = 0 & & GetConVarInt ( g_Cvar_GameType ) = = GameType_GunGame & &
2016-01-19 23:57:32 +01:00
GetConVarInt ( g_Cvar_GameMode ) = = GunGameMode_ArmsRace )
{
g_RoundCounting = RoundCounting_ArmsRace ;
}
2016-08-11 17:48:20 +02:00
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 ( ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
public void OnConfigsExecuted ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ReadMapList ( g_MapList ,
2016-01-19 23:57:32 +01:00
g_mapFileSerial ,
" mapchooser " ,
MAPLIST_FLAG_CLEARARRAY | MAPLIST_FLAG_MAPSFOLDER )
! = INVALID_HANDLE )
{
2016-08-11 17:48:20 +02:00
if ( g_mapFileSerial = = - 1 )
2016-01-19 23:57:32 +01:00
LogError ( " Unable to create a valid map list. " ) ;
}
// Disable the next level vote in TF2 and CS:GO
// In TF2, this has two effects: 1. Stop the next level vote (which overlaps rtv functionality).
// 2. Stop the built-in end level vote. This is the only thing that happens in CS:GO
2016-08-11 17:48:20 +02:00
if ( g_Cvar_VoteNextLevel ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
SetConVarBool ( g_Cvar_VoteNextLevel , false ) ;
SetupTimeleftTimer ( ) ;
g_TotalRounds = 0 ;
g_Extends = 0 ;
g_MapVoteCompleted = false ;
g_NominateCount = 0 ;
ClearArray ( g_NominateList ) ;
ClearArray ( g_NominateOwners ) ;
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < MAXTEAMS ; i + + )
2016-01-19 23:57:32 +01:00
g_winCount [ i ] = 0 ;
/* Check if mapchooser will attempt to start mapvote during bonus round time */
2016-08-11 17:48:20 +02:00
if ( ( g_Cvar_Bonusroundtime ! = INVALID_HANDLE ) & & ! GetConVarInt ( g_Cvar_StartRounds ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! GetConVarInt ( g_Cvar_StartTime ) & & GetConVarFloat ( g_Cvar_Bonusroundtime ) < = GetConVarFloat ( g_Cvar_VoteDuration ) )
2016-01-19 23:57:32 +01:00
LogError ( " Warning - Bonus Round Time shorter than Vote Time. Votes during bonus round may not have time to complete " ) ;
}
InitializeOfficialMapList ( ) ;
}
2016-08-11 17:48:20 +02:00
public void OnMapEnd ( )
2016-01-19 23:57:32 +01:00
{
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 ;
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetCurrentMap ( map , PLATFORM_MAX_PATH ) ;
2016-08-11 17:48:20 +02:00
int Cooldown = InternalGetMapCooldown ( map ) ;
g_OldMapList . SetValue ( map , Cooldown , true ) ;
StringMapSnapshot OldMapListSnapshot = g_OldMapList . Snapshot ( ) ;
for ( int i = 0 ; i < OldMapListSnapshot . Length ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
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 ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
delete OldMapListSnapshot ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
public void OnClientPutInServer ( int client )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
CheckMapPlayerRestriction ( ) ;
}
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
public void OnClientDisconnect_Post ( int client )
{
CheckMapPlayerRestriction ( ) ;
}
public void OnClientDisconnect ( int client )
{
int index = FindValueInArray ( g_NominateOwners , client ) ;
if ( index = = - 1 )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
char oldmap [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetArrayString ( g_NominateList , index , oldmap , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_PushCell ( GetArrayCell ( g_NominateOwners , index ) ) ;
Call_Finish ( ) ;
RemoveFromArray ( g_NominateOwners , index ) ;
RemoveFromArray ( g_NominateList , index ) ;
g_NominateCount - - ;
}
2016-08-11 17:48:20 +02:00
public Action Command_SetNextmap ( int client , int args )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( args < 1 )
2016-01-19 23:57:32 +01:00
{
CReplyToCommand ( client , " [MCE] Usage: sm_setnextmap <map> " ) ;
return Plugin_Handled ;
}
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetCmdArg ( 1 , map , PLATFORM_MAX_PATH ) ;
2016-08-11 17:48:20 +02:00
if ( ! IsMapValid ( map ) )
2016-01-19 23:57:32 +01:00
{
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 ;
return Plugin_Handled ;
}
2016-08-11 17:48:20 +02:00
public Action Command_ReloadMaps ( int client , int args )
2016-01-19 23:57:32 +01:00
{
InitializeOfficialMapList ( ) ;
}
2016-08-11 17:48:20 +02:00
public void OnMapTimeLeftChanged ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( GetArraySize ( g_MapList ) )
2016-01-19 23:57:32 +01:00
SetupTimeleftTimer ( ) ;
}
2016-08-11 17:48:20 +02:00
void SetupTimeleftTimer ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int time ;
if ( GetMapTimeLeft ( time ) & & time > 0 )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int startTime ;
if ( GetConVarBool ( g_Cvar_StartTimePercentEnable ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int timeLimit ;
if ( GetMapTimeLimit ( timeLimit ) & & timeLimit > 0 )
2016-01-19 23:57:32 +01:00
{
startTime = GetConVarInt ( g_Cvar_StartTimePercent ) * ( timeLimit * 60 ) / 100 ;
}
}
else
startTime = GetConVarInt ( g_Cvar_StartTime ) * 60 ;
2016-08-11 17:48:20 +02:00
if ( time - startTime < 0 & & GetConVarBool ( g_Cvar_EndOfMapVote ) & & ! g_MapVoteCompleted & & ! g_HasVoteStarted )
2016-01-19 23:57:32 +01:00
{
SetupWarningTimer ( WarningType_Vote ) ;
}
else
{
2016-08-11 17:48:20 +02:00
if ( g_WarningTimer = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_VoteTimer ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
KillTimer ( g_VoteTimer ) ;
g_VoteTimer = INVALID_HANDLE ;
}
//g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVoteTimer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE);
g_VoteTimer = CreateTimer ( float ( time - startTime ) , Timer_StartWarningTimer , _ , TIMER_FLAG_NO_MAPCHANGE ) ;
}
}
}
}
2016-08-11 17:48:20 +02:00
public Action Timer_StartWarningTimer ( Handle timer )
2016-01-19 23:57:32 +01:00
{
g_VoteTimer = INVALID_HANDLE ;
2016-08-11 17:48:20 +02:00
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
SetupWarningTimer ( WarningType_Vote ) ;
}
2016-08-11 17:48:20 +02:00
public Action Timer_StartMapVote ( Handle timer , Handle data )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
static int timePassed ;
2016-01-19 23:57:32 +01:00
// This is still necessary because InitiateVote still calls this directly via the retry timer
2016-08-11 17:48:20 +02:00
if ( ! GetArraySize ( g_MapList ) | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) | | g_MapVoteCompleted | | g_HasVoteStarted )
2016-01-19 23:57:32 +01:00
{
g_WarningTimer = INVALID_HANDLE ;
return Plugin_Stop ;
}
ResetPack ( data ) ;
2016-08-11 17:48:20 +02:00
int warningMaxTime = ReadPackCell ( data ) ;
int warningTimeRemaining = warningMaxTime - timePassed ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
char warningPhrase [ 32 ] ;
2016-01-19 23:57:32 +01:00
ReadPackString ( data , warningPhrase , sizeof ( warningPhrase ) ) ;
// Tick timer for external plugins
Call_StartForward ( g_MapVoteWarningTickForward ) ;
Call_PushCell ( warningTimeRemaining ) ;
Call_Finish ( ) ;
2016-08-11 17:48:20 +02:00
if ( timePassed = = 0 | | ! GetConVarBool ( g_Cvar_HideTimer ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
TimerLocation timerLocation = view_as < TimerLocation > ( GetConVarInt ( g_Cvar_TimerLocation ) ) ;
2016-01-19 23:57:32 +01:00
switch ( timerLocation )
{
case TimerLocation_Center :
{
PrintCenterTextAll ( " %t " , warningPhrase , warningTimeRemaining ) ;
}
case TimerLocation_Chat :
{
PrintToChatAll ( " %t " , warningPhrase , warningTimeRemaining ) ;
}
default :
{
PrintHintTextToAll ( " %t " , warningPhrase , warningTimeRemaining ) ;
}
}
}
2016-08-11 17:48:20 +02:00
if ( timePassed + + > = warningMaxTime )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( timer = = g_RetryTimer )
2016-01-19 23:57:32 +01:00
{
g_WaitingForVote = false ;
g_RetryTimer = INVALID_HANDLE ;
}
else
g_WarningTimer = INVALID_HANDLE ;
timePassed = 0 ;
2016-08-11 17:48:20 +02:00
MapChange mapChange = view_as < MapChange > ( ReadPackCell ( data ) ) ;
Handle hndl = view_as < Handle > ( ReadPackCell ( data ) ) ;
2016-01-19 23:57:32 +01:00
InitiateVote ( mapChange , hndl ) ;
return Plugin_Stop ;
}
2016-08-11 17:48:20 +02:00
2016-01-19 23:57:32 +01:00
return Plugin_Continue ;
}
2016-08-11 17:48:20 +02:00
public void Event_TFRestartRound ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
/* Game got restarted - reset our round count tracking */
g_TotalRounds = 0 ;
}
2016-08-11 17:48:20 +02:00
public void Event_TeamPlayWinPanel ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_ChangeMapAtRoundEnd )
2016-01-19 23:57:32 +01:00
{
g_ChangeMapAtRoundEnd = false ;
CreateTimer ( 2.0 , Timer_ChangeMap , INVALID_HANDLE , TIMER_FLAG_NO_MAPCHANGE ) ;
g_ChangeMapInProgress = true ;
}
2016-08-11 17:48:20 +02:00
int bluescore = GetEventInt ( event , " blue_score " ) ;
int redscore = GetEventInt ( event , " red_score " ) ;
2016-01-19 23:57:32 +01:00
if ( GetEventInt ( event , " round_complete " ) = = 1 | | StrEqual ( name , " arena_win_panel " ) )
{
g_TotalRounds + + ;
2016-08-11 17:48:20 +02:00
if ( ! GetArraySize ( g_MapList ) | | g_HasVoteStarted | | g_MapVoteCompleted | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) )
2016-01-19 23:57:32 +01:00
return ;
CheckMaxRounds ( g_TotalRounds ) ;
switch ( GetEventInt ( event , " winning_team " ) )
{
case 3 :
{
CheckWinLimit ( bluescore ) ;
}
case 2 :
{
CheckWinLimit ( redscore ) ;
}
//We need to do nothing on winning_team == 0 this indicates stalemate.
default :
{
return ;
}
}
}
}
2016-08-11 17:48:20 +02:00
public void Event_MvMWinPanel ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( GetEventInt ( event , " winning_team " ) = = 2 )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int objectiveEnt = EntRefToEntIndex ( g_ObjectiveEnt ) ;
if ( objectiveEnt ! = INVALID_ENT_REFERENCE )
2016-01-19 23:57:32 +01:00
{
g_TotalRounds = GetEntProp ( g_ObjectiveEnt , Prop_Send , " m_nMannVsMachineWaveCount " ) ;
CheckMaxRounds ( g_TotalRounds ) ;
}
}
}
2016-08-11 17:48:20 +02:00
public void Event_Intermission ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
g_HasIntermissionStarted = true ;
}
2016-08-11 17:48:20 +02:00
public void Event_PhaseEnd ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
/* announce_phase_end fires for both half time and the end of the map, but intermission fires first for end of the map. */
2016-08-11 17:48:20 +02:00
if ( g_HasIntermissionStarted )
2016-01-19 23:57:32 +01:00
return ;
/* No intermission yet, so this must be half time. Swap the score counters. */
2016-08-11 17:48:20 +02:00
int t_score = g_winCount [ 2 ] ;
2016-01-19 23:57:32 +01:00
g_winCount [ 2 ] = g_winCount [ 3 ] ;
g_winCount [ 3 ] = t_score ;
}
2016-08-11 17:48:20 +02:00
public void Event_WeaponRank ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int rank = GetEventInt ( event , " weaponrank " ) ;
if ( rank > g_TotalRounds )
2016-01-19 23:57:32 +01:00
{
g_TotalRounds = rank ;
CheckMaxRounds ( g_TotalRounds ) ;
}
}
/* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */
2016-08-11 17:48:20 +02:00
public void Event_RoundEnd ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_RoundCounting = = RoundCounting_ArmsRace )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
if ( g_ChangeMapAtRoundEnd )
2016-01-19 23:57:32 +01:00
{
g_ChangeMapAtRoundEnd = false ;
CreateTimer ( 2.0 , Timer_ChangeMap , INVALID_HANDLE , TIMER_FLAG_NO_MAPCHANGE ) ;
g_ChangeMapInProgress = true ;
}
2016-08-11 17:48:20 +02:00
int winner ;
if ( strcmp ( name , " round_win " ) = = 0 | | strcmp ( name , " dod_round_win " ) = = 0 )
winner = GetEventInt ( event , " team " ) ; // Nuclear Dawn & DoD:S
2016-01-19 23:57:32 +01:00
else
winner = GetEventInt ( event , " winner " ) ;
2016-08-11 17:48:20 +02:00
if ( winner = = 0 | | winner = = 1 | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
if ( winner > = MAXTEAMS )
2016-01-19 23:57:32 +01:00
SetFailState ( " Mod exceed maximum team count - Please file a bug report. " ) ;
g_TotalRounds + + ;
g_winCount [ winner ] + + ;
2016-08-11 17:48:20 +02:00
if ( ! GetArraySize ( g_MapList ) | | g_HasVoteStarted | | g_MapVoteCompleted )
2016-01-19 23:57:32 +01:00
{
return ;
}
CheckWinLimit ( g_winCount [ winner ] ) ;
CheckMaxRounds ( g_TotalRounds ) ;
}
2016-08-11 17:48:20 +02:00
public void CheckWinLimit ( int winner_score )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Winlimit ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int winlimit = GetConVarInt ( g_Cvar_Winlimit ) ;
if ( winlimit )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( winner_score > = ( winlimit - GetConVarInt ( g_Cvar_StartRounds ) ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
}
2016-08-11 17:48:20 +02:00
if ( g_Cvar_MatchClinch ! = INVALID_HANDLE & & g_Cvar_Maxrounds ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
bool clinch = GetConVarBool ( g_Cvar_MatchClinch ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( clinch )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
int winlimit = RoundFloat ( maxrounds / 2.0 ) ;
2016-01-19 23:57:32 +01:00
if ( winner_score = = winlimit - 1 )
{
2016-08-11 17:48:20 +02:00
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
}
}
2016-08-11 17:48:20 +02:00
public void CheckMaxRounds ( int roundcount )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int maxrounds = 0 ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( g_RoundCounting = = RoundCounting_ArmsRace )
2016-01-19 23:57:32 +01:00
maxrounds = GameRules_GetProp ( " m_iNumGunGameProgressiveWeaponsCT " ) ;
2016-08-11 17:48:20 +02:00
else if ( g_RoundCounting = = RoundCounting_MvM )
2016-01-19 23:57:32 +01:00
maxrounds = GetEntProp ( g_ObjectiveEnt , Prop_Send , " m_nMannVsMachineMaxWaveCount " ) ;
2016-08-11 17:48:20 +02:00
else if ( g_Cvar_Maxrounds ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
else
return ;
2016-08-11 17:48:20 +02:00
if ( maxrounds )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( roundcount > = ( maxrounds - GetConVarInt ( g_Cvar_StartRounds ) ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
}
2016-08-11 17:48:20 +02:00
public void Event_PlayerDeath ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! GetArraySize ( g_MapList ) | | g_Cvar_Fraglimit = = INVALID_HANDLE | | g_HasVoteStarted )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
if ( ! GetConVarInt ( g_Cvar_Fraglimit ) | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
if ( g_MapVoteCompleted )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
int fragger = GetClientOfUserId ( GetEventInt ( event , " attacker " ) ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( ! fragger )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
if ( GetClientFrags ( fragger ) > = ( GetConVarInt ( g_Cvar_Fraglimit ) - GetConVarInt ( g_Cvar_StartFrags ) ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
2016-08-11 17:48:20 +02:00
public Action Command_Mapvote ( int client , int args )
2016-01-19 23:57:32 +01:00
{
ShowActivity2 ( client , " [MCE] " , " %t " , " Initiated Vote Map " ) ;
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd , INVALID_HANDLE , true ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
return Plugin_Handled ;
}
/ * *
* 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 .
* /
2016-08-11 17:48:20 +02:00
void InitiateVote ( MapChange when , Handle inputlist = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
g_WaitingForVote = true ;
g_WarningInProgress = false ;
// Check if a nativevotes vots is in progress first
// NativeVotes running at the same time as a regular vote can cause hintbox problems,
// so always check for a standard vote
2016-08-11 17:48:20 +02:00
if ( IsVoteInProgress ( ) | | ( g_NativeVotes & & NativeVotes_IsVoteInProgress ( ) ) )
2016-01-19 23:57:32 +01:00
{
// Can't start a vote, try again in 5 seconds.
//g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE);
CPrintToChatAll ( " [MCE] %t " , " Cannot Start Vote " , FAILURE_TIMER_LENGTH ) ;
2016-08-11 17:48:20 +02:00
Handle data ;
2016-01-19 23:57:32 +01:00
g_RetryTimer = CreateDataTimer ( 1.0 , Timer_StartMapVote , data , TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT ) ;
/* Mapchooser Extended */
WritePackCell ( data , FAILURE_TIMER_LENGTH ) ;
2016-08-11 17:48:20 +02:00
if ( GetConVarBool ( g_Cvar_RunOff ) & & g_RunoffCount > 0 )
2016-01-19 23:57:32 +01:00
WritePackString ( data , " Revote Warning " ) ;
2016-08-11 17:48:20 +02:00
else
2016-01-19 23:57:32 +01:00
WritePackString ( data , " Vote Warning " ) ;
/* End Mapchooser Extended */
2016-08-11 17:48:20 +02:00
WritePackCell ( data , view_as < int > ( when ) ) ;
WritePackCell ( data , view_as < int > ( inputlist ) ) ;
2016-01-19 23:57:32 +01:00
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 */
2016-08-11 17:48:20 +02:00
if ( g_MapVoteCompleted & & g_ChangeMapInProgress )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
CheckMapPlayerRestriction ( ) ;
2016-08-23 13:26:09 +02:00
CreateNextVote ( ) ;
2016-01-19 23:57:32 +01:00
g_ChangeTime = when ;
g_WaitingForVote = false ;
g_HasVoteStarted = true ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
{
g_VoteMenu = NativeVotes_Create ( Handler_MapVoteMenu , NativeVotesType_NextLevelMult , MenuAction_End | MenuAction_VoteCancel | MenuAction_Display | MenuAction_DisplayItem ) ;
NativeVotes_SetResultCallback ( g_VoteMenu , Handler_NativeVoteFinished ) ;
}
else
{
2016-08-11 17:48:20 +02:00
Handle menuStyle = GetMenuStyleHandle ( view_as < MenuStyle > ( GetConVarInt ( g_Cvar_MenuStyle ) ) ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( menuStyle ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
g_VoteMenu = CreateMenuEx ( menuStyle , Handler_MapVoteMenu , MenuAction_End | MenuAction_Display | MenuAction_DisplayItem | MenuAction_VoteCancel ) ;
}
else
{
// You chose... poorly
g_VoteMenu = CreateMenu ( Handler_MapVoteMenu , MenuAction_End | MenuAction_Display | MenuAction_DisplayItem | MenuAction_VoteCancel ) ;
}
g_AddNoVote = GetConVarBool ( g_Cvar_NoVoteOption ) ;
// Block Vote Slots
2016-08-11 17:48:20 +02:00
if ( GetConVarBool ( g_Cvar_BlockSlots ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
Handle radioStyle = GetMenuStyleHandle ( MenuStyle_Radio ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( GetMenuStyle ( g_VoteMenu ) = = radioStyle )
2016-01-19 23:57:32 +01:00
{
g_BlockedSlots = true ;
AddMenuItem ( g_VoteMenu , LINE_ONE , " Choose something... " , ITEMDRAW_DISABLED ) ;
AddMenuItem ( g_VoteMenu , LINE_TWO , " ...will ya? " , ITEMDRAW_DISABLED ) ;
2016-08-11 17:48:20 +02:00
if ( ! g_AddNoVote )
2016-01-19 23:57:32 +01:00
AddMenuItem ( g_VoteMenu , LINE_SPACER , " " , ITEMDRAW_SPACER ) ;
}
2016-08-11 17:48:20 +02:00
else
g_BlockedSlots = false ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
if ( g_AddNoVote )
2016-01-19 23:57:32 +01:00
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 .
* /
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
/* No input given - User our internal nominations and maplist */
2016-08-11 17:48:20 +02:00
if ( inputlist = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
Handle randomizeList = INVALID_HANDLE ;
if ( GetConVarBool ( g_Cvar_RandomizeNominations ) )
2016-01-19 23:57:32 +01:00
randomizeList = CloneArray ( g_NominateList ) ;
2016-08-11 17:48:20 +02:00
int nominateCount = GetArraySize ( g_NominateList ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
int voteSize = GetVoteSize ( ) ;
2016-01-19 23:57:32 +01:00
// The if and else if could be combined, but it looks extremely messy
// This is a hack to lower the vote menu size by 1 when Don't Change or Extend Map should appear
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ( when = = MapChange_Instant | | when = = MapChange_RoundEnd ) & & GetConVarBool ( g_Cvar_DontChange ) )
2016-01-19 23:57:32 +01:00
voteSize - - ;
2016-08-11 17:48:20 +02:00
else if ( GetConVarBool ( g_Cvar_Extend ) & & g_Extends < GetConVarInt ( g_Cvar_Extend ) )
2016-01-19 23:57:32 +01:00
voteSize - - ;
}
/* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */
2016-08-11 17:48:20 +02:00
int nominationsToAdd = nominateCount > = voteSize ? voteSize : nominateCount ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
bool extendFirst = GetConVarBool ( g_Cvar_ExtendPosition ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( extendFirst )
2016-01-19 23:57:32 +01:00
AddExtendToMenu ( g_VoteMenu , when ) ;
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < nominationsToAdd ; i + + )
2016-01-19 23:57:32 +01:00
{
GetArrayString ( g_NominateList , i , map , PLATFORM_MAX_PATH ) ;
2016-08-11 17:48:20 +02:00
if ( randomizeList = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
AddMapItem ( map ) ;
2016-08-11 17:48:20 +02:00
2016-01-19 23:57:32 +01:00
RemoveStringFromArray ( g_NextMapList , map ) ;
/* Notify Nominations that this map is now free */
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( map ) ;
Call_PushCell ( GetArrayCell ( g_NominateOwners , i ) ) ;
Call_Finish ( ) ;
}
/* Clear out the rest of the nominations array */
2016-08-11 17:48:20 +02:00
for ( int i = nominationsToAdd ; i < nominateCount ; i + + )
2016-01-19 23:57:32 +01:00
{
GetArrayString ( g_NominateList , i , map , PLATFORM_MAX_PATH ) ;
/* These maps shouldn't be excluded from the vote as they weren't really nominated at all */
/* Notify Nominations that this map is now free */
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( map ) ;
Call_PushCell ( GetArrayCell ( g_NominateOwners , i ) ) ;
Call_Finish ( ) ;
}
/* There should currently be 'nominationsToAdd' unique maps in the vote */
2016-08-11 17:48:20 +02:00
int i = nominationsToAdd ;
int count = 0 ;
int availableMaps = GetArraySize ( g_NextMapList ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( i < voteSize & & availableMaps = = 0 )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( i = = 0 )
2016-01-19 23:57:32 +01:00
{
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 ;
}
}
2016-08-11 17:48:20 +02:00
while ( i < voteSize )
2016-01-19 23:57:32 +01:00
{
GetArrayString ( g_NextMapList , count , map , PLATFORM_MAX_PATH ) ;
count + + ;
2016-08-11 17:48:20 +02:00
if ( randomizeList = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
/* Insert the map and increment our count */
AddMapItem ( map ) ;
}
else
PushArrayString ( randomizeList , map ) ;
2016-08-11 17:48:20 +02:00
2016-01-19 23:57:32 +01:00
i + + ;
2016-08-11 17:48:20 +02:00
//Run out of maps, this will have to do.
if ( count > = availableMaps )
2016-01-19 23:57:32 +01:00
break ;
}
2016-08-11 17:48:20 +02:00
if ( randomizeList ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
// Fisher-Yates Shuffle
2016-08-11 17:48:20 +02:00
for ( int j = GetArraySize ( randomizeList ) - 1 ; j > = 1 ; j - - )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int k = GetRandomInt ( 0 , j ) ;
2016-01-19 23:57:32 +01:00
SwapArrayItems ( randomizeList , j , k ) ;
}
2016-08-11 17:48:20 +02:00
for ( int j = 0 ; j < GetArraySize ( randomizeList ) ; j + + )
2016-01-19 23:57:32 +01:00
{
GetArrayString ( randomizeList , j , map , PLATFORM_MAX_PATH ) ;
AddMapItem ( map ) ;
}
CloseHandle ( randomizeList ) ;
randomizeList = INVALID_HANDLE ;
}
/* Wipe out our nominations list - Nominations have already been informed of this */
g_NominateCount = 0 ;
ClearArray ( g_NominateOwners ) ;
ClearArray ( g_NominateList ) ;
2016-08-11 17:48:20 +02:00
if ( ! extendFirst )
2016-01-19 23:57:32 +01:00
AddExtendToMenu ( g_VoteMenu , when ) ;
}
else //We were given a list of maps to start the vote with
{
2016-08-11 17:48:20 +02:00
int size = GetArraySize ( inputlist ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < size ; i + + )
2016-01-19 23:57:32 +01:00
{
GetArrayString ( inputlist , i , map , PLATFORM_MAX_PATH ) ;
2016-08-11 17:48:20 +02:00
if ( IsMapValid ( map ) )
2016-01-19 23:57:32 +01:00
{
AddMapItem ( map ) ;
}
// New in Mapchooser Extended
2016-08-11 17:48:20 +02:00
else if ( StrEqual ( map , VOTE_DONTCHANGE ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_AddItem ( g_VoteMenu , VOTE_DONTCHANGE , " Don't Change " ) ;
else
AddMenuItem ( g_VoteMenu , VOTE_DONTCHANGE , " Don't Change " ) ;
}
2016-08-11 17:48:20 +02:00
else if ( StrEqual ( map , VOTE_EXTEND ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_AddItem ( g_VoteMenu , VOTE_EXTEND , " Extend Map " ) ;
else
AddMenuItem ( g_VoteMenu , VOTE_EXTEND , " Extend Map " ) ;
}
}
CloseHandle ( inputlist ) ;
}
2016-08-11 17:48:20 +02:00
int voteDuration = GetConVarInt ( g_Cvar_VoteDuration ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
{
NativeVotes_DisplayToAll ( g_VoteMenu , voteDuration ) ;
}
else
{
//SetMenuExitButton(g_VoteMenu, false);
2016-08-11 17:48:20 +02:00
if ( GetVoteSize ( ) < = GetMaxPageItems ( GetMenuStyle ( g_VoteMenu ) ) )
2016-01-19 23:57:32 +01:00
{
//This is necessary to get items 9 and 0 as usable voting items
SetMenuPagination ( g_VoteMenu , MENU_NO_PAGINATION ) ;
}
VoteMenuToAll ( g_VoteMenu , 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 " ) ;
}
2016-08-11 17:48:20 +02:00
public int Handler_NativeVoteFinished ( Handle vote ,
int num_votes ,
int num_clients ,
const int [ ] client_indexes ,
const int [ ] client_votes ,
int num_items ,
const int [ ] item_indexes ,
const int [ ] item_votes )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int [ ] [ ] client_info = new int [ num_clients ] [ 2 ] ;
int [ ] [ ] item_info = new int [ num_items ] [ 2 ] ;
2016-01-19 23:57:32 +01:00
NativeVotes_FixResults ( num_clients , client_indexes , client_votes , num_items , item_indexes , item_votes , client_info , item_info ) ;
Handler_MapVoteFinished ( vote , num_votes , num_clients , client_info , num_items , item_info ) ;
}
2016-08-11 17:48:20 +02:00
public void Handler_VoteFinishedGeneric ( Handle menu ,
int num_votes ,
int num_clients ,
const int [ ] [ ] client_info ,
int num_items ,
const int [ ] [ ] item_info )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetMapItem ( menu , item_info [ 0 ] [ VOTEINFO_ITEM_INDEX ] , map , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_MapVoteEndForward ) ;
Call_PushString ( map ) ;
Call_Finish ( ) ;
2016-08-11 17:48:20 +02:00
if ( strcmp ( map , VOTE_EXTEND , false ) = = 0 )
2016-01-19 23:57:32 +01:00
{
g_Extends + + ;
2016-08-11 17:48:20 +02:00
int time ;
if ( GetMapTimeLimit ( time ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( time > 0 )
2016-01-19 23:57:32 +01:00
ExtendMapTimeLimit ( GetConVarInt ( g_Cvar_ExtendTimeStep ) * 60 ) ;
}
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Winlimit ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int winlimit = GetConVarInt ( g_Cvar_Winlimit ) ;
if ( winlimit )
2016-01-19 23:57:32 +01:00
SetConVarInt ( g_Cvar_Winlimit , winlimit + GetConVarInt ( g_Cvar_ExtendRoundStep ) ) ;
}
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Maxrounds ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
if ( maxrounds )
2016-01-19 23:57:32 +01:00
SetConVarInt ( g_Cvar_Maxrounds , maxrounds + GetConVarInt ( g_Cvar_ExtendRoundStep ) ) ;
}
2016-08-11 17:48:20 +02:00
if ( g_Cvar_Fraglimit ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int fraglimit = GetConVarInt ( g_Cvar_Fraglimit ) ;
if ( fraglimit )
2016-01-19 23:57:32 +01:00
SetConVarInt ( g_Cvar_Fraglimit , fraglimit + GetConVarInt ( g_Cvar_ExtendFragStep ) ) ;
}
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayPassEx ( menu , NativeVotesPass_Extend ) ;
CPrintToChatAll ( " [MCE] %t " , " Current Map Extended " , RoundToFloor ( float ( item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ) / float ( num_votes ) * 100 ) , num_votes ) ;
LogAction ( - 1 , - 1 , " Voting for next map has finished. The current map has been extended. " ) ;
// We extended, so we'll have to vote again.
g_RunoffCount = 0 ;
g_HasVoteStarted = false ;
SetupTimeleftTimer ( ) ;
}
2016-08-11 17:48:20 +02:00
else if ( strcmp ( map , VOTE_DONTCHANGE , false ) = = 0 )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayPassEx ( menu , NativeVotesPass_Extend ) ;
CPrintToChatAll ( " [MCE] %t " , " Current Map Stays " , RoundToFloor ( float ( item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ) / float ( num_votes ) * 100 ) , num_votes ) ;
LogAction ( - 1 , - 1 , " Voting for next map has finished. 'No Change' was the winner " ) ;
g_RunoffCount = 0 ;
g_HasVoteStarted = false ;
SetupTimeleftTimer ( ) ;
}
else
{
2016-08-11 17:48:20 +02:00
if ( g_ChangeTime = = MapChange_MapEnd )
2016-01-19 23:57:32 +01:00
{
SetNextMap ( map ) ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayPass ( menu , map ) ;
}
2016-08-11 17:48:20 +02:00
else if ( g_ChangeTime = = MapChange_Instant )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
Handle data ;
2016-01-19 23:57:32 +01:00
CreateDataTimer ( 4.0 , Timer_ChangeMap , data ) ;
WritePackString ( data , map ) ;
g_ChangeMapInProgress = false ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayPassEx ( menu , NativeVotesPass_ChgLevel , map ) ;
}
else // MapChange_RoundEnd
{
SetNextMap ( map ) ;
g_ChangeMapAtRoundEnd = true ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayPass ( menu , map ) ;
}
g_HasVoteStarted = false ;
g_MapVoteCompleted = true ;
CPrintToChatAll ( " [MCE] %t " , " Nextmap Voting Finished " , map , RoundToFloor ( float ( item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ) / float ( num_votes ) * 100 ) , num_votes ) ;
LogAction ( - 1 , - 1 , " Voting for next map has finished. Nextmap: %s. " , map ) ;
}
}
2016-08-11 17:48:20 +02:00
public void Handler_MapVoteFinished ( Handle menu ,
int num_votes ,
int num_clients ,
const int [ ] [ ] client_info ,
int num_items ,
const int [ ] [ ] item_info )
2016-01-19 23:57:32 +01:00
{
// Implement revote logic - Only run this` block if revotes are enabled and this isn't the last revote
2016-08-11 17:48:20 +02:00
if ( GetConVarBool ( g_Cvar_RunOff ) & & num_items > 1 & & g_RunoffCount < GetConVarInt ( g_Cvar_MaxRunOffs ) )
2016-01-19 23:57:32 +01:00
{
g_RunoffCount + + ;
2016-08-11 17:48:20 +02:00
int highest_votes = item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ;
int required_percent = GetConVarInt ( g_Cvar_RunOffPercent ) ;
int required_votes = RoundToCeil ( float ( num_votes ) * float ( required_percent ) / 100 ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( highest_votes = = item_info [ 1 ] [ VOTEINFO_ITEM_VOTES ] )
2016-01-19 23:57:32 +01:00
{
g_HasVoteStarted = false ;
//Revote is needed
2016-08-11 17:48:20 +02:00
int arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
Handle mapList = CreateArray ( arraySize ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < num_items ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( item_info [ i ] [ VOTEINFO_ITEM_VOTES ] = = highest_votes )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetMapItem ( menu , item_info [ i ] [ VOTEINFO_ITEM_INDEX ] , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( mapList , map ) ;
}
else
break ;
}
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayFail ( menu , NativeVotesFail_NotEnoughVotes ) ;
CPrintToChatAll ( " [MCE] %t " , " Tie Vote " , GetArraySize ( mapList ) ) ;
2016-08-11 17:48:20 +02:00
SetupWarningTimer ( WarningType_Revote , view_as < MapChange > ( g_ChangeTime ) , mapList ) ;
2016-01-19 23:57:32 +01:00
return ;
}
2016-08-11 17:48:20 +02:00
else if ( highest_votes < required_votes )
2016-01-19 23:57:32 +01:00
{
g_HasVoteStarted = false ;
//Revote is needed
2016-08-11 17:48:20 +02:00
int arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
Handle mapList = CreateArray ( arraySize ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
static char map1 [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetMapItem ( menu , item_info [ 0 ] [ VOTEINFO_ITEM_INDEX ] , map1 , PLATFORM_MAX_PATH ) ;
PushArrayString ( mapList , map1 ) ;
// We allow more than two maps for a revote if they are tied
2016-08-11 17:48:20 +02:00
for ( int i = 1 ; i < num_items ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( GetArraySize ( mapList ) < 2 | | item_info [ i ] [ VOTEINFO_ITEM_VOTES ] = = item_info [ i - 1 ] [ VOTEINFO_ITEM_VOTES ] )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetMapItem ( menu , item_info [ i ] [ VOTEINFO_ITEM_INDEX ] , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( mapList , map ) ;
}
else
break ;
}
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayFail ( menu , NativeVotesFail_NotEnoughVotes ) ;
CPrintToChatAll ( " [MCE] %t " , " Revote Is Needed " , required_percent ) ;
2016-08-11 17:48:20 +02:00
SetupWarningTimer ( WarningType_Revote , view_as < MapChange > ( g_ChangeTime ) , mapList ) ;
2016-01-19 23:57:32 +01:00
return ;
}
}
// No revote needed, continue as normal.
Handler_VoteFinishedGeneric ( menu , num_votes , num_clients , client_info , num_items , item_info ) ;
}
// This is shared by NativeVotes now, but NV doesn't support Display or DisplayItem
2016-08-11 17:48:20 +02:00
public int Handler_MapVoteMenu ( Handle menu , MenuAction action , int param1 , int param2 )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
switch ( action )
2016-01-19 23:57:32 +01:00
{
case MenuAction_End :
{
g_VoteMenu = INVALID_HANDLE ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_Close ( menu ) ;
else
CloseHandle ( menu ) ;
}
case MenuAction_Display :
{
// NativeVotes uses the standard TF2/CSGO vote screen
2016-08-11 17:48:20 +02:00
if ( ! g_NativeVotes )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
static char buffer [ 255 ] ;
2016-01-19 23:57:32 +01:00
Format ( buffer , sizeof ( buffer ) , " %T " , " Vote Nextmap " , param1 ) ;
2016-08-11 17:48:20 +02:00
Handle panel = view_as < Handle > ( param2 ) ;
2016-01-19 23:57:32 +01:00
SetPanelTitle ( panel , buffer ) ;
}
}
case MenuAction_DisplayItem :
{
2016-08-11 17:48:20 +02:00
char map [ PLATFORM_MAX_PATH ] ;
char buffer [ 255 ] ;
int mark = GetConVarInt ( g_Cvar_MarkCustomMaps ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_GetItem ( menu , param2 , map , PLATFORM_MAX_PATH ) ;
else
GetMenuItem ( menu , param2 , map , PLATFORM_MAX_PATH ) ;
2016-08-11 17:48:20 +02:00
if ( StrEqual ( map , VOTE_EXTEND , false ) )
2016-01-19 23:57:32 +01:00
{
Format ( buffer , sizeof ( buffer ) , " %T " , " Extend Map " , param1 ) ;
}
2016-08-11 17:48:20 +02:00
else if ( StrEqual ( map , VOTE_DONTCHANGE , false ) )
2016-01-19 23:57:32 +01:00
{
Format ( buffer , sizeof ( buffer ) , " %T " , " Dont Change " , param1 ) ;
}
// Mapchooser Extended
2016-08-11 17:48:20 +02:00
else if ( StrEqual ( map , LINE_ONE , false ) )
2016-01-19 23:57:32 +01:00
{
Format ( buffer , sizeof ( buffer ) , " %T " , " Line One " , param1 ) ;
}
2016-08-11 17:48:20 +02:00
else if ( StrEqual ( map , LINE_TWO , false ) )
2016-01-19 23:57:32 +01:00
{
Format ( buffer , sizeof ( buffer ) , " %T " , " Line Two " , param1 ) ;
}
// Note that the first part is to discard the spacer line
2016-08-11 17:48:20 +02:00
else if ( ! StrEqual ( map , LINE_SPACER , false ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( mark = = 1 & & ! InternalIsMapOfficial ( map ) )
2016-01-19 23:57:32 +01:00
{
Format ( buffer , sizeof ( buffer ) , " %T " , " Custom Marked " , param1 , map ) ;
}
2016-08-11 17:48:20 +02:00
else if ( mark = = 2 & & ! InternalIsMapOfficial ( map ) )
2016-01-19 23:57:32 +01:00
{
Format ( buffer , sizeof ( buffer ) , " %T " , " Custom " , param1 , map ) ;
}
}
2016-08-11 17:48:20 +02:00
if ( buffer [ 0 ] ! = '\0' )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
{
NativeVotes_RedrawVoteItem ( buffer ) ;
2016-08-11 17:48:20 +02:00
return view_as < int > ( Plugin_Continue ) ;
2016-01-19 23:57:32 +01:00
}
else
return RedrawMenuItem ( buffer ) ;
}
// End Mapchooser Extended
}
case MenuAction_VoteCancel :
{
// If we receive 0 votes, pick at random.
2016-08-11 17:48:20 +02:00
if ( param1 = = VoteCancel_NoVotes & & GetConVarBool ( g_Cvar_NoVoteMode ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int count ;
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
count = NativeVotes_GetItemCount ( menu ) ;
else
count = GetMenuItemCount ( menu ) ;
2016-08-11 17:48:20 +02:00
int item ;
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
do
{
2016-08-11 17:48:20 +02:00
int startInt = 0 ;
if ( ! g_NativeVotes & & g_BlockedSlots )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_AddNoVote )
2016-01-19 23:57:32 +01:00
{
startInt = 2 ;
}
else
{
startInt = 3 ;
}
}
item = GetRandomInt ( startInt , count - 1 ) ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_GetItem ( menu , item , map , PLATFORM_MAX_PATH ) ;
else
GetMenuItem ( menu , item , map , PLATFORM_MAX_PATH ) ;
}
2016-08-11 17:48:20 +02:00
while ( strcmp ( map , VOTE_EXTEND , false ) = = 0 ) ;
2016-01-19 23:57:32 +01:00
SetNextMap ( map ) ;
g_MapVoteCompleted = true ;
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_DisplayPass ( menu , map ) ;
}
2016-08-11 17:48:20 +02:00
else if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
NativeVotesFailType reason = NativeVotesFail_Generic ;
if ( param1 = = VoteCancel_NoVotes )
2016-01-19 23:57:32 +01:00
reason = NativeVotesFail_NotEnoughVotes ;
NativeVotes_DisplayFail ( menu , reason ) ;
}
g_HasVoteStarted = false ;
}
}
return 0 ;
}
2016-08-11 17:48:20 +02:00
public Action Timer_ChangeMap ( Handle hTimer , Handle dp )
2016-01-19 23:57:32 +01:00
{
g_ChangeMapInProgress = false ;
2016-08-11 17:48:20 +02:00
char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( dp = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! GetNextMap ( map , PLATFORM_MAX_PATH ) )
2016-01-19 23:57:32 +01:00
{
//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 ;
}
2016-08-11 17:48:20 +02:00
bool RemoveStringFromArray ( Handle array , char [ ] str )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int index = FindStringInArray ( array , str ) ;
if ( index ! = - 1 )
2016-01-19 23:57:32 +01:00
{
RemoveFromArray ( array , index ) ;
return true ;
}
return false ;
}
2016-08-11 17:48:20 +02:00
void CreateNextVote ( )
2016-01-19 23:57:32 +01:00
{
assert ( g_NextMapList )
ClearArray ( g_NextMapList ) ;
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-08-23 13:26:09 +02:00
Handle tempMaps = CloneArray ( g_MapList ) ;
2016-01-19 23:57:32 +01:00
GetCurrentMap ( map , PLATFORM_MAX_PATH ) ;
RemoveStringFromArray ( tempMaps , map ) ;
2016-08-11 17:48:20 +02:00
if ( GetConVarInt ( g_Cvar_ExcludeMaps ) & & GetArraySize ( tempMaps ) > GetConVarInt ( g_Cvar_ExcludeMaps ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
StringMapSnapshot OldMapListSnapshot = g_OldMapList . Snapshot ( ) ;
for ( int i = 0 ; i < OldMapListSnapshot . Length ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
OldMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
2016-01-19 23:57:32 +01:00
RemoveStringFromArray ( tempMaps , map ) ;
}
2016-08-11 17:48:20 +02:00
delete OldMapListSnapshot ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
int voteSize = GetVoteSize ( ) ;
int limit = ( voteSize < GetArraySize ( tempMaps ) ? voteSize : GetArraySize ( tempMaps ) ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < limit ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-23 13:26:09 +02:00
int b ;
for ( int j = 0 ; j < 10 ; j + + )
{
b = GetRandomInt ( 0 , GetArraySize ( tempMaps ) - 1 ) ;
GetArrayString ( tempMaps , b , map , PLATFORM_MAX_PATH ) ;
if ( InternalGetMapPlayerRestriction ( map ) = = 0 )
break ;
}
2016-01-19 23:57:32 +01:00
PushArrayString ( g_NextMapList , map ) ;
RemoveFromArray ( tempMaps , b ) ;
}
CloseHandle ( tempMaps ) ;
}
2016-08-11 17:48:20 +02:00
bool CanVoteStart ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_WaitingForVote | | g_HasVoteStarted )
2016-01-19 23:57:32 +01:00
return false ;
return true ;
}
2016-08-11 17:48:20 +02:00
NominateResult InternalNominateMap ( char [ ] map , bool force , int owner )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! IsMapValid ( map ) )
2016-01-19 23:57:32 +01:00
{
return Nominate_InvalidMap ;
}
/* Map already in the vote */
2016-08-11 17:48:20 +02:00
if ( FindStringInArray ( g_NominateList , map ) ! = - 1 )
2016-01-19 23:57:32 +01:00
{
return Nominate_AlreadyInVote ;
}
2016-08-11 17:48:20 +02:00
int index ;
2016-01-19 23:57:32 +01:00
/* Look to replace an existing nomination by this client - Nominations made with owner = 0 aren't replaced */
2016-08-11 17:48:20 +02:00
if ( owner & & ( ( index = FindValueInArray ( g_NominateOwners , owner ) ) ! = - 1 ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
char oldmap [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetArrayString ( g_NominateList , index , oldmap , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_PushCell ( owner ) ;
Call_Finish ( ) ;
SetArrayString ( g_NominateList , index , map ) ;
return Nominate_Replaced ;
}
/* Too many nominated maps. */
2016-08-11 17:48:20 +02:00
if ( g_NominateCount > = GetVoteSize ( ) & & ! force )
2016-01-19 23:57:32 +01:00
{
return Nominate_VoteFull ;
}
PushArrayString ( g_NominateList , map ) ;
PushArrayCell ( g_NominateOwners , owner ) ;
g_NominateCount + + ;
2016-08-11 17:48:20 +02:00
while ( GetArraySize ( g_NominateList ) > GetVoteSize ( ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
char oldmap [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetArrayString ( g_NominateList , 0 , oldmap , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_PushCell ( GetArrayCell ( g_NominateOwners , 0 ) ) ;
Call_Finish ( ) ;
RemoveFromArray ( g_NominateList , 0 ) ;
RemoveFromArray ( g_NominateOwners , 0 ) ;
2016-08-11 17:48:20 +02:00
g_NominateCount - - ;
2016-01-19 23:57:32 +01:00
}
return Nominate_Added ;
}
/* Add natives to allow nominate and initiate vote to be call */
2016-08-11 17:48:20 +02:00
/* native bool NominateMap(const char[] map, bool force, &NominateError:error); */
public int Native_NominateMap ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int len ;
2016-01-19 23:57:32 +01:00
GetNativeStringLength ( 1 , len ) ;
2016-08-11 17:48:20 +02:00
if ( len < = 0 )
return false ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
char [ ] map = new char [ len + 1 ] ;
2016-01-19 23:57:32 +01:00
GetNativeString ( 1 , map , len + 1 ) ;
2016-08-11 17:48:20 +02:00
return view_as < int > ( InternalNominateMap ( map , GetNativeCell ( 2 ) , GetNativeCell ( 3 ) ) ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
bool InternalRemoveNominationByMap ( char [ ] map )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < GetArraySize ( g_NominateList ) ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
char oldmap [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetArrayString ( g_NominateList , i , oldmap , PLATFORM_MAX_PATH ) ;
if ( strcmp ( map , oldmap , false ) = = 0 )
{
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_PushCell ( GetArrayCell ( g_NominateOwners , i ) ) ;
Call_Finish ( ) ;
RemoveFromArray ( g_NominateList , i ) ;
RemoveFromArray ( g_NominateOwners , i ) ;
g_NominateCount - - ;
return true ;
}
}
return false ;
}
2016-08-11 17:48:20 +02:00
/* native bool RemoveNominationByMap(const char[] map); */
public int Native_RemoveNominationByMap ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int len ;
2016-01-19 23:57:32 +01:00
GetNativeStringLength ( 1 , len ) ;
2016-08-11 17:48:20 +02:00
if ( len < = 0 )
return false ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
char [ ] map = new char [ len + 1 ] ;
2016-01-19 23:57:32 +01:00
GetNativeString ( 1 , map , len + 1 ) ;
2016-08-11 17:48:20 +02:00
return view_as < int > ( InternalRemoveNominationByMap ( map ) ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
bool InternalRemoveNominationByOwner ( int owner )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int index ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( owner & & ( ( index = FindValueInArray ( g_NominateOwners , owner ) ) ! = - 1 ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
char oldmap [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
GetArrayString ( g_NominateList , index , oldmap , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_PushCell ( owner ) ;
Call_Finish ( ) ;
RemoveFromArray ( g_NominateList , index ) ;
RemoveFromArray ( g_NominateOwners , index ) ;
g_NominateCount - - ;
return true ;
}
return false ;
}
2016-08-11 17:48:20 +02:00
/* native bool RemoveNominationByOwner(owner); */
public int Native_RemoveNominationByOwner ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
return view_as < int > ( InternalRemoveNominationByOwner ( GetNativeCell ( 1 ) ) ) ;
2016-01-19 23:57:32 +01:00
}
/* native InitiateMapChooserVote(); */
2016-08-11 17:48:20 +02:00
public int Native_InitiateVote ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
MapChange when = view_as < MapChange > ( GetNativeCell ( 1 ) ) ;
Handle inputarray = view_as < Handle > ( GetNativeCell ( 2 ) ) ;
2016-01-19 23:57:32 +01:00
LogAction ( - 1 , - 1 , " Starting map vote because outside request " ) ;
SetupWarningTimer ( WarningType_Vote , when , inputarray ) ;
//InitiateVote(when, inputarray);
}
2016-08-11 17:48:20 +02:00
public int Native_CanVoteStart ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
return CanVoteStart ( ) ;
}
2016-08-11 17:48:20 +02:00
public int Native_CheckVoteDone ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
return g_MapVoteCompleted ;
}
2016-08-11 17:48:20 +02:00
public int Native_EndOfMapVoteEnabled ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
return GetConVarBool ( g_Cvar_EndOfMapVote ) ;
}
2016-08-11 17:48:20 +02:00
public int Native_GetExcludeMapList ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
Handle array = view_as < Handle > ( GetNativeCell ( 1 ) ) ;
if ( array = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
StringMapSnapshot OldMapListSnapshot = g_OldMapList . Snapshot ( ) ;
for ( int i = 0 ; i < OldMapListSnapshot . Length ; i + + )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
OldMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
2016-01-19 23:57:32 +01:00
PushArrayString ( array , map ) ;
}
2016-08-11 17:48:20 +02:00
delete OldMapListSnapshot ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
public int Native_GetNominatedMapList ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
Handle maparray = view_as < Handle > ( GetNativeCell ( 1 ) ) ;
Handle ownerarray = view_as < Handle > ( GetNativeCell ( 2 ) ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( maparray = = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
for ( int i = 0 ; i < GetArraySize ( g_NominateList ) ; i + + )
2016-01-19 23:57:32 +01:00
{
GetArrayString ( g_NominateList , 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 )
{
2016-08-11 17:48:20 +02:00
int index = GetArrayCell ( g_NominateOwners , i ) ;
2016-01-19 23:57:32 +01:00
PushArrayCell ( ownerarray , index ) ;
}
}
}
// Functions new to Mapchooser Extended
2016-08-11 17:48:20 +02:00
stock void SetupWarningTimer ( WarningType type , MapChange when = MapChange_MapEnd , Handle mapList = INVALID_HANDLE , bool force = false )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! GetArraySize ( g_MapList ) | | g_ChangeMapInProgress | | g_HasVoteStarted | | ( ! force & & ( ( when = = MapChange_MapEnd & & ! GetConVarBool ( g_Cvar_EndOfMapVote ) ) | | g_MapVoteCompleted ) ) )
2016-01-19 23:57:32 +01:00
return ;
2016-08-11 17:48:20 +02:00
bool interrupted = false ;
if ( g_WarningInProgress & & g_WarningTimer ! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
{
interrupted = true ;
KillTimer ( g_WarningTimer ) ;
}
g_WarningInProgress = true ;
2016-08-11 17:48:20 +02:00
Handle forwardVote ;
Handle cvarTime ;
static char translationKey [ 64 ] ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
switch ( type )
2016-01-19 23:57:32 +01:00
{
case WarningType_Vote :
{
forwardVote = g_MapVoteWarningStartForward ;
cvarTime = g_Cvar_WarningTime ;
strcopy ( translationKey , sizeof ( translationKey ) , " Vote Warning " ) ;
}
case WarningType_Revote :
{
forwardVote = g_MapVoteRunoffStartForward ;
cvarTime = g_Cvar_RunOffWarningTime ;
strcopy ( translationKey , sizeof ( translationKey ) , " Revote Warning " ) ;
}
}
2016-08-11 17:48:20 +02:00
if ( ! interrupted )
2016-01-19 23:57:32 +01:00
{
Call_StartForward ( forwardVote ) ;
Call_Finish ( ) ;
}
2016-08-11 17:48:20 +02:00
Handle data ;
2016-01-19 23:57:32 +01:00
g_WarningTimer = CreateDataTimer ( 1.0 , Timer_StartMapVote , data , TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT ) ;
WritePackCell ( data , GetConVarInt ( cvarTime ) ) ;
WritePackString ( data , translationKey ) ;
2016-08-11 17:48:20 +02:00
WritePackCell ( data , view_as < int > ( when ) ) ;
WritePackCell ( data , view_as < int > ( mapList ) ) ;
2016-01-19 23:57:32 +01:00
ResetPack ( data ) ;
}
2016-08-11 17:48:20 +02:00
stock void InitializeOfficialMapList ( )
2016-01-19 23:57:32 +01:00
{
// If this fails, we want it to have an empty adt_array
2016-08-11 17:48:20 +02:00
if ( ReadMapList ( g_OfficialList ,
2016-01-19 23:57:32 +01:00
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
2016-08-11 17:48:20 +02:00
else if ( g_mapOfficialFileSerial = = - 1 )
2016-01-19 23:57:32 +01:00
{
LogMessage ( " No official map list found for %s. Consider submitting one! " , g_GameModName ) ;
}
}
2016-08-11 17:48:20 +02:00
stock bool IsMapEndVoteAllowed ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( ! GetConVarBool ( g_Cvar_EndOfMapVote ) | | g_MapVoteCompleted | | g_HasVoteStarted )
2016-01-19 23:57:32 +01:00
return false ;
2016-08-11 17:48:20 +02:00
return true ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
public int Native_IsMapOfficial ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int len ;
2016-01-19 23:57:32 +01:00
GetNativeStringLength ( 1 , len ) ;
2016-08-11 17:48:20 +02:00
if ( len < = 0 )
return false ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
char [ ] map = new char [ len + 1 ] ;
2016-01-19 23:57:32 +01:00
GetNativeString ( 1 , map , len + 1 ) ;
return InternalIsMapOfficial ( map ) ;
}
2016-08-11 17:48:20 +02:00
bool InternalIsMapOfficial ( const char [ ] mapname )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int officialMapIndex = FindStringInArray ( g_OfficialList , mapname ) ;
2016-01-19 23:57:32 +01:00
return ( officialMapIndex > - 1 ) ;
}
2016-08-11 17:48:20 +02:00
public int Native_IsWarningTimer ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
return g_WarningInProgress ;
}
2016-08-11 17:48:20 +02:00
public int Native_CanNominate ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_HasVoteStarted )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
return view_as < int > ( CanNominate_No_VoteInProgress ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
if ( g_MapVoteCompleted )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
return view_as < int > ( CanNominate_No_VoteComplete ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
if ( g_NominateCount > = GetVoteSize ( ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
return view_as < int > ( CanNominate_No_VoteFull ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
return view_as < int > ( CanNominate_Yes ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
public int Native_ExcludeMap ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int len ;
2016-01-19 23:57:32 +01:00
GetNativeStringLength ( 1 , len ) ;
2016-08-11 17:48:20 +02:00
if ( len < = 0 )
2016-01-19 23:57:32 +01:00
return false ;
2016-08-11 17:48:20 +02:00
char [ ] map = new char [ len + 1 ] ;
2016-01-19 23:57:32 +01:00
GetNativeString ( 1 , map , len + 1 ) ;
2016-08-11 17:48:20 +02:00
int Cooldown = InternalGetMapCooldown ( map ) ;
g_OldMapList . SetValue ( map , Cooldown , true ) ;
2016-04-26 12:36:03 +02:00
2016-01-19 23:57:32 +01:00
return true ;
}
2016-08-11 17:48:20 +02:00
public int Native_GetMapCooldown ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
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_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_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 ) ;
}
stock void AddMapItem ( const char [ ] map )
{
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_AddItem ( g_VoteMenu , map , map ) ;
else
AddMenuItem ( g_VoteMenu , map , map ) ;
}
2016-08-11 17:48:20 +02:00
stock void GetMapItem ( Handle menu , int position , char [ ] map , int mapLen )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_GetItem ( menu , position , map , mapLen ) ;
else
GetMenuItem ( menu , position , map , mapLen ) ;
}
2016-08-11 17:48:20 +02:00
stock void AddExtendToMenu ( Handle menu , MapChange when )
2016-01-19 23:57:32 +01:00
{
/* Do we add any special items? */
// Moved for Mapchooser Extended
2016-08-11 17:48:20 +02:00
if ( ( when = = MapChange_Instant | | when = = MapChange_RoundEnd ) & & GetConVarBool ( g_Cvar_DontChange ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
// Built-in votes doesn't have "Don't Change", send Extend instead
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_AddItem ( menu , VOTE_DONTCHANGE , " Don't Change " ) ;
else
AddMenuItem ( menu , VOTE_DONTCHANGE , " Don't Change " ) ;
}
2016-08-11 17:48:20 +02:00
else if ( GetConVarBool ( g_Cvar_Extend ) & & g_Extends < GetConVarInt ( g_Cvar_Extend ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
if ( g_NativeVotes )
2016-01-19 23:57:32 +01:00
NativeVotes_AddItem ( menu , VOTE_EXTEND , " Extend Map " ) ;
else
AddMenuItem ( menu , VOTE_EXTEND , " Extend Map " ) ;
}
}
2016-08-11 17:48:20 +02:00
stock int GetVoteSize ( )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int voteSize = GetConVarInt ( g_Cvar_IncludeMaps ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
// New in 1.9.5 to let us bump up the included maps count
if ( g_NativeVotes )
{
int max = NativeVotes_GetMaxItems ( ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( max < voteSize )
voteSize = max ;
}
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
return voteSize ;
}
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
stock int InternalGetMapCooldown ( const char [ ] map )
{
int Cooldown = g_Cvar_ExcludeMaps . IntValue ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( g_Config & & g_Config . JumpToKey ( map ) )
{
Cooldown = g_Config . GetNum ( " Cooldown " , Cooldown ) ;
g_Config . Rewind ( ) ;
}
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
return Cooldown ;
}
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
void CheckMapPlayerRestriction ( )
{
static char map [ PLATFORM_MAX_PATH ] ;
for ( int i = 0 ; i < GetArraySize ( g_NominateList ) ; i + + )
{
int client = GetArrayCell ( g_NominateOwners , i ) ;
if ( CheckCommandAccess ( client , " sm_nominate_ignore " , ADMFLAG_CHEATS , true ) )
continue ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
GetArrayString ( g_NominateList , i , map , PLATFORM_MAX_PATH ) ;
int Restriction = InternalGetMapPlayerRestriction ( map ) ;
if ( Restriction )
{
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( map ) ;
Call_PushCell ( GetArrayCell ( g_NominateOwners , i ) ) ;
Call_Finish ( ) ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
RemoveFromArray ( g_NominateList , i ) ;
RemoveFromArray ( g_NominateOwners , i ) ;
g_NominateCount - - ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( Restriction < 0 )
CPrintToChat ( client , " [MCE] %t " , " Nomination Removed MinPlayers Error " , map ) ;
else if ( Restriction > 0 )
CPrintToChat ( client , " [MCE] %t " , " Nomination Removed MaxPlayers Error " , map ) ;
2016-01-19 23:57:32 +01:00
}
}
2016-08-11 17:48:20 +02:00
}
stock int InternalGetMapMinPlayers ( const char [ ] map )
{
int MinPlayers = 0 ;
if ( g_Config & & g_Config . JumpToKey ( map ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
MinPlayers = g_Config . GetNum ( " MinPlayers " , MinPlayers ) ;
g_Config . Rewind ( ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
return MinPlayers ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
stock int InternalGetMapMaxPlayers ( const char [ ] map )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
int MaxPlayers = 0 ;
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
if ( g_Config & & g_Config . JumpToKey ( map ) )
2016-01-19 23:57:32 +01:00
{
2016-08-11 17:48:20 +02:00
MaxPlayers = g_Config . GetNum ( " MaxPlayers " , MaxPlayers ) ;
g_Config . Rewind ( ) ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
return MaxPlayers ;
}
// <0 = Less than MinPlayers
// 0 = Okay
// >0 = More than MaxPlayers
stock int InternalGetMapPlayerRestriction ( const char [ ] map )
{
int NumPlayers = GetClientCount ( ) ;
int MinPlayers = InternalGetMapMinPlayers ( map ) ;
int MaxPlayers = InternalGetMapMaxPlayers ( map ) ;
if ( MinPlayers & & NumPlayers < MinPlayers )
return NumPlayers - MinPlayers ;
if ( MaxPlayers & & NumPlayers > MaxPlayers )
return NumPlayers - MaxPlayers ;
return 0 ;
}