Code: Select all
#include <amxmodx>#include <sqlx>#include <engine> //#define USE_AFK_STATUS #if defined USE_AFK_STATUS#include <user_afk_status>new cvar_afktime#endif #define VERSION "2.1.2"#define MOTD_SIZE 1536 new g_KsRecord, g_MaxPlayers, g_HudSync, g_KsRecordOwner[32], g_KillStreak[33], g_PersonalRecord[33], bool:g_IsLoading[33], bool:g_Informer[33], cvar_Host, cvar_User, cvar_Password, cvar_Database, cvar_Table,cvar_MinKills, cvar_AdvertFreq,cvar_MinPlayers, cvar_Sounds, cvar_PruneDays, cvar_SaveBy, Handle:g_SqlTuple, g_Query[512], g_Table[32] enum{ SoundBrokeRecord, SoundAnnounce} new const g_Sounds[][] ={ "misc/mkwelldone.wav", "buttons/bell1.wav"} public plugin_precache(){ cvar_Sounds = register_cvar("ksr_sound", "0") if(get_pcvar_num(cvar_Sounds)) { for(new i = 0; i < sizeof g_Sounds; i++) precache_sound(g_Sounds[i]) }} public plugin_init(){ register_plugin("Killstreak records", VERSION, "beast") register_cvar("ksr", VERSION, FCVAR_SPONLY | FCVAR_SERVER) register_event("DeathMsg", "EventDeathMsg", "a") register_dictionary("ksr.txt") register_clcmd("say /ksr", "Ksr") register_clcmd("say_team /ksr", "Ksr") register_clcmd("say /myksr", "MyKsr") register_clcmd("say_team /myksr", "MyKsr") register_clcmd("say /ksinformer", "KsInformer") register_clcmd("say_team /ksinformer", "KsInformer") register_clcmd("say /kstop", "ShowKsTop") register_clcmd("say_team /kstop", "ShowKsTop") cvar_Host = register_cvar("ksr_host", "localhost") cvar_User = register_cvar("ksr_user", "root") cvar_Password = register_cvar("ksr_password", "") cvar_Database = register_cvar("ksr_database", "") cvar_Table = register_cvar("ksr_table", "ks_records") cvar_MinKills = register_cvar("ksr_min_kills", "2") cvar_AdvertFreq = register_cvar("ksr_advert_freq", "600") cvar_MinPlayers = register_cvar("ksr_min_players", "2") cvar_PruneDays = register_cvar("ksr_prune", "30") cvar_SaveBy = register_cvar("ksr_save_by", "3") // 1 - steamid, 2 - IP, 3 - Nick #if defined USE_AFK_STATUS cvar_afktime = register_cvar("ksr_afktime", "5") #endif register_think("KsrTimer", "KsrTimer") new ent do ent = create_entity("info_null") while(!is_valid_ent(ent)) entity_set_string(ent, EV_SZ_classname, "KsrTimer") entity_set_float(ent, EV_FL_nextthink, get_gametime() + random_float(60.0, 120.0)) g_MaxPlayers = get_maxplayers() g_HudSync = CreateHudSyncObj()} public plugin_cfg() set_task(1.0, "InitSql") public InitSql(){ new host[64], user[32], password[32], database[32] get_pcvar_string(cvar_Host, host, charsmax(host)) get_pcvar_string(cvar_User, user, charsmax(user)) get_pcvar_string(cvar_Password, password, charsmax(password)) get_pcvar_string(cvar_Database, database, charsmax(database)) get_pcvar_string(cvar_Table, g_Table, charsmax(g_Table)) g_SqlTuple = SQL_MakeDbTuple(host, user, password, database) // create table formatex(g_Query, charsmax(g_Query), "CREATE TABLE IF NOT EXISTS %s \ (Authid VARCHAR(34), Name VARCHAR(32), KS_record INT, Date TIMESTAMP NOT NULL \ DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY(Authid)) \ ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC", g_Table) SQL_ThreadQuery(g_SqlTuple, "QueryHandle", g_Query) // delete inactive players formatex(g_Query, charsmax(g_Query), "DELETE FROM %s WHERE \ Date < DATE_SUB(NOW(), INTERVAL %d DAY)", g_Table, get_pcvar_num(cvar_PruneDays)) SQL_ThreadQuery(g_SqlTuple, "QueryHandle", g_Query) // delete empty records formatex(g_Query, charsmax(g_Query), "DELETE FROM %s WHERE KS_record = 0", g_Table) SQL_ThreadQuery(g_SqlTuple, "QueryHandle", g_Query) // select current record holder formatex(g_Query, charsmax(g_Query), "SELECT * FROM %s \ ORDER BY KS_record DESC, Date ASC LIMIT 1", g_Table) SQL_ThreadQuery(g_SqlTuple, "SelectKsRecord", g_Query) } public KsrTimer(ent){ entity_set_float(ent, EV_FL_nextthink, get_gametime() + get_pcvar_float(cvar_AdvertFreq)) if(get_pcvar_num(cvar_Sounds)) client_cmd(0, "spk %s", g_Sounds[SoundAnnounce]) set_hudmessage(0, 255, 20, -1.0, 0.77, 0, 6.0, 8.0, 1.0, 3.0, -1) show_hudmessage(0, "%L", LANG_PLAYER, "CURRENT_GLOBAL_REC", g_KsRecordOwner, g_KsRecord) } public client_disconnect(id){ g_PersonalRecord[id] = 0 g_KillStreak[id] = 0 g_Informer[id] = false g_IsLoading[id] = false} public client_putinserver(id){ if(is_user_bot(id) || is_user_hltv(id)) return PLUGIN_CONTINUE g_IsLoading[id] = true get_gametime() < 15.0 ? set_task(random_float(1.0, 3.0), "PrepareQuery", id) : set_task(1.0, "PrepareQuery", id) return PLUGIN_CONTINUE} public PrepareQuery(id){ if(!is_user_connected(id)) return new data[1] data[0] = id formatex(g_Query, charsmax(g_Query), "SELECT KS_record FROM %s WHERE Authid = '%s'", g_Table, GetAuthid(id)) SQL_ThreadQuery(g_SqlTuple, "LoadKsRecord", g_Query, data, 1)} public EventDeathMsg(){ new killer = read_data(1), victim = read_data(2), minPlNum = get_pcvar_num(cvar_MinPlayers) g_KillStreak[victim] = 0 new plNum, players[32] get_players(players, plNum, "ch") if(plNum < minPlNum || !(1 <= killer <= g_MaxPlayers) || killer == victim || is_user_bot(killer) || g_IsLoading[killer]) return PLUGIN_CONTINUE #if defined USE_AFK_STATUS if(get_user_afktime(victim) >= get_pcvar_float(cvar_afktime)) { client_print(killer, print_chat, "[KSR] %L", killer, "VICTIM_AFK") return PLUGIN_CONTINUE } #endif g_KillStreak[killer]++ if(g_Informer[killer]) client_print(killer, print_center, "KS: %d", g_KillStreak[killer]) if(g_KillStreak[killer] > g_PersonalRecord[killer]) // broke personal record { new sounds = get_pcvar_num(cvar_Sounds), minKills = get_pcvar_num(cvar_MinKills) g_PersonalRecord[killer] = g_KillStreak[killer] new nick[32] get_user_name(killer, nick, charsmax(nick)) if(g_KillStreak[killer] > g_KsRecord) // broke global record { g_KsRecord = g_KillStreak[killer] copy(g_KsRecordOwner, charsmax(g_KsRecordOwner), nick) if(g_KsRecord >= minKills) { if(sounds) client_cmd(0, "spk %s", g_Sounds[SoundBrokeRecord]) set_hudmessage(255, 100, 0, -1.0, 0.28, 1, 6.0, 12.0, 1.0, 2.0) ShowSyncHudMsg(0, g_HudSync, "%L", LANG_PLAYER, "BROKE_GREC", g_KsRecordOwner, g_KillStreak[killer]) client_print(0, print_chat, "[KSR] %L", LANG_PLAYER, "BROKE_GREC", g_KsRecordOwner, g_KillStreak[killer]) } } else if(g_PersonalRecord[killer] >= minKills) { if(sounds) client_cmd(killer, "spk %s", g_Sounds[SoundBrokeRecord]) client_print(killer, print_chat, "[KSR] %L", killer, "BROKE_PREC", g_PersonalRecord[killer]) } formatex(g_Query, charsmax(g_Query), "UPDATE %s SET Name = '%s', \ KS_record = %d WHERE Authid = '%s'", g_Table, GetSecureName(nick), g_PersonalRecord[killer], GetAuthid(killer)) SQL_ThreadQuery(g_SqlTuple, "QueryHandle", g_Query) } return PLUGIN_CONTINUE} public Ksr(id){ if(g_KsRecord) client_print(id, print_chat, "[KSR] %L", id, "CURRENT_GLOBAL_REC", g_KsRecordOwner, g_KsRecord) else client_print(id, print_chat, "[KSR] %L", id, "NO_GREC")} public MyKsr(id){ if(g_PersonalRecord[id]) client_print(id, print_chat, "[KSR] %L", id, "PERSONAL_REC", g_PersonalRecord[id]) else client_print(id, print_chat, "[KSR] %L", id, "NO_PREC")} public KsInformer(id){ if(!g_Informer[id]) { g_Informer[id] = true client_print(id, print_chat, "[KSR] %L", id, "INFORMER_ON") if(g_KillStreak[id]) client_print(id, print_center, "KS: %d", g_KillStreak[id]) } else { g_Informer[id] = false client_print(id, print_chat, "[KSR] %L", id, "INFORMER_OFF") }} public ShowKsTop(id){ new data[1] data[0] = id formatex(g_Query, charsmax(g_Query), "SELECT * FROM %s ORDER BY KS_record DESC, Date \ ASC LIMIT 15", g_Table) SQL_ThreadQuery(g_SqlTuple, "ShowTop15", g_Query, data, 1)} public ShowTop15(failState, Handle:query, error[], errCode, data[]){ if(failState == TQUERY_CONNECT_FAILED) return log_amx("Could not connect to SQL database.") else if(failState == TQUERY_QUERY_FAILED) return log_amx("Error in query [ShowTop15]") if(errCode) return log_amx("Error in query: %s", error) new id = data[0] if(!SQL_NumResults(query)) { client_print(id, print_chat, "[KSR] %L", id, "NO_GREC") return PLUGIN_HANDLED } new name[32], data[MOTD_SIZE], record, len, place len = formatex(data[len], MOTD_SIZE - len, "<body bgcolor=#383838><center>\ <table width=600 cellspacing=0 border=1 bordercolor=#00023C style=color:#00023C;text-align:center;>\ <tr style=font-weight:bold;background:#666666;><th>#</th><th>NICK</th><th>KILLSTREAK</th></tr>") while(SQL_MoreResults(query)) { place++ SQL_ReadResult(query, 1, name, charsmax(name)) replace_all(name, charsmax(name), "<", "<") replace_all(name, charsmax(name), ">", ">") record = SQL_ReadResult(query, 2) len += formatex(data[len], MOTD_SIZE - len, "<tr style=background:%s>\ <td>%d</td>", place % 2 != 0 ? "CECECE" : "B1B1B1", place) len += formatex(data[len], MOTD_SIZE - len, "<td>%s</td>", name) len += formatex(data[len], MOTD_SIZE - len, "<td>%i</td></tr>", record) SQL_NextRow(query) } show_motd(id, data, "Killstreak TOP15") return PLUGIN_CONTINUE} public SelectKsRecord(failState, Handle:query, error[], errCode){ if(failState == TQUERY_CONNECT_FAILED) return log_amx("Could not connect to SQL database.") else if(failState == TQUERY_QUERY_FAILED) return log_amx("Error in query [SelectKsRecord]") if(errCode) return log_amx("Error in query: %s", error) if(!SQL_NumResults(query)) return PLUGIN_CONTINUE SQL_ReadResult(query, 1, g_KsRecordOwner, charsmax(g_KsRecordOwner)) g_KsRecord = SQL_ReadResult(query, 2) return PLUGIN_CONTINUE} public LoadKsRecord(failState, Handle:query, error[], errCode, data[], dataSize){ if(failState == TQUERY_CONNECT_FAILED) return log_amx("Could not connect to SQL database.") else if(failState == TQUERY_QUERY_FAILED) return log_amx("Error in query [LoadKsRecord]") if(errCode) return log_amx("Error in query: %s", error) new id = data[0], nick[32] get_user_name(id, nick, charsmax(nick)) if(!SQL_NumResults(query)) { formatex(g_Query, charsmax(g_Query), "INSERT INTO %s \ (Authid, Name, KS_record) VALUES('%s', '%s', 0)", g_Table, GetAuthid(id), GetSecureName(nick)) SQL_ThreadQuery(g_SqlTuple, "AddRecord", g_Query, data, 1) return PLUGIN_CONTINUE } g_IsLoading[id] = false g_PersonalRecord[id] = SQL_ReadResult(query, 0) formatex(g_Query, charsmax(g_Query), "UPDATE %s SET Name = '%s', Date = NOW() WHERE Authid = '%s'", g_Table, GetSecureName(nick), GetAuthid(id)) SQL_ThreadQuery(g_SqlTuple, "QueryHandle", g_Query) return PLUGIN_CONTINUE} public AddRecord(failState, Handle:query, error[], errCode, data[]){ if(failState == TQUERY_CONNECT_FAILED) return log_amx("Could not connect to SQL database.") else if(failState == TQUERY_QUERY_FAILED) return log_amx("Error in query [AddRecord]") if(errCode) return log_amx("Error in query: %s", error) g_IsLoading[data[0]] = false return PLUGIN_CONTINUE} public QueryHandle(failState, Handle:query, error[], errCode){ if(failState == TQUERY_CONNECT_FAILED) return log_amx("Could not connect to SQL database.") else if(failState == TQUERY_QUERY_FAILED) return log_amx("Error in query [QueryHandle]") if(errCode) return log_amx("Error in query: %s", error) return PLUGIN_CONTINUE} GetAuthid(id){ new authId[34], saveBy = get_pcvar_num(cvar_SaveBy) switch(saveBy) { case 1: get_user_authid(id, authId, charsmax(authId)) case 2: get_user_ip(id, authId, charsmax(authId), 1) case 3: get_user_name(id, authId, charsmax(authId)) default: get_user_authid(id, authId, charsmax(authId)) } return authId} // Credits hleVGetSecureName(const name[]){ new secureName[64] copy(secureName, charsmax(secureName), name) replace_all(secureName, charsmax(secureName), "\", "\\") replace_all(secureName, charsmax(secureName), "'", "\") replace_all(secureName, charsmax(secureName), "`", "\`") return secureName} public plugin_end() SQL_FreeHandle(g_SqlTuple)