Base Votes import.
Base Votes import.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/plugins/basevotes.sp Wed Aug 08 23:35:16 2007 +0000
1.3 @@ -0,0 +1,481 @@
1.4 +/**
1.5 + * basevotes.sp
1.6 + * Implements basic vote commands.
1.7 + * This file is part of SourceMod, Copyright (C) 2004-2007 AlliedModders LLC
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License
1.11 + * as published by the Free Software Foundation; either version 2
1.12 + * of the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1.22 + *
1.23 + * Version: $Id$
1.24 + */
1.25 +
1.26 +#include <sourcemod>
1.27 +
1.28 +#pragma semicolon 1
1.29 +
1.30 +public Plugin:myinfo =
1.31 +{
1.32 + name = "Basic Votes",
1.33 + author = "AlliedModders LLC",
1.34 + description = "Basic Vote Commands",
1.35 + version = SOURCEMOD_VERSION,
1.36 + url = "http://www.sourcemod.net/"
1.37 +};
1.38 +
1.39 +new Handle:g_hVoteMenu = INVALID_HANDLE;
1.40 +
1.41 +new Handle:g_hBanForward = INVALID_HANDLE;
1.42 +
1.43 +new Handle:g_Cvar_VoteMap = INVALID_HANDLE;
1.44 +new Handle:g_Cvar_VoteKick = INVALID_HANDLE;
1.45 +new Handle:g_Cvar_VoteBan = INVALID_HANDLE;
1.46 +//new Handle:g_Cvar_VoteSay = INVALID_HANDLE;
1.47 +
1.48 +enum voteType
1.49 +{
1.50 + question = 0,
1.51 + map,
1.52 + kick,
1.53 + ban
1.54 +}
1.55 +
1.56 +new voteType:g_voteType = voteType:question;
1.57 +
1.58 +// Menu API does not provide us with a way to pass multiple peices of data with a single
1.59 +// choice, so some globals are used to hold stuff.
1.60 +//
1.61 +#define VOTE_CLIENTID 0
1.62 +#define VOTE_USERID 1
1.63 +new g_voteClient[2]; /* Holds the target's client id and user id */
1.64 +
1.65 +#define VOTE_NAME 0
1.66 +#define VOTE_AUTHID 1
1.67 +#define VOTE_IP 2
1.68 +new String:g_voteInfo[3][65]; /* Holds the target's name, authid, and IP */
1.69 +
1.70 +new String:g_voteArg[256]; /* Used to hold ban/kick reasons or vote questions */
1.71 +
1.72 +
1.73 +public OnPluginStart()
1.74 +{
1.75 + LoadTranslations("common.phrases");
1.76 + LoadTranslations("plugin.basevotes");
1.77 +
1.78 + RegAdminCmd("sm_votemap", Command_Votemap, ADMFLAG_VOTE|ADMFLAG_CHANGEMAP, "sm_votemap <mapname> [mapname2] ... [mapname5] ");
1.79 + RegAdminCmd("sm_votekick", Command_Votekick, ADMFLAG_VOTE|ADMFLAG_KICK, "sm_votekick <player> [reason]");
1.80 + RegAdminCmd("sm_voteban", Command_Voteban, ADMFLAG_VOTE|ADMFLAG_BAN, "sm_voteban <player> [reason]");
1.81 + RegAdminCmd("sm_vote", Command_Vote, ADMFLAG_VOTE, "sm_vote <question> [Answer1] [Answer2] ... [Answer5]");
1.82 +
1.83 + //g_Cvar_VoteShow = CreateConVar("sm_vote_show", "1", "Show player's votes? Default on.", 0, true, 0.0, true, 1.0);
1.84 +
1.85 + g_Cvar_VoteMap = CreateConVar("sm_vote_map", "0.60", "percent required for successful map vote.", 0, true, 0.05, true, 1.0);
1.86 + g_Cvar_VoteKick = CreateConVar("sm_vote_kick", "0.60", "percent required for successful kick vote.", 0, true, 0.05, true, 1.0);
1.87 + g_Cvar_VoteBan = CreateConVar("sm_vote_ban", "0.60", "percent required for successful ban vote.", 0, true, 0.05, true, 1.0);
1.88 +
1.89 + g_hBanForward = CreateGlobalForward("OnClientBanned", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_String);
1.90 +}
1.91 +
1.92 +public Action:Command_Votemap(client, args)
1.93 +{
1.94 + if (args < 1)
1.95 + {
1.96 + ReplyToCommand(client, "[SM] Usage: sm_votemap <mapname> [mapname2] ... [mapname5]");
1.97 + return Plugin_Handled;
1.98 + }
1.99 +
1.100 + if (IsVoteInProgress())
1.101 + {
1.102 + ReplyToCommand(client, "[SM] %t", "Vote in Progress");
1.103 + return Plugin_Handled;
1.104 + }
1.105 +
1.106 + decl String:text[256];
1.107 + GetCmdArgString(text, sizeof(text));
1.108 +
1.109 + decl String:maps[5][64];
1.110 + new mapCount;
1.111 + new len, pos;
1.112 +
1.113 + while (pos != -1 && mapCount < 5)
1.114 + {
1.115 + pos = BreakString(text[len], maps[mapCount], sizeof(maps[]));
1.116 +
1.117 + if (!IsMapValid(maps[mapCount]))
1.118 + {
1.119 + ReplyToCommand(client, "[SM] %t", "Map was not found", maps[mapCount]);
1.120 + return Plugin_Handled;
1.121 + }
1.122 +
1.123 + mapCount++;
1.124 +
1.125 + if (pos != -1)
1.126 + {
1.127 + len += pos;
1.128 + }
1.129 + }
1.130 +
1.131 + ShowActivity(client, "%t", "Initiated Vote Map");
1.132 +
1.133 + g_voteType = voteType:map;
1.134 +
1.135 + g_hVoteMenu = CreateMenu(Handler_VoteCallback);
1.136 +
1.137 + if (mapCount == 1)
1.138 + {
1.139 + strcopy(g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]), maps[0]);
1.140 + SetMenuTitle(g_hVoteMenu, "Change Map To");
1.141 + AddMenuItem(g_hVoteMenu, maps[0], "Yes");
1.142 + AddMenuItem(g_hVoteMenu, "no", "No");
1.143 + }
1.144 + else
1.145 + {
1.146 + SetMenuTitle(g_hVoteMenu, "Map Vote");
1.147 + for (new i = 0; i < mapCount; i++)
1.148 + {
1.149 + AddMenuItem(g_hVoteMenu, maps[i], maps[i]);
1.150 + }
1.151 + }
1.152 +
1.153 + SetMenuExitButton(g_hVoteMenu, false);
1.154 + VoteMenuToAll(g_hVoteMenu, 20);
1.155 +
1.156 + return Plugin_Handled;
1.157 +}
1.158 +
1.159 +public Action:Command_Vote(client, args)
1.160 +{
1.161 + if (args < 1)
1.162 + {
1.163 + ReplyToCommand(client, "[SM] Usage: sm_vote <question> [Answer1] [Answer2] ... [Answer5]");
1.164 + return Plugin_Handled;
1.165 + }
1.166 +
1.167 + if (IsVoteInProgress())
1.168 + {
1.169 + ReplyToCommand(client, "[SM] %t", "Vote in Progress");
1.170 + return Plugin_Handled;
1.171 + }
1.172 +
1.173 + decl String:text[256];
1.174 + GetCmdArgString(text, sizeof(text));
1.175 +
1.176 + decl String:answers[5][64];
1.177 + new answerCount;
1.178 + new len = BreakString(text, g_voteArg, sizeof(g_voteArg));
1.179 + new pos = len;
1.180 +
1.181 + while (pos != -1 && answerCount < 5)
1.182 + {
1.183 + pos = BreakString(text[len], answers[answerCount], sizeof(answers[]));
1.184 + answerCount++;
1.185 +
1.186 + if (pos != -1)
1.187 + {
1.188 + len += pos;
1.189 + }
1.190 + }
1.191 +
1.192 + ShowActivity(client, "%t", "Initiate Vote", g_voteArg);
1.193 +
1.194 + g_voteType = voteType:question;
1.195 +
1.196 + g_hVoteMenu = CreateMenu(Handler_VoteCallback);
1.197 + SetMenuTitle(g_hVoteMenu, "%s?", g_voteArg);
1.198 +
1.199 + if (answerCount == 1)
1.200 + {
1.201 + AddMenuItem(g_hVoteMenu, "Yes", "Yes");
1.202 + AddMenuItem(g_hVoteMenu, "No", "No");
1.203 + }
1.204 + else
1.205 + {
1.206 + for (new i = 0; i < answerCount; i++)
1.207 + {
1.208 + AddMenuItem(g_hVoteMenu, answers[i], answers[i]);
1.209 + }
1.210 + }
1.211 +
1.212 + SetMenuExitButton(g_hVoteMenu, false);
1.213 + VoteMenuToAll(g_hVoteMenu, 20);
1.214 +
1.215 + return Plugin_Handled;
1.216 +}
1.217 +
1.218 +public Action:Command_Votekick(client, args)
1.219 +{
1.220 + if (args < 1)
1.221 + {
1.222 + ReplyToCommand(client, "[SM] Usage: sm_votekick <player> [reason]");
1.223 + return Plugin_Handled;
1.224 + }
1.225 +
1.226 + if (IsVoteInProgress())
1.227 + {
1.228 + ReplyToCommand(client, "[SM] %t", "Vote in Progress");
1.229 + return Plugin_Handled;
1.230 + }
1.231 +
1.232 + decl String:text[256], String:arg[64];
1.233 + GetCmdArgString(text, sizeof(text));
1.234 +
1.235 + new len = BreakString(text, arg, sizeof(arg));
1.236 +
1.237 + new target = FindTarget(client, arg);
1.238 + if (target == -1)
1.239 + {
1.240 + return Plugin_Handled;
1.241 + }
1.242 +
1.243 + if (len != -1)
1.244 + {
1.245 + strcopy(g_voteArg, sizeof(g_voteArg), text[len]);
1.246 + }
1.247 + else
1.248 + {
1.249 + g_voteArg[0] = '\0';
1.250 + }
1.251 +
1.252 + g_voteClient[VOTE_CLIENTID] = target;
1.253 + g_voteClient[VOTE_USERID] = GetClientUserId(target);
1.254 +
1.255 + GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
1.256 +
1.257 + ShowActivity(client, "%t", "Initiated Vote Kick", g_voteInfo[VOTE_NAME]);
1.258 +
1.259 + g_voteType = voteType:kick;
1.260 +
1.261 + g_hVoteMenu = CreateMenu(Handler_VoteCallback);
1.262 + SetMenuTitle(g_hVoteMenu, "Votekick Player");
1.263 + AddMenuItem(g_hVoteMenu, "No", "Yes");
1.264 + AddMenuItem(g_hVoteMenu, "No", "No");
1.265 + SetMenuExitButton(g_hVoteMenu, false);
1.266 + VoteMenuToAll(g_hVoteMenu, 20);
1.267 +
1.268 + return Plugin_Handled;
1.269 +}
1.270 +
1.271 +public Action:Command_Voteban(client, args)
1.272 +{
1.273 + if (args < 1)
1.274 + {
1.275 + ReplyToCommand(client, "[SM] Usage: sm_voteban <player> [reason]");
1.276 + return Plugin_Handled;
1.277 + }
1.278 +
1.279 + if (IsVoteInProgress())
1.280 + {
1.281 + ReplyToCommand(client, "[SM] %t", "Vote in Progress");
1.282 + return Plugin_Handled;
1.283 + }
1.284 +
1.285 + decl String:text[256], String:arg[64];
1.286 + GetCmdArgString(text, sizeof(text));
1.287 +
1.288 + new len = BreakString(text, arg, sizeof(arg));
1.289 +
1.290 + new target = FindTarget(client, arg);
1.291 + if (target == -1)
1.292 + {
1.293 + return Plugin_Handled;
1.294 + }
1.295 +
1.296 + if (len != -1)
1.297 + {
1.298 + strcopy(g_voteArg, sizeof(g_voteArg), text[len]);
1.299 + }
1.300 + else
1.301 + {
1.302 + g_voteArg[0] = '\0';
1.303 + }
1.304 +
1.305 + g_voteClient[VOTE_CLIENTID] = target;
1.306 + g_voteClient[VOTE_USERID] = GetClientUserId(target);
1.307 +
1.308 + GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[]));
1.309 + GetClientAuthString(target, g_voteInfo[VOTE_AUTHID], sizeof(g_voteInfo[]));
1.310 + GetClientIP(target, g_voteInfo[VOTE_IP], sizeof(g_voteInfo[]));
1.311 +
1.312 + ShowActivity(client, "%t", "Initiated Vote Ban", g_voteInfo[VOTE_NAME]);
1.313 +
1.314 + g_voteType = voteType:ban;
1.315 +
1.316 + g_hVoteMenu = CreateMenu(Handler_VoteCallback);
1.317 + SetMenuTitle(g_hVoteMenu, "Voteban Player");
1.318 + AddMenuItem(g_hVoteMenu, "No", "Yes");
1.319 + AddMenuItem(g_hVoteMenu, "No", "No");
1.320 + SetMenuExitButton(g_hVoteMenu, false);
1.321 + VoteMenuToAll(g_hVoteMenu, 20);
1.322 +
1.323 + return Plugin_Handled;
1.324 +}
1.325 +
1.326 +public Handler_VoteCallback(Handle:menu, MenuAction:action, param1, param2)
1.327 +{
1.328 + if (action == MenuAction_End)
1.329 + {
1.330 + VoteMenuClose();
1.331 + }
1.332 + else if (action == MenuAction_Display)
1.333 + {
1.334 + }
1.335 + else if (action == MenuAction_DisplayItem)
1.336 + {
1.337 + decl String:display[64];
1.338 + GetMenuItem(menu, param2, "", 0, _, display, sizeof(display));
1.339 +
1.340 + if(strcmp(display, "No") == 0 || strcmp(display, "Yes") == 0)
1.341 + {
1.342 + decl String:buffer[255];
1.343 + Format(buffer, sizeof(buffer), "%T", display, param1);
1.344 +
1.345 + return RedrawMenuItem(buffer);
1.346 + }
1.347 + }
1.348 + /* else if (action == MenuAction_Select)
1.349 + {
1.350 + VoteSelect(menu, param1, param2);
1.351 + }*/
1.352 + else if (action == MenuAction_VoteEnd)
1.353 + {
1.354 + decl String:item[64], String:display[64];
1.355 + new Float:percent, Float:limit, votes, totalVotes;
1.356 + GetMenuVoteInfo(param2, votes, totalVotes);
1.357 +
1.358 + if (totalVotes < 1)
1.359 + {
1.360 + PrintToChatAll("[SM] %t", "No Votes Cast");
1.361 + return;
1.362 + }
1.363 +
1.364 + GetMenuItem(menu, param1, item, sizeof(item), _, display, sizeof(display));
1.365 +
1.366 + if (strcmp(display,"No") == 0 && param1 == 1)
1.367 + {
1.368 + votes = totalVotes - votes; // Reverse the votes to be in relation to the Yes option.
1.369 + }
1.370 +
1.371 + percent = GetVotePercent(votes, totalVotes);
1.372 +
1.373 + switch(g_voteType)
1.374 + {
1.375 + case (voteType:map):
1.376 + limit = GetConVarFloat(g_Cvar_VoteMap);
1.377 +
1.378 + case (voteType:kick):
1.379 + limit = GetConVarFloat(g_Cvar_VoteKick);
1.380 +
1.381 + case (voteType:ban):
1.382 + limit = GetConVarFloat(g_Cvar_VoteBan);
1.383 + }
1.384 +
1.385 + // A multi-argument vote is "always successful", but have to check if its a Yes/No vote.
1.386 + if ((strcmp(display,"Yes") == 0 && FloatCompare(percent,limit) < 0 && param1 == 0) || (strcmp(display,"No") == 0 && param1 == 1))
1.387 + {
1.388 + LogMessage("Vote failed.");
1.389 + PrintToChatAll("[SM] %t", "Vote Failed", RoundToNearest(100.0*limit), RoundToNearest(100.0*percent), totalVotes);
1.390 + }
1.391 + else
1.392 + {
1.393 + PrintToChatAll("[SM] %t", "Vote Successful", RoundToNearest(100.0*percent), totalVotes);
1.394 +
1.395 + switch(g_voteType)
1.396 + {
1.397 + case (voteType:question):
1.398 + {
1.399 + PrintToChatAll("[SM] %t", "Vote End", g_voteArg, item, RoundToNearest(100.0*percent), totalVotes);
1.400 + }
1.401 +
1.402 + case (voteType:map):
1.403 + {
1.404 + LogMessage("Changing map to %s due to vote.", item);
1.405 + PrintToChatAll("[SM] %t", "Changing map", item);
1.406 + new Handle:dp;
1.407 + CreateDataTimer(5.0, Timer_ChangeMap, dp);
1.408 + WritePackString(dp, item);
1.409 + }
1.410 +
1.411 + case (voteType:kick):
1.412 + {
1.413 + if (g_voteArg[0] == '\0')
1.414 + {
1.415 + strcopy(g_voteArg, sizeof(g_voteArg), "Votekicked");
1.416 + }
1.417 +
1.418 + PrintToChatAll("[SM] %t", "Kicked player", g_voteInfo[VOTE_NAME]);
1.419 + LogMessage("Vote kick successful, kicked \"%L\" (reason \"%s\")", g_voteClient[VOTE_USERID], g_voteArg);
1.420 +
1.421 + ServerCommand("kickid %d \"%s\"", g_voteClient[VOTE_USERID], g_voteArg);
1.422 + }
1.423 +
1.424 + case (voteType:ban):
1.425 + {
1.426 + /* Fire the ban forward */
1.427 + Call_StartForward(g_hBanForward);
1.428 + Call_PushCell(0);
1.429 + Call_PushCell(g_voteClient[VOTE_USERID]);
1.430 + Call_PushCell(30);
1.431 + Call_PushString(g_voteArg);
1.432 + Call_Finish();
1.433 +
1.434 + if (g_voteArg[0] == '\0')
1.435 + {
1.436 + strcopy(g_voteArg, sizeof(g_voteArg), "Votebanned");
1.437 + }
1.438 +
1.439 + PrintToChatAll("[SM] %t", "Banned player", g_voteInfo[VOTE_NAME], 30);
1.440 + LogMessage("Vote ban successful, banned \"%L\" (minutes \"30\") (reason \"%s\")", g_voteClient[VOTE_USERID], g_voteArg);
1.441 +
1.442 + ServerCommand("banid %d %s", 30, g_voteClient[VOTE_AUTHID]);
1.443 + ServerCommand("kickid %d \"%s\"", g_voteClient[VOTE_USERID], g_voteArg);
1.444 + }
1.445 + }
1.446 + }
1.447 + }
1.448 +}
1.449 +
1.450 +/*
1.451 +VoteSelect(Handle:menu, param1, param2 = 0)
1.452 +{
1.453 + if (GetConVarInt(g_Cvar_VoteShow) == 1)
1.454 + {
1.455 + decl String:voter[64], String:junk[64], String:choice[64];
1.456 + GetClientName(param1, voter, sizeof(voter));
1.457 + GetMenuItem(menu, param2, junk, sizeof(junk), _, choice, sizeof(choice));
1.458 + PrintToChatAll("[SM] %T", "Vote Select", LANG_SERVER, voter, choice);
1.459 + }
1.460 +}
1.461 +*/
1.462 +
1.463 +VoteMenuClose()
1.464 +{
1.465 + CloseHandle(g_hVoteMenu);
1.466 + g_hVoteMenu = INVALID_HANDLE;
1.467 +}
1.468 +
1.469 +Float:GetVotePercent(votes, totalVotes)
1.470 +{
1.471 + return FloatDiv(float(votes),float(totalVotes));
1.472 +}
1.473 +
1.474 +public Action:Timer_ChangeMap(Handle:timer, Handle:dp)
1.475 +{
1.476 + decl String:mapname[65];
1.477 +
1.478 + ResetPack(dp);
1.479 + ReadPackString(dp, mapname, sizeof(mapname));
1.480 +
1.481 + ServerCommand("changelevel \"%s\"", mapname);
1.482 +
1.483 + return Plugin_Stop;
1.484 +}
1.485 \ No newline at end of file
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/translations/basevotes.phrases.txt Wed Aug 08 23:35:16 2007 +0000
2.3 @@ -0,0 +1,66 @@
2.4 +"Phrases"
2.5 +{
2.6 + "Initiate Vote"
2.7 + {
2.8 + "#format" "{1:s}"
2.9 + "en" "Initiated a vote: {1}"
2.10 + }
2.11 +
2.12 + "Initiated Vote Map"
2.13 + {
2.14 + "en" "Initiated a votemap."
2.15 + }
2.16 +
2.17 + "Initiated Vote Kick"
2.18 + {
2.19 + "#format" "{1:s}"
2.20 + "en" "Initiated a votekick against {1}."
2.21 + }
2.22 +
2.23 + "Initiated Vote Ban"
2.24 + {
2.25 + "#format" "{1:s}"
2.26 + "en" "Initiated a voteban against {1}."
2.27 + }
2.28 +
2.29 + "Map Vote"
2.30 + {
2.31 + "en" "Map Vote:"
2.32 + }
2.33 +
2.34 + "Change Map To"
2.35 + {
2.36 + "#format" "{1:s}"
2.37 + "en" "Change map to {1}?"
2.38 + }
2.39 +
2.40 + "Votekick Player"
2.41 + {
2.42 + "#format" "{1:s}"
2.43 + "en" "Kick {1}?"
2.44 + }
2.45 +
2.46 + "Voteban Player"
2.47 + {
2.48 + "#format" "{1:s}"
2.49 + "en" "Ban {1}?"
2.50 + }
2.51 +
2.52 + "Vote Successful"
2.53 + {
2.54 + "#format" "{1:d},{2:d}"
2.55 + "en" "Vote successful. (Received {1}%% of {2} votes)"
2.56 + }
2.57 +
2.58 + "Vote Failed"
2.59 + {
2.60 + "#format" "{1:d},{2:d},{3:d}"
2.61 + "en" "Vote failed. {1}%% vote required. (Received {2}%% of {3} votes)"
2.62 + }
2.63 +
2.64 + "Vote End"
2.65 + {
2.66 + "#format" "{1:s},{2:s},{3:d},{4:d}"
2.67 + "en" "The answer to {1} is: {2}. (Received {3}%% of {4} votes)"
2.68 + }
2.69 +}
3.1 --- a/translations/common.phrases.txt Wed Aug 08 23:26:42 2007 +0000
3.2 +++ b/translations/common.phrases.txt Wed Aug 08 23:35:16 2007 +0000
3.3 @@ -1,5 +1,15 @@
3.4 "Phrases"
3.5 {
3.6 + "Yes"
3.7 + {
3.8 + "en" "Yes"
3.9 + }
3.10 +
3.11 + "No"
3.12 + {
3.13 + "en" "No"
3.14 + }
3.15 +
3.16 "No matching client"
3.17 {
3.18 "en" "No matching client was found."
3.19 @@ -178,4 +188,15 @@
3.20 {
3.21 "en" "Cancelled the vote."
3.22 }
3.23 +
3.24 + "Vote Select"
3.25 + {
3.26 + "#format" "{1:s},{2:s}"
3.27 + "en" "{1} has chosen {2}."
3.28 + }
3.29 +
3.30 + "No Votes Cast"
3.31 + {
3.32 + "en" "No votes were cast."
3.33 + }
3.34 }