/* AMX Mod X * HL Anticheat * * http://aghl.ru/forum/ - Russian Half-Life and Adrenaline Gamer Community * * This file is provided as is (no warranties) */ #include #include #include #include #define PLUGIN "HL Anticheat" #define VERSION "1.0" #define AUTHOR "Aghl.ru Team" #define MAX_PLAYERS 32 #define PREFIX "[HL Anticheat]" #define DIR_CONF "hl_anticheat" #define DIR_DLL "opengl" #define DIR_LOGS "logs" #define FILE_OPENGL "../opengl32.dll" #define FILE_SETTINGS "settings.ini" #define FILE_ALIASES "aliases.ini" #define FILE_WHITELIST "whitelist.ini" #define FILE_CHECK "files_check.ini" #define TASK_START 393712 #define TASK_ALIAS 592369 #define TASK_LAMP 936812 #define is_user_valid_connected(%1) (1 <= %1 <= g_MaxPlayers && check_bit(g_bit_is_connected,%1)) #define check_bit(%1,%2) (%1 & (1<<%2)) #define set_bit(%1,%2) (%1 |= (1<<%2)) #define clr_bit(%1,%2) (%1 &= ~(1<<%2)) enum _:NOTIFY { NOTIFY_ALL_CHAT, // 1 NOTIFY_ALL_HUD, // 2 NOTIFY_CHEATER_HUD, // 4 NOTIFY_ADMIN_HUD, // 8 NOTIFY_CHEATER_CHAT, // 16 NOTIFY_ADMIN_CHAT // 32 } enum _:BAN { KICK, BAN_IP, BAN_ADVANCED, BAN_AMXBANS_5, BAN_AMXBANS_6, BAN_CUSTOM } enum _:DETECTIONS { DET_OPENGL, DET_FUPD_SPAM, DET_MODEL, DET_LAMPING, DET_SPEED } enum _:GHOST { GHOST_EXPLOSIVE, GHOST_GAUSS } enum _:RESP { RESP_TRIPMINE, RESP_SATCHEL } new g_BanSystem = -1, g_bit_immunity, g_bit_is_connected, g_MaxPlayers, g_pSearch, gm_ent, HamHook:g_Ham_TraceAttack, g_alias_check_runing[MAX_PLAYERS + 1], g_alias[MAX_PLAYERS + 1], g_alias_control[MAX_PLAYERS + 1], g_alias_progress[MAX_PLAYERS + 1], g_alias_repeat[MAX_PLAYERS + 1], g_Detections[MAX_PLAYERS + 1][DETECTIONS], Array: g_Aliases, g_AliasesSize, g_CustomAliases, Trie: g_WhiteList, g_CvarNotify, g_CvarNotifyHud, g_CvarLog, g_CvarBanSystem, g_CvarAlias, g_CvarAliasPunish, g_CvarProtector, g_CvarProtectorPunish, g_CvarCdhack, g_CvarCdhackPunish, g_CvarOpengf, g_CvarOpengfPunish, g_CvarProxy, g_CvarProxyPunish, g_CvarOpenGL, g_CvarOpenGLPunish, g_CvarGMblocker, g_CvarLampGuard, g_CvarLampPunish, g_CvarRespGuard, g_CvarSatchelRadius, g_CvarTripmineRadius public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) register_clcmd("fullupdate", "fullupdate_hook") RegisterHam(Ham_Think, "monster_snark", "fw_SnarkThinkPre") register_forward(FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged") //register_forward(FM_CmdStart, "fw_cmdstart") } new Float: g_playerTime[MAX_PLAYERS + 1] new g_cmdCount[MAX_PLAYERS + 1] public client_connect(id) { g_playerTime[id] = 0.0 g_cmdCount[id] = 0 } public fw_cmdstart(id, uc, seed) { if(is_user_valid_connected(id) && !check_bit(g_bit_immunity, id) && ExecuteHam(Ham_IsAlive, id)) { //client_print(id, print_chat, "detec %d", g_Detections[id][DET_SPEED]) g_cmdCount[id]++ static msec, Float:time msec = get_uc(uc, UC_Msec) time = get_gametime() if (!g_playerTime[id] || g_playerTime[id] < (time - 1)) { //server_print("Time correction: id: %d, dt: +%f", id, time - _playerTime[id]); g_playerTime[id] = time } g_playerTime[id] += msec / 1000.0 /* if (_prevGameTime > time) server_print("id: %d, c: %5d, ms: %2d, gt: %f, pt: %f, btn: %d <------", id, _cmdCount[id], msec, time, _playerTime[id], btn); else server_print("id: %d, c: %5d, ms: %2d, gt: %f, pt: %f, btn: %d", id, _cmdCount[id], msec, time, _playerTime[id], btn); _prevGameTime = time; */ g_Detections[id][DET_SPEED] <= 0 ? g_Detections[id][DET_SPEED] : g_Detections[id][DET_SPEED]-- if (g_playerTime[id] > (time + 0.2) && get_uc(uc, UC_Buttons)) { g_Detections[id][DET_SPEED] += 3 //server_print("%d", g_Detections[id][DET_SPEED] ) /*server_print("-----------------------------------"); server_print("SpeedHack detected: id: %d", id); server_print("-----------------------------------"); server_print("Time correction: id: %d, dt: %f", id, time - _playerTime[id]); _playerTime[id] = time;*/ if(g_Detections[id][DET_SPEED] >= 250) { ban_user(id, -1, "SpeedHack Detected") //notify_detection(id, "SpeedHack Detected") } } } return FMRES_IGNORED } enum MODEL { MODEL_MDL[32], MODEL_TOPCOLOR[32], MODEL_BOTTOMCOLOR[32] } new g_PlayersModels[MAX_PLAYERS + 1][MODEL] public fw_ClientUserInfoChanged(id, buffer) { if(!is_user_valid_connected(id)) return FMRES_IGNORED static val_model[32], val_top[32], val_bottom[32] engfunc(EngFunc_InfoKeyValue, buffer, "model", val_model, charsmax(val_model)) engfunc(EngFunc_InfoKeyValue, buffer, "topcolor", val_top, charsmax(val_top)) engfunc(EngFunc_InfoKeyValue, buffer, "bottomcolor", val_bottom, charsmax(val_bottom)) if(equali(val_model, g_PlayersModels[id][MODEL_MDL]) && equali(val_top, g_PlayersModels[id][MODEL_TOPCOLOR]) && equali(val_bottom, g_PlayersModels[id][MODEL_BOTTOMCOLOR])) return FMRES_IGNORED else { if(g_Detections[id][DET_MODEL]++ >= 20) { set_user_info(id, "model", g_PlayersModels[id][MODEL_MDL]) set_user_info(id, "topcolor", g_PlayersModels[id][MODEL_TOPCOLOR]) set_user_info(id, "bottomcolor", g_PlayersModels[id][MODEL_BOTTOMCOLOR]) return FMRES_SUPERCEDE } } engfunc(EngFunc_InfoKeyValue, buffer, "model", g_PlayersModels[id][MODEL_MDL], charsmax(g_PlayersModels[])) engfunc(EngFunc_InfoKeyValue, buffer, "topcolor", g_PlayersModels[id][MODEL_TOPCOLOR], charsmax(g_PlayersModels[])) engfunc(EngFunc_InfoKeyValue, buffer, "bottomcolor", g_PlayersModels[id][MODEL_BOTTOMCOLOR], charsmax(g_PlayersModels[])) return FMRES_IGNORED } #define SATCHEL_CHECKED pev_iuser4 #define OFFSET_AMMO_TRIPMINE 317 #define OFFSET_AMMO_SNARK 320 #define EXTRAOFFSET 5 stock bool:_fm_is_ent_visible(index, entity, ignoremonsters = 0) { static Float:start[3], Float:dest[3] pev(index, pev_origin, start) pev(index, pev_view_ofs, dest) xs_vec_add(start, dest, start) pev(entity, pev_origin, dest) engfunc(EngFunc_TraceLine, start, dest, ignoremonsters, index, 0) static Float:fraction get_tr2(0, TR_flFraction, fraction) if (fraction == 1.0 || get_tr2(0, TR_pHit) == entity) return true return false } public fw_SatchelThinkPre(satchel_ent) { if(!pev_valid(satchel_ent) || pev(satchel_ent, SATCHEL_CHECKED)) return HAM_IGNORED static Float: velocity[3] pev(satchel_ent, pev_velocity, velocity) if(velocity[0] || velocity[1] || velocity[2]) return HAM_IGNORED static origin[3], ent pev(satchel_ent, pev_origin, origin) set_pev(satchel_ent, SATCHEL_CHECKED, 1) ent = -1 while((ent = engfunc(EngFunc_FindEntityInSphere, ent, origin, float(get_pcvar_num(g_CvarSatchelRadius)))) != 0) { if(pev_valid(ent)) { static classname[32] pev(ent, pev_classname, classname, charsmax(classname)) if((equal(classname, "info_player_deathmatch") || equal(classname, "info_player_start")) && _fm_is_ent_visible(satchel_ent, ent, 1)) { new id = pev(satchel_ent, pev_owner) if(is_user_valid_connected(id) && ExecuteHam(Ham_IsAlive, id)) { set_pdata_int(id, OFFSET_AMMO_TRIPMINE + 1, get_pdata_int(id,OFFSET_AMMO_TRIPMINE + 1, EXTRAOFFSET) + 1, EXTRAOFFSET) set_hudmessage(0, 255, 0, -1.0, 0.88, 1, 1.0, 4.0, 0.05, 0.2, -1) show_hudmessage(id, "Respawn Guard: satchel removed!") } engfunc(EngFunc_RemoveEntity, satchel_ent) return HAM_SUPERCEDE } } } return HAM_IGNORED } public fw_TripmineSpawnPre(mine_ent) { if(!pev_valid(mine_ent)) return HAM_IGNORED static origin[3], ent pev(mine_ent, pev_origin, origin) ent = -1 while((ent = engfunc(EngFunc_FindEntityInSphere, ent, origin, float(get_pcvar_num(g_CvarTripmineRadius)))) != 0) { if(pev_valid(ent)) { static classname[32] pev(ent, pev_classname, classname, charsmax(classname)) if((equal(classname, "info_player_deathmatch") || equal(classname, "info_player_start")) && _fm_is_ent_visible(mine_ent, ent, 1)) { new id = pev(mine_ent, pev_owner) if(is_user_valid_connected(id) && ExecuteHam(Ham_IsAlive, id) && get_user_weapon(id) == HLW_TRIPMINE) { set_pdata_int(id, OFFSET_AMMO_TRIPMINE, get_pdata_int(id, OFFSET_AMMO_TRIPMINE, EXTRAOFFSET) + 1, EXTRAOFFSET) set_hudmessage(0, 255, 0, -1.0, 0.88, 1, 1.0, 4.0, 0.05, 0.2, -1) show_hudmessage(id, "Respawn Guard: tripmine removed!") } return HAM_SUPERCEDE } } } return HAM_IGNORED } public fw_SnarkThinkPre(snark_ent) { if(!pev_valid(snark_ent)) return HAM_IGNORED static Float: velocity[3] pev(snark_ent, pev_velocity, velocity) if(velocity[0] || velocity[1] || velocity[2]) { if(pev(snark_ent, pev_solid) != SOLID_BBOX) set_pev(snark_ent, pev_solid, SOLID_BBOX) return HAM_IGNORED } else { if(pev(snark_ent, pev_solid) != SOLID_NOT) set_pev(snark_ent, pev_solid, SOLID_NOT) return HAM_IGNORED } return HAM_IGNORED } public fw_TraceLine(Float:start[3], Float:dest[3], ignore_monsters, ent, ptr) { if(!pev_valid(ent) || !pev_valid(g_pSearch)) return FMRES_IGNORED static ent2; ent2 = get_tr2(ptr, TR_pHit) static StartSolid, AllSolid, InOpen, flFraction StartSolid = get_tr2(ptr, TR_StartSolid) AllSolid = get_tr2(ptr, TR_AllSolid) InOpen = get_tr2(ptr, TR_InOpen) get_tr2(ptr, TR_flFraction, flFraction) if((flFraction >= 1.0 || ent2 == g_pSearch) && StartSolid) { if((!AllSolid || InOpen) || (AllSolid && flFraction >= 1.0)) { EnableHamForward(g_Ham_TraceAttack) gm_ent = ent return FMRES_IGNORED } } g_pSearch = FM_NULLENT gm_ent = FM_NULLENT return FMRES_IGNORED } public fw_FindEntityInSphere(start, Float:origin[3], Float:radius) { g_pSearch = get_orig_retval() } public lamp_guard(id) { id -= TASK_LAMP if(g_Detections[id][DET_LAMPING] > 140) g_Detections[id][DET_LAMPING] = 140 else if(g_Detections[id][DET_LAMPING] > 0) g_Detections[id][DET_LAMPING] -= 3 else { g_Detections[id][DET_LAMPING] = 0 remove_task(id + TASK_LAMP) return } set_task(3.0, "lamp_guard", id + TASK_LAMP) } public fw_TraceAttack(ent, attacker, Float: damage, Float: direction[3], trace, damagebits) { DisableHamForward(g_Ham_TraceAttack) if(gm_ent && attacker && gm_ent == attacker) { gm_ent = FM_NULLENT new classname[32] pev(attacker, pev_classname, classname, charsmax(classname)) if(equali(classname, "weapon_gauss")) { if(check_bit(get_pcvar_num(g_CvarGMblocker), GHOST_GAUSS)) return HAM_SUPERCEDE if(get_pcvar_num(g_CvarLampGuard)) { new id = pev(attacker, pev_owner) if(is_user_valid_connected(id) || !check_bit(g_bit_immunity, id)) { g_Detections[id][DET_LAMPING] += 15 !task_exists(id + TASK_LAMP) ? set_task(3.0, "lamp_guard", id + TASK_LAMP) : change_task(id + TASK_LAMP, 10.0) if(g_Detections[id][DET_LAMPING] >= 140) { notify_detection(id, "Lamping Detected") ban_user(id, get_pcvar_num(g_CvarLampPunish), "Lamping Detected") return HAM_SUPERCEDE } else if(g_Detections[id][DET_LAMPING] >= 100) { set_hudmessage(255, 0, 0, -1.0, 0.88, 1, 1.0, 12.0, 0.05, 0.2, -1) show_hudmessage(id, "Lamp Guard: 100%% warning", g_Detections[id][DET_LAMPING]) return HAM_SUPERCEDE } else if(20 <= g_Detections[id][DET_LAMPING] < 100) { switch(g_Detections[id][DET_LAMPING]) { case 20..60: set_hudmessage(0, 255, 0, -1.0, 0.88, 1, 1.0, 12.0, 0.05, 0.2, -1) default: set_hudmessage(255, 0, 0, -1.0, 0.88, 1, 1.0, 12.0, 0.05, 0.2, -1) } show_hudmessage(id, "Lamp Guard: %d%% warning", g_Detections[id][DET_LAMPING]) } } } } else if(check_bit(get_pcvar_num(g_CvarGMblocker), GHOST_EXPLOSIVE)) return HAM_SUPERCEDE } return HAM_IGNORED } register_cvars() { g_CvarBanSystem = register_cvar("hl_ac_ban_system", "10") g_CvarNotify = register_cvar("hl_ac_notify", "13") g_CvarNotifyHud = register_cvar("hl_ac_notify_hud", "255 0 0 -1.0 0.35 1 1.0 12.0 0.05 0.2") g_CvarLog = register_cvar("hl_ac_log", "1") g_CvarProtector = register_cvar("hl_ac_hlprotector", "1") g_CvarProtectorPunish = register_cvar("hl_ac_hlprotector_bantime", "7200") g_CvarProxy = register_cvar("hl_ac_hlproxy", "1") g_CvarProxyPunish = register_cvar("hl_ac_hlproxy_bantime", "7200") g_CvarCdhack = register_cvar("hl_ac_cdhack", "1") g_CvarCdhackPunish = register_cvar("hl_ac_cdhack_bantime", "0") g_CvarOpengf = register_cvar("hl_ac_opengf32", "1") g_CvarOpengfPunish = register_cvar("hl_ac_opengf32_bantime", "0") g_CvarOpenGL = register_cvar("hl_ac_opengl", "1") g_CvarOpenGLPunish = register_cvar("hl_ac_opengl_bantime", "0") g_CvarAlias = register_cvar("hl_ac_alias", "1") g_CvarAliasPunish = register_cvar("hl_ac_alias_bantime", "7200") g_CvarGMblocker = register_cvar("hl_ac_ghostmining_block", "1") g_CvarLampGuard = register_cvar("hl_ac_lamp_guard", "1") g_CvarLampPunish = register_cvar("hl_ac_lamp_guard_bantime", "-1") g_CvarRespGuard = register_cvar("hl_ac_respawn_guard", "3") g_CvarTripmineRadius = register_cvar("hl_ac_tripmine_radius", "100") g_CvarSatchelRadius = register_cvar("hl_ac_satchel_radius", "125") } public fullupdate_hook(id) { if(g_Detections[id][DET_FUPD_SPAM] ++ > 40) ban_user(id, -1, "Fullupdate Spam Detected") } public plugin_precache() { if(!is_running("valve")) { new error[64], mod[32]; get_modname(mod, charsmax(mod)) formatex(error, charsmax(error), "Unsupported mod ^"%s^"", mod) set_fail_state(error) } server_cmd("mp_consistency 1") new PluginConfDir[512]; get_localinfo("amx_configdir", PluginConfDir, charsmax(PluginConfDir)) format(PluginConfDir, charsmax(PluginConfDir), "%s/%s", PluginConfDir, DIR_CONF) register_cvars() config_load(PluginConfDir) load_aliases(PluginConfDir) load_white_list(PluginConfDir) load_files_check(PluginConfDir) if(get_pcvar_num(g_CvarOpenGL)) { opengl_load_dll(PluginConfDir) if(file_exists(FILE_OPENGL)) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, FILE_OPENGL) } /*if(get_pcvar_num(g_CvarGMblocker) || get_pcvar_num(g_CvarLampGuard)) { register_forward(FM_FindEntityInSphere, "fw_FindEntityInSphere", 1) register_forward(FM_TraceLine, "fw_TraceLine", 1) g_Ham_TraceAttack = RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack") DisableHamForward(g_Ham_TraceAttack) }*/ new resp_guard = get_pcvar_num(g_CvarRespGuard) if(resp_guard) { if(check_bit(resp_guard, RESP_TRIPMINE)) RegisterHam(Ham_Spawn, "monster_tripmine", "fw_TripmineSpawnPre") if(check_bit(resp_guard, RESP_SATCHEL)) RegisterHam(Ham_Think, "monster_satchel", "fw_SatchelThinkPre") } g_MaxPlayers = get_maxplayers() } public plugin_end() { ArrayDestroy(g_Aliases) TrieDestroy(g_WhiteList) } public client_disconnect(id) { clr_bit(g_bit_immunity,id); clr_bit(g_bit_is_connected, id) g_alias_check_runing[id] = 0 g_alias[id] = 0 g_alias_control[id] = 0 g_alias_progress[id] = 0 g_alias_repeat[id] = 0 for(new i = 0; i < DETECTIONS; i++) g_Detections[id][i] = 0 remove_task(id + TASK_START) remove_task(id + TASK_ALIAS) remove_task(id + TASK_LAMP) } public inconsistent_file(id, const filename[], reason[64]) { if(equali(filename, FILE_OPENGL)) { g_Detections[id][DET_OPENGL] = 1 return PLUGIN_HANDLED } return PLUGIN_CONTINUE } public client_putinserver(id) { set_bit(g_bit_is_connected, id) if(is_user_bot(id) || is_user_hltv(id)) { set_bit(g_bit_immunity, id) return PLUGIN_CONTINUE } new ip[16], authid[32] get_user_ip(id, ip, charsmax(ip), 1) get_user_authid(id, authid, charsmax(authid)) if(TrieKeyExists(g_WhiteList, ip) || TrieKeyExists(g_WhiteList, authid)) { new logmsg[256], name[32] get_user_name(id, name, charsmax(name)) formatex(logmsg, charsmax(logmsg), "^"%s <%s><%s> whitelist^"", name, authid, ip) log_msg(logmsg) set_bit(g_bit_immunity, id) return PLUGIN_CONTINUE } set_task(10.0, "start_checks", id + TASK_START) return PLUGIN_CONTINUE } public client_command(id) { if(!is_user_valid_connected(id) || check_bit(g_bit_immunity, id)) return PLUGIN_CONTINUE new command[128]; read_argv(0, command, charsmax(command)) // Thanks to draft and his Zeta if(g_alias_check_runing[id] && g_alias_progress[id] < g_AliasesSize) { new alias_str[256], alias[20], control_alias[20], info[128], ban[20] ArrayGetString(g_Aliases, g_alias_progress[id], alias_str, charsmax(alias_str)) parse(alias_str, alias, charsmax(alias), control_alias, charsmax(control_alias), info, charsmax(info), ban, charsmax(ban)) if(equali(command, alias)) { g_alias[id]++ return PLUGIN_HANDLED } else if(equali(command, control_alias)) { g_alias_control[id]++ if(g_alias[id] == g_alias_control[id]) g_alias_progress[id]++ else { if(g_alias_repeat[id] <= 4) g_alias_repeat[id]++ else { if(containi(info, "detected") == -1) add(info, charsmax(info), " Detected") g_alias_progress[id] - g_CustomAliases >= 1 ? format(info, charsmax(info), "%s [%d]", info, g_alias_progress[id] - g_CustomAliases) : format(info, charsmax(info), "%s", info) notify_detection(id, info) ban_user(id, str_to_num(ban), info) g_alias_check_runing[id] = 0 g_alias[id] = 0 g_alias_control[id] = 0 g_alias_progress[id] = 0 g_alias_repeat[id] = 0 g_alias_repeat[id] = 0 return PLUGIN_HANDLED } } if(g_alias_progress[id] < g_AliasesSize) set_task(0.5, "alias_check", id + TASK_ALIAS) else { g_alias_check_runing[id] = 0 g_alias[id] = 0 g_alias_control[id] = 0 g_alias_progress[id] = 0 g_alias_repeat[id] = 0 g_alias_repeat[id] = 0 } return PLUGIN_HANDLED } } return PLUGIN_CONTINUE } public start_checks(id) { id -= TASK_START if(get_pcvar_num(g_CvarOpenGL) && file_exists(FILE_OPENGL) && !g_Detections[id][DET_OPENGL]) { notify_detection(id, "OpenGL Hack Detected") ban_user(id, get_pcvar_num(g_CvarOpenGLPunish), "OpenGL Hack Detected") return } if(get_pcvar_num(g_CvarProxy)) { new value[4], setinfo[][] = {"_ip", "_cp", "_cmd"} for(new i = 0; i < sizeof setinfo; i++) { get_user_info(id, setinfo[i], value, charsmax(value)) if(value[0]) { notify_detection(id, "HLProxy Detected") ban_user(id, get_pcvar_num(g_CvarProxyPunish), "HLProxy Detected") return } } } set_task(10.0, "alias_check", id + TASK_ALIAS) } public alias_check(id) { id -= TASK_ALIAS if(g_alias_progress[id] < g_AliasesSize) { g_alias_check_runing[id] = 1 new alias_str[256], alias[20], control_alias[20] ArrayGetString(g_Aliases, g_alias_progress[id], alias_str, charsmax(alias_str)) parse(alias_str, alias, charsmax(alias), control_alias, charsmax(control_alias)) client_cmd(id, "%s;%s", alias, control_alias) } } log_msg(const message[]) { if(!get_pcvar_num(g_CvarLog)) return new PluginLogDir[512] get_localinfo("amx_configdir", PluginLogDir, charsmax(PluginLogDir)) format(PluginLogDir, charsmax(PluginLogDir), "%s/%s/%s", PluginLogDir, DIR_CONF, DIR_LOGS) if(!dir_exists(PluginLogDir)) mkdir(PluginLogDir) new datestr[11];get_time("%Y%m%d", datestr, charsmax(datestr)) format(PluginLogDir, charsmax(PluginLogDir), "%s/L%s.log", PluginLogDir, datestr) log_to_file(PluginLogDir, "%s", message) } notify_detection(cheater, message[]) { new name[32], ip[16], authid[24], logmsg[256] get_user_name(cheater, name, charsmax(name)) get_user_ip(cheater, ip, charsmax(ip), 1) get_user_authid(cheater, authid, charsmax(authid)) formatex(logmsg, charsmax(logmsg), "^"%s <%s><%s> %s^"", name, authid, ip, message) log_msg(logmsg) new mode = get_pcvar_num(g_CvarNotify) if(!mode) return static hud_params[10][6] if(!hud_params[0][0]) { new hud_string[64] get_pcvar_string(g_CvarNotifyHud, hud_string, charsmax(hud_string)) explode_string(hud_params, sizeof hud_params, charsmax(hud_params[]), hud_string, ' ') } set_hudmessage(str_to_num(hud_params[0]), str_to_num(hud_params[1]), str_to_num(hud_params[2]), str_to_float(hud_params[3]), str_to_float(hud_params[4]), str_to_num(hud_params[5]), str_to_float(hud_params[6]), str_to_float(hud_params[7]), str_to_float(hud_params[8]), str_to_float(hud_params[9]), -1) if(check_bit(mode, NOTIFY_ALL_HUD)) show_hudmessage(0, "%s %s - %s", PREFIX, name, message) if(check_bit(mode, NOTIFY_ALL_CHAT)) client_print(0, print_chat, "%s %s - %s", PREFIX, name, message) for(new id = 1; id <= g_MaxPlayers; id++) { if(!is_user_valid_connected(id)) continue if(get_user_flags(id) & ADMIN_BAN) { if(check_bit(mode, NOTIFY_ADMIN_HUD)) show_hudmessage(id, "%s %s - %s", PREFIX, name, message) if(check_bit(mode, NOTIFY_ADMIN_CHAT)) client_print(id, print_chat, "%s %s - %s", PREFIX, name, message) } else if(id == cheater) { if(check_bit(mode, NOTIFY_CHEATER_HUD)) show_hudmessage(id, "%s %s", PREFIX, message) if(check_bit(mode, NOTIFY_CHEATER_CHAT)) client_print(id, print_chat, "%s %s", PREFIX, message) } } } // Thanks to Brad and ConnorMcLeod for config loading code config_load(const PluginConfDir[]) { new temp[512]; formatex(temp, charsmax(temp), "%s/%s", PluginConfDir, FILE_SETTINGS) new file = fopen(temp, "rt") if(file) { new buffer[256], cvar[32], value[480] while(!feof(file)) { fgets(file, buffer, charsmax(buffer));trim(buffer) if(buffer[0] && !equal(buffer, "//", 2) && !equal(buffer, ";", 1)) { strbreak(buffer, cvar, charsmax(cvar), value, charsmax(value)) remove_quotes(value) if(equal(cvar, "hl_ac_notify_hud")) set_cvar_string(cvar, value) else if(value[0] == 0 || isalpha(value[0])) set_cvar_string(cvar, value) else if(contain(value, ".")) set_cvar_float(cvar, floatstr(value)) else set_cvar_num(cvar, str_to_num(value)) } } fclose(file) } else { file = fopen(temp, "wt") if(!file) return new szPluginFileName[96] new iPlugin = get_plugin(-1, szPluginFileName, charsmax(szPluginFileName)) server_print("%s Config file is missing. Creating...", PREFIX) fprintf(file, "; ^"%s^" configuration file^n", PLUGIN) fprintf(file, "; Author : ^"%s^"^n", AUTHOR) fprintf(file, "; Version : ^"%s^"^n", VERSION) fprintf(file, "; File : ^"%s^"^n", szPluginFileName) fprintf(file, "^n; Cvars :^n") new iMax = get_plugins_cvarsnum() new iTempId, iPcvar, szCvarName[256], szCvarValue[128] for(new i; i