· 6 years ago · May 09, 2019, 06:50 PM
1//#pragma newdecls required
2#pragma semicolon 1
3
4#include <sourcemod>
5#include <smlib>
6#include <emitsoundany>
7#include <colors_csgo>
8
9#define FIRST 1
10#define UNIT_TYPE 2
11#define MAX 32
12#define DB_NAME "advanced_noscop"
13#define PREFIX "[{orange}Advanced Noscop{default}] "
14
15ConVar cv_HudDistance = null;
16ConVar cv_Music = null;
17ConVar cv_Directory = null;
18ConVar cv_Weapons = null;
19ConVar cv_Volume = null;
20ConVar cv_Unit = null;
21ConVar cv_MinimumPlayer = null;
22ConVar cv_EnableRank = null;
23ConVar cv_PlayerTop = null;
24
25int gI_Music;
26int gI_MCount;
27int gI_TotalPlayer = 0;
28int gI_PlayerCount = 0;
29
30float gF_Distance[MAXPLAYERS+1];
31
32char gC_ClientAuth3[MAXPLAYERS+1][32];
33char gC_Sound[MAX][128];
34char gC_Chat[2][MAX];
35char gC_CurrentMap[64];
36char gC_Unit[UNIT_TYPE][MAX] =
37{
38 "meter",
39 "mile"
40};
41
42Database gH_SQL = null;
43
44//OLD SYNTAX//
45enum NoscopData
46{
47 String:Attacker[20],
48 String:Victim[20],
49 String:Weapon[32],
50 String:Map[64],
51 Float:Distance,
52 Rank,
53}
54
55Player[MAXPLAYERS+1][NoscopData];
56
57
58public Plugin myinfo =
59{
60 name = "Advanced Noscop",
61 author = "Mish0UU",
62 description = "Advanced Noscop",
63 version = "1.1.0",
64 url = "www.balkanstar.fr"
65};
66
67public void OnPluginStart()
68{
69 HookEvent("player_death", Event_PlayerDeath);
70 HookEvent("round_start", Event_OnRoundStart);
71 HookEvent("player_spawn", Event_OnPlayerSpawn);
72
73 cv_HudDistance = CreateConVar("an_minimum_distance_hud", "15.0", "Minimum distance to show message in HUD", FCVAR_NOTIFY, true, 0.0, true, 160.0);
74 cv_Music = CreateConVar("an_music_enable", "1", "Enable music when HUD is displayed", FCVAR_NOTIFY, true, 0.0, true, 1.0);
75 cv_Directory = CreateConVar("an_music_path", "advanced_noscop", "Path of sounds directory example : sound/advanced_noscop/", FCVAR_NOTIFY);
76 cv_Volume = CreateConVar("an_music_volume", "0.5", "Music volume", FCVAR_NOTIFY, true, 0.0, true, 1.0);
77 cv_Weapons = CreateConVar("an_weapons_allowed", "3", "Allowed weapons: 1 = AWP Only | 2 = SSG08 Only | 3 = AWP + SSG08", FCVAR_NOTIFY, true, 1.0, true, 3.0);
78 cv_Unit = CreateConVar("an_weapons_unit", "1", "Unit of length used: 1 = Meter | 2 = Miles", FCVAR_NOTIFY, true, 1.0, true, 2.0);
79 cv_MinimumPlayer = CreateConVar("an_minimum_player", "6", "Minimum number of player to save noscop distance", FCVAR_NOTIFY);
80 cv_EnableRank = CreateConVar("an_enable_rank", "1", "Enable/Disable rank/top features", FCVAR_NOTIFY, false, 0.0, true, 1.0);
81 cv_PlayerTop = CreateConVar("an_show_player_top", "50", "Number of player to display on top", FCVAR_NOTIFY, true, 1.0, true, 100.0);
82
83 LoadTranslations("advanced_noscop.phrases");
84
85 RegConsoleCmd("sm_mynoscop", Cmd_MyNoscop);
86 RegConsoleCmd("sm_noscop", Cmd_TopNoscop);
87
88 AutoExecConfig(true);
89
90 for(int unit = 0; unit < UNIT_TYPE; unit++)
91 Format(gC_Chat[unit], 8, "%t", gC_Unit[unit]);
92
93 if(cv_EnableRank.IntValue)
94 SQL_DBConnect();
95}
96
97public void OnConfigsExecuted()
98{
99 if(!cv_EnableRank.BoolValue)
100 return;
101
102 if(gH_SQL == null)
103 SQL_DBConnect();
104}
105
106public void OnMapStart()
107{
108 GetCurrentMap(gC_CurrentMap, sizeof(gC_CurrentMap));
109 loadSounds();
110}
111
112public Action Cmd_MyNoscop(int client, int args)
113{
114 if(!cv_EnableRank.IntValue)
115 return;
116
117 if(Player[client][Distance] != 0.0)
118 {
119 CPrintToChatAll("%s%t", PREFIX, "an_chat_mynoscop", client, Player[client][Rank], gI_TotalPlayer, Player[client][Distance], gC_Unit[cv_Unit.IntValue-1], (Player[client][Distance] > 1.0 ? "s" : ""));
120 }
121 else
122 {
123 CPrintToChat(client, "%s%t", PREFIX, "an_chat_need_noscop");
124 }
125}
126
127public Action Cmd_TopNoscop(int client, int args)
128{
129 if(!cv_EnableRank.IntValue)
130 return;
131
132 char query[256];
133 FormatEx(query, sizeof(query), "SELECT name, distance FROM advanced_noscop WHERE map = '%s' AND distance > 0.0 ORDER BY distance DESC LIMIT 0,%d;", gC_CurrentMap, cv_PlayerTop.IntValue);
134 gH_SQL.Query(DisplayTop_Callback, query, client);
135}
136
137public void DisplayTop_Callback(Database db, DBResultSet result, char[] error, any id)
138{
139 if(result == null)
140 {
141 LogError("[Advanced_Noscop] Query Fail: %s", error);
142 return;
143 }
144
145 Menu menu = CreateMenu(MenuHandler_Top);
146
147 char sTitle[64];
148 FormatEx(sTitle, sizeof(sTitle), "Advanced Noscop: (%s)\n ", gC_CurrentMap);
149
150 SetMenuTitle(menu, sTitle);
151
152 int iCount = 0;
153
154 while(result.FetchRow())
155 {
156 iCount++;
157
158 char sName[MAX_NAME_LENGTH];
159 result.FetchString(0, sName, MAX_NAME_LENGTH);
160 float distance = result.FetchFloat(1);
161
162 char sDisplay[128];
163 FormatEx(sDisplay, sizeof(sDisplay), "#%d - %s (%.2f %s%s)", iCount, sName, distance, gC_Chat[cv_Unit.IntValue-1], distance > 1.0 ? "s":"");
164 menu.AddItem("0", sDisplay);
165 }
166 if(!iCount)
167 AddMenuItem(menu, "-1", "No record");
168
169 menu.ExitButton = true;
170 menu.Display(id, 30);
171}
172
173public int MenuHandler_Top(Menu menu, MenuAction action, int param1, int param2)
174{
175 if(action == MenuAction_End)
176 CloseHandle(menu);
177}
178
179public void Event_OnRoundStart(Handle event, const char[] name, bool dB)
180{
181 if(!cv_EnableRank.BoolValue)
182 return;
183
184 gI_PlayerCount = 0;
185 for(int i = 1; i <= GetMaxClients(); i++)
186 {
187 if(IsClientInGame(i) && GetClientTeam(i) > 1)
188 gI_PlayerCount++;
189 }
190 CacheTotalPlayer();
191}
192
193public void Event_OnPlayerSpawn(Handle event, const char[] name, bool dB)
194{
195 if(!cv_EnableRank.BoolValue)
196 return;
197
198 int client = GetClientOfUserId(GetEventInt(event, "userid"));
199
200 if(!IsValidClient(client))
201 return;
202
203 CacheRankPlayer(client);
204}
205
206public void OnClientPutInServer(int client)
207{
208 if(!IsValidClient(client) || IsFakeClient(client) || gH_SQL == null || !cv_EnableRank.BoolValue)
209 return;
210
211 GetClientAuthId(client, AuthId_Steam3, gC_ClientAuth3[client], sizeof(gC_ClientAuth3));
212
213 GetCurrentMap(Player[client][Map], 64);
214
215 Player[client][Distance] = 0.0;
216 Player[client][Rank] = -1;
217
218 char query[256];
219 FormatEx(query, sizeof(query), "SELECT distance FROM advanced_noscop WHERE auth = '%s' AND map = '%s';", gC_ClientAuth3[client], Player[client][Map]);
220
221 gH_SQL.Query(CheckPlayer_Callback, query, GetClientSerial(client));
222}
223
224
225
226public void CheckPlayer_Callback(Database db, DBResultSet result, char[] error, any data)
227{
228 if(result == null)
229 {
230 LogError("[Advanced_Noscop] Query Fail: %s", error);
231 return;
232 }
233
234 int id = GetClientFromSerial(data);
235
236 if(!id)
237 return;
238
239 while(result.FetchRow())
240 {
241 Player[id][Distance] = result.FetchFloat(0);
242 updateName(id);
243 return;
244 }
245
246 char userName[MAX_NAME_LENGTH];
247 GetClientName(id, userName, sizeof(userName));
248
249 int len = strlen(userName) * 2 + 1;
250 char[] escapedName = new char[len];
251 gH_SQL.Escape(userName, escapedName, len);
252
253 len = strlen(gC_ClientAuth3[id]) * 2 + 1;
254 char[] escapedSteamId = new char[len];
255 gH_SQL.Escape(gC_ClientAuth3[id], escapedSteamId, len);
256
257 char query[512];
258 Format(query, sizeof(query), "INSERT INTO `advanced_noscop` (auth, name, distance, map) VALUES ('%s', '%s', '0', '%s') ON DUPLICATE KEY UPDATE name = '%s';", escapedSteamId, escapedName, gC_CurrentMap, escapedName);
259 gH_SQL.Query(Nothing_Callback, query, id);
260}
261
262public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
263{
264 int victim = GetClientOfUserId(GetEventInt(event, "userid"));
265 int attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
266
267 if(!IsValidClient(victim) || !IsValidClient(attacker))
268 return;
269
270 char weapons[32];
271 GetEventString(event, "weapon", weapons, sizeof(weapons));
272
273 if(cv_Weapons.IntValue == 1 && StrEqual(weapons, "ssg08"))
274 return;
275 if(cv_Weapons.IntValue == 2 && StrEqual(weapons, "awp"))
276 return;
277
278 if(!GetEntProp(attacker, Prop_Send, "m_bIsScoped") && (StrEqual(weapons, "awp") || StrEqual(weapons, "ssg08")))
279 {
280 GetClientName(attacker, Player[attacker][Attacker], 20);
281 GetClientName(victim, Player[attacker][Victim], 20);
282
283 float distance = Entity_GetDistance(victim, attacker);
284 if(cv_Unit.IntValue == 1)
285 {
286 distance = Math_UnitsToMeters(distance);
287 }
288 else
289 {
290 distance = Math_UnitsToMiles(distance);
291 }
292 gF_Distance[attacker] = distance;
293
294 if(cv_EnableRank.BoolValue)
295 {
296 if(distance > Player[attacker][Distance])
297 {
298 if(gI_PlayerCount >= cv_MinimumPlayer.IntValue)
299 {
300 DB_UpdateNoscop(attacker);
301 }
302 }
303 }
304 FormatEx(Player[attacker][Weapon], 32, "%s", weapons);
305 CreateTimer(0.1, Timer_Message, attacker);
306 }
307}
308
309public void DB_UpdateNoscop(int client)
310{
311 char query[512];
312 FormatEx(query, sizeof(query), "UPDATE `advanced_noscop` SET distance = %f WHERE auth = '%s' AND map = '%s'", gF_Distance[client], gC_ClientAuth3[client], Player[client][Map]);
313 gH_SQL.Query(UpdateKills_Callback, query, client);
314}
315
316public void UpdateKills_Callback(Database db, DBResultSet result, char[] error, any data)
317{
318 if(result == null)
319 {
320 LogError("[Advanced_Noscop] Query Fail: %s", error);
321 return;
322 }
323 Player[data][Distance] = gF_Distance[data];
324}
325
326public Action Timer_Message(Handle timer, any userid)
327{
328 if(IsClientInGame(userid))
329 SendMessageToAll(userid);
330}
331
332void SendMessageToAll(int id)
333{
334 if(gF_Distance[id] >= cv_HudDistance.FloatValue)
335 {
336 PrintHintTextToAll("%t", "an_hud_message", Player[id][Victim], Player[id][Attacker], gF_Distance[id], gC_Chat[cv_Unit.IntValue-1], (gF_Distance[id] > 1.0 ? "s":"")/*, (cv_MinimumPlayer.IntValue < gI_PlayerCount ? noSaved : "")*/);
337 if(cv_Music.BoolValue)
338 {
339 EmitSoundToAllAny(gC_Sound[gI_Music], SOUND_FROM_PLAYER, SNDCHAN_AUTO, SNDLEVEL_NORMAL, SND_NOFLAGS, cv_Volume.FloatValue);
340 gI_Music++;
341
342 if(gI_Music > gI_MCount)
343 {
344 gI_Music = FIRST;
345 }
346 }
347 }
348 else
349 {
350 char noSaved[64];
351 FormatEx(noSaved, sizeof(noSaved), "%t", "an_noscop_no_saved");
352
353 CPrintToChatAll("%t", "an_chat_message", Player[id][Victim], Player[id][Attacker], gF_Distance[id], gC_Chat[cv_Unit.IntValue-1], (gF_Distance[id] > 1.0 ? "s":""), Player[id][Weapon], (gI_PlayerCount < cv_MinimumPlayer.IntValue ? noSaved : ""));
354 }
355}
356
357stock bool IsValidClient(int client)
358{
359 return (client >= 1 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsClientSourceTV(client));
360}
361
362void loadSounds()
363{
364 gI_MCount = 0;
365
366 char directory[PLATFORM_MAX_PATH];
367 char path[PLATFORM_MAX_PATH];
368
369 cv_Directory.GetString(directory, sizeof(directory));
370
371 Format(path, sizeof(path), "sound/%s/", directory);
372 DirectoryListing pluginsDir = OpenDirectory(path);
373
374 if(pluginsDir != null)
375 {
376 char fileName[128];
377 char soundName[512];
378 while(pluginsDir.GetNext(fileName, sizeof(fileName)))
379 {
380 int fileExt = strlen(fileName) - 4;
381 if(StrContains(fileName, ".mp3", false) == fileExt)
382 {
383
384 Format(soundName, sizeof(soundName), "sound/%s/%s", directory, fileName);
385 AddFileToDownloadsTable(soundName);
386
387 gI_MCount++;
388
389 Format(gC_Sound[gI_MCount], 2048, "%s", soundName);
390 ReplaceString(gC_Sound[gI_MCount], 128, "sound/", "");
391
392 PrecacheSoundAny(gC_Sound[gI_MCount], true);
393
394 }
395 }
396 }
397 gI_Music = GetRandomInt(FIRST, gI_MCount);
398}
399
400void SQL_DBConnect()
401{
402 if(gH_SQL != null)
403 delete gH_SQL;
404
405 if(SQL_CheckConfig(DB_NAME))
406 {
407 Database.Connect(SQLConnect_Callback, DB_NAME);
408 }
409 else
410 {
411 LogError("[Advanced_Noscop] Startup failed. Error: %s", "\"advanced_noscop\" is not a specified entry in databases.cfg.");
412 }
413}
414
415public void SQLConnect_Callback(Database db, char[] error, any data)
416{
417 if(db == null)
418 {
419 LogError("[Advanced_Noscop] Can't connect to server. Error: %s", error);
420 return;
421 }
422 gH_SQL = db;
423 gH_SQL.Query(Nothing_Callback, "CREATE TABLE IF NOT EXISTS `advanced_noscop` (`auth` varchar(32) NOT NULL, `name` varchar(64) NOT NULL, `distance` float DEFAULT '0', `map` varchar(64) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;", DBPrio_High);
424}
425
426public void Nothing_Callback(Database db, DBResultSet result, char[] error, any data)
427{
428 if(result == null)
429 LogError("[Advanced_Noscop] Error: %s", error);
430}
431
432void updateName(int client)
433{
434 char userName[MAX_NAME_LENGTH];
435 GetClientName(client, userName, sizeof(userName));
436
437 int len = strlen(userName) * 2 + 1;
438 char[] escapedName = new char[len];
439 gH_SQL.Escape(userName, escapedName, len);
440
441 len = strlen(gC_ClientAuth3[client]) * 2 + 1;
442 char[] escapedSteamId = new char[len];
443 gH_SQL.Escape(gC_ClientAuth3[client], escapedSteamId, len);
444
445 char query[128];
446 FormatEx(query, sizeof(query), "UPDATE `advanced_noscop` SET name = '%s' WHERE auth = '%s';", escapedName, escapedSteamId);
447 gH_SQL.Query(Nothing_Callback, query, client);
448
449}
450
451void CacheTotalPlayer()
452{
453 gI_TotalPlayer = 0;
454
455 char query[256];
456 FormatEx(query, sizeof(query), "SELECT count(distinct auth) FROM `advanced_noscop` WHERE map = '%s';", gC_CurrentMap);
457 gH_SQL.Query(CacheTotalPlayer_Callback, query, DBPrio_High);
458}
459
460public void CacheTotalPlayer_Callback(Database db, DBResultSet result, char[] error, any data)
461{
462 if(result == null)
463 {
464 LogError("[Advanced_Noscop] Query Fail: %s", error);
465 return;
466 }
467 while(result.FetchRow())
468 {
469 gI_TotalPlayer = result.FetchInt(0);
470 }
471}
472
473void CacheRankPlayer(int client)
474{
475 char query[256];
476 FormatEx(query, sizeof(query), "SELECT auth, distance FROM `advanced_noscop` WHERE distance >= %.2f AND map = '%s' ORDER BY distance DESC;", Player[client][Distance], gC_CurrentMap);
477 gH_SQL.Query(CacheRankPlayer_Callback, query, client);
478}
479
480public void CacheRankPlayer_Callback(Database db, DBResultSet result, char[] error, any client)
481{
482 if(result == null)
483 {
484 LogError("[Advanced_Noscop] Query Fail: %s", error);
485 return;
486 }
487 int count = 0;
488
489 while(result.FetchRow())
490 count++;
491
492 Player[client][Rank] = count;
493}