· 8 years ago · Dec 21, 2017, 02:20 PM
1#include <sourcemod>
2#include <sdktools>
3#include <sdkhooks>
4#include <cstrike>
5#include <gagg>
6
7#undef REQUIRE_PLUGIN
8#include <adminmenu>
9
10#define MAPSVOTE_MENU_TITLE "★ Next Map Vote ★"
11#define VOTING_TIME (12) // Seconds.
12#define DEFAULT_GAG_MINUTES (5) // Minutes, only if not specified.
13
14new Handle:g_pConnection = INVALID_HANDLE;
15new String:g_VotedMaps[3][32];
16new g_VotedMapsVotes[3] = { 0, ... };
17new g_VotedMapsCount = 0;
18new Handle:g_pAdminMenu = INVALID_HANDLE;
19new Handle:g_pNames = INVALID_HANDLE;
20new Handle:g_pIPs = INVALID_HANDLE;
21new Handle:g_pSteams = INVALID_HANDLE;
22
23MakeNameFriendly(String:Name[], Size)
24{
25 ReplaceString(Name, Size, "'", "*");
26 ReplaceString(Name, Size, "\\", "*");
27 ReplaceString(Name, Size, "\"", "*");
28 ReplaceString(Name, Size, "`", "*");
29}
30
31ShortenMapName(String:Old[64], String:New[64])
32{
33 static Iterator, CopyFrom;
34
35 CopyFrom = 0xFF;
36 Old[0] = CharToUpper(Old[0]);
37 ReplaceString(Old, sizeof(Old), "_", " ");
38
39 if (StrContains(Old, " ") != -1)
40 {
41 for (Iterator = 0; Iterator < strlen(Old); Iterator++)
42 {
43 if (Old[Iterator] == ' ')
44 {
45 CopyFrom = Iterator + 1;
46 break;
47 }
48 }
49 }
50
51 if (CopyFrom != 0xFF)
52 {
53 strcopy(New, sizeof(New), Old[CopyFrom]);
54 New[0] = CharToUpper(New[0]);
55
56 for (Iterator = 0; Iterator < strlen(New); Iterator++)
57 {
58 if (Iterator > 0 && New[Iterator - 1] == ' ')
59 New[Iterator] = CharToUpper(New[Iterator]);
60 }
61 }
62
63 else
64 strcopy(New, sizeof(New), Old);
65}
66
67AddCommas(Number, String:Output[16])
68{
69 static String:Temporary[16], outPos, noPos, noLen;
70 outPos = noPos = 0;
71
72 if (Number < 0)
73 Output[outPos++] = '-', Number = -Number;
74
75 if ((noLen = IntToString(Number, Temporary, sizeof(Temporary))) <= 3)
76 outPos = strcopy(Output[outPos], sizeof(Output), Temporary);
77
78 else
79 {
80 while (noPos < noLen)
81 {
82 Output[outPos++] = Temporary[noPos++];
83
84 if ((noLen - noPos) && !((noLen - noPos) % 3))
85 Output[outPos++] = ',';
86 }
87
88 Output[outPos] = EOS;
89 }
90}
91
92bool:ValidPlayer(Player)
93{
94 return Player >= 1 && Player <= MaxClients ? true : false;
95}
96
97bool:BadPlayer(Client, bool:CheckIfConnected = true, bool:CheckIfFake = true)
98{
99 if (!ValidPlayer(Client))
100 return true;
101
102 if (CheckIfConnected && !IsClientInGame(Client))
103 return true;
104
105 if (CheckIfFake && IsFakeClient(Client))
106 return true;
107
108 if (IsClientInKickQueue(Client) || IsClientSourceTV(Client))
109 return true;
110
111 return false;
112}
113
114public OnPluginStart()
115{
116 LoadTranslations("common.phrases");
117
118 RegAdminCmd("sm_votemap", CommandVoteMap, ADMFLAG_VOTE, "sm_votemap <map 1> [map 2] [map 3] - Votes maps.");
119 RegAdminCmd("sm_votemaps", CommandVoteMap, ADMFLAG_VOTE, "sm_votemaps <map 1> [map 2] [map 3] - Votes maps.");
120
121 new String:Error[256];
122 g_pConnection = SQL_Connect("gags", false, Error, sizeof(Error));
123
124 new Handle:pTopMenu = INVALID_HANDLE;
125 if (LibraryExists("adminmenu") && ((pTopMenu = GetAdminTopMenu()) != INVALID_HANDLE))
126 OnAdminMenuReady(pTopMenu);
127
128 if (g_pConnection != INVALID_HANDLE)
129 {
130 RegAdminCmd("sm_last", CommandLast, ADMFLAG_SLAY, "sm_last - Lists all disconnected players.");
131
132 RegAdminCmd("sm_gag", CommandGag, ADMFLAG_SLAY, "sm_gag <target> <minutes> [reason] - Gags player by time and reason (retry resistant).");
133 RegAdminCmd("sm_ungag", CommandUngag, ADMFLAG_SLAY, "sm_ungag <target> - Ungags player.");
134
135 RegAdminCmd("sm_silence", CommandGag, ADMFLAG_SLAY, "sm_silence <target> <minutes> [reason] - Gags player by time and reason (retry resistant).");
136 RegAdminCmd("sm_unsilence", CommandUngag, ADMFLAG_SLAY, "sm_unsilence <target> - Ungags player.");
137
138 RegAdminCmd("sm_mute", CommandGag, ADMFLAG_SLAY, "sm_mute <target> <minutes> [reason] - Gags player by time and reason (retry resistant).");
139 RegAdminCmd("sm_unmute", CommandUngag, ADMFLAG_SLAY, "sm_unmute <target> - Ungags player.");
140
141 SQL_SetCharset(g_pConnection, "utf8");
142 SQL_TQuery(g_pConnection, EmptyFunction, "CREATE TABLE IF NOT EXISTS Gagged (Name TEXT, Steam TEXT, Ip TEXT, gagTime NUMERIC, gagLength NUMERIC, ungagTime NUMERIC, adminName TEXT, adminSteam TEXT, adminIp TEXT, Reason TEXT);");
143
144 CreateTimer(60.0, Timer_CheckGags, _, TIMER_REPEAT);
145 }
146
147 else
148 LogError("SQL_Connect() @ OnPluginStart() resulted error: %s", Error);
149
150 RegConsoleCmd("say", CommandSay);
151 RegConsoleCmd("say_team", CommandSay);
152
153 g_pIPs = CreateArray(64);
154 g_pNames = CreateArray(64);
155 g_pSteams = CreateArray(64);
156}
157
158public OnLibraryRemoved(const String:Name[])
159{
160 if (StrEqual(Name, "adminmenu"))
161 g_pAdminMenu = INVALID_HANDLE;
162}
163
164public OnAdminMenuReady(Handle:pTopMenu)
165{
166 if (pTopMenu == g_pAdminMenu)
167 return;
168
169 g_pAdminMenu = pTopMenu;
170
171 new TopMenuObject:pPlrCmds = FindTopMenuCategory(g_pAdminMenu, ADMINMENU_PLAYERCOMMANDS);
172 if (g_pConnection != INVALID_HANDLE)
173 {
174 AddToTopMenu(g_pAdminMenu, "sm_gag", TopMenuObject_Item, GagTopMenuHandler, pPlrCmds, "sm_gag", ADMFLAG_SLAY);
175 AddToTopMenu(g_pAdminMenu, "sm_ungag", TopMenuObject_Item, UngagTopMenuHandler, pPlrCmds, "sm_ungag", ADMFLAG_SLAY);
176 }
177}
178
179public GagTopMenuHandler(Handle:pTopMenu, TopMenuAction:iAction, TopMenuObject:pObject, Param, String:Buffer[], maxLen)
180{
181 if (iAction == TopMenuAction_DisplayOption)
182 FormatEx(Buffer, maxLen, "Gag+Mute+Silence (+Retry Support)");
183
184 else if (iAction == TopMenuAction_SelectOption)
185 GagPlayersMenu(Param);
186}
187
188public UngagTopMenuHandler(Handle:pTopMenu, TopMenuAction:iAction, TopMenuObject:pObject, Param, String:Buffer[], maxLen)
189{
190 if (iAction == TopMenuAction_DisplayOption)
191 FormatEx(Buffer, maxLen, "Ungag+Unmute+Unsilence (+Retry Support)");
192
193 else if (iAction == TopMenuAction_SelectOption)
194 UngagPlayersMenu(Param);
195}
196
197GagPlayersMenu(client)
198{
199 new Handle:pMenu = CreateMenu(GagPlayersMenuHandler);
200 SetMenuTitle(pMenu, "Gag+Mute+Silence (+Retry Support)");
201
202 new String:Name[64], String:Info[8];
203 for (new Plr = 1; Plr <= MaxClients; Plr++)
204 {
205 if (IsClientInGame(Plr) && !g_Gagged[Plr] && !IsFakeClient(Plr) && !IsClientSourceTV(Plr))
206 {
207 GetClientName(Plr, Name, sizeof(Name));
208 IntToString(GetClientUserId(Plr), Info, sizeof(Info));
209 AddMenuItem(pMenu, Info, Name);
210 }
211 }
212
213 DisplayMenu(pMenu, client, MENU_TIME_FOREVER);
214}
215
216UngagPlayersMenu(client)
217{
218 new Handle:pMenu = CreateMenu(UngagPlayersMenuHandler);
219 SetMenuTitle(pMenu, "Ungag+Unmute+Unsilence (+Retry Support)");
220
221 new String:Name[64], String:Info[8];
222 for (new Plr = 1; Plr <= MaxClients; Plr++)
223 {
224 if (IsClientInGame(Plr) && g_Gagged[Plr] && !IsFakeClient(Plr) && !IsClientSourceTV(Plr))
225 {
226 GetClientName(Plr, Name, sizeof(Name));
227 IntToString(GetClientUserId(Plr), Info, sizeof(Info));
228 AddMenuItem(pMenu, Info, Name);
229 }
230 }
231
232 DisplayMenu(pMenu, client, MENU_TIME_FOREVER);
233}
234
235public GagPlayersMenuHandler(Handle:pMenu, MenuAction:iAction, Client, Selection)
236{
237 if (iAction == MenuAction_Select)
238 {
239 new String:Info[64];
240 GetMenuItem(pMenu, Selection, Info, sizeof(Info));
241 ClientCommand(Client, "sm_gag #%d %d", StringToInt(Info), DEFAULT_GAG_MINUTES);
242 }
243
244 else if (iAction == MenuAction_End)
245 CloseHandle(pMenu);
246}
247
248public UngagPlayersMenuHandler(Handle:pMenu, MenuAction:iAction, Client, Selection)
249{
250 if (iAction == MenuAction_Select)
251 {
252 new String:Info[64];
253 GetMenuItem(pMenu, Selection, Info, sizeof(Info));
254 ClientCommand(Client, "sm_ungag #%d", StringToInt(Info));
255 }
256
257 else if (iAction == MenuAction_End)
258 CloseHandle(pMenu);
259}
260
261public OnGameFrame()
262{
263 if (g_pConnection != INVALID_HANDLE)
264 {
265 for (new Plr = 1; Plr <= MaxClients; Plr++)
266 {
267 if (g_Gagged[Plr] && IsClientInGame(Plr) && !IsFakeClient(Plr) && !IsClientSourceTV(Plr))
268 {
269 SetClientListeningFlags(Plr, VOICE_MUTED);
270 }
271 }
272 }
273}
274
275public Action: CommandSay(Id, Args)
276{
277 static String:Fmt[256], String:Steam[64];
278
279 if (!BadPlayer(Id))
280 {
281 if (g_Gagged[Id])
282 {
283 GetClientAuthId(Id, AuthId_Engine, Steam, sizeof(Steam));
284 FormatEx(Fmt, sizeof(Fmt), "SELECT ungagTime FROM Gagged WHERE Steam = '%s';", Steam);
285 SQL_TQuery(g_pConnection, PrintLeft, Fmt, Id);
286
287 return Plugin_Handled;
288 }
289 }
290
291 return Plugin_Continue;
292}
293
294public Action: Timer_CheckGags(Handle:pTimer, any:Data)
295{
296 if (g_pConnection != INVALID_HANDLE)
297 SQL_TQuery(g_pConnection, ManageGags, "SELECT Name, Steam, ungagTime, Reason FROM Gagged;");
298}
299
300public OnClientPutInServer(Id)
301{
302 if (g_pConnection != INVALID_HANDLE && !IsFakeClient(Id) && !IsClientSourceTV(Id))
303 {
304 new String:Steam[64];
305 GetClientAuthId(Id, AuthId_Engine, Steam, sizeof(Steam));
306
307 new String:Fmt[256];
308 FormatEx(Fmt, sizeof(Fmt), "SELECT gagTime FROM Gagged WHERE Steam = '%s';", Steam);
309
310 SQL_TQuery(g_pConnection, RetrieveGag, Fmt, Id);
311 }
312}
313
314public EmptyFunction(Handle:Db, Handle:Query, String:Error[], Data)
315{
316 if (strlen(Error))
317 LogError("SQL_TQuery() @ EmptyFunction() reported: %s", Error);
318}
319
320public RetrieveGag(Handle:Db, Handle:Query, String:Error[], Data)
321{
322 if (!strlen(Error))
323 {
324 if (IsClientInGame(Data) && SQL_HasResultSet(Query) && SQL_GetRowCount(Query) > 0)
325 g_Gagged[Data] = true;
326 }
327
328 else
329 LogError("SQL_TQuery() @ RetrieveGag() reported: %s", Error);
330}
331
332public OnClientDisconnect(Id)
333{
334 static String:Name[64], String:Steam[64], String:Ip[64];
335
336 GetClientName(Id, Name, sizeof(Name));
337 GetClientIP(Id, Ip, sizeof(Ip), true);
338 GetClientAuthId(Id, AuthId_Engine, Steam, sizeof(Steam));
339
340 if (g_Gagged[Id])
341 {
342 PrintToChatAll("\x01Gagged player\x03 %s\x01 has left, but their gag remains.", Name);
343 g_Gagged[Id] = false;
344 }
345
346 PushArrayString(g_pNames, Name);
347 PushArrayString(g_pSteams, Steam);
348 PushArrayString(g_pIPs, Ip);
349}
350
351public PrintLeft(Handle:Db, Handle:Query, String:Error[], Data)
352{
353 if (!strlen(Error))
354 {
355 if (IsClientInGame(Data) && SQL_HasResultSet(Query) && SQL_GetRowCount(Query) > 0 && SQL_FetchRow(Query))
356 {
357 new ungagTime = SQL_FetchInt(Query, 0);
358 new remainingMinutes = (ungagTime - GetTime()) / 60;
359
360 if (remainingMinutes < 1)
361 PrintToChat(Data, "\x01You will be ungagged in less than\x04 1 minute\x01.");
362
363 else if (remainingMinutes == 1)
364 PrintToChat(Data, "\x01You will be ungagged in\x04 1 minute\x01.");
365
366 else
367 PrintToChat(Data, "\x01You will be ungagged in\x04 %d minutes\x01.", remainingMinutes);
368 }
369 }
370
371 else
372 LogError("SQL_TQuery() @ PrintLeft() reported: %s", Error);
373}
374
375public ManageGags(Handle:Db, Handle:Query, String:Error[], Data)
376{
377 static String:gaggedName[64], ungagTime = 0, String:gaggedSteam[64], Now = 0, String:Fmt[256], String:PlrSteam[64], \
378 String:Reason[64], Plr;
379
380 if (!strlen(Error))
381 {
382 if (SQL_HasResultSet(Query))
383 {
384 Now = GetTime();
385
386 while (SQL_FetchRow(Query))
387 {
388 SQL_FetchString(Query, 0, gaggedName, sizeof(gaggedName));
389 SQL_FetchString(Query, 1, gaggedSteam, sizeof(gaggedSteam));
390 ungagTime = SQL_FetchInt(Query, 2);
391 SQL_FetchString(Query, 3, Reason, sizeof(Reason));
392
393 if (ungagTime < Now)
394 {
395 FormatEx(Fmt, sizeof(Fmt), "DELETE FROM Gagged WHERE Steam = '%s';", gaggedSteam);
396 SQL_TQuery(g_pConnection, UngagEntry, Fmt);
397
398 if (strlen(Reason) > 0)
399 PrintToChatAll("\x01Gag for\x03 %s\x01 expired! Reason\x04 %s\x01.", gaggedName, Reason);
400
401 else
402 PrintToChatAll("\x01Gag for\x03 %s\x01 expired!", gaggedName);
403
404 for (Plr = 1; Plr <= MaxClients; Plr++)
405 {
406 if (!IsClientInGame(Plr))
407 continue;
408
409 GetClientAuthId(Plr,AuthId_Engine, PlrSteam, sizeof(PlrSteam));
410 if (strcmp(PlrSteam, gaggedSteam) == 0)
411 {
412 g_Gagged[Plr] = false;
413 SetClientListeningFlags(Plr, VOICE_NORMAL);
414 }
415 }
416 }
417 }
418 }
419 }
420
421 else
422 LogError("SQL_TQuery() @ ManageGags() reported: %s", Error);
423}
424
425public UngagEntry(Handle:Db, Handle:Query, String:Error[], Data)
426{
427 if (strlen(Error) > 0)
428 LogError("SQL_TQuery() @ UngagEntry() reported: %s", Error);
429}
430
431public Action: CommandLast(Client, Args)
432{
433 if (GetArraySize(g_pNames) == 0)
434 {
435 PrintToConsole(Client, "There are no disconnected clients!");
436 return Plugin_Stop;
437 }
438
439 new String:Name[64], String:Steam[64], String:Ip[64], Total = 0;
440
441 PrintToConsole(Client, "%32s %32s %32s", "Name", "Steam", "IP Address");
442
443 for (new Iter = GetArraySize(g_pNames) - 1; Iter >= 0; Iter--)
444 {
445 GetArrayString(g_pNames, Iter, Name, sizeof(Name));
446 GetArrayString(g_pSteams, Iter, Steam, sizeof(Steam));
447 GetArrayString(g_pIPs, Iter, Ip, sizeof(Ip));
448
449 PrintToConsole(Client, "%32s %32s %32s", Name, Steam, Ip);
450
451 if (++Total >= 20)
452 break;
453 }
454
455 return Plugin_Stop;
456}
457
458public Action: CommandGag(Client, Args)
459{
460 if (Args < 1)
461 {
462 ReplyToCommand(Client, "[SM] Usage: sm_gag <target> <minutes> [reason] - Gags player by time and reason (retry resistant).");
463 return Plugin_Stop;
464 }
465
466 new String:Victim[32], iVictim = 0, String:Minutes[32], iMinutes = 0, iSeconds = 0, String:Reason[32], String:MinutesFmt[16], \
467 String:VictimName[32], String:VictimSteam[32], String:AdminName[32], String:AdminSteam[32], String:VictimIp[32], \
468 String:AdminIp[32], Targets[MAXPLAYERS], Res, bool:bTnIsML, Now = GetTime(), String:TargetName[4], String:Fmt[512];
469
470 GetCmdArg(1, Victim, sizeof(Victim));
471 GetCmdArg(2, Minutes, sizeof(Minutes));
472
473 if (Args >= 3)
474 GetCmdArg(3, Reason, sizeof(Reason));
475
476 iMinutes = StringToInt(Minutes);
477
478 if (iMinutes == 0)
479 iMinutes = DEFAULT_GAG_MINUTES;
480
481 if (iMinutes < 1)
482 {
483 ReplyToCommand(Client, "[SM] You must specify at least one minute.");
484 return Plugin_Stop;
485 }
486
487 if (iMinutes > 1440)
488 {
489 ReplyToCommand(Client, "[SM] You must specify at most 1,440 minutes (1 day).");
490 return Plugin_Stop;
491 }
492
493 iSeconds = iMinutes * 60;
494
495 GetCmdArg(1, Victim, sizeof(Victim));
496 if ((Res = ProcessTargetString(Victim, Client, Targets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_BOTS, TargetName, sizeof(TargetName), bTnIsML)) <= COMMAND_TARGET_NONE)
497 {
498 ReplyToTargetError(Client, Res);
499 return Plugin_Stop;
500 }
501
502 iVictim = Targets[0];
503 if (g_Gagged[iVictim])
504 {
505 ReplyToCommand(Client, "[SM] This user is already gagged.");
506 return Plugin_Stop;
507 }
508
509 if (IsClientSourceTV(iVictim))
510 {
511 ReplyToCommand(Client, "[SM] This user is a GOTV client.");
512 return Plugin_Stop;
513 }
514
515 GetClientName(iVictim, VictimName, sizeof(VictimName));
516 GetClientAuthId(iVictim, AuthId_Engine, VictimSteam, sizeof(VictimSteam));
517 GetClientIP(iVictim, VictimIp, sizeof(VictimIp), true);
518
519 GetClientName(Client, AdminName, sizeof(AdminName));
520 GetClientAuthId(Client,AuthId_Engine, AdminSteam, sizeof(AdminSteam));
521 GetClientIP(Client, AdminIp, sizeof(AdminIp), true);
522
523 MakeNameFriendly(AdminName, sizeof(AdminName));
524 MakeNameFriendly(VictimName, sizeof(VictimName));
525 MakeNameFriendly(Reason, sizeof(Reason));
526
527 FormatEx(Fmt, sizeof(Fmt), "INSERT INTO Gagged VALUES ('%s', '%s', '%s', %d, %d, %d, '%s', '%s', '%s', '%s');", \
528 VictimName, VictimSteam, VictimIp, Now, iMinutes, Now + iSeconds, AdminName, AdminSteam, AdminIp, Reason);
529
530 SQL_TQuery(g_pConnection, AddGag, Fmt);
531
532 AddCommas(iMinutes, MinutesFmt);
533
534 if (strlen(Reason) > 0)
535 PrintToChatAll("\x01Admin\x03 %s\x01 gagged\x03 %s\x01 for\x04 %s minute%s\x01. Reason\x03 %s\x01.", AdminName, VictimName, MinutesFmt, iMinutes == 1 ? "" : "s", Reason);
536
537 else
538 PrintToChatAll("\x01Admin\x03 %s\x01 gagged\x03 %s\x01 for\x04 %s minute%s\x01.", AdminName, VictimName, MinutesFmt, iMinutes == 1 ? "" : "s");
539
540 if (strlen(Reason) > 0)
541 LogMessage("Admin %s (%s) gagged %s (%s) for %s minute%s. Reason %s.", AdminName, AdminSteam, VictimName, VictimSteam, MinutesFmt, iMinutes == 1 ? "" : "s", Reason);
542
543 else
544 LogMessage("Admin %s (%s) gagged %s (%s) for %s minute%s.", AdminName, AdminSteam, VictimName, VictimSteam, MinutesFmt, iMinutes == 1 ? "" : "s");
545
546 g_Gagged[iVictim] = true;
547 return Plugin_Stop;
548}
549
550public Action: CommandUngag(Client, Args)
551{
552 if (Args < 1)
553 {
554 ReplyToCommand(Client, "[SM] Usage: sm_ungag <target> - Ungags player.");
555 return Plugin_Stop;
556 }
557
558 new String:Victim[32], iVictim = 0, String:VictimName[32], String:VictimSteam[32], String:AdminName[32], \
559 String:AdminSteam[32], String:VictimIp[32], String:AdminIp[32], Targets[MAXPLAYERS], Res = 0, bool:bTnIsML = false, \
560 String:TargetName[4], String:Fmt[256];
561
562 GetCmdArg(1, Victim, sizeof(Victim));
563 if ((Res = ProcessTargetString(Victim, Client, Targets, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_BOTS, TargetName, sizeof(TargetName), bTnIsML)) <= COMMAND_TARGET_NONE)
564 {
565 ReplyToTargetError(Client, Res);
566 return Plugin_Stop;
567 }
568
569 iVictim = Targets[0];
570 if (!g_Gagged[iVictim])
571 {
572 ReplyToCommand(Client, "[SM] This user is not gagged.");
573 return Plugin_Stop;
574 }
575
576 if (IsClientSourceTV(iVictim))
577 {
578 ReplyToCommand(Client, "[SM] This user is a GOTV client.");
579 return Plugin_Stop;
580 }
581
582 GetClientName(iVictim, VictimName, sizeof(VictimName));
583 GetClientAuthId(iVictim, AuthId_Engine, VictimSteam, sizeof(VictimSteam));
584 GetClientIP(iVictim, VictimIp, sizeof(VictimIp), true);
585
586 GetClientName(Client, AdminName, sizeof(AdminName));
587 GetClientAuthId(Client, AuthId_Engine, AdminSteam, sizeof(AdminSteam));
588 GetClientIP(Client, AdminIp, sizeof(AdminIp), true);
589
590 FormatEx(Fmt, sizeof(Fmt), "DELETE FROM Gagged WHERE Steam = '%s';", VictimSteam);
591 SQL_TQuery(g_pConnection, UngagSQL, Fmt);
592
593 PrintToChatAll("\x01Admin\x03 %s\x01 ungagged\x03 %s\x01.", AdminName, VictimName);
594 LogMessage("Admin %s (%s) ungagged %s (%s).", AdminName, AdminSteam, VictimName, VictimSteam);
595
596 g_Gagged[iVictim] = false;
597 SetClientListeningFlags(iVictim, VOICE_NORMAL);
598
599 return Plugin_Stop;
600}
601
602public AddGag(Handle:Db, Handle:Query, String:Error[], Data)
603{
604 if (strlen(Error) > 0)
605 LogError("SQL_TQuery() @ AddGag() reported: %s", Error);
606}
607
608public UngagSQL(Handle:Db, Handle:Query, String:Error[], Data)
609{
610 if (strlen(Error) > 0)
611 LogError("SQL_TQuery() @ UngagSQL() reported: %s", Error);
612}
613
614public Action: CommandVoteMap(Client, Args)
615{
616 if (Args < 1)
617 {
618 ReplyToCommand(Client, "[SM] Usage: sm_votemap <map 1> [map 2] [map 3] - Votes maps.");
619 return Plugin_Stop;
620 }
621
622 if (IsVoteInProgress())
623 {
624 ReplyToCommand(Client, "[SM] Vote in progress!");
625 return Plugin_Stop;
626 }
627
628 new String:MapsFull[3][128], Keys = 0;
629
630 if (Args >= 1)
631 GetCmdArg(1, g_VotedMaps[0], sizeof(g_VotedMaps[])), g_VotedMapsCount = 1;
632
633 if (Args >= 2)
634 GetCmdArg(2, g_VotedMaps[1], sizeof(g_VotedMaps[])), g_VotedMapsCount = 2;
635
636 if (Args >= 3)
637 GetCmdArg(3, g_VotedMaps[2], sizeof(g_VotedMaps[])), g_VotedMapsCount = 3;
638
639 switch (g_VotedMapsCount)
640 {
641 case 1:
642 {
643 FormatEx(MapsFull[0], sizeof(MapsFull[]), "maps/%s.bsp", g_VotedMaps[0]);
644 if (!FileExists(MapsFull[0]))
645 {
646 ReplyToCommand(Client, "[SM] Maps '%s' is not valid!", g_VotedMaps[0]);
647 return Plugin_Stop;
648 }
649
650 Keys = 1 << 0;
651 }
652
653 case 2:
654 {
655 FormatEx(MapsFull[0], sizeof(MapsFull[]), "maps/%s.bsp", g_VotedMaps[0]);
656 if (!FileExists(MapsFull[0]))
657 {
658 ReplyToCommand(Client, "[SM] Maps '%s' is not valid!", g_VotedMaps[0]);
659 return Plugin_Stop;
660 }
661
662 FormatEx(MapsFull[1], sizeof(MapsFull[]), "maps/%s.bsp", g_VotedMaps[1]);
663 if (!FileExists(MapsFull[1]))
664 {
665 ReplyToCommand(Client, "[SM] Maps '%s' is not valid!", g_VotedMaps[1]);
666 return Plugin_Stop;
667 }
668
669 Keys = 1 << 0 | 1 << 1;
670 }
671
672 case 3:
673 {
674 FormatEx(MapsFull[0], sizeof(MapsFull[]), "maps/%s.bsp", g_VotedMaps[0]);
675 if (!FileExists(MapsFull[0]))
676 {
677 ReplyToCommand(Client, "[SM] Maps '%s' is not valid!", g_VotedMaps[0]);
678 return Plugin_Stop;
679 }
680
681 FormatEx(MapsFull[1], sizeof(MapsFull[]), "maps/%s.bsp", g_VotedMaps[1]);
682 if (!FileExists(MapsFull[1]))
683 {
684 ReplyToCommand(Client, "[SM] Maps '%s' is not valid!", g_VotedMaps[1]);
685 return Plugin_Stop;
686 }
687
688 FormatEx(MapsFull[2], sizeof(MapsFull[]), "maps/%s.bsp", g_VotedMaps[2]);
689 if (!FileExists(MapsFull[2]))
690 {
691 ReplyToCommand(Client, "[SM] Maps '%s' is not valid!", g_VotedMaps[2]);
692 return Plugin_Stop;
693 }
694
695 Keys = 1 << 0 | 1 << 1 | 1 << 2;
696 }
697 }
698
699 new Handle:Menu_Handle = CreatePanel();
700
701 SetPanelKeys(Menu_Handle, Keys);
702 SetPanelTitle(Menu_Handle, MAPSVOTE_MENU_TITLE);
703 DrawPanelText(Menu_Handle, " \n");
704
705 switch (g_VotedMapsCount)
706 {
707 case 1:
708 {
709 new String:Buffer[128], String:Shorten[64], String:Old[64], String:Name[64], String:Steam[64];
710
711 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[0]);
712 ShortenMapName(Old, Shorten);
713
714 FormatEx(Buffer, sizeof(Buffer), "1. %s", Shorten);
715 DrawPanelText(Menu_Handle, Buffer);
716
717 GetClientName(Client, Name, sizeof(Name));
718 GetClientAuthId(Client, AuthId_Engine, Steam, sizeof(Steam));
719 LogMessage("Admin %s (%s) voted %s [sm_votemap]", Name, Steam, g_VotedMaps[0]);
720 PrintToChatAll("\x01Admin\x03 %s\x01 initiated a vote [\x04 %s\x01 ].", Name, g_VotedMaps[0]);
721 }
722
723 case 2:
724 {
725 new String:Buffer[128], String:Shorten[64], String:Old[64], String:Name[64], String:Steam[64];
726
727 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[0]);
728 ShortenMapName(Old, Shorten);
729
730 FormatEx(Buffer, sizeof(Buffer), "1. %s", Shorten);
731 DrawPanelText(Menu_Handle, Buffer);
732
733 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[1]);
734 ShortenMapName(Old, Shorten);
735
736 FormatEx(Buffer, sizeof(Buffer), "2. %s", Shorten);
737 DrawPanelText(Menu_Handle, Buffer);
738
739 GetClientName(Client, Name, sizeof(Name));
740 GetClientAuthId(Client, AuthId_Engine, Steam, sizeof(Steam));
741 PrintToChatAll("\x01Admin\x03 %s\x01 initiated a vote [\x04 %s\x01 |\x04 %s\x01 ].", Name, g_VotedMaps[0], g_VotedMaps[1]);
742 LogMessage("Admin %s (%s) voted %s | %s [sm_votemap]", Name, Steam, g_VotedMaps[0], g_VotedMaps[1]);
743 }
744
745 case 3:
746 {
747 new String:Buffer[128], String:Shorten[64], String:Old[64], String:Name[64], String:Steam[64];
748
749 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[0]);
750 ShortenMapName(Old, Shorten);
751
752 FormatEx(Buffer, sizeof(Buffer), "1. %s", Shorten);
753 DrawPanelText(Menu_Handle, Buffer);
754
755 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[1]);
756 ShortenMapName(Old, Shorten);
757
758 FormatEx(Buffer, sizeof(Buffer), "2. %s", Shorten);
759 DrawPanelText(Menu_Handle, Buffer);
760
761 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[2]);
762 ShortenMapName(Old, Shorten);
763
764 FormatEx(Buffer, sizeof(Buffer), "3. %s", Shorten);
765 DrawPanelText(Menu_Handle, Buffer);
766
767 GetClientName(Client, Name, sizeof(Name));
768 GetClientAuthId(Client,AuthId_Engine, Steam, sizeof(Steam));
769 PrintToChatAll("\x01Admin\x03 %s\x01 initiated a vote [\x04 %s\x01 |\x04 %s\x01 |\x04 %s\x01 ].", Name, g_VotedMaps[0], g_VotedMaps[1], g_VotedMaps[2]);
770 LogMessage("Admin %s (%s) voted %s | %s | %s [sm_votemap]", Name, Steam, g_VotedMaps[0], g_VotedMaps[1], g_VotedMaps[2]);
771 }
772 }
773
774 g_VotedMapsVotes[0] = 0;
775 g_VotedMapsVotes[1] = 0;
776 g_VotedMapsVotes[2] = 0;
777
778 for (new Other = 1; Other <= MaxClients; Other++)
779 {
780 if (IsClientInGame(Other) && !IsFakeClient(Other) && !IsClientSourceTV(Other))
781 SendPanelToClient(Menu_Handle, Other, VoteMapsMenuHandler, VOTING_TIME);
782 }
783
784 CloseHandle(Menu_Handle);
785
786 CreateTimer(float(VOTING_TIME + 1), Timer_CheckVotesCount, _, TIMER_FLAG_NO_MAPCHANGE);
787 return Plugin_Stop;
788}
789
790public VoteMapsMenuHandler(Handle:Menu_Handle, MenuAction:Menu_Action, Param_A, Param_B)
791{
792 if (Menu_Action == MenuAction_Select && !BadPlayer(Param_A))
793 {
794 g_VotedMapsVotes[Param_B - 1]++;
795
796 new String:Old[64], String:Shorten[64];
797 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[Param_B - 1]);
798
799 ShortenMapName(Old, Shorten);
800 PrintToChat(Param_A, "\x01You voted for\x04 %s\x01.", Shorten);
801 }
802}
803
804public Action: Timer_CheckVotesCount(Handle:pTimer, any:Data)
805{
806 new MaxVotes = -999999, Winner = -1, Votes = 0;
807 for (new Map = 0; Map < g_VotedMapsCount; Map++)
808 {
809 Votes = g_VotedMapsVotes[Map];
810 if (Votes > MaxVotes)
811 {
812 Winner = Map;
813 MaxVotes = Votes;
814 }
815 }
816
817 if (Winner != -1)
818 {
819 new Flags = GetConVarFlags(FindConVar("sm_nextmap")), NewFlags = 0;
820 if (Flags & FCVAR_NOTIFY)
821 {
822 NewFlags = Flags;
823 NewFlags &= ~FCVAR_NOTIFY;
824
825 SetConVarFlags(FindConVar("sm_nextmap"), NewFlags);
826 }
827
828 SetNextMap(g_VotedMaps[Winner]);
829 SetConVarFlags(FindConVar("sm_nextmap"), Flags);
830
831 new String:Old[64], String:Shorten[64];
832 FormatEx(Old, sizeof(Old), "%s", g_VotedMaps[Winner]);
833
834 ShortenMapName(Old, Shorten);
835 PrintToChatAll("\x01The next map will be\x04 %s\x01 (\x03%d vote%s\x01).", Shorten, MaxVotes, MaxVotes == 1 ? "" : "s");
836 }
837}