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>
2017-02-26 00:16:12 +01:00
# include <mapchooser_extended>
2023-04-09 13:57:09 +02:00
# include <unloze_playtime>
2016-01-19 23:57:32 +01:00
# include <nextmap>
# include <sdktools>
2017-02-26 00:16:12 +01:00
# include <multicolors>
2023-03-13 20:00:35 +01:00
# include <PlayerManager>
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
2019-12-22 14:10:01 +01:00
# define MCE_VERSION "1.3.1"
2016-01-19 23:57:32 +01:00
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 " ,
2019-08-14 15:21:24 +02:00
author = " Powerlord, Zuko, BotoX and AlliedModders LLC " ,
2016-01-19 23:57:32 +01:00
description = " Automated Map Voting with Extensions " ,
version = MCE_VERSION ,
2019-08-14 15:21:24 +02:00
url = " "
2016-01-19 23:57:32 +01:00
} ;
/* 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_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 ;
2019-09-18 12:36:08 +02:00
ConVar g_Cvar_ExcludeMapsTime ;
2016-08-11 17:48:20 +02:00
ConVar g_Cvar_IncludeMaps ;
2018-08-10 12:43:49 +02:00
ConVar g_Cvar_IncludeMapsReserved ;
2016-08-11 17:48:20 +02:00
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 ;
2023-01-27 21:07:48 +01:00
Handle g_NominateList [ MAXPLAYERS + 1 ] ;
2016-08-11 17:48:20 +02:00
Handle g_NominateOwners = INVALID_HANDLE ;
StringMap g_OldMapList ;
2019-09-18 12:36:08 +02:00
StringMap g_TimeMapList ;
2016-08-11 17:48:20 +02:00
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 ;
2018-08-10 12:43:49 +02:00
int g_NominateReservedCount = 0 ;
2016-08-11 17:48:20 +02:00
MapChange g_ChangeTime ;
2023-03-13 20:00:35 +01:00
//check if autismbot
bool is_bot_player [ MAXPLAYERS + 1 ] ;
2016-08-11 17:48:20 +02:00
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_TimerLocation ;
ConVar g_Cvar_ExtendPosition ;
ConVar g_Cvar_MarkCustomMaps ;
ConVar g_Cvar_RandomizeNominations ;
ConVar g_Cvar_HideTimer ;
ConVar g_Cvar_NoVoteOption ;
2019-08-14 15:21:24 +02:00
ConVar g_Cvar_ShufflePerClient ;
2019-08-17 14:31:28 +02:00
ConVar g_Cvar_NoRestrictionTimeframeEnable ;
ConVar g_Cvar_NoRestrictionTimeframeMinTime ;
ConVar g_Cvar_NoRestrictionTimeframeMaxTime ;
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 ;
char g_GameModName [ 64 ] ;
bool g_WarningInProgress = false ;
bool g_AddNoVote = false ;
2019-08-18 23:08:23 +02:00
bool g_SaveCDOnMapEnd = true ;
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
2023-01-27 21:07:48 +01:00
//call forward to reset all nominations
public void OnPluginEnd ( )
{
for ( int i = 0 ; i < MaxClients ; i + + )
{
int index = FindValueInArray ( g_NominateOwners , i ) ;
if ( index = = - 1 ) continue ;
for ( int j = 0 ; j < GetArraySize ( g_NominateList [ i ] ) ; j + + )
{
char oldmap [ PLATFORM_MAX_PATH ] ;
Call_StartForward ( g_NominationsResetForward ) ;
GetArrayString ( g_NominateList [ i ] , j , oldmap , PLATFORM_MAX_PATH ) ;
Call_PushString ( oldmap ) ;
Call_Finish ( ) ;
}
}
}
2016-08-11 17:48:20 +02:00
public void OnPluginStart ( )
2016-01-19 23:57:32 +01:00
{
2023-01-27 21:07:48 +01:00
LoadTranslations ( " mapchooser_extended.phrases " ) ;
LoadTranslations ( " basevotes.phrases " ) ;
LoadTranslations ( " common.phrases " ) ;
int arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
g_MapList = CreateArray ( arraySize ) ;
g_NominateOwners = CreateArray ( 1 ) ;
g_OldMapList = new StringMap ( ) ;
g_TimeMapList = new StringMap ( ) ;
g_NextMapList = CreateArray ( arraySize ) ;
g_OfficialList = CreateArray ( arraySize ) ;
for ( int i = 0 ; i < MaxClients ; i + + )
{
g_NominateList [ i ] = CreateArray ( arraySize ) ;
}
GetGameFolderName ( g_GameModName , sizeof ( g_GameModName ) ) ;
g_Cvar_EndOfMapVote = CreateConVar ( " mce_endvote " , " 1 " , " Specifies if MapChooser should run an end of map vote " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_StartTime = CreateConVar ( " mce_starttime " , " 10.0 " , " Specifies when to start the vote based on time remaining. " , _ , true , 1.0 ) ;
g_Cvar_StartRounds = CreateConVar ( " mce_startround " , " 2.0 " , " Specifies when to start the vote based on rounds remaining. Use 0 on DoD:S, CS:S, and TF2 to start vote during bonus round time " , _ , true , 0.0 ) ;
g_Cvar_StartFrags = CreateConVar ( " mce_startfrags " , " 5.0 " , " Specifies when to start the vote base on frags remaining. " , _ , true , 1.0 ) ;
g_Cvar_ExtendTimeStep = CreateConVar ( " mce_extend_timestep " , " 15 " , " Specifies how much many more minutes each extension makes " , _ , true , 5.0 ) ;
g_Cvar_ExtendRoundStep = CreateConVar ( " mce_extend_roundstep " , " 5 " , " Specifies how many more rounds each extension makes " , _ , true , 1.0 ) ;
g_Cvar_ExtendFragStep = CreateConVar ( " mce_extend_fragstep " , " 10 " , " Specifies how many more frags are allowed when map is extended. " , _ , true , 5.0 ) ;
g_Cvar_ExcludeMaps = CreateConVar ( " mce_exclude " , " 5 " , " Specifies how many past maps to exclude from the vote. " , _ , true , 0.0 ) ;
g_Cvar_ExcludeMapsTime = CreateConVar ( " mce_exclude_time " , " 5h " , " Specifies how long in minutes an old map is excluded from the vote. " ) ;
g_Cvar_IncludeMaps = CreateConVar ( " mce_include " , " 5 " , " Specifies how many maps to include in the vote. " , _ , true , 2.0 , true , 7.0 ) ;
g_Cvar_IncludeMapsReserved = CreateConVar ( " mce_include_reserved " , " 2 " , " Specifies how many private/random maps to include in the vote. " , _ , true , 0.0 , true , 5.0 ) ;
g_Cvar_NoVoteMode = CreateConVar ( " mce_novote " , " 1 " , " Specifies whether or not MapChooser should pick a map if no votes are received. " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_Extend = CreateConVar ( " mce_extend " , " 0 " , " Number of extensions allowed each map. " , _ , true , 0.0 ) ;
g_Cvar_DontChange = CreateConVar ( " mce_dontchange " , " 1 " , " Specifies if a 'Don't Change option should be added to early votes " , _ , true , 0.0 ) ;
g_Cvar_VoteDuration = CreateConVar ( " mce_voteduration " , " 20 " , " Specifies how long the mapvote should be available for. " , _ , true , 5.0 ) ;
// MapChooser Extended cvars
CreateConVar ( " mce_version " , MCE_VERSION , " MapChooser Extended Version " , FCVAR_SPONLY | FCVAR_NOTIFY | FCVAR_DONTRECORD ) ;
g_Cvar_RunOff = CreateConVar ( " mce_runoff " , " 1 " , " Hold run off votes if winning choice has less than a certain percentage of votes " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_RunOffPercent = CreateConVar ( " mce_runoffpercent " , " 50 " , " If winning choice has less than this percent of votes, hold a runoff " , _ , true , 0.0 , true , 100.0 ) ;
g_Cvar_BlockSlots = CreateConVar ( " mce_blockslots " , " 0 " , " Block slots to prevent accidental votes. Only applies when Voice Command style menus are in use. " , _ , true , 0.0 , true , 1.0 ) ;
//g_Cvar_BlockSlotsCount = CreateConVar("mce_blockslots_count", "2", "Number of slots to block.", _, true, 1.0, true, 3.0);
g_Cvar_MaxRunOffs = CreateConVar ( " mce_maxrunoffs " , " 1 " , " Number of run off votes allowed each map. " , _ , true , 0.0 ) ;
g_Cvar_StartTimePercent = CreateConVar ( " mce_start_percent " , " 35.0 " , " Specifies when to start the vote based on percents. " , _ , true , 0.0 , true , 100.0 ) ;
g_Cvar_StartTimePercentEnable = CreateConVar ( " mce_start_percent_enable " , " 0 " , " Enable or Disable percentage calculations when to start vote. " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_WarningTime = CreateConVar ( " mce_warningtime " , " 15.0 " , " Warning time in seconds. " , _ , true , 0.0 , true , 60.0 ) ;
g_Cvar_RunOffWarningTime = CreateConVar ( " mce_runoffvotewarningtime " , " 5.0 " , " Warning time for runoff vote in seconds. " , _ , true , 0.0 , true , 30.0 ) ;
g_Cvar_TimerLocation = CreateConVar ( " mce_warningtimerlocation " , " 0 " , " Location for the warning timer text. 0 is HintBox, 1 is Center text, 2 is Chat. Defaults to HintBox. " , _ , true , 0.0 , true , 2.0 ) ;
g_Cvar_MarkCustomMaps = CreateConVar ( " mce_markcustommaps " , " 1 " , " Mark custom maps in the vote list. 0 = Disabled, 1 = Mark with *, 2 = Mark with phrase. " , _ , true , 0.0 , true , 2.0 ) ;
g_Cvar_ExtendPosition = CreateConVar ( " mce_extendposition " , " 0 " , " Position of Extend/Dont Change options. 0 = at end, 1 = at start. " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_RandomizeNominations = CreateConVar ( " mce_randomizeorder " , " 0 " , " Randomize map order? " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_HideTimer = CreateConVar ( " mce_hidetimer " , " 0 " , " Hide the MapChooser Extended warning timer " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_NoVoteOption = CreateConVar ( " mce_addnovote " , " 1 " , " Add \" No Vote \" to vote menu? " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_ShufflePerClient = CreateConVar ( " mce_shuffle_per_client " , " 1 " , " Random shuffle map vote menu per client? " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_NoRestrictionTimeframeEnable = CreateConVar ( " mce_no_restriction_timeframe_enable " , " 1 " , " Enable timeframe where all nomination restrictions and cooldowns are disabled? " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_NoRestrictionTimeframeMinTime = CreateConVar ( " mce_no_restriction_timeframe_mintime " , " 0100 " , " Start of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM) " , _ , true , 0000.0 , true , 2359.0 ) ;
g_Cvar_NoRestrictionTimeframeMaxTime = CreateConVar ( " mce_no_restriction_timeframe_maxtime " , " 0700 " , " End of the timeframe where all nomination restrictions and cooldowns are disabled (Format: HHMM) " , _ , true , 0000.0 , true , 2359.0 ) ;
RegAdminCmd ( " sm_mapvote " , Command_Mapvote , ADMFLAG_CHANGEMAP , " sm_mapvote - Forces MapChooser to attempt to run a map vote now. " ) ;
RegAdminCmd ( " sm_setnextmap " , Command_SetNextmap , ADMFLAG_CHANGEMAP , " sm_setnextmap <map> " ) ;
// Mapchooser Extended Commands
RegAdminCmd ( " mce_reload_maplist " , Command_ReloadMaps , ADMFLAG_CHANGEMAP , " mce_reload_maplist - Reload the Official Maplist file. " ) ;
RegConsoleCmd ( " sm_extends " , Command_ExtendsLeft , " sm_extends - Shows how many extends are left on the current map. " ) ;
RegConsoleCmd ( " sm_extendsleft " , Command_ExtendsLeft , " sm_extendsleft - Shows how many extends are left on the current map. " ) ;
2023-04-09 13:57:09 +02:00
RegConsoleCmd ( " sm_houravg " , Command_hours_average , " Prints in the chat what the current hour average of each player accumulated is. " ) ;
RegConsoleCmd ( " sm_avghour " , Command_hours_average , " Prints in the chat what the current hour average of each player accumulated is. " ) ;
2023-01-27 21:07:48 +01:00
g_Cvar_Winlimit = FindConVar ( " mp_winlimit " ) ;
g_Cvar_Maxrounds = FindConVar ( " mp_maxrounds " ) ;
g_Cvar_Fraglimit = FindConVar ( " mp_fraglimit " ) ;
EngineVersion version = GetEngineVersion ( ) ;
static char mapListPath [ PLATFORM_MAX_PATH ] ;
BuildPath ( Path_SM , mapListPath , PLATFORM_MAX_PATH , " configs/mapchooser_extended/maps/%s.txt " , g_GameModName ) ;
SetMapListCompatBind ( " official " , mapListPath ) ;
switch ( version )
{
case Engine_TF2 :
{
g_Cvar_Bonusroundtime = FindConVar ( " mp_bonusroundtime " ) ;
}
case Engine_CSGO :
{
g_Cvar_GameType = FindConVar ( " game_type " ) ;
g_Cvar_GameMode = FindConVar ( " game_mode " ) ;
g_Cvar_Bonusroundtime = FindConVar ( " mp_round_restart_delay " ) ;
}
case Engine_DODS :
{
g_Cvar_Bonusroundtime = FindConVar ( " dod_bonusroundtime " ) ;
}
case Engine_CSS :
{
g_Cvar_Bonusroundtime = FindConVar ( " mp_round_restart_delay " ) ;
}
default :
{
g_Cvar_Bonusroundtime = FindConVar ( " mp_bonusroundtime " ) ;
}
}
switch ( version )
{
case Engine_TF2 :
{
HookEvent ( " teamplay_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 ) ;
}
case Engine_DODS :
{
HookEvent ( " dod_round_win " , Event_RoundEnd ) ;
}
default :
{
HookEvent ( " round_end " , Event_RoundEnd ) ;
}
}
HookEvent ( " player_death " , Event_PlayerDeath ) ;
AutoExecConfig ( true , " mapchooser_extended " ) ;
//Change the mp_bonusroundtime max so that we have time to display the vote
//If you display a vote during bonus time good defaults are 17 vote duration and 19 mp_bonustime
SetConVarBounds ( g_Cvar_Bonusroundtime , ConVarBound_Upper , true , 30.0 ) ;
g_NominationsResetForward = CreateGlobalForward ( " OnNominationRemoved " , ET_Ignore , Param_String , Param_Cell ) ;
g_MapVoteStartedForward = CreateGlobalForward ( " OnMapVoteStarted " , ET_Ignore ) ;
//MapChooser Extended Forwards
g_MapVoteStartForward = CreateGlobalForward ( " OnMapVoteStart " , ET_Ignore ) ; // Deprecated
g_MapVoteEndForward = CreateGlobalForward ( " OnMapVoteEnd " , ET_Ignore , Param_String ) ;
g_MapVoteWarningStartForward = CreateGlobalForward ( " OnMapVoteWarningStart " , ET_Ignore ) ;
g_MapVoteWarningTickForward = CreateGlobalForward ( " OnMapVoteWarningTick " , ET_Ignore , Param_Cell ) ;
g_MapVoteRunoffStartForward = CreateGlobalForward ( " OnMapVoteRunnoffWarningStart " , ET_Ignore ) ;
InternalRestoreMapCooldowns ( ) ;
2016-01-19 23:57:32 +01:00
}
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
{
2023-04-09 13:57:09 +02:00
if ( LibraryExists ( " mapchooser " ) )
{
strcopy ( error , err_max , " MapChooser already loaded, aborting. " ) ;
return APLRes_Failure ;
}
2016-01-19 23:57:32 +01:00
2023-04-09 13:57:09 +02:00
RegPluginLibrary ( " mapchooser " ) ;
MarkNativeAsOptional ( " GetEngineVersion " ) ;
CreateNative ( " NominateMap " , Native_NominateMap ) ;
CreateNative ( " RemoveNominationByMap " , Native_RemoveNominationByMap ) ;
CreateNative ( " RemoveNominationByOwner " , Native_RemoveNominationByOwner ) ;
CreateNative ( " InitiateMapChooserVote " , Native_InitiateVote ) ;
CreateNative ( " CanMapChooserStartVote " , Native_CanVoteStart ) ;
CreateNative ( " HasEndOfMapVoteFinished " , Native_CheckVoteDone ) ;
CreateNative ( " GetExcludeMapList " , Native_GetExcludeMapList ) ;
CreateNative ( " GetNominatedMapList " , Native_GetNominatedMapList ) ;
CreateNative ( " EndOfMapVoteEnabled " , Native_EndOfMapVoteEnabled ) ;
// MapChooser Extended natives
CreateNative ( " IsMapOfficial " , Native_IsMapOfficial ) ;
CreateNative ( " CanNominate " , Native_CanNominate ) ;
CreateNative ( " ExcludeMap " , Native_ExcludeMap ) ;
CreateNative ( " ExcludeMapTime " , Native_ExcludeMapTime ) ;
CreateNative ( " GetMapCooldown " , Native_GetMapCooldown ) ;
CreateNative ( " GetMapCooldownTime " , Native_GetMapCooldownTime ) ;
CreateNative ( " GetMapMinTime " , Native_GetMapMinTime ) ;
CreateNative ( " GetMapMaxTime " , Native_GetMapMaxTime ) ;
CreateNative ( " GetMapMinPlayers " , Native_GetMapMinPlayers ) ;
CreateNative ( " GetMapMaxPlayers " , Native_GetMapMaxPlayers ) ;
CreateNative ( " GetMapTimeRestriction " , Native_GetMapTimeRestriction ) ;
CreateNative ( " GetMapPlayerRestriction " , Native_GetMapPlayerRestriction ) ;
CreateNative ( " GetMapGroups " , Native_GetMapGroups ) ;
CreateNative ( " GetMapGroupRestriction " , Native_GetMapGroupRestriction ) ;
CreateNative ( " GetMapVIPRestriction " , Native_GetMapVIPRestriction ) ;
CreateNative ( " GetExtendsLeft " , Native_GetExtendsLeft ) ;
CreateNative ( " AreRestrictionsActive " , Native_AreRestrictionsActive ) ;
CreateNative ( " SimulateMapEnd " , Native_SimulateMapEnd ) ;
CreateNative ( " GetAveragePlayerTimeOnServerMapRestriction " , Native_GetAveragePlayerTimeOnServerMapRestriction ) ;
return APLRes_Success ;
2016-01-19 23:57:32 +01:00
}
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 ( ) ;
2019-08-18 23:08:23 +02:00
if ( InternalAreRestrictionsActive ( ) )
g_SaveCDOnMapEnd = true ;
else
g_SaveCDOnMapEnd = false ;
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
{
2023-01-27 21:07:48 +01:00
if ( ReadMapList ( g_MapList ,
g_mapFileSerial ,
" mapchooser " ,
MAPLIST_FLAG_CLEARARRAY | MAPLIST_FLAG_MAPSFOLDER )
! = INVALID_HANDLE )
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
{
if ( g_mapFileSerial = = - 1 )
LogError ( " Unable to create a valid map list. " ) ;
}
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
SetupTimeleftTimer ( ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_TotalRounds = 0 ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_Extends = 0 ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_MapVoteCompleted = false ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_NominateCount = 0 ;
g_NominateReservedCount = 0 ;
for ( int i = 0 ; i < MaxClients ; i + + )
{
if ( g_NominateList [ i ] ! = INVALID_HANDLE )
{
ClearArray ( g_NominateList [ i ] ) ;
}
}
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
ClearArray ( g_NominateOwners ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
for ( int i = 0 ; i < MAXTEAMS ; i + + )
g_winCount [ i ] = 0 ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
/* Check if mapchooser will attempt to start mapvote during bonus round time */
if ( ! GetConVarInt ( g_Cvar_StartRounds ) )
{
if ( ! GetConVarInt ( g_Cvar_StartTime ) & & GetConVarFloat ( g_Cvar_Bonusroundtime ) < = GetConVarFloat ( g_Cvar_VoteDuration ) )
LogError ( " Warning - Bonus Round Time shorter than Vote Time. Votes during bonus round may not have time to complete " ) ;
}
InitializeOfficialMapList ( ) ;
2016-01-19 23:57:32 +01:00
}
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 ;
2019-09-18 09:22:41 +02:00
static char map [ PLATFORM_MAX_PATH ] ;
int Cooldown ;
2019-08-18 23:08:23 +02:00
if ( g_SaveCDOnMapEnd )
2019-08-17 14:31:28 +02:00
{
GetCurrentMap ( map , PLATFORM_MAX_PATH ) ;
2019-09-18 09:22:41 +02:00
Cooldown = InternalGetMapCooldown ( map ) ;
2019-08-17 14:31:28 +02:00
g_OldMapList . SetValue ( map , Cooldown , true ) ;
2019-09-18 12:36:08 +02:00
2019-09-23 17:33:21 +02:00
Cooldown = GetTime ( ) + InternalGetMapCooldownTime ( map ) - RoundToFloor ( GetGameTime ( ) ) ;
2019-09-18 12:36:08 +02:00
g_TimeMapList . SetValue ( map , Cooldown , true ) ;
2019-08-17 14:31:28 +02: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 ) ) ;
g_OldMapList . GetValue ( map , Cooldown ) ;
2019-09-18 09:22:41 +02:00
Cooldown - - ;
2016-08-11 17:48:20 +02:00
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 ;
2019-09-18 12:36:08 +02:00
StringMapSnapshot TimeMapListSnapshot = g_TimeMapList . Snapshot ( ) ;
for ( int i = 0 ; i < TimeMapListSnapshot . Length ; i + + )
{
TimeMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
g_TimeMapList . GetValue ( map , Cooldown ) ;
if ( Cooldown < GetTime ( ) )
g_TimeMapList . Remove ( map ) ;
}
delete OldMapListSnapshot ;
InternalStoreMapCooldowns ( ) ;
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
{
2023-01-27 21:07:48 +01:00
if ( g_NominateList [ client ] ! = INVALID_HANDLE )
{
ClearArray ( g_NominateList [ client ] ) ;
}
2023-04-15 21:41:12 +02:00
CheckMapRestrictions ( true , true ) ; //when creating a mapvote its anyways respecting the time restrictions so we should also just respect them here already
2016-08-11 17:48:20 +02:00
}
2016-01-19 23:57:32 +01:00
2016-08-11 17:48:20 +02:00
public void OnClientDisconnect_Post ( int client )
{
2023-04-15 21:41:12 +02:00
CheckMapRestrictions ( true , true ) ; //when creating a mapvote its anyways respecting the time restrictions so we should also just respect them here already
2016-08-11 17:48:20 +02:00
}
public void OnClientDisconnect ( int client )
{
2023-03-13 20:00:35 +01:00
is_bot_player [ client ] = false ;
2023-01-27 21:07:48 +01:00
int index = FindValueInArray ( g_NominateOwners , client ) ;
2016-08-11 17:48:20 +02:00
2023-01-27 21:07:48 +01:00
if ( index = = - 1 )
return ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
//2023 edit for handling multiple nominations -jenz
for ( int i = 0 ; i < GetArraySize ( g_NominateList [ client ] ) ; i + + )
{
Call_StartForward ( g_NominationsResetForward ) ;
char oldmap [ PLATFORM_MAX_PATH ] ;
GetArrayString ( g_NominateList [ client ] , i , oldmap , PLATFORM_MAX_PATH ) ;
Call_PushString ( oldmap ) ;
Call_Finish ( ) ;
}
RemoveFromArray ( g_NominateOwners , index ) ;
for ( int i = 0 ; i < GetArraySize ( g_NominateList [ client ] ) ; i + + )
{
RemoveFromArray ( g_NominateList [ client ] , i ) ;
}
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
ClearArray ( g_NominateList [ client ] ) ;
g_NominateCount - - ;
2016-01-19 23:57:32 +01:00
}
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 ( ) ;
}
2023-04-09 13:57:09 +02:00
public Action Command_hours_average ( int client , int args )
{
2023-04-10 19:40:27 +02:00
CReplyToCommand ( client , " Average hour count is: %i " , GetAveragePlayerTimeOnServer ( ) ) ;
2023-04-09 13:57:09 +02:00
return Plugin_Handled ;
}
2019-02-07 20:19:14 +01:00
public Action Command_ExtendsLeft ( int client , int args )
{
CReplyToCommand ( client , " [MCE] Available Extends: %d " , GetConVarInt ( g_Cvar_Extend ) - g_Extends ) ;
return Plugin_Handled ;
}
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
{
2021-01-26 13:03:10 +01:00
int timeleft ;
GetMapTimeLeft ( timeleft ) ;
if ( timeleft < = 0 | | g_ChangeMapAtRoundEnd )
{
char map [ 32 ] ;
GetNextMap ( map , sizeof ( map ) ) ;
PrintToChatAll ( " [MCE] Next Map: %s " , map ) ;
PrintToChatAll ( " [MCE] Next Map: %s " , map ) ;
PrintToChatAll ( " [MCE] Next Map: %s " , map ) ;
}
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
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
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 " ) ;
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);
}
}
}
}
2023-01-27 21:07:48 +01:00
public Action Event_PlayerDeath ( Handle event , const char [ ] name , bool dontBroadcast )
2016-01-19 23:57:32 +01:00
{
2023-01-27 21:07:48 +01:00
if ( ! GetArraySize ( g_MapList ) | | g_HasVoteStarted )
return Plugin_Continue ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( ! GetConVarInt ( g_Cvar_Fraglimit ) | | ! GetConVarBool ( g_Cvar_EndOfMapVote ) )
return Plugin_Continue ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( g_MapVoteCompleted )
return Plugin_Continue ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
int fragger = GetClientOfUserId ( GetEventInt ( event , " attacker " ) ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( ! fragger )
return Plugin_Continue ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
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);
}
}
return Plugin_Continue ;
2016-01-19 23:57:32 +01:00
}
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 ;
}
2023-01-27 21:07:48 +01:00
public Handle get_most_nominated_maps ( )
{
int voteSize = GetVoteSize ( 2 ) ;
int arraySize = ByteCountToCells ( PLATFORM_MAX_PATH ) ;
Handle most_nominated_maps = CreateArray ( arraySize ) ;
StringMap sm = new StringMap ( ) ;
for ( int i = 0 ; i < MaxClients ; i + + )
{
for ( int j = 0 ; j < GetArraySize ( g_NominateList [ i ] ) ; j + + )
{
char map_iteration [ PLATFORM_MAX_PATH ] ;
GetArrayString ( g_NominateList [ i ] , j , map_iteration , PLATFORM_MAX_PATH ) ;
//PrintToChatAll("map_iteration: %s", map_iteration);
int nominate_count_for_particular_map = 0 ;
sm . GetValue ( map_iteration , nominate_count_for_particular_map ) ;
nominate_count_for_particular_map + + ;
2023-03-12 19:42:12 +01:00
//if i is 0 its admin nominated map that most come into the vote
2023-02-26 16:55:49 +01:00
if ( ! i )
{
nominate_count_for_particular_map = 999 ;
}
2023-01-27 21:07:48 +01:00
sm . SetValue ( map_iteration , nominate_count_for_particular_map , true ) ;
}
}
2023-01-29 18:04:56 +01:00
static char map_ [ PLATFORM_MAX_PATH ] ;
2023-01-27 21:07:48 +01:00
for ( int i = 0 ; i < voteSize ; i + + )
{
int max_count = 0 ;
char picked_map [ PLATFORM_MAX_PATH ] ;
StringMapSnapshot keys = sm . Snapshot ( ) ;
for ( int j = 0 ; j < keys . Length ; j + + )
{
int size = keys . KeyBufferSize ( j ) ;
char [ ] buffer = new char [ size ] ;
keys . GetKey ( j , buffer , size ) ;
//PrintToChatAll("buffer: %s", buffer);
if ( StrEqual ( buffer , " nominated_maps " ) )
{
continue ;
}
int value = 0 ;
sm . GetValue ( buffer , value ) ;
//PrintToChatAll("value: %i", value);
//first selection has most nominates, second selection second most etc etc
if ( value > = max_count )
{
max_count = value ;
strcopy ( picked_map , sizeof ( picked_map ) , buffer ) ;
}
}
delete keys ;
if ( strlen ( picked_map ) = = 0 )
{
continue ;
}
sm . Remove ( picked_map ) ;
2023-01-29 18:04:56 +01:00
//2023 edit: respecting that only right amount of maps per group is allowed in vote
int groups_ [ 32 ] ;
int groups [ 32 ] ;
int groupsfound = InternalGetMapGroups ( picked_map , groups , sizeof ( groups ) ) ;
bool skip_nomination = false ;
for ( int group = 0 ; group < groupsfound ; group + + )
{
int groupcur = 0 ;
int groupmax = InternalGetGroupMax ( groups [ group ] ) ;
if ( groupmax > = 0 )
{
for ( int j = 0 ; j < GetArraySize ( most_nominated_maps ) ; j + + )
{
//Native_GetMapGroupRestriction
GetArrayString ( most_nominated_maps , j , map_ , PLATFORM_MAX_PATH ) ;
int tmp = InternalGetMapGroups ( map_ , groups_ , sizeof ( groups_ ) ) ;
if ( FindIntInArray ( groups_ , tmp , groups [ group ] ) ! = - 1 )
{
groupcur + + ;
}
if ( groupcur > = groupmax )
{
skip_nomination = true ;
break ;
}
}
if ( skip_nomination )
{
break ;
}
}
}
if ( skip_nomination )
{
continue ;
}
2023-01-27 21:07:48 +01:00
PushArrayString ( most_nominated_maps , picked_map ) ;
//PrintToChatAll("picked_map: %s", picked_map);
}
delete sm ;
return most_nominated_maps ;
}
2016-01-19 23:57:32 +01:00
/ * *
* 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
{
2023-01-27 21:07:48 +01:00
g_WaitingForVote = true ;
g_WarningInProgress = false ;
int MenuRandomShuffleStart = 0 ;
int MenuRandomShuffleStop = 0 ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
// Check if a vote is in progress first
if ( IsVoteInProgress ( ) )
{
// Cant start a vote, try again in 5 seconds.
//g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE);
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
CPrintToChatAll ( " [MCE] %t " , " Cannot Start Vote " , FAILURE_TIMER_LENGTH ) ;
Handle data ;
g_RetryTimer = CreateDataTimer ( 1.0 , Timer_StartMapVote , data , TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
/* Mapchooser Extended */
WritePackCell ( data , FAILURE_TIMER_LENGTH ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( GetConVarBool ( g_Cvar_RunOff ) & & g_RunoffCount > 0 )
WritePackString ( data , " Revote Warning " ) ;
else
WritePackString ( data , " Vote Warning " ) ;
/* End Mapchooser Extended */
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
WritePackCell ( data , view_as < int > ( when ) ) ;
WritePackCell ( data , view_as < int > ( inputlist ) ) ;
ResetPack ( data ) ;
return ;
}
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
/* 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 ;
2016-08-11 17:48:20 +02:00
2023-01-27 21:07:48 +01:00
CheckMapRestrictions ( true , true ) ;
CreateNextVote ( ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_ChangeTime = when ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_WaitingForVote = false ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_HasVoteStarted = true ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_VoteMenu = CreateMenu ( Handler_MapVoteMenu , MenuAction_End | MenuAction_Display | MenuAction_DisplayItem | MenuAction_VoteCancel ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
g_AddNoVote = GetConVarBool ( g_Cvar_NoVoteOption ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
// Block Vote Slots
if ( GetConVarBool ( g_Cvar_BlockSlots ) )
{
Handle radioStyle = GetMenuStyleHandle ( MenuStyle_Radio ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( GetMenuStyle ( g_VoteMenu ) = = radioStyle )
{
g_BlockedSlots = true ;
AddMenuItem ( g_VoteMenu , LINE_ONE , " Choose something... " , ITEMDRAW_DISABLED ) ;
AddMenuItem ( g_VoteMenu , LINE_TWO , " ...will ya? " , ITEMDRAW_DISABLED ) ;
MenuRandomShuffleStart + = 2 ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( ! g_AddNoVote ) {
AddMenuItem ( g_VoteMenu , LINE_SPACER , " " , ITEMDRAW_SPACER ) ;
MenuRandomShuffleStart + + ;
}
}
else
g_BlockedSlots = false ;
}
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( g_AddNoVote )
SetMenuOptionFlags ( g_VoteMenu , MENUFLAG_BUTTON_NOVOTE ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
SetMenuTitle ( g_VoteMenu , " Vote Nextmap " ) ;
SetVoteResultCallback ( g_VoteMenu , Handler_MapVoteFinished ) ;
/* Call OnMapVoteStarted() Forward */
2016-01-19 23:57:32 +01:00
// Call_StartForward(g_MapVoteStartedForward);
// Call_Finish();
2023-01-27 21:07:48 +01:00
/ * *
* TODO : Make a proper decision on when to clear the nominations list .
* Currently it clears when used , and stays if an external list is provided .
* Is this the right thing to do ? External lists will probably come from places
* like sm_mapvote from the adminmenu in the future .
* /
static char map [ PLATFORM_MAX_PATH ] ;
/* No input given - User our internal nominations and maplist */
if ( inputlist = = INVALID_HANDLE )
{
Handle randomizeList = INVALID_HANDLE ;
//2023 edit to allow multiple nominations per player
Handle most_nominated_maps = get_most_nominated_maps ( ) ;
int voteSize = GetVoteSize ( 2 ) ; //voteSize wrong size probably for my for loop
if ( GetConVarBool ( g_Cvar_RandomizeNominations ) )
randomizeList = CloneArray ( most_nominated_maps ) ;
int nominateCount = GetArraySize ( most_nominated_maps ) ;
/* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */
int nominationsToAdd = nominateCount > = voteSize ? voteSize : nominateCount ;
bool extendFirst = GetConVarBool ( g_Cvar_ExtendPosition ) ;
if ( extendFirst ) {
AddExtendToMenu ( g_VoteMenu , when ) ;
MenuRandomShuffleStart + + ;
}
for ( int i = 0 ; i < nominationsToAdd ; i + + )
{
GetArrayString ( most_nominated_maps , i , map , PLATFORM_MAX_PATH ) ;
if ( randomizeList = = INVALID_HANDLE )
AddMapItem ( map ) ;
RemoveStringFromArray ( g_NextMapList , map ) ;
/* Notify Nominations that this map is now free */
2023-03-23 22:25:20 +01:00
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( map ) ;
Call_Finish ( ) ;
2023-01-27 21:07:48 +01:00
}
/* Clear out the rest of the nominations array */
for ( int i = nominationsToAdd ; i < nominateCount ; i + + )
{
//2023 edit: might need to run all g_NominateList[client] through this instead
GetArrayString ( most_nominated_maps , 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 */
2023-03-23 22:25:20 +01:00
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( map ) ;
Call_Finish ( ) ;
2023-01-27 21:07:48 +01:00
}
/* There should currently be 'nominationsToAdd' unique maps in the vote */
int i = nominationsToAdd ;
int count = 0 ;
int availableMaps = GetArraySize ( g_NextMapList ) ;
if ( i < voteSize & & availableMaps = = 0 )
{
if ( i = = 0 )
{
LogError ( " No maps available for vote. " ) ;
return ;
}
else
{
LogMessage ( " Not enough maps to fill map list, reducing map count. Adjust mce_include and mce_exclude to avoid this warning. " ) ;
voteSize = i ;
}
}
while ( i < voteSize )
{
GetArrayString ( g_NextMapList , count , map , PLATFORM_MAX_PATH ) ;
count + + ;
if ( randomizeList = = INVALID_HANDLE )
{
/* Insert the map and increment our count */
AddMapItem ( map ) ;
}
else
PushArrayString ( randomizeList , map ) ;
i + + ;
//Run out of maps, this will have to do.
if ( count > = availableMaps )
break ;
}
if ( randomizeList ! = INVALID_HANDLE )
{
// Fisher-Yates Shuffle
for ( int j = GetArraySize ( randomizeList ) - 1 ; j > = 1 ; j - - )
{
int k = GetRandomInt ( 0 , j ) ;
SwapArrayItems ( randomizeList , j , k ) ;
}
for ( int j = 0 ; j < GetArraySize ( randomizeList ) ; j + + )
{
GetArrayString ( randomizeList , j , map , PLATFORM_MAX_PATH ) ;
AddMapItem ( map ) ;
}
delete randomizeList ;
randomizeList = INVALID_HANDLE ;
delete most_nominated_maps ;
most_nominated_maps = INVALID_HANDLE ;
}
/* Wipe out our nominations list - Nominations have already been informed of this */
g_NominateCount = 0 ;
g_NominateReservedCount = 0 ;
ClearArray ( g_NominateOwners ) ;
for ( int j = 0 ; j < MaxClients ; j + + )
{
ClearArray ( g_NominateList [ j ] ) ;
}
if ( ! extendFirst ) {
AddExtendToMenu ( g_VoteMenu , when ) ;
MenuRandomShuffleStop + + ;
}
}
else //We were given a list of maps to start the vote with
{
int size = GetArraySize ( inputlist ) ;
for ( int i = 0 ; i < size ; i + + )
{
GetArrayString ( inputlist , i , map , PLATFORM_MAX_PATH ) ;
if ( IsMapValid ( map ) )
{
AddMapItem ( map ) ;
}
// New in Mapchooser Extended
else if ( StrEqual ( map , VOTE_DONTCHANGE ) )
{
AddMenuItem ( g_VoteMenu , VOTE_DONTCHANGE , " Dont Change " ) ;
}
else if ( StrEqual ( map , VOTE_EXTEND ) )
{
AddMenuItem ( g_VoteMenu , VOTE_EXTEND , " Extend Map " ) ;
}
}
delete inputlist ;
}
int voteDuration = GetConVarInt ( g_Cvar_VoteDuration ) ;
//SetMenuExitButton(g_VoteMenu, false);
if ( GetVoteSize ( 2 ) < = GetMaxPageItems ( GetMenuStyle ( g_VoteMenu ) ) )
{
//This is necessary to get items 9 and 0 as usable voting items
SetMenuPagination ( g_VoteMenu , MENU_NO_PAGINATION ) ;
}
if ( GetConVarInt ( g_Cvar_ShufflePerClient ) )
MenuShufflePerClient ( g_VoteMenu , MenuRandomShuffleStart , GetMenuItemCount ( g_VoteMenu ) - MenuRandomShuffleStop ) ;
VoteMenuToAll ( g_VoteMenu , voteDuration ) ;
/* 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-01-19 23:57:32 +01:00
}
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
{
2023-01-27 21:07:48 +01:00
static char 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 + + ;
int time ;
if ( GetMapTimeLimit ( time ) )
{
if ( time > 0 )
ExtendMapTimeLimit ( GetConVarInt ( g_Cvar_ExtendTimeStep ) * 60 ) ;
}
int winlimit = GetConVarInt ( g_Cvar_Winlimit ) ;
if ( winlimit )
SetConVarInt ( g_Cvar_Winlimit , winlimit + GetConVarInt ( g_Cvar_ExtendRoundStep ) ) ;
int maxrounds = GetConVarInt ( g_Cvar_Maxrounds ) ;
if ( maxrounds )
SetConVarInt ( g_Cvar_Maxrounds , maxrounds + GetConVarInt ( g_Cvar_ExtendRoundStep ) ) ;
int fraglimit = GetConVarInt ( g_Cvar_Fraglimit ) ;
if ( fraglimit )
SetConVarInt ( g_Cvar_Fraglimit , fraglimit + GetConVarInt ( g_Cvar_ExtendFragStep ) ) ;
CPrintToChatAll ( " [MCE] %t " , " Current Map Extended " , RoundToFloor ( float ( item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ) / float ( num_votes ) * 100.0 ) , num_votes ) ;
LogAction ( - 1 , - 1 , " Voting for next map has finished. The current map has been extended. " ) ;
CPrintToChatAll ( " [MCE] Available Extends: %d " , GetConVarInt ( g_Cvar_Extend ) - g_Extends ) ;
// We extended, so well have to vote again.
g_RunoffCount = 0 ;
g_HasVoteStarted = false ;
SetupTimeleftTimer ( ) ;
}
else if ( strcmp ( map , VOTE_DONTCHANGE , false ) = = 0 )
{
CPrintToChatAll ( " [MCE] %t " , " Current Map Stays " , RoundToFloor ( float ( item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ) / float ( num_votes ) * 100.0 ) , num_votes ) ;
LogAction ( - 1 , - 1 , " Voting for next map has finished. 'No Change' was the winner " ) ;
g_RunoffCount = 0 ;
g_HasVoteStarted = false ;
SetupTimeleftTimer ( ) ;
}
else
{
if ( g_ChangeTime = = MapChange_MapEnd )
{
SetNextMap ( map ) ;
}
else if ( g_ChangeTime = = MapChange_Instant )
{
Handle data ;
CreateDataTimer ( 4.0 , Timer_ChangeMap , data ) ;
WritePackString ( data , map ) ;
g_ChangeMapInProgress = false ;
}
else // MapChange_RoundEnd
{
SetNextMap ( map ) ;
g_ChangeMapAtRoundEnd = true ;
}
g_HasVoteStarted = false ;
g_MapVoteCompleted = true ;
CPrintToChatAll ( " [MCE] %t " , " Nextmap Voting Finished " , map , RoundToFloor ( float ( item_info [ 0 ] [ VOTEINFO_ITEM_VOTES ] ) / float ( num_votes ) * 100.0 ) , num_votes ) ;
LogAction ( - 1 , - 1 , " Voting for next map has finished. Nextmap: %s. " , map ) ;
}
2016-01-19 23:57:32 +01:00
}
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 ) ;
2019-11-28 15:45:31 +01:00
int required_votes = RoundToCeil ( float ( num_votes ) * float ( required_percent ) / 100.0 ) ;
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 ;
}
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 ;
}
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 ) ;
}
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 ;
2019-08-13 20:46:30 +02:00
delete menu ;
2016-01-19 23:57:32 +01:00
}
case MenuAction_Display :
{
2019-08-13 20:46:30 +02:00
static char buffer [ 255 ] ;
Format ( buffer , sizeof ( buffer ) , " %T " , " Vote Nextmap " , param1 ) ;
Handle panel = view_as < Handle > ( param2 ) ;
SetPanelTitle ( panel , buffer ) ;
2020-11-09 16:01:22 +01:00
DrawPanelText ( panel , " Warning: The Position of the Maps are different for each Player. " ) ;
2016-01-19 23:57:32 +01:00
}
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
2019-08-14 15:21:24 +02:00
GetMenuItem ( menu , param2 , map , PLATFORM_MAX_PATH , _ , _ , _ , param1 ) ;
2016-01-19 23:57:32 +01:00
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 ) ;
}
2018-09-23 23:53:59 +02:00
else if ( InternalGetMapVIPRestriction ( map ) )
2018-09-23 18:36:59 +02:00
{
Format ( buffer , sizeof ( buffer ) , " %s (%T) " , map , " VIP Nomination " , param1 ) ;
}
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
if ( buffer [ 0 ] ! = '\0' )
2016-01-19 23:57:32 +01:00
{
2019-08-13 20:46:30 +02:00
return RedrawMenuItem ( buffer ) ;
2016-01-19 23:57:32 +01:00
}
// 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
{
2019-08-13 20:46:30 +02:00
int count = GetMenuItemCount ( menu ) ;
2016-01-19 23:57:32 +01:00
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 ;
2019-08-13 20:46:30 +02:00
if ( 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
2019-08-14 15:21:24 +02:00
GetMenuItem ( menu , item , map , PLATFORM_MAX_PATH , _ , _ , _ , param1 ) ;
2016-01-19 23:57:32 +01:00
}
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 ;
}
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
{
2023-01-27 21:07:48 +01:00
assert ( g_NextMapList )
ClearArray ( g_NextMapList ) ;
static char map [ PLATFORM_MAX_PATH ] ;
Handle tempMaps = CloneArray ( g_MapList ) ;
GetCurrentMap ( map , PLATFORM_MAX_PATH ) ;
RemoveStringFromArray ( tempMaps , map ) ;
if ( GetArraySize ( tempMaps ) > GetConVarInt ( g_Cvar_ExcludeMaps ) & & InternalAreRestrictionsActive ( ) )
{
StringMapSnapshot OldMapListSnapshot = g_OldMapList . Snapshot ( ) ;
for ( int i = 0 ; i < OldMapListSnapshot . Length ; i + + )
{
OldMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
RemoveStringFromArray ( tempMaps , map ) ;
}
delete OldMapListSnapshot ;
}
if ( InternalAreRestrictionsActive ( ) )
{
StringMapSnapshot TimeMapListSnapshot = g_TimeMapList . Snapshot ( ) ;
for ( int i = 0 ; i < TimeMapListSnapshot . Length ; i + + )
{
TimeMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
int Cooldown ;
g_TimeMapList . GetValue ( map , Cooldown ) ;
if ( Cooldown > GetTime ( ) )
RemoveStringFromArray ( tempMaps , map ) ;
}
delete TimeMapListSnapshot ;
}
int voteSize = GetVoteSize ( 2 ) ;
int limit = ( voteSize < GetArraySize ( tempMaps ) ? voteSize : GetArraySize ( tempMaps ) ) ;
// group -> number of maps nominated from group
StringMap groupmap = new StringMap ( ) ;
char groupstr [ 8 ] ;
// populate groupmap with maps from nomination list
static char map_ [ PLATFORM_MAX_PATH ] ;
int groups_ [ 32 ] ;
//2023 edit
Handle most_nominated_maps = get_most_nominated_maps ( ) ;
for ( int i = 0 ; i < GetArraySize ( most_nominated_maps ) ; i + + )
{
GetArrayString ( most_nominated_maps , i , map_ , PLATFORM_MAX_PATH ) ;
int groupsfound = InternalGetMapGroups ( map_ , groups_ , sizeof ( groups_ ) ) ;
for ( int group = 0 ; group < groupsfound ; group + + )
{
IntToString ( group , groupstr , sizeof ( groupstr ) ) ;
int groupcur = 0 ;
groupmap . GetValue ( groupstr , groupcur ) ;
groupcur + + ;
groupmap . SetValue ( groupstr , groupcur , true ) ;
}
}
// find random maps which honor all restrictions
for ( int i = 0 ; i < limit ; i + + )
{
int b ;
for ( int j = 0 ; j < 1000 ; j + + )
{
b = GetRandomInt ( 0 , GetArraySize ( tempMaps ) - 1 ) ;
GetArrayString ( tempMaps , b , map , PLATFORM_MAX_PATH ) ;
if ( ! InternalAreRestrictionsActive ( ) )
break ;
if ( InternalGetMapVIPRestriction ( map ) )
continue ;
if ( InternalGetMapTimeRestriction ( map ) ! = 0 )
continue ;
if ( InternalGetMapPlayerRestriction ( map ) ! = 0 )
continue ;
2023-04-15 21:41:12 +02:00
if ( InternalGetAveragePlayerHourRestriction ( map ) ! = 0 )
continue ;
2023-01-27 21:07:48 +01:00
bool okay = true ;
int groups [ 32 ] ;
int groupsfound = InternalGetMapGroups ( map , groups , sizeof ( groups ) ) ;
for ( int group = 0 ; group < groupsfound ; group + + )
{
IntToString ( group , groupstr , sizeof ( groupstr ) ) ;
int groupmax = InternalGetGroupMax ( groups [ group ] ) ;
if ( groupmax > = 0 )
{
int groupcur = 0 ;
groupmap . GetValue ( groupstr , groupcur ) ;
if ( groupcur > = groupmax )
{
okay = false ;
break ;
}
groupcur + + ;
groupmap . SetValue ( groupstr , groupcur , true ) ;
}
}
if ( okay )
break ;
}
PushArrayString ( g_NextMapList , map ) ;
RemoveFromArray ( tempMaps , b ) ;
}
delete groupmap ;
delete tempMaps ;
2016-01-19 23:57:32 +01:00
}
2016-08-11 17:48:20 +02:00
bool CanVoteStart ( )
2016-01-19 23:57:32 +01:00
{
2023-01-27 21:07:48 +01:00
if ( g_WaitingForVote | | g_HasVoteStarted )
return false ;
return true ;
}
NominateResult InternalNominateMap ( char [ ] map , int owner )
{
if ( ! IsMapValid ( map ) )
{
return Nominate_InvalidMap ;
}
/* Look to replace an existing nomination by this client - Nominations made with owner = 0 arent replaced */
//2023 edit: change clients first nomination out of the clients multiple nominations, make a check if client filled all his nomination slots
//currently hard coded to 3 maps, just add a cvar to replace it with in the future
if ( owner & & ( ( FindValueInArray ( g_NominateOwners , owner ) ) ! = - 1 ) & & GetArraySize ( g_NominateList [ owner ] ) > 2 )
{
char oldmap [ PLATFORM_MAX_PATH ] ;
GetArrayString ( g_NominateList [ owner ] , 0 , oldmap , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_Finish ( ) ;
RemoveFromArray ( g_NominateList [ owner ] , 0 ) ;
PushArrayString ( g_NominateList [ owner ] , map ) ;
return Nominate_Replaced ;
}
/* Too many nominated maps. */
//2023 edit: we dont want this check
/ *
if ( g_NominateCount > = GetVoteSize ( 0 ) & & ! force )
{
return Nominate_VoteFull ;
}
* /
2023-01-29 18:04:56 +01:00
if ( owner ! = 0 & & g_NominateList [ owner ] ! = INVALID_HANDLE )
2023-01-27 21:07:48 +01:00
{
for ( int j = 0 ; j < GetArraySize ( g_NominateList [ owner ] ) ; j + + )
{
char map_iteration [ PLATFORM_MAX_PATH ] ;
GetArrayString ( g_NominateList [ owner ] , j , map_iteration , PLATFORM_MAX_PATH ) ;
if ( StrEqual ( map , map_iteration , false ) )
{
return Nominate_InvalidMap ;
}
}
}
PushArrayString ( g_NominateList [ owner ] , map ) ;
PushArrayCell ( g_NominateOwners , owner ) ; //maybe i only want to do this for the first nomination of each client
if ( owner = = 0 & & g_NominateReservedCount < GetVoteSize ( 1 ) )
g_NominateReservedCount + + ;
else
g_NominateCount + + ;
while ( GetArraySize ( g_NominateList [ owner ] ) > GetVoteSize ( 2 ) )
{
char oldmap [ PLATFORM_MAX_PATH ] ;
GetArrayString ( g_NominateList [ owner ] , 0 , oldmap , PLATFORM_MAX_PATH ) ;
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
int owner_ = GetArrayCell ( g_NominateOwners , 0 ) ;
Call_Finish ( ) ;
RemoveFromArray ( g_NominateList [ owner ] , 0 ) ;
RemoveFromArray ( g_NominateOwners , 0 ) ;
if ( owner_ = = 0 )
g_NominateReservedCount - - ;
else
g_NominateCount - - ;
}
return Nominate_Added ;
2016-01-19 23:57:32 +01:00
}
/* 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 ) ;
2023-01-27 21:07:48 +01:00
return view_as < int > ( InternalNominateMap ( map , 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
{
2023-01-27 21:07:48 +01:00
for ( int client = 0 ; client < MaxClients ; client + + )
{
for ( int i = 0 ; i < GetArraySize ( g_NominateList [ client ] ) ; i + + )
{
char oldmap [ PLATFORM_MAX_PATH ] ;
GetArrayString ( g_NominateList [ client ] , i , oldmap , PLATFORM_MAX_PATH ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( strcmp ( map , oldmap , false ) = = 0 )
{
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_Finish ( ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
int owner = GetArrayCell ( g_NominateOwners , i ) ;
if ( owner )
g_NominateCount - - ;
else
g_NominateReservedCount - - ;
2019-12-22 14:10:01 +01:00
2023-01-27 21:07:48 +01:00
RemoveFromArray ( g_NominateList [ client ] , i ) ;
RemoveFromArray ( g_NominateOwners , i ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
return true ;
}
}
}
return false ;
2016-01-19 23:57:32 +01:00
}
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 ] ;
2023-01-27 21:07:48 +01:00
GetArrayString ( g_NominateList [ owner ] , index , oldmap , PLATFORM_MAX_PATH ) ;
2016-01-19 23:57:32 +01:00
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( oldmap ) ;
Call_Finish ( ) ;
2023-01-27 21:07:48 +01:00
RemoveFromArray ( g_NominateList [ owner ] , index ) ;
//maybe only do once or change g_NominateOwners
2016-01-19 23:57:32 +01:00
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
}
2023-04-15 21:41:12 +02:00
//GetNominatedMapList
2016-08-11 17:48:20 +02:00
public int Native_GetNominatedMapList ( Handle plugin , int numParams )
2016-01-19 23:57:32 +01:00
{
2023-01-27 21:07:48 +01:00
Handle maparray = view_as < Handle > ( GetNativeCell ( 1 ) ) ;
Handle ownerarray = view_as < Handle > ( GetNativeCell ( 2 ) ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
if ( maparray = = INVALID_HANDLE )
return ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
static char map [ PLATFORM_MAX_PATH ] ;
2023-04-15 21:41:12 +02:00
CheckMapRestrictions ( true , true ) ;
/ *
when a guy checks the nomlist the only thing that has changed is the time .
Its not smart to display a map in the nominate list just for InitiateVote ( ) to discard it anyways from the map vote just because of time based restriction
* /
2023-01-27 21:07:48 +01:00
for ( int client = 0 ; client < MaxClients ; client + + )
{
for ( int i = 0 ; i < GetArraySize ( g_NominateList [ client ] ) ; i + + )
{
GetArrayString ( g_NominateList [ client ] , i , map , PLATFORM_MAX_PATH ) ;
PushArrayString ( maparray , map ) ;
2016-01-19 23:57:32 +01:00
2023-01-27 21:07:48 +01:00
// If the optional parameter for an owner list was passed, then we need to fill that out as well
if ( ownerarray ! = INVALID_HANDLE )
{
//int index = GetArrayCell(g_NominateOwners, i);
PushArrayCell ( ownerarray , client ) ;
}
}
}
2016-01-19 23:57:32 +01:00
}
// 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
{
2019-08-17 14:31:28 +02:00
if ( ! InternalAreRestrictionsActive ( ) )
return true ;
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-12-05 18:50:44 +01:00
int Cooldown ;
int Mode = GetNativeCell ( 3 ) ;
if ( Mode = = 0 )
{
Cooldown = InternalGetMapCooldown ( map ) ;
}
else if ( Mode = = 1 )
{
Cooldown = GetNativeCell ( 2 ) ;
}
else if ( Mode = = 2 )
{
g_OldMapList . GetValue ( map , Cooldown ) ;
int NewCooldown = GetNativeCell ( 2 ) ;
if ( NewCooldown > Cooldown )
Cooldown = NewCooldown ;
}
2016-08-11 17:48:20 +02:00
g_OldMapList . SetValue ( map , Cooldown , true ) ;
2018-09-18 16:35:21 +02:00
InternalStoreMapCooldowns ( ) ;
2016-04-26 12:36:03 +02:00
2016-01-19 23:57:32 +01:00
return true ;
}
2019-09-18 12:36:08 +02:00
public int Native_ExcludeMapTime ( Handle plugin , int numParams )
{
if ( ! InternalAreRestrictionsActive ( ) )
return true ;
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
int Cooldown ;
int Mode = GetNativeCell ( 3 ) ;
if ( Mode = = 0 )
{
Cooldown = InternalGetMapCooldownTime ( map ) ;
}
else if ( Mode = = 1 )
{
2019-09-18 16:58:30 +02:00
Cooldown = GetNativeCell ( 2 ) ;
2019-09-18 12:36:08 +02:00
}
else if ( Mode = = 2 )
{
g_TimeMapList . GetValue ( map , Cooldown ) ;
2019-09-18 16:58:30 +02:00
int NewCooldown = GetTime ( ) + GetNativeCell ( 2 ) ;
2019-09-18 12:36:08 +02:00
if ( NewCooldown > Cooldown )
2019-09-18 16:58:30 +02:00
Cooldown = GetNativeCell ( 2 ) ;
2021-05-14 15:42:10 +02:00
else
return true ;
2019-09-18 12:36:08 +02:00
}
Cooldown + = GetTime ( ) ;
g_TimeMapList . SetValue ( map , Cooldown , true ) ;
InternalStoreMapCooldowns ( ) ;
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
{
2019-09-18 12:36:08 +02:00
if ( ! InternalAreRestrictionsActive ( ) )
return 0 ;
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 ;
}
2019-09-18 12:36:08 +02:00
public int Native_GetMapCooldownTime ( Handle plugin , int numParams )
{
if ( ! InternalAreRestrictionsActive ( ) )
return 0 ;
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
int Cooldown = 0 ;
g_TimeMapList . GetValue ( map , Cooldown ) ;
return Cooldown ;
}
2017-10-12 21:52:19 +02:00
public int Native_GetMapMinTime ( Handle plugin , int numParams )
{
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
return InternalGetMapMinTime ( map ) ;
}
public int Native_GetMapMaxTime ( Handle plugin , int numParams )
{
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
return InternalGetMapMaxTime ( map ) ;
}
2016-08-11 17:48:20 +02:00
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 ) ;
}
2017-10-12 21:52:19 +02:00
public int Native_GetMapTimeRestriction ( Handle plugin , int numParams )
{
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
return InternalGetMapTimeRestriction ( map ) ;
}
2023-04-09 13:57:09 +02:00
//GetAveragePlayerTimeOnServerMapRestriction
public int Native_GetAveragePlayerTimeOnServerMapRestriction ( Handle plugin , int numParams )
{
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
2023-04-15 21:41:12 +02:00
return InternalGetAveragePlayerHourRestriction ( map ) ;
}
stock int InternalGetAveragePlayerHourRestriction ( const char [ ] map )
{
2023-04-09 13:57:09 +02:00
int players_average_hours = GetAveragePlayerTimeOnServer ( ) ;
int MinAverageHours = 0 ;
if ( g_Config & & g_Config . JumpToKey ( map ) )
{
MinAverageHours = g_Config . GetNum ( " MinHoursAvg " , MinAverageHours ) ;
g_Config . Rewind ( ) ;
}
//0 means map can be nominated, anything above 0 means more hours are required
if ( players_average_hours > = MinAverageHours )
{
return 0 ;
}
return MinAverageHours - players_average_hours ;
}
//GetMapPlayerRestriction
2016-08-11 17:48:20 +02:00
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 ) ;
}
2018-08-10 12:43:49 +02:00
public int Native_GetMapGroups ( Handle plugin , int numParams )
2018-03-20 01:06:26 +01:00
{
int len ;
GetNativeStringLength ( 1 , len ) ;
int size = GetNativeCell ( 3 ) ;
if ( len < = 0 )
return - 999 ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
2018-08-10 12:43:49 +02:00
int [ ] groups = new int [ size ] ;
int found = InternalGetMapGroups ( map , groups , size ) ;
if ( found > = 0 )
SetNativeArray ( 2 , groups , size ) ;
return found ;
2018-03-20 01:06:26 +01:00
}
2023-01-29 18:04:56 +01:00
//GetMapGroupRestriction
2018-03-20 01:06:26 +01:00
public int Native_GetMapGroupRestriction ( Handle plugin , int numParams )
{
2023-01-29 18:04:56 +01:00
GetNativeCell ( 2 ) ;
2023-01-27 21:07:48 +01:00
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return - 999 ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
int groups [ 32 ] ;
int groupsfound = InternalGetMapGroups ( map , groups , sizeof ( groups ) ) ;
for ( int group = 0 ; group < groupsfound ; group + + )
{
int groupcur = 0 ;
int groupmax = InternalGetGroupMax ( groups [ group ] ) ;
if ( groupmax > = 0 )
{
static char map_ [ PLATFORM_MAX_PATH ] ;
char kv_map [ PLATFORM_MAX_PATH ] ;
int groups_ [ 32 ] ;
KeyValues kv = CreateKeyValues ( " cur_groups " ) ;
for ( int clienti = 0 ; clienti < MaxClients ; clienti + + )
{
for ( int i = 0 ; i < GetArraySize ( g_NominateList [ clienti ] ) ; i + + )
{
GetArrayString ( g_NominateList [ clienti ] , i , map_ , PLATFORM_MAX_PATH ) ;
int tmp = InternalGetMapGroups ( map_ , groups_ , sizeof ( groups_ ) ) ;
kv . GetString ( map_ , kv_map , sizeof ( kv_map ) , " not_found " ) ;
if ( FindIntInArray ( groups_ , tmp , groups [ group ] ) ! = - 1 & & StrEqual ( kv_map , " not_found " ) )
{
groupcur + + ;
kv . SetString ( map_ , map_ ) ;
}
}
}
delete kv ;
}
}
return - 1 ;
2018-03-20 01:06:26 +01:00
}
2018-09-22 11:49:43 +02:00
public int Native_GetMapVIPRestriction ( Handle plugin , int numParams )
{
2018-09-23 23:53:59 +02:00
int client = GetNativeCell ( 2 ) ;
2018-09-22 11:49:43 +02:00
int len ;
GetNativeStringLength ( 1 , len ) ;
if ( len < = 0 )
return false ;
char [ ] map = new char [ len + 1 ] ;
GetNativeString ( 1 , map , len + 1 ) ;
2018-09-23 23:53:59 +02:00
// Check if client should bypass vip restrictions
2019-11-26 22:00:23 +01:00
if ( client > = 1 & & client < = MaxClients )
2018-09-23 23:53:59 +02:00
{
// Client has bypass flag, dont return vip restrictions
if ( CheckCommandAccess ( client , " sm_nominate_ignore " , ADMFLAG_CHEATS ) )
return false ;
// Client has vip flag, dont return vip restrictions
if ( CheckCommandAccess ( client , " sm_nominate_vip " , ADMFLAG_CUSTOM1 ) )
return false ;
}
2018-09-22 11:49:43 +02:00
return InternalGetMapVIPRestriction ( map ) ;
}
2018-03-20 01:06:26 +01:00
2019-06-15 23:25:37 +02:00
public int Native_GetExtendsLeft ( Handle plugin , int numParams )
{
return GetConVarInt ( g_Cvar_Extend ) - g_Extends ;
}
2019-08-17 14:31:28 +02:00
public int Native_AreRestrictionsActive ( Handle plugin , int numParams )
{
return InternalAreRestrictionsActive ( ) ;
}
2020-07-09 23:23:40 +02:00
public int Native_SimulateMapEnd ( Handle plugin , int numParams )
{
OnMapEnd ( ) ;
}
2016-08-11 17:48:20 +02:00
stock void AddMapItem ( const char [ ] map )
{
2019-08-13 20:46:30 +02:00
AddMenuItem ( g_VoteMenu , map , map ) ;
2016-01-19 23:57:32 +01:00
}
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
{
2019-08-14 15:21:24 +02:00
GetMenuItem ( menu , position , map , mapLen , _ , _ , _ , - 1 ) ;
2016-01-19 23:57:32 +01:00
}
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
{
2023-01-27 21:07:48 +01:00
// Built-in votes doesnt have "Dont Change", send Extend instead
AddMenuItem ( menu , VOTE_DONTCHANGE , " Dont Change " ) ;
2016-01-19 23:57:32 +01:00
}
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
{
2019-08-13 20:46:30 +02:00
AddMenuItem ( menu , VOTE_EXTEND , " Extend Map " ) ;
2016-01-19 23:57:32 +01:00
}
}
2018-08-10 12:43:49 +02:00
// 0 = IncludeMaps, 1 = Reserved, 2 = IncludeMaps+Reserved
stock int GetVoteSize ( int what = 0 )
2016-01-19 23:57:32 +01:00
{
2018-08-10 12:43:49 +02:00
int includeMaps = GetConVarInt ( g_Cvar_IncludeMaps ) ;
int includeMapsReserved = GetConVarInt ( g_Cvar_IncludeMapsReserved ) ;
2019-12-22 14:10:01 +01:00
if ( what = = 0 )
return includeMaps ;
else if ( what = = 1 )
return includeMapsReserved ;
else if ( what = = 2 )
return includeMaps + includeMapsReserved ;
2018-08-10 12:43:49 +02:00
2019-12-22 14:10:01 +01:00
return 0 ;
2016-08-11 17:48:20 +02:00
}
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
2019-09-18 09:22:41 +02:00
return Cooldown ;
2016-08-11 17:48:20 +02:00
}
2016-01-19 23:57:32 +01:00
2019-09-18 12:36:08 +02:00
stock int InternalGetMapCooldownTime ( const char [ ] map )
{
2019-09-18 16:58:30 +02:00
char time [ 16 ] ;
g_Cvar_ExcludeMapsTime . GetString ( time , sizeof ( time ) ) ;
int Cooldown = TimeStrToSeconds ( time ) ;
2019-09-18 12:36:08 +02:00
if ( g_Config & & g_Config . JumpToKey ( map ) )
{
2019-09-18 16:58:30 +02:00
g_Config . GetString ( " CooldownTime " , time , sizeof ( time ) , " " ) ;
2019-09-19 21:07:02 +02:00
if ( time [ 0 ] )
Cooldown = TimeStrToSeconds ( time ) ;
2019-09-18 16:58:30 +02:00
2019-09-18 12:36:08 +02:00
g_Config . Rewind ( ) ;
}
return Cooldown ;
}
2017-10-12 21:52:19 +02:00
void CheckMapRestrictions ( bool time = false , bool players = false )
2016-08-11 17:48:20 +02:00
{
2023-01-27 21:07:48 +01:00
if ( ! InternalAreRestrictionsActive ( ) )
return ;
static char map [ PLATFORM_MAX_PATH ] ;
for ( int client = 0 ; client < MaxClients ; client + + )
{
if ( CheckCommandAccess ( client , " sm_nominate_ignore " , ADMFLAG_CHEATS , true ) )
continue ;
for ( int i = 0 ; i < GetArraySize ( g_NominateList [ client ] ) ; i + + )
{
bool remove ;
GetArrayString ( g_NominateList [ client ] , i , map , PLATFORM_MAX_PATH ) ;
if ( time )
{
int TimeRestriction = InternalGetMapTimeRestriction ( map ) ;
if ( TimeRestriction )
{
remove = true ;
2023-03-12 19:42:12 +01:00
if ( client > 0 & & client < = MaxClients & & IsClientConnected ( client ) & & IsClientInGame ( client ) )
{
CPrintToChat ( client , " [MCE] %t " , " Nomination Removed Time Error " , map ) ;
}
2023-01-27 21:07:48 +01:00
}
}
if ( players )
{
int PlayerRestriction = InternalGetMapPlayerRestriction ( map ) ;
if ( PlayerRestriction )
{
remove = true ;
2023-03-12 19:42:12 +01:00
if ( client > 0 & & client < = MaxClients & & IsClientConnected ( client ) & & IsClientInGame ( client ) )
{
if ( PlayerRestriction < 0 )
CPrintToChat ( client , " [MCE] %t " , " Nomination Removed MinPlayers Error " , map ) ;
else
CPrintToChat ( client , " [MCE] %t " , " Nomination Removed MaxPlayers Error " , map ) ;
}
2023-01-27 21:07:48 +01:00
}
2023-04-15 21:41:12 +02:00
if ( InternalGetAveragePlayerHourRestriction ( map ) > 0 & & ! remove )
{
remove = true ;
if ( client > 0 & & client < = MaxClients & & IsClientConnected ( client ) & & IsClientInGame ( client ) )
{
ReplyToCommand ( client , " [MCE] Your nomination %s has been removed because it does not meet the minimum Average hour requirements. " , map ) ;
}
}
2023-01-27 21:07:48 +01:00
}
if ( remove )
{
2023-03-23 22:25:20 +01:00
if ( strlen ( map ) > 0 )
2023-03-23 19:47:48 +01:00
{
Call_StartForward ( g_NominationsResetForward ) ;
Call_PushString ( map ) ;
Call_Finish ( ) ;
}
2023-03-23 22:25:20 +01:00
RemoveFromArray ( g_NominateList [ client ] , i ) ;
RemoveFromArray ( g_NominateOwners , i ) ;
g_NominateCount - - ;
2023-01-27 21:07:48 +01:00
}
}
}
2016-08-11 17:48:20 +02:00
}
2017-10-12 21:52:19 +02:00
stock int InternalGetMapMinTime ( const char [ ] map )
{
int MinTime = 0 ;
if ( g_Config & & g_Config . JumpToKey ( map ) )
{
MinTime = g_Config . GetNum ( " MinTime " , MinTime ) ;
g_Config . Rewind ( ) ;
}
return MinTime ;
}
stock int InternalGetMapMaxTime ( const char [ ] map )
{
int MaxTime = 0 ;
if ( g_Config & & g_Config . JumpToKey ( map ) )
{
MaxTime = g_Config . GetNum ( " MaxTime " , MaxTime ) ;
g_Config . Rewind ( ) ;
}
return MaxTime ;
}
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 ;
}
2018-08-10 12:43:49 +02:00
stock int InternalGetMapGroups ( const char [ ] map , int [ ] groups , int size )
2018-03-20 01:06:26 +01:00
{
2018-08-10 12:43:49 +02:00
int found = 0 ;
2018-03-20 01:06:26 +01:00
if ( g_Config & & g_Config . JumpToKey ( " _groups " ) )
{
if ( ! g_Config . GotoFirstSubKey ( false ) )
{
g_Config . Rewind ( ) ;
return - 999 ;
}
do
{
2018-08-10 12:43:49 +02:00
char groupstr [ 8 ] ;
g_Config . GetSectionName ( groupstr , sizeof ( groupstr ) ) ;
int group = StringToInt ( groupstr ) ;
2018-03-20 01:06:26 +01:00
if ( g_Config . JumpToKey ( map , false ) )
{
2018-08-10 12:43:49 +02:00
groups [ found + + ] = group ;
if ( found > = size )
{
g_Config . Rewind ( ) ;
return found ;
}
g_Config . GoBack ( ) ;
2018-03-20 01:06:26 +01:00
}
} while ( g_Config . GotoNextKey ( ) ) ;
g_Config . Rewind ( ) ;
}
2018-08-10 12:43:49 +02:00
return found ;
}
stock int InternalGetGroupMax ( int group )
{
char groupstr [ 8 ] ;
IntToString ( group , groupstr , sizeof ( groupstr ) ) ;
if ( g_Config & & g_Config . JumpToKey ( " _groups " ) )
{
if ( g_Config . JumpToKey ( groupstr , false ) )
{
int max = g_Config . GetNum ( " _max " , - 1 ) ;
g_Config . Rewind ( ) ;
return max ;
}
g_Config . Rewind ( ) ;
}
return - 1 ;
2018-03-20 01:06:26 +01:00
}
2017-10-12 21:52:19 +02:00
// 0 = Okay
2017-10-15 16:20:53 +02:00
// >0 = Minutes till Okay
2017-10-12 21:52:19 +02:00
stock int InternalGetMapTimeRestriction ( const char [ ] map )
{
2017-10-15 16:20:53 +02:00
char sTime [ 8 ] ;
FormatTime ( sTime , sizeof ( sTime ) , " %H%M " ) ;
2017-10-12 21:52:19 +02:00
2017-10-15 16:20:53 +02:00
int CurTime = StringToInt ( sTime ) ;
2017-10-12 21:52:19 +02:00
int MinTime = InternalGetMapMinTime ( map ) ;
int MaxTime = InternalGetMapMaxTime ( map ) ;
2017-10-23 00:07:05 +02:00
//Wrap around.
CurTime = ( CurTime < = MinTime ) ? CurTime + 2400 : CurTime ;
MaxTime = ( MaxTime < = MinTime ) ? MaxTime + 2400 : MaxTime ;
2017-10-15 16:20:53 +02:00
if ( ! ( MinTime < = CurTime < = MaxTime ) )
{
2017-10-23 00:07:05 +02:00
//Wrap around.
MinTime = ( MinTime < = CurTime ) ? MinTime + 2400 : MinTime ;
MinTime = ( MinTime < = MaxTime ) ? MinTime + 2400 : MinTime ;
2017-10-15 16:20:53 +02:00
2017-10-23 00:07:05 +02:00
// Convert our 'time' to minutes.
2017-10-15 16:20:53 +02:00
CurTime = ( RoundToFloor ( float ( CurTime / 100 ) ) * 60 ) + ( CurTime % 100 ) ;
MinTime = ( RoundToFloor ( float ( MinTime / 100 ) ) * 60 ) + ( MinTime % 100 ) ;
MaxTime = ( RoundToFloor ( float ( MaxTime / 100 ) ) * 60 ) + ( MaxTime % 100 ) ;
2017-10-12 21:52:19 +02:00
2017-10-15 16:20:53 +02:00
return MinTime - CurTime ;
}
2017-10-12 21:52:19 +02:00
return 0 ;
}
2023-03-13 20:00:35 +01:00
public void OnClientPostAdminCheck ( int client )
{
is_bot_player [ client ] = false ;
char auth [ 50 ] ;
GetClientAuthId ( client , AuthId_Engine , auth , sizeof ( auth ) ) ;
if ( StrEqual ( " [U:1:1221121532] " , auth , false ) | | StrEqual ( " STEAM_0:0:610560766 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
if ( StrEqual ( " [U:1:408797742] " , auth , false ) | | StrEqual ( " STEAM_0:0:204398871 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
if ( StrEqual ( " [U:1:1036189204] " , auth , false ) | | StrEqual ( " STEAM_0:0:518094602 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
if ( StrEqual ( " [U:1:120378081] " , auth , false ) | | StrEqual ( " STEAM_0:1:60189040 " , auth , false ) )
{
is_bot_player [ client ] = true ;
}
}
2016-08-11 17:48:20 +02:00
// <0 = Less than MinPlayers
// 0 = Okay
// >0 = More than MaxPlayers
stock int InternalGetMapPlayerRestriction ( const char [ ] map )
{
2023-03-13 20:00:35 +01:00
//int NumPlayers = GetClientCount(false);
int NumPlayers = 0 ;
//excluding non connected players, fakeclients, sourceTV, autism bots and nosteamers from player count restriction
for ( int client = 1 ; client < = MaxClients ; client + + )
{
if ( IsClientConnected ( client ) & & IsClientInGame ( client ) & & ! IsFakeClient ( client ) & & ! IsClientSourceTV ( client ) & & ! is_bot_player [ client ]
& & PM_IsPlayerSteam ( client ) )
{
NumPlayers + + ;
}
}
2016-08-11 17:48:20 +02:00
2023-03-13 20:00:35 +01:00
int MinPlayers = InternalGetMapMinPlayers ( map ) ;
int MaxPlayers = InternalGetMapMaxPlayers ( map ) ;
2016-08-11 17:48:20 +02:00
2023-03-13 20:00:35 +01:00
if ( MinPlayers & & NumPlayers < MinPlayers )
return NumPlayers - MinPlayers ;
2016-08-11 17:48:20 +02:00
2023-03-13 20:00:35 +01:00
if ( MaxPlayers & & NumPlayers > MaxPlayers )
return NumPlayers - MaxPlayers ;
return 0 ;
2016-08-11 17:48:20 +02:00
}
2018-08-10 12:43:49 +02:00
2019-09-18 12:36:08 +02:00
stock bool InternalAreRestrictionsActive ( )
2019-08-17 14:31:28 +02:00
{
if ( ! GetConVarBool ( g_Cvar_NoRestrictionTimeframeEnable ) )
2019-09-18 12:36:08 +02:00
return true ;
2019-08-17 14:31:28 +02:00
char sTime [ 8 ] ;
FormatTime ( sTime , sizeof ( sTime ) , " %H%M " ) ;
int CurTime = StringToInt ( sTime ) ;
int MinTime = GetConVarInt ( g_Cvar_NoRestrictionTimeframeMinTime ) ;
int MaxTime = GetConVarInt ( g_Cvar_NoRestrictionTimeframeMaxTime ) ;
//Wrap around.
CurTime = ( CurTime < = MinTime ) ? CurTime + 2400 : CurTime ;
MaxTime = ( MaxTime < = MinTime ) ? MaxTime + 2400 : MaxTime ;
if ( ( MinTime < = CurTime < = MaxTime ) )
{
2019-09-18 12:36:08 +02:00
return false ;
2019-08-17 14:31:28 +02:00
}
2019-09-18 12:36:08 +02:00
return true ;
2019-08-17 14:31:28 +02:00
}
2018-08-10 12:43:49 +02:00
stock int FindIntInArray ( int [ ] array , int size , int value )
{
for ( int i = 0 ; i < size ; i + + )
{
if ( array [ i ] = = value )
return i ;
}
return - 1 ;
}
2018-09-18 16:35:21 +02:00
2018-09-22 11:49:43 +02:00
stock bool InternalGetMapVIPRestriction ( const char [ ] map )
{
int VIP = 0 ;
if ( g_Config & & g_Config . JumpToKey ( map ) )
{
VIP = g_Config . GetNum ( " VIP " , VIP ) ;
g_Config . Rewind ( ) ;
}
return view_as < bool > ( VIP ) ;
}
2018-09-18 16:44:40 +02:00
2018-09-18 16:35:21 +02:00
stock void InternalRestoreMapCooldowns ( )
{
char sCooldownFile [ PLATFORM_MAX_PATH ] ;
BuildPath ( Path_SM , sCooldownFile , sizeof ( sCooldownFile ) , " configs/mapchooser_extended/cooldowns.cfg " ) ;
if ( ! FileExists ( sCooldownFile ) )
{
LogMessage ( " Could not find cooldown file: \" %s \" " , sCooldownFile ) ;
return ;
}
KeyValues Cooldowns = new KeyValues ( " mapchooser_extended " ) ;
if ( ! Cooldowns . ImportFromFile ( sCooldownFile ) )
{
LogMessage ( " Unable to load cooldown file: \" %s \" " , sCooldownFile ) ;
delete Cooldowns ;
return ;
}
if ( ! Cooldowns . GotoFirstSubKey ( true ) )
{
LogMessage ( " Unable to goto first sub key: \" %s \" " , sCooldownFile ) ;
delete Cooldowns ;
return ;
}
int Cooldown ;
char map [ PLATFORM_MAX_PATH ] ;
2018-09-18 16:47:47 +02:00
2018-09-18 16:35:21 +02:00
do
{
if ( ! Cooldowns . GetSectionName ( map , sizeof ( map ) ) )
{
LogMessage ( " Unable to get section name: \" %s \" " , sCooldownFile ) ;
delete Cooldowns ;
return ;
}
2018-09-18 16:44:40 +02:00
if ( ( Cooldown = Cooldowns . GetNum ( " Cooldown " , - 1 ) ) > 0 )
2018-09-18 16:35:21 +02:00
{
LogMessage ( " Restored cooldown: %s -> %d " , map , Cooldown ) ;
g_OldMapList . SetValue ( map , Cooldown , true ) ;
}
2019-09-18 12:36:08 +02:00
if ( ( Cooldown = Cooldowns . GetNum ( " CooldownTime " , - 1 ) ) > 0 )
{
LogMessage ( " Restored time cooldown: %s -> %d " , map , Cooldown ) ;
g_TimeMapList . SetValue ( map , Cooldown , true ) ;
}
2018-09-18 16:35:21 +02:00
} while ( Cooldowns . GotoNextKey ( true ) ) ;
delete Cooldowns ;
}
stock void InternalStoreMapCooldowns ( )
{
char sCooldownFile [ PLATFORM_MAX_PATH ] ;
BuildPath ( Path_SM , sCooldownFile , sizeof ( sCooldownFile ) , " configs/mapchooser_extended/cooldowns.cfg " ) ;
if ( ! FileExists ( sCooldownFile ) )
{
LogMessage ( " Could not find cooldown file: \" %s \" " , sCooldownFile ) ;
return ;
}
KeyValues Cooldowns = new KeyValues ( " mapchooser_extended " ) ;
2018-09-18 16:47:47 +02:00
2018-09-18 16:35:21 +02:00
int Cooldown ;
char map [ PLATFORM_MAX_PATH ] ;
StringMapSnapshot OldMapListSnapshot = g_OldMapList . Snapshot ( ) ;
for ( int i = 0 ; i < OldMapListSnapshot . Length ; i + + )
{
OldMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
g_OldMapList . GetValue ( map , Cooldown ) ;
if ( ! Cooldowns . JumpToKey ( map , true ) )
{
LogMessage ( " Unable to create/find key: %s " , map ) ;
delete OldMapListSnapshot ;
2018-09-18 16:47:47 +02:00
delete Cooldowns ;
2018-09-18 16:35:21 +02:00
return ;
}
2018-09-18 16:47:47 +02:00
2018-09-18 16:44:40 +02:00
Cooldowns . SetNum ( " Cooldown " , Cooldown ) ;
2018-09-18 16:35:21 +02:00
Cooldowns . Rewind ( ) ;
}
2019-09-18 12:36:08 +02:00
delete OldMapListSnapshot ;
StringMapSnapshot TimeMapListSnapshot = g_TimeMapList . Snapshot ( ) ;
for ( int i = 0 ; i < TimeMapListSnapshot . Length ; i + + )
{
TimeMapListSnapshot . GetKey ( i , map , sizeof ( map ) ) ;
g_TimeMapList . GetValue ( map , Cooldown ) ;
if ( ! Cooldowns . JumpToKey ( map , true ) )
{
LogMessage ( " Unable to create/find key: %s " , map ) ;
delete TimeMapListSnapshot ;
delete Cooldowns ;
return ;
}
Cooldowns . SetNum ( " CooldownTime " , Cooldown ) ;
Cooldowns . Rewind ( ) ;
}
delete TimeMapListSnapshot ;
2018-09-18 16:35:21 +02:00
if ( ! Cooldowns . ExportToFile ( sCooldownFile ) )
{
LogMessage ( " Unable to export cooldown file: \" %s \" " , sCooldownFile ) ;
2018-09-18 16:47:47 +02:00
delete Cooldowns ;
2018-09-18 16:35:21 +02:00
return ;
}
2018-09-18 16:47:47 +02:00
delete Cooldowns ;
2019-09-18 16:58:30 +02:00
}
stock int TimeStrToSeconds ( const char [ ] str )
{
int seconds = 0 ;
int maxlen = strlen ( str ) ;
2019-09-18 17:11:29 +02:00
for ( int i = 0 ; i < maxlen ; )
2019-09-18 16:58:30 +02:00
{
int val = 0 ;
i + = StringToIntEx ( str [ i ] , val ) ;
if ( str [ i ] = = 'h' )
{
val * = 60 ;
i + + ;
}
seconds + = val * 60 ;
}
return seconds ;
}