2023-09-12 16:10:32 +02:00
/ * *
* vim : set ts = 4 :
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Rock The Vote Extended
* Creates a map vote when the required number of players have requested one .
*
* Rock The Vote Extended ( C ) 2012 - 2013 Powerlord ( Ross Bemrose )
* SourceMod ( C ) 2004 - 2007 AlliedModders LLC . All rights reserved .
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU General Public License , version 3.0 , as published by the
* Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE . See the GNU General Public License for more
* details .
*
* You should have received a copy of the GNU General Public License along with
* this program . If not , see < 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 $
* /
# pragma semicolon 1
# pragma newdecls required
# include <sourcemod>
# include <sdktools_functions>
# include <mapchooser>
# include <nextmap>
# include <AFKManager>
# include <PlayerManager>
# include <unloze_playtime>
# define MCE_VERSION "1.3.1"
public Plugin myinfo =
{
name = " Rock The Vote Extended " ,
author = " Powerlord and AlliedModders LLC " ,
description = " Provides RTV Map Voting " ,
version = MCE_VERSION ,
url = " https://forums.alliedmods.net/showthread.php?t=156974 "
} ;
ConVar g_Cvar_Steam_Needed ;
ConVar g_Cvar_MinPlayers ;
ConVar g_Cvar_InitialDelay ;
ConVar g_Cvar_Interval ;
ConVar g_Cvar_ChangeTime ;
ConVar g_Cvar_RTVPostVoteAction ;
ConVar g_Cvar_RTVAutoDisable ;
ConVar g_Cvar_AFKTime ;
ConVar g_Cvar_RTVRevoteDelay ;
//check if autismbot
bool is_bot_player [ MAXPLAYERS + 1 ] ;
bool g_CanRTV = false ; // True if RTV loaded maps and is active.
bool g_RTVAllowed = false ; // True if RTV is available to players. Used to delay rtv votes.
int g_VotesNeeded = 0 ; // Necessary votes before map vote begins. (2023: voters average hour count * percent_needed)
bool g_Voted [ MAXPLAYERS + 1 ] = { false , . . . } ;
int g_iTimeTillRTV [ MAXPLAYERS + 1 ] = { 0 , . . . } ;
bool g_InChange = false ;
public void OnPluginStart ( )
{
LoadTranslations ( " common.phrases " ) ;
LoadTranslations ( " rockthevote_extended.phrases " ) ;
LoadTranslations ( " basevotes.phrases " ) ;
g_Cvar_Steam_Needed = CreateConVar ( " sm_rtv_steam_needed " , " 0.65 " , " Percentage of Steam players added to rockthevote calculation (Def 65%) " , 0 , true , 0.05 , true , 1.0 ) ;
g_Cvar_MinPlayers = CreateConVar ( " sm_rtv_minplayers " , " 0 " , " Number of players required before RTV will be enabled. " , 0 , true , 0.0 , true , float ( MAXPLAYERS ) ) ;
g_Cvar_InitialDelay = CreateConVar ( " sm_rtv_initialdelay " , " 30.0 " , " Time (in seconds) before first RTV can be held " , 0 , true , 0.00 ) ;
g_Cvar_Interval = CreateConVar ( " sm_rtv_interval " , " 240.0 " , " Time (in seconds) after a failed RTV before another can be held " , 0 , true , 0.00 ) ;
g_Cvar_ChangeTime = CreateConVar ( " sm_rtv_changetime " , " 0 " , " When to change the map after a succesful RTV: 0 - Instant, 1 - RoundEnd, 2 - MapEnd " , _ , true , 0.0 , true , 2.0 ) ;
g_Cvar_RTVPostVoteAction = CreateConVar ( " sm_rtv_postvoteaction " , " 0 " , " What to do with RTVs after a mapvote has completed. 0 - Allow, success = instant change, 1 - Deny " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_RTVAutoDisable = CreateConVar ( " sm_rtv_autodisable " , " 0 " , " Automatically disable RTV when map time is over. " , _ , true , 0.0 , true , 1.0 ) ;
g_Cvar_AFKTime = CreateConVar ( " sm_rtv_afk_time " , " 180 " , " AFK Time in seconds after which a player is not counted in the rtv ratio " ) ;
g_Cvar_RTVRevoteDelay = CreateConVar ( " sm_rtv_revote_delay " , " 5 " , " Delay in seconds before a player can vote for RTV after undoing " ) ;
RegConsoleCmd ( " sm_rtv " , Command_RTV ) ;
RegConsoleCmd ( " sm_unrtv " , Command_UnRTV ) ;
RegAdminCmd ( " sm_forcertv " , Command_ForceRTV , ADMFLAG_CHANGEMAP , " Force an RTV vote " ) ;
RegAdminCmd ( " sm_disablertv " , Command_DisableRTV , ADMFLAG_CHANGEMAP , " Disable the RTV command " ) ;
RegAdminCmd ( " sm_enablertv " , Command_EnableRTV , ADMFLAG_CHANGEMAP , " Enable the RTV command " ) ;
RegAdminCmd ( " sm_debugrtv " , Command_DebugRTV , ADMFLAG_CHANGEMAP , " Check the current RTV calculation " ) ;
HookEvent ( " player_team " , OnPlayerChangedTeam , EventHookMode_PostNoCopy ) ;
AutoExecConfig ( true , " rtv " ) ;
}
public void OnMapStart ( )
{
g_VotesNeeded = 0 ;
g_InChange = false ;
/* Handle late load */
for ( int i = 1 ; i < = MaxClients ; i + + )
{
if ( IsClientInGame ( i ) )
{
OnClientPutInServer ( i ) ;
}
}
}
public void OnMapEnd ( )
{
g_CanRTV = false ;
g_RTVAllowed = false ;
}
public void OnConfigsExecuted ( )
{
g_CanRTV = true ;
g_RTVAllowed = false ;
CreateTimer ( g_Cvar_InitialDelay . FloatValue , Timer_DelayRTV , _ , TIMER_FLAG_NO_MAPCHANGE ) ;
}
public void OnClientPutInServer ( int client )
{
g_iTimeTillRTV [ client ] = 0 ;
UpdateRTV ( ) ;
}
public void OnClientDisconnect ( int client )
{
is_bot_player [ client ] = false ;
if ( g_Voted [ client ] )
{
g_Voted [ client ] = false ;
g_iTimeTillRTV [ client ] = 0 ;
}
UpdateRTV ( ) ;
}
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 ;
}
}
public void OnPlayerChangedTeam ( Handle event , const char [ ] name , bool dontBroadcast )
{
UpdateRTV ( ) ;
}
2023-09-30 11:45:13 +02:00
public APLRes AskPluginLoad2 ( Handle myself , bool late , char [ ] error , int err_max )
{
CreateNative ( " GetRtvPercentage " , Native_GetRtvPercentageForClient ) ;
return APLRes_Success ;
}
public int Native_GetRtvPercentageForClient ( Handle plugin , int numParams )
{
int client = GetNativeCell ( 1 ) ;
if ( client > MaxClients | | client < = 0 )
{
ThrowNativeError ( SP_ERROR_NATIVE , " Client is not valid. " ) ;
return - 1 ;
}
if ( ! IsClientInGame ( client ) )
{
ThrowNativeError ( SP_ERROR_NATIVE , " Client is not in-game. " ) ;
return - 1 ;
}
UpdateRTV ( ) ;
int clients_percentage = 0 ;
if ( g_VotesNeeded = = 0 )
{
clients_percentage = RoundToFloor ( ( GetPlayerWorthRTV_ ( client ) / float ( 100 ) ) * 100 ) ;
}
else
{
clients_percentage = RoundToFloor ( ( GetPlayerWorthRTV_ ( client ) / float ( g_VotesNeeded ) ) * 100 ) ;
}
if ( clients_percentage > 100 )
{
clients_percentage = 100 ;
}
return clients_percentage ;
}
2023-09-12 16:10:32 +02:00
void UpdateRTV ( )
{
int iVotersSteam = 0 ;
for ( int i = 1 ; i < = MaxClients ; i + + )
{
if ( IsClientInGame ( i ) & & ! IsFakeClient ( i ) & & ! is_bot_player [ i ] )
{
if ( GetClientIdleTime ( i ) > = g_Cvar_AFKTime . IntValue )
continue ;
if ( PM_IsPlayerSteam ( i ) )
iVotersSteam + + ;
}
}
g_VotesNeeded = RoundToFloor ( float ( iVotersSteam ) * GetConVarFloat ( g_Cvar_Steam_Needed ) ) ;
g_VotesNeeded * = GetAveragePlayerTimeOnServerRTV ( ) ;
if ( ! g_CanRTV )
{
return ;
}
2023-09-17 00:29:00 +02:00
int Votes = get_voted_rtv ( ) ;
if ( Votes & &
2023-09-12 16:10:32 +02:00
iVotersSteam & &
2023-09-17 00:29:00 +02:00
Votes > = g_VotesNeeded & &
2023-09-12 16:10:32 +02:00
RTVAllowed ( ) )
{
if ( g_Cvar_RTVPostVoteAction . IntValue = = 1 & & HasEndOfMapVoteFinished ( ) )
{
return ;
}
StartRTV ( ) ;
}
}
2023-09-17 00:29:00 +02:00
public int get_voted_rtv ( )
{
int Votes = 0 ;
for ( int i = 0 ; i < MaxClients ; i + + )
{
if ( IsValidClient ( i ) & & g_Voted [ i ] )
{
Votes + = GetPlayerWorthRTV_ ( i ) ;
}
}
return Votes ;
}
2023-09-12 16:10:32 +02:00
public void OnClientSayCommand_Post ( int client , const char [ ] command , const char [ ] sArgs )
{
if ( ! g_CanRTV | | ! client )
{
return ;
}
if ( strcmp ( sArgs , " rtv " , false ) = = 0 | | strcmp ( sArgs , " rockthevote " , false ) = = 0 )
{
ReplySource old = SetCmdReplySource ( SM_REPLY_TO_CHAT ) ;
AttemptRTV ( client ) ;
SetCmdReplySource ( old ) ;
}
}
public Action Command_RTV ( int client , int args )
{
if ( ! g_CanRTV | | ! client )
{
return Plugin_Handled ;
}
AttemptRTV ( client ) ;
return Plugin_Handled ;
}
void AttemptRTV ( int client )
{
if ( ! RTVAllowed ( ) | | ( g_Cvar_RTVPostVoteAction . IntValue = = 1 & & HasEndOfMapVoteFinished ( ) ) )
{
ReplyToCommand ( client , " [RTVE] %t " , " RTV Not Allowed " ) ;
return ;
}
if ( ! CanMapChooserStartVote ( ) )
{
ReplyToCommand ( client , " [RTVE] %t " , " RTV Started " ) ;
return ;
}
if ( GetClientCount ( true ) < g_Cvar_MinPlayers . IntValue )
{
ReplyToCommand ( client , " [RTVE] %t " , " Minimal Players Not Met " ) ;
return ;
}
if ( GetTime ( ) < g_iTimeTillRTV [ client ] )
{
ReplyToCommand ( client , " [RTVE] %t " , " Wait Before Revoting " , g_iTimeTillRTV [ client ] - GetTime ( ) ) ;
return ;
}
if ( g_Voted [ client ] )
{
float rtv_worth = GetPlayerWorthRTV_boost_ ( client ) ;
2023-09-17 00:29:00 +02:00
int Votes = get_voted_rtv ( ) ;
2023-09-12 21:20:16 +02:00
if ( g_VotesNeeded = = 0 )
{
2023-09-17 00:29:00 +02:00
g_VotesNeeded = Votes ;
}
int rtv_percentage_reached = RoundToFloor ( ( float ( Votes ) / float ( g_VotesNeeded ) ) * 100 ) ;
if ( rtv_percentage_reached > 100 )
{
rtv_percentage_reached = 100 ;
2023-09-12 21:20:16 +02:00
}
2023-09-30 10:05:40 +02:00
int clients_percentage = RoundToFloor ( ( GetPlayerWorthRTV_ ( client ) / float ( g_VotesNeeded ) ) * 100 ) ;
if ( clients_percentage > 100 )
{
clients_percentage = 100 ;
}
ReplyToCommand ( client , " [RTVE] %t " , " Already Voted " , rtv_percentage_reached , rtv_worth , clients_percentage ) ;
2023-09-12 16:10:32 +02:00
return ;
}
if ( ! PM_IsPlayerSteam ( client ) )
{
ReplyToCommand ( client , " Disabled rtv participation for nosteamers. " ) ;
return ;
}
char name [ MAX_NAME_LENGTH ] ;
GetClientName ( client , name , sizeof ( name ) ) ;
g_Voted [ client ] = true ;
2023-09-17 00:29:00 +02:00
int Votes = get_voted_rtv ( ) ;
2023-09-12 16:10:32 +02:00
float rtv_worth = GetPlayerWorthRTV_boost_ ( client ) ;
2023-09-12 21:20:16 +02:00
if ( g_VotesNeeded = = 0 )
{
2023-09-17 00:29:00 +02:00
g_VotesNeeded = Votes ;
}
int rtv_percentage_reached = RoundToFloor ( ( float ( Votes ) / float ( g_VotesNeeded ) ) * 100 ) ;
2024-09-19 18:59:28 +02:00
if ( rtv_percentage_reached > 100 | | rtv_percentage_reached < 0 )
2023-09-17 00:29:00 +02:00
{
rtv_percentage_reached = 100 ;
2023-09-12 21:20:16 +02:00
}
2023-09-30 10:05:40 +02:00
int clients_percentage = RoundToFloor ( ( GetPlayerWorthRTV_ ( client ) / float ( g_VotesNeeded ) ) * 100 ) ;
2024-09-19 18:59:28 +02:00
if ( clients_percentage > 100 | | clients_percentage < 0 )
2023-09-30 10:05:40 +02:00
{
clients_percentage = 100 ;
}
PrintToChatAll ( " [RTVE] %t " , " RTV Requested " , name , rtv_percentage_reached , rtv_worth , clients_percentage ) ;
2023-09-12 16:10:32 +02:00
2023-09-17 00:29:00 +02:00
if ( Votes > = g_VotesNeeded )
2023-09-12 16:10:32 +02:00
{
StartRTV ( ) ;
}
}
public Action Command_UnRTV ( int client , int args )
{
if ( ! g_CanRTV | | ! client )
{
return Plugin_Handled ;
}
AttemptUnRTV ( client ) ;
return Plugin_Handled ;
}
void AttemptUnRTV ( int client )
{
if ( ! g_Voted [ client ] )
{
ReplyToCommand ( client , " [RTVE] %t " , " Didn't RTV Yet " ) ; //'
return ;
}
char name [ MAX_NAME_LENGTH ] ;
GetClientName ( client , name , sizeof ( name ) ) ;
g_Voted [ client ] = false ;
g_iTimeTillRTV [ client ] = GetTime ( ) + g_Cvar_RTVRevoteDelay . IntValue ;
ReplyToCommand ( client , " [RTVE] %t " , " RTV Undone " ) ;
}
public Action Timer_DelayRTV ( Handle timer )
{
g_RTVAllowed = true ;
PrintToChatAll ( " [RTVE] RockTheVote is available now! " ) ;
return Plugin_Handled ;
}
void StartRTV ( )
{
if ( g_InChange )
{
return ;
}
if ( EndOfMapVoteEnabled ( ) & & HasEndOfMapVoteFinished ( ) )
{
/* Change right now then */
char map [ PLATFORM_MAX_PATH ] ;
if ( GetNextMap ( map , sizeof ( map ) ) )
{
GetMapDisplayName ( map , map , sizeof ( map ) ) ;
PrintToChatAll ( " [RTVE] %t " , " Changing Maps " , map ) ;
CreateTimer ( 5.0 , Timer_ChangeMap , _ , TIMER_FLAG_NO_MAPCHANGE ) ;
g_InChange = true ;
ResetRTV ( ) ;
g_RTVAllowed = false ;
}
return ;
}
if ( CanMapChooserStartVote ( ) )
{
MapChange when = view_as < MapChange > ( g_Cvar_ChangeTime . IntValue ) ;
InitiateMapChooserVote ( when ) ;
ResetRTV ( ) ;
g_RTVAllowed = false ;
CreateTimer ( g_Cvar_Interval . FloatValue , Timer_DelayRTV , _ , TIMER_FLAG_NO_MAPCHANGE ) ;
}
}
void ResetRTV ( )
{
for ( int i = 1 ; i < = MAXPLAYERS ; i + + )
{
g_Voted [ i ] = false ;
}
}
public Action Timer_ChangeMap ( Handle hTimer )
{
g_InChange = false ;
LogMessage ( " RTV changing map manually " ) ;
char map [ PLATFORM_MAX_PATH ] ;
if ( GetNextMap ( map , sizeof ( map ) ) )
{
ForceChangeLevel ( map , " RTV after mapvote " ) ;
}
return Plugin_Stop ;
}
public Action Command_ForceRTV ( int client , int args )
{
if ( ! g_CanRTV )
return Plugin_Handled ;
ShowActivity2 ( client , " [RTVE] " , " %t " , " Initiated Vote Map " ) ;
StartRTV ( ) ;
return Plugin_Handled ;
}
public Action Command_DisableRTV ( int client , int args )
{
if ( ! g_RTVAllowed )
return Plugin_Handled ;
ShowActivity2 ( client , " [RTVE] " , " disabled RockTheVote. " ) ;
g_RTVAllowed = false ;
return Plugin_Handled ;
}
public Action Command_EnableRTV ( int client , int args )
{
if ( g_RTVAllowed )
return Plugin_Handled ;
ShowActivity2 ( client , " [RTVE] " , " enabled RockTheVote " ) ;
g_RTVAllowed = true ;
return Plugin_Handled ;
}
public Action Command_DebugRTV ( int client , int args )
{
if ( ! g_RTVAllowed )
{
ReplyToCommand ( client , " [RTVE] RockTheVote is currently disabled. " ) ;
return Plugin_Handled ;
}
int iVotersSteam = 0 ;
for ( int i = 1 ; i < = MaxClients ; i + + )
{
if ( IsClientInGame ( i ) & & ! IsFakeClient ( i ) & & ! is_bot_player [ i ] )
{
if ( GetClientIdleTime ( i ) > = g_Cvar_AFKTime . IntValue )
continue ;
if ( PM_IsPlayerSteam ( i ) )
iVotersSteam + + ;
}
}
int iVotesNeededTotal = RoundToFloor ( float ( iVotersSteam ) * GetConVarFloat ( g_Cvar_Steam_Needed ) ) ;
ReplyToCommand ( client , " [RTVE] Currently %d Players needed to start a RTV vote. " , iVotesNeededTotal ) ;
return Plugin_Handled ;
}
bool RTVAllowed ( )
{
if ( ! g_RTVAllowed )
return false ;
int time ;
if ( g_Cvar_RTVAutoDisable . BoolValue & & GetMapTimeLeft ( time ) & & time = = 0 )
return false ;
return true ;
}
2023-09-17 00:29:00 +02:00
stock bool IsValidClient ( int client )
{
if ( client > 0 & & client < = MaxClients & & IsClientConnected ( client ) & & IsClientInGame ( client ) )
return true ;
return false ;
}