· 5 years ago · Mar 20, 2020, 10:48 PM
1#include <amxmodx>
2#include <cstrike>
3#include <sqlx>
4#include <ColorChat>
5
6// Uncomment the below to enable real-time stats which will be less efficient because 2 SQL transactions
7// will occur for each kill. Leaving this commented will make kills and deaths save to the database when
8// the player disconnects or at map change.
9#define REALTIMESTATS
10
11new const Version[] = "0.1";
12
13const MAXPLAYERS = 32;
14new const SQLSTATS_DATABASE[] = "";
15new const SQLSTATS_TABLE[] = "tblStats";
16
17enum PlayerInfo
18{
19 PlayerName[ 33 ],
20 PlayerSteamID[ 34 ],
21 PlayerKills,
22 PlayerDeaths,
23 bool:IsBot
24}
25new g_piPlayerInfo[ MAXPLAYERS + 1 ][ PlayerInfo ];
26
27enum QueryTypes
28{
29 QryLoad = 5,
30 QryStats,
31 QryTop15
32}
33
34new Handle:g_SQLTuple , g_szQueryCache[ 512 ] , g_QryData[ 2 ];
35
36public plugin_init()
37{
38 register_plugin( "SQL Stats" , Version , "bugsy" );
39
40 register_event( "DeathMsg" , "DeathMsg" , "a" , "1>0" );
41
42 register_clcmd( "say /top15" , "GetTop15" );
43 register_clcmd( "say /rank" , "GetStats" );
44
45 SQL_SetAffinity( "sqlite" );
46 g_SQLTuple = SQL_MakeDbTuple( "" , "" , "" , SQLSTATS_DATABASE );
47
48 formatex( g_szQueryCache, charsmax( g_szQueryCache ) , "CREATE TABLE IF NOT EXISTS %s (SteamID VARCHAR(34) NOT NULL, PlayerName VARCHAR(32), Kills INT(7), Deaths INT(7), PRIMARY KEY (SteamID));" , SQLSTATS_TABLE );
49 SQL_ThreadQuery( g_SQLTuple , "CreateTableHandle" , g_szQueryCache );
50}
51
52public plugin_end()
53{
54 SQL_FreeHandle( g_SQLTuple );
55}
56
57public client_authorized( id )
58{
59 if ( ( g_piPlayerInfo[ id ][ IsBot ] = bool:!!is_user_bot( id ) ) == false )
60{
61 get_user_authid( id , g_piPlayerInfo[ id ][ PlayerSteamID ] , charsmax( g_piPlayerInfo[][ PlayerSteamID ] ) );
62 get_user_name( id , g_piPlayerInfo[ id ][ PlayerName ] , charsmax( g_piPlayerInfo[][ PlayerName ] ) );
63
64 g_QryData[ 0 ] = _:QryLoad;
65 g_QryData[ 1 ] = id;
66
67 g_piPlayerInfo[ id ][ PlayerKills ] = 0;
68 g_piPlayerInfo[ id ][ PlayerDeaths ] = 0;
69
70 formatex( g_szQueryCache, charsmax( g_szQueryCache ) , "SELECT Kills,Deaths FROM %s WHERE SteamID=^"%s^";" , SQLSTATS_TABLE , g_piPlayerInfo[ id ][ PlayerSteamID ] );
71 SQL_ThreadQuery( g_SQLTuple , "QueryHandle" , g_szQueryCache , g_QryData , sizeof( g_QryData ) );
72 }
73}
74
75#if !defined SQLSTATS_REALTIME
76public client_disconnect( id )
77{
78 if ( !g_piPlayerInfo[ id ][ IsBot ] )
79{
80 formatex( g_szQueryCache, charsmax( g_szQueryCache ) , "REPLACE INTO %s (SteamID,PlayerName,Kills,Deaths) VALUES (^"%s^",^"%s^",%d,%d);" ,
81 SQLSTATS_TABLE ,
82 g_piPlayerInfo[ id ][ PlayerSteamID ] ,
83 g_piPlayerInfo[ id ][ PlayerName ] ,
84 g_piPlayerInfo[ id ][ PlayerKills ] ,
85 g_piPlayerInfo[ id ][ PlayerDeaths ] );
86
87 SQL_ThreadQuery( g_SQLTuple , "SetHandle" , g_szQueryCache );
88 }
89}
90#endif
91
92public DeathMsg()
93{
94 new iKiller , iVictim , CsTeams:iVictimTeam;
95
96 iKiller = read_data( 1 );
97 iVictim = read_data( 2 );
98
99 if ( cs_get_user_team( iKiller ) != ( iVictimTeam = cs_get_user_team( iVictim ) ) ) {
100 g_piPlayerInfo[ iKiller ][ PlayerKills ]++;
101 if ( iVictimTeam != CS_TEAM_T )
102 g_piPlayerInfo[ iVictim ][ PlayerDeaths ]++;
103
104 #if defined REALTIMESTATS
105 new iPlayer[ 2 ];
106
107 iPlayer[ 0 ] = iKiller;
108 iPlayer[ 1 ] = iVictim;
109 for ( new i = 0 ; i < 2 ; i++ )
110 {
111 if ( !g_piPlayerInfo[ i ][ IsBot ] )
112 {
113 formatex( g_szQueryCache, charsmax( g_szQueryCache ) , "REPLACE INTO %s (SteamID,PlayerName,Kills,Deaths) VALUES (^"%s^",^"%s^",%d,%d);" ,
114 SQLSTATS_TABLE ,
115 g_piPlayerInfo[ iPlayer[ i ] ][ PlayerSteamID ] ,
116 g_piPlayerInfo[ iPlayer[ i ] ][ PlayerName ] ,
117 g_piPlayerInfo[ iPlayer[ i ] ][ PlayerKills ] ,
118 g_piPlayerInfo[ iPlayer[ i ] ][ PlayerDeaths ] );
119
120 SQL_ThreadQuery( g_SQLTuple , "SetHandle" , g_szQueryCache );
121 }
122 }
123 #endif
124 }
125}
126
127public CreateTableHandle( FailState , Handle:Query , Error[] , Errcode , Data[] , DataSize )
128{
129 if( FailState == TQUERY_CONNECT_FAILED )
130 return set_fail_state( "Could not connect to SQL database." );
131 else if( FailState == TQUERY_QUERY_FAILED )
132 return set_fail_state( "Query failed." );
133
134 if( Errcode )
135 return log_amx("Error on query: %s",Error);
136
137 return PLUGIN_CONTINUE;
138}
139
140public SetHandle( FailState , Handle:Query , Error[] , Errcode , Data[] , DataSize )
141{
142 if( FailState == TQUERY_CONNECT_FAILED )
143 return set_fail_state( "Could not connect to SQL database." );
144 else if( FailState == TQUERY_QUERY_FAILED )
145 return set_fail_state( "Query failed." );
146
147 if( Errcode )
148 return log_amx( "Error on query: %s" , Error );
149
150 return PLUGIN_CONTINUE;
151}
152
153public QueryHandle( FailState , Handle:Query , Error[] , Errcode , Data[] , DataSize )
154{
155 if( FailState == TQUERY_CONNECT_FAILED )
156 return set_fail_state("Could not connect to SQL database." );
157 else if( FailState == TQUERY_QUERY_FAILED )
158 return set_fail_state( "Query failed." );
159
160 if( Errcode )
161 return log_amx("Error on query: %s",Error);
162
163 new iRank, iKills , iDeaths , szName[ 33 ] , szHTML[ 1000 ] , iHTMLPos;
164
165 switch ( Data[ 0 ] )
166 {
167 case QryLoad:
168 {
169 if ( SQL_NumResults( Query ) )
170 {
171 g_piPlayerInfo[ Data[ 1 ] ][ PlayerKills ] = SQL_ReadResult( Query , 0 );
172 g_piPlayerInfo[ Data[ 1 ] ][ PlayerDeaths ] = SQL_ReadResult( Query , 1 );
173 }
174 }
175 case QryStats:
176 {
177 if ( SQL_NumResults( Query ) )
178 {
179 ColorChat( Data[ 1 ] , GREEN , "*^x01 Twoj ranking wynosi^x04 %d^x01 z^x04 %d^x01 - Masz^x04 %d^x01 zabojstw i^x04 %d^x01 zginiec" , SQL_ReadResult( Query , 3 ) + 1 , SQL_ReadResult( Query , 2 ) , SQL_ReadResult( Query , 0 ) , SQL_ReadResult( Query , 1 ) )
180 }
181 }
182 case QryTop15:
183 {
184 if ( SQL_NumResults( Query ) )
185 {
186 iHTMLPos = copy( szHTML[ iHTMLPos ] , charsmax( szHTML ) , "<html><body bgcolor=^"black^"><table style=^"color:white^">><th><b>Rank</b></th><th><b>Name</b></th><th><b>kile</b></th><th><b>fragi</b></th>" );
187
188 while ( SQL_MoreResults( Query ) )
189 {
190 SQL_ReadResult( Query , 0 , szName , charsmax( szName ) );
191 iKills = SQL_ReadResult( Query , 1 );
192 iDeaths = SQL_ReadResult( Query , 2 );
193
194 iHTMLPos += formatex( szHTML[ iHTMLPos ] , charsmax( szHTML ) - iHTMLPos , "<tr><td><center>%d</center></td><td><center>%s</center></td><td><center>%d</center></td><td><center>%d</center></td></tr>" , ++iRank , szName , iKills , iDeaths );
195
196 SQL_NextRow( Query );
197 }
198
199 copy( szHTML[ iHTMLPos ] , charsmax( szHTML ) - iHTMLPos , "</tr></table></body></html>" );
200 show_motd( Data[ 1 ] , szHTML );
201 }
202 }
203 }
204
205 return PLUGIN_CONTINUE;
206}
207
208public GetStats( id )
209{
210 g_QryData[ 0 ] = _:QryStats;
211 g_QryData[ 1 ] = id;
212
213 formatex( g_szQueryCache , charsmax( g_szQueryCache ) , "SELECT p1.Kills,p1.Deaths,(SELECT Count(*) FROM %s) AS TotalCount,(SELECT Count(*) FROM %s AS p2 WHERE (p2.Kills-p2.Deaths) > (p1.Kills-p1.Deaths)) AS KillRank \
214 FROM %s AS p1 \
215 WHERE SteamID=^"%s^";" , SQLSTATS_TABLE , SQLSTATS_TABLE , SQLSTATS_TABLE , g_piPlayerInfo[ id ][ PlayerSteamID ] );
216 SQL_ThreadQuery( g_SQLTuple , "QueryHandle" , g_szQueryCache , g_QryData , sizeof( g_QryData ) );
217}
218
219public GetTop15( id )
220{
221 g_QryData[ 0 ] = _:QryTop15;
222 g_QryData[ 1 ] = id;
223
224 formatex( g_szQueryCache , charsmax( g_szQueryCache ) , "SELECT `PlayerName`, `Kills`, `Deaths` FROM `tblStats` ORDER BY `tblStats`. `Kills` DESC LIMIT 15;" , SQLSTATS_TABLE );
225 SQL_ThreadQuery( g_SQLTuple , "QueryHandle" , g_szQueryCache , g_QryData , sizeof( g_QryData ) );
226}