· 6 years ago · Mar 17, 2019, 05:12 PM
1#include <amxmodx>
2#include <engine>
3#include <hamsandwich>
4#include <nvault>
5#include <sqlx>
6#include <geoip>
7
8
9// Here you can configure main settings
10
11// #define COLORCHAT
12
13new const g_szPrefix[] = "[GamesBR]";
14
15
16
17#define ADMIN_ACCESS ADMIN_CVAR
18
19// Here you stop
20
21#if defined COLORCHAT
22 #include <colorchat>
23#endif
24
25/* Macro */
26
27#define set_bit(%1,%2) (%1 |= (1<<%2))
28#define get_bit(%1,%2) (%1 & (1<<%2))
29#define clr_bit(%1,%2) (%1 &= ~(1<<%2))
30
31/* Macro */
32
33new const g_szVersion[] = "0.1";
34
35new const g_szTableName[] = "DEATHRUN_STATS";
36
37new g_pWebLink;
38
39new Handle:g_hSqlTuple;
40
41new bool:g_bSqlite;
42
43new g_szMapName[64];
44
45new Trie:g_tStarts, Trie:g_tStops;
46
47new bool:g_bTimerFound;
48
49enum _:eTimer
50{
51 START,
52 STOP
53};
54
55new g_szTimerModels[eTimer][] =
56{
57 "models/deathrun/timer/timer_start.mdl",
58 "models/deathrun/timer/timer_stop.mdl"
59};
60new g_szTimerName[eTimer][] =
61{
62 "Start",
63 "Stop"
64};
65
66new g_iTimer[eTimer];
67new Float:g_vTimerOrigin[eTimer][3];
68
69new g_iTimerAngles[eTimer];
70new Float:g_flTimerAngles[4] =
71{
72 0.0,
73 90.0,
74 180.0,
75 270.0
76};
77
78new g_iPlayerTimer[MAX_PLAYERS + 1];
79
80new g_bConnected, g_bAlive, g_bStarted;
81
82new Float:g_flStartTime[MAX_PLAYERS + 1], Float:g_flFinishTime[MAX_PLAYERS + 1];
83
84new g_iVault;
85
86new g_iMsgRoundTime;
87
88new g_iHudSyncObj;
89
90public plugin_precache()
91{
92 for (new i = 0; i < eTimer; i++)
93 precache_model(g_szTimerModels[i]);
94}
95public plugin_init()
96{
97 register_plugin("DeathRun Timer", g_szVersion, "deniS");
98
99 g_pWebLink = register_cvar("dr_timer_web_link", "http://177.54.156.124/web");
100
101 register_cvar("dr_timer_sql_host", "177.54.156.124");
102 register_cvar("dr_timer_sql_user", "tempo");
103 register_cvar("dr_timer_sql_pass", "Lu@30350783");
104 register_cvar("dr_timer_sql_db", "tempo");
105
106 get_mapname(g_szMapName, charsmax(g_szMapName));
107
108 g_tStarts = TrieCreate();
109 g_tStops = TrieCreate();
110
111 new i, iSize;
112
113 new const szStarts[][] =
114 {
115 "counter_start", "clockstartbutton", "firsttimerelay", "but_start", "counter_start_button",
116 "multi_start", "timer_startbutton", "start_timer_emi", "gogogo"
117 };
118 iSize = sizeof(szStarts);
119
120 for (i = 0; i < iSize; i++)
121 TrieSetCell(g_tStarts, szStarts[i], 1);
122
123 new const szStops[][] =
124 {
125 "counter_off", "clockstopbutton", "clockstop", "but_stop", "counter_stop_button",
126 "multi_stop", "stop_counter", "m_counter_end_emi"
127 };
128 iSize = sizeof(szStops);
129
130 for (i = 0; i < iSize; i++)
131 TrieSetCell(g_tStops, szStops[i], 1);
132
133 new iEntity = -1;
134
135 while ((iEntity = find_ent_by_class(iEntity, "func_button")) != 0)
136 {
137 new szTargetName[64];
138 entity_get_string(iEntity, EV_SZ_targetname, szTargetName, charsmax(szTargetName));
139
140 if (TrieKeyExists(g_tStarts, szTargetName) || TrieKeyExists(g_tStops, szTargetName))
141 {
142 if (!g_bTimerFound)
143 g_bTimerFound = true;
144
145 break;
146 }
147 }
148
149 if (!g_bTimerFound)
150 {
151 TrieDestroy(g_tStarts);
152 TrieDestroy(g_tStops);
153
154 new szFile[96];
155 formatex(szFile, charsmax(szFile), "deathrun/timer/%s", g_szMapName);
156
157 g_iVault = nvault_open(szFile);
158
159 LoadTimers();
160 }
161
162 iEntity = create_entity("info_target");
163
164 if (iEntity)
165 {
166 entity_set_float(iEntity, EV_FL_nextthink, get_gametime() + 0.5);
167 entity_set_string(iEntity, EV_SZ_classname, "_TimerThink");
168 register_think("_TimerThink", "TimerThink");
169 }
170
171 g_iMsgRoundTime = get_user_msgid("RoundTime");
172
173 RegisterHam(Ham_Spawn, "player", "HamSpawnPlayer_Post", true);
174 RegisterHam(Ham_Killed, "player", "HamKilledPlayer_Post", true);
175 RegisterHam(Ham_Use, "func_button", "HamUseFuncButton_Pre", false);
176
177 register_clcmd("say /timer", "ClCmdTimer");
178 register_clcmd("say_team /timer", "ClCmdTimer");
179
180 register_clcmd("say /top", "ClCmdBest");
181 register_clcmd("say_team /top", "ClCmdBest");
182
183 g_iHudSyncObj = CreateHudSyncObj();
184}
185public plugin_cfg()
186{
187 set_task(0.5, "DB_Init");
188}
189public DB_Init()
190{
191 state mysql;
192
193 new szDB[64];
194 get_cvar_string("dr_timer_sql_db", szDB, charsmax(szDB));
195
196 if (contain(szDB, ".") > 0)
197 {
198 state sqlite;
199
200 g_bSqlite = true;
201 }
202
203 SQL_Init();
204}
205SQL_Init()<mysql>
206{
207 new szHost[64], szUser[64], szPass[64], szDB[64];
208 get_cvar_string("dr_timer_sql_host", szHost, charsmax(szHost));
209 get_cvar_string("dr_timer_sql_user", szUser, charsmax(szUser));
210 get_cvar_string("dr_timer_sql_pass", szPass, charsmax(szPass));
211 get_cvar_string("dr_timer_sql_db", szDB, charsmax(szDB));
212
213 g_hSqlTuple = SQL_MakeDbTuple(szHost, szUser, szPass, szDB);
214
215 new szQuery[512];
216
217 formatex
218 (
219 szQuery, charsmax(szQuery),
220 "CREATE TABLE IF NOT EXISTS `%s` \
221 ( \
222 `ID` INT NOT NULL AUTO_INCREMENT, \
223 \
224 `MAPNAME` VARCHAR(64) NOT NULL, \
225 `AUTHID` VARCHAR(32) NOT NULL, \
226 `NICKNAME` VARCHAR(64) NOT NULL, \
227 `IP` VARCHAR(45) NOT NULL, \
228 `COUNTRY_FULL` VARCHAR(45) NOT NULL, \
229 `COUNTRY_SHORT` VARCHAR(3) NOT NULL, \
230 `TIME` DOUBLE NOT NULL, \
231 `DATE` DATETIME NOT NULL, \
232 \
233 PRIMARY KEY(`ID`) \
234 )",
235 g_szTableName
236 );
237
238 SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
239}
240SQL_Init()<sqlite>
241{
242 SQL_SetAffinity("sqlite");
243
244 new szDataDir[128];
245 get_localinfo("amxx_datadir", szDataDir, charsmax(szDataDir));
246
247 new szDB[64];
248 get_cvar_string("dr_timer_sql_db", szDB, charsmax(szDB));
249
250 new szFile[196];
251 formatex(szFile, charsmax(szFile), "%s/%s", szDataDir, szDB);
252
253 if (!file_exists(szFile))
254 {
255 new fp = fopen(szFile, "w");
256
257 if (!fp)
258 {
259 log_amx("[%s] SQL_Init()<sqlite>: File ^"%s^" not found and can't be created!", g_szPrefix, szFile);
260 return;
261 }
262 else
263 fclose(fp);
264 }
265
266 g_hSqlTuple = SQL_MakeDbTuple("", "", "", szFile, 0);
267
268 new szQuery[512];
269
270 formatex
271 (
272 szQuery, charsmax(szQuery),
273 "CREATE TABLE IF NOT EXISTS `%s` \
274 ( \
275 `MAPNAME` TEXT NOT NULL, \
276 `AUTHID` TEXT NOT NULL, \
277 `NICKNAME` TEXT NOT NULL, \
278 `IP` TEXT NOT NULL, \
279 `COUNTRY_FULL` TEXT NOT NULL, \
280 `COUNTRY_SHORT` TEXT NOT NULL, \
281 `TIME` REAL NOT NULL, \
282 `DATE` DATETIME NOT NULL \
283 )",
284 g_szTableName
285 );
286
287 SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
288}
289public client_putinserver(id)
290{
291 set_bit(g_bConnected, id);
292}
293public client_disconnected(id)
294{
295 clr_bit(g_bConnected, id);
296
297 if (get_bit(g_bAlive, id))
298 clr_bit(g_bAlive, id);
299
300 if (get_bit(g_bStarted, id))
301 clr_bit(g_bStarted, id);
302
303 if (g_flStartTime[id] != 0.0)
304 g_flStartTime[id] = 0.0;
305
306 if (g_flFinishTime[id] != 0.0)
307 g_flFinishTime[id] = 0.0;
308}
309public TimerThink(iEntity)
310{
311 if (iEntity)
312 entity_set_float(iEntity, EV_FL_nextthink, get_gametime() + 0.5);
313
314 for (new iAlivePlayer = 0; iAlivePlayer < MAX_PLAYERS; iAlivePlayer++)
315 {
316 if (get_bit(g_bConnected, iAlivePlayer) && get_bit(g_bAlive, iAlivePlayer) && get_bit(g_bStarted, iAlivePlayer))
317 {
318 new Float:flGameTime = get_gametime();
319
320 message_begin(MSG_ONE_UNRELIABLE, g_iMsgRoundTime, _, iAlivePlayer);
321 write_short(floatround(flGameTime - g_flStartTime[iAlivePlayer], floatround_floor) + 1);
322 message_end();
323
324 for (new iDeadPlayer = 0; iDeadPlayer < MAX_PLAYERS; iDeadPlayer++)
325 {
326 if (get_bit(g_bConnected, iDeadPlayer) && !get_bit(g_bAlive, iDeadPlayer) && entity_get_int(iDeadPlayer, EV_INT_iuser2) == iAlivePlayer && entity_get_int(iDeadPlayer, EV_INT_iuser1) == 4)
327 {
328 new iMinutes = floatround(g_flStartTime[iAlivePlayer] / 60.0, floatround_floor);
329 new iSeconds = floatround(g_flStartTime[iAlivePlayer] - iMinutes * 60, floatround_floor);
330
331 set_hudmessage(0, 255, 0, -1.0, 0.25, 0, _, 0.5, _, _, 1);
332 ShowSyncHudMsg(iDeadPlayer, g_iHudSyncObj, "%02d:%02d", iMinutes, iSeconds);
333 }
334 }
335 }
336 }
337}
338public HamSpawnPlayer_Post(id)
339{
340 set_bit(g_bAlive, id);
341
342 if (get_bit(g_bStarted, id))
343 {
344 clr_bit(g_bStarted, id);
345
346 g_flStartTime[id] = 0.0;
347 }
348}
349public HamKilledPlayer_Post(id)
350{
351 clr_bit(g_bAlive, id);
352
353 if (get_bit(g_bStarted, id))
354 {
355 clr_bit(g_bStarted, id);
356
357 g_flStartTime[id] = 0.0;
358 }
359}
360public HamUseFuncButton_Pre(iEntity, id)
361{
362 if (!get_bit(g_bAlive, id))
363 return(HAM_IGNORED);
364
365 if (g_bTimerFound)
366 {
367 new szTarget[32];
368 entity_get_string(iEntity, EV_SZ_target, szTarget, charsmax(szTarget));
369
370 if (TrieKeyExists(g_tStarts, szTarget))
371 Timer_Start(id);
372 else if (TrieKeyExists(g_tStops, szTarget))
373 Timer_Stop(id);
374 }
375 else
376 {
377 if (iEntity == g_iTimer[START])
378 Timer_Start(id);
379 else if (iEntity == g_iTimer[STOP])
380 Timer_Stop(id);
381 }
382
383 return(HAM_IGNORED);
384}
385Timer_Start(id)
386{
387 set_hudmessage(0, 0, 255, -1.0, 0.90, 0, _, 3.0, _, _, 1);
388
389 if (!get_bit(g_bStarted, id))
390 {
391 set_bit(g_bStarted, id);
392
393 ShowSyncHudMsg(id, g_iHudSyncObj, "Timer started!");
394 }
395 else
396 ShowSyncHudMsg(id, g_iHudSyncObj, "Timer re-started!");
397
398 g_flStartTime[id] = get_gametime();
399}
400Timer_Stop(id)
401{
402 if (!get_bit(g_bStarted, id))
403 return;
404
405 clr_bit(g_bStarted, id);
406
407 g_flFinishTime[id] = get_gametime() - g_flStartTime[id];
408
409 g_flStartTime[id] = 0.0;
410
411 message_begin(MSG_ONE_UNRELIABLE, g_iMsgRoundTime, _, id);
412 write_short(1);
413 message_end();
414
415 new szTime[17];
416 ClimbtimeToString(g_flFinishTime[id], szTime, charsmax(szTime));
417
418 #if defined COLORCHAT
419 ColorChat(id, RED, "^4[%s]^1 You finished map in^3 %s^1!", g_szPrefix, szTime);
420 #else
421 client_print_color(id, print_team_default, "%s ^3Você terminou em: ^1%s^3!", g_szPrefix, szTime);
422 #endif
423
424 new iPlayers[MAX_PLAYERS], iNum;
425 get_players(iPlayers, iNum, "ch");
426
427 if (iNum)
428 {
429 new szName[32];
430 get_user_name(id, szName, charsmax(szName));
431
432 new iPlayer;
433
434 for (new i = 0; i < iNum; i++)
435 {
436 iPlayer = iPlayers[i];
437
438 if (iPlayer == id)
439 continue;
440
441 #if defined COLORCHAT
442 ColorChat(iPlayer, RED, "^4[%s]^3 %s^1 finished map in^3 %s^1!", g_szPrefix, szName, szTime);
443 #else
444 client_print_color(iPlayer, print_team_default, "%s ^1%s ^3terminou o mapa em: ^1%s^3!", g_szPrefix, szName, szTime);
445
446 #endif
447 }
448 }
449
450 new szAuthID[32];
451 get_user_authid(id, szAuthID, charsmax(szAuthID));
452
453 new szQuery[512], cData[1]; cData[0] = id;
454
455 formatex
456 (
457 szQuery, charsmax(szQuery),
458 "SELECT \
459 `TIME` \
460 FROM \
461 `%s` \
462 WHERE \
463 `MAPNAME` = '%s' \
464 AND \
465 `AUTHID` = '%s'",
466 g_szTableName,
467 g_szMapName,
468 szAuthID
469 );
470
471 SQL_ThreadQuery(g_hSqlTuple, "Sql_QueryTop_Handler", szQuery, cData, sizeof(cData));
472}
473public Sql_QueryTop_Handler(iFailState, Handle:hQuery, szError[], iError, cData[], iSize)
474{
475 if (iFailState != TQUERY_SUCCESS)
476 {
477 log_amx("[%s] Sql_IgnoredQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
478 return;
479 }
480
481 new id = cData[0];
482
483 if (!get_bit(g_bConnected, id))
484 return;
485
486 new szAuthID[32], szName[64], szIP[32], szCountryFull[45], szCountryShort[3], szDate[32];
487 get_user_authid(id, szAuthID, charsmax(szAuthID));
488 get_user_name(id, szName, charsmax(szName));
489 get_user_ip(id, szIP, charsmax(szIP), 1);
490 geoip_country_ex(szIP, szCountryFull, charsmax(szCountryFull));
491 geoip_code2_ex(szIP, szCountryShort);
492 get_time("%Y%m%d%H%M%S", szDate, charsmax(szDate));
493
494 SQL_PrepareString(szName, szName, charsmax(szName));
495
496 new szQuery[512];
497
498 if (SQL_NumResults(hQuery))
499 {
500 new Float:flOldTime, Float:flResult, szTime[17];
501
502 SQL_ReadResult(hQuery, 0, flOldTime);
503
504 if (g_flFinishTime[id] < flOldTime)
505 {
506 flResult = flOldTime - g_flFinishTime[id];
507
508 ClimbtimeToString(flResult, szTime, charsmax(szTime));
509
510 #if defined COLORCHAT
511 ColorChat(id, RED, "^4[%s]^1 You improved your time for^3 %s^1 msec!", g_szPrefix, szTime);
512 #else
513 client_print_color(id, print_team_default, "%s ^3Você melhorou seu tempo em ^1%s ^3msec!", g_szPrefix, szTime);
514 #endif
515
516 formatex
517 (
518 szQuery, charsmax(szQuery),
519 "UPDATE `%s` \
520 SET \
521 `NICKNAME` = '%s', \
522 `IP` = '%s', \
523 `COUNTRY_FULL` = '%s', \
524 `COUNTRY_SHORT` = '%s', \
525 `TIME` = '%f', \
526 `DATE` = '%s' \
527 WHERE \
528 `MAPNAME` = '%s' \
529 AND \
530 `AUTHID` = '%s'",
531 g_szTableName,
532 szName,
533 szIP,
534 szCountryFull,
535 szCountryShort,
536 g_flFinishTime[id],
537 szDate,
538 g_szMapName,
539 szAuthID
540 );
541
542 SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
543
544 formatex
545 (
546 szQuery, charsmax(szQuery),
547 "SELECT \
548 `AUTHID` \
549 FROM \
550 `%s` \
551 WHERE \
552 MAPNAME='%s' \
553 ORDER BY \
554 `TIME` \
555 LIMIT 15",
556 g_szTableName,
557 g_szMapName
558 );
559
560 SQL_ThreadQuery(g_hSqlTuple, "Sql_GetPlaceQuery_Handler", szQuery, cData, sizeof(cData[]));
561 }
562 else
563 {
564 flResult = g_flFinishTime[id] - flOldTime;
565
566 ClimbtimeToString(flResult, szTime, charsmax(szTime));
567
568 #if defined COLORCHAT
569 ColorChat(id, RED, "^4[%s]^1 You failed your time for^3 %s^1 msec!", g_szPrefix, szTime);
570 #else
571 client_print_color(id, print_team_default, "%s ^3Você falhou seu tempo em: ^1%s ^3msec!", g_szPrefix, szTime);
572 #endif
573 }
574 }
575 else
576 {
577 formatex
578 (
579 szQuery, charsmax(szQuery),
580 "INSERT INTO `%s` \
581 ( \
582 `MAPNAME`, \
583 `AUTHID`, \
584 `NICKNAME`, \
585 `IP`, \
586 `COUNTRY_FULL`, \
587 `COUNTRY_SHORT`, \
588 `TIME`, \
589 `DATE` \
590 ) \
591 \
592 VALUES \
593 ( \
594 '%s', \
595 '%s', \
596 '%s', \
597 '%s', \
598 '%s', \
599 '%s', \
600 '%f', \
601 '%s' \
602 )",
603 g_szTableName,
604 g_szMapName,
605 szAuthID,
606 szName,
607 szIP,
608 szCountryFull,
609 szCountryShort,
610 g_flFinishTime[id],
611 szDate
612 );
613
614 SQL_ThreadQuery(g_hSqlTuple, "Sql_IgnoredQuery_Handler", szQuery);
615
616 formatex
617 (
618 szQuery, charsmax(szQuery),
619 "SELECT \
620 `AUTHID` \
621 FROM \
622 `%s` \
623 WHERE \
624 MAPNAME='%s' \
625 ORDER BY \
626 `TIME` \
627 LIMIT 15",
628 g_szTableName,
629 g_szMapName
630 );
631
632 SQL_ThreadQuery(g_hSqlTuple, "Sql_GetPlaceQuery_Handler", szQuery, cData, sizeof(cData[]));
633 }
634
635 g_flFinishTime[id] = 0.0;
636}
637public Sql_GetPlaceQuery_Handler(iFailState, Handle:hQuery, szError, iError, cData[], iSize)
638{
639 if (iFailState != TQUERY_SUCCESS)
640 {
641 log_amx("[%s] Sql_GetPlaceQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
642 return;
643 }
644
645 new id = cData[0];
646
647 if (!get_bit(g_bConnected, id))
648 return;
649
650 new szAuthID[32];
651 get_user_authid(id, szAuthID, charsmax(szAuthID));
652
653 new i, szAuthID_SQL[32];
654
655 while(SQL_MoreResults(hQuery))
656 {
657 i++;
658
659 SQL_ReadResult(hQuery, 0, szAuthID_SQL, charsmax(szAuthID_SQL));
660
661 if (equal(szAuthID, szAuthID_SQL))
662 {
663 #if defined COLORCHAT
664 ColorChat(id, RED, "^4[%s]^1 You are now on^3 %d^1 place in map top!", g_szPrefix, i);
665 #else
666 client_print_color(id, print_team_default, "%s ^3Agora você está em: ^1%dº ^3posicão do top neste mapa.", g_szPrefix, i);
667 #endif
668
669 new iPlayers[MAX_PLAYERS], iNum;
670 get_players(iPlayers, iNum, "ch");
671
672 if (iNum)
673 {
674 new szName[32];
675 get_user_name(id, szName, charsmax(szName));
676
677 new iPlayer;
678
679 for (new i = 0; i < iNum; i++)
680 {
681 iPlayer = iPlayers[i];
682
683 if (iPlayer == id)
684 continue;
685
686 #if defined COLORCHAT
687 ColorChat(iPlayer, RED, "^4[%s]^3 %s^1 is now on^3 %d^1 place in map top!", g_szPrefix, szName, i);
688 #else
689 client_print_color(iPlayer, print_team_default, "%s ^1%s ^3Agora está em: ^1%dº ^3posicão do top neste mapa.", g_szPrefix, szName, i);
690 #endif
691 }
692 }
693 break;
694 }
695 SQL_NextRow(hQuery);
696 }
697}
698public Sql_IgnoredQuery_Handler(iFailState, Handle:hQuery, szError[], iError, cData[], iSize)
699{
700 if (iFailState != TQUERY_SUCCESS)
701 {
702 log_amx("[%s] Sql_IgnoredQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
703 return;
704 }
705}
706public ClCmdBest(id)
707{
708 if (!g_bSqlite)
709 {
710 new szWebLink[128];
711 get_pcvar_string(g_pWebLink, szWebLink, charsmax(szWebLink));
712
713 new szMotd[256];
714 formatex(szMotd, charsmax(szMotd), "<META HTTP-EQUIV=^"REFRESH^" CONTENT=^"0;URL=%s/maptop.php?mapname=%s^">", szWebLink, g_szMapName);
715
716 show_motd(id, szMotd, "DR - Map Top");
717 }
718 else
719 {
720 new szQuery[512], cData[1]; cData[0] = id;
721
722 formatex
723 (
724 szQuery, charsmax(szQuery),
725 "SELECT \
726 `NICKNAME`, \
727 `TIME` \
728 FROM \
729 `%s` \
730 WHERE \
731 `MAPNAME` = '%s' \
732 ORDER BY \
733 `TIME` \
734 LIMIT 15",
735 g_szTableName,
736 g_szMapName
737 );
738
739 SQL_ThreadQuery(g_hSqlTuple, "Sql_LoadTopQuery_Handler", szQuery, cData, sizeof(cData));
740 }
741}
742public Sql_LoadTopQuery_Handler(iFailState, Handle:hQuery, szError, iError, cData[], iSize)
743{
744 if (iFailState != TQUERY_SUCCESS)
745 {
746 log_amx("[%s] Sql_GetPlaceQuery_Handler(): SQL_Error #%d - %s", g_szPrefix, iError, szError);
747 return;
748 }
749
750 new id = cData[0];
751
752 if (!get_bit(g_bConnected, id))
753 return;
754
755 new szMotd[1536], iSize = charsmax(szMotd);
756
757 new iLen = formatex
758 (
759 szMotd, iSize,
760 "<!DOCTYPE HTML> \
761 <html> \
762 <head> \
763 <style type=^"text/css^"> \
764 body \
765 { \
766 background: #000; \
767 margin: 8px; \
768 color: #FFB000; \
769 font: normal 16px/20px Verdana, Tahoma, sans-serif; \
770 text-align: center; \
771 } \
772 th:nth-child(2){ text-align: left; } \
773 td:nth-child(2){ text-align: left; } \
774 </style> \
775 </head> \
776 <body>"
777 );
778
779 iLen += formatex
780 (
781 szMotd[iLen], iSize - iLen,
782 "<table align=^"center^" width=^"90%%^"> \
783 <tr> \
784 <th width=^"5%%^">#</th>\
785 <th width=^"40%%^">Player</th>\
786 <th width=^"20%%^">Time</th>\
787 </tr> \
788 "
789 );
790
791 new i = 1;
792 new Float:flTime, szName[32], szTime[32];
793
794 while (SQL_MoreResults(hQuery))
795 {
796 SQL_ReadResult(hQuery, 0, szName, 31);
797 SQL_ReadResult(hQuery, 1, flTime);
798
799 ClimbtimeToString(flTime, szTime, 16);
800
801 iLen += formatex
802 (
803 szMotd[iLen], iSize - iLen,
804 "<tr> \
805 <td>%d</td> \
806 <td>%s</td> \
807 <td>%s</td> \
808 </tr>",
809 i,
810 szName,
811 szTime
812 );
813
814 i++;
815 SQL_NextRow(hQuery);
816 }
817
818 formatex
819 (
820 szMotd[iLen], iSize - iLen,
821 "</table> \
822 </body> \
823 </html>"
824 );
825
826 show_motd(id, szMotd, "DR - Map Top");
827}
828stock SQL_PrepareString(const szQuery[], szOutPut[], iSize)
829{
830 copy(szOutPut, iSize, szQuery);
831 replace_all(szOutPut, iSize, "'", "\'");
832 replace_all(szOutPut, iSize, "`", "\`");
833 replace_all(szOutPut, iSize, "\\", "\\\\");
834}
835ClimbtimeToString(Float:flClimbTime, szOutPut[], iLen)
836{
837 new iMinutes = floatround(flClimbTime / 60.0, floatround_floor);
838 new iSeconds = floatround(flClimbTime - iMinutes * 60, floatround_floor);
839 new iMiliSeconds = floatround((flClimbTime - (iMinutes * 60 + iSeconds)) * 100, floatround_floor);
840
841 formatex(szOutPut, iLen, "%02i:%02i.%02i", iMinutes, iSeconds, iMiliSeconds);
842}
843public ClCmdTimer(id)
844{
845 if (~get_user_flags(id) & ADMIN_ACCESS)
846 {
847 #if defined COLORCHAT
848 ColorChat(id, NORMAL, "^4[%s]^1 You don't have enought access!", g_szPrefix);
849 #else
850 client_print(id, print_chat, "[%s] You don't have enought access!", g_szPrefix);
851 #endif
852
853 return(PLUGIN_HANDLED);
854 }
855 if (g_bTimerFound)
856 {
857 #if defined COLORCHAT
858 ColorChat(id, NORMAL, "^4[%s]^1 This map already have timers!", g_szPrefix);
859 #else
860 client_print(id, print_chat, "[%s] This map already have timers!", g_szPrefix);
861 #endif
862 return(PLUGIN_HANDLED);
863 }
864 if (!get_bit(g_bAlive, id))
865 {
866 #if defined COLORCHAT
867 ColorChat(id, NORMAL, "^4[%s]^1 You should be alive!", g_szPrefix);
868 #else
869 client_print(id, print_chat, "[%s] You should be alive!", g_szPrefix);
870 #endif
871 return(PLUGIN_HANDLED);
872 }
873
874 TimerMenu(id);
875
876 return(PLUGIN_HANDLED);
877}
878public TimerMenu(id)
879{
880 new iMenu = menu_create("\r[DeathRun]\y Timer Menu", "TimerMenu_Handler");
881
882 menu_additem(iMenu, "Create");
883 menu_additem(iMenu, "Rotate^n");
884
885 menu_additem(iMenu, "Save^n");
886
887 new szMenuItem[64];
888 formatex(szMenuItem, charsmax(szMenuItem), "Timer - (\y%s\w)", g_szTimerName[g_iPlayerTimer[id]]);
889 menu_additem(iMenu, szMenuItem);
890
891 menu_display(id, iMenu);
892}
893public TimerMenu_Handler(id, iMenu, iItem)
894{
895 if (iItem == MENU_EXIT)
896 {
897 menu_destroy(iMenu);
898 return(PLUGIN_HANDLED);
899 }
900
901 switch (iItem)
902 {
903 case 0: create_timer(id, g_iPlayerTimer[id]);
904 case 1:
905 {
906 if (is_valid_ent(g_iTimer[g_iPlayerTimer[id]]))
907 {
908 switch (g_iTimerAngles[g_iPlayerTimer[id]])
909 {
910 case 3: g_iTimerAngles[g_iPlayerTimer[id]] = 0;
911 case 0, 1, 2: g_iTimerAngles[g_iPlayerTimer[id]]++;
912 }
913
914 new Float:vAngles[3];
915 vAngles[1] = g_flTimerAngles[g_iTimerAngles[g_iPlayerTimer[id]]];
916
917 entity_set_vector(g_iTimer[g_iPlayerTimer[id]], EV_VEC_angles, vAngles);
918 }
919 }
920 case 2:
921 {
922 if (is_valid_ent(g_iTimer[g_iPlayerTimer[id]]))
923 {
924 if (g_iVault == INVALID_HANDLE)
925 return(PLUGIN_HANDLED);
926
927 new szData[128], iTimestamp;
928
929 if (nvault_lookup(g_iVault, g_szTimerName[g_iPlayerTimer[id]], szData, charsmax(szData), iTimestamp))
930 nvault_remove(g_iVault, g_szTimerName[g_iPlayerTimer[id]]);
931
932 formatex(szData, charsmax(szData), "^"%.1f^" ^"%.1f^" ^"%.1f^" ^"%d^"", g_vTimerOrigin[g_iPlayerTimer[id]][0], g_vTimerOrigin[g_iPlayerTimer[id]][1], g_vTimerOrigin[g_iPlayerTimer[id]][2], g_iTimerAngles[g_iPlayerTimer[id]]);
933
934 nvault_set(g_iVault, g_szTimerName[g_iPlayerTimer[id]], szData);
935
936 #if defined COLORCHAT
937 ColorChat(id, RED, "^4[%s]^1 Timer (^3%s^1) saved!", g_szPrefix, g_szTimerName[g_iPlayerTimer[id]]);
938 #else
939 client_print(id, print_chat, "[%s] Timer (%s) saved!", g_szPrefix, g_szTimerName[g_iPlayerTimer[id]]);
940 #endif
941 }
942 }
943 case 3:
944 {
945 switch (g_iPlayerTimer[id])
946 {
947 case START: g_iPlayerTimer[id] = STOP;
948 case STOP: g_iPlayerTimer[id] = START;
949 }
950 }
951 }
952
953 ClCmdTimer(id);
954 return(PLUGIN_HANDLED);
955}
956LoadTimers()
957{
958 if (g_iVault == INVALID_HANDLE)
959 return;
960
961 for (new i = 0; i < 2; i++)
962 {
963 new szData[128], iTimestamp;
964 if (nvault_lookup(g_iVault, g_szTimerName[i], szData, charsmax(szData), iTimestamp))
965 {
966 new szOrigin[3][17], szAngles[2];
967 parse(szData, szOrigin[0], charsmax(szOrigin[]), szOrigin[1], charsmax(szOrigin[]), szOrigin[2], charsmax(szOrigin[]), szAngles, charsmax(szAngles));
968
969 for (new x = 0; x < 3; x++)
970 g_vTimerOrigin[i][x] = str_to_float(szOrigin[x]);
971
972 g_iTimerAngles[i] = str_to_num(szAngles);
973
974 create_timer(0, i, g_vTimerOrigin[i]);
975 }
976 else
977 continue;
978 }
979}
980stock create_timer(id, iType, Float:vOrigin[3] = {0.0, 0.0, 0.0})
981{
982 if (!g_iTimer[iType])
983 {
984 new iEntity = create_entity("func_button");
985
986 if (!is_valid_ent(iEntity))
987 return;
988
989 new szClassName[32];
990 formatex(szClassName, charsmax(szClassName), "Timer_%s", g_szTimerName[iType]);
991
992 entity_set_string(iEntity, EV_SZ_classname, szClassName);
993 entity_set_int(iEntity, EV_INT_solid, SOLID_BBOX);
994 entity_set_int(iEntity, EV_INT_movetype, MOVETYPE_NONE);
995 entity_set_model(iEntity, g_szTimerModels[iType]);
996 entity_set_size(iEntity, Float:{-16.0, -16.0, 0.0}, Float:{16.0, 16.0, 60.0});
997
998 g_iTimer[iType] = iEntity;
999 }
1000 if (id)
1001 {
1002 new vOriginI[3];
1003 get_user_origin(id, vOriginI, 3);
1004
1005 new Float:vOriginF[3];
1006 IVecFVec(vOriginI, vOriginF);
1007
1008 entity_set_origin(g_iTimer[iType], vOriginF);
1009
1010 for (new i = 0; i < 3; i++)
1011 g_vTimerOrigin[iType][i] = vOriginF[i];
1012 }
1013 else
1014 entity_set_origin(g_iTimer[iType], vOrigin);
1015
1016 new Float:vAngles[3];
1017 vAngles[1] = g_flTimerAngles[g_iTimerAngles[iType]];
1018
1019 entity_set_vector(g_iTimer[iType], EV_VEC_angles, vAngles);
1020
1021 drop_to_floor(g_iTimer[iType]);
1022}
1023public plugin_end()
1024{
1025 if (g_bTimerFound)
1026 {
1027 TrieDestroy(g_tStarts);
1028 TrieDestroy(g_tStops);
1029 }
1030 else
1031 {
1032 if (g_iVault != INVALID_HANDLE)
1033 nvault_close(g_iVault);
1034 }
1035
1036 SQL_FreeHandle(g_hSqlTuple);
1037}