dvander@1889: /** dvander@1889: * vim: set ts=4 : dvander@1889: * ============================================================================= dvander@1889: * SourceMod Rock The Vote Plugin dvander@1889: * Creates a map vote when the required number of players have requested one. dvander@1889: * ds@1947: * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. dvander@1889: * ============================================================================= dvander@1889: * dvander@1889: * This program is free software; you can redistribute it and/or modify it under dvander@1889: * the terms of the GNU General Public License, version 3.0, as published by the dvander@1889: * Free Software Foundation. dvander@1889: * dvander@1889: * This program is distributed in the hope that it will be useful, but WITHOUT dvander@1889: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@1889: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more dvander@1889: * details. dvander@1889: * dvander@1889: * You should have received a copy of the GNU General Public License along with dvander@1889: * this program. If not, see . dvander@1889: * dvander@1889: * As a special exception, AlliedModders LLC gives you permission to link the dvander@1889: * code of this program (as well as its derivative works) to "Half-Life 2," the dvander@1889: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software dvander@1889: * by the Valve Corporation. You must obey the GNU General Public License in dvander@1889: * all respects for all other code used. Additionally, AlliedModders LLC grants dvander@1889: * this exception to all derivative works. AlliedModders LLC defines further dvander@1889: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), dvander@1889: * or . dvander@1889: * dvander@1889: * Version: $Id$ dvander@1889: */ dvander@1889: dvander@1889: #include pred@2133: #include pred@2133: #include dvander@1889: dvander@1889: #pragma semicolon 1 dvander@1889: dvander@1889: public Plugin:myinfo = dvander@1889: { dvander@1889: name = "Rock The Vote", dvander@1889: author = "AlliedModders LLC", dvander@1889: description = "Provides RTV Map Voting", dvander@1889: version = SOURCEMOD_VERSION, dvander@1889: url = "http://www.sourcemod.net/" dvander@1889: }; dvander@1889: dvander@1889: new Handle:g_Cvar_Needed = INVALID_HANDLE; dvander@1889: new Handle:g_Cvar_MinPlayers = INVALID_HANDLE; pred@2133: new Handle:g_Cvar_InitialDelay = INVALID_HANDLE; pred@2133: new Handle:g_Cvar_Interval = INVALID_HANDLE; pred@2133: new Handle:g_Cvar_ChangeTime = INVALID_HANDLE; pred@2133: new Handle:g_Cvar_RTVPostVoteAction = INVALID_HANDLE; dvander@1889: dvander@1889: new bool:g_CanRTV = false; // True if RTV loaded maps and is active. dvander@1889: new bool:g_RTVAllowed = false; // True if RTV is available to players. Used to delay rtv votes. dvander@1889: new g_Voters = 0; // Total voters connected. Doesn't include fake clients. dvander@1889: new g_Votes = 0; // Total number of "say rtv" votes dvander@1889: new g_VotesNeeded = 0; // Necessary votes before map vote begins. (voters * percent_needed) dvander@1889: new bool:g_Voted[MAXPLAYERS+1] = {false, ...}; pred@2133: pred@2133: new bool:g_InChange = false; dvander@1889: dvander@1889: public OnPluginStart() dvander@1889: { dvander@1889: LoadTranslations("common.phrases"); ferret99gt@1478: LoadTranslations("rockthevote.phrases"); ferret99gt@1478: dvander@1889: g_Cvar_Needed = CreateConVar("sm_rtv_needed", "0.60", "Percentage of players needed to rockthevote (Def 60%)", 0, true, 0.05, true, 1.0); dvander@1889: g_Cvar_MinPlayers = CreateConVar("sm_rtv_minplayers", "0", "Number of players required before RTV will be enabled.", 0, true, 0.0, true, float(MAXPLAYERS)); pred@2212: g_Cvar_InitialDelay = CreateConVar("sm_rtv_initialdelay", "30.0", "Time (in seconds) before first RTV can be held", 0, true, 0.00); pred@2212: 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); pred@2133: 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); pred@2133: g_Cvar_RTVPostVoteAction = CreateConVar("sm_rtv_postvoteaction", "0", "What to do with RTV's after a mapvote has completed. 0 - Allow, success = instant change, 1 - Deny", _, true, 0.0, true, 1.0); dvander@1889: dvander@1889: RegConsoleCmd("say", Command_Say); dvander@1889: RegConsoleCmd("say_team", Command_Say); dvander@1889: pred@2133: RegConsoleCmd("sm_rtv", Command_RTV); ferret99gt@1478: dvander@1889: AutoExecConfig(true, "rtv"); dvander@1889: } ferret99gt@1703: ferret99gt@1703: public OnMapStart() ferret99gt@1703: { ferret99gt@1703: g_Voters = 0; ferret99gt@1703: g_Votes = 0; ferret99gt@1703: g_VotesNeeded = 0; pred@2133: g_InChange = false; pred@2133: pred@2133: /* Handle late load */ pred@2361: for (new i=1; i<=MaxClients; i++) pred@2133: { pred@2133: if (IsClientConnected(i)) pred@2133: { pred@2370: OnClientConnected(i); pred@2133: } pred@2133: } ferret99gt@1703: } dvander@1889: dvander@1889: public OnMapEnd() ferret99gt@1478: { dvander@1889: g_CanRTV = false; dvander@1889: g_RTVAllowed = false; dvander@1889: } dvander@1889: ferret99gt@1713: public OnConfigsExecuted() pred@2133: { dvander@1889: g_CanRTV = true; pred@2133: g_RTVAllowed = false; pred@2133: CreateTimer(GetConVarFloat(g_Cvar_InitialDelay), Timer_DelayRTV, _, TIMER_FLAG_NO_MAPCHANGE); ferret99gt@1713: } dvander@1889: pred@2366: public OnClientConnected(client) dvander@1889: { pred@2133: if(IsFakeClient(client)) pred@2366: return; dvander@1889: dvander@1889: g_Voted[client] = false; dvander@1889: dvander@1889: g_Voters++; dvander@1889: g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); dvander@1889: pred@2366: return; dvander@1889: } dvander@1889: dvander@1889: public OnClientDisconnect(client) dvander@1889: { pred@2366: if(IsFakeClient(client)) dvander@1889: return; ferret99gt@1494: dvander@1889: if(g_Voted[client]) dvander@1889: { dvander@1889: g_Votes--; dvander@1889: } dvander@1889: dvander@1889: g_Voters--; dvander@1889: dvander@1889: g_VotesNeeded = RoundToFloor(float(g_Voters) * GetConVarFloat(g_Cvar_Needed)); dvander@1889: pred@2366: if (!g_CanRTV) pred@2366: { pred@2366: return; pred@2366: } pred@2366: pred@2133: if (g_Votes && pred@2133: g_Voters && pred@2133: g_Votes >= g_VotesNeeded && pred@2133: g_RTVAllowed ) ferret99gt@1712: { pred@2133: if (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished()) pred@2133: { pred@2133: return; pred@2133: } pred@2133: pred@2133: StartRTV(); dvander@1889: } dvander@1889: } dvander@1889: pred@2133: public Action:Command_RTV(client, args) dvander@1889: { pred@2133: if (!g_CanRTV || !client) ferret99gt@1712: { erik@3165: return Plugin_Handled; dvander@1889: } dvander@1889: pred@2133: AttemptRTV(client); dvander@1889: erik@3165: return Plugin_Handled; dvander@1889: } dvander@1889: dvander@1889: public Action:Command_Say(client, args) dvander@1889: { ferret99gt@1713: if (!g_CanRTV || !client) dvander@1889: { dvander@1889: return Plugin_Continue; dvander@1889: } pred@2133: dvander@1889: decl String:text[192]; dvander@1889: if (!GetCmdArgString(text, sizeof(text))) dvander@1889: { ferret99gt@1713: return Plugin_Continue; dvander@1889: } dvander@1889: dvander@1889: new startidx = 0; dvander@1889: if(text[strlen(text)-1] == '"') dvander@1889: { dvander@1889: text[strlen(text)-1] = '\0'; dvander@1889: startidx = 1; dvander@1889: } dvander@1889: pred@2133: new ReplySource:old = SetCmdReplySource(SM_REPLY_TO_CHAT); pred@2133: dvander@1889: if (strcmp(text[startidx], "rtv", false) == 0 || strcmp(text[startidx], "rockthevote", false) == 0) dvander@1889: { pred@2133: AttemptRTV(client); pred@2133: } pred@2133: pred@2133: SetCmdReplySource(old); pred@2133: pred@2133: return Plugin_Continue; pred@2133: } pred@2133: pred@2133: AttemptRTV(client) pred@2133: { pred@2133: if (!g_RTVAllowed || (GetConVarInt(g_Cvar_RTVPostVoteAction) == 1 && HasEndOfMapVoteFinished())) pred@2133: { pred@2133: ReplyToCommand(client, "[SM] %t", "RTV Not Allowed"); pred@2133: return; pred@2133: } dvander@1889: pred@2133: if (!CanMapChooserStartVote()) dvander@1889: { pred@2133: ReplyToCommand(client, "[SM] %t", "RTV Started"); pred@2133: return; dvander@1889: } dvander@1889: pred@2133: if (GetClientCount(true) < GetConVarInt(g_Cvar_MinPlayers)) pred@2133: { pred@2133: ReplyToCommand(client, "[SM] %t", "Minimal Players Not Met"); pred@2133: return; pred@2133: } pred@2133: pred@2133: if (g_Voted[client]) pred@2133: { pred@2802: ReplyToCommand(client, "[SM] %t", "Already Voted", g_Votes, g_VotesNeeded); pred@2133: return; pred@2133: } pred@2133: pred@2133: new String:name[64]; pred@2133: GetClientName(client, name, sizeof(name)); pred@2133: pred@2133: g_Votes++; pred@2133: g_Voted[client] = true; pred@2133: pred@2133: PrintToChatAll("[SM] %t", "RTV Requested", name, g_Votes, g_VotesNeeded); pred@2133: pred@2133: if (g_Votes >= g_VotesNeeded) pred@2133: { pred@2133: StartRTV(); pred@2133: } dvander@1889: } dvander@1889: dvander@1889: public Action:Timer_DelayRTV(Handle:timer) dvander@1889: { ferret99gt@1777: g_RTVAllowed = true; dvander@1889: } dvander@1889: pred@2133: StartRTV() dvander@1889: { pred@2133: if (g_InChange) dvander@1889: { pred@2133: return; ferret99gt@1478: } ferret99gt@1478: pred@2223: if (EndOfMapVoteEnabled() && HasEndOfMapVoteFinished()) dvander@1889: { pred@2133: /* Change right now then */ pred@2133: new String:map[65]; pred@2133: if (GetNextMap(map, sizeof(map))) dvander@1889: { pred@2133: PrintToChatAll("[SM] %t", "Changing Maps", map); pred@2133: CreateTimer(5.0, Timer_ChangeMap, _, TIMER_FLAG_NO_MAPCHANGE); pred@2133: g_InChange = true; pred@2133: pred@2133: ResetRTV(); dvander@1889: pred@2133: g_RTVAllowed = false; dvander@1889: } pred@2133: return; pred@2133: } pred@2133: pred@2133: if (CanMapChooserStartVote()) pred@2133: { pred@2133: new MapChange:when = MapChange:GetConVarInt(g_Cvar_ChangeTime); pred@2133: InitiateMapChooserVote(when); pred@2133: pred@2133: ResetRTV(); pred@2133: pred@2133: g_RTVAllowed = false; pred@2133: CreateTimer(GetConVarFloat(g_Cvar_Interval), Timer_DelayRTV, _, TIMER_FLAG_NO_MAPCHANGE); dvander@1889: } dvander@1889: } dvander@1889: pred@2133: ResetRTV() dvander@1889: { pred@2133: g_Votes = 0; pred@2133: pred@2133: for (new i=1; i<=MAXPLAYERS; i++) dvander@1889: { pred@2133: g_Voted[i] = false; pred@2133: } pred@2133: } pred@2133: pred@2133: public Action:Timer_ChangeMap(Handle:hTimer) pred@2133: { pred@2133: g_InChange = false; pred@2133: pred@2133: LogMessage("RTV changing map manually"); pred@2133: pred@2133: new String:map[65]; pred@2133: if (GetNextMap(map, sizeof(map))) pred@2133: { pred@2203: ForceChangeLevel(map, "RTV after mapvote"); dvander@1889: } dvander@1889: pred@2133: return Plugin_Stop; ferret99gt@1478: }