· 7 years ago · Dec 02, 2018, 03:34 PM
1#pragma semicolon 1
2#pragma newdecls required
3
4#include <sourcemod>
5#include <sdktools>
6
7Database hDatabase;
8
9ConVar g_Cvar_Warmup;
10ConVar g_Cvar_Kills;
11ConVar g_Cvar_Assists;
12ConVar g_Cvar_Hs;
13ConVar g_Cvar_Deaths;
14ConVar g_Cvar_Bomb_Exploded;
15ConVar g_Cvar_Bomb_Defused;
16ConVar g_Cvar_Bomb_Planted;
17ConVar g_Cvar_Hostage_Rescued;
18ConVar g_Cvar_Hostage_Killed;
19ConVar g_Cvar_MVP;
20
21int g_Headshots[MAXPLAYERS + 1];
22int g_Kills[MAXPLAYERS + 1];
23int g_Deaths[MAXPLAYERS + 1];
24int g_Score[MAXPLAYERS + 1];
25
26public void OnPluginStart()
27{
28 Database.Connect(Handle_ConnectDatabase, "rank");
29
30 g_Cvar_Warmup = CreateConVar("sm_rank_warmup_enabled", "1", "Gather statistics in warmup?.", 0, true, 0.0, true, 1.0);
31 g_Cvar_Kills = CreateConVar("sm_rank_kill_points", "2", "How many points a player should receive for a kill.", 0, true, 0.0, true, 10.0);
32 g_Cvar_Assists = CreateConVar("sm_rank_assist_points", "1", "How many points a player should receive for an assist.", 0, true, 0.0, true, 10.0);
33 g_Cvar_Hs = CreateConVar("sm_rank_hs_points", "1", "How many points a player should receive for an headshot.", 0, true, 0.0, true, 10.0);
34 g_Cvar_Deaths = CreateConVar("sm_rank_death_points", "2", "How many points a player should lose for a death.", 0, true, 0.0, true, 10.0);
35 g_Cvar_Bomb_Exploded = CreateConVar("sm_rank_bomb_exploded_points", "1", "How many points a player should receive for a bomb exploded.", 0, true, 0.0, true, 10.0);
36 g_Cvar_Bomb_Defused = CreateConVar("sm_rank_bomb_defused_points", "1", "How many points a player should receive for a bomb defused.", 0, true, 0.0, true, 10.0);
37 g_Cvar_Bomb_Planted = CreateConVar("sm_rank_bomb_planted_points", "1", "How many points a player should receive for a bomb plant.", 0, true, 0.0, true, 10.0);
38 g_Cvar_Hostage_Rescued = CreateConVar("sm_rank_hostage_rescued_points", "1", "How many points a player should receive for an hostage rescued.", 0, true, 0.0, true, 10.0);
39 g_Cvar_Hostage_Killed = CreateConVar("sm_rank_hostage_killed_points", "5", "How many points a player should lose for an hostage killed.", 0, true, 0.0, true, 10.0);
40 g_Cvar_MVP = CreateConVar("sm_rank_mvp_points", "2", "How many points a player should receive for a MVP.", 0, true, 0.0, true, 10.0);
41 AutoExecConfig(true, "rank");
42
43 HookEvent("player_death", Event_PlayerDeath);
44 HookEvent("bomb_exploded", Event_BombExploded);
45 HookEvent("bomb_defused", Event_BombDefused);
46 HookEvent("bomb_planted", Event_BombPlanted);
47 HookEvent("hostage_rescued", Event_HostageRescued);
48 HookEvent("hostage_killed", Event_HostageKilled);
49 HookEvent("round_mvp", Event_RoundMvp);
50
51 RegConsoleCmd("sm_rank", Command_Rank);
52 RegConsoleCmd("sm_top", Command_Top);
53
54 for (int i = 1; i <= MaxClients; i++)
55 {
56 OnClientConnected(i);
57 }
58}
59
60public void OnPluginEnd()
61{
62 for (int i = 1; i <= MaxClients; i++)
63 {
64 if (IsClientInGame(i))
65 {
66 OnClientDisconnect(i);
67 }
68 }
69}
70
71public void OnMapEnd()
72{
73 hDatabase.Query(Handle_FastQuery, "DELETE FROM rank_table WHERE date < CURRENT_DATE - INTERVAL 1 MONTH;");
74 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;");
75}
76
77public void Handle_ConnectDatabase(Database db, const char[] error, any data)
78{
79 if (db)
80 {
81 hDatabase = db;
82
83 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));");
84 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);");
85 }
86 else
87 {
88 SetFailState("Could not connect to the database: %s", error);
89 }
90}
91
92public void OnClientConnected(int client)
93{
94 g_Headshots[client] = 0;
95 g_Kills[client] = 0;
96 g_Deaths[client] = 0;
97 g_Score[client] = 0;
98}
99
100public void OnClientDisconnect(int client)
101{
102 int steam = GetSteamAccountID(client);
103
104 if (steam)
105 {
106 char query[512], buffer[65], name[131];
107 GetClientName(client, buffer, sizeof(buffer));
108 hDatabase.Escape(buffer, name, sizeof(name));
109
110 Format(query, sizeof(query), "INSERT INTO name_table (steamid, name) VALUES (%d, '%s') ON DUPLICATE KEY UPDATE name = VALUES(name);", steam, name);
111 hDatabase.Query(Handle_FastQuery, query);
112
113 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]);
114 hDatabase.Query(Handle_FastQuery, query);
115 }
116}
117
118public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
119{
120 if (!g_Cvar_Warmup.BoolValue && GameRules_GetProp("m_bWarmupPeriod"))
121 {
122 return;
123 }
124
125 int client = GetClientOfUserId(event.GetInt("userid"));
126 int attacker = GetClientOfUserId(event.GetInt("attacker"));
127 int assister = GetClientOfUserId(event.GetInt("assister"));
128
129 if (g_Cvar_Kills.BoolValue)
130 {
131 if (attacker && client && attacker != client)
132 {
133 if (event.GetBool("headshot"))
134 {
135 g_Headshots[attacker]++;
136 g_Score[attacker] += g_Cvar_Hs.IntValue;
137
138 PrintToChat(attacker, "You have received \x04%d\x01 points (headshot)", g_Cvar_Hs.IntValue);
139 }
140
141 g_Kills[attacker]++;
142 g_Score[attacker] += g_Cvar_Kills.IntValue;
143
144 PrintToChat(attacker, "You have received \x04%d\x01 points (kill)", g_Cvar_Kills.IntValue);
145 }
146 }
147
148 if (g_Cvar_Assists.BoolValue)
149 {
150 if (assister && client && assister != client)
151 {
152 g_Score[assister] += g_Cvar_Assists.IntValue;
153 PrintToChat(assister, "You have received \x04%d\x01 points (assist)", g_Cvar_Assists.IntValue);
154 }
155 }
156
157 if (g_Cvar_Deaths.BoolValue)
158 {
159 g_Score[client] -= g_Cvar_Deaths.IntValue;
160 g_Deaths[client]++;
161
162 PrintToChat(client, " \x04[Rank]\x01 You have lost \x07%d\x01 points (death)", g_Cvar_Deaths.IntValue);
163 }
164}
165
166public void Event_BombExploded(Event event, const char[] name, bool dontBroadcast)
167{
168 if (g_Cvar_Bomb_Exploded.BoolValue)
169 {
170 int client = GetClientOfUserId(event.GetInt("userid"));
171
172 if (client)
173 {
174 g_Score[client] += g_Cvar_Bomb_Exploded.IntValue;
175 PrintToChat(client, " \x04[Rank]\x01 You have received \x04%d\x01 points (bomb exploded)", g_Cvar_Bomb_Defused.IntValue);
176 }
177 }
178}
179
180public void Event_BombDefused(Event event, const char[] name, bool dontBroadcast)
181{
182 if (g_Cvar_Bomb_Defused.BoolValue)
183 {
184 int client = GetClientOfUserId(event.GetInt("userid"));
185
186 if (client)
187 {
188 g_Score[client] += g_Cvar_Bomb_Defused.IntValue;
189 PrintToChat(client, " \x04[Rank]\x01 You have received \x04%d\x01 points (bomb defused)", g_Cvar_Bomb_Defused.IntValue);
190 }
191 }
192}
193
194public void Event_BombPlanted(Event event, const char[] name, bool dontBroadcast)
195{
196 if (g_Cvar_Bomb_Planted.BoolValue)
197 {
198 int client = GetClientOfUserId(event.GetInt("userid"));
199
200 if (client)
201 {
202 g_Score[client] += g_Cvar_Bomb_Planted.IntValue;
203 PrintToChat(client, " \x04[Rank]\x01 You have received \x04%d\x01 points (bomb planted)", g_Cvar_Bomb_Planted.IntValue);
204 }
205 }
206}
207
208public void Event_HostageRescued(Event event, const char[] name, bool dontBroadcast)
209{
210 if (g_Cvar_Hostage_Rescued.BoolValue)
211 {
212 int client = GetClientOfUserId(event.GetInt("userid"));
213
214 if (client)
215 {
216 g_Score[client] += g_Cvar_Hostage_Rescued.IntValue;
217 PrintToChat(client, " \x04[Rank]\x01 You have received \x04%d\x01 points (hostage rescued)", g_Cvar_Hostage_Rescued.IntValue);
218 }
219 }
220}
221
222public void Event_HostageKilled(Event event, const char[] name, bool dontBroadcast)
223{
224 if (g_Cvar_Hostage_Killed.BoolValue)
225 {
226 int client = GetClientOfUserId(event.GetInt("userid"));
227
228 if (client)
229 {
230 g_Score[client] -= g_Cvar_Hostage_Killed.IntValue;
231 PrintToChat(client, " \x04[Rank]\x01 You have lost \x07%d\x01 points (hostage killed)", g_Cvar_Hostage_Killed.IntValue);
232 }
233 }
234}
235
236public void Event_RoundMvp(Event event, const char[] name, bool dontBroadcast)
237{
238 if (g_Cvar_MVP.BoolValue)
239 {
240 int client = GetClientOfUserId(event.GetInt("userid"));
241
242 if (client)
243 {
244 g_Score[client] -= g_Cvar_MVP.IntValue;
245 PrintToChat(client, " \x04[Rank]\x01 You have received \x04%d\x01 points (MVP)", g_Cvar_MVP.IntValue);
246 }
247 }
248}
249
250public Action Command_Rank(int client, int args)
251{
252 if (client)
253 {
254 int steam = GetSteamAccountID(client);
255
256 if (steam)
257 {
258 char query[512];
259 Format(query, sizeof(query), "SELECT r.rank, 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);
260 hDatabase.Query(Handle_GetRank, query, GetClientUserId(client));
261 }
262 }
263
264 return Plugin_Handled;
265}
266
267public void Handle_GetRank(Database db, DBResultSet rs, const char[] error, any data)
268{
269 if (rs)
270 {
271 int client = GetClientOfUserId(data);
272
273 if (client && rs.FetchRow())
274 {
275 int kills = rs.FetchInt(2);
276 int deaths = rs.FetchInt(3);
277 int headshots = rs.FetchInt(4);
278 float KPD = deaths ? 1.0 * kills / deaths : 1.0;
279 int percent = kills ? 100 * headshots / kills : 0;
280
281 PrintToChat(client, "Ranked \x10%d\x01 with %d points", rs.FetchInt(0), rs.FetchInt(1));
282 PrintToChat(client, "%0.1f KPD ratio, %d%% headshots", KPD, percent);
283 }
284 }
285 else
286 {
287 LogError("(Handle_GetRank) %s", error);
288 }
289}
290
291public Action Command_Top(int client, int args)
292{
293 if (client)
294 {
295 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));
296 }
297
298 return Plugin_Handled;
299}
300
301public void Handle_GetTop(Database db, DBResultSet rs, const char[] error, any data)
302{
303 if (rs)
304 {
305 int client = GetClientOfUserId(data);
306
307 if (client && rs.HasResults)
308 {
309 Panel panel = new Panel();
310 panel.DrawText("Top");
311
312 for(int i = 0; i < rs.RowCount; i++)
313 {
314 if (rs.FetchRow())
315 {
316 char name[65], row[256];
317 rs.FetchString(2, name, sizeof(name));
318 Format(row, sizeof(row), "%02d. %05dp : %s", rs.FetchInt(0), rs.FetchInt(1), name);
319 panel.DrawText(row);
320 }
321 }
322
323 panel.DrawItem("Close");
324 panel.Send(client, Panel_DoNothing, MENU_TIME_FOREVER);
325 delete panel;
326 }
327 }
328 else
329 {
330 LogError("Failed to query database: %s", error);
331 }
332}
333
334public int Panel_DoNothing(Menu menu, MenuAction action, int param1, int param2)
335{
336
337}
338
339public void Handle_FastQuery(Database db, DBResultSet rs, const char[] error, any data)
340{
341 if (!rs)
342 {
343 LogError("Failed to query database: %s", error);
344 }
345}