SHOW:
|
|
- or go back to the newest paste.
1 | /*============================================================================== | |
2 | ||
3 | $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$\ $$\ $$\ $$$$$$$$\ $$$$$$\ $$$$$$$$\ | |
4 | $$ __$$\ $$$\ $$ |\__$$ __|\_$$ _|$$ __$$\ $$ | $$ |$$ _____|$$ __$$\\__$$ __| | |
5 | $$ / $$ |$$$$\ $$ | $$ | $$ | $$ / \__|$$ | $$ |$$ | $$ / $$ | $$ | | |
6 | $$$$$$$$ |$$ $$\$$ | $$ | $$ | $$ | $$$$$$$$ |$$$$$\ $$$$$$$$ | $$ | | |
7 | $$ __$$ |$$ \$$$$ | $$ | $$ | $$ | $$ __$$ |$$ __| $$ __$$ | $$ | | |
8 | $$ | $$ |$$ |\$$$ | $$ | $$ | $$ | $$\ $$ | $$ |$$ | $$ | $$ | $$ | | |
9 | $$ | $$ |$$ | \$$ | $$ | $$$$$$\ \$$$$$$ |$$ | $$ |$$$$$$$$\ $$ | $$ | $$ | | |
10 | \__| \__|\__| \__| \__| \______| \______/ \__| \__|\________|\__| \__| \__| | |
11 | ||
12 | ||
13 | Publics: 1/1/2021 | |
14 | ||
15 | Last edited: 4/22/2022 | |
16 | ||
17 | ==============================================================================*/ | |
18 | ||
19 | #include <YSI_Coding\y_hooks> | |
20 | ||
21 | new BitArray:MsgAntiCheat<MAX_PLAYERS>; | |
22 | ||
23 | #define TS3 "bstorm-ts3" | |
24 | ||
25 | #define NO_SUSPICION_LOGS | |
26 | #define VERSION_AC "1.9" | |
27 | #define VERSION_AC_PLUS ""VERSION_AC".58" | |
28 | ||
29 | #define AC_TABLE_SETTINGS "anticheat_settings" // name of the table | |
30 | #define AC_TABLE_FIELD_CODE "ac_code" // table code from sql | |
31 | #define AC_TABLE_FIELD_TRIGGER "ac_code_trigger_type" // warn/ban/kick | |
32 | ||
33 | #define AC_MAX_CODES 54 // number of ac's | |
34 | #define AC_MAX_CODE_LENGTH (5) // 001, 002, 003... etc | |
35 | #define AC_MAX_CODE_NAME_LENGTH (33 + 1) // max name of the cheat +1 security | |
36 | ||
37 | ||
38 | #define AC_MAX_TRIGGER_TYPES 3 // warn, kick, ban | |
39 | #define AC_MAX_TRIGGER_TYPE_NAME_LENGTH (40 + 1) | |
40 | #define AC_GLOBAL_TRIGGER_TYPE_PLAYER 0 | |
41 | #define AC_GLOBAL_TRIGGER_TYPE_IP 1 | |
42 | ||
43 | #define AC_CODE_TRIGGER_TYPE_DISABLED 0 // AC_CODE_TRIGGER_TYPE_DISABLED - Value: #disable | |
44 | #define AC_CODE_TRIGGER_TYPE_WARNING 1 // AC_CODE_TRIGGER_TYPE_WARNING - Value: #warning | |
45 | #define AC_CODE_TRIGGER_TYPE_KICK 2 // AC_CODE_TRIGGER_TYPE_KICK - Value: #kick | |
46 | ||
47 | #define AC_TRIGGER_ANTIFLOOD_TIME 1 // Vreme anti-fluid(sekunde), #disabled in dialogs... | |
48 | ||
49 | #define AC_MAX_CODES_ON_PAGE (20 - 1) // Maksimum anticheata na jednoj strani dialoga | |
50 | #define AC_DIALOG_NEXT_PAGE_TEXT ">>> Nastavi" // Tekst za dalje... | |
51 | #define AC_DIALOG_PREVIOUS_PAGE_TEXT "<<< Vrati" // Tekst za nazad... | |
52 | ||
53 | #define DIALOG_ANTICHEAT_SETTINGS 0 // ID dialoga za anticheat settings... | |
54 | #define DIALOG_ANTICHEAT_EDIT_CODE 1 // ID dialoga za editovanje anticheat-a... | |
55 | ||
56 | static const AC_CODE[AC_MAX_CODES][AC_MAX_CODE_LENGTH] = | |
57 | { | |
58 | "1000", | |
59 | "1001", "1002", "1003", "1004", "1005", "1006", "1007", "1008", "1009", "1010", "1011", "1012", "1013", "1014", "1015", "1016", "1017", "1018", "1019", "1020", | |
60 | "1021", "1022", "1023", "1024", "1025", "1026", "1027", "1028", "1029", "1030", "1031", "1032", "1033", "1034", "1035", "1036", "1037", "1038", "1039", "1040", "1041", | |
61 | "1042", "1043", "1044", "1045", "1046", "1047", "1048", "1049", "1050", "1051", "1052", "1053" | |
62 | }; | |
63 | ||
64 | static const AC_CODE_NAME[AC_MAX_CODES][AC_MAX_CODE_NAME_LENGTH] = | |
65 | { | |
66 | {"AirBreak - onfoot"}, | |
67 | {"AirBreak - veh"}, | |
68 | {"Teleport - onfoot"}, | |
69 | {"Teleport - in veh"}, | |
70 | {"Teleport - veh"}, | |
71 | {"Teleport - veh to player"}, | |
72 | {"Teleport - pickups"}, | |
73 | {"FlyHack - onfoot"}, | |
74 | {"FlyHack - in veh"}, | |
75 | {"SpeedHack - onfoot"}, | |
76 | {"SpeedHack - in veh"}, | |
77 | {"Health hack - in veh"}, | |
78 | {"Health hack - onfoot"}, | |
79 | {"Armour hack"}, | |
80 | {"Money hack"}, | |
81 | {"Weapon hack"}, | |
82 | {"Ammo hack (add)"}, | |
83 | {"Ammo hack (infinite)"}, | |
84 | {"Special actions"}, | |
85 | {"GodMode bullets - onfoot"}, | |
86 | {"GodMode bullets - in veh"}, | |
87 | {"Invisible hack"}, | |
88 | {"Lagcomp-spoof"}, | |
89 | {"Tuning hack"}, | |
90 | {"Parkour mod"}, | |
91 | {"Quick turn"}, | |
92 | {"Rapid fire"}, | |
93 | {"FakeSpawn"}, | |
94 | {"FakeKill"}, | |
95 | {"Pro Aim"}, | |
96 | {"CJ run"}, | |
97 | {"CarShot"}, | |
98 | {"CarJack"}, | |
99 | {"UnFreeze"}, | |
100 | {"AFK Ghost"}, | |
101 | {"Full Aiming"}, | |
102 | {"Fake NPC"}, | |
103 | {"Reconnect"}, | |
104 | {"High ping"}, | |
105 | {"Dialog hack"}, | |
106 | {"Sandbox"}, | |
107 | {"Invalid version"}, | |
108 | {"Rcon hack"}, | |
109 | {"Tuning crasher"}, | |
110 | {"Invalid seat crasher"}, | |
111 | {"Dialog crasher"}, | |
112 | {"Attached object crasher"}, | |
113 | {"Weapon Crasher"}, | |
114 | {"Connects to one slot"}, | |
115 | {"Flood callback functions"}, | |
116 | {"Flood change seat"}, | |
117 | {"DDos"}, | |
118 | {"NOP's"}, | |
119 | {"Fast Movement"} | |
120 | }; | |
121 | ||
122 | static const AC_TRIGGER_TYPE_NAME[AC_MAX_TRIGGER_TYPES][AC_MAX_TRIGGER_TYPE_NAME_LENGTH] = | |
123 | { | |
124 | {"{A84032}#Ugasen"}, {"{DBEB34}#Warning"}, {"{55A832}#Kick"} | |
125 | }; | |
126 | ||
127 | new | |
128 | AC_CODE_TRIGGER_TYPE[AC_MAX_CODES], | |
129 | AC_CODE_TRIGGERED_COUNT[AC_MAX_CODES] = {0, ...}; | |
130 | ||
131 | new | |
132 | pAntiCheatLastCodeTriggerTime[MAX_PLAYERS][AC_MAX_CODES], | |
133 | pAntiCheatSettingsPage[MAX_PLAYERS char], | |
134 | pAntiCheatSettingsMenuListData[MAX_PLAYERS][AC_MAX_CODES_ON_PAGE], | |
135 | pAntiCheatSettingsEditCodeId[MAX_PLAYERS]; | |
136 | ||
137 | hook OnGameModeInit() | |
138 | { | |
139 | new | |
140 | Cache:cache = mysql_query(Database, "SELECT * FROM "AC_TABLE_SETTINGS" ORDER BY "AC_TABLE_FIELD_CODE""), | |
141 | rows = cache_num_rows(), | |
142 | tick = GetTickCount(); | |
143 | ||
144 | if(rows > 0) | |
145 | { | |
146 | for(new i = 0; i < AC_MAX_CODES; i++) | |
147 | { | |
148 | cache_get_value_name_int(i, ""AC_TABLE_FIELD_TRIGGER"", AC_CODE_TRIGGER_TYPE[i]); | |
149 | ||
150 | if(AC_CODE_TRIGGER_TYPE[i] == AC_CODE_TRIGGER_TYPE_DISABLED) | |
151 | EnableAntiCheat(i, 0); | |
152 | } | |
153 | ||
154 | printf("[MySql] Postavke AC Uspeno ucitane (ucitano: %d). Vreme: %dms. Verzija: %d\n", rows, GetTickCount() - tick, VERSION_AC_PLUS); | |
155 | } | |
156 | else | |
157 | { | |
158 | print("[MySQL] Postavke anticheata nisu ucitane proverite bazu."); | |
159 | return GameModeExit(); | |
160 | } | |
161 | ||
162 | cache_delete(cache); | |
163 | return Y_HOOKS_CONTINUE_RETURN_1; | |
164 | } | |
165 | ||
166 | hook OnPlayerConnect(playerid) | |
167 | { | |
168 | for(new i = 0; i < AC_MAX_CODES; i++) | |
169 | pAntiCheatLastCodeTriggerTime[playerid][i] = -1; | |
170 | ||
171 | pAntiCheatSettingsPage{playerid} = 0; | |
172 | pAntiCheatSettingsEditCodeId[playerid] = -1; | |
173 | ||
174 | return Y_HOOKS_CONTINUE_RETURN_1; | |
175 | } | |
176 | ||
177 | forward OnCheatDetected(playerid, ip_address[], type, code, code2); | |
178 | public OnCheatDetected(playerid, ip_address[], type, code, code2) | |
179 | { | |
180 | if(type == AC_GLOBAL_TRIGGER_TYPE_PLAYER) | |
181 | { | |
182 | switch(code) | |
183 | { | |
184 | case 5, 6, 11, 22: return 1; | |
185 | case 32: // CarJack | |
186 | { | |
187 | new Float:X, Float:Y, Float:Z; | |
188 | AntiCheatGetPos( playerid, X, Y, Z ); | |
189 | ac_SetPlayerPos( playerid, X, Y, Z ); | |
190 | SendClientMessage( playerid, ANTICHEATDEC, "[BS-AC]"BELA" Zabranjeno je otimati vozila drugim igracima!" ); | |
191 | return 1; | |
192 | } | |
193 | case 40: // Sandbox | |
194 | { | |
195 | SendClientMessage(playerid, -1, MAX_CONNECTS_MSG); | |
196 | return AntiCheatKickWithDesync(playerid, code); | |
197 | } | |
198 | case 41: // Invalid Version | |
199 | { | |
200 | SendClientMessage(playerid, -1, UNKNOWN_CLIENT_MSG); | |
201 | return AntiCheatKickWithDesync(playerid, code); | |
202 | } | |
203 | default: | |
204 | { | |
205 | if(gettime() - pAntiCheatLastCodeTriggerTime[playerid][code] < AC_TRIGGER_ANTIFLOOD_TIME) | |
206 | return 1; | |
207 | ||
208 | pAntiCheatLastCodeTriggerTime[playerid][code] = gettime(); | |
209 | AC_CODE_TRIGGERED_COUNT[code]++; | |
210 | ||
211 | new trigger_type = AC_CODE_TRIGGER_TYPE[code]; | |
212 | ||
213 | if(trigger_type == AC_CODE_TRIGGER_TYPE_WARNING) if(Bit_Get(MsgAntiCheat, playerid)) return va_SendClientMessageToAll(0xBE2D2DFF, "<Warning>{FFFFFF} %s[%i] Mozda koristi `%s [code: %03d]`.", ReturnPlayerName(playerid), playerid, AC_CODE_NAME[code], code + 1000); | |
214 | ||
215 | else // AC_CODE_TRIGGER_TYPE_KICK | |
216 | { | |
217 | if(Bit_Get(MsgAntiCheat, playerid)) return va_SendClientMessageToAll(0xBE2D2DFF, "<Kick>{FFFFFF} %s[%i] Zbog `%s [code: %03d]`.", ReturnPlayerName(playerid), playerid, AC_CODE_NAME[code], code + 1000); | |
218 | return ToCheat(code, playerid); | |
219 | } | |
220 | } | |
221 | } | |
222 | } | |
223 | return 1; | |
224 | } | |
225 | ||
226 | static stock ToCheat(code, playerid) | |
227 | { | |
228 | new days, year, month, hour, minutes, szIP[ 16 ]; | |
229 | GetPlayerIp( playerid, szIP, sizeof( szIP ) ); | |
230 | getdate(year, month, days); | |
231 | gettime(hour,minutes); | |
232 | format(szNormalString, sizeof(szNormalString), "%02i:%02i %02i.%02i.%i", hour, minutes, days, month, year); | |
233 | format(szLargeString, sizeof(szLargeString), ""ANTICHEAT"\nKickovani ste zbog sumnjivih radnji\n\ | |
234 | Da izbegnete ovakve situacije u buducnosti\n\ | |
235 | Obrisite cleo i ostale modifikacije u igrici\n\n{FFFFFF}- Account: %s\n- IP: %s\n- Code: %s (%i / 1).\n- NetStat: %i(%.2f) \n\n Da izadjete sa servera kucajte /q(uit).", ReturnPlayerName(playerid), szIP, AC_CODE_NAME[code], 1000+code, GetPlayerPing(playerid), NetStats_PacketLossPercent(playerid)); | |
236 | ShowPlayerDialog(playerid, 0, 0, szNormalString, szLargeString, !"X", !""); | |
237 | AntiCheatKickWithDesync(playerid, code); | |
238 | return true; | |
239 | } | |
240 | ||
241 | static stock ShowPlayerDialogEx(playerid, dialogid, style, caption[], info[], button1[], button2[]) | |
242 | { | |
243 | new dtheme[100] = "{BFBBBA}"; | |
244 | strcat(dtheme, caption); | |
245 | PlayerPlaySound(playerid, 1052, 0.0, 0.0, 0.0); | |
246 | ShowPlayerDialog(playerid, dialogid, style, dtheme, info, button1, button2); | |
247 | return 1; | |
248 | } | |
249 | ||
250 | static stock ShowPlayer_AntiCheatEditCode(playerid, code) | |
251 | { | |
252 | new | |
253 | dialog_header[22 - 4 + AC_MAX_CODE_LENGTH + AC_MAX_CODE_NAME_LENGTH], | |
254 | dialog_string[AC_MAX_TRIGGER_TYPE_NAME_LENGTH*AC_MAX_TRIGGER_TYPES]; | |
255 | ||
256 | format(dialog_header, sizeof(dialog_header), "Kod %s | Naziv: %s", AC_CODE[code], AC_CODE_NAME[code]); | |
257 | ||
258 | for(new i = 0; i < AC_MAX_TRIGGER_TYPES; i++) | |
259 | { | |
260 | strcat(dialog_string, AC_TRIGGER_TYPE_NAME[i]); | |
261 | ||
262 | if(i + 1 != AC_MAX_TRIGGER_TYPES) | |
263 | strcat(dialog_string, "\n"); | |
264 | } | |
265 | ||
266 | inline const AC_EDIT_CODE(pid, dialogid, response, listitem, string:inputtext[]) | |
267 | { | |
268 | #pragma unused pid, dialogid, inputtext | |
269 | if(!response) | |
270 | { | |
271 | pAntiCheatSettingsEditCodeId[playerid] = -1; | |
272 | return ShowPlayer_AntiCheatSettings(playerid); | |
273 | } | |
274 | new | |
275 | item = pAntiCheatSettingsEditCodeId[playerid]; | |
276 | ||
277 | if(AC_CODE_TRIGGER_TYPE[item] == listitem) | |
278 | return ShowPlayer_AntiCheatSettings(playerid); | |
279 | ||
280 | if(AC_CODE_TRIGGER_TYPE[item] == AC_CODE_TRIGGER_TYPE_DISABLED && listitem != AC_CODE_TRIGGER_TYPE_DISABLED) | |
281 | EnableAntiCheat(item, 1); | |
282 | ||
283 | AC_CODE_TRIGGER_TYPE[item] = listitem; | |
284 | ||
285 | new | |
286 | sql_query[101 - 4 + 1 + 2]; | |
287 | ||
288 | format(sql_query, sizeof(sql_query), "UPDATE "AC_TABLE_SETTINGS" SET `"AC_TABLE_FIELD_TRIGGER"` = '%d' WHERE `"AC_TABLE_FIELD_CODE"` = '%d'", listitem, item); | |
289 | mysql_tquery(Database, sql_query, "", ""); | |
290 | return ShowPlayer_AntiCheatSettings(playerid); | |
291 | } | |
292 | Dialog_ShowCallback(playerid, using inline AC_EDIT_CODE, DIALOG_STYLE_LIST, dialog_header, dialog_string, !"Odaberi", !"Nazad"); | |
293 | ||
294 | return 1; | |
295 | } | |
296 | ||
297 | static stock ShowPlayer_AntiCheatSettings(playerid) | |
298 | { | |
299 | static | |
300 | dialog_string[42 + 19 - 8 + (AC_MAX_CODE_LENGTH + AC_MAX_CODE_NAME_LENGTH + AC_MAX_TRIGGER_TYPE_NAME_LENGTH + 10)*AC_MAX_CODES_ON_PAGE] = EOS; | |
301 | ||
302 | new | |
303 | triggeredCount = 0, | |
304 | page = pAntiCheatSettingsPage{playerid}, | |
305 | next = 0, | |
306 | index = 0; | |
307 | ||
308 | dialog_string = "Kod i naziv\tRadnja\tBroj Triggera\n"; | |
309 | ||
310 | for(new i = 0; i < AC_MAX_CODES; i++) | |
311 | { | |
312 | if(i >= (page * AC_MAX_CODES_ON_PAGE) && i < (page * AC_MAX_CODES_ON_PAGE) + AC_MAX_CODES_ON_PAGE) | |
313 | next++; | |
314 | ||
315 | if(i >= (page - 1) * AC_MAX_CODES_ON_PAGE && i < ((page - 1) * AC_MAX_CODES_ON_PAGE) + AC_MAX_CODES_ON_PAGE) | |
316 | { | |
317 | triggeredCount = AC_CODE_TRIGGERED_COUNT[i]; | |
318 | ||
319 | format(dialog_string, sizeof(dialog_string), "%s[#%s] %s\t%s\t%d\n", | |
320 | dialog_string, | |
321 | AC_CODE[i], | |
322 | AC_CODE_NAME[i], | |
323 | AC_TRIGGER_TYPE_NAME[AC_CODE_TRIGGER_TYPE[i]], | |
324 | triggeredCount); | |
325 | ||
326 | pAntiCheatSettingsMenuListData[playerid][index++] = i; | |
327 | } | |
328 | } | |
329 | ||
330 | if(next) | |
331 | strcat(dialog_string, ""AC_DIALOG_NEXT_PAGE_TEXT"\n"); | |
332 | ||
333 | if(page > 1) | |
334 | strcat(dialog_string, AC_DIALOG_PREVIOUS_PAGE_TEXT); | |
335 | ||
336 | inline const AC_EDIT(pid, dialogid, response, listitem, string:inputtext[]) | |
337 | { | |
338 | #pragma unused pid, dialogid, inputtext | |
339 | if(!response) | |
340 | { | |
341 | pAntiCheatSettingsPage{playerid} = 0; | |
342 | return 1; | |
343 | } | |
344 | ||
345 | if(!strcmp(inputtext, AC_DIALOG_NEXT_PAGE_TEXT)) | |
346 | { | |
347 | pAntiCheatSettingsPage{playerid} ++; | |
348 | } | |
349 | else if(!strcmp(inputtext, AC_DIALOG_PREVIOUS_PAGE_TEXT)) | |
350 | { | |
351 | pAntiCheatSettingsPage{playerid} --; | |
352 | } | |
353 | else | |
354 | { | |
355 | pAntiCheatSettingsEditCodeId[playerid] = pAntiCheatSettingsMenuListData[playerid][listitem]; | |
356 | return ShowPlayer_AntiCheatEditCode(playerid, pAntiCheatSettingsEditCodeId[playerid]); | |
357 | } | |
358 | return ShowPlayer_AntiCheatSettings(playerid); | |
359 | ||
360 | } | |
361 | Dialog_ShowCallback(playerid, using inline AC_EDIT, DIALOG_STYLE_TABLIST_HEADERS, !"Anti-Cheat", dialog_string, !"Odaberi", !"Odustani"); | |
362 | return 1; | |
363 | } | |
364 | ||
365 | // cmds | |
366 | CMD:msganticheat(playerid) | |
367 | { | |
368 | //if(PI[playerid][pAdmin] < 1) return SendClientMessage(playerid, CRVENADEC, NO_DOSTUP_TEXT); | |
369 | if(Bit_Get(MsgAntiCheat, playerid)) Bit_Vet(MsgAntiCheat, playerid); | |
370 | else Bit_Let(MsgAntiCheat, playerid); | |
371 | return va_SendClientMessage(playerid, -1, "anti-cheat poruke: %s", MsgAntiCheat ? ("{FFFF00}Off") : ("{FFFF00} On")); | |
372 | } | |
373 | ||
374 | CMD:anticheat(playerid, params[]) | |
375 | { | |
376 | pAntiCheatSettingsPage{playerid} = 1; | |
377 | ShowPlayer_AntiCheatSettings(playerid); | |
378 | return 1; | |
379 | } | |
380 | ||
381 | /* SQL SIDE | |
382 | ||
383 | CREATE TABLE IF NOT EXISTS `anticheat_settings` ( | |
384 | `ac_code` int(2) NOT NULL, | |
385 | `ac_code_trigger_type` int(1) NOT NULL, | |
386 | UNIQUE KEY `ac_code` (`ac_code`) | |
387 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |
388 | ||
389 | INSERT INTO `anticheat_settings` (`ac_code`, `ac_code_trigger_type`) VALUES | |
390 | (0, 1), | |
391 | (1, 1), | |
392 | (2, 1), | |
393 | (3, 1), | |
394 | (4, 1), | |
395 | (5, 1), | |
396 | (6, 1), | |
397 | (7, 2), | |
398 | (8, 1), | |
399 | (9, 2), | |
400 | (10, 1), | |
401 | (11, 2), | |
402 | (12, 2), | |
403 | (13, 2), | |
404 | (14, 2), | |
405 | (15, 2), | |
406 | (16, 2), | |
407 | (17, 2), | |
408 | (18, 2), | |
409 | (19, 1), | |
410 | (20, 1), | |
411 | (21, 2), | |
412 | (22, 2), | |
413 | (23, 2), | |
414 | (24, 1), | |
415 | (25, 2), | |
416 | (26, 2), | |
417 | (27, 2), | |
418 | (28, 2), | |
419 | (29, 1), | |
420 | (30, 1), | |
421 | (31, 1), | |
422 | (32, 1), | |
423 | (33, 2), | |
424 | (34, 1), | |
425 | (35, 1), | |
426 | (36, 2), | |
427 | (37, 2), | |
428 | (38, 1), | |
429 | (39, 2), | |
430 | (40, 2), | |
431 | (41, 2), | |
432 | (42, 2), | |
433 | (43, 2), | |
434 | (44, 2), | |
435 | (45, 2), | |
436 | (46, 2), | |
437 | (47, 2), | |
438 | (48, 2), | |
439 | (49, 2), | |
440 | (50, 2), | |
441 | (51, 2), | |
442 | (52, 2); | |
443 | */ |