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: }