· 7 years ago · Oct 29, 2018, 08:40 PM
1/* ===========================================================================
2
3 -----------------------
4 -*- [ZP] SQL: Stats -*-
5 -----------------------
6
7 (c) 2018 - BangkokRush
8 Website: http://genjero.com
9
10=========================================================================== */
11
12#include < amxmodx >
13#include < hamsandwich >
14#include < regex >
15#include < sqlx >
16#include < zp50_ammopacks >
17#include < zp50_class_zombie >
18#include < zp50_class_human >
19#include < zombieplague >
20
21//#pragma semicolon 1;
22
23// Turns stuff into bitsums
24#define turn_into_bit(%1) ( 1 << ( %1 ) )
25
26// Bitsums!
27#define bit_set(%1,%2) ( %1 |= ( turn_into_bit( %2 - 1 ) & 31 ) )
28#define bit_del(%1,%2) ( %1 &= ~ ( turn_into_bit( %2 - 1 ) & 31 ) )
29#define bit_get(%1,%2) ( %1 & ( turn_into_bit( %2 - 1 ) & 31 ) )
30
31// Checks whether a player is valid or not
32#define is_user_valid(%1) ( 1 <= %1 <= MaxClients )
33#define is_user_valid_connected(%1) ( is_user_valid( %1 ) && bit_get( g_bIsConnected, %1 ) )
34#define is_user_valid_alive(%1) ( is_user_valid( %1 ) && bit_get( g_bIsAlive, %1 ) )
35
36// Database information
37#define SQL_HOSTNAME "74.91.126.231"
38#define SQL_USERNAME "lgk"
39#define SQL_PASSWORD "YQfLS07eLWTh5yTc"
40#define SQL_DATABASE "zp_aps"
41
42new Handle:g_hSQLTuple;
43
44new g_iAmmoPacks[ MAX_PLAYERS + 1 ];
45new g_iZombieClass[ MAX_PLAYERS + 1 ];
46new g_iHumanClass[ MAX_PLAYERS + 1 ];
47
48new g_bIsConnected;
49new g_bIsAlive;
50new g_bIsLoaded;
51
52public plugin_init( )
53{
54 // v1.0.0 - Initial release
55 // v1.0.1 - Optimised the code and removed unnecessary codes
56 // v1.0.2 - Fixed replace runtime error, disabled ammo packs save if they are not yet loaded
57 // v1.0.3 - Added so SQL database also save zombie and human classes selection
58 // v1.1.0 - Changed methods class ids are retrieved and redone all most functions
59 // v1.1.1 - Updated the plugin so now it saves FPS settings
60 // v2.0.0 - Added AMX Mod X 1.8.3 support, now it saves map lighting too, and updated checks
61 // v3.0.0 - Completely redone the code and functions
62 register_plugin( "[ZP] SQL: Stats", "3.0.0", "BangkokRush" );
63
64 RegisterHamPlayer( Ham_Killed, "fw_Killed" );
65
66 SQL_CreateDatabase( );
67}
68
69public plugin_end( )
70{
71 if( g_hSQLTuple )
72 SQL_FreeHandle( g_hSQLTuple );
73}
74
75public client_putinserver( id )
76{
77 // Set connected
78 bit_set( g_bIsConnected, id );
79
80 // Make stats never have been loaded
81 bit_del( g_bIsLoaded, id );
82
83 // Reset player stats
84 g_iAmmoPacks[ id ] = 0;
85 g_iHumanClass[ id ] = ZP_INVALID_HUMAN_CLASS;
86 g_iZombieClass[ id ] = ZP_INVALID_ZOMBIE_CLASS;
87 // Load stats
88 SQL_InsertPlayer( id );
89}
90
91public client_disconnected( id )
92{
93 // Clear unnecessary bits
94 bit_del( g_bIsConnected, id );
95 bit_del( g_bIsAlive, id );
96 // Player stats have been loaded
97 if( bit_get( g_bIsLoaded, id ) )
98 {
99 // Save current stats
100 SQL_UpdatePlayer( id );
101
102 // Make stats never have been loaded
103 bit_del( g_bIsLoaded, id );
104
105 // Reset player stats
106 g_iAmmoPacks[ id ] = 0;
107 g_iZombieClass[ id ] = ZP_INVALID_ZOMBIE_CLASS;
108 g_iHumanClass[ id ] = ZP_INVALID_HUMAN_CLASS;
109 }
110}
111
112public zp_fw_core_spawn_post( id )
113{
114 if( !is_user_valid_connected( id ) )
115 return;
116
117 bit_set( g_bIsAlive, id );
118}
119
120public zp_fw_core_cure_pre(id)
121{
122 if( !is_user_valid_alive( id ) )
123 return;
124
125 g_iHumanClass[ id ] = zp_class_human_get_current( id );
126 SQL_UpdatePlayer( id );
127}
128
129public zp_fw_core_infect_pre(id)
130{
131 if( !is_user_valid_alive( id ) )
132 return;
133
134 g_iZombieClass[ id ] = zp_class_zombie_get_next( id );
135 SQL_UpdatePlayer( id );
136}
137
138public zp_fw_core_infect_post( id )
139{
140 // Player should be alive, we need the VERY CURRENT class!
141 if( !is_user_valid_alive( id ) )
142 return;
143
144 // Update with the selected zombie class
145 g_iZombieClass[ id ] = zp_class_zombie_get_next( id );
146}
147
148public zp_fw_core_cure_post( id )
149{
150 // Player should be alive, we need the VERY CURRENT class!
151 if( !is_user_valid_alive( id ) )
152 return;
153
154 // Update with the last played human class
155 g_iHumanClass[ id ] = zp_class_human_get_next( id );
156}
157
158public zp_fw_ammopacks_update( id, iAmount )
159{
160 // Copy amount set to our array! :)
161 g_iAmmoPacks[ id ] = iAmount;
162 SQL_UpdatePlayer( id );
163}
164
165public fw_Killed( victim_id )
166{
167 // Invalid dead player?
168 if( !is_user_valid_connected( victim_id ) )
169 return;
170 // Remove alive
171 bit_del( g_bIsAlive, victim_id );
172}
173
174public SQL_ThreadQuery_Empty( iFailState, Handle:hQuery, szError[ ], iError, szData[ ], iData )
175{
176 if( iFailState != TQUERY_SUCCESS )
177 {
178 set_fail_state( szError );
179 return;
180 }
181
182 SQL_FreeHandle( hQuery );
183}
184
185public SQL_ThreadQuery_Insert( iFailState, Handle:hQuery, szError[ ], iError, szData[ ], iData )
186{
187 if( iFailState != TQUERY_SUCCESS )
188 {
189 set_fail_state( szError );
190 return;
191 }
192
193 static id, iUser;
194 id = szData[ 0 ];
195 iUser = szData[ 1 ];
196
197 if( get_user_userid( id ) != iUser )
198 return;
199
200 static szAuth[ 32 ], szQuery[ 256 ];
201 get_user_authid( id, szAuth, charsmax( szAuth ) );
202
203 formatex( szQuery, charsmax( szQuery ), "SELECT `ammo_packs`, `zombie_class`, `human_class` FROM `cs_zp_stats` WHERE `auth_id` = '%s';", szAuth );
204 SQL_ThreadQuery( g_hSQLTuple, "SQL_ThreadQuery_Select", szQuery, szData, iData );
205
206 SQL_FreeHandle( hQuery );
207}
208
209public SQL_ThreadQuery_Select( iFailState, Handle:hQuery, szError[ ], iError, szData[ ], iData )
210{
211 if( iFailState != TQUERY_SUCCESS )
212 {
213 set_fail_state( szError );
214 return;
215 }
216
217 static id, iUser;
218 id = szData[ 0 ];
219 iUser = szData[ 1 ];
220
221 if( get_user_userid( id ) != iUser )
222 return;
223
224 // Set player's ammo packs, zombie class and human class
225 g_iAmmoPacks[ id ] = SQL_ReadResult( hQuery, SQL_FieldNameToNum( hQuery, "ammo_packs" ) );
226 g_iZombieClass[ id ] = SQL_ReadResult( hQuery, SQL_FieldNameToNum( hQuery, "zombie_class" ) );
227 g_iHumanClass[ id ] = SQL_ReadResult( hQuery, SQL_FieldNameToNum( hQuery, "human_class" ) );
228
229 // Override player's data with the saved ones
230 zp_ammopacks_set( id, g_iAmmoPacks[ id ] );
231
232 if( g_iZombieClass[ id ] != ZP_INVALID_ZOMBIE_CLASS )
233 zp_class_zombie_set_next( id, g_iZombieClass[ id ] );
234
235 if( g_iHumanClass[ id ] != ZP_INVALID_HUMAN_CLASS )
236 zp_class_human_set_next( id, g_iHumanClass[ id ] );
237
238 // Set that the data has been loaded
239 bit_set( g_bIsLoaded, id );
240
241 SQL_FreeHandle( hQuery );
242}
243
244SQL_CreateDatabase( )
245{
246 g_hSQLTuple = SQL_MakeDbTuple( SQL_HOSTNAME, SQL_USERNAME, SQL_PASSWORD, SQL_DATABASE );
247
248 if( !g_hSQLTuple )
249 {
250 set_fail_state( "Could not make database tuple" );
251
252 SQL_FreeHandle( g_hSQLTuple );
253 return;
254 }
255
256 static szQuery[ 512 ];
257
258 formatex( szQuery, charsmax( szQuery ), "CREATE TABLE IF NOT EXISTS `cs_zp_stats` ( `auth_id` VARCHAR( 32 ), `player_name` VARCHAR( 32 ), `ammo_packs` INT( 11 ) NOT NULL DEFAULT 0, `zombie_class` INT( 11 ) NOT NULL DEFAULT -1, `human_class` INT( 11 ) NOT NULL DEFAULT -1, UNIQUE( `auth_id` ) );" );
259 SQL_ThreadQuery( g_hSQLTuple, "SQL_ThreadQuery_Empty", szQuery );
260}
261
262SQL_InsertPlayer( id )
263{
264 static szAuth[ 32 ];
265 get_user_authid( id, szAuth, charsmax( szAuth ) );
266
267// if( !is_steam_valid( szAuth ) )
268// return;
269
270 static szName[ 64 ];
271 get_user_name( id, szName, charsmax( szName ) );
272
273 replace_all( szName, charsmax( szName ), "'", "''" );
274
275 static szData[ 2 ], szQuery[ 256 ];
276 szData[ 0 ] = id;
277 szData[ 1 ] = get_user_userid( id );
278
279 formatex( szQuery, charsmax( szQuery ), "INSERT INTO `cs_zp_stats` ( `auth_id`, `player_name` ) VALUES ( '%s', '%s' ) ON DUPLICATE KEY UPDATE `player_name` = '%s';", szAuth, szName, szName );
280 SQL_ThreadQuery( g_hSQLTuple, "SQL_ThreadQuery_Insert", szQuery, szData, sizeof( szData ) );
281}
282
283SQL_UpdatePlayer( id )
284{
285 static szAuth[ 32 ];
286 get_user_authid( id, szAuth, charsmax( szAuth ) );
287
288// if( !is_steam_valid( szAuth ) )
289// return;
290
291 static szName[ 64 ], szQuery[ 512 ];
292 get_user_name( id, szName, charsmax( szName ) );
293
294 replace_all( szName, charsmax( szName ), "'", "''" );
295
296 formatex( szQuery, charsmax( szQuery ), "UPDATE `cs_zp_stats` SET `player_name` = '%s', `ammo_packs` = %d, `zombie_class` = %d, `human_class` = %d WHERE `auth_id` = '%s';", szName, g_iAmmoPacks[ id ], g_iZombieClass[ id ], g_iHumanClass[ id ], szAuth );
297 SQL_ThreadQuery( g_hSQLTuple, "SQL_ThreadQuery_Empty", szQuery );
298}
299
300/*
301bool:is_steam_valid( const szAuth[ ] )
302{
303 new Regex:iResult = regex_match( szAuth, "^^STEAM_[0-9]:[01]:\d+$" );
304
305 if( iResult )
306 {
307 regex_free( iResult );
308 return true;
309 }
310
311 return false;
312}
313*/