Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * CSStatsX SQL v. 0.7.4
- * by serfreeman1337 http://1337.uz/
- */
- #include <amxmodx>
- #include <sqlx>
- #include <fakemeta>
- #include <hamsandwich>
- #define PLUGIN "CSStatsX SQL"
- #define VERSION "0.7.4"
- #define AUTHOR "serfreeman1337" // AKA SerSQL1337
- #define LASTUPDATE "06, July (07), 2016"
- #if AMXX_VERSION_NUM < 183
- #define MAX_PLAYERS 32
- #define MAX_NAME_LENGTH 32
- new MaxClients
- #endif
- /* - SQL - */
- new Handle:sql
- new Handle:sql_con
- /* - КОНСТАНТЫ - */
- enum _:sql_que_type // тип sql запроса
- {
- SQL_DUMMY,
- SQL_INITDB, // автоматическое созданием таблиц
- SQL_LOAD, // загрузка статистики
- SQL_UPDATE, // обновление
- SQL_INSERT, // внесение новой записи
- SQL_UPDATERANK, // получение ранков игроков,
- SQL_GETSTATS, // потоквый запрос на get_stats
- // 0.7
- SQL_GETWSTATS, // статистика по оружию
- SQL_GETSESSID, // id сессии статистики за карту
- SQL_GETSESTATS, // статистика по картам
- SQL_AUTOCLEAR // чистка БД от неактивных записей
- }
- enum _:load_state_type // состояние получение статистики
- {
- LOAD_NO, // данных нет
- LOAD_WAIT, // ожидание данных
- LOAD_NEWWAIT, // новая запись, ждем ответа
- LOAD_UPDATE, // перезагрузить после обновления
- LOAD_NEW, // новая запись
- LOAD_OK // есть данные
- }
- enum _:row_ids // столбцы таблицы
- {
- ROW_ID,
- ROW_STEAMID,
- ROW_NAME,
- ROW_IP,
- ROW_SKILL,
- ROW_KILLS,
- ROW_DEATHS,
- ROW_HS,
- ROW_TKS,
- ROW_SHOTS,
- ROW_HITS,
- ROW_DMG,
- ROW_BOMBDEF,
- ROW_BOMBDEFUSED,
- ROW_BOMBPLANTS,
- ROW_BOMBEXPLOSIONS,
- ROW_H0,
- ROW_H1,
- ROW_H2,
- ROW_H3,
- ROW_H4,
- ROW_H5,
- ROW_H6,
- ROW_H7,
- ROW_ONLINETIME,
- // 0.7
- ROW_CONNECTS,
- ROW_ROUNDT,
- ROW_WINT,
- ROW_ROUNDCT,
- ROW_WINCT,
- // 0.7.2
- ROW_ASSISTS,
- ROW_FIRSTJOIN,
- ROW_LASTJOIN,
- // 0.7
- ROW_SESSIONID,
- ROW_SESSIONNAME
- }
- new const row_names[row_ids][] = // имена столбцов
- {
- "id",
- "steamid",
- "name",
- "ip",
- "skill",
- "kills",
- "deaths",
- "hs",
- "tks",
- "shots",
- "hits",
- "dmg",
- "bombdef",
- "bombdefused",
- "bombplants",
- "bombexplosions",
- "h_0",
- "h_1",
- "h_2",
- "h_3",
- "h_4",
- "h_5",
- "h_6",
- "h_7",
- "connection_time",
- // 0.7
- "connects",
- "roundt",
- "wint",
- "roundct",
- "winct",
- // 0.7.2
- "assists",
- "first_join",
- "last_join",
- // 0.7
- "session_id",
- "session_map"
- }
- enum _:STATS
- {
- STATS_KILLS,
- STATS_DEATHS,
- STATS_HS,
- STATS_TK,
- STATS_SHOTS,
- STATS_HITS,
- STATS_DMG,
- STATS_END
- }
- enum _:KILL_EVENT
- {
- NORMAL,
- SUICIDE,
- WORLD,
- WORLDSPAWN
- }
- const QUERY_LENGTH = 1472 // размер переменной sql запроса
- #define STATS2_DEFAT 0
- #define STATS2_DEFOK 1
- #define STATS2_PLAAT 2
- #define STATS2_PLAOK 3
- #define STATS2_END 4
- new const task_rankupdate = 31337
- new const task_confin = 21337
- new const task_flush = 11337
- #define MAX_CWEAPONS 6
- #define MAX_WEAPONS CSW_P90 + 1 + MAX_CWEAPONS
- #define HIT_END HIT_RIGHTLEG + 1
- // 0.7
- enum _:row_weapons_ids // столбцы таблицы
- {
- ROW_WEAPON_ID,
- ROW_WEAPON_PLAYER,
- ROW_WEAPON_NAME,
- ROW_WEAPON_KILLS,
- ROW_WEAPON_DEATHS,
- ROW_WEAPON_HS,
- ROW_WEAPON_TKS,
- ROW_WEAPON_SHOTS,
- ROW_WEAPON_HITS,
- ROW_WEAPON_DMG,
- ROW_WEAPON_H0,
- ROW_WEAPON_H1,
- ROW_WEAPON_H2,
- ROW_WEAPON_H3,
- ROW_WEAPON_H4,
- ROW_WEAPON_H5,
- ROW_WEAPON_H6,
- ROW_WEAPON_H7
- }
- new const row_weapons_names[row_weapons_ids][] = // имена столбцов
- {
- "id",
- "player_id",
- "weapon",
- "kills",
- "deaths",
- "hs",
- "tks",
- "shots",
- "hits",
- "dmg",
- "h_0",
- "h_1",
- "h_2",
- "h_3",
- "h_4",
- "h_5",
- "h_6",
- "h_7"
- }
- enum _:row_maps_ids
- {
- ROW_MAP_ID,
- ROW_MAP_SESSID,
- ROW_MAP_PLRID,
- ROW_MAP_MAP,
- ROW_MAP_SKILL,
- ROW_MAP_KILLS,
- ROW_MAP_DEATHS,
- ROW_MAP_HS,
- ROW_MAP_TKS,
- ROW_MAP_SHOTS,
- ROW_MAP_HITS,
- ROW_MAP_DMG,
- ROW_MAP_BOMBDEF,
- ROW_MAP_BOMBDEFUSED,
- ROW_MAP_BOMBPLANTS,
- ROW_MAP_BOMBEXPLOSIONS,
- ROW_MAP_H0,
- ROW_MAP_H1,
- ROW_MAP_H2,
- ROW_MAP_H3,
- ROW_MAP_H4,
- ROW_MAP_H5,
- ROW_MAP_H6,
- ROW_MAP_H7,
- ROW_MAP_ONLINETIME,
- ROW_MAP_CONNECTS,
- ROW_MAP_ROUNDT,
- ROW_MAP_WINT,
- ROW_MAP_ROUNDCT,
- ROW_MAP_WINCT,
- ROW_MAP_ASSISTS,
- ROW_MAP_FIRSTJOIN,
- ROW_MAP_LASTJOIN,
- }
- /* - СТРУКТУРА ДАННЫХ - */
- // 0.7
- enum _:STATS3_END
- {
- STATS3_CURRENTTEAM, // тек. команда игрока (определяется в начале раунда)
- STATS3_CONNECT, // подключения к серверу
- STATS3_ROUNDT, // раунды за теров
- STATS3_WINT, // побед за теров
- STATS3_ROUNDCT, // раунды за спецов
- STATS3_WINCT, // побед за спецов
- // 0.7.2
- STATS3_ASSIST // помощь в убийстве
- }
- enum _:sestats_array_struct
- {
- SESTATS_ID,
- SESTATS_PLAYERID,
- SESTATS_MAP[MAX_NAME_LENGTH],
- SESTATS_STATS[8],
- SESTATS_HITS[8],
- SESTATS_STATS2[4],
- SESTATS_STATS3[STATS3_END],
- Float:SESTATS_SKILL,
- SESTATS_ONLINETIME,
- SESTATS_FIRSTJOIN,
- SESTATS_LASTJOIN
- }
- enum _:player_data_struct
- {
- PLAYER_ID, // ид игрока в базе данных
- PLAYER_LOADSTATE, // состояние загрузки статистики игрока
- PLAYER_RANK, // ранк игрока
- PLAYER_STATS[STATS_END], // статистика игрока
- PLAYER_STATSLAST[STATS_END], // разница в статистики
- PLAYER_HITS[HIT_END], // статистика попаданий
- PLAYER_HITSLAST[HIT_END], // разница в статистике попаданий
- PLAYER_STATS2[4], // статистика cstrike
- PLAYER_STATS2LAST[4], // разница
- Float:PLAYER_SKILL, // скилл
- PLAYER_ONLINE, // время онлайна
- // я не помню чо за diff и last, но без этого не работает XD
- Float:PLAYER_SKILLLAST,
- PLAYER_ONLINEDIFF,
- PLAYER_ONLINELAST,
- PLAYER_NAME[MAX_NAME_LENGTH * 3],
- PLAYER_STEAMID[30],
- PLAYER_IP[16],
- // 0.7
- PLAYER_STATS3[STATS3_END], // stast3
- PLAYER_STATS3LAST[STATS3_END], // stast3
- PLAYER_FIRSTJOIN,
- PLAYER_LASTJOIN
- }
- enum _:stats_cache_struct // кеширование для get_stats
- {
- CACHE_NAME[32],
- CACHE_STEAMID[30],
- CACHE_STATS[8],
- CACHE_HITS[8],
- CACHE_SKILL,
- bool:CACHE_LAST,
- // 0.5.1
- CACHE_ID,
- CACHE_TIME,
- // 0.7
- CACHE_STATS2[4],
- CACHE_STATS3[STATS3_END],
- CACHE_FIRSTJOIN,
- CACHE_LASTJOIN
- }
- enum _:cvar_set
- {
- CVAR_SQL_HOST,
- CVAR_SQL_USER,
- CVAR_SQL_PASS,
- CVAR_SQL_DB,
- CVAR_SQL_TABLE,
- CVAR_SQL_TYPE,
- CVAR_SQL_CREATE_DB,
- CVAR_UPDATESTYLE,
- CVAR_RANK,
- CVAR_RANKFORMULA,
- CVAR_SKILLFORMULA,
- CVAR_RANKBOTS,
- CVAR_USEFORWARDS,
- // 0.7
- CVAR_WEAPONSTATS,
- CVAR_MAPSTATS,
- CVAR_AUTOCLEAR,
- CVAR_CACHETIME,
- CVAR_AUTOCLEAR_DAY,
- // 0.7.2
- CVAR_ASSISTHP
- }
- // 0.7
- enum _:stats_cache_queue_struct
- {
- CACHE_QUE_START,
- CACHE_QUE_TOP,
- }
- #define MAX_DATA_PARAMS 32
- /* - ПЕРЕМЕННЫЕ - */
- // 0.7
- new session_id,session_map[MAX_NAME_LENGTH]
- new player_data[MAX_PLAYERS + 1][player_data_struct]
- new flush_que[QUERY_LENGTH * 3],flush_que_len
- new statsnum
- //
- // Общая стата по оружию
- //
- // 1ый STATS_END + HIT_END - текущая общая статистика по оружию игрока
- // 2ой STATS_END + HIT_END - последнее значение player_wstats, использует для расчета разницы
- // последний индекс - определяет INSERT или UPDATE для запроса
- //
- new player_awstats[MAX_PLAYERS + 1][MAX_WEAPONS][((STATS_END + HIT_END) * 2) + 1]
- new cvar[cvar_set]
- new Trie:stats_cache_trie // дерево кеша для get_stats // ключ - ранг
- new tbl_name[32]
- /* - CSSTATS CORE - */
- #pragma dynamic 32768
- // wstats
- new player_wstats[MAX_PLAYERS + 1][MAX_WEAPONS][STATS_END + HIT_END]
- // wstats2
- new player_wstats2[MAX_PLAYERS + 1][STATS2_END]
- // wrstats rstats
- new player_wrstats[MAX_PLAYERS + 1][MAX_WEAPONS][STATS_END + HIT_END]
- // vstats
- new player_vstats[MAX_PLAYERS + 1][MAX_PLAYERS + 1][STATS_END + HIT_END + MAX_NAME_LENGTH]
- // astats
- new player_astats[MAX_PLAYERS + 1][MAX_PLAYERS + 1][STATS_END + HIT_END + MAX_NAME_LENGTH]
- new FW_Death
- new FW_Damage
- new FW_BPlanting
- new FW_BPlanted
- new FW_BExplode
- new FW_BDefusing
- new FW_BDefused
- new FW_GThrow
- // 0.7.2
- new FW_Assist
- // 0.7.3
- new FW_Initialized
- new dummy_ret
- // осталось монитор прихуярить
- new g_planter
- new g_defuser
- #define WEAPON_INFO_SIZE 1 + (MAX_NAME_LENGTH * 2)
- new Array:weapons_data // массив с инфой по оружию
- new Trie:log_ids_trie // дерево для быстрого определения id оружия по лог-коду
- // 0.7
- new Array:stats_cache_queue
- // 0.7.1
- new bool:weapon_stats_enabled,bool:map_stats_enabled
- // 0.7.3
- new init_seq = -1
- new bool:is_ready = false
- // макрос для помощи реагистрации инфы по оружию
- #define REG_INFO(%0,%1,%2)\
- weapon_info[0] = %0;\
- copy(weapon_info[1],MAX_NAME_LENGTH,%1);\
- copy(weapon_info[MAX_NAME_LENGTH ],MAX_NAME_LENGTH,%2);\
- ArrayPushArray(weapons_data,weapon_info);\
- TrieSetCell(log_ids_trie,%2,ArraySize(weapons_data) - 1)
- public plugin_precache()
- {
- register_plugin(PLUGIN,VERSION,AUTHOR)
- register_cvar("csstatsx_sql", VERSION, FCVAR_SERVER | FCVAR_SPONLY | FCVAR_UNLOGGED)
- /*
- * хост mysql
- */
- cvar[CVAR_SQL_HOST] = register_cvar("csstats_sql_host","127.0.0.1",FCVAR_UNLOGGED|FCVAR_PROTECTED)
- /*
- * пользователь mysql
- */
- cvar[CVAR_SQL_USER] = register_cvar("csstats_sql_user","root",FCVAR_UNLOGGED|FCVAR_PROTECTED)
- /*
- * пароль mysql
- */
- cvar[CVAR_SQL_PASS] = register_cvar("csstats_sql_pass","pass",FCVAR_UNLOGGED|FCVAR_PROTECTED)
- /*
- * название БД mysql или sqlite
- */
- cvar[CVAR_SQL_DB] = register_cvar("csstats_sql_db","db",FCVAR_UNLOGGED|FCVAR_PROTECTED)
- /*
- * название таблицы в БД
- */
- cvar[CVAR_SQL_TABLE] = register_cvar("csstats_sql_table","csstats",FCVAR_UNLOGGED|FCVAR_PROTECTED)
- /*
- * тип бд
- * mysql - база данных MySQL
- * sqlite - локальная база данных SQLite
- */
- cvar[CVAR_SQL_TYPE] = register_cvar("csstats_sql_type","mysql")
- /*
- * отправка запроса на создание таблицы
- * 0 - не отправлять запрос
- * 1 - отправлять запрос при загрузке карты
- */
- cvar[CVAR_SQL_CREATE_DB] = register_cvar("csstats_sql_create_db","1")
- /*
- * как вести учет игроков
- * -1 - не учитывать
- * 0 - по нику
- * 1 - по steamid
- * 2 - по ip
- */
- cvar[CVAR_RANK] = get_cvar_pointer("csstats_rank")
- if(!cvar[CVAR_RANK])
- cvar[CVAR_RANK] = register_cvar("csstats_rank","1")
- /*
- * запись статистики ботов
- * 0 - не записывать
- * 1 - записывать0
- */
- cvar[CVAR_RANKBOTS] = get_cvar_pointer("csstats_rankbots")
- if(!cvar[CVAR_RANKBOTS])
- cvar[CVAR_RANKBOTS] = register_cvar("csstats_rankbots","1")
- /*
- * как обновлять статистику игрока в БД
- * -2 - при смерти и дисконнекте
- * -1 - в конце раунда и дисконнекте
- * 0 - при дисконнекте
- * значение больше 0 - через указанное кол-во секунд и дисконнекте
- */
- cvar[CVAR_UPDATESTYLE] = register_cvar("csstats_sql_update","10")
- /*
- * включить собственные форварды для client_death, client_damage
- * 0 - выключить
- * 1 - включить, небоходимо, если csstats_sql используется в качестве замены модуля
- */
- cvar[CVAR_USEFORWARDS] = register_cvar("csstats_sql_forwards","0")
- /*
- * формула расчета ранга
- * 0 - убйиства - смерти - тк
- * 1 - убийства
- * 2 - убийства + хедшоты
- * 3 - скилл
- * 4 - время онлайн
- */
- cvar[CVAR_RANKFORMULA] = register_cvar("csstats_sql_rankformula","0")
- /*
- * формула расчета скилла
- * 0 - The ELO Method (http://fastcup.net/rating.html)
- */
- cvar[CVAR_SKILLFORMULA] = register_cvar("csstats_sql_skillformula","0")
- // 0.7
- /*
- * ведение статистики по оружию
- */
- cvar[CVAR_WEAPONSTATS] = register_cvar("csstats_sql_weapons","1")
- /*
- * ведение статистики по картам
- */
- cvar[CVAR_MAPSTATS] = register_cvar("csstats_sql_maps","0")
- /*
- * автоматическое удаление неактвиных игроков в БД
- */
- cvar[CVAR_AUTOCLEAR] = register_cvar("csstats_sql_autoclear","0")
- /*
- * использование кеша для get_stats
- * -1 - обновлять в конце раунда или по времени csstats_sql_update
- * 0 - отключить использование кеша
- */
- cvar[CVAR_CACHETIME] = register_cvar("csstats_sql_cachetime","-1")
- /*
- * автоматическая очистка всей игровой статистики в БД в определенный день
- */
- cvar[CVAR_AUTOCLEAR_DAY] = register_cvar("csstats_sql_autoclear_day","0")
- /*
- * урон для засчитывания ассиста
- */
- cvar[CVAR_ASSISTHP] = register_cvar("csstats_sql_assisthp","50")
- #if AMXX_VERSION_NUM < 183
- MaxClients = get_maxplayers()
- #endif
- }
- public plugin_init()
- {
- register_logevent("LogEventHooK_RoundEnd", 2, "1=Round_End")
- register_logevent("LogEventHooK_RoundStart", 2, "1=Round_Start")
- register_event("CurWeapon","EventHook_CurWeapon","b","1=1")
- register_event("Damage","EventHook_Damage","b","2!0")
- register_event("BarTime","EventHook_BarTime","be")
- register_event("SendAudio","EventHook_SendAudio","a")
- register_event("TextMsg","EventHook_TextMsg","a")
- register_srvcmd("csstats_sql_reset","SrvCmd_DBReset")
- new weapon_info[WEAPON_INFO_SIZE]
- //
- log_ids_trie = TrieCreate()
- // is_meele + название + логнейм
- weapons_data = ArrayCreate(WEAPON_INFO_SIZE)
- REG_INFO(false,"","")
- REG_INFO(false,"p228","p228")
- REG_INFO(false,"","")
- REG_INFO(false,"scout","scout")
- REG_INFO(false,"hegrenade","grenade")
- REG_INFO(false,"xm1014","xm1014")
- REG_INFO(false,"c4","weapon_c4")
- REG_INFO(false,"mac10","mac10")
- REG_INFO(false,"aug","aug")
- REG_INFO(false,"sgrenade","grenade")
- REG_INFO(false,"elite","elite")
- REG_INFO(false,"fiveseven","fiveseven")
- REG_INFO(false,"ump45","ump45")
- REG_INFO(false,"sg550","sg550")
- REG_INFO(false,"galil","galil")
- REG_INFO(false,"famas","famas")
- REG_INFO(false,"usp","usp")
- REG_INFO(false,"glock18","glock18")
- REG_INFO(false,"awp","awp")
- REG_INFO(false,"mp5navy","mp5navy")
- REG_INFO(false,"m249","m249")
- REG_INFO(false,"m3","m3")
- REG_INFO(false,"m4a1","m4a1")
- REG_INFO(false,"tmp","tmp")
- REG_INFO(false,"g3sg1","g3sg1")
- REG_INFO(false,"flashbang","flashbang")
- REG_INFO(false,"deagle","deagle")
- REG_INFO(false,"sg552","sg552")
- REG_INFO(false,"ak47","ak47")
- REG_INFO(true,"knife","knife")
- REG_INFO(false,"p90","p90")
- RegisterHam(Ham_Spawn,"player","HamHook_PlayerSpawn",true)
- }
- #if AMXX_VERSION_NUM < 183
- public plugin_cfg()
- #else
- public OnAutoConfigsBuffered()
- #endif
- {
- #if AMXX_VERSION_NUM < 183
- // форсируем выполнение exec addons/amxmodx/configs/amxx.cfg
- server_exec()
- #endif
- // читаем квары на подключение
- new host[128],user[64],pass[64],db[64],type[10]
- get_pcvar_string(cvar[CVAR_SQL_HOST],host,charsmax(host))
- get_pcvar_string(cvar[CVAR_SQL_USER],user,charsmax(user))
- get_pcvar_string(cvar[CVAR_SQL_PASS],pass,charsmax(pass))
- get_pcvar_string(cvar[CVAR_SQL_DB],db,charsmax(db))
- get_pcvar_string(cvar[CVAR_SQL_TABLE],tbl_name,charsmax(tbl_name))
- get_pcvar_string(cvar[CVAR_SQL_TYPE],type,charsmax(type))
- // и снова здравствуй wopox3
- if(!SQL_SetAffinity(type))
- {
- new error_msg[128]
- formatex(error_msg,charsmax(error_msg),"failed to use ^"%s^" for db driver",
- error_msg)
- set_fail_state(error_msg)
- return
- }
- sql = SQL_MakeDbTuple(host,user,pass,db)
- // для поддержки utf8 ников требуется AMXX 1.8.3-dev-git3799 или выше
- #if AMXX_VERSION_NUM >= 183
- SQL_SetCharset(sql,"utf8")
- #endif
- weapon_stats_enabled = get_pcvar_num(cvar[CVAR_WEAPONSTATS]) == 1 ? true : false
- map_stats_enabled = get_pcvar_num(cvar[CVAR_MAPSTATS]) == 1 ? true : false
- new query[QUERY_LENGTH * 2],que_len
- new sql_data[1]
- sql_data[0] = SQL_INITDB
- // запрос на создание таблицы
- if(get_pcvar_num(cvar[CVAR_SQL_CREATE_DB]))
- {
- // запрос для mysql
- if(strcmp(type,"mysql") == 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- CREATE TABLE IF NOT EXISTS `%s` (\
- `%s` int(11) NOT NULL AUTO_INCREMENT,\
- `%s` varchar(30) NOT NULL,\
- `%s` varchar(32) NOT NULL,\
- `%s` varchar(16) NOT NULL,\
- `%s` float NOT NULL DEFAULT '0.0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- tbl_name,
- row_names[ROW_ID],
- row_names[ROW_STEAMID],
- row_names[ROW_NAME],
- row_names[ROW_IP],
- row_names[ROW_SKILL],
- row_names[ROW_KILLS],
- row_names[ROW_DEATHS],
- row_names[ROW_HS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- row_names[ROW_TKS],
- row_names[ROW_SHOTS],
- row_names[ROW_HITS],
- row_names[ROW_DMG],
- row_names[ROW_BOMBDEF],
- row_names[ROW_BOMBDEFUSED],
- row_names[ROW_BOMBPLANTS],
- row_names[ROW_BOMBEXPLOSIONS],
- row_names[ROW_H0]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- row_names[ROW_H1],
- row_names[ROW_H2],
- row_names[ROW_H3],
- row_names[ROW_H4],
- row_names[ROW_H5],
- row_names[ROW_H6],
- row_names[ROW_H7],
- row_names[ROW_ONLINETIME]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- row_names[ROW_CONNECTS],
- row_names[ROW_ROUNDT],
- row_names[ROW_WINT],
- row_names[ROW_ROUNDCT],
- row_names[ROW_WINCT],
- row_names[ROW_ASSISTS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\
- `%s` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\
- `%s` int(11) DEFAULT NULL,\
- `%s` varchar(32) DEFAULT NULL,\
- PRIMARY KEY (%s),\
- KEY `%s` (`%s`(16)),\
- KEY `%s` (`%s`(16)),\
- KEY `%s` (`%s`)\
- ) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;",
- row_names[ROW_FIRSTJOIN],
- row_names[ROW_LASTJOIN],
- row_names[ROW_SESSIONID],
- row_names[ROW_SESSIONNAME],
- row_names[ROW_ID],
- row_names[ROW_STEAMID],row_names[ROW_STEAMID],
- row_names[ROW_NAME],row_names[ROW_NAME],
- row_names[ROW_IP],row_names[ROW_IP]
- )
- }
- // запрос для sqlite
- else if(strcmp(type,"sqlite") == 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- CREATE TABLE IF NOT EXISTS `%s` (\
- `%s` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\
- `%s` TEXT NOT NULL,\
- `%s` TEXT NOT NULL,\
- `%s` TEXT NOT NULL,\
- `%s` REAL NOT NULL DEFAULT 0.0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,",
- tbl_name,
- row_names[ROW_ID],
- row_names[ROW_STEAMID],
- row_names[ROW_NAME],
- row_names[ROW_IP],
- row_names[ROW_SKILL],
- row_names[ROW_KILLS],
- row_names[ROW_DEATHS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,",
- row_names[ROW_HS],
- row_names[ROW_TKS],
- row_names[ROW_SHOTS],
- row_names[ROW_HITS],
- row_names[ROW_DMG],
- row_names[ROW_BOMBDEF],
- row_names[ROW_BOMBDEFUSED],
- row_names[ROW_BOMBPLANTS],
- row_names[ROW_BOMBEXPLOSIONS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,",
- row_names[ROW_H0],
- row_names[ROW_H1],
- row_names[ROW_H2],
- row_names[ROW_H3],
- row_names[ROW_H4],
- row_names[ROW_H5],
- row_names[ROW_H6],
- row_names[ROW_H7]
- )
- // 0.7
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,",
- row_names[ROW_ONLINETIME],
- row_names[ROW_CONNECTS],
- row_names[ROW_ROUNDT],
- row_names[ROW_WINT],
- row_names[ROW_ROUNDCT],
- row_names[ROW_WINCT],
- row_names[ROW_ASSISTS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\
- `%s` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',\
- `%s` INTEGER,\
- `%s` TEXT\
- );",
- row_names[ROW_FIRSTJOIN],
- row_names[ROW_LASTJOIN],
- row_names[ROW_SESSIONID],
- row_names[ROW_SESSIONNAME]
- )
- }
- else
- {
- set_fail_state("invalid ^"csstats_sql_type^" cvar value")
- }
- DB_AddInitSeq()
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- if(weapon_stats_enabled)
- {
- que_len = 0
- // запрос для mysql
- if(strcmp(type,"mysql") == 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- CREATE TABLE IF NOT EXISTS `%s_weapons` (\
- `%s` int(11) NOT NULL AUTO_INCREMENT,\
- `%s` int(11) NOT NULL,\
- `%s` varchar(32) NOT NULL,\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- tbl_name,
- row_weapons_names[ROW_WEAPON_ID],
- row_weapons_names[ROW_WEAPON_PLAYER],
- row_weapons_names[ROW_WEAPON_NAME],
- row_weapons_names[ROW_WEAPON_KILLS],
- row_weapons_names[ROW_WEAPON_DEATHS],
- row_weapons_names[ROW_WEAPON_HS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- row_weapons_names[ROW_WEAPON_TKS],
- row_weapons_names[ROW_WEAPON_SHOTS],
- row_weapons_names[ROW_WEAPON_HITS],
- row_weapons_names[ROW_WEAPON_DMG]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',\
- `%s` int(11) NOT NULL DEFAULT '0',",
- row_weapons_names[ROW_WEAPON_H0],
- row_weapons_names[ROW_WEAPON_H1],
- row_weapons_names[ROW_WEAPON_H2],
- row_weapons_names[ROW_WEAPON_H3],
- row_weapons_names[ROW_WEAPON_H4],
- row_weapons_names[ROW_WEAPON_H5],
- row_weapons_names[ROW_WEAPON_H6],
- row_weapons_names[ROW_WEAPON_H7]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- PRIMARY KEY (%s),\
- KEY `%s` (`%s`(16))\
- ) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;",
- row_weapons_names[ROW_WEAPON_ID],
- row_weapons_names[ROW_WEAPON_NAME],
- row_weapons_names[ROW_WEAPON_NAME]
- )
- }
- // запрос для sqlite
- else if(strcmp(type,"sqlite") == 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- CREATE TABLE IF NOT EXISTS `%s_weapons` (\
- `%s` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,\
- `%s` INTEGER NOT NULL,\
- `%s` TEXT NOT NULL,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,",
- tbl_name,
- row_weapons_names[ROW_WEAPON_ID],
- row_weapons_names[ROW_WEAPON_PLAYER],
- row_weapons_names[ROW_WEAPON_NAME],
- row_weapons_names[ROW_WEAPON_KILLS],
- row_weapons_names[ROW_WEAPON_DEATHS]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,",
- row_weapons_names[ROW_WEAPON_HS],
- row_weapons_names[ROW_WEAPON_TKS],
- row_weapons_names[ROW_WEAPON_SHOTS],
- row_weapons_names[ROW_WEAPON_HITS],
- row_weapons_names[ROW_WEAPON_DMG]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,"`%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0,\
- `%s` INTEGER NOT NULL DEFAULT 0",
- row_weapons_names[ROW_WEAPON_H0],
- row_weapons_names[ROW_WEAPON_H1],
- row_weapons_names[ROW_WEAPON_H2],
- row_weapons_names[ROW_WEAPON_H3],
- row_weapons_names[ROW_WEAPON_H4],
- row_weapons_names[ROW_WEAPON_H5],
- row_weapons_names[ROW_WEAPON_H6],
- row_weapons_names[ROW_WEAPON_H7]
- )
- que_len += formatex(query[que_len],charsmax(query) - que_len,");")
- }
- else
- {
- set_fail_state("invalid ^"csstats_sql_type^" cvar value")
- }
- if(que_len)
- {
- DB_AddInitSeq()
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- }
- }
- }
- DB_AutoClearOpt()
- // обновление статистики в БД каждые n сек
- if(get_pcvar_num(cvar[CVAR_UPDATESTYLE]) > 0)
- {
- set_task(
- float(get_pcvar_num(cvar[CVAR_UPDATESTYLE])),
- "DB_SaveAll",
- .flags = "b"
- )
- }
- if(get_pcvar_num(cvar[CVAR_USEFORWARDS]))
- {
- FW_Death = CreateMultiForward("client_death",ET_IGNORE,FP_CELL,FP_CELL,FP_CELL,FP_CELL,FP_CELL)
- FW_Damage = CreateMultiForward("client_damage",ET_IGNORE,FP_CELL,FP_CELL,FP_CELL,FP_CELL,FP_CELL,FP_CELL)
- FW_BPlanting = CreateMultiForward("bomb_planting",ET_IGNORE,FP_CELL)
- FW_BPlanted = CreateMultiForward("bomb_planted",ET_IGNORE,FP_CELL)
- FW_BExplode = CreateMultiForward("bomb_explode",ET_IGNORE,FP_CELL,FP_CELL)
- FW_BDefusing = CreateMultiForward("bomb_defusing",ET_IGNORE,FP_CELL)
- FW_BDefused = CreateMultiForward("bomb_defused",ET_IGNORE,FP_CELL)
- FW_GThrow = CreateMultiForward("grenade_throw",ET_IGNORE,FP_CELL,FP_CELL,FP_CELL)
- register_forward(FM_SetModel,"FMHook_SetModel",true)
- }
- // 0.7.2
- FW_Assist = CreateMultiForward("client_assist_sql",ET_IGNORE,FP_CELL,FP_CELL,FP_CELL)
- // 0.7.3
- FW_Initialized = CreateMultiForward("csxsql_initialized",ET_IGNORE)
- // 0.7
- //
- // запрос на получение ID сессии статистики за карту
- //
- if(map_stats_enabled)
- {
- new query[128],sql_data[1] = SQL_GETSESSID
- formatex(query,charsmax(query),"SELECT MAX(`session_id`) FROM `%s_maps`",
- tbl_name
- )
- DB_AddInitSeq()
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- }
- // защита от ретардов, которые не читаю README
- if(
- (get_pcvar_num(cvar[CVAR_UPDATESTYLE]) == -2) ||
- (get_pcvar_num(cvar[CVAR_UPDATESTYLE]) == 0)
- )
- {
- // выключаем кеширование
- set_pcvar_num(cvar[CVAR_CACHETIME],0)
- }
- DB_InitSeq()
- }
- //
- // последовательность перед началом работы плагина
- //
- DB_AddInitSeq()
- {
- init_seq --
- }
- //
- // проверяем выполнение последовательности инициализации
- //
- DB_InitSeq()
- {
- if(init_seq ==0)
- {
- log_amx("!?!?!?!?!?")
- return
- }
- init_seq ++
- // все выполнено, начинаем работу
- if(init_seq == 0)
- {
- ExecuteForward(FW_Initialized,dummy_ret)
- }
- }
- //
- // Функция очистки БД от неактивных игроков
- //
- DB_AutoClearOpt()
- {
- // 0.7
- new autoclear_days = get_pcvar_num(cvar[CVAR_AUTOCLEAR])
- if(autoclear_days > 0)
- {
- DB_ClearTables(autoclear_days)
- }
- // полные сброс статистики в определенный день
- autoclear_days = get_pcvar_num(cvar[CVAR_AUTOCLEAR_DAY])
- if(autoclear_days > 0)
- {
- new s_data[10]
- get_time("%d",s_data,charsmax(s_data))
- if(str_to_num(s_data) == autoclear_days)
- {
- s_data[0] = 0
- get_vaultdata("csxsql_clear",s_data,charsmax(s_data))
- // проверяем не было ли сброса
- if(!str_to_num(s_data))
- {
- set_vaultdata("csxsql_clear","1")
- DB_ClearTables(-1)
- }
- }
- /// очищяем проверку на сброс
- else
- {
- set_vaultdata("csxsql_clear","0")
- }
- }
- }
- //
- // Начало работы с БД
- //
- public csxsql_initialized()
- {
- is_ready = true
- new players[MAX_PLAYERS],pnum
- get_players(players,pnum)
- // загружаем стату игроков
- for(new i ; i < pnum ; i++)
- {
- client_putinserver(players[i])
- }
- }
- public SrvCmd_DBReset()
- {
- DB_ClearTables(-1)
- }
- //
- // Очистка таблиц от неактивных записей
- //
- DB_ClearTables(by_days)
- {
- if(by_days == -1)
- {
- log_amx("database reset")
- }
- new query[QUERY_LENGTH],que_len
- new type[10]
- get_pcvar_string(cvar[CVAR_SQL_TYPE],type,charsmax(type))
- if(strcmp(type,"mysql") == 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"DELETE `%s`",
- tbl_name
- )
- if(weapon_stats_enabled)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,",`%s_weapons`",tbl_name)
- }
- if(map_stats_enabled)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,",`%s_maps`",tbl_name)
- }
- que_len += formatex(query[que_len],charsmax(query) - que_len," FROM `%s`",
- tbl_name
- )
- if(weapon_stats_enabled)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- LEFT JOIN `%s_weapons` ON `%s`.`%s` = `%s_weapons`.`%s`",
- tbl_name,
- tbl_name,row_names[ROW_ID],
- tbl_name,row_weapons_names[ROW_WEAPON_PLAYER]
- )
- }
- if(map_stats_enabled)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- LEFT JOIN `%s_maps` ON `%s`.`%s` = `%s_maps`.`%s`",
- tbl_name,
- tbl_name,row_names[ROW_ID],
- tbl_name,row_weapons_names[ROW_WEAPON_PLAYER]
- )
- }
- if(by_days > 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"WHERE `%s`.`%s` <= DATE_SUB(NOW(),INTERVAL %d DAY);",
- tbl_name,row_names[ROW_LASTJOIN],by_days
- )
- }
- else
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"WHERE 1")
- }
- }
- else if(strcmp(type,"sqlite") == 0)
- {
- if(weapon_stats_enabled)
- {
- if(by_days > 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- DELETE FROM `%s_weapons` WHERE `%s` IN (\
- SELECT `%s` FROM `%s` WHERE `%s` <= DATETIME('now','-%d day')\
- );",
- tbl_name,row_weapons_names[ROW_WEAPON_PLAYER],
- row_names[ROW_ID],tbl_name,row_names[ROW_LASTJOIN],
- by_days
- )
- }
- else
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- DELETE FROM `%s_weapons` WHERE `%s` IN (\
- SELECT `%s` FROM `%s` WHERE 1\
- );",
- tbl_name,row_weapons_names[ROW_WEAPON_PLAYER],
- row_names[ROW_ID],tbl_name
- )
- }
- }
- if(map_stats_enabled)
- {
- if(by_days > 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- DELETE FROM `%s_maps` WHERE `%s` IN (\
- SELECT `%s` FROM `%s` WHERE `%s` <= DATETIME('now','-%d day')\
- );",
- tbl_name,row_weapons_names[ROW_WEAPON_PLAYER],
- row_names[ROW_ID],tbl_name,row_names[ROW_LASTJOIN],
- by_days
- )
- }
- else
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- DELETE FROM `%s_maps` WHERE `%s` IN (\
- SELECT `%s` FROM `%s` WHERE 1\
- );",
- tbl_name,row_weapons_names[ROW_WEAPON_PLAYER],
- row_names[ROW_ID],tbl_name
- )
- }
- }
- if(by_days > 0)
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- DELETE FROM `%s` WHERE `%s` <= DATETIME('now','-%d day');",
- tbl_name,row_names[ROW_LASTJOIN],by_days
- )
- }
- else
- {
- que_len += formatex(query[que_len],charsmax(query) - que_len,"\
- DELETE FROM `%s` WHERE 1;",tbl_name
- )
- }
- }
- new sql_data[1]
- sql_data[0] = SQL_AUTOCLEAR
- DB_AddInitSeq()
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- }
- public plugin_end()
- {
- // выполняем накопившиеся запросы при смене карты или выключении серваре
- DB_FlushQuery()
- SQL_FreeHandle(sql)
- if(sql_con != Empty_Handle)
- {
- SQL_FreeHandle(sql_con)
- }
- if(stats_cache_trie)
- {
- TrieDestroy(stats_cache_trie)
- }
- TrieDestroy(log_ids_trie)
- ArrayDestroy(weapons_data)
- }
- /*
- * загружаем статистику при подключении
- */
- public client_putinserver(id)
- {
- // ждем начала работы с БД
- if(!is_ready)
- {
- return PLUGIN_CONTINUE
- }
- reset_user_allstats(id)
- reset_user_wstats(id)
- arrayset(player_data[id],0,player_data_struct)
- for(new wpn ; wpn < MAX_WEAPONS ; wpn ++)
- {
- arrayset(player_awstats[id][wpn],0,sizeof player_awstats[][])
- }
- DB_LoadPlayerData(id)
- return PLUGIN_CONTINUE
- }
- /*
- * сохраняем статистику при дисконнекте
- */
- #if AMXX_VERSION_NUM < 183
- public client_disconnect(id)
- #else
- public client_disconnected(id)
- #endif
- {
- DB_SavePlayerData(id)
- }
- public HamHook_PlayerSpawn(id)
- {
- reset_user_wstats(id)
- }
- //
- // Регистрация выстрелов
- //
- public EventHook_CurWeapon(player)
- {
- #define LASTWEAPON 0 // id посл. оружия
- #define LASTCLIP 1 // кол-во потронов посл. оружия
- static event_tmp[MAX_PLAYERS + 1][LASTCLIP + 1] // помним послед
- static weapon_id; weapon_id = read_data(2)
- static clip_ammo; clip_ammo = read_data(3)
- if(event_tmp[player][LASTWEAPON] != weapon_id) // оружие было изменено, запоминаем новое кол-во патронов
- {
- event_tmp[player][LASTWEAPON] = weapon_id
- event_tmp[player][LASTCLIP] = clip_ammo
- }
- else if(event_tmp[player][LASTCLIP] > clip_ammo) // кол-во патронов в магазине уменьшилось, регистрируем выстрел
- {
- Stats_SaveShot(player,weapon_id)
- event_tmp[player][LASTCLIP] = clip_ammo
- }
- }
- //
- // Регистрация попадания
- //
- public EventHook_Damage(player)
- {
- static damage_take;damage_take = read_data(2)
- static dmg_inflictor;dmg_inflictor = pev(player,pev_dmg_inflictor)
- if(pev_valid(dmg_inflictor) != 2)
- {
- return PLUGIN_CONTINUE
- }
- if(!(0 < dmg_inflictor <= MaxClients))
- {
- // урон с гранаты на данным момент не учитывается
- return PLUGIN_CONTINUE
- }
- static weapon_id,last_hit,attacker
- attacker = get_user_attacker(player,weapon_id,last_hit)
- if(0 <= last_hit < HIT_END)
- {
- Stats_SaveHit(dmg_inflictor,player,damage_take,weapon_id,last_hit)
- }
- if(!is_user_alive(player))
- {
- if(is_user_connected(attacker))
- {
- Stats_SaveKill(attacker,player,weapon_id,last_hit)
- }
- }
- return PLUGIN_CONTINUE
- }
- //
- // Регистрация установки и дефьюза бомбы
- //
- public EventHook_BarTime(player)
- {
- new duration = read_data(1)
- if(!duration)
- {
- return PLUGIN_CONTINUE
- }
- if(duration == 3)
- {
- g_planter = player
- g_defuser = 0
- if(FW_BPlanting)
- ExecuteForward(FW_BPlanting,dummy_ret,player)
- }
- else
- {
- g_defuser = player
- Stats_SaveBDefusing(player)
- }
- return PLUGIN_CONTINUE
- }
- public EventHook_SendAudio(player)
- {
- new audio_code[16]
- read_data(2,audio_code,charsmax(audio_code))
- if (!player && audio_code[7] == 'B')
- {
- if (audio_code[11]=='P' && g_planter)
- {
- Stats_SaveBPlanted(g_planter)
- }
- else if (audio_code[11] =='D' && g_defuser)
- {
- Stats_SaveBDefused(g_defuser)
- Event_CTWin()
- }
- }
- }
- public EventHook_TextMsg(player)
- {
- new message[16]
- read_data(2,message,charsmax(message))
- if (!player)
- {
- // #Target_Bombed
- if ((message[1]=='T' && message[8] == 'B') && g_planter)
- {
- Stats_SaveBExplode(g_planter)
- g_planter = 0
- g_defuser = 0
- Event_TWin()
- }
- // #Terrorists_Win -- #Hostages_Not_R
- else if(
- (message[2] == 'e' && message[12] == 'W') ||
- (message[1] == 'H' && message[14] == 'R')
- )
- {
- Event_TWin()
- }
- // #Target_Saved -- #CTs_Win -- #All_Hostages_R
- else if(
- (message[1] == 'T' && message[8] == 'S') ||
- (message[2] == 'T' && message[5] == 'W') ||
- (message[1] == 'A' && message[14] == 'R')
- )
- {
- Event_CTWin()
- }
- }
- }
- //
- // Победа TERRORIST
- //
- Event_TWin()
- {
- new players[MAX_PLAYERS],pnum
- get_players(players,pnum)
- for(new i,player ; i < pnum ; i++)
- {
- player = players[i]
- // считаем статистику побед по командам
- if(player_data[player][PLAYER_STATS3][STATS3_CURRENTTEAM] == 1)
- {
- player_data[player][PLAYER_STATS3][STATS3_WINT] ++
- }
- }
- }
- //
- // Победа CT
- //
- Event_CTWin()
- {
- new players[MAX_PLAYERS],pnum
- get_players(players,pnum)
- for(new i,player ; i < pnum ; i++)
- {
- player = players[i]
- // считаем статистику побед по командам
- if(player_data[player][PLAYER_STATS3][STATS3_CURRENTTEAM] == 2)
- {
- player_data[player][PLAYER_STATS3][STATS3_WINCT] ++
- }
- }
- }
- //
- // Форвард grenade_throw
- //
- public FMHook_SetModel(ent,model[])
- {
- new owner = pev(ent,pev_owner)
- new Float:dmg_time
- pev(ent,pev_dmgtime,dmg_time)
- if(dmg_time <= 0.0 || !is_user_connected(owner))
- {
- return FMRES_IGNORED
- }
- new classname[32]
- pev(ent,pev_classname,classname,charsmax(classname))
- if(strcmp(classname,"grenade") != 0) // реагируем только на гранаты
- {
- return FMRES_IGNORED
- }
- new wId
- if(model[9] == 'h') // модель хеешки
- {
- wId = CSW_HEGRENADE
- }
- else if(model[9] == 'f') // модель флешки
- {
- wId = CSW_FLASHBANG
- }
- else if(model[9] == 's') // модель смока
- {
- wId = CSW_SMOKEGRENADE
- }
- ExecuteForward(FW_GThrow,dummy_ret,owner,ent,wId)
- return FMRES_IGNORED
- }
- //
- // Учет ассистов
- //
- Stats_SaveAssist(player,victim,assisted)
- {
- player_data[player][PLAYER_STATS3][STATS3_ASSIST] ++
- ExecuteForward(FW_Assist,dummy_ret,player,victim,assisted)
- return true
- }
- //
- // Учет выстрелов
- //
- Stats_SaveShot(player,wpn_id)
- {
- player_wstats[player][0][STATS_SHOTS] ++
- player_wstats[player][wpn_id][STATS_SHOTS] ++
- player_wrstats[player][0][STATS_SHOTS] ++
- player_wrstats[player][wpn_id][STATS_SHOTS] ++
- return true
- }
- //
- // Учет попадания
- //
- Stats_SaveHit(attacker,victim,damage,wpn_id,hit_place)
- {
- player_wstats[attacker][0][STATS_HITS] ++
- player_wstats[attacker][0][STATS_DMG] += damage
- player_wstats[attacker][0][hit_place + STATS_END] ++
- player_wrstats[attacker][0][STATS_HITS] ++
- player_wrstats[attacker][0][STATS_DMG] += damage
- player_wrstats[attacker][0][hit_place + STATS_END] ++
- player_wstats[attacker][wpn_id][STATS_DMG] += damage
- player_wrstats[attacker][wpn_id][STATS_DMG] += damage
- player_wstats[attacker][wpn_id][STATS_HITS] ++
- player_wrstats[attacker][wpn_id][STATS_HITS] ++
- player_wstats[attacker][wpn_id][hit_place + STATS_END] ++
- player_wrstats[attacker][wpn_id][hit_place + STATS_END] ++
- player_vstats[attacker][victim][STATS_HITS] ++
- player_vstats[attacker][victim][STATS_DMG] += damage
- player_vstats[attacker][victim][hit_place + STATS_END] ++
- player_astats[victim][attacker][STATS_HITS] ++
- player_astats[victim][attacker][STATS_DMG] += damage
- player_astats[victim][attacker][hit_place + STATS_END] ++
- player_vstats[attacker][0][STATS_HITS] ++
- player_vstats[attacker][0][STATS_DMG] += damage
- player_vstats[attacker][0][hit_place + STATS_END] ++
- player_astats[victim][0][STATS_HITS] ++
- player_astats[victim][0][STATS_DMG] += damage
- player_astats[victim][0][hit_place + STATS_END] ++
- // оружие, с которого убил для astats, vstats
- new weapon_info[WEAPON_INFO_SIZE]
- ArrayGetArray(weapons_data,wpn_id,weapon_info)
- copy(player_vstats[attacker][victim][STATS_END + HIT_END],
- MAX_NAME_LENGTH - 1,
- weapon_info[1]
- )
- copy(player_astats[victim][attacker][STATS_END + HIT_END],
- MAX_NAME_LENGTH - 1,
- weapon_info[1]
- )
- if(FW_Damage)
- ExecuteForward(FW_Damage,dummy_ret,attacker,victim,damage,wpn_id,hit_place,is_tk(attacker,victim))
- return true
- }
- //
- // Учет смертей
- //
- Stats_SaveKill(killer,victim,wpn_id,hit_place)
- {
- if(killer == victim) // не учитываем суицид
- {
- return false
- }
- if(!is_tk(killer,victim))
- {
- player_wstats[killer][0][STATS_KILLS] ++
- player_wstats[killer][wpn_id][STATS_KILLS] ++
- player_wrstats[killer][0][STATS_KILLS] ++
- player_wrstats[killer][wpn_id][STATS_KILLS] ++
- player_vstats[killer][victim][STATS_KILLS] ++
- player_astats[victim][killer][STATS_KILLS] ++
- player_vstats[killer][0][STATS_KILLS] ++
- player_astats[victim][0][STATS_KILLS] ++
- if(hit_place == HIT_HEAD)
- {
- player_wstats[killer][0][STATS_HS] ++
- player_wstats[killer][wpn_id][STATS_HS] ++
- player_wrstats[killer][0][STATS_HS] ++
- player_wrstats[killer][wpn_id][STATS_HS] ++
- player_vstats[killer][victim][STATS_HS] ++
- player_astats[victim][killer][STATS_HS] ++
- player_vstats[killer][0][STATS_HS] ++
- player_astats[victim][0][STATS_HS] ++
- }
- }
- else
- {
- player_wstats[killer][0][STATS_TK] ++
- player_wstats[killer][wpn_id][STATS_TK] ++
- player_wrstats[killer][0][STATS_TK] ++
- player_wrstats[killer][wpn_id][STATS_TK] ++
- player_vstats[killer][victim][STATS_TK] ++
- player_astats[victim][killer][STATS_TK] ++
- player_vstats[killer][0][STATS_TK] ++
- player_astats[victim][0][STATS_TK] ++
- }
- player_wstats[victim][0][STATS_DEATHS] ++
- player_wrstats[victim][0][STATS_DEATHS] ++
- // смотрим ассисты
- for(new i = 1,assist_hp = get_pcvar_num(cvar[CVAR_ASSISTHP]); (assist_hp) && (i <= MAX_PLAYERS) ; i++)
- {
- if(i == killer)
- {
- continue
- }
- if(player_astats[victim][i][STATS_DMG] >= assist_hp)
- {
- Stats_SaveAssist(i,victim,killer)
- }
- }
- new victim_wpn_id = get_user_weapon(victim)
- if(victim_wpn_id)
- {
- player_wstats[victim][victim_wpn_id][STATS_DEATHS] ++
- player_wrstats[victim][victim_wpn_id][STATS_DEATHS] ++
- }
- if(FW_Death)
- ExecuteForward(FW_Death,dummy_ret,killer,victim,wpn_id,hit_place,is_tk(killer,victim))
- if(player_data[killer][PLAYER_LOADSTATE] == LOAD_OK && player_data[victim][PLAYER_LOADSTATE] == LOAD_OK) // скилл расчитывается только при наличии статистики из БД
- {
- switch(get_pcvar_num(cvar[CVAR_SKILLFORMULA])) // расчет скилла
- {
- case 0: // The ELO Method (http://fastcup.net/rating.html)
- {
- new Float:delta = 1.0 / (1.0 + floatpower(10.0,(player_data[killer][PLAYER_SKILL] - player_data[victim][PLAYER_SKILL]) / 100.0))
- new Float:koeff = 0.0
- if(player_data[killer][PLAYER_STATS][STATS_KILLS] < 100)
- {
- koeff = 2.0
- }
- else
- {
- koeff = 1.5
- }
- player_data[killer][PLAYER_SKILL] += (koeff * delta)
- player_data[victim][PLAYER_SKILL] -= (koeff * delta)
- }
- }
- }
- // обновляем статистику в БД при смерти
- if(get_pcvar_num(cvar[CVAR_UPDATESTYLE]) == -2)
- {
- DB_SavePlayerData(victim)
- }
- return true
- }
- //
- // Учет статистики по бомба
- //
- Stats_SaveBDefusing(id)
- {
- player_wstats2[id][STATS2_DEFAT] ++
- if(FW_BDefusing)
- ExecuteForward(FW_BDefusing,dummy_ret,id)
- return true
- }
- Stats_SaveBDefused(id)
- {
- player_wstats2[id][STATS2_DEFOK] ++
- if(FW_BDefused)
- ExecuteForward(FW_BDefused,dummy_ret,id)
- return true
- }
- Stats_SaveBPlanted(id)
- {
- player_wstats2[id][STATS2_PLAAT] ++
- if(FW_BPlanted)
- ExecuteForward(FW_BPlanted,dummy_ret,id)
- return true
- }
- Stats_SaveBExplode(id)
- {
- player_wstats2[id][STATS2_PLAOK] ++
- if(FW_BExplode)
- ExecuteForward(FW_BExplode,dummy_ret,id,g_defuser)
- return true
- }
- /*
- * изменение ника игрока
- */
- public client_infochanged(id)
- {
- new cur_name[MAX_NAME_LENGTH],new_name[MAX_NAME_LENGTH]
- get_user_name(id,cur_name,charsmax(cur_name))
- get_user_info(id,"name",new_name,charsmax(new_name))
- if(strcmp(cur_name,new_name) != 0)
- {
- copy(player_data[id][PLAYER_NAME],charsmax(player_data[][PLAYER_NAME]),new_name)
- mysql_escape_string(player_data[id][PLAYER_NAME],charsmax(player_data[][PLAYER_NAME]))
- if(get_pcvar_num(cvar[CVAR_RANK]) == 0)
- {
- DB_SavePlayerData(id,true)
- }
- }
- }
- /*
- * сбрасываем astats,vstats статистику в начале раунда
- */
- public LogEventHooK_RoundStart()
- {
- // сбрасываем wrstats, vstats, astats в начале раунда
- new players[32],pnum
- get_players(players,pnum)
- for(new i,player ; i < pnum ; i++)
- {
- player = players[i]
- // определяем в какой команде игрок
- switch(get_user_team(player))
- {
- // статистика сыгранных раундов по командам
- case 1:
- {
- player_data[player][PLAYER_STATS3][STATS3_ROUNDT] ++
- player_data[player][PLAYER_STATS3][STATS3_CURRENTTEAM] = 1
- }
- case 2:
- {
- player_data[player][PLAYER_STATS3][STATS3_ROUNDCT] ++
- player_data[player][PLAYER_STATS3][STATS3_CURRENTTEAM] = 2
- }
- }
- }
- }
- //
- // сохраняем статистику в конце раунда
- //
- public LogEventHooK_RoundEnd()
- {
- if(get_pcvar_num(cvar[CVAR_UPDATESTYLE]) == -1)
- {
- DB_SaveAll()
- }
- }
- /*
- * загрузка статистики игрока из базы данных
- */
- DB_LoadPlayerData(id)
- {
- // пропускаем HLTV
- if(is_user_hltv(id))
- {
- return false
- }
- // пропускаем ботов, если отключена запись статистики ботов
- if( is_user_bot(id) && !get_pcvar_num(cvar[CVAR_RANKBOTS]))
- {
- return false
- }
- get_user_info(id,"name",player_data[id][PLAYER_NAME],charsmax(player_data[][PLAYER_NAME]))
- mysql_escape_string(player_data[id][PLAYER_NAME],charsmax(player_data[][PLAYER_NAME]))
- get_user_authid(id,player_data[id][PLAYER_STEAMID],charsmax(player_data[][PLAYER_STEAMID]))
- get_user_ip(id,player_data[id][PLAYER_IP],charsmax(player_data[][PLAYER_IP]),true)
- // формируем SQL запрос
- new query[QUERY_LENGTH],len,sql_data[2]
- sql_data[0] = SQL_LOAD
- sql_data[1] = id
- player_data[id][PLAYER_LOADSTATE] = LOAD_WAIT
- len += formatex(query[len],charsmax(query)-len,"SELECT *,(")
- len += DB_QueryBuildScore(query[len],charsmax(query)-len)
- len += formatex(query[len],charsmax(query)-len,"),(")
- len += DB_QueryBuildStatsnum(query[len],charsmax(query)-len)
- len += formatex(query[len],charsmax(query)-len,")")
- switch(get_pcvar_num(cvar[CVAR_RANK]))
- {
- case 0: // статистика по нику
- {
- len += formatex(query[len],charsmax(query)-len," FROM `%s` AS `a` WHERE `name` = '%s'",
- tbl_name,player_data[id][PLAYER_NAME]
- )
- }
- case 1: // статистика по steamid
- {
- len += formatex(query[len],charsmax(query)-len," FROM `%s` AS `a` WHERE `steamid` = '%s'",
- tbl_name,player_data[id][PLAYER_STEAMID]
- )
- }
- case 2: // статистика по ip
- {
- len += formatex(query[len],charsmax(query)-len," FROM `%s` AS `a` WHERE `ip` = '%s'",
- tbl_name,player_data[id][PLAYER_IP]
- )
- }
- default:
- {
- return false
- }
- }
- // отправка потокового запроса
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- return true
- }
- //
- // Загрузка статистики по оружию
- //
- DB_LoadPlayerWstats(id)
- {
- if(!player_data[id][PLAYER_ID])
- {
- return false
- }
- new query[QUERY_LENGTH],sql_data[2]
- sql_data[0] = SQL_GETWSTATS
- sql_data[1] = id
- formatex(query,charsmax(query),"SELECT * FROM `%s_weapons` WHERE `player_id` = '%d'",
- tbl_name,player_data[id][PLAYER_ID]
- )
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- return true
- }
- /*
- * сохранение статистики игрока
- */
- DB_SavePlayerData(id,bool:reload = false)
- {
- if(player_data[id][PLAYER_LOADSTATE] < LOAD_NEW) // игрок не загрузился
- {
- return false
- }
- new query[QUERY_LENGTH],i,len
- new sql_data[2]
- sql_data[1] = id
- new stats[8],stats2[4],hits[8]
- get_user_wstats(id,0,stats,hits)
- get_user_stats2(id,stats2)
- switch(player_data[id][PLAYER_LOADSTATE])
- {
- case LOAD_OK: // обновление данных
- {
- if(reload)
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_UPDATE
- }
- sql_data[0] = SQL_UPDATE
- new diffstats[sizeof player_data[][PLAYER_STATS]]
- new diffstats2[sizeof player_data[][PLAYER_STATS2]]
- new diffhits[sizeof player_data[][PLAYER_HITS]]
- new to_save
- len += formatex(query[len],charsmax(query) - len,"UPDATE `%s` SET",tbl_name)
- // обновляем по разнице с предедущими данными
- for(i = 0 ; i < sizeof player_data[][PLAYER_STATS] ; i++)
- {
- diffstats[i] = stats[i] - player_data[id][PLAYER_STATSLAST][i] // узнаем разницу
- player_data[id][PLAYER_STATSLAST][i] = stats[i]
- if(diffstats[i])
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + %d",
- !to_save ? " " : ",",
- row_names[i + ROW_KILLS],
- row_names[i + ROW_KILLS],
- diffstats[i]
- )
- to_save ++
- }
- }
- // обновляем по разнице с предедущими данными
- for(i = 0 ; i < sizeof player_data[][PLAYER_STATS2] ; i++)
- {
- diffstats2[i] = stats2[i] - player_data[id][PLAYER_STATS2LAST][i] // узнаем разницу
- player_data[id][PLAYER_STATS2LAST][i] = stats2[i]
- if(diffstats2[i])
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + %d",
- !to_save ? " " : ",",
- row_names[i + ROW_BOMBDEF],
- row_names[i + ROW_BOMBDEF],
- diffstats2[i]
- )
- to_save ++
- }
- }
- new Float:diffskill = player_data[id][PLAYER_SKILL] - player_data[id][PLAYER_SKILLLAST]
- player_data[id][PLAYER_SKILLLAST] = _:player_data[id][PLAYER_SKILL]
- if(diffskill != 0.0)
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + %.2f",
- !to_save ? " " : ",",
- row_names[ROW_SKILL],
- row_names[ROW_SKILL],
- diffskill
- )
- to_save ++
- }
- if(stats[STATS_HITS])
- {
- // запрос на сохранение мест попаданий
- for(i = 0; i < sizeof player_data[][PLAYER_HITS] ; i++)
- {
- diffhits[i] = hits[i] - player_data[id][PLAYER_HITSLAST][i] // узнаем разницу
- player_data[id][PLAYER_HITSLAST][i] = hits[i]
- if(diffhits[i])
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + '%d'",
- !to_save ? " " : ",",
- row_names[i + ROW_H0],row_names[i + ROW_H0],
- diffhits[i]
- )
- }
- }
- }
- // 0.7
- new diffstats3[STATS3_END]
- for(i = STATS3_CONNECT ; i < sizeof player_data[][PLAYER_STATS3] ; i++)
- {
- diffstats3[i] = player_data[id][PLAYER_STATS3][i] - player_data[id][PLAYER_STATS3LAST][i]
- player_data[id][PLAYER_STATS3LAST][i] = player_data[id][PLAYER_STATS3][i]
- if(diffstats3[i])
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + '%d'",
- !to_save ? " " : ",",
- row_names[(i - 1) + ROW_CONNECTS],row_names[(i - 1) + ROW_CONNECTS],
- diffstats3[i]
- )
- to_save ++
- }
- }
- // не сохраняем только подключения
- to_save --
- // 0.7 задаем поля для тригерром статистики по картам
- if(session_id)
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = '%d',`%s` = '%s'",
- to_save <= 0 ? " " : ",",
- row_names[ROW_SESSIONID],session_id,
- row_names[ROW_SESSIONNAME],session_map
- )
- }
- //
- player_data[id][PLAYER_ONLINE] += get_user_time(id) - player_data[id][PLAYER_ONLINEDIFF]
- player_data[id][PLAYER_ONLINEDIFF] = get_user_time(id)
- new diffonline = player_data[id][PLAYER_ONLINE]- player_data[id][PLAYER_ONLINELAST]
- player_data[id][PLAYER_ONLINELAST] = player_data[id][PLAYER_ONLINE]
- if(diffonline)
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + %d",
- to_save <= 0 ? " " : ",",
- row_names[ROW_ONLINETIME],
- row_names[ROW_ONLINETIME],
- diffonline
- )
- //to_save ++
- }
- // обновляем время последнего подключения, ник, ип и steamid
- len += formatex(query[len],charsmax(query) - len,",\
- `last_join` = CURRENT_TIMESTAMP,\
- `%s` = '%s',\
- `%s` = '%s'",
- row_names[ROW_STEAMID],player_data[id][PLAYER_STEAMID],
- row_names[ROW_IP],player_data[id][PLAYER_IP],
- row_names[ROW_ID],player_data[id][PLAYER_ID]
- )
- if(!reload) // не обновляем ник при его смене
- {
- len += formatex(query[len],charsmax(query) - len,",`%s` = '%s'",
- row_names[ROW_NAME],player_data[id][PLAYER_NAME]
- )
- }
- len += formatex(query[len],charsmax(query) - len,"WHERE `%s` = '%d'",row_names[ROW_ID],player_data[id][PLAYER_ID])
- if(to_save <= 0) // нечего сохранять
- {
- if(player_data[id][PLAYER_LOADSTATE] == LOAD_UPDATE) // релоад для обновления ника
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_NO
- DB_LoadPlayerData(id)
- }
- return false
- }
- else
- {
- //
- // Сравниваем статистику
- //
- for(new i ; i < sizeof player_data[][PLAYER_STATS] ; i++)
- {
- player_data[id][PLAYER_STATS][i] += diffstats[i]
- }
- for(new i ; i < sizeof player_data[][PLAYER_HITS] ; i++)
- {
- player_data[id][PLAYER_HITS][i] += diffhits[i]
- }
- for(new i ; i < sizeof player_data[][PLAYER_STATS2] ; i++)
- {
- player_data[id][PLAYER_STATS2][i] += diffstats2[i]
- }
- }
- }
- case LOAD_NEW: // запрос на добавление новой записи
- {
- sql_data[0] = SQL_INSERT
- new Float:skill
- switch(get_pcvar_num(cvar[CVAR_SKILLFORMULA]))
- {
- case 0: skill = 100.0
- }
- formatex(query,charsmax(query),"INSERT INTO `%s` \
- (`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`)\
- VALUES('%s','%s','%s','%.2f','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d',CURRENT_TIMESTAMP)\
- ",tbl_name,
- row_names[ROW_STEAMID],
- row_names[ROW_NAME],
- row_names[ROW_IP],
- row_names[ROW_SKILL],
- row_names[ROW_KILLS],
- row_names[ROW_DEATHS],
- row_names[ROW_HS],
- row_names[ROW_TKS],
- row_names[ROW_SHOTS],
- row_names[ROW_HITS],
- row_names[ROW_DMG],
- row_names[ROW_BOMBDEF],
- row_names[ROW_BOMBDEFUSED],
- row_names[ROW_BOMBPLANTS],
- row_names[ROW_BOMBEXPLOSIONS],
- row_names[ROW_LASTJOIN],
- player_data[id][PLAYER_STEAMID],
- player_data[id][PLAYER_NAME],
- player_data[id][PLAYER_IP],
- skill,
- stats[STATS_KILLS],
- stats[STATS_DEATHS],
- stats[STATS_HS],
- stats[STATS_TK],
- stats[STATS_SHOTS],
- stats[STATS_HITS],
- stats[STATS_DMG],
- stats2[STATS2_DEFAT],
- stats2[STATS2_DEFOK],
- stats2[STATS2_PLAAT],
- stats2[STATS2_PLAOK]
- )
- //
- // Сравниваем статистику
- //
- for(new i ; i < sizeof player_data[][PLAYER_STATS] ; i++)
- {
- player_data[id][PLAYER_STATS][i] = stats[i]
- }
- for(new i ; i < sizeof player_data[][PLAYER_HITS] ; i++)
- {
- player_data[id][PLAYER_HITS][i] = hits[i]
- }
- for(new i ; i < sizeof player_data[][PLAYER_STATS2] ; i++)
- {
- player_data[id][PLAYER_STATS2][i] = stats2[i]
- }
- player_data[id][PLAYER_SKILL] = _:player_data[id][PLAYER_SKILLLAST] = _:skill
- if(reload)
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_UPDATE
- }
- else
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_NEWWAIT
- }
- }
- }
- if(query[0])
- {
- if(weapon_stats_enabled)
- {
- DB_SavePlayerWstats(id)
- }
- switch(sql_data[0])
- {
- // накапливаем запросы
- case SQL_UPDATE:
- {
- // запросов достаточно, сбрасываем их
- DB_AddQuery(query,len)
- return true
- }
- }
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- }
- return true
- }
- //
- // Сохранение статистики по оружию
- //
- public DB_SavePlayerWstats(id)
- {
- if(player_data[id][PLAYER_LOADSTATE] < LOAD_OK) // игрок не загрузился
- {
- return false
- }
- new query[QUERY_LENGTH],len,log[MAX_NAME_LENGTH],wpn,stats_index,stats_index_last,to_save
- new diff[STATS_END + HIT_END]
- const load_index = sizeof player_awstats[][] - 1
- // по всем оружиям
- for(wpn = 0; wpn < MAX_WEAPONS ; wpn++)
- {
- Info_Weapon_GetLog(wpn,log,charsmax(log))
- if(!log[0])
- {
- continue
- }
- to_save = 0
- len = 0
- // расчитываем разницу статисткии
- for(stats_index = 0; stats_index < STATS_END + HIT_END; stats_index++)
- {
- stats_index_last = stats_index + (STATS_END + HIT_END)
- diff[stats_index] = player_wstats[id][wpn][stats_index] - player_awstats[id][wpn][stats_index_last]
- player_awstats[id][wpn][stats_index_last] = player_wstats[id][wpn][stats_index]
- }
- switch(player_awstats[id][wpn][load_index])
- {
- // новая статистика оружия
- case LOAD_NEW:
- {
- new id_row
- // строим запрос
- len += formatex(query[len],charsmax(query) - len,"INSERT INTO `%s_weapons` (`%s`,`%s`",
- tbl_name,
- row_weapons_names[ROW_WEAPON_PLAYER],
- row_weapons_names[ROW_WEAPON_NAME]
- )
- for(stats_index = 0; stats_index < STATS_END + HIT_END; stats_index++)
- {
- id_row = ROW_WEAPON_KILLS + stats_index
- if(diff[stats_index])
- {
- len += formatex(query[len],charsmax(query) - len,",`%s`",
- row_weapons_names[id_row]
- )
- to_save ++
- }
- }
- if(to_save)
- {
- len += formatex(query[len],charsmax(query) - len,") VALUES('%d','%s'",
- player_data[id][PLAYER_ID],
- log
- )
- for(stats_index = 0; stats_index < STATS_END + HIT_END; stats_index++)
- {
- id_row = ROW_WEAPON_KILLS + stats_index
- if(diff[stats_index])
- {
- len += formatex(query[len],charsmax(query) - len,",'%d'",
- diff[stats_index]
- )
- }
- }
- len += formatex(query[len],charsmax(query) - len,")")
- player_awstats[id][wpn][load_index] = _:LOAD_OK
- }
- }
- // обновляем статистику
- case LOAD_OK:
- {
- new id_row
- // строим запрос
- len += formatex(query[len],charsmax(query) - len,"UPDATE `%s_weapons` SET",tbl_name)
- for(stats_index = 0; stats_index < STATS_END + HIT_END; stats_index++)
- {
- id_row = ROW_WEAPON_KILLS + stats_index
- if(diff[stats_index])
- {
- len += formatex(query[len],charsmax(query) - len,"%s`%s` = `%s` + '%d'",
- to_save ? "," : "",
- row_weapons_names[id_row],
- row_weapons_names[id_row],
- diff[stats_index]
- )
- to_save ++
- }
- }
- len += formatex(query[len],charsmax(query) - len,"WHERE `%s` = '%s' AND `%s` = '%d'",
- row_weapons_names[ROW_WEAPON_NAME],log,
- row_weapons_names[ROW_WEAPON_PLAYER],player_data[id][PLAYER_ID]
- )
- }
- }
- if(to_save)
- {
- DB_AddQuery(query,len)
- }
- }
- return true
- }
- DB_AddQuery(query[],len)
- {
- if((flush_que_len + len + 1) > charsmax(flush_que))
- {
- DB_FlushQuery()
- }
- flush_que_len += formatex(
- flush_que[flush_que_len],
- charsmax(flush_que) - flush_que_len,
- "%s%s",flush_que_len ? ";" : "",
- query
- )
- // задание на сброс накопленных запросов
- remove_task(task_flush)
- set_task(0.1,"DB_FlushQuery",task_flush)
- }
- //
- // Сброс накопленных запросов
- //
- public DB_FlushQuery()
- {
- if(flush_que_len)
- {
- new sql_data[1] = SQL_UPDATE
- SQL_ThreadQuery(sql,"SQL_Handler",flush_que,sql_data,sizeof sql_data)
- flush_que_len = 0
- }
- }
- #define falos false
- /*
- * получение новых позиции в топе игроков
- */
- public DB_GetPlayerRanks()
- {
- new players[32],pnum
- get_players(players,pnum)
- new query[QUERY_LENGTH],len
- // строим SQL запрос
- len += formatex(query[len],charsmax(query) - len,"SELECT `id`,(")
- len += DB_QueryBuildScore(query[len],charsmax(query) - len)
- len += formatex(query[len],charsmax(query) - len,") FROM `%s` as `a` WHERE `id` IN(",tbl_name)
- new bool:letsgo
- for(new i,player,bool:y ; i < pnum ; i++)
- {
- player = players[i]
- if(player_data[player][PLAYER_ID])
- {
- len += formatex(query[len],charsmax(query) - len,"%s'%d'",y ? "," : "",player_data[player][PLAYER_ID])
- y = true
- letsgo = true
- }
- }
- len += formatex(query[len],charsmax(query) - len,")")
- if(letsgo)
- {
- new data[1] = SQL_UPDATERANK
- SQL_ThreadQuery(sql,"SQL_Handler",query,data,sizeof data)
- }
- }
- new bool:update_cache = false
- /*
- * сохранение статистики всех игроков
- */
- public DB_SaveAll()
- {
- new players[32],pnum
- get_players(players,pnum)
- if(get_pcvar_num(cvar[CVAR_CACHETIME]) == -1)
- {
- update_cache = true
- }
- for(new i ; i < pnum ; i++)
- {
- DB_SavePlayerData(players[i])
- }
- }
- /*
- * запрос на просчет ранка
- */
- DB_QueryBuildScore(sql_que[] = "",sql_que_len = 0,bool:only_rows = falos,overide_order = 0)
- {
- // стандартная формула csstats (убийства-смерти-tk)
- if(only_rows)
- {
- switch(overide_order ? overide_order : get_pcvar_num(cvar[CVAR_RANKFORMULA]))
- {
- case 1: return formatex(sql_que,sql_que_len,"`kills`")
- case 2: return formatex(sql_que,sql_que_len,"`kills`+`hs`")
- case 3: return formatex(sql_que,sql_que_len,"`skill`")
- case 4: return formatex(sql_que,sql_que_len,"`connection_time`")
- default: return formatex(sql_que,sql_que_len,"`kills`-`deaths`-`tks`")
- }
- }
- else
- {
- switch(overide_order ? overide_order : get_pcvar_num(cvar[CVAR_RANKFORMULA]))
- {
- case 1: return formatex(sql_que,sql_que_len,"SELECT COUNT(*) FROM %s WHERE (kills)>=(a.kills)",tbl_name)
- case 2: return formatex(sql_que,sql_que_len,"SELECT COUNT(*) FROM %s WHERE (kills+hs)>=(a.kills+a.hs)",tbl_name)
- case 3: return formatex(sql_que,sql_que_len,"SELECT COUNT(*) FROM %s WHERE (skill)>=(a.skill)",tbl_name)
- case 4: return formatex(sql_que,sql_que_len,"SELECT COUNT(*) FROM %s WHERE (connection_time)>=(a.connection_time)",tbl_name)
- default: return formatex(sql_que,sql_que_len,"SELECT COUNT(*) FROM %s WHERE (kills-deaths-tks)>=(a.kills-a.deaths-a.tks)",tbl_name)
- }
- }
- return 0
- }
- /*
- * запрос на общее кол-во записей в БД
- */
- DB_QueryBuildStatsnum(sql_que[] = "",sql_que_len = 0)
- {
- return formatex(sql_que,sql_que_len,"SELECT COUNT(*) FROM %s WHERE 1",tbl_name)
- }
- /*
- * запрос на выборку статистики по позиции
- * index - начальная позиция
- * index_count - кол-во выбираемых записей
- */
- DB_QueryBuildGetstats(query[],query_max,len = 0,index,index_count = 2,overide_order = 0)
- {
- // строим запрос
- len += formatex(query[len],query_max-len,"SELECT *")
- // запрос на ранк
- len += formatex(query[len],query_max-len,",(")
- len += DB_QueryBuildScore(query[len],query_max-len,true,overide_order)
- len += formatex(query[len],query_max-len,") as `rank`")
- // запрашиваем следующию запись
- // если есть, то возврашаем нативом index + 1
- len += formatex(query[len],query_max-len," FROM `%s` as `a` ORDER BY `rank` DESC LIMIT %d,%d",
- tbl_name,index,index_count
- )
- return len
- }
- /*
- * чтение результата get_stats запроса
- */
- DB_ReadGetStats(Handle:sqlQue,name[] = "",name_len = 0,authid[] = "",authid_len = 0,stats[8] = 0,hits[8] = 0,stats2[4] = 0,stats3[STATS3_END] = 0,&stats_count = 0,index)
- {
- stats_count = SQL_NumResults(sqlQue)
- if(!stats_count)
- {
- return false
- }
- new stats_cache[stats_cache_struct]
- switch(get_pcvar_num(cvar[CVAR_RANK]))
- {
- case 0: SQL_ReadResult(sqlQue,ROW_NAME,stats_cache[CACHE_STEAMID],charsmax(stats_cache[CACHE_STEAMID]))
- case 1: SQL_ReadResult(sqlQue,ROW_STEAMID,stats_cache[CACHE_STEAMID],charsmax(stats_cache[CACHE_STEAMID]))
- case 2: SQL_ReadResult(sqlQue,ROW_IP,stats_cache[CACHE_STEAMID],charsmax(stats_cache[CACHE_STEAMID]))
- }
- SQL_ReadResult(sqlQue,ROW_NAME,stats_cache[CACHE_NAME],charsmax(stats_cache[CACHE_NAME]))
- copy(name,name_len,stats_cache[CACHE_NAME])
- copy(authid,authid_len,stats_cache[CACHE_STEAMID])
- new i
- for(i = ROW_SKILL ; i <= ROW_LASTJOIN ; i++)
- {
- switch(i)
- {
- case ROW_SKILL: SQL_ReadResult(sqlQue,i,stats_cache[CACHE_SKILL])
- case ROW_KILLS..ROW_DMG:
- {
- stats_cache[CACHE_STATS][i - ROW_KILLS] = stats[i - ROW_KILLS] = SQL_ReadResult(sqlQue,i)
- }
- case ROW_BOMBDEF..ROW_BOMBEXPLOSIONS:
- {
- stats_cache[CACHE_STATS2][i - ROW_BOMBDEF] = stats2[i - ROW_BOMBDEF] = SQL_ReadResult(sqlQue,i)
- }
- case ROW_H0..ROW_H7:
- {
- stats_cache[CACHE_HITS][i - ROW_H0] = hits[i - ROW_H0] = SQL_ReadResult(sqlQue,i)
- }
- // 0.7
- case ROW_CONNECTS..ROW_ASSISTS:
- {
- stats_cache[CACHE_STATS3][((i - ROW_CONNECTS) + 1)] = stats3[((i - ROW_CONNECTS) + 1)] = SQL_ReadResult(sqlQue,i)
- }
- case ROW_FIRSTJOIN..ROW_LASTJOIN:
- {
- new date_str[32]
- SQL_ReadResult(sqlQue,i,date_str,charsmax(date_str))
- stats_cache[(CACHE_FIRSTJOIN + (i - ROW_FIRSTJOIN))] = parse_time(date_str,"%Y-%m-%d %H:%M:%S")
- }
- }
- }
- // кеширование данных
- if(!stats_cache_trie)
- {
- stats_cache_trie = TrieCreate()
- }
- stats_cache[CACHE_LAST] = SQL_NumResults(sqlQue) <= 1
- SQL_ReadResult(sqlQue,ROW_SKILL,stats_cache[CACHE_SKILL])
- stats_cache[CACHE_ID] = SQL_ReadResult(sqlQue,ROW_ID)
- stats_cache[CACHE_TIME] = SQL_ReadResult(sqlQue,ROW_ONLINETIME)
- new index_str[10]
- num_to_str(index,index_str,charsmax(index_str))
- TrieSetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct)
- // кешироавние данных
- SQL_NextRow(sqlQue)
- return SQL_MoreResults(sqlQue)
- }
- //
- // Задаем очередь для обновления кеша
- //
- Cache_Stats_SetQueue(start_index,top)
- {
- // очередь уже создана
- if(Cache_Stats_CheckQueue(start_index,top))
- {
- return false
- }
- if(!stats_cache_queue)
- {
- stats_cache_queue = ArrayCreate(stats_cache_queue_struct)
- }
- new length = ArraySize(stats_cache_queue)
- new cache_queue_info[stats_cache_queue_struct]
- cache_queue_info[CACHE_QUE_START] = start_index
- cache_queue_info[CACHE_QUE_TOP] = top
- if(!length) // новая очередь
- {
- ArrayPushArray(stats_cache_queue,cache_queue_info)
- }
- else // в топ
- {
- ArrayInsertArrayBefore(stats_cache_queue,0,cache_queue_info)
- }
- length ++
- if(length > 5) // максимум 5 заданий в очереди
- {
- ArrayDeleteItem(stats_cache_queue,5)
- length --
- }
- return true
- }
- //
- // Обновление кеша через очередь
- //
- Cache_Stats_UpdateQueue()
- {
- if(!stats_cache_queue)
- {
- return false
- }
- for(new i,length = ArraySize(stats_cache_queue),cache_queue_info[stats_cache_queue_struct] ; i < length ; i++)
- {
- ArrayGetArray(stats_cache_queue,i,cache_queue_info)
- DB_QueryTop15(0,-1,-1,-1,cache_queue_info[CACHE_QUE_START],cache_queue_info[CACHE_QUE_TOP],-1)
- }
- return true
- }
- Cache_Stats_CheckQueue(start_index,top)
- {
- if(!stats_cache_queue)
- {
- return false
- }
- for(new i,length = ArraySize(stats_cache_queue),cache_queue_info[stats_cache_queue_struct] ; i < length ; i++)
- {
- ArrayGetArray(stats_cache_queue,i,cache_queue_info)
- if(start_index == cache_queue_info[0] &&
- top == cache_queue_info[1]
- )
- {
- return true
- }
- }
- return false
- }
- //
- // Потоковый запрос на Top15
- //
- DB_QueryTop15(id,plugin_id,func_id,position,start_index,top,params)
- {
- // кеширование
- if((get_pcvar_num(cvar[CVAR_CACHETIME]) != 0) && stats_cache_trie)
- {
- Cache_Stats_SetQueue(start_index,top)
- new bool:use_cache = true
- // проверяем что требуемые данные есть в кеше
- for(new i = start_index,index_str[10]; i < (start_index + top) ; i++)
- {
- num_to_str(i,index_str,charsmax(index_str))
- if(!TrieKeyExists(stats_cache_trie,index_str))
- {
- use_cache = false
- }
- }
- // юзаем кеш
- if(use_cache)
- {
- // вызываем хандлер другого плагина
- if(func_id > -1)
- {
- if(callfunc_begin_i(func_id,plugin_id))
- {
- callfunc_push_int(id)
- callfunc_push_int(position)
- callfunc_end()
- }
- }
- return true
- }
- }
- // кеширование
- // строим новый запрос
- new query[QUERY_LENGTH]
- if(params == 5)
- {
- DB_QueryBuildGetstats(query,charsmax(query),.index = start_index,.index_count = top,.overide_order = get_param(5))
- }
- else
- {
- DB_QueryBuildGetstats(query,charsmax(query),.index = start_index,.index_count = top)
- }
- new sql_data[6]
- sql_data[0] = SQL_GETSTATS
- sql_data[1] = id
- sql_data[2] = plugin_id
- sql_data[3] = func_id
- sql_data[4] = position
- sql_data[5] = start_index
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,sizeof sql_data)
- return true
- }
- /*
- * обновляем кеш для get_stats
- */
- Cache_Stats_Update()
- {
- if(!stats_cache_trie)
- return false
- TrieClear(stats_cache_trie)
- return true
- }
- /*
- * обработка ответов на SQL запросы
- */
- public SQL_Handler(failstate,Handle:sqlQue,err[],errNum,data[],dataSize){
- // есть ошибки
- switch(failstate)
- {
- case TQUERY_CONNECT_FAILED: // ошибка соединения с mysql сервером
- {
- log_amx("SQL connection failed")
- log_amx("[ %d ] %s",errNum,err)
- return PLUGIN_HANDLED
- }
- case TQUERY_QUERY_FAILED: // ошибка SQL запроса
- {
- new lastQue[QUERY_LENGTH]
- SQL_GetQueryString(sqlQue,lastQue,charsmax(lastQue)) // узнаем последний SQL запрос
- log_amx("SQL query failed")
- log_amx("[ %d ] %s",errNum,err)
- log_amx("[ SQL ] %s",lastQue)
- return PLUGIN_HANDLED
- }
- }
- switch(data[0])
- {
- case SQL_INITDB:
- {
- DB_InitSeq()
- }
- case SQL_LOAD: // загрзука статистики игрока
- {
- new id = data[1]
- if(!is_user_connected(id))
- {
- return PLUGIN_HANDLED
- }
- if(SQL_NumResults(sqlQue)) // считываем статистику
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_OK
- player_data[id][PLAYER_ID] = SQL_ReadResult(sqlQue,ROW_ID)
- // общая статистика
- player_data[id][PLAYER_STATS][STATS_KILLS] = SQL_ReadResult(sqlQue,ROW_KILLS)
- player_data[id][PLAYER_STATS][STATS_DEATHS] = SQL_ReadResult(sqlQue,ROW_DEATHS)
- player_data[id][PLAYER_STATS][STATS_HS] = SQL_ReadResult(sqlQue,ROW_HS)
- player_data[id][PLAYER_STATS][STATS_TK] = SQL_ReadResult(sqlQue,ROW_TKS)
- player_data[id][PLAYER_STATS][STATS_SHOTS] = SQL_ReadResult(sqlQue,ROW_SHOTS)
- player_data[id][PLAYER_STATS][STATS_HITS] = SQL_ReadResult(sqlQue,ROW_HITS)
- player_data[id][PLAYER_STATS][STATS_DMG] = SQL_ReadResult(sqlQue,ROW_DMG)
- // статистика cstrike
- player_data[id][PLAYER_STATS2][STATS2_DEFAT] = SQL_ReadResult(sqlQue,ROW_BOMBDEF)
- player_data[id][PLAYER_STATS2][STATS2_DEFOK] = SQL_ReadResult(sqlQue,ROW_BOMBDEFUSED)
- player_data[id][PLAYER_STATS2][STATS2_PLAAT] = SQL_ReadResult(sqlQue,ROW_BOMBPLANTS)
- player_data[id][PLAYER_STATS2][STATS2_PLAOK] = SQL_ReadResult(sqlQue,ROW_BOMBEXPLOSIONS)
- // время онлайн
- player_data[id][PLAYER_ONLINE] = player_data[id][PLAYER_ONLINELAST] = SQL_ReadResult(sqlQue,ROW_ONLINETIME)
- // скилл
- SQL_ReadResult(sqlQue,ROW_SKILL,player_data[id][PLAYER_SKILL])
- player_data[id][PLAYER_SKILLLAST] = _:player_data[id][PLAYER_SKILL]
- // посл подключение и первое подкчлючение
- new date_str[32]
- SQL_ReadResult(sqlQue,ROW_FIRSTJOIN,date_str,charsmax(date_str))
- player_data[id][PLAYER_FIRSTJOIN] = parse_time(date_str,"%Y-%m-%d %H:%M:%S")
- SQL_ReadResult(sqlQue,ROW_LASTJOIN,date_str,charsmax(date_str))
- player_data[id][PLAYER_LASTJOIN] = parse_time(date_str,"%Y-%m-%d %H:%M:%S")
- // доп. запросы
- player_data[id][PLAYER_RANK] = SQL_ReadResult(sqlQue,row_ids) // ранк игрока
- statsnum = SQL_ReadResult(sqlQue,row_ids + 1) // общее кол-во игроков в БД
- // статистика попаданий
- for(new i ; i < sizeof player_data[][PLAYER_HITS] ; i++)
- {
- player_data[id][PLAYER_HITS][i] = SQL_ReadResult(sqlQue,ROW_H0 + i)
- }
- // 0.7
- for(new i = STATS3_CONNECT ; i < sizeof player_data[][PLAYER_STATS3] ; i++)
- {
- player_data[id][PLAYER_STATS3][i] = player_data[id][PLAYER_STATS3LAST][i] = SQL_ReadResult(sqlQue,(i - 1) + ROW_CONNECTS)
- // плюсуем стату подключений
- if(i == STATS3_CONNECT)
- {
- player_data[id][PLAYER_STATS3][i] ++
- }
- }
- if(weapon_stats_enabled)
- {
- DB_LoadPlayerWstats(id)
- }
- }
- else // помечаем как нового игрока
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_NEW
- DB_SavePlayerData(id) // добавляем запись в базу данных
- }
- }
- case SQL_INSERT: // запись новых данных
- {
- new id = data[1]
- if(is_user_connected(id))
- {
- if(player_data[id][PLAYER_LOADSTATE] == LOAD_UPDATE)
- {
- player_data[id][PLAYER_LOADSTATE] = LOAD_NO
- DB_LoadPlayerData(id)
- return PLUGIN_HANDLED
- }
- player_data[id][PLAYER_ID] = SQL_GetInsertId(sqlQue) // первичный ключ
- player_data[id][PLAYER_LOADSTATE] = LOAD_OK // данные загружены
- // я упрлся 0)0)0
- // обновляем счетчик общего кол-ва записей
- statsnum++
- if(weapon_stats_enabled)
- {
- DB_LoadPlayerWstats(id)
- }
- }
- // обновляем позици игроков
- // действие с задержкой, что-бы учесть изменения при множественном обновлении данных
- if(!task_exists(task_rankupdate))
- {
- set_task(1.0,"DB_GetPlayerRanks",task_rankupdate)
- }
- }
- case SQL_UPDATE: // обновление данных
- {
- // обновляем позици игроков
- // действие с задержкой, что-бы учесть изменения при множественном обновлении данных
- if(!task_exists(task_rankupdate))
- {
- set_task(0.1,"DB_GetPlayerRanks",task_rankupdate)
- }
- new players[MAX_PLAYERS],pnum
- get_players(players,pnum)
- for(new i,player ; i < pnum ; i++)
- {
- player = players[i]
- if(player_data[player][PLAYER_LOADSTATE] == LOAD_UPDATE)
- {
- player_data[player][PLAYER_LOADSTATE] = LOAD_NO
- DB_LoadPlayerData(player)
- }
- }
- if(update_cache)
- {
- update_cache = false
- Cache_Stats_Update()
- Cache_Stats_UpdateQueue()
- }
- }
- case SQL_UPDATERANK:
- {
- while(SQL_MoreResults(sqlQue))
- {
- new pK = SQL_ReadResult(sqlQue,0)
- new rank = SQL_ReadResult(sqlQue,1)
- for(new i ; i < MAX_PLAYERS ; i++)
- {
- if(player_data[i][PLAYER_ID] == pK) // задаем ранк по первичному ключу
- {
- player_data[i][PLAYER_RANK] = rank
- }
- }
- SQL_NextRow(sqlQue)
- }
- }
- case SQL_GETSTATS: // потоковый get_stats
- {
- new id = data[1]
- if(id && !is_user_connected(id))
- {
- return PLUGIN_HANDLED
- }
- new index = data[5]
- new name[32],authid[30]
- // кешируем ответ
- while(DB_ReadGetStats(sqlQue,name,charsmax(name),authid,charsmax(authid),.index = index ++))
- {
- }
- if(data[3] > -1)
- {
- // вызываем хандлер другого плагина
- if(callfunc_begin_i(data[3],data[2]))
- {
- callfunc_push_int(id)
- callfunc_push_int(data[4])
- callfunc_end()
- }
- }
- }
- // 0.7
- case SQL_GETWSTATS:
- {
- new id = data[1]
- if(!is_user_connected(id))
- {
- return PLUGIN_HANDLED
- }
- const load_index = sizeof player_awstats[][] - 1
- // загружаем статистику по оружию
- while(SQL_MoreResults(sqlQue))
- {
- new log[MAX_NAME_LENGTH]
- SQL_ReadResult(sqlQue,ROW_WEAPON_NAME,log,charsmax(log))
- new wpn = Info_Weapon_GetId(log)
- if(wpn == -1)
- {
- continue
- }
- for(new i ; i < STATS_END + HIT_END ; i++)
- {
- player_awstats[id][wpn][i] = SQL_ReadResult(sqlQue,i + ROW_WEAPON_KILLS)
- }
- player_awstats[id][wpn][load_index] = _:LOAD_OK
- SQL_NextRow(sqlQue)
- }
- // помечаем статистику по другим оружиям как новую
- for(new wpn ; wpn < MAX_WEAPONS ; wpn++)
- {
- if(_:player_awstats[id][wpn][load_index] != _:LOAD_OK)
- {
- player_awstats[id][wpn][load_index] = _:LOAD_NEW
- }
- }
- }
- case SQL_GETSESSID:
- {
- session_id = SQL_ReadResult(sqlQue,0) + 1
- get_mapname(session_map,charsmax(session_map))
- DB_InitSeq()
- }
- // get_sestats_thread_sql
- case SQL_GETSESTATS:
- {
- new Array:sestats_array = ArrayCreate(sestats_array_struct)
- new sestats_data[sestats_array_struct]
- while(SQL_MoreResults(sqlQue))
- {
- arrayset(sestats_data,0,sestats_array_struct)
- // заполняем массив со статой сессии
- for(new i = ROW_MAP_ID ; i <= ROW_MAP_LASTJOIN ; i++)
- {
- switch(i)
- {
- case ROW_MAP_ID: sestats_data[SESTATS_ID] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_PLRID: sestats_data[SESTATS_PLAYERID] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_MAP: SQL_ReadResult(sqlQue,i,sestats_data[SESTATS_MAP],charsmax(sestats_data[SESTATS_MAP]))
- case ROW_MAP_SKILL: SQL_ReadResult(sqlQue,i,sestats_data[SESTATS_SKILL])
- case ROW_MAP_KILLS..ROW_MAP_DMG: sestats_data[SESTATS_STATS][(i - ROW_MAP_KILLS)] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_H0..ROW_MAP_H7: sestats_data[SESTATS_HITS][(i - ROW_MAP_H0)] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_BOMBDEF..ROW_MAP_BOMBEXPLOSIONS: sestats_data[SESTATS_STATS2][(i - ROW_MAP_BOMBDEF)] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_ROUNDT..ROW_MAP_ASSISTS: sestats_data[SESTATS_STATS3][((i - ROW_MAP_ROUNDT) + 1)] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_ONLINETIME: sestats_data[SESTATS_ONLINETIME] = SQL_ReadResult(sqlQue,i)
- case ROW_MAP_FIRSTJOIN,ROW_LASTJOIN:
- {
- new date_str[32]
- SQL_ReadResult(sqlQue,i,date_str,charsmax(date_str))
- sestats_data[(SESTATS_FIRSTJOIN + (i - ROW_MAP_FIRSTJOIN))] = parse_time(date_str,"%Y-%m-%d %H:%M:%S")
- }
- }
- }
- ArrayPushArray(sestats_array,sestats_data)
- SQL_NextRow(sqlQue)
- }
- new func_id = data[1]
- new plugin_id = data[2]
- if(callfunc_begin_i(func_id,plugin_id))
- {
- callfunc_push_int(int:sestats_array)
- // передаваемые данные
- if(dataSize > 3)
- {
- new cb_data[MAX_DATA_PARAMS]
- for(new i ; i < (dataSize - 3) ; i++)
- {
- cb_data[i] = data[(3 + i)]
- }
- callfunc_push_array(cb_data,(dataSize - 3))
- callfunc_push_int((dataSize - 3))
- }
- callfunc_end()
- }
- else
- {
- log_amx("get_sestats_thread_sql callback function failed")
- }
- }
- case SQL_AUTOCLEAR:
- {
- if(SQL_AffectedRows(sqlQue))
- {
- log_amx("deleted %d inactive entries",
- SQL_AffectedRows(sqlQue)
- )
- }
- DB_InitSeq()
- }
- }
- return PLUGIN_HANDLED
- }
- //
- // Поиск ID оружия по его лог коду
- //
- Info_Weapon_GetId(weapon[])
- {
- new weapon_info[WEAPON_INFO_SIZE]
- new length = ArraySize(weapons_data)
- for(new i ; i < length; i++)
- {
- ArrayGetArray(weapons_data,i,weapon_info)
- new weapon_name[MAX_NAME_LENGTH]
- copy(weapon_name,charsmax(weapon_name),weapon_info[MAX_NAME_LENGTH])
- if(strcmp(weapon_name,weapon) == 0)
- {
- return i
- }
- }
- return -1
- }
- //
- // Поиск лог кода по ID оружия
- //
- Info_Weapon_GetLog(wpn_id,weapon_name[],len)
- {
- if(!(0 < wpn_id < ArraySize(weapons_data)))
- {
- formatex(weapon_name,len,"")
- return
- }
- new weapon_info[WEAPON_INFO_SIZE]
- ArrayGetArray(weapons_data,wpn_id,weapon_info)
- copy(weapon_name,len,weapon_info[MAX_NAME_LENGTH])
- }
- /*
- *
- * API
- *
- */
- #define CHECK_PLAYER(%1) \
- if (%1 < 1 || %1 > MaxClients) { \
- log_error(AMX_ERR_NATIVE, "Player out of range (%d)", %1); \
- return 0; \
- } else { \
- if (!is_user_connected(%1) || pev_valid(%1) != 2) { \
- log_error(AMX_ERR_NATIVE, "Invalid player %d", %1); \
- return 0; \
- } \
- }
- #define CHECK_PLAYERRANGE(%1) \
- if(%1 < 0 || %1 > MaxClients) {\
- log_error(AMX_ERR_NATIVE,"Player out of range (%d)",%1);\
- return 0;\
- }
- #define CHECK_WEAPON(%1) \
- if(!(0 <= %1 < ArraySize(weapons_data))){\
- log_error(AMX_ERR_NATIVE,"Invalid weapon id %d",%1);\
- return 0;\
- }
- public plugin_natives()
- {
- // default csstats
- register_library("xstats")
- register_native("get_user_wstats","native_get_user_wstats")
- register_native("get_user_wrstats","native_get_user_wrstats")
- register_native("get_user_stats","native_get_user_stats")
- register_native("get_user_rstats","native_get_user_rstats")
- register_native("get_user_vstats","native_get_user_vstats")
- register_native("get_user_astats","native_get_user_astats")
- register_native("reset_user_wstats","native_reset_user_wstats")
- register_native("get_stats","native_get_stats")
- register_native("get_statsnum","native_get_statsnum")
- register_native("get_user_stats2","native_get_user_stats2")
- register_native("get_stats2","native_get_stats2")
- register_native("xmod_is_melee_wpn","native_xmod_is_melee_wpn")
- register_native("xmod_get_wpnname","native_xmod_get_wpnname")
- register_native("xmod_get_wpnlogname","native_xmod_get_wpnlogname")
- register_native("xmod_get_maxweapons","native_xmod_get_maxweapons")
- register_native("xmod_get_stats_size","native_get_statsnum")
- register_native("get_map_objectives","native_get_map_objectives")
- register_native("custom_weapon_add","native_custom_weapon_add")
- register_native("custom_weapon_dmg","native_custom_weapon_dmg")
- register_native("custom_weapon_shot","native_custom_weapon_shot")
- register_library("csstatsx_sql")
- // csstats mysql
- register_native("get_statsnum_sql","native_get_statsnum")
- register_native("get_user_stats_sql","native_get_user_stats")
- register_native("get_stats_sql","native_get_stats")
- register_native("get_stats_sql_thread","native_get_stats_thread")
- register_native("get_stats2_sql","native_get_stats2")
- register_native("get_user_skill","native_get_user_skill")
- register_native("get_skill","native_get_skill")
- // 0.5.1
- register_native("get_user_gametime","native_get_user_gametime")
- register_native("get_stats_gametime","native_get_stats_gametime")
- register_native("get_user_stats_id","native_get_user_stats_id")
- register_native("get_stats_id","native_get_stats_id")
- register_native("update_stats_cache","native_update_stats_cache")
- // 0.7
- register_native("get_user_stats3_sql","native_get_user_stats3")
- register_native("get_stats3_sql","native_get_stats3")
- register_native("get_user_wstats_sql","native_get_user_wstats_sql")
- register_native("get_sestats_thread_sql","native_get_sestats_thread_sql")
- register_native("get_sestats_read_count","native_get_sestats_read_count")
- register_native("get_sestats_read_stats","native_get_sestats_read_stats")
- register_native("get_sestats_read_stats2","native_get_sestats_read_stats2")
- register_native("get_sestats_read_stats3","native_get_sestats_read_stats3")
- register_native("get_sestats_read_online","native_get_sestats_read_online")
- register_native("get_sestats_read_skill","native_get_sestats_read_skill")
- register_native("get_sestats_read_map","native_get_sestats_read_map")
- register_native("get_sestats_read_stime","native_get_sestats_read_stime")
- register_native("get_sestats_read_etime","native_get_sestats_read_etime")
- register_native("get_sestats_free","native_get_sestats_free")
- register_native("get_user_firstjoin_sql","native_get_user_firstjoin_sql")
- register_native("get_user_lastjoin_sql","native_get_user_lastjoin_sql")
- // 0.7.2
- register_native("xmod_get_maxweapons_sql","native_xmod_get_maxweapons")
- }
- public native_get_user_firstjoin_sql(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- if(player_data[id][PLAYER_LOADSTATE] == LOAD_NO)
- {
- return -1
- }
- return player_data[id][PLAYER_FIRSTJOIN]
- }
- public native_get_user_lastjoin_sql(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- if(player_data[id][PLAYER_LOADSTATE] == LOAD_NO)
- {
- return -1
- }
- return player_data[id][PLAYER_LASTJOIN]
- }
- public native_get_sestats_read_stime(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- return sestats_data[SESTATS_FIRSTJOIN]
- }
- public native_get_sestats_read_etime(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- return sestats_data[SESTATS_LASTJOIN]
- }
- public native_get_sestats_free(plugin_id,params)
- {
- new sestats = get_param_byref(1)
- ArrayDestroy(Array:sestats)
- set_param_byref(1,0)
- return true
- }
- public native_get_sestats_read_map(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new length = get_param(4)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- return set_string(3,sestats_data[SESTATS_MAP],length)
- }
- public Float:native_get_sestats_read_skill(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0.0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- return sestats_data[SESTATS_SKILL]
- }
- public native_get_sestats_read_online(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- return sestats_data[SESTATS_ONLINETIME]
- }
- public native_get_sestats_read_stats(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- set_array(3,sestats_data[SESTATS_STATS],8)
- set_array(4,sestats_data[SESTATS_HITS],8)
- index ++
- return (index >= sestats_size) ? 0 : index
- }
- public native_get_sestats_read_stats2(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 <= index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- set_array(3,sestats_data[SESTATS_STATS2],4)
- index ++
- return (index >= sestats_size) ? 0 : index
- }
- public native_get_sestats_read_stats3(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- new index = get_param(2)
- new sestats_size = ArraySize(sestats)
- if(!(0 < index < sestats_size))
- {
- log_error(AMX_ERR_NATIVE,"Stats index out of range (%d)",index)
- return 0
- }
- new sestats_data[sestats_array_struct]
- ArrayGetArray(sestats,index,sestats_data)
- set_array(3,sestats_data[SESTATS_STATS3],STATS3_END)
- index ++
- return (index >= sestats_size) ? 0 : index
- }
- public native_get_sestats_read_count(plugin_id,params)
- {
- new Array:sestats = Array:get_param(1)
- return ArraySize(sestats)
- }
- public native_get_sestats_thread_sql(plugin_id,params)
- {
- // статистика по картам выключена
- if(session_id == 0)
- {
- return false
- }
- new callback_func[32]
- get_string(2,callback_func,charsmax(callback_func))
- new func_id = get_func_id(callback_func,plugin_id)
- // функция ответа не найдена
- if(func_id == -1)
- {
- log_error(AMX_ERR_NATIVE,"Callback function ^"%s^" not found",callback_func)
- return false
- }
- new data_size = get_param(4)
- if(data_size > MAX_DATA_PARAMS)
- {
- log_error(AMX_ERR_NATIVE,"Max data size %d reached.",MAX_DATA_PARAMS)
- return false
- }
- // подготавливаем данные
- new sql_data[3 + MAX_DATA_PARAMS],data_array[MAX_DATA_PARAMS]
- sql_data[0] = SQL_GETSESTATS
- sql_data[1] = func_id
- sql_data[2] = plugin_id
- // передаваемые данные
- if(data_size)
- {
- get_array(3,data_array,data_size)
- for(new i ; i < data_size ; i++)
- {
- sql_data[i + 3] = data_array[i]
- }
- }
- new player_db_id = get_param(1) // ищем по ID игрока
- new limit = get_param(5) // лимит на выборку
- new query[QUERY_LENGTH]
- formatex(query,charsmax(query),"SELECT * FROM `%s_maps` WHERE `%s` = '%d' ORDER BY `%s` DESC LIMIT %d",
- tbl_name,
- row_weapons_names[ROW_WEAPON_PLAYER],player_db_id,
- row_names[ROW_FIRSTJOIN],limit
- )
- SQL_ThreadQuery(sql,"SQL_Handler",query,sql_data,3 + data_size)
- return true
- }
- public native_get_user_wstats_sql(plugin_id,params)
- {
- if(params != 4)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 4, passed %d",params)
- return false
- }
- if(!weapon_stats_enabled)
- {
- return -1
- }
- new player_id = get_param(1)
- CHECK_PLAYERRANGE(player_id)
- new weapon_id = get_param(2)
- CHECK_WEAPON(weapon_id)
- new stats[8],bh[8]
- const stats_index_last = (STATS_END + HIT_END)
- for(new i ; i < STATS_END ; i++)
- {
- stats[i] = player_awstats[player_id][weapon_id][i] + player_awstats[player_id][weapon_id][i + stats_index_last]
- }
- // игрок не пользовался этим оружием
- if(!stats[STATS_DEATHS] && !stats[STATS_SHOTS])
- {
- return false
- }
- for(new i = STATS_END ; i < (STATS_END + HIT_END) ; i ++)
- {
- bh[(i - STATS_END)] = player_awstats[player_id][weapon_id][i] + player_awstats[player_id][weapon_id][i + stats_index_last]
- }
- set_array(3,stats,sizeof stats)
- set_array(4,bh,sizeof bh)
- return true
- }
- public native_update_stats_cache()
- {
- return Cache_Stats_Update()
- }
- /*
- * Функция возвращает онлайн время игрока
- *
- * native get_user_gametime(id)
- */
- public native_get_user_gametime(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- if(player_data[id][PLAYER_LOADSTATE] == LOAD_NO)
- {
- return -1
- }
- return player_data[id][PLAYER_ONLINE]
- }
- /*
- * Получение времени по позиции
- *
- * native get_stats_gametime(index,&game_time)
- */
- public native_get_stats_gametime(plugin_id,params)
- {
- new index = get_param(1) // индекс в статистике
- // кеширование
- new index_str[10],stats_cache[stats_cache_struct]
- num_to_str(index,index_str,charsmax(index_str))
- // есть информация в кеше
- if(stats_cache_trie && TrieGetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct))
- {
- set_param_byref(2,stats_cache[CACHE_TIME])
- return !stats_cache[CACHE_LAST] ? index + 1 : 0
- }
- // кеширование
- return 0
- }
- /*
- * Функция возрващает ID игрока в БД
- *
- * native get_user_stats_id(id)
- */
- public native_get_user_stats_id(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- return player_data[id][PLAYER_ID]
- }
- /*
- * Получение ID по позиции
- *
- * native get_stats_id(index,&db_id)
- */
- public native_get_stats_id(plugin_id,params)
- {
- new index = get_param(1) // индекс в статистике
- // кеширование
- new index_str[10],stats_cache[stats_cache_struct]
- num_to_str(index,index_str,charsmax(index_str))
- // есть информация в кеше
- if(stats_cache_trie && TrieGetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct))
- {
- set_param_byref(2,stats_cache[CACHE_ID])
- return !stats_cache[CACHE_LAST] ? index + 1 : 0
- }
- // кеширование
- return 0
- }
- /*
- * Функция возрващает скилл игрока
- *
- * native get_user_skill(player,&Float:skill)
- */
- public native_get_user_skill(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- set_float_byref(2,player_data[id][PLAYER_SKILL])
- return true
- }
- /*
- * Получение скилла по позиции
- *
- * native get_skill(index,&Float:skill)
- */
- public native_get_skill(plugin_id,params)
- {
- new index = get_param(1) // индекс в статистике
- // кеширование
- new index_str[10],stats_cache[stats_cache_struct]
- if(index < 0)
- index = 0
- num_to_str(index,index_str,charsmax(index_str))
- // есть информация в кеше
- if(stats_cache_trie && TrieGetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct))
- {
- set_float_byref(2,Float:stats_cache[CACHE_SKILL])
- return !stats_cache[CACHE_LAST] ? index + 1 : 0
- }
- // кеширование
- return 0
- }
- /*
- * Добавление кастомного оружия для статистики
- *
- * native custom_weapon_add(const wpnname[], melee = 0, const logname[] = "")
- */
- public native_custom_weapon_add(plugin_id,params)
- {
- if(ArraySize(weapons_data) >= MAX_WEAPONS)
- {
- return 0
- }
- new weapon_name[MAX_NAME_LENGTH],weapon_log[MAX_NAME_LENGTH],is_melee
- get_string(1,weapon_name,charsmax(weapon_name))
- if(params >= 2) // задан флаг is_melee
- is_melee = get_param(2)
- if(params == 3) // указан лог код
- {
- get_string(3,weapon_log,charsmax(weapon_log))
- }
- else // копируем название оружия для лог кода
- {
- copy(weapon_log,charsmax(weapon_log),weapon_name)
- }
- // регистриурем
- new weapon_info[WEAPON_INFO_SIZE]
- REG_INFO(is_melee,weapon_name,weapon_info)
- return ArraySize(weapons_data) - 1
- }
- /*
- * Учет урона кастомного оружия
- *
- * native custom_weapon_dmg(weapon, att, vic, damage, hitplace = 0)
- */
- public native_custom_weapon_dmg(plugin_id,params)
- {
- new weapon_id = get_param(1)
- CHECK_WEAPON(weapon_id)
- new att = get_param(2)
- CHECK_PLAYERRANGE(att)
- new vic = get_param(3)
- CHECK_PLAYERRANGE(vic)
- new dmg = get_param(4)
- if(dmg < 1)
- {
- log_error(AMX_ERR_NATIVE,"Invalid damage %d", dmg)
- return 0
- }
- new hit_place = get_param(5)
- return Stats_SaveHit(att,vic,dmg,weapon_id,hit_place)
- }
- /*
- * Регистрация выстрела кастомного оружия
- *
- * native custom_weapon_shot(weapon, index)
- */
- public native_custom_weapon_shot(plugin_id,params)
- {
- new weapon_id = get_param(1)
- CHECK_WEAPON(weapon_id)
- new id = get_param(2)
- CHECK_PLAYERRANGE(id)
- return Stats_SaveShot(id,weapon_id)
- }
- /*
- * Возвращает true, если оружие рукопашного боя
- *
- * native xmod_is_melee_wpn(wpnindex)
- */
- public native_xmod_is_melee_wpn(plugin_id,params)
- {
- new wpn_id = get_param(1)
- CHECK_WEAPON(wpn_id)
- new weapon_info[WEAPON_INFO_SIZE]
- ArrayGetArray(weapons_data,wpn_id,weapon_info)
- return weapon_info[0]
- }
- /*
- * Получение полного названия оружия
- *
- * native xmod_get_wpnname(wpnindex, name[], len)
- */
- public native_xmod_get_wpnname(plugin_id,params)
- {
- new wpn_id = get_param(1)
- CHECK_WEAPON(wpn_id)
- new weapon_info[WEAPON_INFO_SIZE]
- ArrayGetArray(weapons_data,wpn_id,weapon_info)
- new weapon_name[MAX_NAME_LENGTH]
- copy(weapon_name,charsmax(weapon_name),weapon_info[1])
- set_string(2,weapon_name,get_param(3))
- return strlen(weapon_name)
- }
- /*
- * Получение лог кода для оружия
- *
- * native xmod_get_wpnlogname(wpnindex, name[], len)
- */
- public native_xmod_get_wpnlogname(plugin_id,params)
- {
- new wpn_id = get_param(1)
- CHECK_WEAPON(wpn_id)
- new weapon_name[MAX_NAME_LENGTH]
- Info_Weapon_GetLog(wpn_id,weapon_name,get_param(3))
- set_string(2,weapon_name,get_param(3))
- return strlen(weapon_name)
- }
- /*
- * Возврашение общего количества оружия для статистики
- *
- * native xmod_get_maxweapons()
- */
- public native_xmod_get_maxweapons(plugin_id,params)
- {
- return ArraySize(weapons_data)
- }
- public native_get_map_objectives(plugin_id,params)
- {
- return false
- }
- /*
- * Статистика за текущую сессию
- *
- * native get_user_wstats(index, wpnindex, stats[8], bodyhits[8])
- */
- public native_get_user_wstats(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- new wpn_id = get_param(2)
- CHECK_WEAPON(wpn_id)
- new stats[8],bh[8]
- get_user_wstats(id,wpn_id,stats,bh)
- set_array(3,stats,STATS_END)
- set_array(4,bh,HIT_END)
- return (stats[STATS_DEATHS] || stats[STATS_SHOTS])
- }
- /*
- * Статистика за текущий раунд
- *
- * native get_user_wrstats(index, wpnindex, stats[8], bodyhits[8])
- */
- public native_get_user_wrstats(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- new wpn_id = get_param(2)
- CHECK_WEAPON(wpn_id)
- if(wpn_id != 0 && !(0 < wpn_id < MAX_WEAPONS))
- {
- log_error(AMX_ERR_NATIVE,"Weapon index out of bounds (%d)",id)
- return false
- }
- new stats[8],bh[8]
- get_user_wrstats(id,wpn_id,stats,bh)
- set_array(3,stats,STATS_END)
- set_array(4,bh,HIT_END)
- return (stats[STATS_DEATHS] || stats[STATS_SHOTS])
- }
- /*
- * Получение статистики игрока
- *
- * native get_user_stats(index, stats[8], bodyhits[8])
- */
- public native_get_user_stats(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- if(player_data[id][PLAYER_LOADSTATE] < LOAD_OK) // данные отсутствуют
- {
- return 0
- }
- set_array(2,player_data[id][PLAYER_STATS],8)
- set_array(3,player_data[id][PLAYER_HITS],8)
- return player_data[id][PLAYER_RANK]
- }
- /*
- * Статистика за текущий раунд
- *
- * native get_user_rstats(index, stats[8], bodyhits[8])
- */
- public native_get_user_rstats(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- new stats[8],bh[8]
- get_user_rstats(id,stats,bh)
- set_array(2,stats,STATS_END)
- set_array(3,bh,HIT_END)
- return (stats[STATS_DEATHS] || stats[STATS_SHOTS])
- }
- /*
- * Статистика по жертвам
- *
- * native get_user_vstats(index, victim, stats[8], bodyhits[8], wpnname[] = "", len = 0);
- */
- public native_get_user_vstats(plugin_id,params)
- {
- if(params != 6)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 6, passed %d",params)
- return false
- }
- new id = get_param(1)
- new victim = get_param(2)
- CHECK_PLAYERRANGE(id)
- CHECK_PLAYERRANGE(victim)
- new stats[STATS_END],hits[HIT_END],wname[MAX_NAME_LENGTH]
- unpack_vstats(id,victim,stats,hits,wname,charsmax(wname))
- set_array(3,stats,STATS_END)
- set_array(4,hits,HIT_END)
- set_string(5,wname,get_param(6))
- return (stats[STATS_KILLS] || stats[STATS_HITS])
- }
- unpack_vstats(killer,victim,stats[STATS_END],hits[HIT_END],vname[],vname_len)
- {
- new i,stats_i
- for(i = 0; i < STATS_END ; i++,stats_i++)
- {
- stats[i]= player_vstats[killer][victim][stats_i]
- }
- for(i = 0; i < HIT_END ; i++,stats_i++)
- {
- hits[i]= player_vstats[killer][victim][stats_i]
- }
- copy(vname,vname_len,player_vstats[killer][victim][stats_i])
- }
- unpack_astats(attacker,victim,stats[STATS_END],hits[HIT_END],vname[],vname_len)
- {
- new i,stats_i
- for(i = 0; i < STATS_END ; i++,stats_i++)
- {
- stats[i]= player_astats[victim][attacker][stats_i]
- }
- for(i = 0; i < HIT_END ; i++,stats_i++)
- {
- hits[i]= player_astats[victim][attacker][stats_i]
- }
- copy(vname,vname_len,player_astats[victim][attacker][stats_i])
- }
- /*
- * Статистика по врагам
- *
- * native get_user_astats(index, victim, stats[8], bodyhits[8], wpnname[] = "", len = 0);
- */
- public native_get_user_astats(plugin_id,params)
- {
- if(params != 6)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 6, passed %d",params)
- return false
- }
- new id = get_param(1)
- new attacker = get_param(2)
- CHECK_PLAYERRANGE(id)
- CHECK_PLAYERRANGE(attacker)
- new stats[STATS_END],hits[HIT_END],wname[MAX_NAME_LENGTH]
- unpack_astats(attacker,id,stats,hits,wname,charsmax(wname))
- set_array(3,stats,STATS_END)
- set_array(4,hits,HIT_END)
- set_string(5,wname,get_param(6))
- return (stats[STATS_KILLS] || stats[STATS_HITS])
- }
- public native_reset_user_wstats()
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- return reset_user_wstats(id)
- }
- /*
- * Возвращает общее количество записей в базе данных
- *
- * native get_statsnum()
- */
- public native_get_statsnum(plugin_id,params)
- {
- return statsnum
- }
- /*
- * Получение статистик по позиции
- *
- * native get_stats(index, stats[8], bodyhits[8], name[], len, authid[] = "", authidlen = 0);
- */
- public native_get_stats(plugin_id,params)
- {
- // ждем начала работы с БД
- if(!is_ready)
- {
- return 0
- }
- if(params < 5)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 5, passed %d",params)
- return 0
- }
- else if(params > 5 && params != 7)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 7, passed %d",params)
- return 0
- }
- new index = get_param(1) // индекс в статистике
- // кеширование
- new index_str[10],stats_cache[stats_cache_struct]
- num_to_str(index,index_str,charsmax(index_str))
- // есть информация в кеше
- if(stats_cache_trie && TrieGetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct))
- {
- set_array(2,stats_cache[CACHE_STATS],sizeof stats_cache[CACHE_STATS])
- set_array(3,stats_cache[CACHE_HITS],sizeof stats_cache[CACHE_HITS])
- set_string(4,stats_cache[CACHE_NAME],get_param(5))
- if(params == 7)
- {
- set_string(6,stats_cache[CACHE_STEAMID],get_param(7))
- }
- return !stats_cache[CACHE_LAST] ? index + 1 : 0
- }
- // кеширование
- /*
- * прямой запрос в БД, в случае если нету данных в кеше
- */
- // открываем соединение с БД для получения актуальных данных
- if(!DB_OpenConnection())
- {
- return false // ошибка открытия соединения
- }
- else
- {
- // задание на сброс содеинения
- // чтобы не открывать новые и успеть получить сразу несколько данных за одно соединение
- if(!task_exists(task_confin))
- {
- set_task(0.1,"DB_CloseConnection",task_confin)
- }
- }
- // подготавливаем запрос в БД
- new query[QUERY_LENGTH]
- DB_QueryBuildGetstats(query,charsmax(query),.index = index)
- new Handle:sqlQue = SQL_PrepareQuery(sql_con,query)
- // ошибка выполнения запроса
- if(!SQL_Execute(sqlQue))
- {
- new errNum,err[256]
- errNum = SQL_QueryError(sqlQue,err,charsmax(err))
- log_amx("SQL query failed")
- log_amx("[ %d ] %s",errNum,err)
- log_amx("[ SQL ] %s",query)
- SQL_FreeHandle(sqlQue)
- return 0
- }
- // читаем результат
- new name[32],steamid[30],stats[8],hits[8],stats_count
- DB_ReadGetStats(sqlQue,
- name,charsmax(name),
- steamid,charsmax(steamid),
- stats,
- hits,
- .stats_count = stats_count,
- .index = index
- )
- // статистики нет
- if(!stats_count)
- {
- return false
- }
- SQL_FreeHandle(sqlQue)
- // возвращаем данные натива
- set_array(2,stats,sizeof player_data[][PLAYER_STATS])
- set_array(3,hits,sizeof player_data[][PLAYER_HITS])
- set_string(4,name,get_param(5))
- if(params == 7)
- {
- set_string(6,steamid,get_param(7))
- }
- return stats_count > 1 ? index + 1 : 0
- }
- /*
- * Получение статистик по позиции
- *
- * native get_stats2_sql(index, stats[4], authid[] = "", authidlen = 0)
- */
- public native_get_stats2(plugin_id,params)
- {
- // ждем начала работы с БД
- if(!is_ready)
- {
- return 0
- }
- if(params < 2)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 2, passed %d",params)
- return false
- }
- else if(params > 2 && params != 4)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 4, passed %d",params)
- return false
- }
- new index = get_param(1) // индекс в статистике
- // кеширование
- new index_str[10],stats_cache[stats_cache_struct]
- num_to_str(index,index_str,charsmax(index_str))
- // есть информация в кеше
- if(stats_cache_trie && TrieGetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct))
- {
- set_array(2,stats_cache[CACHE_STATS2],sizeof stats_cache[CACHE_STATS2])
- if(params == 4)
- {
- set_string(3,stats_cache[CACHE_STEAMID],get_param(4))
- }
- return !stats_cache[CACHE_LAST] ? index + 1 : 0
- }
- // кеширование
- /*
- * прямой запрос в БД, в случае если нету данных в кеше
- */
- // открываем соединение с БД для получения актуальных данных
- if(!DB_OpenConnection())
- {
- return false // ошибка открытия соединения
- }
- else
- {
- // задание на сброс содеинения
- // чтобы не открывать новые и успеть получить сразу несколько данных за одно соединение
- if(!task_exists(task_confin))
- {
- set_task(0.1,"DB_CloseConnection",task_confin)
- }
- }
- // подготавливаем запрос в БД
- new query[QUERY_LENGTH]
- DB_QueryBuildGetstats(query,charsmax(query),.index = index)
- new Handle:sqlQue = SQL_PrepareQuery(sql_con,query)
- // ошибка выполнения запроса
- if(!SQL_Execute(sqlQue))
- {
- new errNum,err[256]
- errNum = SQL_QueryError(sqlQue,err,charsmax(err))
- log_amx("SQL query failed")
- log_amx("[ %d ] %s",errNum,err)
- log_amx("[ SQL ] %s",query)
- SQL_FreeHandle(sqlQue)
- return 0
- }
- // читаем результат
- new name[32],steamid[30],stats2[4],stats_count
- DB_ReadGetStats(sqlQue,
- name,charsmax(name),
- steamid,charsmax(steamid),
- .stats2 = stats2,
- .stats_count = stats_count,
- .index = index
- )
- // статистики нет
- if(!stats_count)
- {
- return false
- }
- SQL_FreeHandle(sqlQue)
- // возвращаем данные натива
- set_array(2,stats2,sizeof player_data[][PLAYER_STATS2])
- if(params == 4)
- {
- set_string(3,steamid,get_param(4))
- }
- return stats_count > 1 ? index + 1 : 0
- }
- /*
- * Потоковый запрос на получение статистик по позиции
- * id - для кого мы запрашиваем
- * position - позиция
- * top - кол-во
- * callback[] - хандлер ответа
- *
- * native get_stats_sql_thread(id,position,top,callback[]);
- */
- public native_get_stats_thread(plugin_id,params)
- {
- // ждем начала работы с БД
- if(!is_ready)
- {
- return false
- }
- if(params < 4)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 4, passed %d",params)
- return false
- }
- new id = get_param(1)
- new position = min(statsnum,get_param(2))
- new top = get_param(3)
- new start_index = max((position - top),0)
- new callback[20]
- get_string(4,callback,charsmax(callback))
- new func_id = get_func_id(callback,plugin_id)
- if(func_id == -1)
- {
- log_error(AMX_ERR_NATIVE,"Unable to locate ^"%s^" handler.",callback)
- return false
- }
- return DB_QueryTop15(id,plugin_id,func_id,position,start_index,top,params)
- }
- // 0.7
- /*
- * Получение статистик по позиции
- *
- * native get_stats3_sql(index, stats3[STATS3_END], authid[] = "", authidlen = 0)
- */
- public native_get_stats3(plugin_id,params)
- {
- // ждем начала работы с БД
- if(!is_ready)
- {
- return 0
- }
- if(params < 2)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 2, passed %d",params)
- return false
- }
- else if(params > 2 && params != 4)
- {
- log_error(AMX_ERR_NATIVE,"Bad arguments num, expected 4, passed %d",params)
- return false
- }
- new index = get_param(1) // индекс в статистике
- // кеширование
- new index_str[10],stats_cache[stats_cache_struct]
- num_to_str(index,index_str,charsmax(index_str))
- // есть информация в кеше
- if(stats_cache_trie && TrieGetArray(stats_cache_trie,index_str,stats_cache,stats_cache_struct))
- {
- set_array(2,stats_cache[CACHE_STATS3],sizeof stats_cache[CACHE_STATS3])
- if(params == 4)
- {
- set_string(3,stats_cache[CACHE_STEAMID],get_param(4))
- }
- return !stats_cache[CACHE_LAST] ? index + 1 : 0
- }
- // кеширование
- /*
- * прямой запрос в БД, в случае если нету данных в кеше
- */
- // открываем соединение с БД для получения актуальных данных
- if(!DB_OpenConnection())
- {
- return false // ошибка открытия соединения
- }
- else
- {
- // задание на сброс содеинения
- // чтобы не открывать новые и успеть получить сразу несколько данных за одно соединение
- if(!task_exists(task_confin))
- {
- set_task(0.1,"DB_CloseConnection",task_confin)
- }
- }
- // подготавливаем запрос в БД
- new query[QUERY_LENGTH]
- DB_QueryBuildGetstats(query,charsmax(query),.index = index)
- new Handle:sqlQue = SQL_PrepareQuery(sql_con,query)
- // ошибка выполнения запроса
- if(!SQL_Execute(sqlQue))
- {
- new errNum,err[256]
- errNum = SQL_QueryError(sqlQue,err,charsmax(err))
- log_amx("SQL query failed")
- log_amx("[ %d ] %s",errNum,err)
- log_amx("[ SQL ] %s",query)
- SQL_FreeHandle(sqlQue)
- return 0
- }
- // читаем результат
- new name[32],steamid[30],stats3[STATS3_END],stats_count
- DB_ReadGetStats(sqlQue,
- name,charsmax(name),
- steamid,charsmax(steamid),
- .stats3 = stats3,
- .stats_count = stats_count,
- .index = index
- )
- // статистики нет
- if(!stats_count)
- {
- return false
- }
- SQL_FreeHandle(sqlQue)
- // возвращаем данные натива
- set_array(2,stats3,sizeof player_data[][PLAYER_STATS3])
- if(params == 4)
- {
- set_string(3,steamid,get_param(4))
- }
- return stats_count > 1 ? index + 1 : 0
- }
- /*
- * Получение статистик по позиции
- *
- * native get_user_stats3_sql(id,stats3[STATS3_END])
- */
- public native_get_user_stats3(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- if(player_data[id][PLAYER_LOADSTATE] < LOAD_OK) // данные отсутствуют
- {
- return 0
- }
- set_array(2,player_data[id][PLAYER_STATS3],STATS3_END)
- return player_data[id][PLAYER_RANK]
- }
- public native_get_user_stats2(plugin_id,params)
- {
- new id = get_param(1)
- CHECK_PLAYERRANGE(id)
- set_array(2,player_data[id][PLAYER_STATS2],sizeof player_data[][PLAYER_STATS2])
- return true
- }
- /*
- *
- * ВСЯКАЯ ХРЕНЬ ДЛЯ САМОСТОЯТЕЛЬНОГО ПРОСЧЕТА СТАТИСТИКИ
- *
- */
- is_tk(killer,victim)
- {
- if(killer == victim)
- return true
- return false
- }
- get_user_wstats(index, wpnindex, stats[8], bh[8])
- {
- for(new i ; i < STATS_END ; i++)
- {
- stats[i] = player_wstats[index][wpnindex][i]
- }
- #define krisa[%1] player_wstats[index][wpnindex][STATS_END + %1]
- for(new i ; i < HIT_END ; i++)
- {
- bh[i] = krisa[i]
- }
- }
- get_user_wrstats(index, wpnindex, stats[8], bh[8])
- {
- for(new i ; i < STATS_END ; i++)
- {
- stats[i] = player_wrstats[index][wpnindex][i]
- }
- for(new i ; i < HIT_END ; i++)
- {
- bh[i] = player_wrstats[index][wpnindex][STATS_END + i]
- }
- }
- get_user_rstats(index, stats[8], bh[8])
- {
- for(new i ; i < STATS_END ; i++)
- {
- stats[i] = player_wrstats[index][0][i]
- }
- for(new i ; i < HIT_END ; i++)
- {
- bh[i] = player_wrstats[index][0][STATS_END + i]
- }
- }
- get_user_stats2(index, stats[4])
- {
- for(new i ; i < STATS2_END ; i++)
- {
- stats[i] = player_wstats2[index][i]
- }
- return true
- }
- reset_user_wstats(index)
- {
- for(new i ; i < MAX_WEAPONS ; i++)
- {
- arrayset(player_wrstats[index][i],0,sizeof player_wrstats[][])
- }
- for(new i ; i < MAX_PLAYERS + 1 ;i++)
- {
- arrayset(player_vstats[index][i],0,sizeof player_vstats[][])
- arrayset(player_astats[index][i],0,sizeof player_astats[][])
- }
- return true
- }
- reset_user_allstats(index)
- {
- for(new i ; i < MAX_WEAPONS ; i++)
- {
- arrayset(player_wstats[index][i],0,sizeof player_wstats[][])
- }
- arrayset(player_wstats2[index],0,sizeof player_wstats2[])
- return true
- }
- public DB_OpenConnection()
- {
- if(!is_ready)
- {
- return false
- }
- if(sql_con != Empty_Handle)
- {
- return true
- }
- new errNum,err[256]
- sql_con = SQL_Connect(sql,errNum,err,charsmax(err))
- #if AMXX_VERSION_NUM >= 183
- SQL_SetCharset(sql_con,"utf8")
- #endif
- if(errNum)
- {
- log_amx("SQL query failed")
- log_amx("[ %d ] %s",errNum,err)
- return false
- }
- return true
- }
- public DB_CloseConnection()
- {
- if(sql_con != Empty_Handle)
- {
- SQL_FreeHandle(sql_con)
- sql_con = Empty_Handle
- }
- }
- /********* mysql escape functions ************/
- mysql_escape_string(dest[],len)
- {
- //copy(dest, len, source);
- replace_all(dest,len,"\\","\\\\");
- replace_all(dest,len,"\0","\\0");
- replace_all(dest,len,"\n","\\n");
- replace_all(dest,len,"\r","\\r");
- replace_all(dest,len,"\x1a","\Z");
- replace_all(dest,len,"'","''");
- replace_all(dest,len,"^"","^"^"");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement