plugins/basefunvotes.sp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1297 423d171fafac
child 1364 99405d7da69d
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

(This day shall henceforth be known as the Eighty Column Massacre of '07)
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod Fun Votes Plugin
     5  * Implements extra fun vote commands.
     6  *
     7  * SourceMod (C)2004-2007 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 public Plugin:myinfo =
    40 {
    41 	name = "Fun Votes",
    42 	author = "AlliedModders LLC",
    43 	description = "Fun Vote Commands",
    44 	version = SOURCEMOD_VERSION,
    45 	url = "http://www.sourcemod.net/"
    46 };
    47 
    48 #define VOTE_NO "###no###"
    49 #define VOTE_YES "###yes###"
    50 
    51 new Handle:g_hVoteMenu = INVALID_HANDLE;
    52 
    53 new Handle:g_Cvar_Limits[5] = {INVALID_HANDLE, ...};
    54 new Handle:g_Cvar_Gravity = INVALID_HANDLE;
    55 new Handle:g_Cvar_Alltalk = INVALID_HANDLE;
    56 new Handle:g_Cvar_FF = INVALID_HANDLE;
    57 
    58 // new Handle:g_Cvar_Show = INVALID_HANDLE;
    59 
    60 enum voteType
    61 {
    62 	gravity = 0,
    63 	burn,
    64 	slay,
    65 	alltalk,
    66 	ff
    67 }
    68 
    69 new voteType:g_voteType = voteType:gravity;
    70 
    71 // Menu API does not provide us with a way to pass multiple peices of data with a single
    72 // choice, so some globals are used to hold stuff.
    73 //
    74 #define VOTE_CLIENTID	0
    75 #define VOTE_USERID	1
    76 new g_voteClient[2];		/* Holds the target's client id and user id */
    77 
    78 #define VOTE_NAME	0
    79 #define VOTE_AUTHID	1
    80 #define	VOTE_IP		2
    81 new String:g_voteInfo[3][65];	/* Holds the target's name, authid, and IP */
    82 
    83 public OnPluginStart()
    84 {
    85 	LoadTranslations("common.phrases");
    86 	LoadTranslations("basevotes.phrases");
    87 	LoadTranslations("basefunvotes.phrases");
    88 	
    89 	RegAdminCmd("sm_votegravity", Command_VoteGravity, ADMFLAG_VOTE, "sm_votegravity <amount> [amount2] ... [amount5]");
    90 	RegAdminCmd("sm_voteburn", Command_VoteBurn, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteburn <player>");
    91 	RegAdminCmd("sm_voteslay", Command_VoteSlay, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteslay <player>");
    92 	RegAdminCmd("sm_votealltalk", Command_VoteAlltalk, ADMFLAG_VOTE, "sm_votealltalk");
    93 	RegAdminCmd("sm_voteff", Command_VoteFF, ADMFLAG_VOTE, "sm_voteff");
    94 
    95 	g_Cvar_Limits[0] = CreateConVar("sm_vote_gravity", "0.60", "percent required for successful gravity vote.", 0, true, 0.05, true, 1.0);
    96 	g_Cvar_Limits[1] = CreateConVar("sm_vote_burn", "0.60", "percent required for successful burn vote.", 0, true, 0.05, true, 1.0);
    97 	g_Cvar_Limits[2] = CreateConVar("sm_vote_slay", "0.60", "percent required for successful slay vote.", 0, true, 0.05, true, 1.0);
    98 	g_Cvar_Limits[3] = CreateConVar("sm_vote_alltalk", "0.60", "percent required for successful alltalk vote.", 0, true, 0.05, true, 1.0);
    99 	g_Cvar_Limits[4] = CreateConVar("sm_vote_ff", "0.60", "percent required for successful friendly fire vote.", 0, true, 0.05, true, 1.0);
   100 	
   101 	g_Cvar_Gravity = FindConVar("sv_gravity");
   102 	g_Cvar_Alltalk = FindConVar("sv_alltalk");
   103 	g_Cvar_FF = FindConVar("mp_friendlyfire");
   104 	
   105 	/*
   106 	g_Cvar_Show = FindConVar("sm_vote_show");
   107 	if (g_Cvar_Show == INVALID_HANDLE)
   108 	{
   109 		g_Cvar_Show = CreateConVar("sm_vote_show", "1", "Show player's votes? Default on.", 0, true, 0.0, true, 1.0);
   110 	}
   111 	*/
   112 }
   113 
   114 public Action:Command_VoteGravity(client, args)
   115 {
   116 	if (args < 1)
   117 	{
   118 		ReplyToCommand(client, "[SM] Usage: sm_votegravity <amount> [amount2] ... [amount5]");
   119 		return Plugin_Handled;	
   120 	}
   121 	
   122 	if (IsVoteInProgress())
   123 	{
   124 		ReplyToCommand(client, "[SM] %t", "Vote in Progress");
   125 		return Plugin_Handled;
   126 	}
   127 	
   128 	if (!TestVoteDelay(client))
   129 	{
   130 		return Plugin_Handled;
   131 	}
   132 	
   133 	decl String:text[256];
   134 	GetCmdArgString(text, sizeof(text));
   135 
   136 	decl String:items[5][64];
   137 	new count;	
   138 	new len, pos;
   139 	
   140 	while (pos != -1 && count < 5)
   141 	{	
   142 		pos = BreakString(text[len], items[count], sizeof(items[]));
   143 		
   144 		decl Float:temp;
   145 		if (StringToFloatEx(items[count], temp) == 0)
   146 		{
   147 			ReplyToCommand(client, "[SM] %t", "Invalid Amount");
   148 			return Plugin_Handled;
   149 		}		
   150 
   151 		count++;
   152 		
   153 		if (pos != -1)
   154 		{
   155 			len += pos;
   156 		}	
   157 	}
   158 
   159 	ShowActivity(client, "%t", "Initiated Vote Gravity");
   160 	
   161 	g_voteType = voteType:gravity;
   162 	
   163 	g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
   164 	
   165 	if (count == 1)
   166 	{
   167 		strcopy(g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]), items[0]);
   168 			
   169 		SetMenuTitle(g_hVoteMenu, "Change Gravity To");
   170 		AddMenuItem(g_hVoteMenu, items[0], "Yes");
   171 		AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
   172 	}
   173 	else
   174 	{
   175 		g_voteInfo[VOTE_NAME][0] = '\0';
   176 		
   177 		SetMenuTitle(g_hVoteMenu, "Gravity Vote");
   178 		for (new i = 0; i < count; i++)
   179 		{
   180 			AddMenuItem(g_hVoteMenu, items[i], items[i]);
   181 		}	
   182 	}
   183 	
   184 	SetMenuExitButton(g_hVoteMenu, false);
   185 	VoteMenuToAll(g_hVoteMenu, 20);		
   186 	
   187 	return Plugin_Handled;	
   188 }
   189 
   190 public Action:Command_VoteBurn(client, args)
   191 {
   192 	if (args < 1)
   193 	{
   194 		ReplyToCommand(client, "[SM] Usage: sm_voteburn <player>");
   195 		return Plugin_Handled;	
   196 	}
   197 	
   198 	if (IsVoteInProgress())
   199 	{
   200 		ReplyToCommand(client, "[SM] %t", "Vote in Progress");
   201 		return Plugin_Handled;
   202 	}	
   203 	
   204 	if (!TestVoteDelay(client))
   205 	{
   206 		return Plugin_Handled;
   207 	}
   208 	
   209 	decl String:text[256], String:arg[64];
   210 	GetCmdArgString(text, sizeof(text));
   211 	
   212 	BreakString(text, arg, sizeof(arg));
   213 	
   214 	new target = FindTarget(client, arg);
   215 	if (target == -1)
   216 	{
   217 		return Plugin_Handled;
   218 	}
   219 
   220 	if (!IsPlayerAlive(target))
   221 	{
   222 		ReplyToCommand(client, "[SM] %t", "Cannot performed on dead", arg);
   223 		return Plugin_Handled;
   224 	}
   225 	
   226 	g_voteClient[VOTE_CLIENTID] = target;
   227 	GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
   228 
   229 	ShowActivity(client, "%t", "Initiated Vote Burn", g_voteInfo[VOTE_NAME]);
   230 	
   231 	g_voteType = voteType:burn;
   232 	
   233 	g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
   234 	SetMenuTitle(g_hVoteMenu, "Voteburn Player");
   235 	AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
   236 	AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
   237 	SetMenuExitButton(g_hVoteMenu, false);
   238 	VoteMenuToAll(g_hVoteMenu, 20);
   239 	
   240 	return Plugin_Handled;
   241 }
   242 
   243 public Action:Command_VoteSlay(client, args)
   244 {
   245 	if (args < 1)
   246 	{
   247 		ReplyToCommand(client, "[SM] Usage: sm_voteslay <player>");
   248 		return Plugin_Handled;	
   249 	}
   250 	
   251 	if (IsVoteInProgress())
   252 	{
   253 		ReplyToCommand(client, "[SM] %t", "Vote in Progress");
   254 		return Plugin_Handled;
   255 	}	
   256 	
   257 	if (!TestVoteDelay(client))
   258 	{
   259 		return Plugin_Handled;
   260 	}
   261 	
   262 	decl String:text[256], String:arg[64];
   263 	GetCmdArgString(text, sizeof(text));
   264 	
   265 	BreakString(text, arg, sizeof(arg));
   266 	
   267 	new target = FindTarget(client, arg);
   268 	if (target == -1)
   269 	{
   270 		return Plugin_Handled;
   271 	}
   272 
   273 	if (!IsPlayerAlive(target))
   274 	{
   275 		ReplyToCommand(client, "[SM] %t", "Cannot performed on dead", arg);
   276 		return Plugin_Handled;
   277 	}
   278 	
   279 	g_voteClient[VOTE_CLIENTID] = target;
   280 	GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
   281 
   282 	ShowActivity(client, "%t", "Initiated Vote Slay", g_voteInfo[VOTE_NAME]);
   283 	
   284 	g_voteType = voteType:slay;
   285 	
   286 	g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
   287 	SetMenuTitle(g_hVoteMenu, "Voteslay Player");
   288 	AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
   289 	AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
   290 	SetMenuExitButton(g_hVoteMenu, false);
   291 	VoteMenuToAll(g_hVoteMenu, 20);
   292 	
   293 	return Plugin_Handled;
   294 }
   295 
   296 public Action:Command_VoteAlltalk(client, args)
   297 {
   298 	if (args > 0)
   299 	{
   300 		ReplyToCommand(client, "[SM] Usage: sm_votealltalk");
   301 		return Plugin_Handled;	
   302 	}
   303 	
   304 	if (IsVoteInProgress())
   305 	{
   306 		ReplyToCommand(client, "[SM] %t", "Vote in Progress");
   307 		return Plugin_Handled;
   308 	}	
   309 	
   310 	if (!TestVoteDelay(client))
   311 	{
   312 		return Plugin_Handled;
   313 	}
   314 	
   315 	ShowActivity(client, "%t", "Initiated Vote Alltalk");
   316 	
   317 	g_voteType = voteType:alltalk;
   318 	g_voteInfo[VOTE_NAME][0] = '\0';
   319 
   320 	g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
   321 	
   322 	if (GetConVarBool(g_Cvar_Alltalk))
   323 	{
   324 		SetMenuTitle(g_hVoteMenu, "Votealltalk Off");
   325 	}
   326 	else
   327 	{
   328 		SetMenuTitle(g_hVoteMenu, "Votealltalk On");
   329 	}
   330 	
   331 	AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
   332 	AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
   333 	SetMenuExitButton(g_hVoteMenu, false);
   334 	VoteMenuToAll(g_hVoteMenu, 20);
   335 	
   336 	return Plugin_Handled;
   337 }
   338 
   339 public Action:Command_VoteFF(client, args)
   340 {
   341 	if (args > 0)
   342 	{
   343 		ReplyToCommand(client, "[SM] Usage: sm_voteff");
   344 		return Plugin_Handled;	
   345 	}
   346 	
   347 	if (IsVoteInProgress())
   348 	{
   349 		ReplyToCommand(client, "[SM] %t", "Vote in Progress");
   350 		return Plugin_Handled;
   351 	}	
   352 	
   353 	if (!TestVoteDelay(client))
   354 	{
   355 		return Plugin_Handled;
   356 	}
   357 	
   358 	ShowActivity(client, "%t", "Initiated Vote FF");
   359 	
   360 	g_voteType = voteType:ff;
   361 	g_voteInfo[VOTE_NAME][0] = '\0';
   362 	
   363 	g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
   364 	
   365 	if (GetConVarBool(g_Cvar_Alltalk))
   366 	{
   367 		SetMenuTitle(g_hVoteMenu, "Voteff Off");
   368 	}
   369 	else
   370 	{
   371 		SetMenuTitle(g_hVoteMenu, "Voteff On");
   372 	}
   373 	
   374 	AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
   375 	AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
   376 	SetMenuExitButton(g_hVoteMenu, false);
   377 	VoteMenuToAll(g_hVoteMenu, 20);
   378 	
   379 	return Plugin_Handled;
   380 }
   381 
   382 public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
   383 {
   384 	if (action == MenuAction_End)
   385 	{
   386 		VoteMenuClose();
   387 	}
   388 	else if (action == MenuAction_Display)
   389 	{
   390 	 	decl String:title[64];
   391 		GetMenuTitle(g_hVoteMenu, title, sizeof(title));
   392 
   393 	 	decl String:buffer[255];
   394 		Format(buffer, sizeof(buffer), "%T", title, param1, g_voteInfo[VOTE_NAME]);
   395 
   396 		SetMenuTitle(g_hVoteMenu, buffer);
   397 	}
   398 	else if (action == MenuAction_DisplayItem)
   399 	{
   400 		decl String:display[64];
   401 		GetMenuItem(menu, param2, "", 0, _, display, sizeof(display));
   402 	 
   403 	 	if (strcmp(display, VOTE_NO) == 0 || strcmp(display, VOTE_YES) == 0)
   404 	 	{
   405 			decl String:buffer[255];
   406 			Format(buffer, sizeof(buffer), "%T", display, param1);
   407 
   408 			return RedrawMenuItem(buffer);
   409 		}
   410 	}
   411 	/* else if (action == MenuAction_Select)
   412 	{
   413 		VoteSelect(menu, param1, param2);
   414 	}*/
   415 	else if (action == VoteCancel_NoVotes)
   416 	{
   417 		PrintToChatAll("[SM] %t", "No Votes Cast");
   418 	}
   419 	else if (action == MenuAction_VoteEnd)
   420 	{
   421 		decl String:item[64];
   422 		new Float:percent, Float:limit, votes, totalVotes;
   423 
   424 		GetMenuVoteInfo(param2, votes, totalVotes);
   425 		GetMenuItem(menu, param1, item, sizeof(item));
   426 		
   427 		if (strcmp(item, VOTE_NO) == 0 && param1 == 1)
   428 		{
   429 			votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
   430 		}
   431 		
   432 		percent = GetVotePercent(votes, totalVotes);
   433 		
   434 		limit = GetConVarFloat(g_Cvar_Limits[g_voteType]);
   435 
   436 		// A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
   437 		if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1))
   438 		{
   439 			LogMessage("Vote failed.");
   440 			PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
   441 		}
   442 		else
   443 		{
   444 			PrintToChatAll("[SM] %t", "Vote Successful", RoundToNearest(100.0*percent), totalVotes);
   445 			
   446 			switch (g_voteType)
   447 			{
   448 				case (voteType:gravity):
   449 				{
   450 					PrintToChatAll("[SM] %t", "Cvar changed", "sv_gravity", item);					
   451 					LogMessage("Changing gravity to %s due to vote.", item);
   452 					SetConVarInt(g_Cvar_Gravity, StringToInt(item));
   453 				}
   454 				
   455 				case (voteType:burn):
   456 				{
   457 					PrintToChatAll("[SM] %t", "Ignited player", g_voteInfo[VOTE_NAME]);					
   458 					LogMessage("Vote burn successful, igniting \"%L\"", g_voteClient[VOTE_CLIENTID]);
   459 					
   460 					IgniteEntity(g_voteClient[VOTE_CLIENTID], 19.8);	
   461 				}
   462 				
   463 				case (voteType:slay):
   464 				{
   465 					PrintToChatAll("[SM] %t", "Slayed player", g_voteInfo[VOTE_NAME]);					
   466 					LogMessage("Vote slay successful, slaying \"%L\"", g_voteClient[VOTE_CLIENTID]);
   467 					
   468 					ExtinguishEntity(g_voteClient[VOTE_CLIENTID]);
   469 					ForcePlayerSuicide(g_voteClient[VOTE_CLIENTID]);
   470 				}
   471 				
   472 				case (voteType:alltalk):
   473 				{
   474 					PrintToChatAll("[SM] %t", "Cvar changed", "sv_alltalk", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1"));
   475 					LogMessage("Changing alltalk to %s due to vote.", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1"));
   476 					SetConVarBool(g_Cvar_Alltalk, !GetConVarBool(g_Cvar_Alltalk));
   477 				}
   478 				
   479 				case (voteType:ff):
   480 				{
   481 					PrintToChatAll("[SM] %t", "Cvar changed", "mp_friendlyfire", (GetConVarBool(g_Cvar_FF) ? "0" : "1"));
   482 					LogMessage("Changing friendly fire to %s due to vote.", (GetConVarBool(g_Cvar_FF) ? "0" : "1"));
   483 					SetConVarBool(g_Cvar_FF, !GetConVarBool(g_Cvar_FF));
   484 				}				
   485 			}
   486 		}
   487 	}
   488 	
   489 	return 0;
   490 }
   491 
   492 /*
   493 VoteSelect(Handle:menu, param1, param2 = 0)
   494 {
   495 	if (GetConVarInt(g_Cvar_VoteShow) == 1)
   496 	{
   497 		decl String:voter[64], String:junk[64], String:choice[64];
   498 		GetClientName(param1, voter, sizeof(voter));
   499 		GetMenuItem(menu, param2, junk, sizeof(junk), _, choice, sizeof(choice));
   500 		PrintToChatAll("[SM] %T", "Vote Select", LANG_SERVER, voter, choice);
   501 	}
   502 }
   503 */
   504 
   505 VoteMenuClose()
   506 {
   507 	CloseHandle(g_hVoteMenu);
   508 	g_hVoteMenu = INVALID_HANDLE;
   509 }
   510 
   511 Float:GetVotePercent(votes, totalVotes)
   512 {
   513 	return FloatDiv(float(votes),float(totalVotes));
   514 }
   515 
   516 bool:TestVoteDelay(client)
   517 {
   518  	new delay = CheckVoteDelay();
   519  	
   520  	if (delay > 0)
   521  	{
   522  		if (delay > 60)
   523  		{
   524  			ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60);
   525  		}
   526  		else
   527  		{
   528  			ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay);
   529  		}
   530  		
   531  		return false;
   532  	}
   533  	
   534 	return true;
   535 }