3 * Implements extra fun vote commands.
4 * This file is part of SourceMod, Copyright (C) 2004-2007 AlliedModders LLC
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 public Plugin:myinfo =
31 author = "AlliedModders LLC",
32 description = "Fun Vote Commands",
33 version = SOURCEMOD_VERSION,
34 url = "http://www.sourcemod.net/"
37 #define VOTE_NO "###no###"
38 #define VOTE_YES "###yes###"
40 new Handle:g_hVoteMenu = INVALID_HANDLE;
42 new Handle:g_Cvar_Limits[5] = {INVALID_HANDLE, ...};
43 new Handle:g_Cvar_Gravity = INVALID_HANDLE;
44 new Handle:g_Cvar_Alltalk = INVALID_HANDLE;
45 new Handle:g_Cvar_FF = INVALID_HANDLE;
47 // new Handle:g_Cvar_Show = INVALID_HANDLE;
58 new voteType:g_voteType = voteType:gravity;
60 // Menu API does not provide us with a way to pass multiple peices of data with a single
61 // choice, so some globals are used to hold stuff.
63 #define VOTE_CLIENTID 0
65 new g_voteClient[2]; /* Holds the target's client id and user id */
70 new String:g_voteInfo[3][65]; /* Holds the target's name, authid, and IP */
72 public OnPluginStart()
74 LoadTranslations("common.phrases");
75 LoadTranslations("basevotes.phrases");
76 LoadTranslations("basefunvotes.phrases");
78 RegAdminCmd("sm_votegravity", Command_VoteGravity, ADMFLAG_VOTE, "sm_votegravity <amount> [amount2] ... [amount5]");
79 RegAdminCmd("sm_voteburn", Command_VoteBurn, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteburn <player>");
80 RegAdminCmd("sm_voteslay", Command_VoteSlay, ADMFLAG_VOTE|ADMFLAG_SLAY, "sm_voteslay <player>");
81 RegAdminCmd("sm_votealltalk", Command_VoteAlltalk, ADMFLAG_VOTE, "sm_votealltalk");
82 RegAdminCmd("sm_voteff", Command_VoteFF, ADMFLAG_VOTE, "sm_voteff");
84 g_Cvar_Limits[0] = CreateConVar("sm_vote_gravity", "0.60", "percent required for successful gravity vote.", 0, true, 0.05, true, 1.0);
85 g_Cvar_Limits[1] = CreateConVar("sm_vote_burn", "0.60", "percent required for successful burn vote.", 0, true, 0.05, true, 1.0);
86 g_Cvar_Limits[2] = CreateConVar("sm_vote_slay", "0.60", "percent required for successful slay vote.", 0, true, 0.05, true, 1.0);
87 g_Cvar_Limits[3] = CreateConVar("sm_vote_alltalk", "0.60", "percent required for successful alltalk vote.", 0, true, 0.05, true, 1.0);
88 g_Cvar_Limits[4] = CreateConVar("sm_vote_ff", "0.60", "percent required for successful friendly fire vote.", 0, true, 0.05, true, 1.0);
90 g_Cvar_Gravity = FindConVar("sv_gravity");
91 g_Cvar_Alltalk = FindConVar("sv_alltalk");
92 g_Cvar_FF = FindConVar("mp_friendlyfire");
95 g_Cvar_Show = FindConVar("sm_vote_show");
96 if (g_Cvar_Show == INVALID_HANDLE)
98 g_Cvar_Show = CreateConVar("sm_vote_show", "1", "Show player's votes? Default on.", 0, true, 0.0, true, 1.0);
103 public Action:Command_VoteGravity(client, args)
107 ReplyToCommand(client, "[SM] Usage: sm_votegravity <amount> [amount2] ... [amount5]");
108 return Plugin_Handled;
111 if (IsVoteInProgress())
113 ReplyToCommand(client, "[SM] %t", "Vote in Progress");
114 return Plugin_Handled;
117 if (!TestVoteDelay(client))
119 return Plugin_Handled;
122 decl String:text[256];
123 GetCmdArgString(text, sizeof(text));
125 decl String:items[5][64];
129 while (pos != -1 && count < 5)
131 pos = BreakString(text[len], items[count], sizeof(items[]));
134 if (StringToFloatEx(items[count], temp) == 0)
136 ReplyToCommand(client, "[SM] %t", "Invalid Amount");
137 return Plugin_Handled;
148 ShowActivity(client, "%t", "Initiated Vote Gravity");
150 g_voteType = voteType:gravity;
152 g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
156 strcopy(g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]), items[0]);
158 SetMenuTitle(g_hVoteMenu, "Change Gravity To");
159 AddMenuItem(g_hVoteMenu, items[0], "Yes");
160 AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
164 g_voteInfo[VOTE_NAME][0] = '\0';
166 SetMenuTitle(g_hVoteMenu, "Gravity Vote");
167 for (new i = 0; i < count; i++)
169 AddMenuItem(g_hVoteMenu, items[i], items[i]);
173 SetMenuExitButton(g_hVoteMenu, false);
174 VoteMenuToAll(g_hVoteMenu, 20);
176 return Plugin_Handled;
179 public Action:Command_VoteBurn(client, args)
183 ReplyToCommand(client, "[SM] Usage: sm_voteburn <player>");
184 return Plugin_Handled;
187 if (IsVoteInProgress())
189 ReplyToCommand(client, "[SM] %t", "Vote in Progress");
190 return Plugin_Handled;
193 if (!TestVoteDelay(client))
195 return Plugin_Handled;
198 decl String:text[256], String:arg[64];
199 GetCmdArgString(text, sizeof(text));
201 BreakString(text, arg, sizeof(arg));
203 new target = FindTarget(client, arg);
206 return Plugin_Handled;
209 if (!IsPlayerAlive(target))
211 ReplyToCommand(client, "[SM] %t", "Cannot performed on dead", arg);
212 return Plugin_Handled;
215 g_voteClient[VOTE_CLIENTID] = target;
216 GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
218 ShowActivity(client, "%t", "Initiated Vote Burn", g_voteInfo[VOTE_NAME]);
220 g_voteType = voteType:burn;
222 g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
223 SetMenuTitle(g_hVoteMenu, "Voteburn Player");
224 AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
225 AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
226 SetMenuExitButton(g_hVoteMenu, false);
227 VoteMenuToAll(g_hVoteMenu, 20);
229 return Plugin_Handled;
232 public Action:Command_VoteSlay(client, args)
236 ReplyToCommand(client, "[SM] Usage: sm_voteslay <player>");
237 return Plugin_Handled;
240 if (IsVoteInProgress())
242 ReplyToCommand(client, "[SM] %t", "Vote in Progress");
243 return Plugin_Handled;
246 if (!TestVoteDelay(client))
248 return Plugin_Handled;
251 decl String:text[256], String:arg[64];
252 GetCmdArgString(text, sizeof(text));
254 BreakString(text, arg, sizeof(arg));
256 new target = FindTarget(client, arg);
259 return Plugin_Handled;
262 if (!IsPlayerAlive(target))
264 ReplyToCommand(client, "[SM] %t", "Cannot performed on dead", arg);
265 return Plugin_Handled;
268 g_voteClient[VOTE_CLIENTID] = target;
269 GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
271 ShowActivity(client, "%t", "Initiated Vote Slay", g_voteInfo[VOTE_NAME]);
273 g_voteType = voteType:slay;
275 g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
276 SetMenuTitle(g_hVoteMenu, "Voteslay Player");
277 AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
278 AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
279 SetMenuExitButton(g_hVoteMenu, false);
280 VoteMenuToAll(g_hVoteMenu, 20);
282 return Plugin_Handled;
285 public Action:Command_VoteAlltalk(client, args)
289 ReplyToCommand(client, "[SM] Usage: sm_votealltalk");
290 return Plugin_Handled;
293 if (IsVoteInProgress())
295 ReplyToCommand(client, "[SM] %t", "Vote in Progress");
296 return Plugin_Handled;
299 if (!TestVoteDelay(client))
301 return Plugin_Handled;
304 ShowActivity(client, "%t", "Initiated Vote Alltalk");
306 g_voteType = voteType:alltalk;
307 g_voteInfo[VOTE_NAME][0] = '\0';
309 g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
311 if (GetConVarBool(g_Cvar_Alltalk))
313 SetMenuTitle(g_hVoteMenu, "Votealltalk Off");
317 SetMenuTitle(g_hVoteMenu, "Votealltalk On");
320 AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
321 AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
322 SetMenuExitButton(g_hVoteMenu, false);
323 VoteMenuToAll(g_hVoteMenu, 20);
325 return Plugin_Handled;
328 public Action:Command_VoteFF(client, args)
332 ReplyToCommand(client, "[SM] Usage: sm_voteff");
333 return Plugin_Handled;
336 if (IsVoteInProgress())
338 ReplyToCommand(client, "[SM] %t", "Vote in Progress");
339 return Plugin_Handled;
342 if (!TestVoteDelay(client))
344 return Plugin_Handled;
347 ShowActivity(client, "%t", "Initiated Vote FF");
349 g_voteType = voteType:ff;
350 g_voteInfo[VOTE_NAME][0] = '\0';
352 g_hVoteMenu = CreateMenu(Handler_VoteCallback, MenuAction:MENU_ACTIONS_ALL);
354 if (GetConVarBool(g_Cvar_Alltalk))
356 SetMenuTitle(g_hVoteMenu, "Voteff Off");
360 SetMenuTitle(g_hVoteMenu, "Voteff On");
363 AddMenuItem(g_hVoteMenu, VOTE_YES, "Yes");
364 AddMenuItem(g_hVoteMenu, VOTE_NO, "No");
365 SetMenuExitButton(g_hVoteMenu, false);
366 VoteMenuToAll(g_hVoteMenu, 20);
368 return Plugin_Handled;
371 public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
373 if (action == MenuAction_End)
377 else if (action == MenuAction_Display)
379 decl String:title[64];
380 GetMenuTitle(g_hVoteMenu, title, sizeof(title));
382 decl String:buffer[255];
383 Format(buffer, sizeof(buffer), "%T", title, param1, g_voteInfo[VOTE_NAME]);
385 SetMenuTitle(g_hVoteMenu, buffer);
387 else if (action == MenuAction_DisplayItem)
389 decl String:display[64];
390 GetMenuItem(menu, param2, "", 0, _, display, sizeof(display));
392 if (strcmp(display, VOTE_NO) == 0 || strcmp(display, VOTE_YES) == 0)
394 decl String:buffer[255];
395 Format(buffer, sizeof(buffer), "%T", display, param1);
397 return RedrawMenuItem(buffer);
400 /* else if (action == MenuAction_Select)
402 VoteSelect(menu, param1, param2);
404 else if (action == VoteCancel_NoVotes)
406 PrintToChatAll("[SM] %t", "No Votes Cast");
408 else if (action == MenuAction_VoteEnd)
410 decl String:item[64];
411 new Float:percent, Float:limit, votes, totalVotes;
413 GetMenuVoteInfo(param2, votes, totalVotes);
414 GetMenuItem(menu, param1, item, sizeof(item));
416 if (strcmp(item, VOTE_NO) == 0 && param1 == 1)
418 votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
421 percent = GetVotePercent(votes, totalVotes);
423 limit = GetConVarFloat(g_Cvar_Limits[g_voteType]);
425 // A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
426 if ((strcmp(item, VOTE_YES) == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(item, VOTE_NO) == 0 && param1 == 1))
428 LogMessage("Vote failed.");
429 PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
433 PrintToChatAll("[SM] %t", "Vote Successful", RoundToNearest(100.0*percent), totalVotes);
437 case (voteType:gravity):
439 PrintToChatAll("[SM] %t", "Cvar changed", "sv_gravity", item);
440 LogMessage("Changing gravity to %s due to vote.", item);
441 SetConVarInt(g_Cvar_Gravity, StringToInt(item));
444 case (voteType:burn):
446 PrintToChatAll("[SM] %t", "Ignited player", g_voteInfo[VOTE_NAME]);
447 LogMessage("Vote burn successful, igniting \"%L\"", g_voteClient[VOTE_CLIENTID]);
449 IgniteEntity(g_voteClient[VOTE_CLIENTID], 19.8);
452 case (voteType:slay):
454 PrintToChatAll("[SM] %t", "Slayed player", g_voteInfo[VOTE_NAME]);
455 LogMessage("Vote slay successful, slaying \"%L\"", g_voteClient[VOTE_CLIENTID]);
457 ExtinguishEntity(g_voteClient[VOTE_CLIENTID]);
458 ForcePlayerSuicide(g_voteClient[VOTE_CLIENTID]);
461 case (voteType:alltalk):
463 PrintToChatAll("[SM] %t", "Cvar changed", "sv_alltalk", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1"));
464 LogMessage("Changing alltalk to %s due to vote.", (GetConVarBool(g_Cvar_Alltalk) ? "0" : "1"));
465 SetConVarBool(g_Cvar_Alltalk, !GetConVarBool(g_Cvar_Alltalk));
470 PrintToChatAll("[SM] %t", "Cvar changed", "mp_friendlyfire", (GetConVarBool(g_Cvar_FF) ? "0" : "1"));
471 LogMessage("Changing friendly fire to %s due to vote.", (GetConVarBool(g_Cvar_FF) ? "0" : "1"));
472 SetConVarBool(g_Cvar_FF, !GetConVarBool(g_Cvar_FF));
482 VoteSelect(Handle:menu, param1, param2 = 0)
484 if (GetConVarInt(g_Cvar_VoteShow) == 1)
486 decl String:voter[64], String:junk[64], String:choice[64];
487 GetClientName(param1, voter, sizeof(voter));
488 GetMenuItem(menu, param2, junk, sizeof(junk), _, choice, sizeof(choice));
489 PrintToChatAll("[SM] %T", "Vote Select", LANG_SERVER, voter, choice);
496 CloseHandle(g_hVoteMenu);
497 g_hVoteMenu = INVALID_HANDLE;
500 Float:GetVotePercent(votes, totalVotes)
502 return FloatDiv(float(votes),float(totalVotes));
505 bool:TestVoteDelay(client)
507 new delay = CheckVoteDelay();
513 ReplyToCommand(client, "[SM] %t", "Vote Delay Minutes", delay % 60);
517 ReplyToCommand(client, "[SM] %t", "Vote Delay Seconds", delay);