· 6 years ago · Mar 06, 2019, 06:14 PM
1#pragma semicolon 1
2#pragma newdecls required
3
4#include <sourcemod>
5#include <sdktools>
6
7Database hDatabase;
8int g_Headshots[MAXPLAYERS + 1];
9int g_Kills[MAXPLAYERS + 1];
10int g_Deaths[MAXPLAYERS + 1];
11int g_Score[MAXPLAYERS + 1];
12
13public void OnPluginStart()
14{
15 Database.Connect(Handle_ConnectDatabase, "rank");
16
17 HookEvent("player_death", Event_PlayerDeath);
18 HookEvent("bomb_exploded", Event_BombExploded);
19 HookEvent("bomb_defused", Event_BombDefused);
20 HookEvent("bomb_planted", Event_BombPlanted);
21 HookEvent("hostage_rescued", Event_HostageRescued);
22 HookEvent("hostage_killed", Event_HostageKilled);
23 HookEvent("round_mvp", Event_RoundMvp);
24
25 RegConsoleCmd("sm_rank", Command_Rank);
26 RegConsoleCmd("sm_top", Command_Top);
27
28 for (int i = 1; i <= MaxClients; i++)
29 {
30 OnClientConnected(i);
31 }
32}
33
34public void OnPluginEnd()
35{
36 for (int i = 1; i <= MaxClients; i++)
37 {
38 if (IsClientInGame(i))
39 {
40 OnClientDisconnect(i);
41 }
42 }
43}
44
45public void OnMapEnd()
46{
47 hDatabase.Query(Handle_FastQuery, "DELETE FROM rank_table WHERE date < CURRENT_DATE - INTERVAL 1 MONTH;");
48 hDatabase.Query(Handle_FastQuery, "DELETE a.* FROM name_table a LEFT JOIN rank_table b ON b.steamid = a.steamid WHERE b.steamid IS NULL;");
49}
50
51public void Handle_ConnectDatabase(Database db, const char[] error, any data)
52{
53 if (db)
54 {
55 hDatabase = db;
56
57 db.Query(Handle_FastQuery, "CREATE TABLE IF NOT EXISTS rank_table (steamid INT UNSIGNED, date DATE, score INT, kills INT UNSIGNED, deaths INT UNSIGNED, hs INT UNSIGNED, PRIMARY KEY (steamid, date));");
58 db.Query(Handle_FastQuery, "CREATE TABLE IF NOT EXISTS name_table (steamid INT UNSIGNED PRIMARY KEY, name VARCHAR(65) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci);");
59 }
60 else
61 {
62 SetFailState("Could not connect to the database: %s", error);
63 }
64}
65
66public void OnClientConnected(int client)
67{
68 g_Headshots[client] = 0;
69 g_Kills[client] = 0;
70 g_Deaths[client] = 0;
71 g_Score[client] = 0;
72}
73
74public void OnClientDisconnect(int client)
75{
76 int steam = GetSteamAccountID(client);
77
78 if (steam)
79 {
80 char query[512], buffer[65], name[131];
81 GetClientName(client, buffer, sizeof(buffer));
82 hDatabase.Escape(buffer, name, sizeof(name));
83
84 Format(query, sizeof(query), "INSERT INTO name_table (steamid, name) VALUES (%d, '%s') ON DUPLICATE KEY UPDATE name = VALUES(name);", steam, name);
85 hDatabase.Query(Handle_FastQuery, query);
86
87 Format(query, sizeof(query), "INSERT INTO rank_table (steamid, date, score, kills, deaths, hs) VALUES (%d, CURRENT_DATE, %d, %d, %d, %d) ON DUPLICATE KEY UPDATE score = score + VALUES(score), kills = kills + VALUES(kills), deaths = deaths + VALUES(deaths), hs = hs + VALUES(hs);", steam, g_Score[client], g_Kills[client], g_Deaths[client], g_Headshots[client]);
88 hDatabase.Query(Handle_FastQuery, query);
89 }
90}
91
92public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
93{
94 if (GameRules_GetProp("m_bWarmupPeriod"))
95 {
96 return;
97 }
98
99 int client = GetClientOfUserId(event.GetInt("userid"));
100 int attacker = GetClientOfUserId(event.GetInt("attacker"));
101 int assister = GetClientOfUserId(event.GetInt("assister"));
102
103 if (attacker && client && attacker != client)
104 {
105 if (event.GetBool("headshot"))
106 {
107 g_Headshots[attacker]++;
108 g_Score[attacker] += 1;
109 }
110
111 g_Kills[attacker]++;
112 g_Score[attacker] += 2;
113 }
114
115 if (assister && client && assister != client)
116 {
117 g_Score[assister] += 1;
118 }
119
120 g_Score[client] -= 2;
121 g_Deaths[client]++;
122}
123
124public void Event_BombExploded(Event event, const char[] name, bool dontBroadcast)
125{
126 int client = GetClientOfUserId(event.GetInt("userid"));
127
128 if (client)
129 {
130 g_Score[client] += 2;
131 }
132}
133
134public void Event_BombDefused(Event event, const char[] name, bool dontBroadcast)
135{
136 int client = GetClientOfUserId(event.GetInt("userid"));
137
138 if (client)
139 {
140 g_Score[client] += 2;
141 }
142}
143
144public void Event_BombPlanted(Event event, const char[] name, bool dontBroadcast)
145{
146 int client = GetClientOfUserId(event.GetInt("userid"));
147
148 if (client)
149 {
150 g_Score[client] += 1;
151 }
152}
153
154public void Event_HostageRescued(Event event, const char[] name, bool dontBroadcast)
155{
156 int client = GetClientOfUserId(event.GetInt("userid"));
157
158 if (client)
159 {
160 g_Score[client] += 2;
161 }
162}
163
164public void Event_HostageKilled(Event event, const char[] name, bool dontBroadcast)
165{
166 int client = GetClientOfUserId(event.GetInt("userid"));
167
168 if (client)
169 {
170 g_Score[client] -= 2;
171 }
172}
173
174public void Event_RoundMvp(Event event, const char[] name, bool dontBroadcast)
175{
176 int client = GetClientOfUserId(event.GetInt("userid"));
177
178 if (client)
179 {
180 g_Score[client] += 2;
181 }
182}
183
184public Action Command_Rank(int client, int args)
185{
186 if (client)
187 {
188 int steam = GetSteamAccountID(client);
189
190 if (steam)
191 {
192 char query[512];
193 Format(query, sizeof(query), "SELECT r.rank, (SELECT count(steamid) from name_table) total, r.score, r.kills, r.deaths, r.hs FROM (SELECT @rank := @rank + 1 rank, s.* FROM (SELECT steamid, sum(score) score, sum(kills) kills, sum(deaths) deaths, sum(hs) hs FROM rank_table GROUP BY steamid ORDER BY score DESC, steamid ASC) s, (SELECT @rank := 0) init) r WHERE steamid = %d;", steam);
194 hDatabase.Query(Handle_GetRank, query, GetClientUserId(client));
195 }
196 }
197
198 return Plugin_Handled;
199}
200
201public void Handle_GetRank(Database db, DBResultSet rs, const char[] error, any data)
202{
203 if (rs)
204 {
205 int client = GetClientOfUserId(view_as<int>(data));
206
207 if (client)
208 {
209 if (rs.FetchRow())
210 {
211 int kills = rs.FetchInt(3);
212 int deaths = rs.FetchInt(4);
213 int headshots = rs.FetchInt(5);
214 float KPD = deaths ? 1.0 * kills / deaths : 1.0;
215 int HPK = kills ? 100 * headshots / kills : 0;
216
217 Panel panel = new Panel();
218 panel.DrawText("Rank");
219 panel.DrawText(" ");
220
221 char row[256];
222
223 Format(row, sizeof(row), "Ranked %d of %d", rs.FetchInt(0), rs.FetchInt(1));
224 panel.DrawText(row);
225
226 Format(row, sizeof(row), "%d points", rs.FetchInt(2));
227 panel.DrawText(row);
228
229 Format(row, sizeof(row), "%d:%d frags (%0.2f)", kills, deaths, KPD);
230 panel.DrawText(row);
231
232 Format(row, sizeof(row), "%d headshots (%d%c)", headshots, HPK, '%');
233 panel.DrawText(row);
234
235 panel.DrawText(" ");
236
237 panel.DrawItem("Close");
238 panel.Send(client, Panel_DoNothing, MENU_TIME_FOREVER);
239
240 delete panel;
241 }
242 }
243 }
244 else
245 {
246 LogError("Failed to query database: %s", error);
247 }
248}
249
250public Action Command_Top(int client, int args)
251{
252 if (client)
253 {
254 hDatabase.Query(Handle_GetTop, "SELECT r.rank, r.score, r.name FROM (SELECT @rank := @rank + 1 rank, s.* FROM (SELECT b.name, sum(a.score) score FROM rank_table a JOIN name_table b ON a.steamid = b.steamid GROUP BY a.steamid ORDER BY score DESC, a.steamid ASC LIMIT 10) s, (SELECT @rank := 0) init) r;", GetClientUserId(client));
255 }
256
257 return Plugin_Handled;
258}
259
260public void Handle_GetTop(Database db, DBResultSet rs, const char[] error, any data)
261{
262 if (rs)
263 {
264 int client = GetClientOfUserId(view_as<int>(data));
265
266 if (client)
267 {
268 if (rs.HasResults)
269 {
270 Panel panel = new Panel();
271
272 panel.DrawText("Top");
273 panel.DrawText(" ");
274
275 for(int i = 0; i < rs.RowCount; i++)
276 {
277 if (rs.FetchRow())
278 {
279 char name[65], row[256];
280 rs.FetchString(2, name, sizeof(name));
281 Format(row, sizeof(row), "%02d. %dp : %s", rs.FetchInt(0), rs.FetchInt(1), name);
282 panel.DrawText(row);
283 }
284 }
285
286 panel.DrawText(" ");
287 panel.DrawItem("Close");
288
289 panel.Send(client, Panel_DoNothing, MENU_TIME_FOREVER);
290 delete panel;
291 }
292 }
293 }
294 else
295 {
296 LogError("Failed to query database: %s", error);
297 }
298}
299
300public int Panel_DoNothing(Menu menu, MenuAction action, int param1, int param2)
301{
302
303}
304
305public void Handle_FastQuery(Database db, DBResultSet rs, const char[] error, any data)
306{
307 if (!rs)
308 {
309 LogError("Failed to query database: %s", error);
310 }
311}