2008-02-22 22:01:08 +01:00
/ * *
* vim : set ts = 4 :
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* SourceMod Rock The Vote Plugin
* Creates a map vote when the required number of players have requested one .
*
* 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 $
* /
# include <sourcemod>
# pragma semicolon 1
public Plugin : myinfo =
{
name = " Rock The Vote " ,
author = " AlliedModders LLC " ,
description = " Provides RTV Map Voting " ,
version = SOURCEMOD_VERSION ,
url = " http://www.sourcemod.net/ "
} ;
new Handle : g_Cvar_Needed = INVALID_HANDLE ;
new Handle : g_Cvar_Maps = INVALID_HANDLE ;
new Handle : g_Cvar_Nominate = INVALID_HANDLE ;
new Handle : g_Cvar_MinPlayers = INVALID_HANDLE ;
new Handle : g_MapList = INVALID_HANDLE ;
new Handle : g_RTVMapList = INVALID_HANDLE ;
new Handle : g_MapMenu = INVALID_HANDLE ;
new Handle : g_RetryTimer = INVALID_HANDLE ;
new g_mapFileSerial = - 1 ;
new bool : g_CanRTV = false ; // True if RTV loaded maps and is active.
new bool : g_RTVAllowed = false ; // True if RTV is available to players. Used to delay rtv votes.
new bool : g_RTVStarted = false ; // Indicates that the actual map vote has started
new bool : g_RTVEnded = false ; // Indicates that the actual map vote has concluded
new g_Voters = 0 ; // Total voters connected. Doesn't include fake clients.
new g_Votes = 0 ; // Total number of "say rtv" votes
new g_VotesNeeded = 0 ; // Necessary votes before map vote begins. (voters * percent_needed)
new bool : g_Voted [ MAXPLAYERS + 1 ] = { false , . . . } ;
new bool : g_Nominated [ MAXPLAYERS + 1 ] = { false , . . . } ;
public OnPluginStart ( )
{
LoadTranslations ( " common.phrases " ) ;
2007-09-26 04:18:26 +02:00
LoadTranslations ( " rockthevote.phrases " ) ;
2007-11-10 00:46:05 +01:00
new arraySize = ByteCountToCells ( 33 ) ;
g_MapList = CreateArray ( arraySize ) ;
2008-02-22 22:01:08 +01:00
g_RTVMapList = CreateArray ( arraySize ) ;
g_Cvar_Needed = CreateConVar ( " sm_rtv_needed " , " 0.60 " , " Percentage of players needed to rockthevote (Def 60%) " , 0 , true , 0.05 , true , 1.0 ) ;
g_Cvar_Maps = CreateConVar ( " sm_rtv_maps " , " 4 " , " Number of maps to be voted on. 2 to 6. (Def 4) " , 0 , true , 2.0 , true , 6.0 ) ;
g_Cvar_Nominate = CreateConVar ( " sm_rtv_nominate " , " 1 " , " Enables nomination system. " , 0 , true , 0.0 , 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 ) ) ;
RegConsoleCmd ( " say " , Command_Say ) ;
RegConsoleCmd ( " say_team " , Command_Say ) ;
2007-09-26 04:18:26 +02:00
RegAdminCmd ( " sm_rtv_addmap " , Command_Addmap , ADMFLAG_CHANGEMAP , " sm_rtv_addmap <mapname> - Forces a map to be on the RTV, and lowers the allowed nominations. " ) ;
2008-02-22 22:01:08 +01:00
AutoExecConfig ( true , " rtv " ) ;
}
2007-11-20 04:55:54 +01:00
public OnMapStart ( )
{
g_Voters = 0 ;
g_Votes = 0 ;
g_VotesNeeded = 0 ;
g_RTVStarted = false ;
g_RTVEnded = false ;
}
2008-02-22 22:01:08 +01:00
public OnMapEnd ( )
2007-09-26 04:18:26 +02:00
{
2008-02-22 22:01:08 +01:00
g_CanRTV = false ;
g_RTVAllowed = false ;
}
2007-11-23 02:13:13 +01:00
public OnConfigsExecuted ( )
{
if ( g_RTVMapList ! = INVALID_HANDLE )
{
ClearArray ( g_RTVMapList ) ;
}
2008-02-22 22:01:08 +01:00
if ( ReadMapList ( g_MapList ,
g_mapFileSerial ,
" rockthevote " ,
MAPLIST_FLAG_CLEARARRAY | MAPLIST_FLAG_MAPSFOLDER )
= = INVALID_HANDLE )
2007-11-23 02:13:13 +01:00
{
2008-02-22 22:01:08 +01:00
if ( g_mapFileSerial = = - 1 )
{
LogError ( " Unable to create a valid map list. " ) ;
}
2007-11-23 02:13:13 +01:00
}
2008-02-22 22:01:08 +01:00
BuildMapMenu ( ) ;
g_CanRTV = true ;
CreateTimer ( 30.0 , Timer_DelayRTV ) ;
2007-11-23 02:13:13 +01:00
}
2008-02-22 22:01:08 +01:00
public bool : OnClientConnect ( client , String : rejectmsg [ ] , maxlen )
{
if ( ! g_CanRTV | | IsFakeClient ( client ) )
return true ;
g_Voted [ client ] = false ;
g_Nominated [ client ] = false ;
g_Voters + + ;
g_VotesNeeded = RoundToFloor ( float ( g_Voters ) * GetConVarFloat ( g_Cvar_Needed ) ) ;
return true ;
}
public OnClientDisconnect ( client )
{
if ( ! g_CanRTV | | IsFakeClient ( client ) )
return ;
if ( g_Voted [ client ] )
{
g_Votes - - ;
}
g_Voters - - ;
g_VotesNeeded = RoundToFloor ( float ( g_Voters ) * GetConVarFloat ( g_Cvar_Needed ) ) ;
if ( g_Votes & & g_Voters & & g_Votes > = g_VotesNeeded & & g_RTVAllowed & & ! g_RTVStarted )
{
g_RTVStarted = true ;
CreateTimer ( 2.0 , Timer_StartRTV , TIMER_FLAG_NO_MAPCHANGE ) ;
}
}
public Action : Command_Addmap ( client , args )
{
if ( args < 1 )
2007-11-23 02:06:35 +01:00
{
2008-02-22 22:01:08 +01:00
ReplyToCommand ( client , " [SM] Usage: sm_rtv_addmap <mapname> " ) ;
return Plugin_Handled ;
2007-11-23 02:06:35 +01:00
}
if ( ! g_CanRTV )
{
ReplyToCommand ( client , " [SM] RockTheVote is not available. " ) ;
return Plugin_Handled ;
2008-02-22 22:01:08 +01:00
}
decl String : mapname [ 64 ] ;
GetCmdArg ( 1 , mapname , sizeof ( mapname ) ) ;
if ( FindStringInArray ( g_MapList , mapname ) = = - 1 )
{
ReplyToCommand ( client , " %t " , " Map was not found " , mapname ) ;
return Plugin_Handled ;
}
if ( GetArraySize ( g_RTVMapList ) > 0 )
2007-11-10 00:46:05 +01:00
{
if ( FindStringInArray ( g_RTVMapList , mapname ) ! = - 1 )
{
ReplyToCommand ( client , " %t " , " Map Already In Vote " , mapname ) ;
return Plugin_Handled ;
2008-02-22 22:01:08 +01:00
}
ShiftArrayUp ( g_RTVMapList , 0 ) ;
SetArrayString ( g_RTVMapList , 0 , mapname ) ;
while ( GetArraySize ( g_RTVMapList ) > GetConVarInt ( g_Cvar_Maps ) )
{
RemoveFromArray ( g_RTVMapList , GetConVarInt ( g_Cvar_Maps ) ) ;
}
}
else
{
PushArrayString ( g_RTVMapList , mapname ) ;
}
decl String : item [ 64 ] ;
for ( new i = 0 ; i < GetMenuItemCount ( g_MapMenu ) ; i + + )
{
GetMenuItem ( g_MapMenu , i , item , sizeof ( item ) ) ;
if ( strcmp ( item , mapname ) = = 0 )
{
RemoveMenuItem ( g_MapMenu , i ) ;
break ;
}
}
ReplyToCommand ( client , " %t " , " Map Inserted " , mapname ) ;
LogAction ( client , - 1 , " \" %L \" inserted map \" %s \" . " , client , mapname ) ;
return Plugin_Handled ;
}
public Action : Command_Say ( client , args )
{
2007-11-23 02:13:13 +01:00
if ( ! g_CanRTV | | ! client )
2008-02-22 22:01:08 +01:00
{
return Plugin_Continue ;
}
decl String : text [ 192 ] ;
if ( ! GetCmdArgString ( text , sizeof ( text ) ) )
{
2007-11-23 02:13:13 +01:00
return Plugin_Continue ;
2008-02-22 22:01:08 +01:00
}
new startidx = 0 ;
if ( text [ strlen ( text ) - 1 ] = = '"' )
{
text [ strlen ( text ) - 1 ] = '\0' ;
startidx = 1 ;
}
if ( strcmp ( text [ startidx ] , " rtv " , false ) = = 0 | | strcmp ( text [ startidx ] , " rockthevote " , false ) = = 0 )
{
if ( ! g_RTVAllowed )
{
PrintToChat ( client , " [SM] %t " , " RTV Not Allowed " ) ;
return Plugin_Continue ;
}
if ( g_RTVEnded )
{
PrintToChat ( client , " [SM] %t " , " RTV Ended " ) ;
return Plugin_Continue ;
}
if ( g_RTVStarted )
{
PrintToChat ( client , " [SM] %t " , " RTV Started " ) ;
return Plugin_Continue ;
}
if ( GetClientCount ( true ) < GetConVarInt ( g_Cvar_MinPlayers ) & & g_Votes = = 0 ) // Should we keep checking g_Votes here?
{
PrintToChat ( client , " [SM] %t " , " Minimal Players Not Met " ) ;
return Plugin_Continue ;
}
if ( g_Voted [ client ] )
{
PrintToChat ( client , " [SM] %t " , " Already Voted " ) ;
return Plugin_Continue ;
}
new String : name [ 64 ] ;
GetClientName ( client , name , sizeof ( name ) ) ;
g_Votes + + ;
g_Voted [ client ] = true ;
PrintToChatAll ( " [SM] %t " , " RTV Requested " , name , g_Votes , g_VotesNeeded ) ;
if ( g_Votes > = g_VotesNeeded )
{
g_RTVStarted = true ;
CreateTimer ( 2.0 , Timer_StartRTV , TIMER_FLAG_NO_MAPCHANGE ) ;
}
}
else if ( GetConVarBool ( g_Cvar_Nominate ) & & strcmp ( text [ startidx ] , " nominate " , false ) = = 0 )
{
if ( g_RTVEnded )
2007-11-23 02:06:35 +01:00
{
2008-02-22 22:01:08 +01:00
PrintToChat ( client , " [SM] %t " , " RTV Ended " ) ;
return Plugin_Continue ;
}
if ( g_RTVStarted )
{
PrintToChat ( client , " [SM] %t " , " RTV Started " ) ;
return Plugin_Continue ;
}
if ( g_Nominated [ client ] )
{
PrintToChat ( client , " [SM] %t " , " Already Nominated " ) ;
return Plugin_Continue ;
}
if ( GetArraySize ( g_RTVMapList ) > = GetConVarInt ( g_Cvar_Maps ) )
{
PrintToChat ( client , " [SM] %t " , " Max Nominations " ) ;
return Plugin_Continue ;
}
DisplayMenu ( g_MapMenu , client , MENU_TIME_FOREVER ) ;
}
return Plugin_Continue ;
}
public Action : Timer_DelayRTV ( Handle : timer )
{
2007-12-09 22:45:23 +01:00
g_RTVAllowed = true ;
g_RTVStarted = false ;
2008-02-22 22:01:08 +01:00
g_RTVEnded = false ;
}
public Action : Timer_StartRTV ( Handle : timer )
{
if ( timer = = g_RetryTimer )
{
g_RetryTimer = INVALID_HANDLE ;
}
if ( g_RetryTimer ! = INVALID_HANDLE )
{
return ;
}
if ( IsVoteInProgress ( ) )
{
// Can't start a vote, try again in 5 seconds.
g_RetryTimer = CreateTimer ( 5.0 , Timer_StartRTV , TIMER_FLAG_NO_MAPCHANGE ) ;
return ;
}
PrintToChatAll ( " [SM] %t " , " RTV Vote Ready " ) ;
new Handle : MapVoteMenu = CreateMenu ( Handler_MapMapVoteMenu , MenuAction : MENU_ACTIONS_ALL ) ;
SetMenuTitle ( MapVoteMenu , " Rock The Vote " ) ;
2007-11-10 00:46:05 +01:00
new Handle : tempMaps = CloneArray ( g_MapList ) ;
2007-10-09 00:13:17 +02:00
decl String : map [ 32 ] ;
2007-11-24 04:28:33 +01:00
GetCurrentMap ( map , sizeof ( map ) ) ;
new index = FindStringInArray ( tempMaps , map ) ;
if ( index ! = - 1 )
{
RemoveFromArray ( tempMaps , index ) ;
}
2007-09-26 04:18:26 +02:00
2007-10-09 00:13:17 +02:00
// We assume that g_RTVMapList is within the correct limits, based on the logic for nominations
for ( new i = 0 ; i < GetArraySize ( g_RTVMapList ) ; i + + )
2007-09-26 04:18:26 +02:00
{
2007-10-09 00:13:49 +02:00
GetArrayString ( g_RTVMapList , i , map , sizeof ( map ) ) ;
2007-10-09 00:13:17 +02:00
AddMenuItem ( MapVoteMenu , map , map ) ;
2007-11-24 04:28:33 +01:00
index = FindStringInArray ( tempMaps , map ) ;
2007-11-10 00:46:05 +01:00
if ( index ! = - 1 )
2007-10-09 00:13:17 +02:00
{
2007-11-10 00:46:05 +01:00
RemoveFromArray ( tempMaps , index ) ;
2007-10-09 00:13:17 +02:00
}
}
new limit = GetConVarInt ( g_Cvar_Maps ) - GetArraySize ( g_RTVMapList ) ;
if ( limit > GetArraySize ( tempMaps ) )
{
limit = GetArraySize ( tempMaps ) ;
}
for ( new i = 0 ; i < limit ; i + + )
{
new b = GetRandomInt ( 0 , GetArraySize ( tempMaps ) - 1 ) ;
GetArrayString ( tempMaps , b , map , sizeof ( map ) ) ;
PushArrayString ( g_RTVMapList , map ) ;
AddMenuItem ( MapVoteMenu , map , map ) ;
RemoveFromArray ( tempMaps , b ) ;
}
2007-10-25 05:29:55 +02:00
CloseHandle ( tempMaps ) ;
2008-02-22 22:01:08 +01:00
AddMenuItem ( MapVoteMenu , " Don't Change " , " Don't Change " ) ;
SetMenuExitButton ( MapVoteMenu , false ) ;
VoteMenuToAll ( MapVoteMenu , 20 ) ;
LogMessage ( " [SM] Rockthevote was successfully started. " ) ;
}
public Action : Timer_ChangeMap ( Handle : hTimer , Handle : dp )
{
new String : map [ 65 ] ;
ResetPack ( dp ) ;
ReadPackString ( dp , map , sizeof ( map ) ) ;
ServerCommand ( " changelevel \" %s \" " , map ) ;
return Plugin_Stop ;
}
public Handler_MapMapVoteMenu ( Handle : menu , MenuAction : action , param1 , param2 )
{
switch ( action )
{
case MenuAction_End :
{
CloseHandle ( menu ) ;
}
case MenuAction_Display :
{
2007-09-26 04:18:26 +02:00
decl String : oldTitle [ 255 ] , String : buffer [ 255 ] ;
2008-02-22 22:01:08 +01:00
GetMenuTitle ( menu , oldTitle , sizeof ( oldTitle ) ) ;
Format ( buffer , sizeof ( buffer ) , " %T " , oldTitle , param1 ) ;
new Handle : panel = Handle : param2 ;
SetPanelTitle ( panel , buffer ) ;
2007-09-26 04:18:26 +02:00
}
case MenuAction_DisplayItem :
{
if ( GetMenuItemCount ( menu ) - 1 = = param2 )
{
decl String : buffer [ 255 ] ;
Format ( buffer , sizeof ( buffer ) , " %T " , " Don't Change " , param1 ) ;
return RedrawMenuItem ( buffer ) ;
}
2008-02-22 22:01:08 +01:00
}
// Why am I commented out? Because BAIL hasn't decided yet if
// vote notification will be built into the Vote API.
/ * case MenuAction_Select :
{
decl String : Name [ 32 ] , String : Map [ 32 ] ;
GetClientName ( param1 , Name , sizeof ( Name ) ) ;
GetMenuItem ( menu , param2 , Map , sizeof ( Map ) ) ;
PrintToChatAll ( " [SM] %s has voted for map '%s' " , Name , Map ) ;
} * /
case MenuAction_VoteCancel :
{
if ( param1 = = VoteCancel_NoVotes )
{
2007-11-23 02:13:13 +01:00
PrintToChatAll ( " [SM] %t " , " No Votes " ) ;
2008-02-22 22:01:08 +01:00
g_RTVEnded = true ;
}
}
case MenuAction_VoteEnd :
{
new String : map [ 64 ] ;
GetMenuItem ( menu , param1 , map , sizeof ( map ) ) ;
if ( GetMenuItemCount ( menu ) - 1 = = param1 ) // This should always match the "Keep Current" option
{
PrintToChatAll ( " [SM] %t " , " Current Map Stays " ) ;
LogMessage ( " [SM] Rockthevote has ended, current map kept. " ) ;
}
else
{
PrintToChatAll ( " [SM] %t " , " Changing Maps " , map ) ;
LogMessage ( " [SM] Rockthevote has ended, changing to map %s. " , map ) ;
new Handle : dp ;
CreateDataTimer ( 5.0 , Timer_ChangeMap , dp ) ;
WritePackString ( dp , map ) ;
}
g_RTVEnded = true ;
}
}
return 0 ;
}
public Handler_MapSelectMenu ( Handle : menu , MenuAction : action , param1 , param2 )
{
switch ( action )
{
case MenuAction_Select :
{
if ( GetArraySize ( g_RTVMapList ) > = GetConVarInt ( g_Cvar_Maps ) )
{
PrintToChat ( param1 , " [SM] %t " , " Max Nominations " ) ;
return ;
}
decl String : map [ 64 ] , String : name [ 64 ] ;
GetMenuItem ( menu , param2 , map , sizeof ( map ) ) ;
if ( FindStringInArray ( g_RTVMapList , map ) ! = - 1 )
{
PrintToChat ( param1 , " [SM] %t " , " Map Already Nominated " ) ;
return ;
}
GetClientName ( param1 , name , 64 ) ;
PushArrayString ( g_RTVMapList , map ) ;
RemoveMenuItem ( menu , param2 ) ;
g_Nominated [ param1 ] = true ;
PrintToChatAll ( " [SM] %t " , " Map Nominated " , name , map ) ;
}
}
}
BuildMapMenu ( )
{
if ( g_MapMenu ! = INVALID_HANDLE )
{
CloseHandle ( g_MapMenu ) ;
g_MapMenu = INVALID_HANDLE ;
}
g_MapMenu = CreateMenu ( Handler_MapSelectMenu ) ;
SetMenuTitle ( g_MapMenu , " %t " , " Nominate Title " ) ;
decl String : map [ 64 ] ;
for ( new i = 0 ; i < GetArraySize ( g_MapList ) ; i + + )
{
GetArrayString ( g_MapList , i , map , sizeof ( map ) ) ;
AddMenuItem ( g_MapMenu , map , map ) ;
2007-09-26 04:18:26 +02:00
}
2008-02-22 22:01:08 +01:00
SetMenuExitButton ( g_MapMenu , false ) ;
2007-09-26 04:18:26 +02:00
}