· 6 years ago · Jul 28, 2019, 12:58 AM
1#pragma semicolon 1
2#include <sourcemod>
3#include <morecolors>
4#include <sdktools>
5#include <clientprefs>
6#include <sdkhooks>
7#undef REQUIRE_PLUGIN
8#tryinclude <tf_dodgeball>
9#tryinclude <ccc>
10#tryinclude <nanobot>
11#tryinclude <juggernaut>
12#define REQUIRE_PLUGIN
13#include <SteamWorks>
14
15#define PLUGIN_VERSION "2.1"
16
17public Plugin myinfo = {
18 name = "[TF2] Dodgeball Stats",
19 author = "Nanochip",
20 description = "Records a database of Dodgeball statistics.",
21 version = PLUGIN_VERSION,
22 url = "http://steamcommunity.com/id/xNanochip/"
23};
24
25Database db = null;
26
27ConVar cvarSeason, cvarDebug, cvarBotDisabled, cvarJuggDisabled, cvarTrack;
28bool g_bTrack;
29int seasonYear;
30int rocketDeflects = 0;
31bool tfdb = false;
32bool ccc = false;
33bool nanobot = false;
34bool juggernaut = false;
35bool canTrackSpeed = false;
36int playerDeflects[MAXPLAYERS + 1] = { 0, ... };
37int playerSpeed[MAXPLAYERS + 1] = { 0, ... };
38int playerKills[MAXPLAYERS + 1] = { 0, ... };
39int playerTopSpeed[MAXPLAYERS + 1] = {0, ...}; // BETA
40
41/* BETA UNCOMMENT
42bool gBeatPersonSpeed[MAXPLAYERS + 1] = {false, ...};
43int gRecordPlayerSpeed[MAXPLAYERS + 1] = {0, ...};
44int gBeatRecordSpeed = 0;*/
45
46//int g_iTarget = 0;
47//int g_iOrgOwner = 0;
48int prevTopSpeed = 0;
49char kvPath[PLATFORM_MAX_PATH];
50
51char g_ColorNames[13][10] = {"White", "Red", "Green", "Blue", "Yellow", "Purple", "Cyan", "Orange", "Pink", "Olive", "Lime", "Violet", "Lightblue"};
52int g_Colors[13][3] = {{255,255,255},{255,0,0},{0,255,0},{0,0,255},{255,255,0},{255,0,255},{0,255,255},{255,128,0},{255,0,128},{128,255,0},{0,255,128},{128,0,255},{0,128,255}};
53
54Handle cPRecordSound, cGRecordSound, cDialogMessage;
55bool pRecordSound[MAXPLAYERS+1], gRecordSound[MAXPLAYERS+1], bDialogMessage[MAXPLAYERS+1];
56
57Handle hTimer[MAXPLAYERS+1];
58
59public void OnPluginStart()
60{
61 CreateConVar("sm_dbstats_version", PLUGIN_VERSION, "Dodgeball Stats Version", FCVAR_DONTRECORD);
62
63 LoadTranslations("common.phrases");
64
65 cvarSeason = CreateConVar("sm_dbstats_season", "1", "The season number (change this if you want to reset stats and start a new season)");
66 //cvarSeasonYear = CreateConVar("sm_dbstats_season_year", "2017", "The season year (change this if you want to reset stats and start a new year)");
67 cvarDebug = CreateConVar("sm_dbstats_debug", "0", "Show debugging?");
68 cvarBotDisabled = CreateConVar("sm_dbstats_pvb_disable", "1", "Disable stats when Player vs Bot mode is on.");
69 cvarJuggDisabled = CreateConVar("sm_dbstats_juggernaut_disable", "1", "Disable stat tracking when Juggernaut mode is on.");
70 cvarTrack = CreateConVar("sm_dbstats_track", "1", "Enable/Disable tracking of stats");
71 cvarTrack.AddChangeHook(OnCvarChange);
72 char timeYear[32];
73 FormatTime(timeYear, sizeof(timeYear), "%Y", GetTime());
74 seasonYear = StringToInt(timeYear);
75
76 g_bTrack = cvarTrack.BoolValue;
77
78 RegConsoleCmd("sm_stats", Cmd_Stats, "View dodgeball statistics.");
79 RegConsoleCmd("sm_dbstats", Cmd_Stats, "View dodgeball statistics.");
80 RegConsoleCmd("sm_myrank", Cmd_MyRank, "View your rank.");
81 RegConsoleCmd("sm_rank", Cmd_Rank, "View rank.");
82 RegConsoleCmd("sm_top10", Cmd_Top, "View top 10 ranked players.");
83 RegConsoleCmd("sm_top", Cmd_Top, "View top 10 ranked players.");
84 RegConsoleCmd("sm_topspeed", Cmd_TopSpeed, "View top 10 record speeds for the current map.");
85 RegConsoleCmd("sm_topdeflects", Cmd_TopDeflects, "View Top Deflects");
86 RegConsoleCmd("sm_topupspikes", Cmd_TopUpspikes, "View Top Upspikes");
87 RegConsoleCmd("sm_topdownspikes", Cmd_TopDownspikes, "View Top Downspikes");
88 RegConsoleCmd("sm_topsteals", Cmd_TopSteals, "View Top Steals");
89 RegConsoleCmd("sm_topkills", Cmd_TopKills, "View Top Kills");
90 RegConsoleCmd("sm_topdeaths", Cmd_TopDeaths, "View Top Deaths");
91 RegConsoleCmd("sm_topkilldeathratio", Cmd_TopKDR, "View Top Kill/Death Ratios");
92 RegConsoleCmd("sm_topkdr", Cmd_TopKDR, "View Top Kill/Death Ratios");
93 RegConsoleCmd("sm_leaderboard", Cmd_LeaderBoard, "View the leaderboard");
94 RegConsoleCmd("sm_leaderboards", Cmd_LeaderBoard, "View the leaderboard");
95 RegConsoleCmd("sm_ranks", Cmd_Ranks, "View the rank titles");
96 RegConsoleCmd("sm_next", Cmd_Next, "View the next rank title and the person ahead of you in the ranking system");
97 RegConsoleCmd("sm_nextrank", Cmd_Next, "View the next rank title and the person ahead of you in the ranking system");
98 RegConsoleCmd("sm_nextplayers", Cmd_Next, "View the next rank title and the person ahead of you in the ranking system");
99
100 RegAdminCmd("sm_delstats", Cmd_DelStats, ADMFLAG_RCON, "Deletes a player's stats.");
101 RegAdminCmd("sm_givepoints", Cmd_GivePoints, ADMFLAG_RCON, "Give points to a player.");
102
103 AddCommandListener(Cmd_ReloadCCC, "sm_reloadccc");
104
105 HookEvent("player_death", Event_PlayerDeath);
106 HookEvent("player_spawn", Event_PlayerSpawn);
107 HookEvent("teamplay_round_start", Event_RoundStart);
108
109 cPRecordSound = RegClientCookie("dbstats_precordsound", "", CookieAccess_Private);
110 cGRecordSound = RegClientCookie("dbstats_grecordsound", "", CookieAccess_Private);
111 cDialogMessage = RegClientCookie("dbstats_dialogmessage", "", CookieAccess_Private);
112
113 SetCookiePrefabMenu(cPRecordSound, CookieMenu_OnOff_Int, "[DBS] New Personal Record Sound");
114 SetCookiePrefabMenu(cGRecordSound, CookieMenu_OnOff_Int, "[DBS] New Global Record Sound");
115 SetCookiePrefabMenu(cDialogMessage, CookieMenu_OnOff_Int, "[DBS] Top Left Dialog Messages");
116
117 for (int i = 1; i <= MaxClients; i++)
118 {
119 pRecordSound[i] = true;
120 gRecordSound[i] = true;
121 bDialogMessage[i] = true;
122 if (IsClientInGame(i) && AreClientCookiesCached(i)) OnClientCookiesCached(i);
123 }
124
125 AutoExecConfig(true);
126
127 BuildPath(Path_SM, kvPath, sizeof(kvPath), "configs/dbstats.cfg");
128 if (!FileExists(kvPath)) LogError("dbstats.cfg does not exist in %s!", kvPath);
129}
130
131public int OnCvarChange(ConVar cvar, const char[] oldValue, const char[] newValue)
132{
133 if (cvar == cvarTrack)
134 {
135 g_bTrack = view_as<bool>(StringToInt(newValue));
136 }
137}
138
139public void OnMapStart()
140{
141 StartSQL();
142}
143
144public void OnClientPutInServer(int client)
145{
146 hTimer[client] = CreateTimer(60.0, Timer_TrackTime, GetClientUserId(client), TIMER_REPEAT);
147}
148
149public Action Timer_TrackTime(Handle htimer, any data)
150{
151 int client = GetClientOfUserId(data);
152 if (IsClientInGame(client) && !IsFakeClient(client))
153 {
154 char steamid[32], query[256];
155 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
156
157 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `time_played`=(`time_played`+1) WHERE steamid = '%s'", cvarSeason.IntValue, seasonYear, steamid);
158 db.Query(T_UpdateTimePlayed, query);
159 }
160}
161
162public void T_UpdateTimePlayed(Database hndl, DBResultSet results, const char[] error, any data)
163{
164 if (results == null)
165 {
166 LogError("T_UpdateTimePlayed query failed: %s", error);
167 return;
168 }
169}
170
171public void OnLibraryAdded(const char[] name)
172{
173 if (StrEqual(name, "tf_dodgeball"))
174 {
175 tfdb = true;
176 LogAction(0, -1, "Detected TF_Dodgeball.");
177 }
178 if (StrEqual(name, "ccc"))
179 {
180 ccc = true;
181 LogAction(0, -1, "Detected Custom-Chatcolors.");
182 char query[1024], steamid[32];
183 for (int i = 1; i <= MaxClients; i++)
184 {
185 if (IsClientInGame(i) && !IsFakeClient(i))
186 {
187 GetClientAuthId(i, AuthId_Steam2, steamid, sizeof(steamid));
188 Format(query, sizeof(query), "SELECT `ranktitle`, `ranktitlehex` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
189 db.Query(T_GetRankTitle, query, GetClientUserId(i));
190 }
191 }
192 }
193 if (StrEqual(name, "nanobot"))
194 {
195 nanobot = true;
196 LogAction(0, -1, "Detected Nanobot.");
197 }
198 if (StrEqual(name, "juggernaut"))
199 {
200 juggernaut = true;
201 LogAction(0, -1, "Detected Juggernaut.");
202 }
203}
204
205public void OnLibraryRemoved(const char[] name)
206{
207 if (StrEqual(name, "tf_dodgeball")) tfdb = false;
208 if (StrEqual(name, "ccc")) ccc = false;
209 if (StrEqual(name, "nanobot")) nanobot = false;
210 if (StrEqual(name, "juggernaut")) juggernaut = false;
211}
212
213public Action Cmd_ReloadCCC(int client, const char[] command, int argc)
214{
215 char query[1024], steamid[32];
216 for (int i = 1; i <= MaxClients; i++)
217 {
218 if (IsClientInGame(i) && !IsFakeClient(i))
219 {
220 GetClientAuthId(i, AuthId_Steam2, steamid, sizeof(steamid));
221 Format(query, sizeof(query), "SELECT `ranktitle`, `ranktitlehex` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
222 db.Query(T_GetRankTitle, query, GetClientUserId(i));
223 }
224 }
225}
226
227public Action Cmd_GivePoints(int client, int args)
228{
229 char arg1[MAX_NAME_LENGTH], arg2[32];
230
231 GetCmdArg(1, arg1, sizeof(arg1));
232 GetCmdArg(2, arg2, sizeof(arg2));
233 int points = StringToInt(arg2);
234 int target = FindTarget(client, arg1, true);
235 if (target == -1) return Plugin_Handled;
236
237 GivePoints(target, points);
238 PrintToChat(client, "[SM] Gave %N %d points", target, points);
239
240 return Plugin_Handled;
241}
242
243public Action Cmd_Top(int client, int args)
244{
245 if (!IsValidClient(client)) return Plugin_Handled;
246
247 ShowTopMenu(client);
248 return Plugin_Handled;
249}
250
251public Action Cmd_TopSpeed(int client, int args)
252{
253 if (!IsValidClient(client)) return Plugin_Handled;
254
255 ShowTopSpeedMenu(client);
256 return Plugin_Handled;
257}
258
259public Action Cmd_TopDeflects(int client, int args)
260{
261 if (!IsValidClient(client)) return Plugin_Handled;
262
263 ShowTopDeflects(client);
264 return Plugin_Handled;
265}
266
267public Action Cmd_TopUpspikes(int client, int args)
268{
269 if (!IsValidClient(client)) return Plugin_Handled;
270
271 ShowTopUpspikes(client);
272 return Plugin_Handled;
273}
274
275public Action Cmd_TopDownspikes(int client, int args)
276{
277 if (!IsValidClient(client)) return Plugin_Handled;
278
279 ShowTopDownspikes(client);
280 return Plugin_Handled;
281}
282
283public Action Cmd_TopSteals(int client, int args)
284{
285 if (!IsValidClient(client)) return Plugin_Handled;
286
287 ShowTopSteals(client);
288 return Plugin_Handled;
289}
290
291public Action Cmd_TopKills(int client, int args)
292{
293 if (!IsValidClient(client)) return Plugin_Handled;
294
295 ShowTopKills(client);
296 return Plugin_Handled;
297}
298
299public Action Cmd_TopDeaths(int client, int args)
300{
301 if (!IsValidClient(client)) return Plugin_Handled;
302
303 ShowTopDeaths(client);
304 return Plugin_Handled;
305}
306
307public Action Cmd_TopKDR(int client, int args)
308{
309 if (!IsValidClient(client)) return Plugin_Handled;
310
311 ShowTopKDR(client);
312 return Plugin_Handled;
313}
314
315public Action Cmd_LeaderBoard(int client, int args)
316{
317 if (!IsValidClient(client)) return Plugin_Handled;
318
319 ShowLeaderboards(client);
320 return Plugin_Handled;
321}
322
323public Action Cmd_Ranks(int client, int args)
324{
325 if (!IsValidClient(client)) return Plugin_Handled;
326
327 ShowRanks(client);
328 return Plugin_Handled;
329}
330
331public Action Cmd_Next(int client, int args)
332{
333 if (!IsValidClient(client)) return Plugin_Handled;
334
335 ProcessNextMenu(client);
336 return Plugin_Handled;
337}
338
339public Action OnClientSayCommand(int client, const char[] command, const char[] sArgs)
340{
341 if (StrEqual(sArgs, "rank", false) || StrEqual(sArgs, "myrank", false))
342 {
343 Cmd_MyRank(client, 0);
344 }
345 if (StrEqual(sArgs, "top", false) || StrEqual(sArgs, "top10", false))
346 {
347 Cmd_Top(client, 0);
348 }
349 if (StrEqual(sArgs, "topspeed", false))
350 {
351 Cmd_TopSpeed(client, 0);
352 }
353 if (StrEqual(sArgs, "topdeflects", false) || StrEqual(sArgs, "topdf", false))
354 {
355 Cmd_TopDeflects(client, 0);
356 }
357 if (StrEqual(sArgs, "topupspikes", false) || StrEqual(sArgs, "topus", false))
358 {
359 Cmd_TopUpspikes(client, 0);
360 }
361 if (StrEqual(sArgs, "topdownspikes", false) || StrEqual(sArgs, "topds", false))
362 {
363 Cmd_TopDownspikes(client, 0);
364 }
365 if (StrEqual(sArgs, "topsteals", false))
366 {
367 Cmd_TopSteals(client, 0);
368 }
369 if (StrEqual(sArgs, "topkills", false))
370 {
371 Cmd_TopKills(client, 0);
372 }
373 if (StrEqual(sArgs, "topdeaths", false))
374 {
375 Cmd_TopDeaths(client, 0);
376 }
377 if (StrEqual(sArgs, "topkdr", false))
378 {
379 Cmd_TopKDR(client, 0);
380 }
381 if (StrEqual(sArgs, "leaderboard", false) || StrEqual(sArgs, "leaderboards", false))
382 {
383 Cmd_LeaderBoard(client, 0);
384 }
385 if (StrEqual(sArgs, "ranks", false))
386 {
387 Cmd_Ranks(client, 0);
388 }
389 if (StrEqual(sArgs, "nextrank", false) || StrEqual(sArgs, "nextplayers", false))
390 {
391 Cmd_Next(client, 0);
392 }
393 return Plugin_Continue;
394}
395
396public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast)
397{
398 int client = GetClientOfUserId(GetEventInt(event, "userid"));
399 playerKills[client] = 0;
400}
401
402public Event_RoundStart(Handle event, const char[] name, bool dontBroadcast)
403{
404 if (nanobot && cvarBotDisabled.BoolValue && NB_NanobotEnabled())
405 {
406 for (int i = 1; i <= MaxClients; i++)
407 {
408 if (IsClientInGame(i) && !IsFakeClient(i))
409 {
410 if (bDialogMessage[i]) SendDialogToOne(i, FindColor("Green"), 10, "[DBS] Stat tracking is disabled.");
411 }
412 }
413 }
414 if (juggernaut && cvarJuggDisabled.BoolValue)
415 {
416 for (int i = 1; i <= MaxClients; i++)
417 {
418 if (GetJuggernautUserId(i) != -1)
419 {
420 for (int x = 1; x <= MaxClients; x++)
421 {
422 if (IsClientInGame(x) && !IsFakeClient(x))
423 {
424 if (bDialogMessage[x]) SendDialogToOne(x, FindColor("Green"), 10, "[DBS] Stat tracking is disabled.");
425 }
426 }
427 }
428 }
429 }
430}
431
432public void OnClientConnected(int client)
433{
434 ResetVariables(client);
435 pRecordSound[client] = true;
436 gRecordSound[client] = true;
437 bDialogMessage[client] = true;
438}
439
440public void OnClientCookiesCached(int client)
441{
442 char info[32];
443 GetClientCookie(client, cPRecordSound, info, sizeof(info));
444 if (StrEqual(info, "0")) pRecordSound[client] = false;
445 GetClientCookie(client, cGRecordSound, info, sizeof(info));
446 if (StrEqual(info, "0")) gRecordSound[client] = false;
447 GetClientCookie(client, cDialogMessage, info, sizeof(info));
448 if (StrEqual(info, "0")) bDialogMessage[client] = false;
449}
450
451public void OnClientDisconnect(int client)
452{
453 ResetVariables(client);
454}
455
456void ResetVariables(int client)
457{
458 playerDeflects[client] = 0;
459 playerSpeed[client] = 0;
460 playerTopSpeed[client] = 0; // BETA
461 playerKills[client] = 0;
462 /*BETA UNCOMMENT
463 gBeatPersonSpeed[client] = false;
464 gRecordPlayerSpeed[client] = 0;
465 if (GetClientUserId(client) == gBeatRecordSpeed) gBeatRecordSpeed = 0;*/
466 if (hTimer[client] != null)
467 {
468 KillTimer(hTimer[client]);
469 hTimer[client] = null;
470 }
471}
472
473int FindColor(const char[] color)
474{
475 for (int i = 0; i < sizeof(g_ColorNames); i++)
476 {
477 if (strcmp(color, g_ColorNames[i], false) == 0)
478 return i;
479 }
480
481 return -1;
482}
483
484void SendDialogToOne(int client, int color, int time, const char[] text, any ...)
485{
486 char message[100];
487 VFormat(message, sizeof(message), text, 4);
488
489 KeyValues kv = new KeyValues("Stuff", "title", message);
490 kv.SetColor("color", g_Colors[color][0], g_Colors[color][1], g_Colors[color][2], 255);
491 kv.SetNum("level", 1);
492 kv.SetNum("time", time);
493
494 CreateDialog(client, kv, DialogType_Msg);
495
496 delete kv;
497}
498
499public Action Cmd_DelStats(int client, int args)
500{
501 if (args < 2)
502 {
503 ReplyToCommand(client, "[SM] Command Usage: !delstats [steamid (replace : with +)] [global/map]");
504 ReplyToCommand(client, "[SM] Exmaple: !delsats STEAM_0+1+6089982 map");
505 return Plugin_Handled;
506 }
507
508 char query[1024], map[64], steamid[32], arg2[24];
509 GetCurrentMap(map, sizeof(map));
510 GetCmdArg(1, steamid, sizeof(steamid));
511 GetCmdArg(2, arg2, sizeof(arg2));
512 ReplaceString(steamid, sizeof(steamid), "+", ":");
513
514 if (StrEqual(arg2, "global"))
515 {
516 Format(query, sizeof(query), "DELETE FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid, map);
517 db.Query(T_DelStats, query, GetClientUserId(client));
518 }
519
520 Format(query, sizeof(query), "DELETE FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
521 db.Query(T_DelStats, query, GetClientUserId(client));
522
523 return Plugin_Handled;
524}
525
526public void T_DelStats(Database hndl, DBResultSet results, const char[] error, any data)
527{
528 int client = 0;
529 if ((client = GetClientOfUserId(data)) == 0) return;
530
531 if (results == null)
532 {
533 LogError("T_DelStats query failed: %s", error);
534 }
535
536 ReplyToCommand(client, "[SM] Stats deleted.");
537}
538
539public Action Cmd_MyRank(int client, int args)
540{
541 if (!IsValidClient(client)) return Plugin_Handled;
542
543 char query[1024], steamid[32];
544 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
545 Format(query, sizeof(query), "SELECT `points`, `rank`, `ranktitle`, `ranktitlehex` FROM `dbstats_season%d_%d` WHERE steamid = '%s'", cvarSeason.IntValue, seasonYear, steamid);
546 db.Query(T_MyRank, query, GetClientUserId(client));
547
548 PlayerStatsMenu(client);
549 return Plugin_Handled;
550}
551
552public Action Cmd_Rank(int client, int args)
553{
554 if (!IsValidClient(client)) return Plugin_Handled;
555
556 if (args == 0)
557 {
558 Cmd_MyRank(client, args);
559 return Plugin_Handled;
560 }
561
562 char arg1[32];
563 GetCmdArg(1, arg1, sizeof(arg1));
564
565 int target = FindTarget(client, arg1, true);
566 if (target == -1)
567 {
568 return Plugin_Handled;
569 }
570
571 PlayerStatsMenu(client, target);
572 return Plugin_Handled;
573}
574
575public void T_MyRank(Database hndl, DBResultSet results, const char[] error, any data)
576{
577 int client = 0;
578 if ((client = GetClientOfUserId(data)) == 0)return;
579
580 if (results == null)
581 {
582 LogError("T_MyRank query failed: %s", error);
583 return;
584 }
585
586 if (results.RowCount == 0)
587 {
588 return;
589 }
590
591 if (!results.FetchRow())
592 {
593 LogError("T_MyRank: Unable to fetch rows.");
594 return;
595 }
596
597 int points, rank;
598 char ranktitle[32];
599 points = results.FetchInt(0);
600 rank = results.FetchInt(1);
601 results.FetchString(2, ranktitle, sizeof(ranktitle));
602
603 if (rank == 0)
604 {
605 CPrintToChatAll("{gold}[DBS] {bisque}%N is {gold}not yet ranked{bisque}!", client);
606 }
607 else
608 {
609 PrintToChatAll("\x07FFD700[DBS] \x07FFE4C4%N is rank \x07FFD700#%d\x07FFE4C4 with \x07FFD700%d\x07FFE4C4 Points and has reached \"%s\"\x07FFE4C4 level.", client, rank, points, ranktitle);
610 }
611}
612
613public void T_SetDescription(Database hndl, DBResultSet results, const char[] error, any data)
614{
615 if (results == null)
616 {
617 LogError("T_SetDescription query failed: %s", error);
618 return;
619 }
620
621 if (results.RowCount == 0)return;
622 if (!results.FetchRow())
623 {
624 LogError("T_SetDescription: Unable to fetch row: %s", error);
625 return;
626 }
627
628 char name[MAX_NAME_LENGTH];
629 int speed = 0;
630 results.FetchString(0, name, sizeof(name));
631 speed = results.FetchInt(1);
632
633 char text[1024];
634 Format(text, sizeof(text), "Top Speed: %dmph By: %s", speed, name);
635 SteamWorks_SetGameDescription(text);
636 if (cvarDebug.BoolValue) LogAction(0, -1, "Description has been set.");
637}
638
639public void OnEntityCreated(int entity, const char[] classname)
640{
641 if (StrEqual(classname, "tf_projectile_rocket") || StrEqual(classname, "tf_projectile_sentryrocket"))
642 {
643 rocketDeflects = 0;
644 if (!tfdb) canTrackSpeed = true;
645 else
646 {
647 //CreateTimer(0.5, Timer_GetTarget);
648 SDKHook(entity, SDKHook_SpawnPost, OnRocketSpawnPost);
649 //g_iOrgOwner = 0;
650 }
651 }
652}
653
654/*public Action Timer_GetTarget(Handle hTimer)
655{
656 g_iTarget = DB_GetRocketTarget();
657 PrintToChatAll("%d", g_iTarget);
658}*/
659
660public void OnRocketSpawnPost(int entity)
661{
662 if (nanobot && cvarBotDisabled.BoolValue && NB_NanobotEnabled()) return;
663 if (juggernaut && cvarJuggDisabled.BoolValue)
664 {
665 for (int i = 1; i <= MaxClients; i++)
666 {
667 if (GetJuggernautUserId(i) != -1)
668 {
669 return;
670 }
671 }
672 }
673 if (!g_bTrack) return;
674 //g_iTarget = DB_GetRocketTarget();
675 //PrintToChatAll("%d", g_iTarget); //debug
676
677 //Get current topspeed BETA
678 char query[1024], map[64];
679 GetCurrentMap(map, sizeof(map));
680 Format(query, sizeof(query), "SELECT MAX(`top_speed`) FROM `dbstats_season%d_%d_mapspeeds` WHERE `map_name` = '%s'", cvarSeason.IntValue, seasonYear, map);
681 db.Query(T_CheckCurrentTopSpeed, query);
682
683 // Get each individual player's personal top speed and store it. BETA
684 for (int i = 1; i <= MaxClients; i++)
685 {
686 if (IsClientInGame(i) && !IsFakeClient(i))
687 {
688 char steamid[32];
689 GetClientAuthId(i, AuthId_Steam2, steamid, sizeof(steamid));
690 //Get top personal record
691 Format(query, sizeof(query), "SELECT `top_speed` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, steamid, map);
692 db.Query(T_CheckStats, query, GetClientUserId(i));
693 }
694 }
695}
696
697public void OnEntityDestroyed(int entity)
698{
699 if (nanobot && cvarBotDisabled.BoolValue && NB_NanobotEnabled()) return;
700 if (juggernaut && cvarJuggDisabled.BoolValue)
701 {
702 for (int i = 1; i <= MaxClients; i++)
703 {
704 if (GetJuggernautUserId(i) != -1)
705 {
706 return;
707 }
708 }
709 }
710 if (!g_bTrack) return;
711
712 if (!IsValidEdict(entity)) return;
713 char classname[35];
714 GetEdictClassname(entity, classname, sizeof(classname));
715 if (StrEqual(classname, "tf_projectile_rocket") || StrEqual(classname, "tf_projectile_sentryrocket"))
716 {
717 //CreateTimer(5.0, Timer_RocketDestroyed); BETA UNCOMMENT
718 //BETA
719 int max = 0;
720 int beatRecordSpeed = 0;
721 // see who has the maximum speed within this rocket life
722 for (int i = 1; i <= MaxClients; i++)
723 {
724 if (IsClientInGame(i) && !IsFakeClient(i))
725 {
726 if (playerSpeed[i] > max)
727 {
728 max = playerSpeed[i];
729 beatRecordSpeed = GetClientUserId(i);
730 }
731 }
732 }
733
734 char query[1024], map[64], steamid[32], name[MAX_NAME_LENGTH];
735 GetCurrentMap(map, sizeof(map));
736
737 // if the maximum speed within this rocket life surpassed the top global record speed, then announce, update db, and update description
738 int client = GetClientOfUserId(beatRecordSpeed);
739 if (max > prevTopSpeed && client != 0 && IsClientInGame(client))
740 {
741 CPrintToChatAll("{gold}[DBS] {bisque}%N has earned a new map record of {gold}%d {bisque}MPH!", client, max);
742 for (int i = 1; i <= MaxClients; i++)
743 {
744 if (IsClientInGame(i) && gRecordSound[i]) ClientCommand(i, "playgamesound \"%s\"", "ui\\mm_xp_chime.wav");
745 }
746
747 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
748 GetClientName(client, name, sizeof(name));
749 int bufferLen = strlen(name) * 2 + 1;
750 char[] newName = new char[bufferLen];
751
752 db.Escape(name, newName, bufferLen);
753
754 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d_mapspeeds` SET `top_speed` = '%d', `player_name` = '%s' WHERE steamid = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, max, newName, steamid, map);
755 db.Query(T_UpdateTopSpeed, query, GetClientUserId(client));
756
757 Format(query, sizeof(query), "Top Speed: %dmph By: %s", max, name);
758 SteamWorks_SetGameDescription(query);
759 if (cvarDebug.BoolValue) LogAction(0, -1, "Description has been set.");
760 }
761 else beatRecordSpeed = 0;
762
763 // if the player surpassed their own personal record speed within this rocket life, then announce & update db
764 for (int i = 1; i <= MaxClients; i++)
765 {
766 if (IsClientInGame(i) && !IsFakeClient(i))
767 {
768
769 if (playerSpeed[i] > playerTopSpeed[i])
770 {
771 if (GetClientUserId(i) == beatRecordSpeed) continue;
772 CPrintToChat(i, "{gold}[DBS] {bisque}You've beaten your personal record with {gold}%d {bisque}MPH!", playerSpeed[i]);
773 if (pRecordSound[i] && beatRecordSpeed == 0) ClientCommand(i, "playgamesound \"%s\"", "ui\\mm_rank_up.wav");
774
775 GetClientAuthId(i, AuthId_Steam2, steamid, sizeof(steamid));
776 GetClientName(i, name, sizeof(name));
777 int bufferLen = strlen(name) * 2 + 1;
778 char[] newName = new char[bufferLen];
779
780 db.Escape(name, newName, bufferLen);
781
782 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d_mapspeeds` SET `top_speed` = '%d', `player_name` = '%s' WHERE steamid = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, playerSpeed[i], newName, steamid, map);
783 db.Query(T_UpdateTopSpeed, query, GetClientUserId(i));
784 }
785 }
786 }
787 }
788}
789
790// BETA UNCOMMENT
791/*public Action Timer_RocketDestroyed(Handle theTimer)
792{
793 if (gBeatRecordSpeed != 0)
794 {
795 int client = GetClientOfUserId(gBeatRecordSpeed);
796 CPrintToChatAll("{gold}[DBS] {bisque}%N has earned a new map record of {gold}%d {bisque}MPH!", client, gRecordPlayerSpeed[client]);
797 for (int i = 1; i <= MaxClients; i++)
798 {
799 if (IsClientInGame(i) && gRecordSound[i]) ClientCommand(i, "playgamesound \"%s\"", "ui\\mm_xp_chime.wav");
800 }
801 }
802
803 for (int i = 1; i <= MaxClients; i++)
804 {
805 if (gBeatPersonSpeed[i])
806 {
807 if (GetClientUserId(i) == gBeatRecordSpeed) continue;
808 CPrintToChat(i, "{gold}[DBS] {bisque}You've beaten your personal record with {gold}%d {bisque}MPH!", gRecordPlayerSpeed[i]);
809 if (pRecordSound[i] && gBeatRecordSpeed == 0) ClientCommand(i, "playgamesound \"%s\"", "ui\\mm_rank_up.wav");
810 }
811 }
812
813 gBeatRecordSpeed = 0;
814 for (int i = 1; i <= MaxClients; i++)
815 {
816 gBeatPersonSpeed[i] = false;
817 gRecordPlayerSpeed[i] = 0;
818 }
819}*/
820
821public void OnGameFrame()
822{
823 int rocket = FindEntityByClassname(-1, "tf_projectile_rocket");
824 if (rocket == -1) rocket = FindEntityByClassname(-1, "tf_projectile_sentryrocket");
825 if (IsValidEntity(rocket))
826 {
827 if (canTrackSpeed && !tfdb)
828 {
829 canTrackSpeed = false;
830 float entityVelocity[3];
831 GetEntPropVector(rocket, Prop_Data, "m_vecAbsVelocity", entityVelocity);
832 int client = GetEntPropEnt(rocket, Prop_Send, "m_hOwnerEntity");
833 playerSpeed[client] = RoundFloat(GetVectorLength(entityVelocity) * (15.0 / 352.0)); //Convert to MPH by multiplying by (15/352)
834 }
835 int rDeflects = GetEntProp(rocket, Prop_Send, "m_iDeflected") - 1;
836 /*if (rDeflects == rocketDeflects)
837 {
838 g_iOrgOwner = GetEntPropEnt(rocket, Prop_Send, "m_hOwnerEntity");
839 if (rDeflects == 0 && rocketDeflects == 0) g_iOrgOwner = 0;
840 }*/
841 if (rDeflects > rocketDeflects)
842 {
843 rocketDeflects++;
844 if (tfdb)
845 {
846 int client = GetEntPropEnt(rocket, Prop_Send, "m_hOwnerEntity");
847 playerSpeed[client] = DB_GetRocketSpeed();
848 }
849 else
850 {
851 canTrackSpeed = true;
852 }
853 OnDeflected(rocket);
854 }
855 }
856}
857
858public void OnClientAuthorized(int client, const char[] auth)
859{
860 if (StrEqual(auth, "BOT") || db == null) return;
861 char query[256], map[64];
862 GetCurrentMap(map, sizeof(map));
863 //Format(query, sizeof(query), "SELECT * FROM `dbstats_season%d_%d` WHERE `steamid` = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, auth, map);
864 Format(query, sizeof(query), "SELECT * FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, auth);
865 db.Query(T_CheckUserExists, query, GetClientUserId(client));
866
867 Format(query, sizeof(query), "SELECT * FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, auth, map);
868 db.Query(T_CheckUserExistsMap, query, GetClientUserId(client));
869}
870
871public void T_CheckUserExists(Database hndl, DBResultSet results, const char[] error, any data)
872{
873 int client = 0;
874 if ((client = GetClientOfUserId(data)) == 0)return;
875
876 if (results == null)
877 {
878 LogError("T_CheckUserExists query failed: %s", error);
879 return;
880 }
881
882 if (results.RowCount == 0)
883 {
884 char query[2024], steamid[32], name[MAX_NAME_LENGTH];
885 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
886
887 GetClientName(client, name, sizeof(name));
888 int bufferLen = strlen(name) * 2 + 1;
889 char[] newName = new char[bufferLen];
890
891 db.Escape(name, newName, bufferLen);
892
893 Format(query, sizeof(query), "INSERT INTO `dbstats_season%d_%d` (player_name, steamid, ranktitle, ranktitlehex, deflects, rank, kills, deaths, time_played, upspikes, downspikes, switches, backshots, steals, points) VALUES ('%s', '%s', 'Unranked', 'FFFFFF', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0')", cvarSeason.IntValue, seasonYear, newName, steamid);
894 db.Query(T_InsertNewUser, query, GetClientUserId(client));
895 }
896}
897
898public void T_CheckUserExistsMap(Database hndl, DBResultSet results, const char[] error, any data)
899{
900 int client = 0;
901 if ((client = GetClientOfUserId(data)) == 0)return;
902
903 if (results == null)
904 {
905 LogError("T_CheckUserExistsMap query failed: %s", error);
906 return;
907 }
908
909 if (results.RowCount == 0)
910 {
911 char query[2024], steamid[32], name[MAX_NAME_LENGTH], map[64];
912 GetCurrentMap(map, sizeof(map));
913 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
914
915 GetClientName(client, name, sizeof(name));
916 int bufferLen = strlen(name) * 2 + 1;
917 char[] newName = new char[bufferLen];
918
919 db.Escape(name, newName, bufferLen);
920
921 Format(query, sizeof(query), "INSERT INTO `dbstats_season%d_%d_mapspeeds` (player_name, map_name, steamid, top_speed) VALUES ('%s', '%s', '%s', '0')", cvarSeason.IntValue, seasonYear, newName, map, steamid);
922 db.Query(T_InsertMapSpeeds, query, GetClientUserId(client));
923 }
924}
925
926public void T_InsertMapSpeeds(Database hndl, DBResultSet results, const char[] error, any data)
927{
928 int client = 0;
929 client = GetClientOfUserId(data);
930 if (client == 0)return;
931
932 if (results == null)
933 {
934 LogError("T_InsertMapSpeeds query failed: %s", error);
935 return;
936 }
937
938 if (cvarDebug.BoolValue) LogAction(0, -1, "Added %N to dbstats_mapspeeds table.", client);
939}
940
941public void OnClientPostAdminCheck(int client)
942{
943 if ((IsClientInGame(client) && IsFakeClient(client)) || db == null) return;
944 char query[1024], steamid[32];
945 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
946
947 Format(query, sizeof(query), "SELECT `ranktitle`, `ranktitlehex` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
948 db.Query(T_GetRankTitle, query, GetClientUserId(client));
949}
950
951public void T_GetRankTitle(Database hndl, DBResultSet results, const char[] error, any data)
952{
953 int client = 0;
954 if ((client = GetClientOfUserId(data)) == 0)return;
955
956 if (results == null)
957 {
958 LogError("T_GetRankTitle query failed: %s", error);
959 return;
960 }
961
962 if (results.RowCount == 0)
963 {
964 LogError("T_GetRankTitle didn't return any rows.");
965 return;
966 }
967
968 if (!results.FetchRow())
969 {
970 LogError("T_GetRankTitle: Couldn't fetch row: %s", error);
971 return;
972 }
973
974 char ranktitle[32];
975 char ranktitlehex[32];
976 char tag[32];
977 results.FetchString(0, ranktitle, sizeof(ranktitle));
978 results.FetchString(1, ranktitlehex, sizeof(ranktitlehex));
979 Format(tag, sizeof(tag), "[%s] ", ranktitle);
980
981 if (ccc)
982 {
983 CCC_SetTag(client, tag);
984 CCC_SetColor(client, CCC_TagColor, StringToInt(ranktitlehex, 16), false);
985 }
986 else
987 {
988 LogMessage("Custom-ChatColors was not detected, therefore ranktitles cannot be set.");
989 }
990}
991
992public void T_InsertNewUser(Database hndl, DBResultSet results, const char[] error, any data)
993{
994 int client = 0;
995 client = GetClientOfUserId(data);
996 if (client == 0)return;
997
998 if (results == null)
999 {
1000 LogError("T_InsertNewUser query failed: %s", error);
1001 return;
1002 }
1003
1004 if (cvarDebug.BoolValue) LogAction(0, -1, "Added %N to dbstats table.", client);
1005}
1006
1007void OnDeflected(int rocket)
1008{
1009 if (nanobot && cvarBotDisabled.BoolValue && NB_NanobotEnabled()) return;
1010 if (juggernaut && cvarJuggDisabled.BoolValue)
1011 {
1012 for (int i = 1; i <= MaxClients; i++)
1013 {
1014 if (GetJuggernautUserId(i) != -1)
1015 {
1016 return;
1017 }
1018 }
1019 }
1020 if (!g_bTrack) return;
1021
1022 int client = GetEntPropEnt(rocket, Prop_Send, "m_hOwnerEntity");
1023 playerDeflects[client]++;
1024 char query[1024], map[64], steamid[32], name[MAX_NAME_LENGTH];
1025 GetCurrentMap(map, sizeof(map));
1026 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1027
1028 //check current top_speed BETA UNCOMMENT
1029 //Format(query, sizeof(query), "SELECT MAX(`top_speed`) FROM `dbstats_season%d_%d_mapspeeds` WHERE `map_name` = '%s'", cvarSeason.IntValue, seasonYear, map);
1030 //db.Query(T_CheckCurrentTopSpeed, query, GetClientUserId(client));
1031 GivePoints(client, 1);
1032
1033 GetClientName(client, name, sizeof(name));
1034 int bufferLen = strlen(name) * 2 + 1;
1035 char[] newName = new char[bufferLen];
1036
1037 db.Escape(name, newName, bufferLen);
1038
1039 // update deflects
1040 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `deflects`=(`deflects`+1), `player_name` = '%s' WHERE steamid = '%s'", cvarSeason.IntValue, seasonYear, newName, steamid);
1041 db.Query(T_UpdateDeflects, query, GetClientUserId(client));
1042
1043 // determine rank title
1044 Format(query, sizeof(query), "SELECT `points`, `ranktitle` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1045 db.Query(T_GetPoints, query, GetClientUserId(client));
1046
1047 float eyeAngles[3];
1048 GetClientEyeAngles(client, eyeAngles);
1049 if (eyeAngles[0] < -40.0 && (GetEntityFlags(client) & FL_ONGROUND))
1050 {
1051 //upspike
1052 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `upspikes`=(`upspikes`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1053 db.Query(T_UpdateUpspikes, query, GetClientUserId(client));
1054 GivePoints(client, 1);
1055 if (bDialogMessage[client]) SendDialogToOne(client, FindColor("Cyan"), 1, "[DBS] You upspiked!");
1056 }
1057
1058 if (eyeAngles[0] > 20.0 && (GetEntityFlags(client) & FL_ONGROUND))
1059 {
1060 //downspike
1061 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `downspikes`=(`downspikes`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1062 db.Query(T_UpdateDownspikes, query, GetClientUserId(client));
1063 GivePoints(client, 1);
1064 if (bDialogMessage[client]) SendDialogToOne(client, FindColor("Cyan"), 1, "[DBS] You downspiked!");
1065 }
1066 /*int oldTarget = g_iTarget;
1067 g_iTarget = DB_GetRocketTarget();
1068 PrintToChatAll("target %d", g_iTarget); //debug
1069 if (oldTarget != 0 && g_iOrgOwner != 0 && g_iOrgOwner != g_iTarget)
1070 {
1071 //switching
1072 //PrintToChatAll("switch"); //debug
1073 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `switches`=(`switches`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1074 db.Query(T_UpdateSwitches, query, GetClientUserId(client));
1075 if (bDialogMessage[client]) SendDialogToOne(client, FindColor("Cyan"), 1, "[DBS] You switched the rocket!");
1076 }*/
1077
1078 /*if (!IsTargetInSightRange(client, g_iTarget))
1079 {
1080 //backshot
1081 //PrintToChatAll("backshot"); //debug
1082 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `backshots`=(`backshots`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1083 db.Query(T_UpdateBackshots, query, GetClientUserId(client));
1084 GivePoints(client, 1);
1085 if (bDialogMessage[client]) SendDialogToOne(client, FindColor("Cyan"), 1, "[DBS] You backshotted!");
1086 }*/
1087
1088 //Give points based on their speed BETA
1089 if (playerSpeed[client] >= 100 && playerSpeed[client] < 150)
1090 {
1091 GivePoints(client, 1);
1092 }
1093 else if (playerSpeed[client] >= 150 && playerSpeed[client] < 200)
1094 {
1095 GivePoints(client, 2);
1096 }
1097 else if (playerSpeed[client] >= 200 && playerSpeed[client] < 250)
1098 {
1099 GivePoints(client, 3);
1100 }
1101 else if (playerSpeed[client] >= 250 && playerSpeed[client] < 300)
1102 {
1103 GivePoints(client, 4);
1104 }
1105 else if (playerSpeed[client] >= 300)
1106 {
1107 GivePoints(client, 5);
1108 }
1109
1110 // Adjust rank variable
1111 Transaction trans = new Transaction();
1112 trans.AddQuery("SET @rownumber = 0;");
1113 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `rank` = (@rownumber:=@rownumber+1) ORDER BY `points` DESC ;", cvarSeason.IntValue, seasonYear);
1114 trans.AddQuery(query);
1115 db.Execute(trans, T_AdjustRanks, T_AdjustRanksError, GetClientUserId(client));
1116}
1117
1118public Action DB_OnRocketSteal(int client)
1119{
1120 char query[1024], steamid[32];
1121 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1122
1123 //PrintToChatAll("steal"); //debug
1124 if (bDialogMessage[client]) SendDialogToOne(client, FindColor("Cyan"), 1, "[DBS] You stole the rocket!");
1125
1126 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `steals`=(`steals`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1127 db.Query(T_UpdateSteals, query, GetClientUserId(client));
1128
1129 return Plugin_Continue;
1130}
1131
1132public void T_GetPoints(Database hndl, DBResultSet results, const char[] error, any data)
1133{
1134 int client = 0;
1135 if ((client = GetClientOfUserId(data)) == 0) return;
1136 if (IsClientInGame(client) && IsFakeClient(client)) return;
1137 char query[1024], steamid[32];
1138 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1139
1140 if (results == null)
1141 {
1142 LogError("T_GetPoints query failed: %s", error);
1143 return;
1144 }
1145
1146 if (!results.FetchRow())
1147 {
1148 LogError("T_GetPoints: No points found.");
1149 return;
1150 }
1151
1152 int points = results.FetchInt(0);
1153 char ranktitle[32];
1154 char newRankTitle[32];
1155 char rankColorHex[32];
1156 results.FetchString(1, ranktitle, sizeof(ranktitle));
1157 if (points == 0)
1158 {
1159 if (!StrEqual(ranktitle, "Unranked"))
1160 {
1161 Format(newRankTitle, sizeof(newRankTitle), "Unranked");
1162 Format(rankColorHex, sizeof(rankColorHex), "000000");
1163 }
1164 }
1165
1166 KeyValues kv = new KeyValues("RankTitles");
1167 kv.ImportFromFile(kvPath);
1168 if (!kv.GotoFirstSubKey())
1169 {
1170 LogError("No ranktitles set in configs/dbstats.cfg");
1171 return;
1172 }
1173
1174 char buffer[64], minRange[32], maxRange[32];
1175 int min, max;
1176 do
1177 {
1178 kv.GetSectionName(buffer, sizeof(buffer));
1179 if (!StrEqual(ranktitle, buffer))
1180 {
1181 kv.GetString("min", minRange, sizeof(minRange));
1182 kv.GetString("max", maxRange, sizeof(maxRange));
1183 min = StringToInt(minRange);
1184 max = StringToInt(maxRange);
1185 if (points >= min && points <= max)
1186 {
1187 Format(newRankTitle, sizeof(newRankTitle), buffer);
1188 kv.GetString("color hex", rankColorHex, sizeof(rankColorHex));
1189 }
1190 }
1191 } while (kv.GotoNextKey());
1192
1193 delete kv;
1194
1195 if (!StrEqual(ranktitle, newRankTitle) && (newRankTitle[0] != '\0'))
1196 {
1197 CPrintToChatAll("{gold}[DBS] {bisque}%N has been leveled up to \"%s\"{bisque}!", client, newRankTitle);
1198 for (int i = 1; i <= MaxClients; i++)
1199 {
1200 if (IsClientInGame(i) && gRecordSound[i]) ClientCommand(i, "playgamesound \"%s\"", "ui\\mm_xp_chime.wav");
1201 }
1202 char tag[32];
1203 Format(tag, sizeof(tag), "[%s] ", newRankTitle);
1204
1205 if (ccc)
1206 {
1207 CCC_SetTag(client, tag);
1208 CCC_SetColor(client, CCC_TagColor, StringToInt(rankColorHex, 16), false);
1209 }
1210 else
1211 {
1212 LogMessage("Custom-ChatColors was not detected, therefore ranktitles cannot be set.");
1213 }
1214
1215 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `ranktitle`='%s' WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, newRankTitle, steamid);
1216 db.Query(T_UpdateRankTitle, query, GetClientUserId(client));
1217
1218 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `ranktitlehex`='%s' WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, rankColorHex, steamid);
1219 db.Query(T_UpdateRankTitleHex, query);
1220 }
1221}
1222
1223public void T_UpdateRankTitle(Database hndl, DBResultSet results, const char[] error, any data)
1224{
1225 int client = 0;
1226 if ((client = GetClientOfUserId(data)) == 0) return;
1227
1228 if (results == null)
1229 {
1230 LogError("T_UpdateRankTitle query failed: %s", error);
1231 return;
1232 }
1233
1234 if (results.RowCount == 0)
1235 {
1236 return;
1237 }
1238
1239 if (cvarDebug.BoolValue) LogAction(0, -1, "%N's ranktitle has been updated.", client);
1240}
1241
1242public void T_UpdateRankTitleHex(Database hndl, DBResultSet results, const char[] error, any data)
1243{
1244 if (results == null)
1245 {
1246 LogError("T_UpdateRankTitleHex query failed: %s", error);
1247 return;
1248 }
1249}
1250
1251void GivePoints(int client, int points)
1252{
1253 char query[1024], steamid[32], map[64];
1254 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1255 GetCurrentMap(map, sizeof(map));
1256
1257 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `points`=(`points`+%d) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, points, steamid);
1258 db.Query(T_GivePoints, query, GetClientUserId(client));
1259}
1260
1261public void T_GivePoints(Database hndl, DBResultSet results, const char[] error, any data)
1262{
1263 int client = 0;
1264 if ((client = GetClientOfUserId(data)) == 0) return;
1265
1266 if (results == null)
1267 {
1268 LogError("T_GivePoints query failed: %s", error);
1269 return;
1270 }
1271
1272 if (results.RowCount == 0)
1273 {
1274 return;
1275 }
1276
1277 if (cvarDebug.BoolValue)
1278 {
1279 char text[64];
1280 Format(text, sizeof(text), "[DBS] %N was given points.", client);
1281 PrintToNano(text);
1282 }
1283}
1284
1285public void T_UpdateUpspikes(Database hndl, DBResultSet results, const char[] error, any data)
1286{
1287 int client = 0;
1288 if ((client = GetClientOfUserId(data)) == 0) return;
1289
1290 if (results == null)
1291 {
1292 LogError("T_UpdateUpspikes query failed: %s", error);
1293 return;
1294 }
1295
1296 if (results.RowCount == 0)
1297 {
1298 return;
1299 }
1300
1301 if (cvarDebug.BoolValue)
1302 {
1303 char text[64];
1304 Format(text, sizeof(text), "[DBS] %N upspiked.", client);
1305 PrintToNano(text);
1306 }
1307}
1308
1309public void T_UpdateSteals(Database hndl, DBResultSet results, const char[] error, any data)
1310{
1311 int client = 0;
1312 if ((client = GetClientOfUserId(data)) == 0) return;
1313
1314 if (results == null)
1315 {
1316 LogError("T_UpdateSteals query failed: %s", error);
1317 return;
1318 }
1319
1320 if (results.RowCount == 0)
1321 {
1322 return;
1323 }
1324
1325 if (cvarDebug.BoolValue)
1326 {
1327 char text[64];
1328 Format(text, sizeof(text), "[DBS] %N stole a rocket.", client);
1329 PrintToNano(text);
1330 }
1331}
1332
1333public void T_UpdateBackshots(Database hndl, DBResultSet results, const char[] error, any data)
1334{
1335 int client = 0;
1336 if ((client = GetClientOfUserId(data)) == 0) return;
1337
1338 if (results == null)
1339 {
1340 LogError("T_UpdateBackshots query failed: %s", error);
1341 return;
1342 }
1343
1344 if (results.RowCount == 0)
1345 {
1346 return;
1347 }
1348
1349 if (cvarDebug.BoolValue)
1350 {
1351 char text[64];
1352 Format(text, sizeof(text), "[DBS] %N did a backshot.", client);
1353 PrintToNano(text);
1354 }
1355}
1356
1357public void T_UpdateSwitches(Database hndl, DBResultSet results, const char[] error, any data)
1358{
1359 int client = 0;
1360 if ((client = GetClientOfUserId(data)) == 0) return;
1361
1362 if (results == null)
1363 {
1364 LogError("T_UpdateSwitches query failed: %s", error);
1365 return;
1366 }
1367
1368 if (results.RowCount == 0)
1369 {
1370 return;
1371 }
1372
1373 if (cvarDebug.BoolValue)
1374 {
1375 char text[64];
1376 Format(text, sizeof(text), "[DBS] %N switched the rocket.", client);
1377 PrintToNano(text);
1378 }
1379}
1380
1381public void T_UpdateDownspikes(Database hndl, DBResultSet results, const char[] error, any data)
1382{
1383 int client = 0;
1384 if ((client = GetClientOfUserId(data)) == 0) return;
1385
1386 if (results == null)
1387 {
1388 LogError("T_UpdateDownspikes query failed: %s", error);
1389 return;
1390 }
1391
1392 if (results.RowCount == 0)
1393 {
1394 return;
1395 }
1396
1397 if (cvarDebug.BoolValue)
1398 {
1399 char text[64];
1400 Format(text, sizeof(text), "[DBS] %N downspiked.", client);
1401 PrintToNano(text);
1402 }
1403}
1404
1405public void T_CheckCurrentTopSpeed(Database hndl, DBResultSet results, const char[] error, any data)
1406{
1407 //BETA UNCOMMENT
1408 //int client = 0;
1409 //if ((client = GetClientOfUserId(data)) == 0) return;
1410
1411 if (results == null)
1412 {
1413 LogError("T_CheckCurrentTopSpeed query failed: %s", error);
1414 return;
1415 }
1416
1417 if (!results.FetchRow())
1418 {
1419 LogError("T_CheckCurrentTopSpeed: Didn't fetch any rows");
1420 return;
1421 }
1422
1423 prevTopSpeed = results.FetchInt(0);
1424
1425 // BETA UNCOMMENT
1426 /*char query[1024], map[64], steamid[32];
1427 GetCurrentMap(map, sizeof(map));
1428 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1429
1430 Format(query, sizeof(query), "SELECT `top_speed` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, steamid, map);
1431 db.Query(T_CheckStats, query, GetClientUserId(client));*/
1432}
1433
1434public void T_CheckStats(Database hndl, DBResultSet results, const char[] error, any data)
1435{
1436 int client = 0;
1437 if ((client = GetClientOfUserId(data)) == 0) return;
1438
1439 if (results == null)
1440 {
1441 LogError("T_CheckStats query failed: %s", error);
1442 return;
1443 }
1444
1445 if (!results.FetchRow())
1446 {
1447 LogError("T_CheckStats: Didn't fetch any rows");
1448 return;
1449 }
1450
1451 /* BETA UNCOMMENT
1452 int top_speed;
1453 //prevTopSpeed = top_speed = results.FetchInt(0);
1454 top_speed = results.FetchInt(0);*/
1455
1456 playerTopSpeed[client] = results.FetchInt(0); //BETA
1457
1458 // BETA UNCOMMENT
1459 /*if (playerSpeed[client] > top_speed)
1460 {
1461 //CPrintToChat(client, "{gold}[DBS] {bisque}You've beaten your personal record with {gold}%d {bisque}MPH!", playerSpeed[client]);
1462 //if (pRecordSound[client]) ClientCommand(client, "playgamesound \"%s\"", "ui\\mm_rank_up.wav");
1463 gBeatPersonSpeed[client] = true;
1464 gRecordPlayerSpeed[client] = playerSpeed[client];
1465
1466 char query[1024], map[64], steamid[32], name[MAX_NAME_LENGTH];
1467 GetCurrentMap(map, sizeof(map));
1468 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1469
1470 GetClientName(client, name, sizeof(name));
1471 int bufferLen = strlen(name) * 2 + 1;
1472 char[] newName = new char[bufferLen];
1473
1474 db.Escape(name, newName, bufferLen);
1475
1476 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d_mapspeeds` SET `top_speed` = '%d', `player_name` = '%s' WHERE steamid = '%s' AND `map_name` = '%s'", cvarSeason.IntValue, seasonYear, playerSpeed[client], newName, steamid, map);
1477 db.Query(T_UpdateTopSpeed, query, GetClientUserId(client));
1478 }*/
1479}
1480
1481public void T_AdjustRanks(Database hndl, any data, int numQueries, Handle[] results, any[] queryData)
1482{
1483 int client = 0;
1484 client = GetClientOfUserId(data);
1485 if (client == 0)return;
1486}
1487
1488//BETA
1489public void T_UpdateTopSpeed(Database hndl, DBResultSet results, const char[] error, any data)
1490{
1491 int client = 0;
1492 if ((client = GetClientOfUserId(data)) == 0) return;
1493
1494 if (results == null)
1495 {
1496 LogError("T_UpdateTopSpeed query failed: %s", error);
1497 return;
1498 }
1499
1500 if (cvarDebug.BoolValue) LogAction(0, -1, "Updated %N's top speed.", client);
1501}
1502
1503//BETA UNCOMMENT
1504/*public void T_UpdateTopSpeed(Database hndl, DBResultSet results, const char[] error, any data)
1505{
1506 int client = 0;
1507 if ((client = GetClientOfUserId(data)) == 0) return;
1508
1509 if (results == null)
1510 {
1511 LogError("T_UpdateTopSpeed query failed: %s", error);
1512 return;
1513 }
1514
1515 if (cvarDebug.BoolValue) LogAction(0, -1, "Updated %N's top speed.", client);
1516
1517 char query[256], map[64], steamid[32];
1518 GetCurrentMap(map, sizeof(map));
1519 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1520 Format(query, sizeof(query), "SELECT MAX(`top_speed`) FROM `dbstats_season%d_%d_mapspeeds` WHERE `map_name` = '%s'", cvarSeason.IntValue, seasonYear, map);
1521 db.Query(T_FetchSpeedRank, query, GetClientUserId(client));
1522}
1523
1524public void T_FetchSpeedRank(Database hndl, DBResultSet results, const char[] error, any data)
1525{
1526 int client = 0;
1527 if ((client = GetClientOfUserId(data)) == 0) return;
1528
1529 if (results == null)
1530 {
1531 LogError("T_FetchSpeedRank query failed: %s", error);
1532 return;
1533 }
1534
1535 if (!results.FetchRow())
1536 {
1537 LogError("T_FetchSpeedRank: Failed to fetch row");
1538 return;
1539 }
1540
1541 int top_speed = results.FetchInt(0);
1542
1543 if (top_speed > prevTopSpeed)
1544 {
1545 //CPrintToChatAll("{gold}[DBS] {bisque}%N has earned a new map record of {gold}%d {bisque}MPH!", client, playerSpeed[client]);
1546 //for (int i = 1; i <= MaxClients; i++)
1547 //{
1548 // if (IsClientInGame(i) && i != client && gRecordSound[i]) ClientCommand(i, "playgamesound \"%s\"", "ui\\mm_xp_chime.wav");
1549 //}
1550 gBeatRecordSpeed = GetClientUserId(client);
1551 if (playerSpeed[client] >= 100 && playerSpeed[client] < 150)
1552 {
1553 GivePoints(client, 1);
1554 }
1555 else if (playerSpeed[client] >= 150 && playerSpeed[client] < 200)
1556 {
1557 GivePoints(client, 2);
1558 }
1559 else if (playerSpeed[client] >= 200 && playerSpeed[client] < 250)
1560 {
1561 GivePoints(client, 3);
1562 }
1563 else if (playerSpeed[client] >= 250 && playerSpeed[client] < 300)
1564 {
1565 GivePoints(client, 4);
1566 }
1567 else if (playerSpeed[client] >= 300)
1568 {
1569 GivePoints(client, 5);
1570 }
1571 char query[256], map[64];
1572 GetCurrentMap(map, sizeof(map));
1573 Format(query, sizeof(query), "SELECT `player_name`, MAX(`top_speed`) FROM `dbstats_season%d_%d_mapspeeds` WHERE `map_name` = '%s'", cvarSeason.IntValue, seasonYear, map);
1574 db.Query(T_SetDescription, query);
1575 }
1576}*/
1577
1578public void T_AdjustRanksError(Database hndl, any data, int numQueries, const char[] error, int failIndex, any[] queryData)
1579{
1580 LogError("T_AdjustRanks query failed: %s", error);
1581}
1582
1583public void T_UpdateDeflects(Database hndl, DBResultSet results, const char[] error, any data)
1584{
1585 int client = 0;
1586 client = GetClientOfUserId(data);
1587 if (client == 0) return;
1588
1589 if (results == null)
1590 {
1591 LogError("T_UpdateDeflects query failed: %s", error);
1592 return;
1593 }
1594}
1595
1596public Action Event_PlayerDeath(Handle event, const char[] name, bool dontBroadcast)
1597{
1598 if (nanobot && cvarBotDisabled.BoolValue && NB_NanobotEnabled()) return;
1599 if (juggernaut && cvarJuggDisabled.BoolValue)
1600 {
1601 for (int i = 1; i <= MaxClients; i++)
1602 {
1603 if (GetJuggernautUserId(i) != -1)
1604 {
1605 return;
1606 }
1607 }
1608 }
1609 if (!g_bTrack) return;
1610
1611 int client = GetClientOfUserId(GetEventInt(event, "userid"));
1612 int attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
1613
1614 char query[1024], steamid[32];
1615
1616 //Manage attacker's kills
1617 if (IsValidClient(attacker))
1618 {
1619 GetClientAuthId(attacker, AuthId_Steam2, steamid, sizeof(steamid));
1620 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `kills`=(`kills`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1621 db.Query(T_UpdateKills, query);
1622 GivePoints(attacker, 1);
1623 }
1624
1625 //Manage dead player's deaths
1626 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1627 Format(query, sizeof(query), "UPDATE `dbstats_season%d_%d` SET `deaths`=(`deaths`+1) WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1628 db.Query(T_UpdateDeaths, query);
1629}
1630
1631public void T_UpdateKills(Database hndl, DBResultSet results, const char[] error, any data)
1632{
1633 if (results == null)
1634 {
1635 LogError("T_UpdateKills query failed: %s", error);
1636 }
1637}
1638
1639public void T_UpdateDeaths(Database hndl, DBResultSet results, const char[] error, any data)
1640{
1641 if (results == null)
1642 {
1643 LogError("T_UpdateDeaths query failed: %s", error);
1644 }
1645}
1646
1647public Action Cmd_Stats(int client, int args)
1648{
1649 PlayerStatsMenu(client);
1650 return Plugin_Handled;
1651}
1652
1653void PlayerStatsMenu(int client, int target = 0)
1654{
1655 char map[64];
1656 GetCurrentMap(map, sizeof(map));
1657 char steamid[32];
1658 if (target == 0) GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1659 else GetClientAuthId(target, AuthId_Steam2, steamid, sizeof(steamid));
1660
1661 char query[3024];
1662 Format(query, sizeof(query), "(SELECT `deflects`, `ranktitle`, `kills`, `deaths`, `time_played`, `rank`, `player_name`, `steamid`, `upspikes`, `downspikes`, `switches`, `backshots`, `steals`, `points` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s') UNION (SELECT `top_speed`, `map_name`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' ORDER BY `top_speed` DESC LIMIT 1) UNION (SELECT `top_speed`, '(dummy for union)' AS `ranktitle`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s')", cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, map);
1663 db.Query(T_PlayerStatsMenu, query, GetClientUserId(client));
1664}
1665
1666void ShowRanks(int client)
1667{
1668 Menu menu = new Menu(ShowRanksHandler, MENU_ACTIONS_ALL);
1669
1670 char text[256];
1671 Format(text, sizeof(text), "╡ Rank Titles ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
1672 menu.SetTitle(text);
1673
1674 KeyValues kv = new KeyValues("RankTitles");
1675 kv.ImportFromFile(kvPath);
1676 if (!kv.GotoFirstSubKey())
1677 {
1678 LogError("No ranktitles set in configs/dbstats.cfg");
1679 return;
1680 }
1681
1682 char title[64], minRange[32], maxRange[32];
1683 do
1684 {
1685 kv.GetSectionName(title, sizeof(title));
1686 kv.GetString("min", minRange, sizeof(minRange));
1687 kv.GetString("max", maxRange, sizeof(maxRange));
1688
1689 Format(text, sizeof(text), "%s ║ %s >> %s", title, minRange, maxRange);
1690 menu.AddItem(title, text);
1691 } while (kv.GotoNextKey());
1692
1693 delete kv;
1694
1695 menu.ExitBackButton = true;
1696 menu.Display(client, 20);
1697}
1698
1699public int ShowRanksHandler(Menu menu, MenuAction action, int client, int param2)
1700{
1701 if (action == MenuAction_Select)
1702 {
1703 char info[64];
1704 menu.GetItem(param2, info, sizeof(info));
1705
1706 char query[1024];
1707 Format(query, sizeof(query), "SELECT `points`, `player_name`, `steamid`, `ranktitle` FROM `dbstats_season%d_%d` WHERE `ranktitle` = '%s' ORDER BY `points` DESC LIMIT 10", cvarSeason.IntValue, seasonYear, info);
1708 db.Query(T_ShowRankTitles, query, GetClientUserId(client));
1709 }
1710 if (action == MenuAction_Cancel)
1711 {
1712 if (param2 == MenuCancel_ExitBack) PlayerStatsMenu(client);
1713 }
1714 if (action == MenuAction_End)
1715 {
1716 delete menu;
1717 }
1718}
1719
1720public void T_ShowRankTitles(Database hndl, DBResultSet results, const char[] error, any data)
1721{
1722 int client = 0;
1723 if ((client = GetClientOfUserId(data)) == 0) return;
1724
1725 if (results == null)
1726 {
1727 LogError("T_ShowRankTitles query failed: %s", error);
1728 return;
1729 }
1730
1731 results.FetchRow();
1732
1733 char name[MAX_NAME_LENGTH], steamid[32], ranktitle[64];
1734 int points;
1735 int rank = 1;
1736
1737 Menu menu = new Menu(ShowRankTitlesHandler, MENU_ACTIONS_ALL);
1738 char text[256];
1739
1740 if (results.RowCount == 0)
1741 {
1742 menu.AddItem("0", "None yet!");
1743 menu.ExitBackButton = true;
1744 menu.Display(client, 20);
1745 return;
1746 }
1747
1748 points = results.FetchInt(0);
1749 results.FetchString(1, name, sizeof(name));
1750 results.FetchString(2, steamid, sizeof(steamid));
1751 results.FetchString(3, ranktitle, sizeof(ranktitle));
1752
1753 Format(text, sizeof(text), "╡ Top %s Players ║ Season %d %d ╞", ranktitle, cvarSeason.IntValue, seasonYear);
1754 menu.SetTitle(text);
1755
1756 char strPoints[24];
1757 IntToString(points, strPoints, sizeof(strPoints));
1758 for (int i = 0; i < sizeof(strPoints); i++)
1759 {
1760 if (!IsCharNumeric(strPoints[i]))
1761 {
1762 switch (i)
1763 {
1764 case 1: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1765 case 2: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1766 case 3: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1767 case 4: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1768 case 5: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1769 case 6: { Format(strPoints, sizeof(strPoints), "%s", strPoints); break; }
1770 }
1771 }
1772 }
1773
1774 char strRank[24];
1775 IntToString(rank, strRank, sizeof(strRank));
1776 for (int i = 0; i < sizeof(strRank); i++)
1777 {
1778 if (!IsCharNumeric(strRank[i]))
1779 {
1780 switch (i)
1781 {
1782 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
1783 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
1784
1785 }
1786 }
1787 }
1788
1789 Format(text, sizeof(text), "%s %s PTS ➝ %s", strRank, strPoints, name);
1790 menu.AddItem(steamid, text);
1791
1792 do
1793 {
1794 if (!results.FetchRow())
1795 {
1796 menu.ExitBackButton = true;
1797 menu.Display(client, 20);
1798 return;
1799 }
1800
1801 rank++;
1802 points = results.FetchInt(0);
1803 results.FetchString(1, name, sizeof(name));
1804 results.FetchString(2, steamid, sizeof(steamid));
1805
1806 IntToString(points, strPoints, sizeof(strPoints));
1807 for (int i = 0; i < sizeof(strPoints); i++)
1808 {
1809 if (!IsCharNumeric(strPoints[i]))
1810 {
1811 switch (i)
1812 {
1813 case 1: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1814 case 2: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1815 case 3: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1816 case 4: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1817 case 5: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1818 case 6: { Format(strPoints, sizeof(strPoints), "%s", strPoints); break; }
1819 }
1820 }
1821 }
1822
1823 IntToString(rank, strRank, sizeof(strRank));
1824 for (int i = 0; i < sizeof(strRank); i++)
1825 {
1826 if (!IsCharNumeric(strRank[i]))
1827 {
1828 switch (i)
1829 {
1830 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
1831 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
1832
1833 }
1834 }
1835 }
1836
1837 Format(text, sizeof(text), "%s %s PTS ➝ %s", strRank, strPoints, name);
1838 menu.AddItem(steamid, text);
1839
1840 } while (results.MoreRows && rank < 10);
1841
1842 menu.ExitBackButton = true;
1843 menu.Display(client, 20);
1844}
1845
1846public int ShowRankTitlesHandler(Menu menu, MenuAction action, int client, int param2)
1847{
1848 if (action == MenuAction_Select)
1849 {
1850 char steamid[32];
1851 menu.GetItem(param2, steamid, sizeof(steamid));
1852 if (!StrEqual(steamid, "0"))
1853 {
1854 char map[64];
1855 GetCurrentMap(map, sizeof(map));
1856 char query[3024];
1857 Format(query, sizeof(query), "(SELECT `deflects`, `ranktitle`, `kills`, `deaths`, `time_played`, `rank`, `player_name`, `steamid`, `upspikes`, `downspikes`, `switches`, `backshots`, `steals`, `points` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s') UNION (SELECT `top_speed`, `map_name`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' ORDER BY `top_speed` DESC LIMIT 1) UNION (SELECT `top_speed`, '(dummy for union)' AS `ranktitle`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s')", cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, map);
1858 db.Query(T_PlayerStatsMenu, query, GetClientUserId(client));
1859 }
1860 }
1861 if (action == MenuAction_Cancel)
1862 {
1863 if (param2 == MenuCancel_ExitBack) ShowRanks(client);
1864 }
1865 if (action == MenuAction_End)
1866 {
1867 delete menu;
1868 }
1869}
1870
1871void ProcessNextMenu(int client)
1872{
1873 char query[1024], steamid[32];
1874 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1875 Format(query, sizeof(query), "SELECT `rank`, `points` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s'", cvarSeason.IntValue, seasonYear, steamid);
1876 db.Query(T_GetRankPoints, query, GetClientUserId(client));
1877}
1878
1879public void T_GetRankPoints(Database hndl, DBResultSet results, const char[] error, any data)
1880{
1881 if (results == null)
1882 {
1883 LogError("T_GetRankPoints query failed: %s", error);
1884 return;
1885 }
1886
1887 if (!results.FetchRow())
1888 {
1889 LogError("T_GetRankPoints query failed: Couldn't fetch any rows...", error);
1890 return;
1891 }
1892
1893 int rank = results.FetchInt(0);
1894 int points = results.FetchInt(1);
1895
1896 char query[256];
1897 Format(query, sizeof(query), "SELECT `rank`, `points`, `player_name`, `steamid` FROM `dbstats_season%d_%d` WHERE `rank` < %d ORDER BY `rank` DESC LIMIT 9", cvarSeason.IntValue, seasonYear, rank);
1898
1899 DataPack pk = new DataPack();
1900 pk.WriteCell(data);
1901 pk.WriteCell(rank);
1902 pk.WriteCell(points);
1903
1904 db.Query(T_GetNextPlayers, query, pk);
1905}
1906
1907public void T_GetNextPlayers(Database hndl, DBResultSet results, const char[] error, any data)
1908{
1909 DataPack pk = view_as<DataPack>(data);
1910 pk.Reset();
1911
1912 int client = 0;
1913 if ((client = GetClientOfUserId(pk.ReadCell())) == 0) return;
1914
1915 if (results == null)
1916 {
1917 LogError("T_GetNextPlayers query failed: %s", error);
1918 return;
1919 }
1920
1921 int rank = pk.ReadCell();
1922 int playerPoints = pk.ReadCell();
1923 delete pk;
1924 int points = playerPoints;
1925 int pointsDiff = points - playerPoints;
1926 char name[MAX_NAME_LENGTH], steamid[32];
1927 GetClientName(client, name, sizeof(name));
1928 GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid));
1929
1930 Menu menu = new Menu(ShowNextPlayersHandler, MENU_ACTIONS_ALL);
1931 char text[256];
1932
1933 Format(text, sizeof(text), "╡ Next Players ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
1934 menu.SetTitle(text);
1935
1936 if (results.RowCount == 0)
1937 {
1938 menu.AddItem("0", "No players ahead of you! :O");
1939 menu.ExitBackButton = true;
1940 menu.Display(client, 20);
1941 return;
1942 }
1943
1944 char strRank[24]; //156
1945 IntToString(rank, strRank, sizeof(strRank));
1946 for (int i = 0; i < sizeof(strRank); i++)
1947 {
1948 if (!IsCharNumeric(strRank[i]))
1949 {
1950 switch (i)
1951 {
1952 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
1953 case 2: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
1954 case 3: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
1955
1956 }
1957 }
1958 }
1959
1960 char strPoints[24];
1961 IntToString(points, strPoints, sizeof(strPoints));
1962 for (int i = 0; i < sizeof(strPoints); i++)
1963 {
1964 if (!IsCharNumeric(strPoints[i]))
1965 {
1966 switch (i)
1967 {
1968 case 1: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1969 case 2: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1970 case 3: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1971 case 4: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
1972 case 5: { Format(strPoints, sizeof(strPoints), "%s", strPoints); break; }
1973 }
1974 }
1975 }
1976
1977 char strPointsDiff[24];
1978 IntToString(pointsDiff, strPointsDiff, sizeof(strPointsDiff));
1979 for (int i = 0; i < sizeof(strPointsDiff); i++)
1980 {
1981 if (!IsCharNumeric(strPointsDiff[i]))
1982 {
1983 switch (i)
1984 {
1985 case 1: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
1986 case 2: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
1987 case 3: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
1988 case 4: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
1989 case 5: { Format(strPointsDiff, sizeof(strPointsDiff), "+%s", strPointsDiff); break; }
1990 }
1991 }
1992 }
1993
1994 Format(text, sizeof(text), "%s %s %s PTS ➝ %s", strRank, strPoints, strPointsDiff, name);
1995 menu.AddItem(steamid, text);
1996
1997 do
1998 {
1999 if (!results.FetchRow())
2000 {
2001 menu.ExitBackButton = true;
2002 menu.Display(client, 20);
2003 return;
2004 }
2005
2006 rank = results.FetchInt(0);
2007 points = results.FetchInt(1);
2008 pointsDiff = points - playerPoints;
2009 results.FetchString(2, name, sizeof(name));
2010 results.FetchString(3, steamid, sizeof(steamid));
2011
2012 IntToString(rank, strRank, sizeof(strRank));
2013 for (int i = 0; i < sizeof(strRank); i++)
2014 {
2015 if (!IsCharNumeric(strRank[i]))
2016 {
2017 switch (i)
2018 {
2019 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2020 case 2: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2021 case 3: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2022
2023 }
2024 }
2025 }
2026
2027 IntToString(points, strPoints, sizeof(strPoints));
2028 for (int i = 0; i < sizeof(strPoints); i++)
2029 {
2030 if (!IsCharNumeric(strPoints[i]))
2031 {
2032 switch (i)
2033 {
2034 case 1: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2035 case 2: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2036 case 3: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2037 case 4: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2038 case 5: { Format(strPoints, sizeof(strPoints), "%s", strPoints); break; }
2039 }
2040 }
2041 }
2042
2043 IntToString(pointsDiff, strPointsDiff, sizeof(strPointsDiff));
2044 for (int i = 0; i < sizeof(strPointsDiff); i++)
2045 {
2046 if (!IsCharNumeric(strPointsDiff[i]))
2047 {
2048 switch (i)
2049 {
2050 case 1: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
2051 case 2: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
2052 case 3: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
2053 case 4: { Format(strPointsDiff, sizeof(strPointsDiff), " +%s", strPointsDiff); break; }
2054 case 5: { Format(strPointsDiff, sizeof(strPointsDiff), "+%s", strPointsDiff); break; }
2055 }
2056 }
2057 }
2058
2059 Format(text, sizeof(text), "%s %s %s PTS ➝ %s", strRank, strPoints, strPointsDiff, name);
2060 menu.AddItem(steamid, text);
2061
2062 } while (results.MoreRows);
2063 menu.ExitBackButton = true;
2064 menu.Display(client, 20);
2065}
2066
2067public int ShowNextPlayersHandler(Menu menu, MenuAction action, int client, int param2)
2068{
2069 if (action == MenuAction_Select)
2070 {
2071 char steamid[32];
2072 menu.GetItem(param2, steamid, sizeof(steamid));
2073 if (!StrEqual(steamid, "0"))
2074 {
2075 char map[64];
2076 GetCurrentMap(map, sizeof(map));
2077 char query[3024];
2078 Format(query, sizeof(query), "(SELECT `deflects`, `ranktitle`, `kills`, `deaths`, `time_played`, `rank`, `player_name`, `steamid`, `upspikes`, `downspikes`, `switches`, `backshots`, `steals`, `points` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s') UNION (SELECT `top_speed`, `map_name`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' ORDER BY `top_speed` DESC LIMIT 1) UNION (SELECT `top_speed`, '(dummy for union)' AS `ranktitle`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s')", cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, map);
2079 db.Query(T_PlayerStatsMenu, query, GetClientUserId(client));
2080 }
2081 }
2082 if (action == MenuAction_Cancel)
2083 {
2084 if (param2 == MenuCancel_ExitBack) PlayerStatsMenu(client);
2085 }
2086 if (action == MenuAction_End)
2087 {
2088 delete menu;
2089 }
2090}
2091
2092void ShowLeaderboards(int client)
2093{
2094 Menu menu = new Menu(ShowLeadersboardsHandler, MENU_ACTIONS_ALL);
2095
2096 char text[256];
2097 Format(text, sizeof(text), "╡ Leaderboards ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2098 menu.SetTitle(text);
2099
2100 menu.AddItem("1", "Top 10 Ranked Players");
2101 menu.AddItem("2", "Top Map Speeds");
2102 menu.AddItem("3", "Top Deflects");
2103 menu.AddItem("4", "Top Upspikes");
2104 menu.AddItem("5", "Top Downspikes");
2105 menu.AddItem("6", "Top Steals");
2106 menu.AddItem("7", "Top Kills");
2107 menu.AddItem("8", "Top Kill/Death Ratios");
2108 menu.ExitBackButton = true;
2109
2110 menu.Display(client, 20);
2111}
2112
2113public int ShowLeadersboardsHandler(Menu menu, MenuAction action, int client, int param2)
2114{
2115 if (action == MenuAction_Select)
2116 {
2117 char info[8];
2118 menu.GetItem(param2, info, sizeof(info));
2119 int value = StringToInt(info);
2120 switch (value)
2121 {
2122 case 1: ShowTopMenu(client);
2123 case 2: ShowTopSpeedMenu(client);
2124 case 3: ShowTopDeflects(client);
2125 case 4: ShowTopUpspikes(client);
2126 case 5: ShowTopDownspikes(client);
2127 case 6: ShowTopSteals(client);
2128 case 7: ShowTopKills(client);
2129 case 8: ShowTopKDR(client);
2130 }
2131 }
2132 if (action == MenuAction_Cancel)
2133 {
2134 if (param2 == MenuCancel_ExitBack) PlayerStatsMenu(client);
2135 }
2136 if (action == MenuAction_End)
2137 {
2138 delete menu;
2139 }
2140}
2141
2142void ShowTopDeflects(int client)
2143{
2144 char query[1024];
2145 Format(query, sizeof(query), "SELECT `deflects`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `deflects` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2146 db.Query(T_ShowTopDeflects, query, GetClientUserId(client));
2147}
2148
2149public void T_ShowTopDeflects(Database hndl, DBResultSet results, const char[] error, any data)
2150{
2151 int client = 0;
2152 if ((client = GetClientOfUserId(data)) == 0) return;
2153
2154 if (results == null)
2155 {
2156 LogError("T_ShowTopDeflects query failed: %s", error);
2157 return;
2158 }
2159
2160 int deflects;
2161 int rank = 0;
2162 char name[MAX_NAME_LENGTH], steamid[32];
2163
2164 if (results.RowCount == 0)
2165 {
2166 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top deflects.");
2167 return;
2168 }
2169
2170 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2171
2172 char text[256];
2173 Format(text, sizeof(text), "╡ Top Deflects ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2174 menu.SetTitle(text);
2175
2176 do
2177 {
2178 rank++;
2179 if (!results.FetchRow())
2180 {
2181 LogError("T_ShowTopDeflects: Failed to fetch row: %s", error);
2182 return;
2183 }
2184
2185 deflects = results.FetchInt(0);
2186 results.FetchString(1, name, sizeof(name));
2187 results.FetchString(2, steamid, sizeof(steamid));
2188
2189 char strDeflects[24];
2190 IntToString(deflects, strDeflects, sizeof(strDeflects));
2191 for (int i = 0; i < sizeof(strDeflects); i++)
2192 {
2193 if (!IsCharNumeric(strDeflects[i]))
2194 {
2195 switch (i)
2196 {
2197 case 1: { Format(strDeflects, sizeof(strDeflects), " %s", strDeflects); break; }
2198 case 2: { Format(strDeflects, sizeof(strDeflects), " %s", strDeflects); break; }
2199 case 3: { Format(strDeflects, sizeof(strDeflects), " %s", strDeflects); break; }
2200 case 4: { Format(strDeflects, sizeof(strDeflects), " %s", strDeflects); break; }
2201 case 5: { Format(strDeflects, sizeof(strDeflects), " %s", strDeflects); break; }
2202 }
2203 }
2204 }
2205
2206 char strRank[24];
2207 IntToString(rank, strRank, sizeof(strRank));
2208 for (int i = 0; i < sizeof(strRank); i++)
2209 {
2210 if (!IsCharNumeric(strRank[i]))
2211 {
2212 switch (i)
2213 {
2214 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2215 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2216
2217 }
2218 }
2219 }
2220
2221 Format(text, sizeof(text), "%s %s deflects ➝ %s", strRank, strDeflects, name);
2222 menu.AddItem(steamid, text);
2223 } while (results.MoreRows && rank < 10);
2224 menu.ExitBackButton = true;
2225 menu.Display(client, 20);
2226}
2227
2228void ShowTopUpspikes(int client)
2229{
2230 char query[1024];
2231 Format(query, sizeof(query), "SELECT `upspikes`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `upspikes` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2232 db.Query(T_ShowTopUpspikes, query, GetClientUserId(client));
2233}
2234
2235public void T_ShowTopUpspikes(Database hndl, DBResultSet results, const char[] error, any data)
2236{
2237 int client = 0;
2238 if ((client = GetClientOfUserId(data)) == 0) return;
2239
2240 if (results == null)
2241 {
2242 LogError("T_ShowTopUpspikes query failed: %s", error);
2243 return;
2244 }
2245
2246 int upspikes;
2247 int rank = 0;
2248 char name[MAX_NAME_LENGTH], steamid[32];
2249
2250 if (results.RowCount == 0)
2251 {
2252 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top upspikes.");
2253 return;
2254 }
2255
2256 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2257
2258 char text[256];
2259 Format(text, sizeof(text), "╡ Top Upspikes ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2260 menu.SetTitle(text);
2261
2262 do
2263 {
2264 rank++;
2265 if (!results.FetchRow())
2266 {
2267 LogError("T_ShowTopUpspikes: Failed to fetch row: %s", error);
2268 return;
2269 }
2270
2271 upspikes = results.FetchInt(0);
2272 results.FetchString(1, name, sizeof(name));
2273 results.FetchString(2, steamid, sizeof(steamid));
2274
2275 char strRecord[24];
2276 IntToString(upspikes, strRecord, sizeof(strRecord));
2277 for (int i = 0; i < sizeof(strRecord); i++)
2278 {
2279 if (!IsCharNumeric(strRecord[i]))
2280 {
2281 switch (i)
2282 {
2283 case 1: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2284 case 2: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2285 case 3: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2286 case 4: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2287 }
2288 }
2289 }
2290
2291 char strRank[24];
2292 IntToString(rank, strRank, sizeof(strRank));
2293 for (int i = 0; i < sizeof(strRank); i++)
2294 {
2295 if (!IsCharNumeric(strRank[i]))
2296 {
2297 switch (i)
2298 {
2299 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2300 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2301
2302 }
2303 }
2304 }
2305
2306 Format(text, sizeof(text), "%s %s upspikes ➝ %s", strRank, strRecord, name);
2307 menu.AddItem(steamid, text);
2308 } while (results.MoreRows && rank < 10);
2309 menu.ExitBackButton = true;
2310 menu.Display(client, 20);
2311}
2312
2313void ShowTopDownspikes(int client)
2314{
2315 char query[1024];
2316 Format(query, sizeof(query), "SELECT `downspikes`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `downspikes` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2317 db.Query(T_ShowTopDownspikes, query, GetClientUserId(client));
2318}
2319
2320public void T_ShowTopDownspikes(Database hndl, DBResultSet results, const char[] error, any data)
2321{
2322 int client = 0;
2323 if ((client = GetClientOfUserId(data)) == 0) return;
2324
2325 if (results == null)
2326 {
2327 LogError("T_ShowTopDownspikes query failed: %s", error);
2328 return;
2329 }
2330
2331 int downspikes;
2332 int rank = 0;
2333 char name[MAX_NAME_LENGTH], steamid[32];
2334
2335 if (results.RowCount == 0)
2336 {
2337 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top downspikes.");
2338 return;
2339 }
2340
2341 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2342
2343 char text[256];
2344 Format(text, sizeof(text), "╡ Top Downspikes ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2345 menu.SetTitle(text);
2346
2347 do
2348 {
2349 rank++;
2350 if (!results.FetchRow())
2351 {
2352 LogError("T_ShowTopDownspikes: Failed to fetch row: %s", error);
2353 return;
2354 }
2355
2356 downspikes = results.FetchInt(0);
2357 results.FetchString(1, name, sizeof(name));
2358 results.FetchString(2, steamid, sizeof(steamid));
2359
2360 char strRecord[24];
2361 IntToString(downspikes, strRecord, sizeof(strRecord));
2362 for (int i = 0; i < sizeof(strRecord); i++)
2363 {
2364 if (!IsCharNumeric(strRecord[i]))
2365 {
2366 switch (i)
2367 {
2368 case 1: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2369 case 2: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2370 case 3: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2371 case 4: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2372 }
2373 }
2374 }
2375
2376 char strRank[24];
2377 IntToString(rank, strRank, sizeof(strRank));
2378 for (int i = 0; i < sizeof(strRank); i++)
2379 {
2380 if (!IsCharNumeric(strRank[i]))
2381 {
2382 switch (i)
2383 {
2384 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2385 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2386
2387 }
2388 }
2389 }
2390
2391 Format(text, sizeof(text), "%s %s downspikes ➝ %s", strRank, strRecord, name);
2392 menu.AddItem(steamid, text);
2393 } while (results.MoreRows && rank < 10);
2394 menu.ExitBackButton = true;
2395 menu.Display(client, 20);
2396}
2397
2398void ShowTopSteals(int client)
2399{
2400 char query[1024];
2401 Format(query, sizeof(query), "SELECT `steals`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `steals` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2402 db.Query(T_ShowTopSteals, query, GetClientUserId(client));
2403}
2404
2405public void T_ShowTopSteals(Database hndl, DBResultSet results, const char[] error, any data)
2406{
2407 int client = 0;
2408 if ((client = GetClientOfUserId(data)) == 0) return;
2409
2410 if (results == null)
2411 {
2412 LogError("T_ShowTopSteals query failed: %s", error);
2413 return;
2414 }
2415
2416 int steals;
2417 int rank = 0;
2418 char name[MAX_NAME_LENGTH], steamid[32];
2419
2420 if (results.RowCount == 0)
2421 {
2422 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top steals.");
2423 return;
2424 }
2425
2426 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2427
2428 char text[256];
2429 Format(text, sizeof(text), "╡ Top Steals ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2430 menu.SetTitle(text);
2431
2432 do
2433 {
2434 rank++;
2435 if (!results.FetchRow())
2436 {
2437 LogError("T_ShowTopSteals: Failed to fetch row: %s", error);
2438 return;
2439 }
2440
2441 steals = results.FetchInt(0);
2442 results.FetchString(1, name, sizeof(name));
2443 results.FetchString(2, steamid, sizeof(steamid));
2444
2445 char strRecord[24];
2446 IntToString(steals, strRecord, sizeof(strRecord));
2447 for (int i = 0; i < sizeof(strRecord); i++)
2448 {
2449 if (!IsCharNumeric(strRecord[i]))
2450 {
2451 switch (i)
2452 {
2453 case 1: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2454 case 2: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2455 case 3: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2456 case 4: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2457 }
2458 }
2459 }
2460
2461 char strRank[24];
2462 IntToString(rank, strRank, sizeof(strRank));
2463 for (int i = 0; i < sizeof(strRank); i++)
2464 {
2465 if (!IsCharNumeric(strRank[i]))
2466 {
2467 switch (i)
2468 {
2469 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2470 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2471
2472 }
2473 }
2474 }
2475
2476 Format(text, sizeof(text), "%s %s steals ➝ %s", strRank, strRecord, name);
2477 menu.AddItem(steamid, text);
2478 } while (results.MoreRows && rank < 10);
2479 menu.ExitBackButton = true;
2480 menu.Display(client, 20);
2481}
2482
2483void ShowTopKills(int client)
2484{
2485 char query[1024];
2486 Format(query, sizeof(query), "SELECT `kills`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `kills` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2487 db.Query(T_ShowTopKills, query, GetClientUserId(client));
2488}
2489
2490public void T_ShowTopKills(Database hndl, DBResultSet results, const char[] error, any data)
2491{
2492 int client = 0;
2493 if ((client = GetClientOfUserId(data)) == 0) return;
2494
2495 if (results == null)
2496 {
2497 LogError("T_ShowTopKills query failed: %s", error);
2498 return;
2499 }
2500
2501 int kills;
2502 int rank = 0;
2503 char name[MAX_NAME_LENGTH], steamid[32];
2504
2505 if (results.RowCount == 0)
2506 {
2507 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top kills.");
2508 return;
2509 }
2510
2511 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2512
2513 char text[256];
2514 Format(text, sizeof(text), "╡ Top Kills ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2515 menu.SetTitle(text);
2516
2517 do
2518 {
2519 rank++;
2520 if (!results.FetchRow())
2521 {
2522 LogError("T_ShowTopKills: Failed to fetch row: %s", error);
2523 return;
2524 }
2525
2526 kills = results.FetchInt(0);
2527 results.FetchString(1, name, sizeof(name));
2528 results.FetchString(2, steamid, sizeof(steamid));
2529
2530 char strRecord[24];
2531 IntToString(kills, strRecord, sizeof(strRecord));
2532 for (int i = 0; i < sizeof(strRecord); i++)
2533 {
2534 if (!IsCharNumeric(strRecord[i]))
2535 {
2536 switch (i)
2537 {
2538 case 1: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2539 case 2: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2540 case 3: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2541 case 4: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2542 }
2543 }
2544 }
2545
2546 char strRank[24];
2547 IntToString(rank, strRank, sizeof(strRank));
2548 for (int i = 0; i < sizeof(strRank); i++)
2549 {
2550 if (!IsCharNumeric(strRank[i]))
2551 {
2552 switch (i)
2553 {
2554 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2555 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2556
2557 }
2558 }
2559 }
2560
2561 Format(text, sizeof(text), "%s %s kills ➝ %s", strRank, strRecord, name);
2562 menu.AddItem(steamid, text);
2563 } while (results.MoreRows && rank < 10);
2564 menu.ExitBackButton = true;
2565 menu.Display(client, 20);
2566}
2567
2568void ShowTopDeaths(int client)
2569{
2570 char query[1024];
2571 Format(query, sizeof(query), "SELECT `deaths`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `deaths` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2572 db.Query(T_ShowTopDeaths, query, GetClientUserId(client));
2573}
2574
2575public void T_ShowTopDeaths(Database hndl, DBResultSet results, const char[] error, any data)
2576{
2577 int client = 0;
2578 if ((client = GetClientOfUserId(data)) == 0) return;
2579
2580 if (results == null)
2581 {
2582 LogError("T_ShowTopDeaths query failed: %s", error);
2583 return;
2584 }
2585
2586 int deaths;
2587 int rank = 0;
2588 char name[MAX_NAME_LENGTH], steamid[32];
2589
2590 if (results.RowCount == 0)
2591 {
2592 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top kills.");
2593 return;
2594 }
2595
2596 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2597
2598 char text[256];
2599 Format(text, sizeof(text), "╡ Top Deaths ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2600 menu.SetTitle(text);
2601
2602 do
2603 {
2604 rank++;
2605 if (!results.FetchRow())
2606 {
2607 LogError("T_ShowTopDeaths: Failed to fetch row: %s", error);
2608 return;
2609 }
2610
2611 deaths = results.FetchInt(0);
2612 results.FetchString(1, name, sizeof(name));
2613 results.FetchString(2, steamid, sizeof(steamid));
2614
2615 char strRecord[24];
2616 IntToString(deaths, strRecord, sizeof(strRecord));
2617 for (int i = 0; i < sizeof(strRecord); i++)
2618 {
2619 if (!IsCharNumeric(strRecord[i]))
2620 {
2621 switch (i)
2622 {
2623 case 1: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2624 case 2: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2625 case 3: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2626 case 4: { Format(strRecord, sizeof(strRecord), " %s", strRecord); break; }
2627 }
2628 }
2629 }
2630
2631 char strRank[24];
2632 IntToString(rank, strRank, sizeof(strRank));
2633 for (int i = 0; i < sizeof(strRank); i++)
2634 {
2635 if (!IsCharNumeric(strRank[i]))
2636 {
2637 switch (i)
2638 {
2639 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2640 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2641
2642 }
2643 }
2644 }
2645
2646 Format(text, sizeof(text), "%s %s deaths ➝ %s", strRank, strRecord, name);
2647 menu.AddItem(steamid, text);
2648 } while (results.MoreRows && rank < 10);
2649 menu.ExitBackButton = true;
2650 menu.Display(client, 20);
2651}
2652
2653void ShowTopKDR(int client)
2654{
2655 char query[1024];
2656 Format(query, sizeof(query), "SELECT `kills`, `deaths`, `player_name`, `steamid` FROM `dbstats_season%d_%d` WHERE `kills` > 100 ORDER BY `kills`/`deaths` DESC LIMIT 10", cvarSeason.IntValue, seasonYear);
2657 db.Query(T_ShowTopKDR, query, GetClientUserId(client));
2658}
2659
2660public void T_ShowTopKDR(Database hndl, DBResultSet results, const char[] error, any data)
2661{
2662 int client = 0;
2663 if ((client = GetClientOfUserId(data)) == 0) return;
2664
2665 if (results == null)
2666 {
2667 LogError("T_ShowTopKDR query failed: %s", error);
2668 return;
2669 }
2670
2671 int kills;
2672 int deaths;
2673 float kdr;
2674 char strRecord[24];
2675 int rank = 0;
2676 char name[MAX_NAME_LENGTH], steamid[32];
2677
2678 if (results.RowCount == 0)
2679 {
2680 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top kill/death ratios.");
2681 return;
2682 }
2683
2684 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2685
2686 char text[256];
2687 Format(text, sizeof(text), "╡ Top Kill/Death Ratios ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2688 menu.SetTitle(text);
2689
2690 do
2691 {
2692 rank++;
2693 if (!results.FetchRow())
2694 {
2695 LogError("T_ShowTopKDR: Failed to fetch row: %s", error);
2696 return;
2697 }
2698
2699 kills = results.FetchInt(0);
2700 deaths = results.FetchInt(1);
2701 kdr = float(kills)/float(deaths);
2702 Format(strRecord, sizeof(strRecord), "%.2f", kdr);
2703 results.FetchString(2, name, sizeof(name));
2704 results.FetchString(3, steamid, sizeof(steamid));
2705
2706 char strRank[24];
2707 IntToString(rank, strRank, sizeof(strRank));
2708 for (int i = 0; i < sizeof(strRank); i++)
2709 {
2710 if (!IsCharNumeric(strRank[i]))
2711 {
2712 switch (i)
2713 {
2714 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2715 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2716
2717 }
2718 }
2719 }
2720
2721 Format(text, sizeof(text), "%s %s K/D Ratio ➝ %s", strRank, strRecord, name);
2722 menu.AddItem(steamid, text);
2723 } while (results.MoreRows && rank < 10);
2724 menu.ExitBackButton = true;
2725 menu.Display(client, 20);
2726}
2727
2728void ShowOnlinePlayers(int client)
2729{
2730 Menu menu = new Menu(ShowOnlinePlayersHandler, MENU_ACTIONS_ALL);
2731
2732 char text[256], name[MAX_NAME_LENGTH], steamid[32];
2733 Format(text, sizeof(text), "╡ Online Players ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2734 menu.SetTitle(text);
2735
2736 int i = 0;
2737 do
2738 {
2739 i++;
2740 if (IsValidClient(i) && IsClientInGame(i) && !IsFakeClient(i))
2741 {
2742 GetClientName(i, name, sizeof(name));
2743 GetClientAuthId(i, AuthId_Steam2, steamid, sizeof(steamid));
2744 menu.AddItem(steamid, name);
2745 }
2746 } while (i <= MaxClients);
2747
2748 menu.ExitBackButton = true;
2749 menu.Display(client, 20);
2750}
2751
2752public int ShowOnlinePlayersHandler(Menu menu, MenuAction action, int client, int param2)
2753{
2754 if (action == MenuAction_Select)
2755 {
2756 char steamid[32];
2757 menu.GetItem(param2, steamid, sizeof(steamid));
2758 char map[64];
2759 GetCurrentMap(map, sizeof(map));
2760 char query[3024];
2761 Format(query, sizeof(query), "(SELECT `deflects`, `ranktitle`, `kills`, `deaths`, `time_played`, `rank`, `player_name`, `steamid`, `upspikes`, `downspikes`, `switches`, `backshots`, `steals`, `points` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s') UNION (SELECT `top_speed`, `map_name`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' ORDER BY `top_speed` DESC LIMIT 1) UNION (SELECT `top_speed`, '(dummy for union)' AS `ranktitle`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s')", cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, map);
2762 db.Query(T_PlayerStatsMenu, query, GetClientUserId(client));
2763 }
2764 if (action == MenuAction_Cancel)
2765 {
2766 if (param2 == MenuCancel_ExitBack) PlayerStatsMenu(client);
2767 }
2768 if (action == MenuAction_End)
2769 {
2770 delete menu;
2771 }
2772}
2773
2774void ShowTopMenu(int client)
2775{
2776 char query[1024];
2777 Format(query, sizeof(query), "SELECT `points`, `rank`, `player_name`, `steamid` FROM `dbstats_season%d_%d` ORDER BY `rank`", cvarSeason.IntValue, seasonYear);
2778 db.Query(T_ShowTopMenu, query, GetClientUserId(client));
2779}
2780
2781public void T_ShowTopMenu(Database hndl, DBResultSet results, const char[] error, any data)
2782{
2783 int client = 0;
2784 if ((client = GetClientOfUserId(data)) == 0) return;
2785
2786 if (results == null)
2787 {
2788 LogError("T_ShowTopMenu query failed: %s", error);
2789 return;
2790 }
2791
2792 int points, rank;
2793 char name[MAX_NAME_LENGTH], steamid[32];
2794
2795 if (results.RowCount == 0)
2796 {
2797 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top 10 players.");
2798 return;
2799 }
2800
2801 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2802
2803 char text[256];
2804 Format(text, sizeof(text), "╡ Top 10 ║ Season %d %d ╞", cvarSeason.IntValue, seasonYear);
2805 menu.SetTitle(text);
2806
2807 do
2808 {
2809 if (!results.FetchRow())
2810 {
2811 LogError("T_ShowTopMenu: Failed to fetch row: %s", error);
2812 return;
2813 }
2814
2815 points = results.FetchInt(0);
2816 rank = results.FetchInt(1);
2817 if (rank == 0) continue;
2818 results.FetchString(2, name, sizeof(name));
2819 results.FetchString(3, steamid, sizeof(steamid));
2820
2821 char strPoints[24];
2822 IntToString(points, strPoints, sizeof(strPoints));
2823 for (int i = 0; i < sizeof(strPoints); i++)
2824 {
2825 if (!IsCharNumeric(strPoints[i]))
2826 {
2827 switch (i)
2828 {
2829 case 1: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2830 case 2: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2831 case 3: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2832 case 4: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2833 case 5: { Format(strPoints, sizeof(strPoints), " %s", strPoints); break; }
2834 case 6: { Format(strPoints, sizeof(strPoints), "%s", strPoints); break; }
2835 }
2836 }
2837 }
2838
2839 char strRank[24];
2840 IntToString(rank, strRank, sizeof(strRank));
2841 for (int i = 0; i < sizeof(strRank); i++)
2842 {
2843 if (!IsCharNumeric(strRank[i]))
2844 {
2845 switch (i)
2846 {
2847 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2848 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2849
2850 }
2851 }
2852 }
2853
2854 Format(text, sizeof(text), "%s %s PTS ➝ %s", strRank, strPoints, name);
2855 menu.AddItem(steamid, text);
2856
2857 } while (results.MoreRows && rank < 10);
2858
2859 menu.ExitBackButton = true;
2860 menu.Display(client, 20);
2861}
2862
2863void ShowTopSpeedMenu(int client)
2864{
2865 char query[1024], map[64];
2866 GetCurrentMap(map, sizeof(map));
2867 Format(query, sizeof(query), "SELECT `player_name`, `top_speed`, `steamid` FROM `dbstats_season%d_%d_mapspeeds` WHERE `map_name` = '%s' ORDER BY `top_speed` DESC", cvarSeason.IntValue, seasonYear, map);
2868 db.Query(T_ShowTopSpeedMenu, query, GetClientUserId(client));
2869}
2870
2871public void T_ShowTopSpeedMenu(Database hndl, DBResultSet results, const char[] error, any data)
2872{
2873 int client = 0;
2874 if ((client = GetClientOfUserId(data)) == 0) return;
2875
2876 if (results == null)
2877 {
2878 LogError("T_ShowTopSpeedMenu query failed: %s", error);
2879 return;
2880 }
2881
2882 if (results.RowCount == 0)
2883 {
2884 CReplyToCommand(client, "{gold}[DBS] {bisque}There are no top 10 speed records for this map.");
2885 return;
2886 }
2887
2888 int top_speed;
2889 int rank = 0;
2890 char name[MAX_NAME_LENGTH], steamid[32], map[64];
2891
2892 GetCurrentMap(map, sizeof(map));
2893
2894 Menu menu = new Menu(ShowTopMenuHandler, MENU_ACTIONS_ALL);
2895
2896 char text[256];
2897 Format(text, sizeof(text), "╡ Top 10 Map Speeds ║ %s ║ Season %d %d ╞", map, cvarSeason.IntValue, seasonYear);
2898 menu.SetTitle(text);
2899
2900 do
2901 {
2902 rank++;
2903 if (!results.FetchRow())
2904 {
2905 LogError("T_ShowTopSpeedMenu: Failed to fetch row: %s", error);
2906 return;
2907 }
2908
2909 results.FetchString(0, name, sizeof(name));
2910 top_speed = results.FetchInt(1);
2911 results.FetchString(2, steamid, sizeof(steamid));
2912
2913 char strSpeed[24];
2914 IntToString(top_speed, strSpeed, sizeof(strSpeed));
2915 for (int i = 0; i < sizeof(strSpeed); i++)
2916 {
2917 if (!IsCharNumeric(strSpeed[i]))
2918 {
2919 switch (i)
2920 {
2921 case 1: { Format(strSpeed, sizeof(strSpeed), " %s", strSpeed); break; }
2922 case 2: { Format(strSpeed, sizeof(strSpeed), " %s", strSpeed); break; }
2923 case 3: { Format(strSpeed, sizeof(strSpeed), " %s", strSpeed); break; }
2924 case 4: { Format(strSpeed, sizeof(strSpeed), "%s", strSpeed); break; }
2925 }
2926 }
2927 }
2928
2929 char strRank[24];
2930 IntToString(rank, strRank, sizeof(strRank));
2931 for (int i = 0; i < sizeof(strRank); i++)
2932 {
2933 if (!IsCharNumeric(strRank[i]))
2934 {
2935 switch (i)
2936 {
2937 case 1: { Format(strRank, sizeof(strRank), " #%s", strRank); break; }
2938 case 2: { Format(strRank, sizeof(strRank), "#%s", strRank); break; }
2939
2940 }
2941 }
2942 }
2943
2944 Format(text, sizeof(text), "%s %s MPH ➝ %s", strRank, strSpeed, name);
2945 menu.AddItem(steamid, text);
2946
2947 } while (results.MoreRows && rank < 10);
2948
2949 menu.ExitBackButton = true;
2950 menu.Display(client, 20);
2951}
2952
2953public int ShowTopMenuHandler(Menu menu, MenuAction action, int client, int param2)
2954{
2955 if (action == MenuAction_Select)
2956 {
2957 char steamid[32];
2958 menu.GetItem(param2, steamid, sizeof(steamid));
2959 char map[64];
2960 GetCurrentMap(map, sizeof(map));
2961 char query[3024];
2962 Format(query, sizeof(query), "(SELECT `deflects`, `ranktitle`, `kills`, `deaths`, `time_played`, `rank`, `player_name`, `steamid`, `upspikes`, `downspikes`, `switches`, `backshots`, `steals`, `points` FROM `dbstats_season%d_%d` WHERE `steamid` = '%s') UNION (SELECT `top_speed`, `map_name`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' ORDER BY `top_speed` DESC LIMIT 1) UNION (SELECT `top_speed`, '(dummy for union)' AS `ranktitle`, '(dummy for union)' AS `kills`, '(dummy for union)' AS `deaths`, '(dummy for union)' AS `time_played`, '(dummy for union)' AS `rank`, '(dummy for union)' AS `player_name`, '(dummy for union)' AS `steamid`, '(dummy for union)' AS `upspikes`, '(dummy for union)' AS `downspikes`, '(dummy for union)' AS `switches`, '(dummy for union)' AS `backshots`, '(dummy for union)' AS `steals`, '(dummy for union)' AS `points` FROM `dbstats_season%d_%d_mapspeeds` WHERE `steamid` = '%s' AND `map_name` = '%s')", cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, cvarSeason.IntValue, seasonYear, steamid, map);
2963 db.Query(T_PlayerStatsMenu, query, GetClientUserId(client));
2964 }
2965 if (action == MenuAction_Cancel)
2966 {
2967 if (param2 == MenuCancel_ExitBack) ShowLeaderboards(client);
2968 }
2969 if (action == MenuAction_End)
2970 {
2971 delete menu;
2972 }
2973}
2974
2975public void T_PlayerStatsMenu(Database hndl, DBResultSet results, const char[] error, any data)
2976{
2977 int client = 0;
2978 if ((client = GetClientOfUserId(data)) == 0) return;
2979
2980 if (results == null)
2981 {
2982 LogError("Getting stats query failed: %s", error);
2983 return;
2984 }
2985
2986 int deflects, time_played, rank, speed, kills, deaths, upspikes, downspikes, /*switches, backshots, */steals, points, gSpeed;
2987 char name[MAX_NAME_LENGTH], steamid[32], kdrString[32], ranktitle[32], gMap[64];
2988 if (results.RowCount == 0)
2989 {
2990 deflects = 0;
2991 speed = 0;
2992 gSpeed = 0;
2993 rank = 0;
2994 }
2995 else
2996 {
2997 if (!results.FetchRow())
2998 {
2999 LogError("T_PlayerStatsMenu: Didn't fetch any rows");
3000 return;
3001 }
3002 //`deflects`, `ranktitle`, `kills`, `deaths`, `time_played`, `rank`, `player_name`, `steamid`, `upspikes`, `downspikes`, `switches`, `backshots`, `steals`, `points`
3003 deflects = results.FetchInt(0);
3004 results.FetchString(1, ranktitle, sizeof(ranktitle));
3005 kills = results.FetchInt(2);
3006 deaths = results.FetchInt(3);
3007 time_played = results.FetchInt(4);
3008 rank = results.FetchInt(5);
3009 results.FetchString(6, name, sizeof(name));
3010 results.FetchString(7, steamid, sizeof(steamid));
3011 upspikes = results.FetchInt(8);
3012 downspikes = results.FetchInt(9);
3013 //switches = results.FetchInt(10);
3014 //backshots = results.FetchInt(11);
3015 steals = results.FetchInt(12);
3016 points = results.FetchInt(13);
3017
3018 if (results.FetchRow())
3019 {
3020 gSpeed = results.FetchInt(0);
3021 results.FetchString(1, gMap, sizeof(gMap));
3022 }
3023 else
3024 {
3025 gSpeed = 0;
3026 Format(gMap, sizeof(gMap), "null");
3027 }
3028
3029 if (results.FetchRow())
3030 {
3031 speed = results.FetchInt(0);
3032 }
3033 else
3034 {
3035 speed = 0;
3036 }
3037 }
3038
3039 char map[64];
3040 GetCurrentMap(map, sizeof(map));
3041
3042 Panel panel = new Panel();
3043
3044 char text[2024];
3045 Format(text, sizeof(text), "╡ %s's Stats ║ Season %d %d ╞", name, cvarSeason.IntValue, seasonYear);
3046 panel.SetTitle(text);
3047
3048 panel.DrawText(" ");
3049 Format(text, sizeof(text), " ▶ Rank: #%d and is \"%s\"", rank, ranktitle);
3050 panel.DrawText(text);
3051 Format(text, sizeof(text), " ▶ Points: %d", points);
3052 panel.DrawText(text);
3053 panel.DrawText(" ");
3054
3055 float hours = float(time_played)/60.0;
3056 Format(text, sizeof(text), " ➝ Time Played: %.2f hrs", hours);
3057 panel.DrawText(text);
3058 Format(text, sizeof(text), " ➝ Deflects: %d", deflects);
3059 panel.DrawText(text);
3060 Format(text, sizeof(text), " ➝ Upspikes: %d", upspikes);
3061 panel.DrawText(text);
3062 Format(text, sizeof(text), " ➝ Downspikes: %d", downspikes);
3063 panel.DrawText(text);
3064 Format(text, sizeof(text), " ➝ Steals: %d", steals);
3065 panel.DrawText(text);
3066 Format(text, sizeof(text), " ➝ Kills: %d", kills);
3067 panel.DrawText(text);
3068 Format(text, sizeof(text), " ➝ Deaths: %d", deaths);
3069 panel.DrawText(text);
3070
3071 float kdr = float(kills)/float(deaths);
3072 Format(kdrString, sizeof(kdrString), "%.2f", kdr);
3073 Format(text, sizeof(text), " ➝ K/D Ratio: %s", kdrString);
3074 panel.DrawText(text);
3075 panel.DrawText(" ");
3076
3077 Format(text, sizeof(text), " Top Global Speed: %d MPH (%s)", gSpeed, gMap);
3078 panel.DrawText(text);
3079 Format(text, sizeof(text), " Top Map Speed: %d MPH (%s)", speed, map);
3080 panel.DrawText(text);
3081 panel.DrawText(" ");
3082
3083 if (CheckCommandAccess(client, "sm_dbstats_override", ADMFLAG_GENERIC, true))
3084 {
3085 Format(text, sizeof(text), " %s", steamid);
3086 panel.DrawText(text);
3087 }
3088
3089 panel.DrawItem("View Leaderboards", ITEMDRAW_CONTROL);
3090 panel.DrawItem("View Online Players", ITEMDRAW_CONTROL);
3091 panel.DrawItem("View Rank Legend", ITEMDRAW_CONTROL);
3092 panel.DrawItem("View Next Players", ITEMDRAW_CONTROL);
3093 panel.DrawItem("", ITEMDRAW_NOTEXT);
3094 panel.DrawItem("", ITEMDRAW_NOTEXT);
3095 panel.DrawItem("", ITEMDRAW_NOTEXT);
3096 panel.DrawItem("", ITEMDRAW_NOTEXT);
3097 panel.DrawItem("", ITEMDRAW_NOTEXT);
3098 panel.DrawItem("Exit", ITEMDRAW_CONTROL);
3099
3100 panel.Send(client, PanelHandler, 20);
3101
3102 delete panel;
3103}
3104
3105public int PanelHandler(Menu menu, MenuAction action, int client, int param2)
3106{
3107 if (action == MenuAction_Select)
3108 {
3109 switch (param2)
3110 {
3111 case 1:
3112 {
3113 ClientCommand(client, "playgamesound \"%s\"", "ui\\menu_focus.wav");
3114 ShowLeaderboards(client);
3115 }
3116 case 2:
3117 {
3118 ClientCommand(client, "playgamesound \"%s\"", "ui\\menu_focus.wav");
3119 ShowOnlinePlayers(client);
3120 }
3121 case 3:
3122 {
3123 ClientCommand(client, "playgamesound \"%s\"", "ui\\menu_focus.wav");
3124 ShowRanks(client);
3125 }
3126 case 4:
3127 {
3128 ClientCommand(client, "playgamesound \"%s\"", "ui\\menu_focus.wav");
3129 ProcessNextMenu(client);
3130 }
3131 default: ClientCommand(client, "playgamesound \"%s\"", "ui\\panel_close.wav");
3132 }
3133 }
3134}
3135
3136void StartSQL()
3137{
3138 Database.Connect(GotDatabase);
3139}
3140
3141public void GotDatabase(Database newDB, const char[] error, any data)
3142{
3143 if (newDB == null) LogError("Failed to connect to database: %s", error);
3144 else
3145 {
3146 db = newDB;
3147 LogAction(0, -1, "Connection to databse established.");
3148 SetupDB();
3149 char query[256], map[64];
3150 GetCurrentMap(map, sizeof(map));
3151 Format(query, sizeof(query), "SELECT `player_name`, MAX(`top_speed`) FROM `dbstats_season%d_%d_mapspeeds` WHERE `map_name` = '%s'", cvarSeason.IntValue, seasonYear, map);
3152 db.Query(T_SetDescription, query);
3153 }
3154}
3155
3156void SetupDB()
3157{
3158 char query[1024];
3159 Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `dbstats_season%d_%d` (id int NOT NULL AUTO_INCREMENT, player_name varchar(32) NOT NULL, steamid varchar(32) NOT NULL, ranktitle varchar(32), ranktitlehex varchar(32), deflects int, kills int, upspikes int, downspikes int, switches int, backshots int, steals int, deaths int, time_played int, rank int, points int, PRIMARY KEY (id));", cvarSeason.IntValue, seasonYear);
3160 if (!SQL_FastQuery(db, query, sizeof(query)))
3161 {
3162 char errors[1024];
3163 SQL_GetError(db, errors, sizeof(errors));
3164 LogError("Unable to create dbstats_season%d_%d table: %s", cvarSeason.IntValue, seasonYear, errors);
3165 return;
3166 }
3167
3168 Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `dbstats_season%d_%d_mapspeeds` (id int NOT NULL AUTO_INCREMENT, player_name varchar(32) NOT NULL, steamid varchar(32) NOT NULL, map_name varchar(32) NOT NULL, top_speed int, PRIMARY KEY (id));", cvarSeason.IntValue, seasonYear);
3169 if (!SQL_FastQuery(db, query, sizeof(query)))
3170 {
3171 char errors[1024];
3172 SQL_GetError(db, errors, sizeof(errors));
3173 LogError("Unable to create dbstats_season%d_%d_mapspeeds table: %s", cvarSeason.IntValue, seasonYear, errors);
3174 return;
3175 }
3176}
3177
3178stock void PrintToNano(char[] msg)
3179{
3180 /*char authid[32];
3181 for (int i = 1; i <= MaxClients; i++)
3182 {
3183 if (!IsValidClient(i))continue;
3184 GetClientAuthId(i, AuthId_Steam2, authid, sizeof(authid));
3185 if (StrEqual(authid, "STEAM_0:1:40991361"))
3186 {
3187 PrintToChat(i, msg);
3188 return;
3189 }
3190 }*/
3191 PrintToChatAll(msg);
3192}
3193
3194stock bool IsValidClient(int client)
3195{
3196 if (!(1 <= client <= MaxClients) || !IsClientInGame(client))
3197 return false;
3198 return true;
3199}
3200
3201stock bool:IsTargetInSightRange(client, target, Float:angle=90.0, Float:distance=0.0, bool:heightcheck=true, bool:negativeangle=false)
3202{
3203 if(angle > 360.0 || angle < 0.0)
3204 ThrowError("Angle Max : 360 & Min : 0. %d isn't proper angle.", angle);
3205 if(!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
3206 ThrowError("Client is not Alive.");
3207 if(!IsClientConnected(target) || !IsClientInGame(target) || !IsPlayerAlive(target))
3208 ThrowError("Target is not Alive.");
3209
3210 decl Float:clientpos[3], Float:targetpos[3], Float:anglevector[3], Float:targetvector[3], Float:resultangle, Float:resultdistance;
3211
3212 GetClientEyeAngles(client, anglevector);
3213 anglevector[0] = anglevector[2] = 0.0;
3214 GetAngleVectors(anglevector, anglevector, NULL_VECTOR, NULL_VECTOR);
3215 NormalizeVector(anglevector, anglevector);
3216 if(negativeangle)
3217 NegateVector(anglevector);
3218
3219 GetClientAbsOrigin(client, clientpos);
3220 GetClientAbsOrigin(target, targetpos);
3221 if(heightcheck && distance > 0)
3222 resultdistance = GetVectorDistance(clientpos, targetpos);
3223 clientpos[2] = targetpos[2] = 0.0;
3224 MakeVectorFromPoints(clientpos, targetpos, targetvector);
3225 NormalizeVector(targetvector, targetvector);
3226
3227 resultangle = RadToDeg(ArcCosine(GetVectorDotProduct(targetvector, anglevector)));
3228
3229 if(resultangle <= angle/2)
3230 {
3231 if(distance > 0)
3232 {
3233 if(!heightcheck)
3234 resultdistance = GetVectorDistance(clientpos, targetpos);
3235 if(distance >= resultdistance)
3236 return true;
3237 else
3238 return false;
3239 }
3240 else
3241 return true;
3242 }
3243 else
3244 return false;
3245}