plugins/funvotes.sp
author David Anderson <dvander@alliedmods.net>
Sat Sep 26 17:19:47 2009 -0400 (2009-09-26)
changeset 2808 d3ebb7dd63fc
parent 2289 44045ead61cd
permissions -rw-r--r--
Another forgotten-file for bug 4015. Thanks mqueues.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod Fun Votes Plugin
     5  * Implements extra fun vote commands.
     6  *
     7  * SourceMod (C)2004-2008 AlliedModders LLC.  All rights reserved.
     8  * =============================================================================
     9  *
    10  * This program is free software; you can redistribute it and/or modify it under
    11  * the terms of the GNU General Public License, version 3.0, as published by the
    12  * Free Software Foundation.
    13  * 
    14  * This program is distributed in the hope that it will be useful, but WITHOUT
    15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    17  * details.
    18  *
    19  * You should have received a copy of the GNU General Public License along with
    20  * this program.  If not, see <http://www.gnu.org/licenses/>.
    21  *
    22  * As a special exception, AlliedModders LLC gives you permission to link the
    23  * code of this program (as well as its derivative works) to "Half-Life 2," the
    24  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    25  * by the Valve Corporation.  You must obey the GNU General Public License in
    26  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    27  * this exception to all derivative works.  AlliedModders LLC defines further
    28  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    29  * or <http://www.sourcemod.net/license.php>.
    30  *
    31  * Version: $Id$
    32  */
    33 
    34 #pragma semicolon 1
    35 
    36 #include <sourcemod>
    37 #include <sdktools>
    38 
    39 #undef REQUIRE_PLUGIN
    40 #include <adminmenu>
    41 
    42 public Plugin:myinfo =
    43 {
    44 	name = "Fun Votes",
    45 	author = "AlliedModders LLC",
    46 	description = "Fun Vote Commands",
    47 	version = SOURCEMOD_VERSION,
    48 	url = "http://www.sourcemod.net/"
    49 };
    50 
    51 #define VOTE_NO "###no###"
    52 #define VOTE_YES "###yes###"
    53 
    54 new Handle:g_hVoteMenu = INVALID_HANDLE;
    55 
    56 new Handle:g_Cvar_Limits[5] = {INVALID_HANDLE, ...};
    57 new Handle:g_Cvar_Gravity = INVALID_HANDLE;
    58 new Handle:g_Cvar_Alltalk = INVALID_HANDLE;
    59 new Handle:g_Cvar_FF = INVALID_HANDLE;
    60 
    61 // new Handle:g_Cvar_Show = INVALID_HANDLE;
    62 
    63 enum voteType
    64 {
    65 	gravity = 0,
    66 	burn,
    67 	slay,
    68 	alltalk,
    69 	ff
    70 };
    71 
    72 new voteType:g_voteType = voteType:gravity;
    73 
    74 // Menu API does not provide us with a way to pass multiple peices of data with a single
    75 // choice, so some globals are used to hold stuff.
    76 //
    77 #define VOTE_CLIENTID	0
    78 #define VOTE_USERID	1
    79 new g_voteClient[2];		/* Holds the target's client id and user id */
    80 
    81 #define VOTE_NAME	0
    82 #define VOTE_AUTHID	1
    83 #define	VOTE_IP		2
    84 new String:g_voteInfo[3][65];	/* Holds the target's name, authid, and IP */
    85 
    86 new Handle:hTopMenu = INVALID_HANDLE;
    87 
    88 #include "funvotes/votegravity.sp"
    89 #include "funvotes/voteburn.sp"
    90 #include "funvotes/voteslay.sp"
    91 #include "funvotes/votealltalk.sp"
    92 #include "funvotes/voteff.sp"
    93 
    94 public OnPluginStart()
    95 {
    96 	if (FindPluginByFile("basefunvotes.smx") != INVALID_HANDLE)
    97 	{
    98 		ThrowError("This plugin replaces basefuncommands.  You cannot run both at once.");
    99 	}
   100 	
   101 	LoadTranslations("common.phrases");
   102 	LoadTranslations("basevotes.phrases");
   103 	LoadTranslations("funvotes.phrases");
   104 	LoadTranslations("funcommands.phrases");
   105 	
   106 	RegAdminCmd("sm_votegravity", Command_VoteGravity, ADMFLAG_VOTE, "sm_votegravity <amount> [amount2] ... [amount5]");
   107 	RegAdminCmd("sm_voteburn", Command_VoteBurn, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteburn <player>");
   108 	RegAdminCmd("sm_voteslay", Command_VoteSlay, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteslay <player>");
   109 	RegAdminCmd("sm_votealltalk", Command_VoteAlltalk, ADMFLAG_VOTE, "sm_votealltalk");
   110 	RegAdminCmd("sm_voteff", Command_VoteFF, ADMFLAG_VOTE, "sm_voteff");
   111 
   112 	g_Cvar_Limits[0] = CreateConVar("sm_vote_gravity", "0.60", "percent required for successful gravity vote.", 0, true, 0.05, true, 1.0);
   113 	g_Cvar_Limits[1] = CreateConVar("sm_vote_burn", "0.60", "percent required for successful burn vote.", 0, true, 0.05, true, 1.0);
   114 	g_Cvar_Limits[2] = CreateConVar("sm_vote_slay", "0.60", "percent required for successful slay vote.", 0, true, 0.05, true, 1.0);
   115 	g_Cvar_Limits[3] = CreateConVar("sm_vote_alltalk", "0.60", "percent required for successful alltalk vote.", 0, true, 0.05, true, 1.0);
   116 	g_Cvar_Limits[4] = CreateConVar("sm_vote_ff", "0.60", "percent required for successful friendly fire vote.", 0, true, 0.05, true, 1.0);
   117 	
   118 	g_Cvar_Gravity = FindConVar("sv_gravity");
   119 	g_Cvar_Alltalk = FindConVar("sv_alltalk");
   120 	g_Cvar_FF = FindConVar("mp_friendlyfire");
   121 	
   122 	/*
   123 	g_Cvar_Show = FindConVar("sm_vote_show");
   124 	if (g_Cvar_Show == INVALID_HANDLE)
   125 	{
   126 		g_Cvar_Show = CreateConVar("sm_vote_show", "1", "Show player's votes? Default on.", 0, true, 0.0, true, 1.0);
   127 	}
   128 	*/
   129 	
   130 	/* Account for late loading */
   131 	new Handle:topmenu;
   132 	if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE))
   133 	{
   134 		OnAdminMenuReady(topmenu);
   135 	}
   136 }
   137 
   138 public OnAdminMenuReady(Handle:topmenu)
   139 {
   140 	/* Block us from being called twice */
   141 	if (topmenu == hTopMenu)
   142 	{
   143 		return;
   144 	}
   145 	
   146 	/* Save the Handle */
   147 	hTopMenu = topmenu;
   148 	
   149 	/* Build the "Voting Commands" category */
   150 	new TopMenuObject:voting_commands = FindTopMenuCategory(hTopMenu, ADMINMENU_VOTINGCOMMANDS);
   151 
   152 	if (voting_commands != INVALID_TOPMENUOBJECT)
   153 	{
   154 		AddToTopMenu(hTopMenu,
   155 			"sm_votegravity",
   156 			TopMenuObject_Item,
   157 			AdminMenu_VoteGravity,
   158 			voting_commands,
   159 			"sm_votegravity",
   160 			ADMFLAG_VOTE);
   161 			
   162 		AddToTopMenu(hTopMenu,
   163 			"sm_voteburn",
   164 			TopMenuObject_Item,
   165 			AdminMenu_VoteBurn,
   166 			voting_commands,
   167 			"sm_voteburn",
   168 			ADMFLAG_VOTE|ADMFLAG_SLAY);
   169 			
   170 		AddToTopMenu(hTopMenu,
   171 			"sm_voteslay",
   172 			TopMenuObject_Item,
   173 			AdminMenu_VoteSlay,
   174 			voting_commands,
   175 			"sm_voteslay",
   176 			ADMFLAG_VOTE|ADMFLAG_SLAY);
   177 			
   178 		AddToTopMenu(hTopMenu,
   179 			"sm_votealltalk",
   180 			TopMenuObject_Item,
   181 			AdminMenu_VoteAllTalk,
   182 			voting_commands,
   183 			"sm_votealltalk",
   184 			ADMFLAG_VOTE);
   185 			
   186 		AddToTopMenu(hTopMenu,
   187 			"sm_voteff",
   188 			TopMenuObject_Item,
   189 			AdminMenu_VoteFF,
   190 			voting_commands,
   191 			"sm_voteff",
   192 			ADMFLAG_VOTE);
   193 	}
   194 }
   195 
   196 public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
   197 {
   198 	if (action == MenuAction_End)
   199 	{
   200 		VoteMenuClose();
   201 	}
   202 	else if (action == MenuAction_Display)
   203 	{
   204 	 	decl String:title[64];
   205 		GetMenuTitle(menu, title, sizeof(title));
   206 
   207 	 	decl String:buffer[255];
   208 		Format(buffer, sizeof(buffer), "%T", title, param1, g_voteInfo[VOTE_NAME]);
   209 
   210 		new Handle:panel = Handle:param2;
   211 		SetPanelTitle(panel, buffer);
   212 	}
   213 	else if (action == MenuAction_DisplayItem)
   214 	{
   215 		decl String:display[64];
   216 		GetMenuItem(menu, param2, "", 0, _, display, sizeof(display));
   217 	 
   218 	 	if (strcmp(display, VOTE_NO) == 0 || strcmp(display, VOTE_YES) == 0)
   219 	 	{
   220 			decl String:buffer[255];
   221 			Format(buffer, sizeof(buffer), "%T", display, param1);
   222 
   223 			return RedrawMenuItem(buffer);
   224 		}
   225 	}
   226 	/* else if (action == MenuAction_Select)
   227 	{
   228 		VoteSelect(menu, param1, param2);
   229 	}*/
   230 	else if (action == MenuAction_VoteCancel && param1 == VoteCancel_NoVotes)
   231 	{
   232 		PrintToChatAll("[SM] %t", "No Votes Cast");
   233 	}
   234 	else if (action == MenuAction_VoteEnd)
   235 	{
   236 		decl String:item[64];
   237 		new Float:percent, Float:limit, votes, totalVotes;
   238 
   239 		GetMenuVoteInfo(param2, votes, totalVotes);
   240 		GetMenuItem(menu, param1, item, sizeof(item));
   241 		
   242 		if (strcmp(item, VOTE_NO) == 0 && param1 == 1)
   243 		{
   244 			votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
   245 		}
   246 		
   247 		percent = GetVotePercent(votes, totalVotes);
   248 		
   249 		limit = GetConVarFloat(g_Cvar_Limits[g_voteType]);
   250 		
   251 		/* :TODO: g_voteClient[userid] needs to be checked.
   252 		 */
   253 
   254 		// A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
   255 		if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1))
   256 		{
   257 			/* :TODO: g_voteClient[userid] should be used here and set to -1 if not applicable.
   258 			 */
   259 			LogAction(-1, -1, "Vote failed.");
   260 			PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
   261 		}
   262 		else
   263 		{
   264 			PrintToChatAll("[SM] %t", "Vote Successful", RoundToNearest(100.0*percent), totalVotes);
   265 			
   266 			switch (g_voteType)
   267 			{
   268 				case (voteType:gravity):
   269 				{
   270 					PrintToChatAll("[SM] %t", "Cvar changed", "sv_gravity", item);					
   271 					LogAction(-1, -1, "Changing gravity to %s due to vote.", item);
   272 					SetConVarInt(g_Cvar_Gravity, StringToInt(item));
   273 				}
   274 				
   275 				case (voteType:burn):
   276 				{
   277 					PrintToChatAll("[SM] %t", "Set target on fire", "_s", g_voteInfo[VOTE_NAME]);					
   278 					LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote burn successful, igniting \"%L\"", g_voteClient[VOTE_CLIENTID]);
   279 					
   280 					IgniteEntity(g_voteClient[VOTE_CLIENTID], 19.8);	
   281 				}
   282 				
   283 				case (voteType:slay):
   284 				{
   285 					PrintToChatAll("[SM] %t", "Slayed player", g_voteInfo[VOTE_NAME]);					
   286 					LogAction(-1, g_voteClient[VOTE_CLIENTID], "Vote slay successful, slaying \"%L\"", g_voteClient[VOTE_CLIENTID]);
   287 					
   288 					ExtinguishEntity(g_voteClient[VOTE_CLIENTID]);
   289 					ForcePlayerSuicide(g_voteClient[VOTE_CLIENTID]);
   290 				}
   291 				
   292 				case (voteType:alltalk):
   293 				{
   294 					PrintToChatAll("[SM] %t", "Cvar changed", "sv_alltalk", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1"));
   295 					LogAction(-1, -1, "Changing alltalk to %s due to vote.", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1"));
   296 					SetConVarBool(g_Cvar_Alltalk, !GetConVarBool(g_Cvar_Alltalk));
   297 				}
   298 				
   299 				case (voteType:ff):
   300 				{
   301 					PrintToChatAll("[SM] %t", "Cvar changed", "mp_friendlyfire", (GetConVarBool(g_Cvar_FF) ? "0" : "1"));
   302 					LogAction(-1, -1, "Changing friendly fire to %s due to vote.", (GetConVarBool(g_Cvar_FF) ? "0" : "1"));
   303 					SetConVarBool(g_Cvar_FF, !GetConVarBool(g_Cvar_FF));
   304 				}				
   305 			}
   306 		}
   307 	}
   308 	
   309 	return 0;
   310 }
   311 
   312 /*
   313 VoteSelect(Handle:menu, param1, param2 = 0)
   314 {
   315 	if (GetConVarInt(g_Cvar_VoteShow) == 1)
   316 	{
   317 		decl String:voter[64], String:junk[64], String:choice[64];
   318 		GetClientName(param1, voter, sizeof(voter));
   319 		GetMenuItem(menu, param2, junk, sizeof(junk), _, choice, sizeof(choice));
   320 		PrintToChatAll("[SM] %T", "Vote Select", LANG_SERVER, voter, choice);
   321 	}
   322 }
   323 */
   324 
   325 VoteMenuClose()
   326 {
   327 	CloseHandle(g_hVoteMenu);
   328 	g_hVoteMenu = INVALID_HANDLE;
   329 }
   330 
   331 Float:GetVotePercent(votes, totalVotes)
   332 {
   333 	return FloatDiv(float(votes),float(totalVotes));
   334 }
   335 
   336 bool:TestVoteDelay(client)
   337 {
   338  	new delay = CheckVoteDelay();
   339  	
   340  	if (delay > 0)
   341  	{
   342  		if (delay > 60)
   343  		{
   344  			ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60);
   345  		}
   346  		else
   347  		{
   348  			ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay);
   349  		}
   350  		
   351  		return false;
   352  	}
   353  	
   354 	return true;
   355 }