· 5 years ago · Mar 25, 2020, 03:32 AM
1#pragma semicolon 1
2
3#define PLUGIN_AUTHOR "DeadSworn"
4#define PLUGIN_VERSION "1.2"
5
6#include <sourcemod>
7#include <clients>
8#include <dbi>
9#include <morecolors>
10
11#pragma newdecls required
12
13public Plugin myinfo =
14{
15 name = "Top Speed",
16 author = PLUGIN_AUTHOR,
17 description = "Records top speeds for dodgeball",
18 version = PLUGIN_VERSION,
19 url = ""
20};
21
22Menu g_MenuTop = null;
23
24Handle g_hCvarServerChatTag;
25Handle g_hCvarMainChatColor;
26Handle g_hCvarKeywordChatColor;
27Handle g_hCvarClientChatColor;
28
29char gMainChatColor[256];
30char gKeywordChatColor[256];
31char gClientChatColor[256];
32
33ConVar g_CVPopMax;
34int g_iPopMax;
35
36ConVar g_CVMPH;
37bool g_bDisplayMph;
38
39ConVar g_CVAllowBots;
40bool g_bAllowBots;
41
42
43Database g_Database;
44DBStatement g_DBSMenuTop = null;
45
46int PlayerSpeeds[MAXPLAYERS];
47
48char gPluginTag[256] = "\x07900c3f[\x01TopSpeed\x07900c3f]\x01";
49char gPluginCleanTag[] = "[TopSpeed]";
50
51public void OnPluginStart() {
52 if(!SQL_CheckConfig("top_speed")) {
53 LogError("%s Invalid database config", gPluginCleanTag);
54 }
55
56 char error[255];
57 g_Database = SQL_Connect("top_speed", true, error, sizeof(error));
58
59 if(g_Database == null) {
60 LogError("%s Could not connect: %s", gPluginCleanTag, error);
61 }
62
63 SQL_CreateTable();
64
65 (g_CVPopMax = CreateConVar("sm_topspeed_population_max", "10", "Amount of players shown on the menu", _, true, 0.0)).AddChangeHook(OnConVarChanged);
66 g_iPopMax = GetConVarInt(g_CVPopMax);
67
68 (g_CVMPH = CreateConVar("sm_topspeed_mph", "1", "Display in MPH", _, true, 0.0, true, 1.0)).AddChangeHook(OnConVarChanged);
69 g_bDisplayMph = GetConVarBool(g_CVMPH);
70
71 (g_CVAllowBots = CreateConVar("sm_topspeed_allowbots", "0", "Allow top speeds against bots to be recorded", _, true, 0.0, true, 1.0)).AddChangeHook(OnConVarChanged);
72 g_bAllowBots = GetConVarBool(g_CVAllowBots);
73 g_hCvarServerChatTag = CreateConVar("tf_dodgeball_servertag", "{DARKOLIVEGREEN}[TFDB]", "Tag that appears at the start of each chat announcement.", FCVAR_PROTECTED);
74 g_hCvarMainChatColor = CreateConVar("tf_dodgeball_maincolor", "{WHITE}", "Color assigned to the majority of the words in chat announcements.");
75 g_hCvarKeywordChatColor = CreateConVar("tf_dodgeball_keywordcolor", "{DARKOLIVEGREEN}", "Color assigned to the most important words in chat announcements.", FCVAR_PROTECTED);
76 g_hCvarClientChatColor = CreateConVar("tf_dodgeball_clientwordcolor", "{ORANGE}", "Color assigned to the client in chat announcements.", FCVAR_PROTECTED);
77
78 GetConVarString(g_hCvarServerChatTag, gPluginTag, sizeof(gPluginTag));
79 GetConVarString(g_hCvarMainChatColor, gMainChatColor, sizeof(gMainChatColor));
80 GetConVarString(g_hCvarKeywordChatColor, gKeywordChatColor, sizeof(gKeywordChatColor));
81 GetConVarString(g_hCvarClientChatColor, gClientChatColor, sizeof(gClientChatColor));
82
83 // reg menu commands
84 RegAdminCmd("sm_topspeedlog", Command_LogSpeed, ADMFLAG_ROOT);
85 RegConsoleCmd("sm_tc", Command_PersonalTopSpeed, "Get personal top speed");
86 RegConsoleCmd("sm_ts", Command_TopSpeed, "Get Top Speeds");
87
88 AutoExecConfig(true, "tf2_TopSpeed");
89 GetPlayersData();
90}
91
92// Hooks
93public void OnMapStart() {
94 GetTopSpeeds();
95}
96
97
98public void OnMapEnd() {
99 delete g_MenuTop;
100}
101
102public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
103 g_iPopMax = GetConVarInt(g_CVPopMax);
104 g_bDisplayMph = GetConVarBool(g_CVMPH);
105 g_bAllowBots = GetConVarBool(g_CVAllowBots);
106}
107
108/* on player join get data? */
109public void OnClientPostAdminCheck(int client) {
110 if(!IsValidClient(client)) {
111 return;
112 }
113
114 char auth[32];
115 GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth));
116
117 // define query
118 char query[512];
119 Format(query, sizeof(query), "SELECT `top_speed` FROM `ts_players` WHERE `steam_id` = '%s'", auth);
120
121 // query
122 DBResultSet data = SQL_Query(g_Database, query);
123
124 char error[255];
125 if(SQL_GetError(g_Database, error, sizeof(error))) {
126 LogError("%s Error getting player data: %s", gPluginCleanTag, error);
127 }
128
129 char buffer[MAX_NAME_LENGTH];
130 GetClientName(client, buffer, sizeof(buffer));
131
132 char escaped_username[MAX_NAME_LENGTH*2+1];
133 SQL_EscapeString(g_Database, buffer, escaped_username, sizeof(escaped_username));
134
135 bool GotData = SQL_FetchRow(data);
136 if(data.RowCount == 0) {
137 SQL_FastQuery(g_Database, "SET NAMES \'utf8\'");
138 Format(query, sizeof(query), "INSERT INTO `ts_players` (`steam_id`, `username`) VALUES ('%s', '%s')", auth, escaped_username);
139 SQL_FastQuery(g_Database, query);
140 }
141
142 if(GotData) {
143 PlayerSpeeds[client] = SQL_FetchInt(data, 0);
144 }
145
146 CloseHandle(data);
147}
148
149public void OnClientDisconnect(int client) {
150 PlayerSpeeds[client] = 0;
151}
152
153public Action Command_LogSpeed(int server, int args) {
154 if(server != 0 ) {
155 return Plugin_Handled;
156 }
157
158 char buffer[32];
159 int client;
160 int rocket_target;
161 int speed;
162
163 GetCmdArg(1, buffer, sizeof(buffer));
164 client = StringToInt(buffer);
165
166 GetCmdArg(2, buffer, sizeof(buffer));
167 rocket_target = StringToInt(buffer);
168
169 if(!IsValidClient(client)) {
170 return Plugin_Handled;
171 }
172
173 if(!IsValidClient(rocket_target, g_bAllowBots)) {
174 return Plugin_Handled;
175 }
176
177
178 GetCmdArg(3, buffer, sizeof(buffer));
179 speed = RoundFloat(StringToFloat(buffer));
180
181 if(speed <= PlayerSpeeds[client]) {
182 return Plugin_Handled;
183 } else {
184 PlayerSpeeds[client] = speed;
185 }
186
187 char auth[32];
188 GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth));
189
190 char query[512];
191 Format(query, sizeof(query), "UPDATE `ts_players` SET `top_speed` = '%d' WHERE `steam_id` = '%s' AND '%d' > `top_speed`", speed, auth, speed);
192 bool success = SQL_FastQuery(g_Database, query);
193
194 return Plugin_Handled;
195}
196
197// Commands
198public Action Command_PersonalTopSpeed(int client, int args) {
199 if(g_bDisplayMph) {
200 CPrintToChat(client, "%s %sPersonal top speed: %s%d%s mph!", gPluginTag, gMainChatColor, gKeywordChatColor, HammerToMPH(PlayerSpeeds[client]), gMainChatColor);
201 } else {
202 CPrintToChat(client, "%s Personal top speed: %d", gPluginTag, PlayerSpeeds[client]);
203 }
204
205}
206
207public Action Command_TopSpeed(int client, int args) {
208 if(g_MenuTop == null) {
209 GetTopSpeeds();
210 }
211
212 g_MenuTop.Display(client, 10);
213
214 return Plugin_Handled;
215}
216
217
218// Menu
219Menu BuildTopMenu(Handle query) {
220 Menu menu = new Menu(Menu_Top);
221
222 int buffer;
223 char info[512];
224 char name[MAX_NAME_LENGTH];
225
226 while(SQL_FetchRow(query)) {
227 SQL_FetchString(query, 0, name, sizeof(name));
228
229 buffer = SQL_FetchInt(query, 1);
230 Format(info, sizeof(info), "%d;%s", buffer, name);
231
232 menu.AddItem(info, name);
233 }
234
235 menu.SetTitle("Top Speeds");
236 menu.ExitButton = true;
237
238 return menu;
239}
240
241public int Menu_Top(Menu menu, MenuAction action, int param1, int param2) {
242 if(action == MenuAction_Select) {
243 char info[32];
244
245 /* Get item info */
246 bool found = menu.GetItem(param2, info, sizeof(info));
247
248 int top_speed;
249 char buffer[32];
250 char name[MAX_NAME_LENGTH];
251
252 int index = SplitString(info, ";", buffer, sizeof(buffer));
253 top_speed = StringToInt(buffer);
254
255 Format(name, sizeof(name), "%s", info[index]);
256
257 Menu_DisplayPlayer(param1, name, sizeof(name), top_speed);
258
259 CPrintToChatAll("%s %s%s%s's Top Speed is %s%d %smph!", gPluginTag, gClientChatColor, name, gMainChatColor, gKeywordChatColor, HammerToMPH(top_speed), gMainChatColor);
260
261 }
262}
263
264public int Menu_Handler(Menu menu, MenuAction action, int param1, int param2) {
265 if(action == MenuAction_End) {
266 delete menu;
267 } else if(action == MenuAction_VoteEnd) {
268
269 } else if(action == MenuAction_DisplayItem) {
270
271 } else if(action == MenuAction_Display) {
272
273 } else if(action == MenuAction_Cancel) {
274 if(param2 == MenuCancel_ExitBack) {
275 Command_TopSpeed(param1, 0);
276 }
277 }
278}
279
280void Menu_DisplayPlayer(int client, char[] name, int maxlen, int top_speed) {
281 Menu menu = new Menu(Menu_Handler);
282 menu.SetTitle("%s\n▶ Speed: %dmph", name, HammerToMPH(top_speed));
283 char displayString[64];
284 bool mph = GetConVarBool(g_CVMPH);
285
286 if(mph) {
287 Format(displayString, sizeof(displayString), "Close");
288 } else {
289 Format(displayString, sizeof(displayString), "Close");
290 }
291
292 menu.ExitButton = false;
293 menu.AddItem("", displayString);
294 menu.ExitBackButton = false;
295 menu.Display(client, 60);
296 return;
297}
298
299
300// SQL
301void GetTopSpeeds() {
302 /* Check if we haven't already created the statement */
303 if(g_DBSMenuTop == null) {
304 char error[255];
305 SQL_FastQuery(g_Database, "SET NAMES \'utf8\'");
306 g_DBSMenuTop = SQL_PrepareQuery(g_Database, "SELECT `username`, `top_speed` FROM ts_players WHERE `display` = 1 ORDER BY `top_speed` DESC LIMIT ?", error, sizeof(error));
307
308 if(g_DBSMenuTop == null) {
309 LogError("%s %s", gPluginCleanTag, error);
310 return;
311 }
312 }
313
314 SQL_BindParamInt(g_DBSMenuTop, 0, g_iPopMax, false);
315
316 if(!SQL_Execute(g_DBSMenuTop)) {
317 return;
318 }
319
320 g_MenuTop = BuildTopMenu(g_DBSMenuTop);
321}
322
323void SQL_CreateTable() {
324 char query[1028];
325 Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `ts_players` ( \
326 `id` int(32) NOT NULL AUTO_INCREMENT PRIMARY KEY, \
327 `steam_id` varchar(32) NOT NULL, \
328 `username` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, \
329 `top_speed` int(32) NOT NULL DEFAULT '0', \
330 `display` tinyint(1) NOT NULL DEFAULT '1', \
331 UNIQUE KEY `steam_id` (`steam_id`) \
332 );");
333 SQL_FastQuery(g_Database, query);
334
335 char error[255];
336 if(SQL_GetError(g_Database, error, sizeof(error))) {
337 LogError("%s Error in creating table: %s", gPluginCleanTag, error);
338 }
339}
340
341/*
342CREATE TABLE IF NOT EXISTS ts_players (
343 `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
344 `steam_id` varchar(32) NOT NULL,
345 `username` varchar(128) NOT NULL,
346 `top_speed` int(32) NOT NULL DEFAULT '0',
347 `display` tinyint(1) NOT NULL DEFAULT '1',
348); */
349
350void GetPlayersData() {
351 char auth[32];
352 char query[512];
353 char buffer[MAX_NAME_LENGTH];
354 char escaped_username[MAX_NAME_LENGTH*2+1];
355
356 for(int i = 1; i <= MaxClients; i++) {
357 if(!IsValidClient(i)) {
358 continue;
359 }
360
361 GetClientAuthId(i, AuthId_Steam2, auth, sizeof(auth));
362
363 // define query
364
365 Format(query, sizeof(query), "SELECT `top_speed` FROM `ts_players` WHERE `steam_id` = '%s'", auth);
366
367 // query
368 DBResultSet data = SQL_Query(g_Database, query);
369
370 char error[255];
371 if(SQL_GetError(g_Database, error, sizeof(error))) {
372 LogError("%s Error getting player data: %s", gPluginCleanTag, error);
373 }
374
375
376 GetClientName(i, buffer, sizeof(buffer));
377
378
379 SQL_EscapeString(g_Database, buffer, escaped_username, sizeof(escaped_username));
380
381 bool GotData = SQL_FetchRow(data);
382
383 if(data.RowCount == 0) {
384 SQL_FastQuery(g_Database, "SET NAMES \'utf8\'");
385 Format(query, sizeof(query), "INSERT INTO `ts_players` (`steam_id`, `username`) VALUES ('%s', '%s')", auth, escaped_username);
386 SQL_FastQuery(g_Database, query);
387 }
388
389 if(GotData) {
390 PlayerSpeeds[i] = SQL_FetchInt(data, 0);
391 }
392
393 CloseHandle(data);
394 }
395}
396
397stock bool IsValidClient(int client, bool allowBot = false) {
398 if(client <= 0 || client > MaxClients || !IsClientInGame(client) || (!allowBot && IsFakeClient(client))) {
399 return false;
400 }
401
402 return true;
403}
404
405stock int HammerToMPH(int speed) {
406 return RoundFloat(speed * 0.0426496); // * 1.904) * 0.0224
407}