· 7 years ago · Mar 02, 2019, 04:16 PM
1#include <amxmodx>
2#include <reapi>
3#include <sqlx>
4
5#pragma loadlib sqlite
6
7#pragma semicolon 1
8
9const QUERY_STRLEN = 512;
10const PATH_STRLEN = 64;
11const MESSAGE_STRLEN = 512;
12const TIME_STRLEN = 32;
13const ELLIPSES_ARG = 4;
14const AUTHID_STRLEN = 24;
15const PLAYER_NAME_STRLEN = 32;
16
17new const DATA_BASE_NAME[] = "stats.db";
18
19enum _:PLAYER_DATA {
20 em_sAuthID[AUTHID_STRLEN],
21 em_sName[PLAYER_NAME_STRLEN],
22 em_iKills,
23 em_iDeaths,
24 em_iHead,
25 em_iSkill
26}
27
28new Handle:g_SQLTuple;
29new g_SQLQuery[QUERY_STRLEN];
30
31new g_sLogsDir[PATH_STRLEN];
32new g_sDataDir[PATH_STRLEN];
33new g_sDataBaseFile[PATH_STRLEN + 32];
34
35new g_aPlayersData[MAX_PLAYERS + 1][PLAYER_DATA];
36
37public plugin_init() {
38 register_plugin("Stats", "2.0", "Javekson");
39 RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", .post = true);
40}
41
42public plugin_cfg() {
43 get_localinfo("amxx_logs", g_sLogsDir, charsmax(g_sLogsDir));
44 add(g_sLogsDir, charsmax(g_sLogsDir), "/stats");
45 if(!dir_exists(g_sLogsDir)) mkdir(g_sLogsDir);
46
47 get_localinfo("amxx_datadir", g_sDataDir, charsmax(g_sDataDir));
48 formatex(g_sDataBaseFile, charsmax(g_sDataBaseFile), "%s/%s", g_sDataDir, DATA_BASE_NAME);
49
50 if(!file_exists(g_sDataBaseFile)) {
51 new iFileID = fopen(g_sDataBaseFile, "a");
52 fclose(iFileID);
53 }
54
55 SQL_SetAffinity("sqlite");
56 g_SQLTuple = SQL_MakeDbTuple("", "", "", g_sDataBaseFile);
57
58 formatex(g_SQLQuery, charsmax(g_SQLQuery),
59 "CREATE TABLE IF NOT EXISTS stats( \
60 AuthID TEXT PRIMARY KEY, \
61 Name TEXT NOT NULL, \
62 Kills INTEGER DEFAULT 0, \
63 Deaths INTEGER DEFAULT 0, \
64 Head INTEGER DEFAULT 0, \
65 Skill INTEGER DEFAULT 0)"
66 );
67
68 SQL_ThreadQuery(g_SQLTuple, "QueryCreateTableHandle", g_SQLQuery);
69}
70
71public client_putinserver(id) {
72 if(is_user_bot(id) || is_user_hltv(id)) {
73 return PLUGIN_CONTINUE;
74 }
75
76 arrayset(g_aPlayersData[id], false, sizeof(g_aPlayersData[]));
77
78 new sAuthID[AUTHID_STRLEN], sPlayerName[PLAYER_NAME_STRLEN];
79 get_user_authid(id, sAuthID, charsmax(sAuthID));
80 get_user_name(id, sPlayerName, charsmax(sPlayerName));
81
82 g_aPlayersData[id][em_sAuthID] = sAuthID;
83 g_aPlayersData[id][em_sName] = sPlayerName;
84
85 new data[1]; data[0] = id;
86 formatex(g_SQLQuery, charsmax(g_SQLQuery), "SELECT * FROM stats WHERE AuthID = '%s'", g_aPlayersData[id][em_sAuthID]);
87 SQL_ThreadQuery(g_SQLTuple, "QueryCheckPlayerHandle", g_SQLQuery, data, sizeof(data));
88
89 return PLUGIN_CONTINUE;
90}
91
92public client_disconnected(id) {
93 formatex(g_SQLQuery, charsmax(g_SQLQuery),
94 "UPDATE stats SET \
95 Name = '%s' \
96 Kills = %d \
97 Deaths = %d \
98 Head = %d \
99 Skill = %d \
100 WHERE AuthID = '%s'",
101 g_aPlayersData[id][em_sName],
102 g_aPlayersData[id][em_iKills],
103 g_aPlayersData[id][em_iDeaths],
104 g_aPlayersData[id][em_iHead],
105 g_aPlayersData[id][em_iSkill],
106 g_aPlayersData[id][em_sAuthID]
107 );
108
109 SQL_ThreadQuery(g_SQLTuple, "QueryUpdatePlayerHandle", g_SQLQuery);
110}
111
112public plugin_end() {
113 SQL_FreeHandle(g_SQLTuple);
114}
115
116public QueryCreateTableHandle(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) {
117 if(failstate != TQUERY_SUCCESS) {
118 logging(g_sLogsDir, "stats_error_", "^"Error QueryCreateTableHandle: %s^"", error);
119 pause("a");
120 }
121}
122
123public QueryCheckPlayerHandle(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) {
124 if(failstate != TQUERY_SUCCESS) {
125 logging(g_sLogsDir, "stats_error_", "^"Error QueryCheckPlayerHandle: %s^"", error);
126 return PLUGIN_CONTINUE;
127 }
128
129 new id = data[0];
130
131 if(SQL_MoreResults(query)) {
132 g_aPlayersData[id][em_iKills] = SQL_ReadResult(query, 2);
133 g_aPlayersData[id][em_iDeaths] = SQL_ReadResult(query, 3);
134 g_aPlayersData[id][em_iHead] = SQL_ReadResult(query, 4);
135 g_aPlayersData[id][em_iSkill] = SQL_ReadResult(query, 5);
136
137 return PLUGIN_CONTINUE;
138 }
139
140 formatex(g_SQLQuery, charsmax(g_SQLQuery), "INSERT INTO stats(AuthID, Name) VALUES ('%s', '%s')", g_aPlayersData[id][em_sAuthID], g_aPlayersData[id][em_sName]);
141 SQL_ThreadQuery(g_SQLTuple, "QueryInsertIntoHandle", g_SQLQuery);
142
143 return PLUGIN_CONTINUE;
144}
145
146public QueryInsertIntoHandle(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) {
147 if(failstate != TQUERY_SUCCESS) {
148 logging(g_sLogsDir, "stats_error_", "^"Error QueryInsertIntoHandle: %s^"", error);
149 return PLUGIN_CONTINUE;
150 }
151 return PLUGIN_CONTINUE;
152}
153
154public QueryUpdatePlayerHandle(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) {
155 if(failstate != TQUERY_SUCCESS) {
156 logging(g_sLogsDir, "stats_error_", "^"Error QueryUpdatePlayerHandle: %s^"", error);
157 return PLUGIN_CONTINUE;
158 }
159 return PLUGIN_CONTINUE;
160}
161
162public CBasePlayer_Killed(const this, pevAttacker, iGib) {
163 g_aPlayersData[this][em_iDeaths]++;
164
165 if(is_user_connected(pevAttacker)) {
166 g_aPlayersData[pevAttacker][em_iKills]++;
167
168 if(get_member(this, m_bHeadshotKilled)) {
169 g_aPlayersData[pevAttacker][em_iHead]++;
170 }
171 }
172}
173
174stock logging(const sLogsDir[], const sFileName[], const sMessage[], any:...) {
175 new sFmtMsg[MESSAGE_STRLEN], sTime[TIME_STRLEN], sLogFile[PATH_STRLEN + 32], iFileID;
176 vformat(sFmtMsg, charsmax(sFmtMsg), sMessage, ELLIPSES_ARG);
177 get_time("%m.%Y.log", sTime, charsmax(sTime));
178 formatex(sLogFile, charsmax(sLogFile), "%s/%s%s", sLogsDir, sFileName, sTime);
179 iFileID = fopen(sLogFile, "at");
180 get_time("%d.%m.%Y - %H:%M:%S", sTime, charsmax(sTime));
181 fprintf(iFileID, "^"%s^" %s^n", sTime, sFmtMsg);
182 fclose(iFileID);
183}