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
# 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
# pragma semicolon 1
# include <sourcemod>
# include <mapchooser>
# include "include/mapchooser_extended"
# include <nextmap>
# include <sdktools>
# include <colors>
# undef REQUIRE_PLUGIN
# include <nativevotes>
2016-04-26 12:36:03 +02:00
# define MCE_VERSION "1.11.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 ,
}
public Plugin : myinfo =
{
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 */
new Handle : g_Cvar_Winlimit = INVALID_HANDLE ;
new Handle : g_Cvar_Maxrounds = INVALID_HANDLE ;
new Handle : g_Cvar_Fraglimit = INVALID_HANDLE ;
new Handle : g_Cvar_Bonusroundtime = INVALID_HANDLE ;
new Handle : g_Cvar_MatchClinch = INVALID_HANDLE ;
new Handle : g_Cvar_VoteNextLevel = INVALID_HANDLE ;
new Handle : g_Cvar_GameType = INVALID_HANDLE ;
new Handle : g_Cvar_GameMode = INVALID_HANDLE ;
/* Plugin ConVars */
new Handle : g_Cvar_StartTime = INVALID_HANDLE ;
new Handle : g_Cvar_StartRounds = INVALID_HANDLE ;
new Handle : g_Cvar_StartFrags = INVALID_HANDLE ;
new Handle : g_Cvar_ExtendTimeStep = INVALID_HANDLE ;
new Handle : g_Cvar_ExtendRoundStep = INVALID_HANDLE ;
new Handle : g_Cvar_ExtendFragStep = INVALID_HANDLE ;
new Handle : g_Cvar_ExcludeMaps = INVALID_HANDLE ;
new Handle : g_Cvar_IncludeMaps = INVALID_HANDLE ;
new Handle : g_Cvar_NoVoteMode = INVALID_HANDLE ;
new Handle : g_Cvar_Extend = INVALID_HANDLE ;
new Handle : g_Cvar_DontChange = INVALID_HANDLE ;
new Handle : g_Cvar_EndOfMapVote = INVALID_HANDLE ;
new Handle : g_Cvar_VoteDuration = INVALID_HANDLE ;
new Handle : g_VoteTimer = INVALID_HANDLE ;
new Handle : g_RetryTimer = INVALID_HANDLE ;
new Handle : g_WarningTimer = INVALID_HANDLE ;
/* Data Handles */
new Handle : g_MapList = INVALID_HANDLE ;
new Handle : g_NominateList = INVALID_HANDLE ;
new Handle : g_NominateOwners = INVALID_HANDLE ;
new Handle : g_OldMapList = INVALID_HANDLE ;
new Handle : g_NextMapList = INVALID_HANDLE ;
new Handle : g_VoteMenu = INVALID_HANDLE ;
new g_Extends ;
new g_TotalRounds ;
new bool : g_HasVoteStarted ;
new bool : g_WaitingForVote ;
new bool : g_MapVoteCompleted ;
new bool : g_ChangeMapAtRoundEnd ;
new bool : g_ChangeMapInProgress ;
new bool : g_HasIntermissionStarted = false ;
new g_mapFileSerial = - 1 ;
new g_NominateCount = 0 ;
new MapChange : g_ChangeTime ;
new Handle : g_NominationsResetForward = INVALID_HANDLE ;
new Handle : g_MapVoteStartedForward = INVALID_HANDLE ;
/* Mapchooser Extended Plugin ConVars */
new Handle : g_Cvar_RunOff = INVALID_HANDLE ;
new Handle : g_Cvar_RunOffPercent = INVALID_HANDLE ;
new Handle : g_Cvar_BlockSlots = INVALID_HANDLE ;
new Handle : g_Cvar_MaxRunOffs = INVALID_HANDLE ;
new Handle : g_Cvar_StartTimePercent = INVALID_HANDLE ;
new Handle : g_Cvar_StartTimePercentEnable = INVALID_HANDLE ;
new Handle : g_Cvar_WarningTime = INVALID_HANDLE ;
new Handle : g_Cvar_RunOffWarningTime = INVALID_HANDLE ;
new Handle : g_Cvar_MenuStyle = INVALID_HANDLE ;
new Handle : g_Cvar_TimerLocation = INVALID_HANDLE ;
new Handle : g_Cvar_ExtendPosition = INVALID_HANDLE ;
new Handle : g_Cvar_MarkCustomMaps = INVALID_HANDLE ;
new Handle : g_Cvar_RandomizeNominations = INVALID_HANDLE ;
new Handle : g_Cvar_HideTimer = INVALID_HANDLE ;
new Handle : g_Cvar_NoVoteOption = INVALID_HANDLE ;
/* Mapchooser Extended Data Handles */
new Handle : g_OfficialList = INVALID_HANDLE ;
/* Mapchooser Extended Forwards */
new Handle : g_MapVoteWarningStartForward = INVALID_HANDLE ;
new Handle : g_MapVoteWarningTickForward = INVALID_HANDLE ;
new Handle : g_MapVoteStartForward = INVALID_HANDLE ;
new Handle : g_MapVoteEndForward = INVALID_HANDLE ;
new Handle : g_MapVoteRunoffStartForward = INVALID_HANDLE ;
/* Mapchooser Extended Globals */
new g_RunoffCount = 0 ;
new g_mapOfficialFileSerial = - 1 ;
new bool : g_NativeVotes = false ;
new String : g_GameModName [ 64 ] ;
new bool : g_WarningInProgress = false ;
new bool : g_AddNoVote = false ;
new RoundCounting : g_RoundCounting = RoundCounting_Standard ;
/* Upper bound of how many team there could be */
# define MAXTEAMS 10
new g_winCount [ MAXTEAMS ] ;
new bool : g_BlockedSlots = false ;
new 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
public OnPluginStart ( )
{
LoadTranslations ( " mapchooser_extended.phrases " ) ;
LoadTranslations ( " basevotes.phrases " ) ;
LoadTranslations ( " common.phrases " ) ;
new arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
g_MapList = CreateArray ( arraySize ) ;
g_NominateList = CreateArray ( arraySize ) ;
g_NominateOwners = CreateArray ( 1 ) ;
g_OldMapList = CreateArray ( arraySize ) ;
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 " ) ;
new EngineVersion : version = GetEngineVersionCompat ( ) ;
decl String : 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_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 " ) ;
}
}
if ( g_Cvar_Winlimit ! = INVALID_HANDLE | | g_Cvar_Maxrounds ! = INVALID_HANDLE )
{
switch ( version )
{
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 ) ;
}
}
}
if ( g_Cvar_Fraglimit ! = INVALID_HANDLE )
{
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
if ( g_Cvar_Bonusroundtime ! = INVALID_HANDLE )
{
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 ) ;
}
public APLRes : AskPluginLoad2 ( Handle : myself , bool : late , String : error [ ] , 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 ) ;
// BotoX
CreateNative ( " ExcludeMap " , Native_ExcludeMap ) ;
return APLRes_Success ;
}
public OnAllPluginsLoaded ( )
{
g_NativeVotes = LibraryExists ( NV ) & & NativeVotes_IsVoteTypeSupported ( NativeVotesType_NextLevelMult ) ;
}
public OnLibraryAdded ( const String : name [ ] )
{
if ( StrEqual ( name , NV ) & & NativeVotes_IsVoteTypeSupported ( NativeVotesType_NextLevelMult ) )
{
g_NativeVotes = true ;
}
}
public OnLibraryRemoved ( const String : name [ ] )
{
if ( StrEqual ( name , NV ) )
{
g_NativeVotes = false ;
}
}
public OnMapStart ( )
{
decl String : 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 ;
}
}
public 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. " ) ;
}
}
// 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
if ( g_Cvar_VoteNextLevel ! = INVALID_HANDLE )
{
SetConVarBool ( g_Cvar_VoteNextLevel , false ) ;
}
CreateNextVote ( ) ;
SetupTimeleftTimer ( ) ;
g_TotalRounds = 0 ;
g_Extends = 0 ;
g_MapVoteCompleted = false ;
g_NominateCount = 0 ;
ClearArray ( g_NominateList ) ;
ClearArray ( g_NominateOwners ) ;
for ( new i = 0 ; i < MAXTEAMS ; i + + )
{
g_winCount [ i ] = 0 ;
}
/* Check if mapchooser will attempt to start mapvote during bonus round time */
if ( ( g_Cvar_Bonusroundtime ! = INVALID_HANDLE ) & & ! 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 OnMapEnd ( )
{
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 ;
decl String : map [ PLATFORM_MAX_PATH ] ;
GetCurrentMap ( map , PLATFORM_MAX_PATH ) ;
PushArrayString ( g_OldMapList , map ) ;
if ( GetArraySize ( g_OldMapList ) > GetConVarInt ( g_Cvar_ExcludeMaps ) )
{
RemoveFromArray ( g_OldMapList , 0 ) ;
}
}
public OnClientDisconnect ( client )
{
new index = FindValueInArray ( g_NominateOwners , client ) ;
if ( index = = - 1 )
{
return ;
}
new String : oldmap [ PLATFORM_MAX_PATH ] ;
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 - - ;
}
public Action : Command_SetNextmap ( client , args )
{
if ( args < 1 )
{
CReplyToCommand ( client , " [MCE] Usage: sm_setnextmap <map> " ) ;
return Plugin_Handled ;
}
decl String : 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 ;
return Plugin_Handled ;
}
public Action : Command_ReloadMaps ( client , args )
{
InitializeOfficialMapList ( ) ;
}
public OnMapTimeLeftChanged ( )
{
if ( GetArraySize ( g_MapList ) )
{
SetupTimeleftTimer ( ) ;
}
}
SetupTimeleftTimer ( )
{
new time ;
if ( GetMapTimeLeft ( time ) & & time > 0 )
{
new startTime ;
if ( GetConVarBool ( g_Cvar_StartTimePercentEnable ) )
{
new 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 )
{
SetupWarningTimer ( WarningType_Vote ) ;
}
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);
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 )
{
SetupWarningTimer ( WarningType_Vote ) ;
}
}
public Action : Timer_StartMapVote ( Handle : timer , Handle : data )
{
static 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 ;
return Plugin_Stop ;
}
ResetPack ( data ) ;
new warningMaxTime = ReadPackCell ( data ) ;
new warningTimeRemaining = warningMaxTime - timePassed ;
new String : 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 ) )
{
new TimerLocation : timerLocation = TimerLocation : 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 ) ;
}
}
}
if ( timePassed + + > = warningMaxTime )
{
if ( timer = = g_RetryTimer )
{
g_WaitingForVote = false ;
g_RetryTimer = INVALID_HANDLE ;
}
else
{
g_WarningTimer = INVALID_HANDLE ;
}
timePassed = 0 ;
new MapChange : mapChange = MapChange : ReadPackCell ( data ) ;
new Handle : hndl = Handle : ReadPackCell ( data ) ;
InitiateVote ( mapChange , hndl ) ;
return Plugin_Stop ;
}
return Plugin_Continue ;
}
public Event_TFRestartRound ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
/* Game got restarted - reset our round count tracking */
g_TotalRounds = 0 ;
}
public Event_TeamPlayWinPanel ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
if ( g_ChangeMapAtRoundEnd )
{
g_ChangeMapAtRoundEnd = false ;
CreateTimer ( 2.0 , Timer_ChangeMap , INVALID_HANDLE , TIMER_FLAG_NO_MAPCHANGE ) ;
g_ChangeMapInProgress = true ;
}
new bluescore = GetEventInt ( event , " blue_score " ) ;
new redscore = GetEventInt ( event , " red_score " ) ;
if ( GetEventInt ( event , " round_complete " ) = = 1 | | StrEqual ( name , " arena_win_panel " ) )
{
g_TotalRounds + + ;
if ( ! GetArraySize ( g_MapList ) | | g_HasVoteStarted | | g_MapVoteCompleted | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) )
{
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 ;
}
}
}
}
public Event_MvMWinPanel ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
if ( GetEventInt ( event , " winning_team " ) = = 2 )
{
new objectiveEnt = EntRefToEntIndex ( g_ObjectiveEnt ) ;
if ( objectiveEnt ! = INVALID_ENT_REFERENCE )
{
g_TotalRounds = GetEntProp ( g_ObjectiveEnt , Prop_Send , " m_nMannVsMachineWaveCount " ) ;
CheckMaxRounds ( g_TotalRounds ) ;
}
}
}
public Event_Intermission ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
g_HasIntermissionStarted = true ;
}
public Event_PhaseEnd ( Handle : event , const String : 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. */
new t_score = g_winCount [ 2 ] ;
g_winCount [ 2 ] = g_winCount [ 3 ] ;
g_winCount [ 3 ] = t_score ;
}
public Event_WeaponRank ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
new 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 Event_RoundEnd ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
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 ;
}
new winner ;
if ( strcmp ( name , " round_win " ) = = 0 | | strcmp ( name , " dod_round_win " ) = = 0 )
{
// Nuclear Dawn & DoD:S
winner = GetEventInt ( event , " team " ) ;
}
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 CheckWinLimit ( winner_score )
{
if ( g_Cvar_Winlimit ! = INVALID_HANDLE )
{
new 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 ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
}
if ( g_Cvar_MatchClinch ! = INVALID_HANDLE & & g_Cvar_Maxrounds ! = INVALID_HANDLE )
{
new bool : clinch = GetConVarBool ( g_Cvar_MatchClinch ) ;
if ( clinch )
{
new maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
new winlimit = RoundFloat ( maxrounds / 2.0 ) ;
if ( winner_score = = winlimit - 1 )
{
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
}
}
public CheckMaxRounds ( roundcount )
{
new 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 if ( g_Cvar_Maxrounds ! = INVALID_HANDLE )
{
maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
}
else
{
return ;
}
if ( maxrounds )
{
if ( roundcount > = ( maxrounds - GetConVarInt ( g_Cvar_StartRounds ) ) )
{
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
}
public Event_PlayerDeath ( Handle : event , const String : name [ ] , bool : dontBroadcast )
{
if ( ! GetArraySize ( g_MapList ) | | g_Cvar_Fraglimit = = INVALID_HANDLE | | g_HasVoteStarted )
{
return ;
}
if ( ! GetConVarInt ( g_Cvar_Fraglimit ) | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) )
{
return ;
}
if ( g_MapVoteCompleted )
{
return ;
}
new fragger = GetClientOfUserId ( GetEventInt ( event , " attacker " ) ) ;
if ( ! fragger )
{
return ;
}
if ( GetClientFrags ( fragger ) > = ( GetConVarInt ( g_Cvar_Fraglimit ) - GetConVarInt ( g_Cvar_StartFrags ) ) )
{
if ( ! g_WarningInProgress | | g_WarningTimer = = INVALID_HANDLE )
{
SetupWarningTimer ( WarningType_Vote , MapChange_MapEnd ) ;
//InitiateVote(MapChange_MapEnd, INVALID_HANDLE);
}
}
}
public Action : Command_Mapvote ( client , args )
{
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 .
* /
InitiateVote ( MapChange : when , Handle : inputlist = INVALID_HANDLE )
{
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
if ( IsVoteInProgress ( ) | | ( g_NativeVotes & & NativeVotes_IsVoteInProgress ( ) ) )
{
// 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 ) ;
new Handle : data ;
g_RetryTimer = CreateDataTimer ( 1.0 , Timer_StartMapVote , data , TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT ) ;
/* 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 , _ : when ) ;
WritePackCell ( data , _ : 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 )
{
return ;
}
g_ChangeTime = when ;
g_WaitingForVote = false ;
g_HasVoteStarted = true ;
if ( g_NativeVotes )
{
g_VoteMenu = NativeVotes_Create ( Handler_MapVoteMenu , NativeVotesType_NextLevelMult , MenuAction_End | MenuAction_VoteCancel | MenuAction_Display | MenuAction_DisplayItem ) ;
NativeVotes_SetResultCallback ( g_VoteMenu , Handler_NativeVoteFinished ) ;
}
else
{
new Handle : menuStyle = GetMenuStyleHandle ( MenuStyle : GetConVarInt ( g_Cvar_MenuStyle ) ) ;
if ( menuStyle ! = INVALID_HANDLE )
{
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
if ( GetConVarBool ( g_Cvar_BlockSlots ) )
{
new 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 ) ;
if ( ! g_AddNoVote )
{
AddMenuItem ( g_VoteMenu , LINE_SPACER , " " , ITEMDRAW_SPACER ) ;
}
} 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 .
* /
decl String : map [ PLATFORM_MAX_PATH ] ;
/* No input given - User our internal nominations and maplist */
if ( inputlist = = INVALID_HANDLE )
{
new Handle : randomizeList = INVALID_HANDLE ;
if ( GetConVarBool ( g_Cvar_RandomizeNominations ) )
{
randomizeList = CloneArray ( g_NominateList ) ;
}
new nominateCount = GetArraySize ( g_NominateList ) ;
new voteSize = GetVoteSize ( ) ;
// 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
if ( g_NativeVotes )
{
if ( ( when = = MapChange_Instant | | when = = MapChange_RoundEnd ) & & GetConVarBool ( g_Cvar_DontChange ) )
{
voteSize - - ;
}
else if ( GetConVarBool ( g_Cvar_Extend ) & & g_Extends < GetConVarInt ( g_Cvar_Extend ) )
{
voteSize - - ;
}
}
/* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */
new nominationsToAdd = nominateCount > = voteSize ? voteSize : nominateCount ;
new bool : extendFirst = GetConVarBool ( g_Cvar_ExtendPosition ) ;
if ( extendFirst )
{
AddExtendToMenu ( g_VoteMenu , when ) ;
}
for ( new i = 0 ; i < nominationsToAdd ; i + + )
{
GetArrayString ( g_NominateList , i , map , PLATFORM_MAX_PATH ) ;
if ( randomizeList = = INVALID_HANDLE )
{
AddMapItem ( map ) ;
}
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 */
for ( new i = nominationsToAdd ; i < nominateCount ; i + + )
{
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 */
new i = nominationsToAdd ;
new count = 0 ;
new 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 + + ;
if ( count > = availableMaps )
{
//Run out of maps, this will have to do.
break ;
}
}
if ( randomizeList ! = INVALID_HANDLE )
{
// Fisher-Yates Shuffle
for ( new j = GetArraySize ( randomizeList ) - 1 ; j > = 1 ; j - - )
{
new k = GetRandomInt ( 0 , j ) ;
SwapArrayItems ( randomizeList , j , k ) ;
}
for ( new j = 0 ; j < GetArraySize ( randomizeList ) ; j + + )
{
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 ) ;
if ( ! extendFirst )
{
AddExtendToMenu ( g_VoteMenu , when ) ;
}
}
else //We were given a list of maps to start the vote with
{
new size = GetArraySize ( inputlist ) ;
for ( new 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 ) )
{
if ( g_NativeVotes )
{
NativeVotes_AddItem ( g_VoteMenu , VOTE_DONTCHANGE , " Don't Change " ) ;
}
else
{
AddMenuItem ( g_VoteMenu , VOTE_DONTCHANGE , " Don't Change " ) ;
}
}
else if ( StrEqual ( map , VOTE_EXTEND ) )
{
if ( g_NativeVotes )
{
NativeVotes_AddItem ( g_VoteMenu , VOTE_EXTEND , " Extend Map " ) ;
}
else
{
AddMenuItem ( g_VoteMenu , VOTE_EXTEND , " Extend Map " ) ;
}
}
}
CloseHandle ( inputlist ) ;
}
new voteDuration = GetConVarInt ( g_Cvar_VoteDuration ) ;
if ( g_NativeVotes )
{
NativeVotes_DisplayToAll ( g_VoteMenu , voteDuration ) ;
}
else
{
//SetMenuExitButton(g_VoteMenu, false);
if ( GetVoteSize ( ) < = GetMaxPageItems ( GetMenuStyle ( g_VoteMenu ) ) )
{
//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 " ) ;
}
public Handler_NativeVoteFinished ( Handle : vote ,
num_votes ,
num_clients ,
const client_indexes [ ] ,
const client_votes [ ] ,
num_items ,
const item_indexes [ ] ,
const item_votes [ ] )
{
new client_info [ num_clients ] [ 2 ] ;
new item_info [ num_items ] [ 2 ] ;
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 ) ;
}
public Handler_VoteFinishedGeneric ( Handle : menu ,
num_votes ,
num_clients ,
const client_info [ ] [ 2 ] ,
num_items ,
const item_info [ ] [ 2 ] )
{
decl String : map [ PLATFORM_MAX_PATH ] ;
GetMapItem ( menu , item_info [ 0 ] [ VOTEINFO_ITEM_INDEX ] , map , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_MapVoteEndForward ) ;
Call_PushString ( map ) ;
Call_Finish ( ) ;
if ( strcmp ( map , VOTE_EXTEND , false ) = = 0 )
{
g_Extends + + ;
new time ;
if ( GetMapTimeLimit ( time ) )
{
if ( time > 0 )
{
ExtendMapTimeLimit ( GetConVarInt ( g_Cvar_ExtendTimeStep ) * 60 ) ;
}
}
if ( g_Cvar_Winlimit ! = INVALID_HANDLE )
{
new winlimit = GetConVarInt ( g_Cvar_Winlimit ) ;
if ( winlimit )
{
SetConVarInt ( g_Cvar_Winlimit , winlimit + GetConVarInt ( g_Cvar_ExtendRoundStep ) ) ;
}
}
if ( g_Cvar_Maxrounds ! = INVALID_HANDLE )
{
new maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
if ( maxrounds )
{
SetConVarInt ( g_Cvar_Maxrounds , maxrounds + GetConVarInt ( g_Cvar_ExtendRoundStep ) ) ;
}
}
if ( g_Cvar_Fraglimit ! = INVALID_HANDLE )
{
new fraglimit = GetConVarInt ( g_Cvar_Fraglimit ) ;
if ( fraglimit )
{
SetConVarInt ( g_Cvar_Fraglimit , fraglimit + GetConVarInt ( g_Cvar_ExtendFragStep ) ) ;
}
}
if ( g_NativeVotes )
{
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 ;
CreateNextVote ( ) ;
SetupTimeleftTimer ( ) ;
}
else if ( strcmp ( map , VOTE_DONTCHANGE , false ) = = 0 )
{
if ( g_NativeVotes )
{
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 ;
CreateNextVote ( ) ;
SetupTimeleftTimer ( ) ;
}
else
{
if ( g_ChangeTime = = MapChange_MapEnd )
{
SetNextMap ( map ) ;
if ( g_NativeVotes )
{
NativeVotes_DisplayPass ( menu , map ) ;
}
}
else if ( g_ChangeTime = = MapChange_Instant )
{
new Handle : data ;
CreateDataTimer ( 4.0 , Timer_ChangeMap , data ) ;
WritePackString ( data , map ) ;
g_ChangeMapInProgress = false ;
if ( g_NativeVotes )
{
NativeVotes_DisplayPassEx ( menu , NativeVotesPass_ChgLevel , map ) ;
}
}
else // MapChange_RoundEnd
{
SetNextMap ( map ) ;
g_ChangeMapAtRoundEnd = true ;
if ( g_NativeVotes )
{
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 ) ;
}
}
public Handler_MapVoteFinished ( Handle : menu ,
num_votes ,
num_clients ,
const client_info [ ] [ 2 ] ,
num_items ,
const item_info [ ] [ 2 ] )
{
// Implement revote logic - Only run this` block if revotes are enabled and this isn't the last revote
if ( GetConVarBool ( g_Cvar_RunOff ) & & num_items > 1 & & g_RunoffCount < GetConVarInt ( g_Cvar_MaxRunOffs ) )
{
g_RunoffCount + + ;
new highest_votes = item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ;
new required_percent = GetConVarInt ( g_Cvar_RunOffPercent ) ;
new required_votes = RoundToCeil ( float ( num_votes ) * float ( required_percent ) / 100 ) ;
if ( highest_votes = = item_info [ 1 ] [ VOTEINFO_ITEM_VOTES ] )
{
g_HasVoteStarted = false ;
//Revote is needed
new arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
new Handle : mapList = CreateArray ( arraySize ) ;
for ( new i = 0 ; i < num_items ; i + + )
{
if ( item_info [ i ] [ VOTEINFO_ITEM_VOTES ] = = highest_votes )
{
decl String : map [ PLATFORM_MAX_PATH ] ;
GetMapItem ( menu , item_info [ i ] [ VOTEINFO_ITEM_INDEX ] , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( mapList , map ) ;
}
else
{
break ;
}
}
if ( g_NativeVotes )
{
NativeVotes_DisplayFail ( menu , NativeVotesFail_NotEnoughVotes ) ;
}
CPrintToChatAll ( " [MCE] %t " , " Tie Vote " , GetArraySize ( mapList ) ) ;
SetupWarningTimer ( WarningType_Revote , MapChange : g_ChangeTime , mapList ) ;
return ;
}
else if ( highest_votes < required_votes )
{
g_HasVoteStarted = false ;
//Revote is needed
new arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
new Handle : mapList = CreateArray ( arraySize ) ;
decl String : map1 [ PLATFORM_MAX_PATH ] ;
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
for ( new i = 1 ; i < num_items ; i + + )
{
if ( GetArraySize ( mapList ) < 2 | | item_info [ i ] [ VOTEINFO_ITEM_VOTES ] = = item_info [ i - 1 ] [ VOTEINFO_ITEM_VOTES ] )
{
decl String : map [ PLATFORM_MAX_PATH ] ;
GetMapItem ( menu , item_info [ i ] [ VOTEINFO_ITEM_INDEX ] , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( mapList , map ) ;
}
else
{
break ;
}
}
if ( g_NativeVotes )
{
NativeVotes_DisplayFail ( menu , NativeVotesFail_NotEnoughVotes ) ;
}
CPrintToChatAll ( " [MCE] %t " , " Revote Is Needed " , required_percent ) ;
SetupWarningTimer ( WarningType_Revote , MapChange : g_ChangeTime , mapList ) ;
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
public Handler_MapVoteMenu ( Handle : menu , MenuAction : action , param1 , param2 )
{
switch ( action )
{
case MenuAction_End :
{
g_VoteMenu = INVALID_HANDLE ;
if ( g_NativeVotes )
{
NativeVotes_Close ( menu ) ;
}
else
{
CloseHandle ( menu ) ;
}
}
case MenuAction_Display :
{
// NativeVotes uses the standard TF2/CSGO vote screen
if ( ! g_NativeVotes )
{
decl String : buffer [ 255 ] ;
Format ( buffer , sizeof ( buffer ) , " %T " , " Vote Nextmap " , param1 ) ;
new Handle : panel = Handle : param2 ;
SetPanelTitle ( panel , buffer ) ;
}
}
case MenuAction_DisplayItem :
{
new String : map [ PLATFORM_MAX_PATH ] ;
new String : buffer [ 255 ] ;
new mark = GetConVarInt ( g_Cvar_MarkCustomMaps ) ;
if ( g_NativeVotes )
{
NativeVotes_GetItem ( menu , param2 , map , PLATFORM_MAX_PATH ) ;
}
else
{
GetMenuItem ( menu , param2 , map , PLATFORM_MAX_PATH ) ;
}
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 ) ;
}
}
if ( buffer [ 0 ] ! = '\0' )
{
if ( g_NativeVotes )
{
NativeVotes_RedrawVoteItem ( buffer ) ;
return _ : Plugin_Continue ;
}
else
{
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 ) )
{
new count ;
if ( g_NativeVotes )
{
count = NativeVotes_GetItemCount ( menu ) ;
}
else
{
count = GetMenuItemCount ( menu ) ;
}
decl item ;
decl String : map [ PLATFORM_MAX_PATH ] ;
do
{
new startInt = 0 ;
if ( ! g_NativeVotes & & g_BlockedSlots )
{
if ( g_AddNoVote )
{
startInt = 2 ;
}
else
{
startInt = 3 ;
}
}
item = GetRandomInt ( startInt , count - 1 ) ;
if ( g_NativeVotes )
{
NativeVotes_GetItem ( menu , item , map , PLATFORM_MAX_PATH ) ;
}
else
{
GetMenuItem ( menu , item , map , PLATFORM_MAX_PATH ) ;
}
}
while ( strcmp ( map , VOTE_EXTEND , false ) = = 0 ) ;
SetNextMap ( map ) ;
g_MapVoteCompleted = true ;
if ( g_NativeVotes )
{
NativeVotes_DisplayPass ( menu , map ) ;
}
}
else if ( g_NativeVotes )
{
new NativeVotesFailType : reason = NativeVotesFail_Generic ;
if ( param1 = = VoteCancel_NoVotes )
{
reason = NativeVotesFail_NotEnoughVotes ;
}
NativeVotes_DisplayFail ( menu , reason ) ;
}
else
{
// We were actually cancelled. I guess we do nothing.
}
g_HasVoteStarted = false ;
}
}
return 0 ;
}
public Action : Timer_ChangeMap ( Handle : hTimer , Handle : dp )
{
g_ChangeMapInProgress = false ;
new String : 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 , String : str [ ] )
{
new index = FindStringInArray ( array , str ) ;
if ( index ! = - 1 )
{
RemoveFromArray ( array , index ) ;
return true ;
}
return false ;
}
CreateNextVote ( )
{
assert ( g_NextMapList )
ClearArray ( g_NextMapList ) ;
decl String : map [ PLATFORM_MAX_PATH ] ;
new Handle : tempMaps = CloneArray ( g_MapList ) ;
GetCurrentMap ( map , PLATFORM_MAX_PATH ) ;
RemoveStringFromArray ( tempMaps , map ) ;
if ( GetConVarInt ( g_Cvar_ExcludeMaps ) & & GetArraySize ( tempMaps ) > GetConVarInt ( g_Cvar_ExcludeMaps ) )
{
for ( new i = 0 ; i < GetArraySize ( g_OldMapList ) ; i + + )
{
GetArrayString ( g_OldMapList , i , map , PLATFORM_MAX_PATH ) ;
RemoveStringFromArray ( tempMaps , map ) ;
}
}
new voteSize = GetVoteSize ( ) ;
new limit = ( voteSize < GetArraySize ( tempMaps ) ? voteSize : GetArraySize ( tempMaps ) ) ;
for ( new i = 0 ; i < limit ; i + + )
{
new b = GetRandomInt ( 0 , GetArraySize ( tempMaps ) - 1 ) ;
GetArrayString ( tempMaps , b , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( g_NextMapList , map ) ;
RemoveFromArray ( tempMaps , b ) ;
}
CloseHandle ( tempMaps ) ;
}
bool : CanVoteStart ( )
{
if ( g_WaitingForVote | | g_HasVoteStarted )
{
return false ;
}
return true ;
}
NominateResult : InternalNominateMap ( String : map [ ] , bool : force , owner )
{
if ( ! IsMapValid ( map ) )
{
return Nominate_InvalidMap ;
}
/* Map already in the vote */
if ( FindStringInArray ( g_NominateList , map ) ! = - 1 )
{
return Nominate_AlreadyInVote ;
}
new index ;
/* Look to replace an existing nomination by this client - Nominations made with owner = 0 aren't replaced */
if ( owner & & ( ( index = FindValueInArray ( g_NominateOwners , owner ) ) ! = - 1 ) )
{
new String : oldmap [ PLATFORM_MAX_PATH ] ;
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. */
if ( g_NominateCount > = GetVoteSize ( ) & & ! force )
{
return Nominate_VoteFull ;
}
PushArrayString ( g_NominateList , map ) ;
PushArrayCell ( g_NominateOwners , owner ) ;
g_NominateCount + + ;
while ( GetArraySize ( g_NominateList ) > GetVoteSize ( ) )
{
new String : oldmap [ PLATFORM_MAX_PATH ] ;
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 ) ;
}
return Nominate_Added ;
}
/* Add natives to allow nominate and initiate vote to be call */
/* native bool:NominateMap(const String:map[], bool:force, &NominateError:error); */
public Native_NominateMap ( Handle : plugin , numParams )
{
new len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
{
return false ;
}
new String : map [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
return _ : InternalNominateMap ( map , GetNativeCell ( 2 ) , GetNativeCell ( 3 ) ) ;
}
bool : InternalRemoveNominationByMap ( String : map [ ] )
{
for ( new i = 0 ; i < GetArraySize ( g_NominateList ) ; i + + )
{
new String : oldmap [ PLATFORM_MAX_PATH ] ;
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 ;
}
/* native bool:RemoveNominationByMap(const String:map[]); */
public Native_RemoveNominationByMap ( Handle : plugin , numParams )
{
new len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
{
return false ;
}
new String : map [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
return _ : InternalRemoveNominationByMap ( map ) ;
}
bool : InternalRemoveNominationByOwner ( owner )
{
new index ;
if ( owner & & ( ( index = FindValueInArray ( g_NominateOwners , owner ) ) ! = - 1 ) )
{
new String : oldmap [ PLATFORM_MAX_PATH ] ;
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 ;
}
/* native bool:RemoveNominationByOwner(owner); */
public Native_RemoveNominationByOwner ( Handle : plugin , numParams )
{
return _ : InternalRemoveNominationByOwner ( GetNativeCell ( 1 ) ) ;
}
/* native InitiateMapChooserVote(); */
public Native_InitiateVote ( Handle : plugin , numParams )
{
new MapChange : when = MapChange : GetNativeCell ( 1 ) ;
new Handle : inputarray = Handle : GetNativeCell ( 2 ) ;
LogAction ( - 1 , - 1 , " Starting map vote because outside request " ) ;
SetupWarningTimer ( WarningType_Vote , when , inputarray ) ;
//InitiateVote(when, inputarray);
}
public Native_CanVoteStart ( Handle : plugin , numParams )
{
return CanVoteStart ( ) ;
}
public Native_CheckVoteDone ( Handle : plugin , numParams )
{
return g_MapVoteCompleted ;
}
public Native_EndOfMapVoteEnabled ( Handle : plugin , numParams )
{
return GetConVarBool ( g_Cvar_EndOfMapVote ) ;
}
public Native_GetExcludeMapList ( Handle : plugin , numParams )
{
new Handle : array = Handle : GetNativeCell ( 1 ) ;
if ( array = = INVALID_HANDLE )
{
return ;
}
new size = GetArraySize ( g_OldMapList ) ;
decl String : map [ PLATFORM_MAX_PATH ] ;
for ( new i = 0 ; i < size ; i + + )
{
GetArrayString ( g_OldMapList , i , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( array , map ) ;
}
return ;
}
public Native_GetNominatedMapList ( Handle : plugin , numParams )
{
new Handle : maparray = Handle : GetNativeCell ( 1 ) ;
new Handle : ownerarray = Handle : GetNativeCell ( 2 ) ;
if ( maparray = = INVALID_HANDLE )
return ;
decl String : map [ PLATFORM_MAX_PATH ] ;
for ( new i = 0 ; i < GetArraySize ( g_NominateList ) ; i + + )
{
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 )
{
new index = GetArrayCell ( g_NominateOwners , i ) ;
PushArrayCell ( ownerarray , index ) ;
}
}
return ;
}
// Functions new to Mapchooser Extended
/ *
SetupWarningTimer ( MapChange : when = MapChange_MapEnd , Handle : mapList = INVALID_HANDLE )
{
if ( ! IsMapEndVoteAllowed ( ) )
{
return ;
}
Call_StartForward ( g_MapVoteWarningStartForward ) ;
Call_Finish ( ) ;
new Handle : data ;
g_WarningTimer = CreateDataTimer ( 1.0 , Timer_StartMapVote , data , TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT ) ;
WritePackCell ( data , GetConVarInt ( g_Cvar_WarningTime ) ) ;
WritePackString ( data , " Vote Warning " ) ;
WritePackCell ( data , _ : when ) ;
WritePackCell ( data , _ : mapList ) ;
}
SetupRunoffTimer ( MapChange : when , Handle : mapList )
{
if ( ! IsMapEndVoteAllowed ( ) )
{
return ;
}
Call_StartForward ( g_MapVoteRunoffStartForward ) ;
Call_Finish ( ) ;
new Handle : data ;
g_WarningTimer = CreateDataTimer ( 1.0 , Timer_StartMapVote , data , TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT ) ;
WritePackCell ( data , GetConVarInt ( g_Cvar_RunOffWarningTime ) ) ;
WritePackString ( data , " Revote Warning " ) ;
WritePackCell ( data , _ : when ) ;
WritePackCell ( data , _ : mapList ) ;
}
* /
stock 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 ;
}
new bool : interrupted = false ;
if ( g_WarningInProgress & & g_WarningTimer ! = INVALID_HANDLE )
{
interrupted = true ;
KillTimer ( g_WarningTimer ) ;
}
g_WarningInProgress = true ;
decl Handle : forwardVote ;
decl Handle : cvarTime ;
decl String : translationKey [ 64 ] ;
switch ( type )
{
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 " ) ;
}
}
if ( ! interrupted )
{
Call_StartForward ( forwardVote ) ;
Call_Finish ( ) ;
}
new 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 , _ : when ) ;
WritePackCell ( data , _ : mapList ) ;
ResetPack ( data ) ;
}
stock 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 ;
}
else
{
return true ;
}
}
public Native_IsMapOfficial ( Handle : plugin , numParams )
{
new len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
{
return false ;
}
new String : map [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
return InternalIsMapOfficial ( map ) ;
}
bool : InternalIsMapOfficial ( const String : mapname [ ] )
{
new officialMapIndex = FindStringInArray ( g_OfficialList , mapname ) ;
return ( officialMapIndex > - 1 ) ;
}
public Native_IsWarningTimer ( Handle : plugin , numParams )
{
return g_WarningInProgress ;
}
public Native_CanNominate ( Handle : plugin , numParams )
{
if ( g_HasVoteStarted )
{
return _ : CanNominate_No_VoteInProgress ;
}
if ( g_MapVoteCompleted )
{
return _ : CanNominate_No_VoteComplete ;
}
if ( g_NominateCount > = GetVoteSize ( ) )
{
return _ : CanNominate_No_VoteFull ;
}
return _ : CanNominate_Yes ;
}
public Native_ExcludeMap ( Handle : plugin , numParams )
{
new len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
{
return false ;
}
new String : map [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
PushArrayString ( g_OldMapList , map ) ;
2016-04-26 12:36:03 +02:00
if ( GetArraySize ( g_OldMapList ) > GetConVarInt ( g_Cvar_ExcludeMaps ) )
{
RemoveFromArray ( g_OldMapList , 0 ) ;
}
2016-01-19 23:57:32 +01:00
return true ;
}
stock AddMapItem ( const String : map [ ] )
{
if ( g_NativeVotes )
{
NativeVotes_AddItem ( g_VoteMenu , map , map ) ;
}
else
{
AddMenuItem ( g_VoteMenu , map , map ) ;
}
}
stock GetMapItem ( Handle : menu , position , String : map [ ] , mapLen )
{
if ( g_NativeVotes )
{
NativeVotes_GetItem ( menu , position , map , mapLen ) ;
}
else
{
GetMenuItem ( menu , position , map , mapLen ) ;
}
}
stock 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 ) )
{
if ( g_NativeVotes )
{
// Built-in votes don't have "Don't Change", send Extend instead
NativeVotes_AddItem ( menu , VOTE_DONTCHANGE , " Don't Change " ) ;
}
else
{
AddMenuItem ( menu , VOTE_DONTCHANGE , " Don't Change " ) ;
}
}
else if ( GetConVarBool ( g_Cvar_Extend ) & & g_Extends < GetConVarInt ( g_Cvar_Extend ) )
{
if ( g_NativeVotes )
{
NativeVotes_AddItem ( menu , VOTE_EXTEND , " Extend Map " ) ;
}
else
{
AddMenuItem ( menu , VOTE_EXTEND , " Extend Map " ) ;
}
}
}
// Using this stock REQUIRES you to add the following to AskPluginLoad2:
// MarkNativeAsOptional("GetEngineVersion");
stock EngineVersion : GetEngineVersionCompat ( )
{
new EngineVersion : version ;
if ( GetFeatureStatus ( FeatureType_Native , " GetEngineVersion " ) ! = FeatureStatus_Available )
{
new sdkVersion = GuessSDKVersion ( ) ;
switch ( sdkVersion )
{
case SOURCE_SDK_ORIGINAL :
{
version = Engine_Original ;
}
case SOURCE_SDK_DARKMESSIAH :
{
version = Engine_DarkMessiah ;
}
case SOURCE_SDK_EPISODE1 :
{
version = Engine_SourceSDK2006 ;
}
case SOURCE_SDK_EPISODE2 :
{
version = Engine_SourceSDK2007 ;
}
case SOURCE_SDK_BLOODYGOODTIME :
{
version = Engine_BloodyGoodTime ;
}
case SOURCE_SDK_EYE :
{
version = Engine_EYE ;
}
case SOURCE_SDK_CSS :
{
version = Engine_CSS ;
}
case SOURCE_SDK_EPISODE2VALVE :
{
decl String : gameFolder [ PLATFORM_MAX_PATH ] ;
GetGameFolderName ( gameFolder , PLATFORM_MAX_PATH ) ;
if ( StrEqual ( gameFolder , " dod " , false ) )
{
version = Engine_DODS ;
}
else if ( StrEqual ( gameFolder , " hl2mp " , false ) )
{
version = Engine_HL2DM ;
}
else
{
version = Engine_TF2 ;
}
}
case SOURCE_SDK_LEFT4DEAD :
{
version = Engine_Left4Dead ;
}
case SOURCE_SDK_LEFT4DEAD2 :
{
decl String : gameFolder [ PLATFORM_MAX_PATH ] ;
GetGameFolderName ( gameFolder , PLATFORM_MAX_PATH ) ;
if ( StrEqual ( gameFolder , " nd " , false ) )
{
version = Engine_NuclearDawn ;
}
else
{
version = Engine_Left4Dead2 ;
}
}
case SOURCE_SDK_ALIENSWARM :
{
version = Engine_AlienSwarm ;
}
case SOURCE_SDK_CSGO :
{
version = Engine_CSGO ;
}
default :
{
version = Engine_Unknown ;
}
}
}
else
{
version = GetEngineVersion ( ) ;
}
return version ;
}
GetVoteSize ( )
{
new voteSize = GetConVarInt ( g_Cvar_IncludeMaps ) ;
// New in 1.9.5 to let us bump up the included maps count
if ( g_NativeVotes )
{
new max = NativeVotes_GetMaxItems ( ) ;
if ( max < voteSize )
{
voteSize = max ;
}
}
return voteSize ;
2016-01-06 02:11:56 +01:00
}