· 5 years ago · Feb 23, 2020, 09:06 PM
1#include < amxmodx >
2#include < amxmisc >
3#include < engine >
4#include < sqlx >
5
6#define MAX_PLAYERS 32
7
8#define MAX_PATTERN_LEN 255
9
10enum ( <<= 1 )
11{
12 GAG_CHAT = 1,
13 GAG_TEAMSAY,
14 GAG_VOICE
15};
16
17enum _:GagData
18{
19 GAG_STEAMID[ 35 ],
20 GAG_TIME,
21 GAG_START,
22 GAG_FLAGS,
23 GAG_SAVE,
24 GAG_NOTIFY
25};
26
27enum _:TimeUnit
28{
29 TIMEUNIT_SECONDS = 0,
30 TIMEUNIT_MINUTES,
31 TIMEUNIT_HOURS,
32 TIMEUNIT_DAYS,
33 TIMEUNIT_WEEKS
34};
35
36new const g_szTimeUnitName[ TimeUnit ][ 2 ][ ] =
37{
38 { "second", "seconds" },
39 { "minute", "minutes" },
40 { "hour", "hours" },
41 { "day", "days" },
42 { "week", "weeks" }
43};
44
45new const g_iTimeUnitMult[ TimeUnit ] =
46{
47 1,
48 60,
49 3600,
50 86400,
51 604800
52};
53
54new const DATETIME_FORMAT[ ] = "%Y-%m-%d %H:%M:%S";
55const DATE_SIZE = 20;
56
57new Array:g_aGagTimes;
58new Array:g_aGagData;
59new Trie:g_tArrayPos;
60new Trie:g_tTimeUnitWords;
61
62new g_iGagged;
63new g_iThinker;
64new g_iTotalGagTimes;
65new g_iMsgSayText;
66
67new g_szSteamID[ MAX_PLAYERS + 1 ][ 35 ];
68new g_iMenuOption[ MAX_PLAYERS + 1 ];
69new g_iMenuPosition[ MAX_PLAYERS + 1 ];
70new g_iMenuPlayers[ MAX_PLAYERS + 1 ][ 32 ];
71new g_iMenuFlags[ MAX_PLAYERS + 1 ];
72
73new g_szGagFile[ 64 ];
74
75new bool:g_bColorSupported;
76
77new g_pCvarDefaultFlags;
78new g_pCvarDefaultTime;
79new g_pCvarTimeUnit;
80new g_pCvarMaxTime;
81new g_pCvarSQL;
82new g_pCvarSQLHost;
83new g_pCvarSQLUser;
84new g_pCvarSQLPass;
85new g_pCvarSQLDb;
86
87new bool:g_bUsingSQL = false;
88new Handle:g_hSqlTuple;
89
90new szQuery[ 1024 ];
91
92public plugin_init( )
93{
94 register_plugin( "AMXX Gag", "1.5.0", "xPaw & Exolent" );
95
96 register_clcmd( "say", "CmdSay" );
97 register_clcmd( "say_team", "CmdTeamSay" );
98
99 register_concmd( "amx_gag", "CmdGagPlayer", ADMIN_KICK, "<nick or #userid> <time> <a|b|c> -- Use 0 time for permanent" );
100 register_concmd( "amx_addgag", "CmdAddGag", ADMIN_KICK, "<authid> <time> <a|b|c> -- Use 0 time for permanent" );
101 register_concmd( "amx_ungag", "CmdUnGagPlayer", ADMIN_KICK, "<nick or #userid>" );
102 register_concmd( "amx_gagmenu", "CmdGagMenu", ADMIN_KICK, "- displays gag menu" );
103 register_srvcmd( "amx_gag_times", "CmdSetBanTimes" );
104
105 register_menu( "Gag Menu", 1023, "ActionGagMenu" );
106 register_menu( "Gag Flags", 1023, "ActionGagFlags" );
107 register_message( get_user_msgid( "SayText" ), "MessageSayText" );
108
109 g_pCvarDefaultFlags = register_cvar( "amx_gag_default_flags", "abc" );
110 g_pCvarDefaultTime = register_cvar( "amx_gag_default_time", "600" );
111 g_pCvarTimeUnit = register_cvar( "amx_gag_time_units", "0" );
112 g_pCvarMaxTime = register_cvar( "amx_gag_max_time", "86400" );
113 g_pCvarSQL = register_cvar( "amx_gag_sql", "0" );
114 g_pCvarSQLHost = register_cvar( "amx_gag_sql_host", "" );
115 g_pCvarSQLUser = register_cvar( "amx_gag_sql_user", "" );
116 g_pCvarSQLPass = register_cvar( "amx_gag_sql_pass", "" );
117 g_pCvarSQLDb = register_cvar( "amx_gag_sql_db", "" );
118
119 g_tArrayPos = TrieCreate( );
120 g_aGagTimes = ArrayCreate( );
121 g_aGagData = ArrayCreate( GagData );
122 g_bColorSupported = bool:colored_menus( );
123 g_iMsgSayText = get_user_msgid( "SayText" );
124
125 // Let words work with the time unit cvar
126 g_tTimeUnitWords = TrieCreate( );
127
128 for( new i = 0; i < TimeUnit; i++ )
129 {
130 TrieSetCell( g_tTimeUnitWords, g_szTimeUnitName[ i ][ 0 ], i );
131 TrieSetCell( g_tTimeUnitWords, g_szTimeUnitName[ i ][ 1 ], i );
132 }
133
134 // This is used for ungag in the menu
135 ArrayPushCell( g_aGagTimes, 0 );
136
137 // Gag times for the gag menu (amx_gagmenu)
138 // Default values: 60 300 600 1800 3600 7200 86400
139 new const iDefaultTimes[ ] = { 60, 300, 600, 1800, 3600, 7200, 86400, 0 };
140
141 // Load up standart times
142 for( new i = 0; i < sizeof( iDefaultTimes ); i++ )
143 {
144 ArrayPushCell( g_aGagTimes, iDefaultTimes[ i ] );
145 }
146
147 g_iTotalGagTimes = sizeof( iDefaultTimes ) + 1;
148
149 // Set up entity-thinker
150 new const szClassName[ ] = "gag_thinker";
151
152 g_iThinker = create_entity( "info_target" );
153 entity_set_string( g_iThinker, EV_SZ_classname, szClassName );
154
155 register_think( szClassName, "FwdThink" );
156
157 // Load gags from file
158 get_datadir( g_szGagFile, charsmax( g_szGagFile ) );
159 add( g_szGagFile, charsmax( g_szGagFile ), "/gags.txt" );
160
161 // Set server's SteamID to "SERVER"
162 copy( g_szSteamID[ 0 ], charsmax( g_szSteamID[ ] ), "SERVER" );
163}
164
165public plugin_natives( )
166{
167 register_library( "amx_gag" );
168
169 register_native( "is_user_gagged" , "_is_user_gagged" );
170 register_native( "set_user_gagged", "_set_user_gagged" );
171 register_native( "get_gagtime" , "_get_gagtime" );
172
173 register_native( "gag_check" , "_gag_check" );
174 register_native( "gag_add" , "_gag_add" );
175 register_native( "gag_remove", "_gag_remove" );
176}
177
178public _is_user_gagged( iPlugin, iParams )
179{
180 new iPlayer = get_param( 1 );
181
182 return ( is_user_connected( iPlayer ) && TrieKeyExists( g_tArrayPos, g_szSteamID[ iPlayer ] ) );
183}
184
185public _set_user_gagged( iPlugin, iParams )
186{
187 new iPlayer = get_param( 1 );
188 new bGagged = get_param( 2 );
189 new iSeconds = get_param( 3 );
190 new bSave = get_param( 4 );
191 new iFlags = get_param( 5 );
192
193 if( !is_user_connected( iPlayer ) )
194 {
195 return 0;
196 }
197
198 if( bGagged )
199 {
200 if( TrieKeyExists( g_tArrayPos, g_szSteamID[ iPlayer ] ) )
201 {
202 return 0;
203 }
204
205 GagPlayer( 0, iPlayer, g_szSteamID[ iPlayer ], iSeconds, iFlags, bSave, 0 );
206 }
207 else
208 {
209 new iArrayPos;
210
211 if( !TrieGetCell( g_tArrayPos, g_szSteamID[ iPlayer ], iArrayPos ) )
212 {
213 return 0;
214 }
215
216 new data[ GagData ];
217 ArrayGetArray( g_aGagData, iArrayPos, data );
218
219 DeleteGag( iArrayPos );
220
221 if( !g_bUsingSQL && data[ GAG_SAVE ] )
222 {
223 SaveToFile( );
224 }
225 }
226
227 return 1;
228}
229
230public _get_gagtime( iPlugin, iParams )
231{
232 new iPlayer = get_param( 1 );
233 new iTime = 0;
234
235 if( is_user_connected( iPlayer ) )
236 {
237 new iArrayPos;
238
239 if( TrieGetCell( g_tArrayPos, g_szSteamID[ iPlayer ], iArrayPos ) )
240 {
241 new data[ GagData ];
242 ArrayGetArray( g_aGagData, iArrayPos, data );
243
244 if( data[ GAG_TIME ] > 0 )
245 {
246 iTime = data[ GAG_START ] + data[ GAG_TIME ] - get_systime( );
247 }
248 }
249 }
250
251 return iTime;
252}
253
254public _gag_check( iPlugin, iParams )
255{
256 new szSteamID[ 35 ];
257 get_string( 1, szSteamID, charsmax( szSteamID ) );
258
259 return _:TrieKeyExists( g_tArrayPos, szSteamID );
260}
261
262public _gag_add( iPlugin, iParams )
263{
264 new szSteamID[ 35 ];
265 get_string( 1, szSteamID, charsmax( szSteamID ) );
266
267 if( TrieKeyExists( g_tArrayPos, szSteamID ) )
268 {
269 return 0;
270 }
271
272 new iSeconds = get_param( 2 );
273 new bSave = get_param( 3 );
274 new iFlags = get_param( 4 );
275
276 GagPlayer( 0, 0, szSteamID, iSeconds, iFlags, bSave, 0 );
277
278 return 1;
279}
280
281public _gag_remove( iPlugin, iParams )
282{
283 new szSteamID[ 35 ];
284 get_string( 1, szSteamID, charsmax( szSteamID ) );
285
286 new iArrayPos;
287
288 if( !TrieGetCell( g_tArrayPos, szSteamID, iArrayPos ) )
289 {
290 return 0;
291 }
292
293 DeleteGag( iArrayPos );
294
295 return 1;
296}
297
298public plugin_cfg( )
299{
300 // Check SQL
301 InitSQL( );
302
303 if( !g_bUsingSQL )
304 {
305 // If not using SQL, load from file
306 LoadFromFile( );
307 }
308}
309
310InitSQL( )
311{
312 // Init SQL after configs were executed
313 if( get_pcvar_num( g_pCvarSQL ) )
314 {
315 new szHost[ 64 ], szUser[ 64 ], szPass[ 64 ], szDb[ 64 ];
316 get_pcvar_string( g_pCvarSQLHost, szHost, charsmax( szHost ) );
317 get_pcvar_string( g_pCvarSQLUser, szUser, charsmax( szUser ) );
318 get_pcvar_string( g_pCvarSQLPass, szPass, charsmax( szPass ) );
319 get_pcvar_string( g_pCvarSQLDb, szDb, charsmax( szDb ) );
320
321 g_hSqlTuple = SQL_MakeDbTuple( szHost, szUser, szPass, szDb );
322
323 if( g_hSqlTuple == Empty_Handle ) return;
324
325 // TABLE STRUCTURE
326 // admin_name VARCHAR(32) NOT NULL
327 // admin_steamid VARCHAR(35) NOT NULL
328 // admin_ip VARCHAR(15) NOT NULL
329 // player_name VARCHAR(32) NOT NULL
330 // player_steamid VARCHAR(35) NOT NULL PRIMARY KEY
331 // player_ip VARCHAR(15) NOT NULL
332 // date_gagged DATETIME NOT NULL
333 // date_ungag DATETIME NOT NULL
334 // gag_seconds INT NOT NULL
335 // gag_flags VARCHAR(3) NOT NULL
336
337 new iError, szError[ 128 ];
338 new Handle:hDb = SQL_Connect( g_hSqlTuple, iError, szError, charsmax( szError ) );
339
340 if( hDb == Empty_Handle )
341 {
342 log_amx( "Failed to connect to database: (%d) %s", iError, szError );
343 return;
344 }
345
346 new Handle:hQuery = SQL_PrepareQuery( hDb, "CREATE TABLE IF NOT EXISTS gagged_players (\
347 admin_name VARCHAR(32) NOT NULL,\
348 admin_steamid VARCHAR(35) NOT NULL,\
349 admin_ip VARCHAR(15) NOT NULL,\
350 player_name VARCHAR(32) NOT NULL,\
351 player_steamid VARCHAR(35) NOT NULL PRIMARY KEY,\
352 player_ip VARCHAR(15) NOT NULL,\
353 date_gagged DATETIME NOT NULL,\
354 date_ungag DATETIME NOT NULL,\
355 gag_seconds INT NOT NULL,\
356 gag_flags VARCHAR(3) NOT NULL);" );
357
358 if( !SQL_Execute( hQuery ) )
359 {
360 SQL_QueryError( hQuery, szError, charsmax( szError ) );
361 log_amx( "Failed create table query: %s", szError );
362 }
363 else
364 {
365 SQL_FreeHandle( hQuery );
366
367 new szDate[ DATE_SIZE ];
368 get_time( DATETIME_FORMAT, szDate, charsmax( szDate ) );
369
370 // Load all users
371 hQuery = SQL_PrepareQuery( hDb, "SELECT * FROM gagged_players WHERE date_ungag > '%s' OR gag_seconds = 0;", szDate );
372
373 if( !SQL_Execute( hQuery ) )
374 {
375 SQL_QueryError( hQuery, szError, charsmax( szError ) );
376 log_amx( "Failed load gags query: %s", szError );
377 }
378 else
379 {
380 g_bUsingSQL = true;
381
382 if( SQL_NumResults( hQuery ) )
383 {
384 new iSystime = get_systime( );
385 new iShortestTime = 999999;
386
387 new data[ GagData ];
388 new szFlags[ 4 ];
389 new iTimeLeft;
390
391 data[ GAG_SAVE ] = 1;
392 data[ GAG_NOTIFY ] = 1;
393
394 new iFieldSteamID = SQL_FieldNameToNum( hQuery, "player_steamid" );
395 new iFieldDateGagged = SQL_FieldNameToNum( hQuery, "date_gagged" );
396 new iFieldGagTime = SQL_FieldNameToNum( hQuery, "gag_seconds" );
397 new iFieldGagFlags = SQL_FieldNameToNum( hQuery, "gag_flags" );
398
399 while( SQL_MoreResults( hQuery ) )
400 {
401 SQL_ReadResult( hQuery, iFieldSteamID, data[ GAG_STEAMID ], charsmax( data[ GAG_STEAMID ] ) );
402 SQL_ReadResult( hQuery, iFieldDateGagged, szDate, charsmax( szDate ) );
403 data[ GAG_TIME ] = SQL_ReadResult( hQuery, iFieldGagTime );
404 SQL_ReadResult( hQuery, iFieldGagFlags, szFlags, charsmax( szFlags ) );
405
406 data[ GAG_START ] = strtotime( szDate );
407 data[ GAG_FLAGS ] = read_flags( szFlags );
408
409 if( data[ GAG_TIME ] > 0 )
410 {
411 iTimeLeft = data[ GAG_START ] + data[ GAG_TIME ] - iSystime;
412
413 if( iShortestTime > iTimeLeft )
414 {
415 iShortestTime = iTimeLeft;
416 }
417 }
418
419 ArrayPushArray( g_aGagData, data );
420 TrieSetCell( g_tArrayPos, data[ GAG_STEAMID ], g_iGagged );
421 g_iGagged++;
422
423 SQL_NextRow( hQuery );
424 }
425
426 if( iShortestTime < 999999 )
427 {
428 entity_set_float( g_iThinker, EV_FL_nextthink, get_gametime( ) + iShortestTime );
429 }
430 }
431 }
432 }
433
434 SQL_FreeHandle( hQuery );
435 SQL_FreeHandle( hDb );
436 }
437}
438
439public plugin_end( )
440{
441 TrieDestroy( g_tArrayPos );
442 ArrayDestroy( g_aGagData );
443 ArrayDestroy( g_aGagTimes );
444 TrieDestroy( g_tTimeUnitWords );
445}
446
447public CmdSetBanTimes( )
448{
449 new iArgs = read_argc( );
450
451 if( iArgs <= 1 )
452 {
453 server_print( "Usage: amx_gag_times <time1> [time2] [time3] ..." );
454 return PLUGIN_HANDLED;
455 }
456
457 ArrayClear( g_aGagTimes );
458
459 // This is used for ungag in the menu
460 ArrayPushCell( g_aGagTimes, 0 );
461 g_iTotalGagTimes = 1;
462
463 // Get max time allowed
464 new iTimeLimit = get_pcvar_num( g_pCvarMaxTime );
465
466 new szBuffer[ 32 ], iTime;
467 for( new i = 1; i < iArgs; i++ )
468 {
469 read_argv( i, szBuffer, 31 );
470
471 if( !is_str_num( szBuffer ) )
472 {
473 server_print( "[AMXX GAG] Time must be an integer! (%s)", szBuffer );
474 continue;
475 }
476
477 iTime = str_to_num( szBuffer );
478
479 if( iTime < 0 )
480 {
481 server_print( "[AMXX GAG] Time must be a positive integer! (%d)", iTime );
482 continue;
483 }
484
485 if( 0 < iTimeLimit < iTime )
486 {
487 server_print( "[AMXX GAG] Time more then %d is not allowed! (%d)", iTimeLimit, iTime );
488 continue;
489 }
490
491 ArrayPushCell( g_aGagTimes, iTime );
492 g_iTotalGagTimes++;
493 }
494
495 return PLUGIN_HANDLED;
496}
497
498public client_putinserver( id )
499{
500 if( CheckGagFlag( id, GAG_VOICE ) )
501 {
502 set_speak( id, SPEAK_MUTED );
503 }
504
505 // Default flags are "abc"
506 g_iMenuFlags[ id ] = GAG_CHAT | GAG_TEAMSAY | GAG_VOICE;
507}
508
509public client_authorized( id )
510{
511 get_user_authid( id, g_szSteamID[ id ], 34 );
512}
513
514public client_disconnect( id )
515{
516 if( TrieKeyExists( g_tArrayPos, g_szSteamID[ id ] ) )
517 {
518 new szName[ 32 ];
519 get_user_name( id, szName, 31 );
520
521 new iPlayers[ 32 ], iNum, iPlayer;
522 get_players( iPlayers, iNum, "ch" );
523
524 for( new i; i < iNum; i++ )
525 {
526 iPlayer = iPlayers[ i ];
527
528 if( get_user_flags( iPlayer ) & ADMIN_KICK )
529 {
530 if( g_bColorSupported )
531 {
532 GreenPrint( iPlayer, id, "^4[AMXX GAG]^1 Gagged player ^"^3%s^1<^4%s^1>^" has disconnected!", szName, g_szSteamID[ id ] );
533 }
534 else
535 {
536 client_print( iPlayer, print_chat, "[AMXX GAG] Gagged player ^"%s<%s>^" has disconnected!", szName, g_szSteamID[ id ] );
537 }
538 }
539 }
540 }
541
542 g_szSteamID[ id ][ 0 ] = '^0';
543}
544
545public client_infochanged( id )
546{
547 if( !CheckGagFlag( id, ( GAG_CHAT | GAG_TEAMSAY ) ) )
548 {
549 return;
550 }
551
552 static const name[ ] = "name";
553
554 static szNewName[ 32 ], szOldName[ 32 ];
555 get_user_info( id, name, szNewName, 31 );
556 get_user_name( id, szOldName, 31 );
557
558 if( !equal( szNewName, szOldName ) )
559 {
560 if( g_bColorSupported )
561 {
562 GreenPrint( id, id, "^4[AMXX GAG]^1 Gagged players cannot change their names!" );
563 }
564 else
565 {
566 client_print( id, print_chat, "[AMXX GAG] Gagged players cannot change their names!" );
567 }
568
569 set_user_info( id, name, szOldName );
570 }
571}
572
573public MessageSayText( )
574{
575 static const Cstrike_Name_Change[ ] = "#Cstrike_Name_Change";
576
577 new szMessage[ sizeof( Cstrike_Name_Change ) + 1 ];
578 get_msg_arg_string( 2, szMessage, charsmax( szMessage ) );
579
580 if( equal( szMessage, Cstrike_Name_Change ) )
581 {
582 new szName[ 32 ], id;
583 for( new i = 3; i <= 4; i++ )
584 {
585 get_msg_arg_string( i, szName, 31 );
586
587 id = get_user_index( szName );
588
589 if( is_user_connected( id ) )
590 {
591 if( CheckGagFlag( id, ( GAG_CHAT | GAG_TEAMSAY ) ) )
592 {
593 return PLUGIN_HANDLED;
594 }
595
596 break;
597 }
598 }
599 }
600
601 return PLUGIN_CONTINUE;
602}
603
604public FwdThink( const iEntity )
605{
606 if( !g_iGagged )
607 {
608 return;
609 }
610
611 new iSystime = get_systime( );
612 new bool:bRemovedGags = false;
613
614 new bool:bUsingSQL = g_bUsingSQL;
615 new Array:aRemoveSteamIDs, iNumRemoveSteamIDs;
616
617 if( bUsingSQL )
618 {
619 aRemoveSteamIDs = ArrayCreate( 35 );
620 g_bUsingSQL = false;
621 }
622
623 new data[ GagData ], id, szName[ 32 ];
624 for( new i = 0; i < g_iGagged; i++ )
625 {
626 ArrayGetArray( g_aGagData, i, data );
627
628 if( data[ GAG_TIME ] > 0 && ( data[ GAG_START ] + data[ GAG_TIME ] ) <= iSystime )
629 {
630 id = find_player( "c", data[ GAG_STEAMID ] );
631
632 if( is_user_connected( id ) )
633 {
634 get_user_name( id, szName, 31 );
635
636 if( g_bColorSupported )
637 {
638 GreenPrint( 0, id, "^4[AMXX GAG]^1 Player ^"^3%s^1^" is no longer gagged", szName );
639 }
640 else
641 {
642 client_print( 0, print_chat, "[AMXX GAG] Player ^"%s^" is no longer gagged", szName );
643 }
644 }
645 else
646 {
647 if( g_bColorSupported )
648 {
649 GreenPrint( 0, 0, "^4[AMXX GAG]^1 SteamID ^"^3%s^1^" is no longer gagged", data[ GAG_STEAMID ] );
650 }
651 else
652 {
653 client_print( 0, print_chat, "[AMXX GAG] SteamID ^"%s^" is no longer gagged", data[ GAG_STEAMID ] );
654 }
655 }
656
657 DeleteGag( i-- );
658
659 bRemovedGags = true;
660
661 if( bUsingSQL )
662 {
663 ArrayPushString( aRemoveSteamIDs, data[ GAG_STEAMID ] );
664 iNumRemoveSteamIDs++;
665 }
666 }
667 }
668
669 if( !bUsingSQL )
670 {
671 if( bRemovedGags )
672 {
673 SaveToFile( );
674 }
675 }
676 else
677 {
678 if( iNumRemoveSteamIDs )
679 {
680 new szNext[ 64 ], iNextLen, iDefaultLen, iLen = iDefaultLen = copy( szQuery, charsmax( szQuery ), "DELETE FROM gagged_players WHERE " );
681
682 for( new i = 0; i < iNumRemoveSteamIDs; i++ )
683 {
684 ArrayGetString( aRemoveSteamIDs, i, data[ GAG_STEAMID ], charsmax( data[ GAG_STEAMID ] ) );
685
686 iNextLen = formatex( szNext, charsmax( szNext ), "%splayer_steamid = ^"%s^"", i ? " OR " : "", data[ GAG_STEAMID ] );
687
688 if( ( iLen + iNextLen + 1 ) > charsmax( szQuery ) )
689 {
690 szQuery[ iLen++ ] = ';'
691 szQuery[ iLen ] = 0;
692
693 SQL_ThreadQuery( g_hSqlTuple, "HandleDefaultQuery", szQuery );
694
695 szQuery[ ( iLen = iDefaultLen ) ] = 0;
696 }
697
698 iLen += copy( szQuery[ iLen ], charsmax( szQuery ) - iLen, szNext );
699 }
700
701 szQuery[ iLen++ ] = ';';
702 szQuery[ iLen ] = 0;
703
704 SQL_ThreadQuery( g_hSqlTuple, "HandleDefaultQuery", szQuery );
705 }
706
707 ArrayDestroy( aRemoveSteamIDs );
708
709 g_bUsingSQL = true;
710 }
711
712 if( !g_iGagged )
713 return;
714
715 new iNextTime = 999999;
716 for( new i = 0; i < g_iGagged; i++ )
717 {
718 ArrayGetArray( g_aGagData, i, data );
719
720 if( data[ GAG_TIME ] > 0 )
721 iNextTime = min( iNextTime, data[ GAG_START ] + data[ GAG_TIME ] - iSystime );
722 }
723
724 if( iNextTime < 999999 )
725 entity_set_float( iEntity, EV_FL_nextthink, get_gametime( ) + iNextTime );
726}
727
728public CmdSay( const id )
729{
730 return CheckSay( id, 0 );
731}
732
733public CmdTeamSay( const id )
734{
735 return CheckSay( id, 1 );
736}
737
738CheckSay( const id, const bIsTeam )
739{
740 new iArrayPos;
741
742 if( TrieGetCell( g_tArrayPos, g_szSteamID[ id ], iArrayPos ) )
743 {
744 new data[ GagData ];
745 ArrayGetArray( g_aGagData, iArrayPos, data );
746
747 new const iFlags[ ] = { GAG_CHAT, GAG_TEAMSAY };
748
749 if( data[ GAG_FLAGS ] & iFlags[ bIsTeam ] )
750 {
751 if( data[ GAG_TIME ] > 0 )
752 {
753 new szInfo[ 128 ], iTime = data[ GAG_START ] + data[ GAG_TIME ] - get_systime( );
754
755 GetTimeLength( iTime, szInfo, charsmax( szInfo ) );
756
757 if( g_bColorSupported )
758 {
759 GreenPrint( id, id, "^4[AMXX GAG]^3 %s^1 left before your ungag!", szInfo );
760 }
761 else
762 {
763 client_print( id, print_chat, "[AMXX GAG] %s left before your ungag!", szInfo );
764 }
765 }
766 else
767 {
768 if( g_bColorSupported )
769 {
770 GreenPrint( id, id, "^4[AMXX GAG]^3 You are gagged permanently!" );
771 }
772 else
773 {
774 client_print( id, print_chat, "[AMXX GAG] You are gagged permanently!" );
775 }
776 }
777
778 client_print( id, print_center, "** You are gagged from%s chat! **", bIsTeam ? " team" : "" );
779
780 return PLUGIN_HANDLED;
781 }
782 }
783
784 return PLUGIN_CONTINUE;
785}
786
787public CmdGagPlayer( const id, const iLevel, const iCid )
788{
789 if( !cmd_access( id, iLevel, iCid, 2 ) )
790 {
791 console_print( id, "Flags: a - Chat | b - Team Chat | c - Voice communications" );
792 return PLUGIN_HANDLED;
793 }
794
795 new szArg[ 32 ];
796 read_argv( 1, szArg, 31 );
797
798 new iPlayer = cmd_target( id, szArg, CMDTARGET_OBEY_IMMUNITY | CMDTARGET_NO_BOTS );
799
800 if( !iPlayer )
801 {
802 return PLUGIN_HANDLED;
803 }
804
805 new szName[ 20 ];
806 get_user_name( iPlayer, szName, 19 );
807
808 if( TrieKeyExists( g_tArrayPos, g_szSteamID[ iPlayer ] ) )
809 {
810 console_print( id, "User ^"%s^" is already gagged!", szName );
811 return PLUGIN_HANDLED;
812 }
813
814 new iFlags;
815 new iGagTime = -1;
816
817 read_argv( 2, szArg, 31 );
818
819 if( szArg[ 0 ] ) // No time entered
820 {
821 if( is_str_num( szArg ) ) // Seconds entered
822 {
823 iGagTime = abs( str_to_num( szArg ) );
824 }
825 else
826 {
827 console_print( id, "The value must be in seconds!" );
828 return PLUGIN_HANDLED;
829 }
830
831 read_argv( 3, szArg, 31 );
832
833 if( szArg[ 0 ] )
834 {
835 iFlags = read_flags( szArg );
836 }
837 }
838
839 GagPlayer( id, iPlayer, g_szSteamID[ iPlayer ], iGagTime, iFlags );
840
841 return PLUGIN_HANDLED;
842}
843
844GagPlayer( id, iPlayer, const szPlayerSteamID[ ], iGagTime, iFlags, bSave=1, bNotify=1 )
845{
846 new iMaxTime = get_pcvar_num( g_pCvarMaxTime );
847
848 if( iGagTime == -1 )
849 {
850 iGagTime = clamp( get_pcvar_num( g_pCvarDefaultTime ), 0, iMaxTime );
851 }
852
853 if( iGagTime )
854 {
855 new iTimeUnit = GetTimeUnit( );
856
857 iGagTime = clamp( iGagTime, 1, iMaxTime ) * g_iTimeUnitMult[ iTimeUnit ];
858 }
859
860 if( !iFlags )
861 {
862 new szFlags[ 27 ];
863 get_pcvar_string( g_pCvarDefaultFlags, szFlags, charsmax( szFlags ) );
864
865 iFlags = read_flags( szFlags );
866 }
867
868 new data[ GagData ];
869 data[ GAG_START ] = get_systime( );
870 data[ GAG_TIME ] = iGagTime;
871 data[ GAG_FLAGS ] = iFlags;
872 data[ GAG_SAVE ] = bSave;
873 data[ GAG_NOTIFY ] = bNotify;
874 copy( data[ GAG_STEAMID ], 34, szPlayerSteamID );
875
876 TrieSetCell( g_tArrayPos, szPlayerSteamID, g_iGagged );
877 ArrayPushArray( g_aGagData, data );
878
879 g_iGagged++;
880
881 if( iGagTime > 0 )
882 {
883 new Float:flGametime = get_gametime( ), Float:flNextThink;
884 flNextThink = entity_get_float( g_iThinker, EV_FL_nextthink );
885
886 if( !flNextThink || flNextThink > ( flGametime + iGagTime ) )
887 {
888 entity_set_float( g_iThinker, EV_FL_nextthink, flGametime + iGagTime );
889 }
890 }
891
892 if( bSave )
893 {
894 if( g_bUsingSQL )
895 {
896 new szPlayerName[ 32 ], szPlayerIP[ 32 ];
897
898 if( iPlayer )
899 {
900 get_user_name( iPlayer, szPlayerName, charsmax( szPlayerName ) );
901 get_user_ip( iPlayer, szPlayerIP, charsmax( szPlayerIP ), 1 );
902 }
903 else
904 {
905 szPlayerName[ 0 ] = szPlayerIP[ 0 ] = '?';
906 }
907
908 AddGag( id, g_szSteamID[ iPlayer ], szPlayerName, szPlayerIP, iGagTime, iFlags );
909 }
910 else
911 {
912 SaveToFile( );
913 }
914 }
915
916 if( bNotify )
917 {
918 new szFrom[ 64 ];
919
920 if( iFlags & GAG_CHAT )
921 {
922 copy( szFrom, 63, "say" );
923 }
924
925 if( iFlags & GAG_TEAMSAY )
926 {
927 if( !szFrom[ 0 ] )
928 copy( szFrom, 63, "say_team" );
929 else
930 add( szFrom, 63, " / say_team" );
931 }
932
933 if( iFlags & GAG_VOICE )
934 {
935 set_speak( iPlayer, SPEAK_MUTED );
936
937 if( !szFrom[ 0 ] )
938 copy( szFrom, 63, "voicecomm" );
939 else
940 add( szFrom, 63, " / voicecomm" );
941 }
942
943 new szName[ 64 ];
944
945 if( iPlayer )
946 {
947 get_user_name( iPlayer, szName, 19 );
948 }
949 else
950 {
951 formatex( szName, charsmax( szName ), "a non-connected player <%s>", szPlayerSteamID );
952 }
953
954 new szInfo[ 32 ], szAdmin[ 32 ];
955 get_user_name( id, szAdmin, 31 );
956
957 if( iGagTime > 0 )
958 {
959 new iLen = copy( szInfo, 31, "for " );
960 GetTimeLength( iGagTime, szInfo[ iLen ], charsmax( szInfo ) - iLen );
961 }
962 else
963 {
964 copy( szInfo, 31, "permanently" );
965 }
966
967 show_activity( id, szAdmin, "Has gagged %s from speaking %s! (%s)", szName, szInfo, szFrom );
968
969 console_print( id, "You have gagged ^"%s^" (%s) !", szName, szFrom );
970
971 log_amx( "Gag: ^"%s<%s>^" has gagged ^"%s<%s>^" %s. (%s)", szAdmin, g_szSteamID[ id ], szName, szPlayerSteamID, szInfo, szFrom );
972 }
973}
974
975public CmdAddGag( const id, const iLevel, const iCid )
976{
977 if( !cmd_access( id, iLevel, iCid, 2 ) )
978 {
979 console_print( id, "Flags: a - Chat | b - Team Chat | c - Voice communications" );
980 return PLUGIN_HANDLED;
981 }
982
983 new szArg[ 32 ];
984 read_argv( 1, szArg, 31 );
985
986 if( !IsValidSteamID( szArg ) )
987 {
988 console_print( id, "Invalid SteamID provided (%s). Must be in ^"STEAM_0:X:XXXXX^" format (remember to use quotes!)", szArg );
989 return PLUGIN_HANDLED;
990 }
991
992 new iPlayer = find_player( "c", szArg );
993
994 if( is_user_connected( iPlayer ) )
995 {
996 new szTime[ 12 ], szFlags[ 4 ];
997 read_argv( 2, szTime, charsmax( szTime ) );
998 read_argv( 3, szFlags, charsmax( szFlags ) );
999
1000 client_cmd( id, "amx_gag #%d ^"%s^" ^"%s^"", get_user_userid( iPlayer ), szTime, szFlags );
1001 return PLUGIN_HANDLED;
1002 }
1003
1004 if( TrieKeyExists( g_tArrayPos, szArg ) )
1005 {
1006 console_print( id, "This user is already gagged!" );
1007 return PLUGIN_HANDLED;
1008 }
1009
1010 if( GetAccessBySteamID( szArg ) & ADMIN_IMMUNITY )
1011 {
1012 console_print( id, "This user has immunity!" );
1013 return PLUGIN_HANDLED;
1014 }
1015
1016 new data[ GagData ];
1017 copy( data[ GAG_STEAMID ], 34, szArg );
1018
1019 get_pcvar_string( g_pCvarDefaultFlags, szArg, charsmax( szArg ) );
1020 new iFlags = read_flags( szArg );
1021
1022 new iMaxTime = get_pcvar_num( g_pCvarMaxTime );
1023 new iGagTime = clamp( get_pcvar_num( g_pCvarDefaultTime ), 0, iMaxTime );
1024
1025 read_argv( 2, szArg, 31 );
1026
1027 if( szArg[ 0 ] ) // No time entered
1028 {
1029 if( is_str_num( szArg ) ) // Seconds entered
1030 {
1031 iGagTime = min( abs( str_to_num( szArg ) ), iMaxTime );
1032 }
1033 else
1034 {
1035 console_print( id, "The value must be in seconds!" );
1036 return PLUGIN_HANDLED;
1037 }
1038
1039 read_argv( 3, szArg, 31 );
1040
1041 if( szArg[ 0 ] )
1042 {
1043 iFlags = read_flags( szArg );
1044 }
1045 }
1046
1047 new iTimeUnit = GetTimeUnit( );
1048
1049 // convert to seconds
1050 iGagTime *= g_iTimeUnitMult[ iTimeUnit ];
1051
1052 data[ GAG_START ] = get_systime( );
1053 data[ GAG_TIME ] = iGagTime;
1054 data[ GAG_FLAGS ] = iFlags;
1055 data[ GAG_SAVE ] = 1;
1056
1057 TrieSetCell( g_tArrayPos, data[ GAG_STEAMID ], g_iGagged );
1058 ArrayPushArray( g_aGagData, data );
1059
1060 new szFrom[ 64 ];
1061
1062 if( iFlags & GAG_CHAT )
1063 {
1064 copy( szFrom, 63, "say" );
1065 }
1066
1067 if( iFlags & GAG_TEAMSAY )
1068 {
1069 if( !szFrom[ 0 ] )
1070 copy( szFrom, 63, "say_team" );
1071 else
1072 add( szFrom, 63, " / say_team" );
1073 }
1074
1075 if( iFlags & GAG_VOICE )
1076 {
1077 if( !szFrom[ 0 ] )
1078 copy( szFrom, 63, "voicecomm" );
1079 else
1080 add( szFrom, 63, " / voicecomm" );
1081 }
1082
1083 g_iGagged++;
1084
1085 if( iGagTime > 0 )
1086 {
1087 new Float:flGametime = get_gametime( ), Float:flNextThink;
1088 flNextThink = entity_get_float( g_iThinker, EV_FL_nextthink );
1089
1090 if( !flNextThink || flNextThink > ( flGametime + iGagTime ) )
1091 entity_set_float( g_iThinker, EV_FL_nextthink, flGametime + iGagTime );
1092 }
1093
1094 if( g_bUsingSQL )
1095 {
1096 AddGag( id, data[ GAG_STEAMID ], "?", "?", iGagTime, iFlags );
1097 }
1098 else
1099 {
1100 SaveToFile( );
1101 }
1102
1103 new szInfo[ 32 ], szAdmin[ 32 ];
1104 get_user_name( id, szAdmin, 31 );
1105
1106 if( iGagTime > 0 )
1107 {
1108 new iLen = copy( szInfo, 31, "for " );
1109 GetTimeLength( iGagTime, szInfo[ iLen ], charsmax( szInfo ) - iLen );
1110 }
1111 else
1112 {
1113 copy( szInfo, 31, "permanently" );
1114 }
1115
1116 show_activity( id, szAdmin, "Has gagged a non-connected player <%s> from speaking %s! (%s)", data[ GAG_STEAMID ], szInfo, szFrom );
1117
1118 console_print( id, "You have gagged ^"%s^" (%s) !", data[ GAG_STEAMID ], szFrom );
1119
1120 log_amx( "Gag: ^"%s<%s>^" has gagged a non-connected player ^"<%s>^" %s. (%s)", szAdmin, g_szSteamID[ id ], data[ GAG_STEAMID ], szInfo, szFrom );
1121
1122 return PLUGIN_HANDLED;
1123}
1124
1125public CmdUnGagPlayer( const id, const iLevel, const iCid )
1126{
1127 if( !cmd_access( id, iLevel, iCid, 2 ) )
1128 return PLUGIN_HANDLED;
1129
1130 new szArg[ 32 ];
1131 read_argv( 1, szArg, 31 );
1132
1133 if( szArg[ 0 ] == '@' && equali( szArg[ 1 ], "all" ) )
1134 {
1135 if( !g_iGagged )
1136 {
1137 console_print( id, "No gagged players!" );
1138 return PLUGIN_HANDLED;
1139 }
1140
1141 DeleteAllGags( );
1142
1143 if( entity_get_float( g_iThinker, EV_FL_nextthink ) > 0.0 )
1144 entity_set_float( g_iThinker, EV_FL_nextthink, 0.0 );
1145
1146 console_print( id, "You have ungagged all players!" );
1147
1148 new szAdmin[ 32 ];
1149 get_user_name( id, szAdmin, 31 );
1150
1151 show_activity( id, szAdmin, "Has ungagged all players." );
1152
1153 log_amx( "UnGag: ^"%s<%s>^" has ungagged all players.", szAdmin, g_szSteamID[ id ] );
1154
1155 return PLUGIN_HANDLED;
1156 }
1157
1158 new iPlayer = cmd_target( id, szArg, CMDTARGET_NO_BOTS );
1159 new iArrayPos, szName[ 32 ];
1160
1161 if( !iPlayer )
1162 {
1163 // Maybe it's a steamid
1164
1165 if( !IsValidSteamID( szArg ) )
1166 {
1167 return PLUGIN_HANDLED;
1168 }
1169
1170 if( !TrieGetCell( g_tArrayPos, szArg, iArrayPos ) )
1171 {
1172 console_print( id, "This steamid is not gagged!" );
1173 return PLUGIN_HANDLED;
1174 }
1175
1176 copy( szName, charsmax( szName ), szArg );
1177 }
1178 else
1179 {
1180 get_user_name( iPlayer, szName, charsmax( szName ) );
1181
1182 if( !TrieGetCell( g_tArrayPos, g_szSteamID[ iPlayer ], iArrayPos ) )
1183 {
1184 console_print( id, "User ^"%s^" is not gagged!", szName );
1185 return PLUGIN_HANDLED;
1186 }
1187 }
1188
1189 DeleteGag( iArrayPos );
1190
1191 if( !g_bUsingSQL )
1192 {
1193 SaveToFile( );
1194 }
1195
1196 new szAdmin[ 32 ];
1197 get_user_name( id, szAdmin, 31 );
1198
1199 show_activity( id, szAdmin, "Has ungagged %s.", szName );
1200
1201 console_print( id, "You have ungagged ^"%s^" !", szName );
1202
1203 log_amx( "UnGag: ^"%s<%s>^" has ungagged ^"%s<%s>^"", szAdmin, g_szSteamID[ id ], szName, g_szSteamID[ iPlayer ] );
1204
1205 return PLUGIN_HANDLED;
1206}
1207
1208public CmdGagMenu( const id, const iLevel, const iCid )
1209{
1210 if( !cmd_access( id, iLevel, iCid, 1 ) )
1211 {
1212 return PLUGIN_HANDLED;
1213 }
1214
1215 g_iMenuOption[ id ] = 0;
1216 arrayset( g_iMenuPlayers[ id ], 0, 32 );
1217
1218 DisplayGagMenu( id, g_iMenuPosition[ id ] = 0 );
1219
1220 return PLUGIN_HANDLED;
1221}
1222
1223#define PERPAGE 6
1224
1225public ActionGagMenu( const id, const iKey )
1226{
1227 switch( iKey )
1228 {
1229 case 6: DisplayGagFlags( id );
1230 case 7:
1231 {
1232 ++g_iMenuOption[ id ];
1233 g_iMenuOption[ id ] %= g_iTotalGagTimes;
1234
1235 DisplayGagMenu( id, g_iMenuPosition[ id ] );
1236 }
1237 case 8: DisplayGagMenu( id, ++g_iMenuPosition[ id ] );
1238 case 9: DisplayGagMenu( id, --g_iMenuPosition[ id ] );
1239 default:
1240 {
1241 new iPlayer = g_iMenuPlayers[ id ][ g_iMenuPosition[ id ] * PERPAGE + iKey ];
1242
1243 if( is_user_connected( iPlayer ) )
1244 {
1245 if( !g_iMenuOption[ id ] )
1246 {
1247 new iArrayPos;
1248
1249 if( TrieGetCell( g_tArrayPos, g_szSteamID[ iPlayer ], iArrayPos ) )
1250 {
1251 DeleteGag( iArrayPos );
1252
1253 if( !g_bUsingSQL )
1254 {
1255 SaveToFile( );
1256 }
1257
1258 new szName[ 32 ];
1259 get_user_name( iPlayer, szName, 31 );
1260
1261 new szAdmin[ 32 ];
1262 get_user_name( id, szAdmin, 31 );
1263
1264 show_activity( id, szAdmin, "Has ungagged %s.", szName );
1265
1266 console_print( id, "You have ungagged ^"%s^" !", szName );
1267
1268 log_amx( "UnGag: ^"%s<%s>^" has ungagged ^"%s<%s>^"", szAdmin, g_szSteamID[ id ], szName, g_szSteamID[ iPlayer ] );
1269 }
1270 }
1271 else if( !TrieKeyExists( g_tArrayPos, g_szSteamID[ iPlayer ] ) )
1272 {
1273 GagPlayer( id, iPlayer, g_szSteamID[ iPlayer ], ArrayGetCell( g_aGagTimes, g_iMenuOption[ id ] ), g_iMenuFlags[ id ] );
1274 }
1275 }
1276
1277 DisplayGagMenu( id, g_iMenuPosition[ id ] );
1278 }
1279 }
1280}
1281
1282// I just copied this from AMXX Ban menu, so don't blame me :D
1283DisplayGagMenu( const id, iPosition )
1284{
1285 if( iPosition < 0 )
1286 {
1287 arrayset( g_iMenuPlayers[ id ], 0, 32 );
1288 return;
1289 }
1290
1291 new iPlayers[ 32 ], iNum, iCount, szMenu[ 512 ], iPlayer, iFlags, szName[ 32 ];
1292 get_players( iPlayers, iNum, "ch" ); // Ignore bots and hltv
1293
1294 new iStart = iPosition * PERPAGE;
1295
1296 if( iStart >= iNum )
1297 iStart = iPosition = g_iMenuPosition[ id ] = 0;
1298
1299 new iEnd = iStart + PERPAGE, iKeys = MENU_KEY_0 | MENU_KEY_8;
1300 new iLen = formatex( szMenu, 511, g_bColorSupported ? "\rGag Menu\R%d/%d^n^n" : "Gag Menu %d/%d^n^n", iPosition + 1, ( ( iNum + PERPAGE - 1 ) / PERPAGE ) );
1301
1302 new bool:bUngag = bool:!g_iMenuOption[ id ];
1303
1304 if( iEnd > iNum ) iEnd = iNum;
1305
1306 for( new i = iStart; i < iEnd; ++i )
1307 {
1308 iPlayer = iPlayers[ i ];
1309 iFlags = get_user_flags( iPlayer );
1310 get_user_name( iPlayer, szName, 31 );
1311
1312 if( iPlayer == id || ( iFlags & ADMIN_IMMUNITY ) || bUngag != TrieKeyExists( g_tArrayPos, g_szSteamID[ iPlayer ] ) )
1313 {
1314 ++iCount;
1315
1316 if( g_bColorSupported )
1317 iLen += formatex( szMenu[ iLen ], 511 - iLen, "\d%d. %s^n", iCount, szName );
1318 else
1319 iLen += formatex( szMenu[ iLen ], 511 - iLen, "#. %s^n", szName );
1320 }
1321 else
1322 {
1323 iKeys |= ( 1 << iCount );
1324 ++iCount;
1325
1326 iLen += formatex( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "\r%d.\w %s\y%s\r%s^n" : "%d. %s%s%s^n", iCount, szName, TrieKeyExists( g_tArrayPos, g_szSteamID[ iPlayer ] ) ? " GAGGED" : "", ( ~iFlags & ADMIN_USER ? " *" : "" ) );
1327 }
1328 }
1329
1330 g_iMenuPlayers[ id ] = iPlayers;
1331
1332 new szFlags[ 4 ];
1333 get_flags( g_iMenuFlags[ id ], szFlags, 3 );
1334
1335 iLen += formatex( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? ( bUngag ? "^n\d7. Flags: %s" : "^n\r7.\y Flags:\w %s" ) : ( bUngag ? "^n#. Flags: %s" : "^n7. Flags: %s" ), szFlags );
1336
1337 if( !bUngag )
1338 {
1339 iKeys |= MENU_KEY_7;
1340
1341 new iGagTime = ArrayGetCell( g_aGagTimes, g_iMenuOption[ id ] );
1342
1343 if( iGagTime )
1344 {
1345 new szTime[ 128 ];
1346 GetTimeLength( iGagTime * g_iTimeUnitMult[ GetTimeUnit( ) ], szTime, charsmax( szTime ) );
1347
1348 iLen += formatex( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "^n\r8.\y Time:\w %s^n" : "^n8. Time: %s^n", szTime );
1349 }
1350 else
1351 iLen += copy( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "^n\r8.\y Time: Permanent^n" : "^n8. Time: Permanent^n" );
1352 }
1353 else
1354 iLen += copy( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "^n\r8.\w Ungag^n" : "^n8. Ungag^n" );
1355
1356 if( iEnd != iNum )
1357 {
1358 formatex( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "^n\r9.\w More...^n\r0.\w %s" : "^n9. More...^n0. %s", iPosition ? "Back" : "Exit" );
1359 iKeys |= MENU_KEY_9;
1360 }
1361 else
1362 formatex( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "^n\r0.\w %s" : "^n0. %s", iPosition ? "Back" : "Exit" );
1363
1364 show_menu( id, iKeys, szMenu, -1, "Gag Menu" );
1365}
1366
1367public ActionGagFlags( const id, const iKey )
1368{
1369 switch( iKey )
1370 {
1371 case 9: DisplayGagMenu( id, g_iMenuPosition[ id ] );
1372 default:
1373 {
1374 g_iMenuFlags[ id ] ^= ( 1 << iKey );
1375
1376 DisplayGagFlags( id );
1377 }
1378 }
1379}
1380
1381DisplayGagFlags( const id )
1382{
1383 new szMenu[ 512 ];
1384 new iLen = copy( szMenu, 511, g_bColorSupported ? "\rGag Flags^n^n" : "Gag Flags^n^n" );
1385
1386 if( g_bColorSupported )
1387 {
1388 iLen += formatex( szMenu[ iLen ], 511 - iLen, "\r1.\w Chat: %s^n", ( g_iMenuFlags[ id ] & GAG_CHAT ) ? "\yYES" : "\rNO" );
1389 iLen += formatex( szMenu[ iLen ], 511 - iLen, "\r2.\w TeamSay: %s^n", ( g_iMenuFlags[ id ] & GAG_TEAMSAY ) ? "\yYES" : "\rNO" );
1390 iLen += formatex( szMenu[ iLen ], 511 - iLen, "\r3.\w Voice: %s^n", ( g_iMenuFlags[ id ] & GAG_VOICE ) ? "\yYES" : "\rNO" );
1391 }
1392 else
1393 {
1394 iLen += formatex( szMenu[ iLen ], 511 - iLen, "1. Chat: %s^n", ( g_iMenuFlags[ id ] & GAG_CHAT ) ? "YES" : "NO" );
1395 iLen += formatex( szMenu[ iLen ], 511 - iLen, "2. TeamSay: %s^n", ( g_iMenuFlags[ id ] & GAG_TEAMSAY ) ? "YES" : "NO" );
1396 iLen += formatex( szMenu[ iLen ], 511 - iLen, "3. Voice: %s^n", ( g_iMenuFlags[ id ] & GAG_VOICE ) ? "YES" : "NO" );
1397 }
1398
1399 copy( szMenu[ iLen ], 511 - iLen, g_bColorSupported ? "^n\r0. \wBack to Gag Menu" : "^n0. Back to Gag Menu" );
1400
1401 show_menu( id, ( MENU_KEY_1 | MENU_KEY_2 | MENU_KEY_3 | MENU_KEY_0 ), szMenu, -1, "Gag Flags" );
1402}
1403
1404CheckGagFlag( const id, const iFlag )
1405{
1406 new iArrayPos;
1407
1408 if( TrieGetCell( g_tArrayPos, g_szSteamID[ id ], iArrayPos ) )
1409 {
1410 new data[ GagData ];
1411 ArrayGetArray( g_aGagData, iArrayPos, data );
1412
1413 return ( data[ GAG_FLAGS ] & iFlag );
1414 }
1415
1416 return 0;
1417}
1418
1419DeleteAllGags( )
1420{
1421 new data[ GagData ];
1422 new iPlayer;
1423
1424 for( new i = 0; i < g_iGagged; i++ )
1425 {
1426 ArrayGetArray( g_aGagData, i, data );
1427
1428 iPlayer = find_player( "c", data[ GAG_STEAMID ] );
1429
1430 if( is_user_connected( iPlayer ) )
1431 {
1432 set_speak( iPlayer, SPEAK_NORMAL );
1433 }
1434 }
1435
1436 ArrayClear( g_aGagData );
1437 TrieClear( g_tArrayPos );
1438
1439 g_iGagged = 0;
1440
1441 if( g_bUsingSQL )
1442 {
1443 SQL_ThreadQuery( g_hSqlTuple, "HandleDefaultQuery", "TRUNCATE TABLE gagged_players" );
1444 }
1445}
1446
1447DeleteGag( const iArrayPos )
1448{
1449 new data[ GagData ];
1450 ArrayGetArray( g_aGagData, iArrayPos, data );
1451
1452 if( data[ GAG_FLAGS ] & GAG_VOICE )
1453 {
1454 new iPlayer = find_player( "c", data[ GAG_STEAMID ] );
1455
1456 if( is_user_connected( iPlayer ) )
1457 {
1458 set_speak( iPlayer, SPEAK_NORMAL );
1459 }
1460 }
1461
1462 TrieDeleteKey( g_tArrayPos, data[ GAG_STEAMID ] );
1463 ArrayDeleteItem( g_aGagData, iArrayPos );
1464
1465 g_iGagged--;
1466
1467 for( new i = iArrayPos; i < g_iGagged; i++ )
1468 {
1469 ArrayGetArray( g_aGagData, i, data );
1470 TrieSetCell( g_tArrayPos, data[ GAG_STEAMID ], i );
1471 }
1472
1473 if( g_bUsingSQL && data[ GAG_SAVE ] )
1474 {
1475 formatex( szQuery, charsmax( szQuery ), "DELETE FROM gagged_players WHERE player_steamid = '%s'", data[ GAG_STEAMID ] );
1476
1477 SQL_ThreadQuery( g_hSqlTuple, "HandleDefaultQuery", szQuery );
1478 }
1479}
1480
1481LoadFromFile( )
1482{
1483 new hFile = fopen( g_szGagFile, "rt" );
1484
1485 if( hFile )
1486 {
1487 new szData[ 128 ], szTime[ 16 ], szStart[ 16 ], szFlags[ 4 ];
1488 new data[ GagData ], iSystime = get_systime( ), iTimeLeft, iShortestTime = 999999;
1489 new bool:bRemovedGags = false;
1490
1491 data[ GAG_SAVE ] = 1;
1492 data[ GAG_NOTIFY ] = 1;
1493
1494 while( !feof( hFile ) )
1495 {
1496 fgets( hFile, szData, charsmax( szData ) );
1497 trim( szData );
1498
1499 if( !szData[ 0 ] )
1500 {
1501 continue;
1502 }
1503
1504 parse( szData,
1505 data[ GAG_STEAMID ], charsmax( data[ GAG_STEAMID ] ),
1506 szTime, charsmax( szTime ),
1507 szStart, charsmax( szStart ),
1508 szFlags, charsmax( szFlags )
1509 );
1510
1511 // Remove old gags
1512 if( contain( szStart, "." ) > 0 )
1513 {
1514 continue;
1515 }
1516
1517 data[ GAG_TIME ] = str_to_num( szTime );
1518 data[ GAG_START ] = str_to_num( szStart );
1519 data[ GAG_FLAGS ] = read_flags( szFlags );
1520
1521 if( data[ GAG_TIME ] > 0 )
1522 {
1523 iTimeLeft = data[ GAG_START ] + data[ GAG_TIME ] - iSystime;
1524
1525 if( iTimeLeft <= 0 )
1526 {
1527 bRemovedGags = true;
1528 continue;
1529 }
1530
1531 if( iShortestTime > iTimeLeft )
1532 {
1533 iShortestTime = iTimeLeft;
1534 }
1535 }
1536
1537 TrieSetCell( g_tArrayPos, data[ GAG_STEAMID ], g_iGagged );
1538 ArrayPushArray( g_aGagData, data );
1539 g_iGagged++;
1540 }
1541
1542 fclose( hFile );
1543
1544 if( bRemovedGags )
1545 {
1546 SaveToFile( );
1547 }
1548
1549 if( iShortestTime < 999999 )
1550 {
1551 entity_set_float( g_iThinker, EV_FL_nextthink, get_gametime( ) + iShortestTime );
1552 }
1553 }
1554}
1555
1556SaveToFile( )
1557{
1558 new hFile = fopen( g_szGagFile, "wt" );
1559
1560 if( hFile )
1561 {
1562 new data[ GagData ], szFlags[ 4 ];
1563
1564 for( new i = 0; i < g_iGagged; i++ )
1565 {
1566 ArrayGetArray( g_aGagData, i, data );
1567
1568 if( data[ GAG_SAVE ] )
1569 {
1570 get_flags( data[ GAG_FLAGS ], szFlags, charsmax( szFlags ) );
1571
1572 fprintf( hFile, "^"%s^" ^"%d^" ^"%d^" ^"%s^"^n", data[ GAG_STEAMID ], data[ GAG_TIME ], data[ GAG_START ], szFlags );
1573 }
1574 }
1575
1576 fclose( hFile );
1577 }
1578}
1579
1580GetTimeUnit( )
1581{
1582 new szTimeUnit[ 64 ], iTimeUnit;
1583 get_pcvar_string( g_pCvarTimeUnit, szTimeUnit, charsmax( szTimeUnit ) );
1584
1585 if( is_str_num( szTimeUnit ) )
1586 {
1587 iTimeUnit = get_pcvar_num( g_pCvarTimeUnit );
1588
1589 if( !( 0 <= iTimeUnit < TimeUnit ) )
1590 {
1591 iTimeUnit = -1;
1592 }
1593 }
1594 else
1595 {
1596 strtolower( szTimeUnit );
1597
1598 if( !TrieGetCell( g_tTimeUnitWords, szTimeUnit, iTimeUnit ) )
1599 {
1600 iTimeUnit = -1;
1601 }
1602 }
1603
1604 if( iTimeUnit == -1 )
1605 {
1606 iTimeUnit = TIMEUNIT_SECONDS;
1607
1608 set_pcvar_num( g_pCvarTimeUnit, TIMEUNIT_SECONDS );
1609 }
1610
1611 return iTimeUnit;
1612}
1613
1614GetTimeLength( iTime, szOutput[ ], iOutputLen )
1615{
1616 new szTimes[ TimeUnit ][ 32 ];
1617 new iUnit, iValue, iTotalDisplay;
1618
1619 for( new i = TimeUnit - 1; i >= 0; i-- )
1620 {
1621 iUnit = g_iTimeUnitMult[ i ];
1622 iValue = iTime / iUnit;
1623
1624 if( iValue )
1625 {
1626 formatex( szTimes[ i ], charsmax( szTimes[ ] ), "%d %s", iValue, g_szTimeUnitName[ i ][ iValue != 1 ] );
1627
1628 iTime %= iUnit;
1629
1630 iTotalDisplay++;
1631 }
1632 }
1633
1634 new iLen, iTotalLeft = iTotalDisplay;
1635 szOutput[ 0 ] = 0;
1636
1637 for( new i = TimeUnit - 1; i >= 0; i-- )
1638 {
1639 if( szTimes[ i ][ 0 ] )
1640 {
1641 iLen += formatex( szOutput[ iLen ], iOutputLen - iLen, "%s%s%s",
1642 ( iTotalDisplay > 2 && iLen ) ? ", " : "",
1643 ( iTotalDisplay > 1 && iTotalLeft == 1 ) ? ( ( iTotalDisplay > 2 ) ? "and " : " and " ) : "",
1644 szTimes[ i ]
1645 );
1646
1647 iTotalLeft--;
1648 }
1649 }
1650
1651 return iLen
1652}
1653
1654GreenPrint( id, iSender, const szRawMessage[ ], any:... )
1655{
1656 if( !iSender )
1657 {
1658 new iPlayers[ 32 ], iNum;
1659 get_players( iPlayers, iNum, "ch" );
1660
1661 if( !iNum ) return;
1662
1663 iSender = iPlayers[ 0 ];
1664 }
1665
1666 new szMessage[ 192 ];
1667 vformat( szMessage, charsmax( szMessage ), szRawMessage, 4 );
1668
1669 message_begin( id ? MSG_ONE_UNRELIABLE : MSG_BROADCAST, g_iMsgSayText, _, id );
1670 write_byte( iSender );
1671 write_string( szMessage );
1672 message_end( );
1673}
1674
1675bool:IsValidSteamID( const szSteamID[ ] )
1676{
1677 // STEAM_0:(0|1):\d+
1678 // 012345678 90
1679
1680 // 0-7 = STEAM_0:
1681 // 8 = 0 or 1
1682 // 9 = :
1683 // 10+ = integer
1684
1685 return ( ( '0' <= szSteamID[ 8 ] <= '1' ) && szSteamID[ 9 ] == ':' && equal( szSteamID, "STEAM_0:", 8 ) && is_str_num( szSteamID[ 10 ] ) );
1686}
1687
1688GetAccessBySteamID( const szSteamID[ ] )
1689{
1690 new szAuthData[ 44 ], iCount = admins_num( );
1691
1692 for( new i; i < iCount; i++ )
1693 {
1694 if( admins_lookup( i, AdminProp_Flags ) & FLAG_AUTHID )
1695 {
1696 admins_lookup( i, AdminProp_Auth, szAuthData, charsmax( szAuthData ) );
1697
1698 if( equal( szAuthData, szSteamID ) )
1699 {
1700 return admins_lookup( i, AdminProp_Access );
1701 }
1702 }
1703 }
1704
1705 return 0;
1706}
1707
1708strtotime( const string[ ] )
1709{
1710 new szTemp[ 32 ];
1711 new szYear[ 5 ], szMonth[ 3 ], szDay[ 3 ], szHour[ 3 ], szMinute[ 3 ], szSecond[ 3 ];
1712 strtok( string, szYear, charsmax( szYear ), szTemp, charsmax( szTemp ), '-' );
1713 strtok( szTemp, szMonth, charsmax( szMonth ), szTemp, charsmax( szTemp ), '-' );
1714 strtok( szTemp, szDay, charsmax( szDay ), szTemp, charsmax( szTemp ), ' ' );
1715 strtok( szTemp, szHour, charsmax( szHour ), szTemp, charsmax( szTemp ), ':' );
1716 strtok( szTemp, szMinute, charsmax( szMinute ), szSecond, charsmax( szSecond ), ':' );
1717
1718 return TimeToUnix( str_to_num( szYear ), str_to_num( szMonth ), str_to_num( szDay ), str_to_num( szHour ), str_to_num( szMinute ), str_to_num( szSecond ) );
1719}
1720
1721AddGag( admin, const szPlayerSteamID[ ], const szPlayerName[ ], const szPlayerIP[ ], iGagTime, iFlags )
1722{
1723 new szAdminName[ 32 ], szAdminIP[ 16 ];
1724
1725 if( admin )
1726 {
1727 get_user_name( admin, szAdminName, charsmax( szAdminName ) );
1728 }
1729 else
1730 {
1731 copy( szAdminName, charsmax( szAdminName ), "SERVER" );
1732 }
1733
1734 get_user_ip( admin, szAdminIP, charsmax( szAdminIP ), 1 );
1735
1736 new szDateNow[ DATE_SIZE ], szDateUngag[ DATE_SIZE ];
1737 get_time( DATETIME_FORMAT, szDateNow, charsmax( szDateNow ) );
1738 format_time( szDateUngag, charsmax( szDateUngag ), DATETIME_FORMAT, get_systime( ) + iGagTime );
1739
1740 new szFlags[ 4 ];
1741 get_flags( iFlags, szFlags, charsmax( szFlags ) );
1742
1743 formatex( szQuery, charsmax( szQuery ), "REPLACE INTO gagged_players \
1744 (admin_name, admin_steamid, admin_ip, player_name, player_steamid, player_ip, date_gagged, date_ungag, gag_seconds, gag_flags) \
1745 VALUES \
1746 (^"%s^", ^"%s^", ^"%s^", ^"%s^", ^"%s^", ^"%s^", ^"%s^", ^"%s^", %d, ^"%s^")",\
1747 szAdminName, g_szSteamID[ admin ], szAdminIP,\
1748 szPlayerName, szPlayerSteamID , szPlayerIP,\
1749 szDateNow, szDateUngag, iGagTime, szFlags );
1750
1751 SQL_ThreadQuery( g_hSqlTuple, "HandleDefaultQuery", szQuery );
1752}
1753
1754public HandleDefaultQuery( iFailState, Handle:hQuery, szError[ ], iError, iData[ ], iDataSize, Float:flQueueTime )
1755{
1756 if( iFailState != TQUERY_SUCCESS )
1757 {
1758 switch( iFailState )
1759 {
1760 case TQUERY_CONNECT_FAILED: log_amx( "Failed to connect to database: (%d) %s", iError, szError );
1761 case TQUERY_QUERY_FAILED: log_amx( "Failed to execute query: (%d) %s", iError, szError );
1762 }
1763 }
1764}
1765
1766// CODE BELOW FROM BUGSY'S UNIX TIME INCLUDE
1767//
1768
1769new const YearSeconds[ 2 ] =
1770{
1771 31536000, //Normal year
1772 31622400 //Leap year
1773};
1774
1775new const MonthSeconds[ 12 ] =
1776{
1777 2678400, //January 31
1778 2419200, //February 28
1779 2678400, //March 31
1780 2592000, //April 30
1781 2678400, //May 31
1782 2592000, //June 30
1783 2678400, //July 31
1784 2678400, //August 31
1785 2592000, //September 30
1786 2678400, //October 31
1787 2592000, //November 30
1788 2678400 //December 31
1789};
1790
1791const DaySeconds = 86400;
1792const HourSeconds = 3600;
1793const MinuteSeconds = 60;
1794
1795TimeToUnix( const iYear, const iMonth, const iDay, const iHour, const iMinute, const iSecond )
1796{
1797 new i, iTimeStamp;
1798
1799 for( i = 1970; i < iYear; i++ )
1800 iTimeStamp += YearSeconds[ IsLeapYear( i ) ];
1801
1802 for( i = 1; i < iMonth; i++ )
1803 iTimeStamp += SecondsInMonth( iYear, i );
1804
1805 iTimeStamp += ( ( iDay - 1 ) * DaySeconds );
1806 iTimeStamp += ( iHour * HourSeconds );
1807 iTimeStamp += ( iMinute * MinuteSeconds );
1808 iTimeStamp += iSecond;
1809
1810 return iTimeStamp;
1811}
1812
1813SecondsInMonth( const iYear , const iMonth )
1814{
1815 return ( ( IsLeapYear( iYear ) && ( iMonth == 2 ) ) ? ( MonthSeconds[ iMonth - 1 ] + DaySeconds ) : MonthSeconds[ iMonth - 1 ] );
1816}
1817
1818IsLeapYear( const iYear )
1819{
1820 return ( ( ( iYear % 4 ) == 0) && ( ( ( iYear % 100 ) != 0) || ( ( iYear % 400 ) == 0 ) ) );
1821}