Parent Directory | Revision Log
Revision 1 - (view) (download)
1 : | ian | 1 | /* |
2 : | Climb v2.0a2 | ||
3 : | Copyright (C) 2006 Ian (Juan) Cammarata | ||
4 : | |||
5 : | This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. | ||
6 : | |||
7 : | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
8 : | |||
9 : | You should have received a copy of the GNU General Public License along with this program; go to http://www.opensource.org/licenses/gpl-license.php | ||
10 : | */ | ||
11 : | /* | ||
12 : | *To do: | ||
13 : | * Recalc limiter/timeout on stats pages. | ||
14 : | * Flags for weapons used | ||
15 : | * Save user/pass login data for sessions (don't require login ever map change) | ||
16 : | * Account management for accounts with user/pass login. email, change password, password recovery | ||
17 : | * Unsolid as function of position and velocity | ||
18 : | * Respawn vehicles if they go out of the map | ||
19 : | *=============================================================================== | ||
20 : | * Climb v2.0a2 | ||
21 : | * Created by Ian (Juan) Cammarata | ||
22 : | * http://ian.cammarata.us | ||
23 : | * AMXX 1.76 | ||
24 : | * 3/2/2007 1:23:06 AM | ||
25 : | *=============================================================================== | ||
26 : | * Description: | ||
27 : | * This plugin is designed for use in climbing maps like those available from | ||
28 : | * www.kreedz.com. If you want to disable this plugin for the duration of a | ||
29 : | * map you can set cvar "climb 0", this will disable the ability to make and | ||
30 : | * recall checkpoints and the automatic respawning. | ||
31 : | *=============================================================================== | ||
32 : | * Commands: | ||
33 : | * say /checkpoint : Save your position | ||
34 : | * say /gocheck : Teleport you to your last saved position | ||
35 : | * say /stuck : Teleport you to your previous checkpoint in case | ||
36 : | * you get stuck in a wall | ||
37 : | *=============================================================================== | ||
38 : | * Cvars: | ||
39 : | * climb <1|0> : Enables|Disables all climb.amx functionality. | ||
40 : | * climb_boost <1|0> : Enables|Disables boosting. | ||
41 : | * climb_cpprice <0|...> : Set to dollar amount for cost of checkpoints. | ||
42 : | * climb_startmoney <1337|0-16000> : Money amount set when players start timer. | ||
43 : | * | ||
44 : | * climb_render <0|1> : Changes unsolid rendering style, 0=classic, other=new more see through rendering. | ||
45 : | * climb_sounds <1|0> : Enables|Disables sounds build in to the Climb plugin. | ||
46 : | * | ||
47 : | * climb_webmod <0|1> : Disables|Enables web mod interoperability. | ||
48 : | * climb_stats_path <NULL|...> : Path to save generated stats pages. (If using | ||
49 : | * WebMod, enter path to webmods www folder.) | ||
50 : | * climb_stats_url <NULL|...> : URL to send clients to for stats pages. Only | ||
51 : | * use if you have a web server running on the | ||
52 : | * same machine as the game server. | ||
53 : | * IF WEBMOD=1 THIS IS IGNORED. | ||
54 : | * climb_stats_hsurl <NULL|...> : "%s" will be replaced with map name. Set | ||
55 : | * to send client to URL if you have a page | ||
56 : | * that automatically generates high scores via | ||
57 : | * direct DB access. | ||
58 : | * IF WEBMOD=1 THIS IS IGNORED. | ||
59 : | * climb_stats_msg <NULL|...> : Message to display on scoreboard. Use HTML | ||
60 : | * | ||
61 : | * ip_internal <localhost|...> : Set to internal network IP or hostname. (If server behind NAT) | ||
62 : | * ip_external <localhost|...> : Set to external network IP or hostname. | ||
63 : | * | ||
64 : | * climb_msg_r <0|0-255> : Display message red value. | ||
65 : | * climb_msg_g <150|0-255> : Display message green value. | ||
66 : | * climb_msg_b <250|0-255> : Display message blue value. | ||
67 : | * climb_msg_x <0.05|0-1> : Display message x position. | ||
68 : | * climb_msg_y <0.5|0-1> : Display message y position. | ||
69 : | * | ||
70 : | * *The following cvars are only read at plugin load, changes will not take | ||
71 : | * effect until the map is changed. | ||
72 : | * climb_save <1|0> : Enables|Disables saving of stats to a database. | ||
73 : | * | ||
74 : | * climb_db_type <sqlite|mysql> : Database type. | ||
75 : | * climb_db_host <127.0.0.1> : Database host name/ip. | ||
76 : | * climb_db_user <NULL|...> : Database user name. | ||
77 : | * climb_db_pass <NULL|...> : Database password. | ||
78 : | * climb_db_name <climb|...> : Database name. | ||
79 : | * climb_db_prefix <climb_|...> : Table name prefix. | ||
80 : | *=============================================================================== | ||
81 : | * Requirements: | ||
82 : | * Modules: | ||
83 : | * Engine | ||
84 : | * Fakemeta | ||
85 : | * DB Module (MySQL or SQLite/Only need to use stats.) | ||
86 : | * AMXX 1.76 or higher | ||
87 : | *=============================================================================== | ||
88 : | * Notes: | ||
89 : | * Enjoy! | ||
90 : | *=============================================================================== | ||
91 : | * Change Log: | ||
92 : | * Key (+ added | - removed | c changed | f fixed | r refactored) | ||
93 : | * | ||
94 : | * v2.0a2 (FEB 16, 2007) | ||
95 : | * +: 2 addition boost types. Super jump and double jump. (No partner needed for boosting anymore) | ||
96 : | * +: Boosts are counted. (Not logged in DB yet.) | ||
97 : | * +: Stats saving in database. MySQL or SQLite. (MySQL not tested yet. Only works with single db module enabled) | ||
98 : | * +: Players now get rewarded for finishing even without starting the timer. | ||
99 : | * +: Cvars for message color and position. (climb_msg_r, ..._g, ..._b, ..._x, ..._y) | ||
100 : | * +: Cvar climb_startmoney - Value to set money to when players start timer. | ||
101 : | * +: Cvar climb_stats_msg - Message to display on the HTML scoreboards. | ||
102 : | * +: Cvar climb_unsolid_type - Change rendering style for unsolid players. | ||
103 : | * +: Cvar climb_sounds - Disabled Climb plugin sounds. | ||
104 : | * +: Several cvars for database settings. | ||
105 : | * +: All players spawn at spawn point closest to the start button. (Eliminates cheat in maps with a spawn point at the finish button.) | ||
106 : | * +: Additional spawns added during map load to fix maps without enough spawns. | ||
107 : | * +: Timeouts for respawning and boosting. | ||
108 : | * +: Command "help". Displays HTML help pages. | ||
109 : | * -: AMX compatability. (AMX is officially dead) | ||
110 : | * c: Cvars now prefixed with climb_ instead of amx_. | ||
111 : | * c: Minor code optimizations. | ||
112 : | * c: Command "Boost" now takes players to the boost help page instead of activating solid boost. | ||
113 : | * r: All internal cvar handling is now done with pointers. (With the acception of cvars used only during init functions.) | ||
114 : | * r: Solid boost only lasts 15 seconds at a time now since its usage is being tracked. | ||
115 : | * r: Major internal rewrite (Probably added a few bugs. More major rewrites coming in next release.) | ||
116 : | * v1.9.19 (AUG 02, 2006) | ||
117 : | * +: New public cvar 'climb_version' to aid in searching for server with this plugin. | ||
118 : | * +: Show checkpoints, gochecks, and finish stats (Stats will be more extensive in next version) with finish announcement. | ||
119 : | * -: Global chat. Use AllChat plugin instead. | ||
120 : | * -: Cvar: amx_climb_globchat | ||
121 : | * c: The /spec command now obeys the cvar "allow_spectators", clients with reserved slot always allowed. | ||
122 : | * c: Shows number of checks and gocheck on client finish announcement. | ||
123 : | * f: Bug caused by using stop command while paused. | ||
124 : | * r: Client commands reworked. Everything functions the same, but with more functionality. For example the gc command can be entered as any of the following: gc, /gc, \gc, say gc, say /gc, say \gc, say_team gc, etc... | ||
125 : | * v1.9.18 (MAY 15, 2006) | ||
126 : | * r: Recoded the way health is handled. Should work for any map now. | ||
127 : | * v1.9.17 (APR 07, 2006) | ||
128 : | * c: Plugin is now compatible with both AMX and AMXX. | ||
129 : | * c: The /spectate command can now be used by anyone. Admin no longer required. | ||
130 : | * v1.9.16a | ||
131 : | * f: Added health fix for kz_cfl_yamakasi. | ||
132 : | * c: New CSS theme for html scoreboard. | ||
133 : | * v1.9.16 | ||
134 : | * +: Counts usage of CP and GC commands(only displayed on html scoreboard). | ||
135 : | * f: Added health fix for kz_lighthouse and kz_phoogi. | ||
136 : | * v1.9.15 | ||
137 : | * +: Colorized global chat. ADMIN_RESERVATION has name in green instead of team color. | ||
138 : | * +: /stop command. Resets timer to zero, end climbing session. | ||
139 : | * c: Reset function. /stop + /respawn. Client is now reset automatically when pressing the start button if they are not already started. | ||
140 : | * f: YOU CAN'T GET STUCK ANYMORE!!! (Well almost. Doing gocheck a second time gets you unstuck.) | ||
141 : | * f: Global chat is now logged correctly and shows up in HLSW. | ||
142 : | * v1.9.14 | ||
143 : | * +: Hook is taken away when client starts timer, given back if they reset. | ||
144 : | * +: Max health fixes for several new maps. | ||
145 : | * +: Sort clients on CS scoreboard by climb rank. | ||
146 : | * +: Cvar amx_climb_boost - enable\disable boosting. | ||
147 : | * +: Cvar amx_climb_cpprice - charge money for checkpoints. | ||
148 : | * +: Custom configurable commands based on events. (climb.ini) | ||
149 : | * +: Global chat. cvar: amx_climb_globchat <1|0> | ||
150 : | * +: Client climb time is now shown using the round time HUD sprites. | ||
151 : | * -: Command /mytime, not needed because of HUD sprite timer. | ||
152 : | * -: Auto time display every 30 seconds, not needed because of HUD sprite timer. | ||
153 : | * c: Added another start button sound. | ||
154 : | * c: Super healing doors no longer removed. (Needed for shortcuts in some maps.) | ||
155 : | * f: Admins can't be alive as spectator even with 3rd party respawn plugin. | ||
156 : | * f: Keep godmode after respawning if finished map and not reset. | ||
157 : | * f: Admins VIP display on CS scoreboard is now updated whenever clients connect. | ||
158 : | * f: Health charger minimaps in kz_real_skyscraper & kz_northpole_b01. | ||
159 : | * f: Not teleporting to exact cp position if another client is on your cp. | ||
160 : | * f: Respawning outside of maps sometimes immediately after leaving spectator. | ||
161 : | */ | ||
162 : | #include <amxmodx> | ||
163 : | #include <fun> | ||
164 : | #include <amxmisc> | ||
165 : | #include <engine> | ||
166 : | #include <fakemeta> | ||
167 : | #include <sqlx> | ||
168 : | #include <string2> | ||
169 : | #include <cstrike> | ||
170 : | #include <cstrike2> | ||
171 : | |||
172 : | #define SF_MAX 50 //Maximum number of start/finish commands in climb.ini | ||
173 : | #define VERSION "2.0a2" | ||
174 : | |||
175 : | //DB variables | ||
176 : | new Handle:db_tuple,db_prefix[10],bool:climb_save | ||
177 : | |||
178 : | //Client flags arrays | ||
179 : | new Float:origins[32][41],timer[32][13],time_stamps[33][2],Float:post_think_vel[32][3] | ||
180 : | |||
181 : | //Temp save vars | ||
182 : | new steamid[32][32],savepos=0,Float:originssave[32][41],timersave[32][13] | ||
183 : | |||
184 : | //Touch for unsolid clients | ||
185 : | new trig[100],trignum=0,brk[50],brknum=0 | ||
186 : | |||
187 : | //Other stuff | ||
188 : | new hooked[32],hp=100 | ||
189 : | new sfactions[SF_MAX][50],sfcount=0 | ||
190 : | new score_ts,hscore_ts | ||
191 : | new dyn_spawn_ids[32],dyn_spawn_count=-1,Float:spawn_tp_orig[3] | ||
192 : | |||
193 : | //Cvar Pointers | ||
194 : | new p_climb,p_webmod,p_boost,p_cpprice | ||
195 : | new p_msg_r,p_msg_g,p_msg_b,p_msg_x,p_msg_y | ||
196 : | new p_sounds,p_render | ||
197 : | new p_ip_internal,p_ip_external,p_port | ||
198 : | new p_allow_spectators,p_startmoney | ||
199 : | new p_stats_path,p_stats_url,p_stats_hsurl,p_stats_msg | ||
200 : | |||
201 : | //Model size | ||
202 : | //standing 32x32x72 | ||
203 : | //crouched 32x32x36 | ||
204 : | |||
205 : | //timestamps[id][x] | ||
206 : | #define TS_SPAWN 0 | ||
207 : | #define TS_BOOST 1 | ||
208 : | |||
209 : | //Tasks: | ||
210 : | //#define TSK_AUTOHEAL 50 //50+ : Auto Heal | ||
211 : | //#define TSK_AUTORSPN 100 //100+: Auto Respawn | ||
212 : | //#define TSK_BOOSTTMR 150 //150+: Solid Boost Timer | ||
213 : | |||
214 : | //timer[id][x]: | ||
215 : | #define TMR_CFLAGS 0 //Status | ||
216 : | #define TMR_STARTD 1 //Start Time | ||
217 : | #define TMR_FINISH 2 //Finish Time | ||
218 : | #define TMR_CPSCNT 3 //CP Count | ||
219 : | #define TMR_GCSCNT 4 //GC Count | ||
220 : | #define TMR_BSTTME 5 //Best Time | ||
221 : | #define TMR_BSTCPS 6 //Best CP | ||
222 : | #define TMR_BSTGCS 7 //Best GC | ||
223 : | #define TMR_SESFIN 8 //Finished this session | ||
224 : | #define TMR_MAPFIN 9 //Total times finished this map | ||
225 : | #define TMR_DBUSER 10 //Database player ID; 0=not registered; -1=not registered & shared steam id | ||
226 : | #define TMR_BOOSTS 11 //Number of boosts used | ||
227 : | #define TMR_WPNUSE 12 //Bit sum of used weapons | ||
228 : | |||
229 : | //Status timer[id][TMR_CFLAGS]&=x | ||
230 : | #define CF_NULL 0 //Used to clear flags in change_status() and change_boost() functions | ||
231 : | #define CF_STOP (1<<0) //STATUS FLAG: Not Started | ||
232 : | #define CF_START (1<<1) //STATUS FLAG: Climbing | ||
233 : | #define CF_PAUSE (1<<2) //STATUS FLAG: Paused | ||
234 : | #define CF_SOLID (1<<3) //BOOST FLAG | ||
235 : | #define CF_SUPER_JUMP (1<<4) //BOOST FLAG | ||
236 : | #define CF_DOUBLE_JUMP (1<<5) //BOOST FLAG | ||
237 : | #define CF_SPAWN_NO_GC (1<<6) | ||
238 : | #define CF_NO_SCOUT (1<<7) | ||
239 : | #define CF_NO_VIP (1<<8) | ||
240 : | |||
241 : | public client_putinserver(id){ | ||
242 : | if(get_pcvar_num(p_climb)&&!is_user_bot(id)){ | ||
243 : | new ida[1] | ||
244 : | ida[0]=id | ||
245 : | set_task(20.0,"connect_advert",0,ida,1) | ||
246 : | //Set CF_STOP status | ||
247 : | change_status(id,CF_STOP) | ||
248 : | //search steamid to position reference for match | ||
249 : | new searchid[32] | ||
250 : | get_user_authid(id,searchid,31) | ||
251 : | for(new i=0;i<32;i++) | ||
252 : | if(equal(searchid,steamid[i])){ | ||
253 : | //load origins & timer array if match found | ||
254 : | origins[id]=originssave[i] | ||
255 : | timer[id]=timersave[i] | ||
256 : | return PLUGIN_CONTINUE | ||
257 : | } | ||
258 : | if(climb_save&&timer[id][TMR_DBUSER]<1) | ||
259 : | set_task(5.0,"auto_login",0,ida,1) | ||
260 : | } | ||
261 : | return PLUGIN_CONTINUE | ||
262 : | } | ||
263 : | public connect_advert(ida[1]){ | ||
264 : | new id=ida[0] | ||
265 : | new msg[51] | ||
266 : | formatex(msg,50,"^x04 ^t^t^t^t^t^t^tThis server is using Climb v%s by:",VERSION) | ||
267 : | saytext(id,id,msg) | ||
268 : | saytext(id,id,"^x04 ^t^t^t^t^t^t^tIan (Juan) Cammarata (http://ian.cammarata.us)") | ||
269 : | } | ||
270 : | public auto_login(ida[1]) | ||
271 : | return client_cmd(ida[0],"login") | ||
272 : | public client_disconnect(id){ | ||
273 : | if(get_pcvar_num(p_climb)&&!is_user_bot(id)){ | ||
274 : | savepos++ | ||
275 : | if(savepos==31)savepos=0 | ||
276 : | new saveid[32] | ||
277 : | get_user_authid(id,saveid,32) | ||
278 : | //erase previous save if exists | ||
279 : | for(new i=0;i<32;i++)if(equal(saveid,steamid[i]))steamid[i]="" | ||
280 : | //save steamid to position reference | ||
281 : | steamid[savepos]=saveid | ||
282 : | //save origins | ||
283 : | originssave[savepos]=origins[id] | ||
284 : | //save timer array/Pause if running | ||
285 : | if(timer[id][TMR_CFLAGS]&CF_START)change_status(id,CF_PAUSE) | ||
286 : | timersave[savepos]=timer[id] | ||
287 : | //clear origins for new client in that slot | ||
288 : | for(new i=0;i<8;i++)origins[id][i]=0.0 | ||
289 : | for(new i=0;i<11;i++)timer[id][i]=0 | ||
290 : | hooked[id]=0 | ||
291 : | } | ||
292 : | return PLUGIN_HANDLED | ||
293 : | } | ||
294 : | public check(id){ | ||
295 : | if(get_pcvar_num(p_climb)&&isalive(id)&¬paused(id)){ | ||
296 : | new cpprice=get_pcvar_num(p_cpprice) | ||
297 : | if(cpprice>0){ | ||
298 : | new cash=cs_get_user_money(id) | ||
299 : | if(cpprice>cash){ | ||
300 : | clmsg(id,"You don't have enough cash for more checkpoints.") | ||
301 : | client_print(id,print_chat,"You don't have enough cash for more checkpoints.") | ||
302 : | return PLUGIN_HANDLED | ||
303 : | } | ||
304 : | cs_set_user_money(id,cash-cpprice) | ||
305 : | } | ||
306 : | if(!hooked[id]){ | ||
307 : | new Float:vel[3] | ||
308 : | entity_get_vector(id,EV_VEC_velocity,vel) | ||
309 : | if(vel[2]>=0){ | ||
310 : | new Float:coords[3] | ||
311 : | entity_get_vector(id,EV_VEC_origin,coords) | ||
312 : | if(coords[0]||coords[1]||coords[2]){ | ||
313 : | for(new i=39;i>3;i--) origins[id][i]=origins[id][i-4] | ||
314 : | for(new i=0;i<3;i++) origins[id][i]=coords[i] | ||
315 : | origins[id][3]=entity_get_float(id, EV_FL_gravity) | ||
316 : | new msg[100]="Checkpoint saved." | ||
317 : | if(timer[id][TMR_CFLAGS]&CF_START){ | ||
318 : | timer[id][TMR_CPSCNT]++ | ||
319 : | formatex(msg,99,"Checkpoint saved. (%d CPS/ %d GCS/ %d Boosts)",timer[id][TMR_CPSCNT],timer[id][TMR_GCSCNT],timer[id][TMR_BOOSTS]) | ||
320 : | } | ||
321 : | clmsg(id,msg) | ||
322 : | } | ||
323 : | else clmsg(id,"Can not save checkpoint at current location.") | ||
324 : | } | ||
325 : | else clmsg(id,"You can't make checkpoints while falling.") | ||
326 : | } | ||
327 : | else clmsg(id,"You can't make checkpoints while using hook.") | ||
328 : | } | ||
329 : | return PLUGIN_HANDLED | ||
330 : | } | ||
331 : | public gocheck(id){ | ||
332 : | if(get_pcvar_num(p_climb)&&isalive(id)&¬paused(id)){ | ||
333 : | if(origins[id][0]||origins[id][1]||origins[id][2]){ | ||
334 : | new Float:coords[3] | ||
335 : | for(new i=0;i<3;i++)coords[i]=origins[id][i] | ||
336 : | entity_set_float(id,EV_FL_gravity,origins[id][3]) | ||
337 : | teleport(id,coords) | ||
338 : | new msg[100]="Checkpoint restored." | ||
339 : | if(timer[id][TMR_CFLAGS]&CF_START){ | ||
340 : | timer[id][TMR_GCSCNT]++ | ||
341 : | formatex(msg,99,"Checkpoint restored. (%d CPS/ %d GCS/ %d Boosts)",timer[id][TMR_CPSCNT],timer[id][TMR_GCSCNT],timer[id][TMR_BOOSTS]) | ||
342 : | } | ||
343 : | clmsg(id,msg) | ||
344 : | } | ||
345 : | else{ | ||
346 : | clmsg(id,"You must make a checkpoint first.") | ||
347 : | return 0 | ||
348 : | } | ||
349 : | } | ||
350 : | return 1 | ||
351 : | } | ||
352 : | public stuck(id){ | ||
353 : | if(get_pcvar_num(p_climb)&&isalive(id)&¬paused(id)){ | ||
354 : | if(origins[id][4]||origins[id][5]||origins[id][6]){ | ||
355 : | new Float:coords[3] | ||
356 : | for(new i=0;i<36;i++) origins[id][i]=origins[id][i+4] | ||
357 : | for(new i=0;i<3;i++) coords[i]=origins[id][i] | ||
358 : | entity_set_float(id,EV_FL_gravity,origins[id][3]) | ||
359 : | teleport(id,coords) | ||
360 : | new msg[100]="Previous checkpoint restored." | ||
361 : | if(timer[id][TMR_CFLAGS]&CF_START){ | ||
362 : | timer[id][TMR_CPSCNT]-- | ||
363 : | formatex(msg,99,"Previous checkpoint restored. (%d CPS/ %d GCS/ %d Boosts)",timer[id][TMR_CPSCNT],timer[id][TMR_GCSCNT],timer[id][TMR_BOOSTS]) | ||
364 : | } | ||
365 : | clmsg(id,msg) | ||
366 : | new cpprice=get_pcvar_num(p_cpprice) | ||
367 : | if(cpprice>0){ | ||
368 : | new cash=cs_get_user_money(id) | ||
369 : | cs_set_user_money(id,cash+cpprice) | ||
370 : | } | ||
371 : | } | ||
372 : | else clmsg(id,"You have no previous checkpoints remaining.") | ||
373 : | } | ||
374 : | return PLUGIN_HANDLED | ||
375 : | } | ||
376 : | //Respawn client when they die | ||
377 : | public death_msg(){ | ||
378 : | if (get_pcvar_num(p_climb)){ | ||
379 : | new id=read_data(2) | ||
380 : | new ida[1] | ||
381 : | ida[0]=id | ||
382 : | if(task_exists(100+id))remove_task(100+id) | ||
383 : | if(isct(id)){ | ||
384 : | set_task(0.2,"respawn",100+id,ida,1) | ||
385 : | } | ||
386 : | } | ||
387 : | return PLUGIN_HANDLED | ||
388 : | } | ||
389 : | public change_status(id,newstat){ | ||
390 : | new cflags=timer[id][TMR_CFLAGS] | ||
391 : | if(cflags&CF_STOP)timer[id][TMR_CFLAGS]-=CF_STOP | ||
392 : | else if(cflags&CF_START)timer[id][TMR_CFLAGS]-=CF_START | ||
393 : | else if(cflags&CF_PAUSE)timer[id][TMR_CFLAGS]-=CF_PAUSE | ||
394 : | if(newstat&CF_PAUSE){ | ||
395 : | if(cflags&CF_PAUSE){ | ||
396 : | timer[id][TMR_CFLAGS]+=CF_START | ||
397 : | timer[id][TMR_STARTD]=get_systime()-timer[id][TMR_STARTD] | ||
398 : | set_entity_flags(id,FL_FROZEN,0) | ||
399 : | unsolid(id) | ||
400 : | entity_set_float(id,EV_FL_gravity,origins[id][40]) | ||
401 : | clmsg(id,"UNPAUSED") | ||
402 : | } | ||
403 : | else if(cflags&CF_START){ | ||
404 : | cl_pause(id) | ||
405 : | timer[id][TMR_CFLAGS]+=CF_PAUSE | ||
406 : | } | ||
407 : | else{ | ||
408 : | clmsg(id,"You must start the timer before you can pause.") | ||
409 : | timer[id][TMR_CFLAGS]=cflags | ||
410 : | } | ||
411 : | } | ||
412 : | else timer[id][TMR_CFLAGS]+=newstat | ||
413 : | return PLUGIN_HANDLED | ||
414 : | } | ||
415 : | public cl_pause(id){ | ||
416 : | timer[id][TMR_STARTD]=get_systime()-timer[id][TMR_STARTD] | ||
417 : | set_entity_flags(id,FL_FROZEN,1) | ||
418 : | unsolid(id) | ||
419 : | set_rendering(id,kRenderFxGlowShell,0,0,255,kRenderTransColor,1) | ||
420 : | origins[id][40]=entity_get_float(id,EV_FL_gravity) | ||
421 : | entity_set_float(id,EV_FL_gravity,0.0) | ||
422 : | clmsg(id,"PAUSED") | ||
423 : | return PLUGIN_HANDLED | ||
424 : | } | ||
425 : | public stop(id){ | ||
426 : | if(get_pcvar_num(p_climb)&&timer[id][TMR_CFLAGS]&CF_START/*&¬paused(id)*/){ | ||
427 : | change_status(id,CF_STOP) | ||
428 : | sfexec(id,4) //Execute commands from start/finish config | ||
429 : | } | ||
430 : | return PLUGIN_HANDLED | ||
431 : | } | ||
432 : | public reset(id){ | ||
433 : | if(get_pcvar_num(p_climb)&&check_timeout(id,get_systime(),time_stamps[id][TS_SPAWN],5)){ | ||
434 : | stop(id) | ||
435 : | frespawn(id) | ||
436 : | } | ||
437 : | return PLUGIN_HANDLED | ||
438 : | } | ||
439 : | public frespawn(id){ | ||
440 : | if(get_pcvar_num(p_climb)&&check_timeout(id,get_systime(),time_stamps[id][TS_SPAWN],5)){ | ||
441 : | if(get_user_team(id)==3)cs_set_user_team(id,2) | ||
442 : | timer[id][TMR_CFLAGS]+=CF_SPAWN_NO_GC | ||
443 : | cs_user_spawn(id) | ||
444 : | } | ||
445 : | return PLUGIN_HANDLED | ||
446 : | } | ||
447 : | public respawn(ida[]){ | ||
448 : | new id=ida[0] | ||
449 : | if(!get_user_team(id)||is_user_alive(id)||!isct(id)) | ||
450 : | return PLUGIN_HANDLED | ||
451 : | cs_user_spawn(id) | ||
452 : | //gocheck(id) | ||
453 : | return PLUGIN_HANDLED | ||
454 : | } | ||
455 : | public spawned(id){ | ||
456 : | if(get_pcvar_num(p_climb)){ | ||
457 : | //Block Buying | ||
458 : | new cflags=timer[id][TMR_CFLAGS] | ||
459 : | set_msg_block(get_user_msgid("StatusIcon"),2) | ||
460 : | if(is_user_alive(id)){ | ||
461 : | //Set them to CT if they're a spectator | ||
462 : | if(get_user_team(id)==3)cs_set_user_team(id,2) | ||
463 : | sortcssb() | ||
464 : | //If they are paused freeze them again. | ||
465 : | if(cflags&CF_PAUSE)cl_pause(id) | ||
466 : | set_user_health(id,hp) | ||
467 : | //Only admins can shoot other clients. | ||
468 : | //if(!(get_user_flags(id)&ADMIN_SLAY))set_user_hitzones(id,0,0) //Keeps players from seeing eachothers names. | ||
469 : | //Remove stuff dropped on death | ||
470 : | remove_entity_name("weaponbox") | ||
471 : | remove_entity_name("item_thighpack") | ||
472 : | //Execute commands from start/finish config | ||
473 : | sfexec(id,1) | ||
474 : | //Show admin as VIP on Scoreboard. | ||
475 : | if(get_user_flags(id)&ADMIN_SLAY)cs_set_user_scoreattrib(id,4) | ||
476 : | //Equip Task | ||
477 : | new ida[1] | ||
478 : | ida[0]=id | ||
479 : | set_task(0.1,"equip",_,ida,1) | ||
480 : | time_stamps[id][TS_SPAWN]=get_systime() | ||
481 : | //Teleport to safe place/old primary spawn position | ||
482 : | if(cflags&CF_SPAWN_NO_GC){ | ||
483 : | if(vector_distance(spawn_tp_orig,Float:{0,0,0}))teleport(id,spawn_tp_orig) | ||
484 : | timer[id][TMR_CFLAGS]-=CF_SPAWN_NO_GC | ||
485 : | } | ||
486 : | else if(!gocheck(id))if(!(cflags&CF_START&&!getusertime(id)))if(vector_distance(spawn_tp_orig,Float:{0,0,0}))teleport(id,spawn_tp_orig) | ||
487 : | } | ||
488 : | } | ||
489 : | else set_msg_block(get_user_msgid("StatusIcon"),0) | ||
490 : | return PLUGIN_CONTINUE | ||
491 : | } | ||
492 : | public equip(ida[]){ //Give equipment to client, delayed to prevent crash | ||
493 : | new id=ida[0] | ||
494 : | for(new i=0;i<2;i++)give_item(id,"weapon_scout") | ||
495 : | give_item(id,"weapon_c4") | ||
496 : | cs_set_user_nvg(id) | ||
497 : | } | ||
498 : | public check_timeout(id,time1,time2,freq){ | ||
499 : | if(time1<time2)return 1 | ||
500 : | new dif=time1-time2 | ||
501 : | if(dif<freq){ | ||
502 : | new msg[76] | ||
503 : | format(msg,75,"You must wait %d more seconds to use this command again.",freq-dif) | ||
504 : | if(id>0)clmsg(id,msg) | ||
505 : | return 0 | ||
506 : | } | ||
507 : | return 1 | ||
508 : | } | ||
509 : | public change_boost(id,newboost){ //Change Boost flags | ||
510 : | if(!(cvar_enabled(id,p_boost)&&isalive(id))&¬paused(id))return PLUGIN_HANDLED | ||
511 : | new msg[151],rmflag,cflags=timer[id][TMR_CFLAGS] | ||
512 : | if(cflags&CF_SOLID){ | ||
513 : | if(task_exists(150+id))remove_task(150+id) | ||
514 : | rmflag=CF_SOLID | ||
515 : | msg="Solid Boost Disabled.^n" | ||
516 : | } | ||
517 : | else if(cflags&CF_SUPER_JUMP){ | ||
518 : | rmflag=CF_SUPER_JUMP | ||
519 : | msg="Super Jump Disabled.^n" | ||
520 : | } | ||
521 : | else if(cflags&CF_DOUBLE_JUMP){ | ||
522 : | rmflag=CF_DOUBLE_JUMP | ||
523 : | msg="Double Jump Disabled.^n" | ||
524 : | } | ||
525 : | if(rmflag>0)timer[id][TMR_CFLAGS]-=rmflag | ||
526 : | if(!(rmflag&newboost)&&check_timeout(id,(cflags&CF_START?getusertime(id):get_systime()),time_stamps[id][TS_BOOST],5)){ | ||
527 : | if(newboost==CF_SOLID){ | ||
528 : | format(msg,150,"%sSolid Boost Enabled.",msg) | ||
529 : | new ida[1] | ||
530 : | ida[0]=id | ||
531 : | set_task(15.0,"solid_boost_timer",150+id,ida,1) | ||
532 : | if(timer[id][TMR_CFLAGS]&CF_START)timer[id][TMR_BOOSTS]++ | ||
533 : | } | ||
534 : | if(newboost==CF_SUPER_JUMP)format(msg,150,"%sSuper Jump Enabled.",msg) | ||
535 : | if(newboost==CF_DOUBLE_JUMP)format(msg,150,"%sDouble Jump Enabled.",msg) | ||
536 : | timer[id][TMR_CFLAGS]+=newboost | ||
537 : | } | ||
538 : | if(strlen(msg))clmsg(id,msg) | ||
539 : | return PLUGIN_HANDLED | ||
540 : | } | ||
541 : | public solid_boost_timer(ida[]){ //Task to auto disable solid boost after timeout | ||
542 : | //if(timer[id][TMR_CFLAGS]&CF_SOLID)solid_boost(id) //Shouldn't need the if statement | ||
543 : | change_boost(ida[0],CF_SOLID) | ||
544 : | return PLUGIN_HANDLED | ||
545 : | } | ||
546 : | //Semi-clip, and entity touch detection for non-solid clients | ||
547 : | //* Maybe move this to client prethink | ||
548 : | public server_frame(){ | ||
549 : | if(get_pcvar_num(p_climb)){ | ||
550 : | new players[32],num,i,j,Float:c1[3],Float:c2[3] | ||
551 : | new Float:c1z[3],Float:c2z[3] | ||
552 : | new id_i,id_j,cflags_i,cflags_j | ||
553 : | get_players(players,num,"ac") | ||
554 : | if(trignum){ | ||
555 : | for(i=0;i<num;i++){ | ||
556 : | id_i=players[i] | ||
557 : | if(!playersolid(id_i)){ | ||
558 : | for(j=0;j<trignum;j++){ | ||
559 : | id_j=trig[j] | ||
560 : | entity_get_vector(id_j,EV_VEC_absmin,c2) | ||
561 : | entity_get_vector(id_j,EV_VEC_absmax,c2z) | ||
562 : | entity_get_vector(id_i,EV_VEC_origin,c1) | ||
563 : | if(c2[0]<=c1[0]&&c2z[0]>=c1[0]&&c2[1]<=c1[1]&&c2z[1]>=c1[1]&&c2[2]<=c1[2]&&c2z[2]>=c1[2]){ | ||
564 : | fake_touch(id_j,id_i) | ||
565 : | j=trignum | ||
566 : | } | ||
567 : | } | ||
568 : | } | ||
569 : | } | ||
570 : | } | ||
571 : | if(brknum){ | ||
572 : | for(i=0;i<num;i++){ | ||
573 : | id_i=players[i] | ||
574 : | if(!playersolid(id_i)){ | ||
575 : | for(j=0;j<brknum;j++){ | ||
576 : | id_j=brk[j] | ||
577 : | entity_get_vector(id_j,EV_VEC_absmin,c2) | ||
578 : | entity_get_vector(id_j,EV_VEC_absmax,c2z) | ||
579 : | entity_get_vector(id_i,EV_VEC_origin,c1) | ||
580 : | c1[0]-=26 | ||
581 : | c1z[0]=c1[0]+32 | ||
582 : | c1[1]-=16 | ||
583 : | c1z[1]=c1[1]+32 | ||
584 : | c1[2]-=40 | ||
585 : | c1z[2]=c1[2]+50 | ||
586 : | if(((c2[0]<c1[0]<c2z[0])||(c2[0]<c1z[0]<c2z[0])||(c1[0]<c2[0]<c1z[0])||(c1[0]<c2z[0]<c1z[0])) | ||
587 : | &&((c2[1]<c1[1]<c2z[1])||(c2[1]<c1z[1]<c2z[1])||(c1[1]<c2[1]<c1z[1])||(c1[1]<c2z[1]<c1z[1])) | ||
588 : | &&((c2[2]<c1[2]<c2z[2])||(c2[2]<c1z[2]<c2z[2])||(c1[2]<c2[2]<c1z[2])||(c1[2]<c2z[2]<c1z[2])) | ||
589 : | ){ | ||
590 : | fake_touch(id_j,id_i) | ||
591 : | j=brknum | ||
592 : | } | ||
593 : | } | ||
594 : | } | ||
595 : | } | ||
596 : | } | ||
597 : | c1z[0]=0.0 | ||
598 : | c1z[1]=0.0 | ||
599 : | c2z[0]=0.0 | ||
600 : | c2z[1]=0.0 | ||
601 : | //new Float:c1d[3],Float:c2d[3],xyadd,zadd | ||
602 : | for(i=0;i<num;i++){ | ||
603 : | id_i=players[i] | ||
604 : | cflags_i=timer[id_i][TMR_CFLAGS] | ||
605 : | if(!(cflags_i&CF_PAUSE)){ | ||
606 : | //solid(players[i]) | ||
607 : | entity_get_vector(id_i,EV_VEC_origin,c1) | ||
608 : | //entity_get_vector(players[i],EV_VEC_velocity,c1d) | ||
609 : | c1z[2]=c1[2] | ||
610 : | c1[2]=0.0 | ||
611 : | for(j=0;j<num;j++){ | ||
612 : | id_j=players[j] | ||
613 : | cflags_j=timer[id_j][TMR_CFLAGS] | ||
614 : | if(!(cflags_j&CF_SOLID)&&i!=j){ | ||
615 : | entity_get_vector(id_j,EV_VEC_origin,c2) | ||
616 : | //entity_get_vector(players[j],EV_VEC_velocity,c2d) | ||
617 : | c2z[2]=c2[2] | ||
618 : | c2[2]=0.0 | ||
619 : | if(vector_distance(c1,c2)<90&&vector_distance(c1z,c2z)<110){ | ||
620 : | if(!(cflags_i&CF_SOLID&&cflags_j&CF_SOLID)){//&&vector_distance(c1,c2)>25&&vector_distance(c1z,c2z)>30)){ | ||
621 : | unsolid(id_i) | ||
622 : | unsolid(id_j) | ||
623 : | j=num | ||
624 : | } | ||
625 : | } | ||
626 : | } | ||
627 : | if(j+1==num)solid(id_i) | ||
628 : | } | ||
629 : | } | ||
630 : | } | ||
631 : | } | ||
632 : | return PLUGIN_CONTINUE | ||
633 : | } | ||
634 : | public client_PreThink(id){ | ||
635 : | if(!(get_pcvar_num(p_climb)&&get_pcvar_num(p_boost)&&isalive(id)))return PLUGIN_CONTINUE | ||
636 : | new cflags=timer[id][TMR_CFLAGS],bool:onground=false | ||
637 : | if(get_entity_flags(id)&FL_ONGROUND)onground=true | ||
638 : | if(get_user_button(id)&IN_JUMP){ | ||
639 : | if(cflags&CF_SUPER_JUMP&&onground){ | ||
640 : | entity_get_vector(id,EV_VEC_velocity,post_think_vel[id]) | ||
641 : | if(post_think_vel[id][0]!=0.0||post_think_vel[id][1]!=0.0){ | ||
642 : | velocity_by_aim(id,600,post_think_vel[id]) | ||
643 : | if(post_think_vel[id][2]<250.0)post_think_vel[id][2]=250.0 | ||
644 : | if(post_think_vel[id][2]>350.0)post_think_vel[id][2]=350.0 | ||
645 : | } | ||
646 : | else post_think_vel[id]=Float:{0.0,0.0,0.0} | ||
647 : | } | ||
648 : | else if(cflags&CF_DOUBLE_JUMP){ | ||
649 : | if(!onground&&!(get_user_oldbutton(id)&IN_JUMP)){ | ||
650 : | entity_get_vector(id,EV_VEC_velocity,post_think_vel[id]) | ||
651 : | if(is_finished(id)||post_think_vel[id][2]>-500)post_think_vel[id][2]=250.0 | ||
652 : | else post_think_vel[id]=Float:{0.0,0.0,0.0} | ||
653 : | } | ||
654 : | } | ||
655 : | } | ||
656 : | return PLUGIN_CONTINUE | ||
657 : | } | ||
658 : | public client_PostThink(id){ | ||
659 : | if(!(get_pcvar_num(p_climb)&&get_pcvar_num(p_boost)&&isalive(id)))return PLUGIN_CONTINUE | ||
660 : | if(_:get_distance(_:post_think_vel[id],{0,0,0})){ | ||
661 : | entity_set_vector(id,EV_VEC_velocity,post_think_vel[id]) | ||
662 : | post_think_vel[id]=Float:{0.0,0.0,0.0} | ||
663 : | if(timer[id][TMR_CFLAGS]&CF_START){ | ||
664 : | timer[id][TMR_BOOSTS]++ //Increment client boost count | ||
665 : | time_stamps[id][TS_BOOST]=getusertime(id) //Timeout based on timer so they can't pause to avoid timeout | ||
666 : | change_boost(id,CF_NULL) | ||
667 : | } | ||
668 : | else if(!is_finished(id)){ | ||
669 : | time_stamps[id][TS_BOOST]=get_systime() | ||
670 : | change_boost(id,CF_NULL) | ||
671 : | } | ||
672 : | } | ||
673 : | return PLUGIN_CONTINUE | ||
674 : | } | ||
675 : | public is_finished(id){ | ||
676 : | new cflags=timer[id][TMR_CFLAGS] | ||
677 : | if(cflags&CF_STOP&&(get_user_flags(id)&ADMIN_RESERVATION||timer[id][TMR_SESFIN]>0)) | ||
678 : | return 1 | ||
679 : | return 0 | ||
680 : | } | ||
681 : | public traceline(Float:v1[3], Float:v2[3], noMonsters, entity){ | ||
682 : | if(get_pcvar_num(p_climb)){ | ||
683 : | new id=entity | ||
684 : | new entity2=get_tr(TR_pHit) | ||
685 : | if(id>0&&entity2>0){ | ||
686 : | if(is_user_alive(id)){ | ||
687 : | new class[32] | ||
688 : | entity_get_string(entity2,EV_SZ_classname,class,32) | ||
689 : | new Float:orig1[3],Float:orig2[3] | ||
690 : | entity_get_vector(id,EV_VEC_origin,orig1) | ||
691 : | get_brush_entity_origin(entity2,orig2) | ||
692 : | //if(get_user_button(id)&IN_USE&&get_user_aiming(id,a,b)<70&&equal(class,"func_button")){ | ||
693 : | if(get_user_button(id)&IN_USE&&vector_distance(orig1,orig2)<95&&equal(class,"func_button")){ | ||
694 : | new targ[32] | ||
695 : | entity_get_string(entity2,EV_SZ_target,targ,32) | ||
696 : | //Timer Start | ||
697 : | //if((!(timer[id][TMR_CFLAGS]&CF_START)||getusertime(id)>4)&&/*(timer[id][TMR_CFLAGS]&CF_STOP||timer[id][TMR_CFLAGS]==TMR_CFLAGS_FNSH)&&(*/equal(targ,"counter_start")||equal(targ,"clockstartbutton")||equal(targ,"firsttimerelay")/*)*/){ | ||
698 : | if((!(timer[id][TMR_CFLAGS]&CF_START)||check_timeout(id,get_systime(),time_stamps[id][TS_SPAWN],5))&&(equal(targ,"counter_start")||equal(targ,"clockstartbutton")||equal(targ,"firsttimerelay"))){ | ||
699 : | new Float:orig[3],Float:view[3] | ||
700 : | //Erase checkpoints | ||
701 : | for(new i=0;i<8;i++)origins[id][i]=0.0 | ||
702 : | //Set all associated variables | ||
703 : | timer[id][TMR_STARTD]=get_systime() | ||
704 : | change_status(id,CF_START) | ||
705 : | timer[id][TMR_CPSCNT]=0 | ||
706 : | timer[id][TMR_GCSCNT]=0 | ||
707 : | timer[id][TMR_BOOSTS]=0 | ||
708 : | //Respawn client to clear items. | ||
709 : | entity_get_vector(id,EV_VEC_origin,orig) | ||
710 : | entity_get_vector(id,EV_VEC_angles,view) | ||
711 : | cs_user_spawn(id) | ||
712 : | entity_set_vector(id,EV_VEC_origin,orig) | ||
713 : | entity_set_vector(id,EV_VEC_angles,view) | ||
714 : | delay_duck(id) | ||
715 : | cs_set_user_money(id,get_pcvar_num(p_startmoney)) | ||
716 : | //Play random start sound and text messages | ||
717 : | if(get_pcvar_num(p_sounds))switch(random_num(0,2)){ | ||
718 : | case 0:client_cmd(id,"spk barney/beertopside") | ||
719 : | case 1:client_cmd(id,"spk scientist/c3a2_sci_portopen") | ||
720 : | case 2:client_cmd(id,"spk barney/c1a2_ba_climb") | ||
721 : | } | ||
722 : | //Disable Boosts | ||
723 : | change_boost(id,CF_NULL) | ||
724 : | time_stamps[id][TS_BOOST]=0 | ||
725 : | clmsg(id,"Timer started. Go Go Go!!!") | ||
726 : | client_print(id,print_chat,"Timer started. Go Go Go!!!") | ||
727 : | //Update frags to reorder scoreboard | ||
728 : | sortcssb() | ||
729 : | //If stats save enabled warn unregistered clients to register | ||
730 : | if(climb_save)regwarn(id) | ||
731 : | //Execute commands from start/finish config | ||
732 : | sfexec(id,2) | ||
733 : | time_stamps[id][TS_SPAWN]=get_systime() | ||
734 : | } | ||
735 : | //Timer Stop | ||
736 : | else if(equal(targ,"counter_off")||equal(targ,"clockstopbutton")||equal(targ,"clockstop")){ | ||
737 : | if(timer[id][TMR_CFLAGS]&CF_START){ | ||
738 : | //Set client variables | ||
739 : | timer[id][TMR_FINISH]=get_systime() | ||
740 : | change_status(id,CF_STOP) | ||
741 : | timer[id][TMR_SESFIN]++ | ||
742 : | timer[id][TMR_MAPFIN]++ | ||
743 : | //Update frags to reorder scoreboard | ||
744 : | sortcssb() | ||
745 : | //Announce to client | ||
746 : | if(get_pcvar_num(p_sounds))client_cmd(0,"spk woop") | ||
747 : | clmsg(id,"Congratulations 1337 climber.") | ||
748 : | client_print(id,print_chat,"Congratulations 1337 climber.") | ||
749 : | new name[32],msg[21] | ||
750 : | formatex(msg,sizeof(msg)-1,"%s^t%s",getuserstatus(id),parsetime(getusertime(id))) | ||
751 : | //clmsg(id,msg) | ||
752 : | //client_print(id,print_chat,msg) | ||
753 : | //Announce to all | ||
754 : | get_user_name(id,name,32) | ||
755 : | client_print(0,print_chat,"%s^t%s^t(%d CPS/ %d GCS/ %d Boosts)^tCompleted (%d, %d)",name,msg,timer[id][TMR_CPSCNT],timer[id][TMR_GCSCNT],timer[id][TMR_BOOSTS],timer[id][TMR_SESFIN],timer[id][TMR_MAPFIN]) | ||
756 : | //If new record | ||
757 : | if(getusertime(id)<timer[id][TMR_BSTTME]||timer[id][TMR_BSTTME]==0){ | ||
758 : | timer[id][TMR_BSTTME]=getusertime(id) | ||
759 : | timer[id][TMR_BSTCPS]=timer[id][TMR_CPSCNT] | ||
760 : | timer[id][TMR_BSTGCS]=timer[id][TMR_GCSCNT] | ||
761 : | } | ||
762 : | //Execute commands from start/finish config | ||
763 : | sfexec(id,2) | ||
764 : | //If stats enabled, warn unregistered clients to register, or save for registered clients | ||
765 : | if(climb_save) | ||
766 : | if(!regwarn(id)) | ||
767 : | db_save(id) | ||
768 : | } | ||
769 : | else if(timer[id][TMR_CFLAGS]&CF_STOP&&timer[id][TMR_SESFIN]==0){ | ||
770 : | //change_status(id,CF_FINISH) | ||
771 : | timer[id][TMR_SESFIN]++ | ||
772 : | new msg[100]="Congratulations, you finished! But you didn't start the timer. :(" | ||
773 : | clmsg(id,msg) | ||
774 : | client_print(id,print_chat,msg) | ||
775 : | //Execute commands from start/finish config | ||
776 : | sfexec(id,2) | ||
777 : | //If stats save enabled warn unregistered clients to register | ||
778 : | if(climb_save)regwarn(id) | ||
779 : | } | ||
780 : | } | ||
781 : | } | ||
782 : | } | ||
783 : | } | ||
784 : | } | ||
785 : | return PLUGIN_CONTINUE | ||
786 : | } | ||
787 : | //Execute commands from start/finish config | ||
788 : | public sfexec(id,clevent){ | ||
789 : | new clstat[3],cflags=timer[id][TMR_CFLAGS] | ||
790 : | /*switch(timer[id][TMR_CFLAGS]){ | ||
791 : | case TMR_CFLAGS_STOP: clstat="ns" | ||
792 : | case TMR_CFLAGS_STRT: clstat="st" | ||
793 : | case TMR_CFLAGS_FNSH: clstat="fn" | ||
794 : | }*/ | ||
795 : | if(is_finished(id))clstat="fn" | ||
796 : | else if(cflags&CF_STOP)clstat="ns" | ||
797 : | else if(cflags&CF_START)clstat="st" | ||
798 : | //else if(timer[id][TMR_CFLAGS]&CF_FINISH)clstat="fn" | ||
799 : | //if(equal(clstat,"ns")&&(get_user_flags(id)&ADMIN_RESERVATION||timer[id][TMR_SESFIN]>0))clstat="fn" | ||
800 : | |||
801 : | for(new i=0;i<sfcount;i++){ | ||
802 : | new cmdstat[3],cmdevent[2],cmdtype[3],cmd[60],idtype[5] | ||
803 : | parse(sfactions[i],cmdstat,2,cmdevent,1,cmdtype,2,cmd,sizeof(cmd)-1,idtype,4) | ||
804 : | if((equali(cmdstat,clstat)||equali(cmdstat,"ay"))&&str_to_num(cmdevent)&clevent){ | ||
805 : | if(equali(cmdtype,"sc")){ | ||
806 : | if(equali(idtype,"uid"))format(cmd,sizeof(cmd)-1,cmd,get_user_userid(id)) | ||
807 : | else{ | ||
808 : | new name[24] | ||
809 : | get_user_name(id,name,sizeof(name)-1) | ||
810 : | format(name,sizeof(name),"^"%s^"",name) | ||
811 : | format(cmd,sizeof(cmd)-1,cmd,name) | ||
812 : | client_print(id,print_chat,cmd) | ||
813 : | } | ||
814 : | server_cmd(cmd) | ||
815 : | } | ||
816 : | else{ | ||
817 : | client_cmd(id,cmd) | ||
818 : | } | ||
819 : | } | ||
820 : | } | ||
821 : | return 1 | ||
822 : | } | ||
823 : | //Pad text for console score listing | ||
824 : | public pad(pad){ | ||
825 : | new j=4,str[50]="" | ||
826 : | for(new i=strlen(str);i<pad;i++){ | ||
827 : | if(j==5){ | ||
828 : | copy(str[i],1,"^t") | ||
829 : | j=0 | ||
830 : | } | ||
831 : | else copy(str[i],1," ") | ||
832 : | j++ | ||
833 : | } | ||
834 : | return str | ||
835 : | } | ||
836 : | //Update frags to reorder scoreboard | ||
837 : | public sortcssb(){ | ||
838 : | new players[32],num | ||
839 : | get_players_ordered(players,num) | ||
840 : | for(new i=0;i<num;i++){ | ||
841 : | set_user_frags(players[i],0) | ||
842 : | cs_set_user_deaths(players[i],i+1) | ||
843 : | } | ||
844 : | return 1 | ||
845 : | } | ||
846 : | //Returns array of client id's sorted by climb time | ||
847 : | public get_players_ordered(players[32],&num){ | ||
848 : | get_players(players,num,"c") | ||
849 : | //Insertion Sort clients by finished time | ||
850 : | for(new i=1;i<num;i++){ | ||
851 : | new j=i,tmp | ||
852 : | if(timer[players[i]][TMR_BSTTME]>0){ | ||
853 : | tmp=players[i] | ||
854 : | while(j>0&&(timer[players[j-1]][TMR_BSTTME]==0?18000:timer[players[j-1]][TMR_BSTTME])>timer[tmp][TMR_BSTTME]){ | ||
855 : | players[j]=players[j-1] | ||
856 : | j-- | ||
857 : | } | ||
858 : | players[j]=tmp | ||
859 : | } | ||
860 : | } | ||
861 : | //2nd Insertion Sort clients by climbing time | ||
862 : | for(new i=1;i<num;i++){ | ||
863 : | new j=i,tmp | ||
864 : | if(getusertime(players[i])>0){ | ||
865 : | tmp=players[i] | ||
866 : | while(j>0&&(getusertime(players[j-1])==0?18000:getusertime(players[j-1]))>getusertime(tmp)&&timer[players[j-1]][TMR_BSTTME]==timer[tmp][TMR_BSTTME]){ | ||
867 : | players[j]=players[j-1] | ||
868 : | j-- | ||
869 : | } | ||
870 : | players[j]=tmp | ||
871 : | } | ||
872 : | } | ||
873 : | return 1 | ||
874 : | } | ||
875 : | //Make pathname for scoreboard html files | ||
876 : | public pathname(filename[]){ | ||
877 : | new path[100] | ||
878 : | get_pcvar_string(p_stats_path,path,79) | ||
879 : | format(path,99,"%s%s",path,filename) | ||
880 : | return path | ||
881 : | } | ||
882 : | public get_limit(){ | ||
883 : | if(get_pcvar_num(p_webmod)) | ||
884 : | return 0 | ||
885 : | new url[100] | ||
886 : | get_pcvar_string(p_stats_url,url,99) | ||
887 : | if(strlen(url)) | ||
888 : | return 0 | ||
889 : | return 1 | ||
890 : | } | ||
891 : | public get_url(id,file[]){ | ||
892 : | new url[100] | ||
893 : | get_pcvar_string(p_stats_url,url,99) | ||
894 : | if(get_pcvar_num(p_webmod)){ | ||
895 : | new ip[10],iip[33],eip[33],port[10] | ||
896 : | get_user_ip(id,ip,9) | ||
897 : | get_pcvar_string(p_ip_internal,iip,32) | ||
898 : | get_pcvar_string(p_ip_external,eip,32) | ||
899 : | get_pcvar_string(p_port,port,9) | ||
900 : | if(equal(ip,"192.168.",8))format(url,99,"http://%s:%s/%s",iip,port,file) | ||
901 : | else format(url,99,"http://%s:%s/%s",eip,port,file) | ||
902 : | } | ||
903 : | else if(strlen(url)){ | ||
904 : | format(url,99,"%sclimb_scores.html",url) | ||
905 : | } | ||
906 : | return url | ||
907 : | } | ||
908 : | //Show scoreboard | ||
909 : | public climbscores(id){ | ||
910 : | if(get_pcvar_num(p_climb)){ | ||
911 : | new fpn[100],bool:limit=true,cust_msg[129] | ||
912 : | get_pcvar_string(p_stats_msg,cust_msg,128) | ||
913 : | if(!get_limit())limit=false | ||
914 : | fpn=pathname("climb_scores.html") | ||
915 : | if(get_systime()-score_ts>2){ | ||
916 : | new fh=fopen(fpn,"w") | ||
917 : | fprintf(fh,"<html><head>%s<link rel=stylesheet href=http://ian.cammarata.us/climb/sb.css></head><body><table><tr>",limit?"":"<meta http-equiv=pragma content=no-cache>") | ||
918 : | fprintf(fh,"<th height=1%%>Reg</th><th>#</th><th width=28%%>Name</th><th width=15%%>Status</th><th width=8%%>Time</th><th width=6%%>CP#</th><th width=6%%>GC#</th>") | ||
919 : | fprintf(fh,"<th width=8%%>Best</th><th width=6%%>CP#</th><th width=6%%>GC#</th><th width=10%%>Completed</th></tr><tr><td class=st colspan=11></td></tr>") | ||
920 : | //99+144+134=377 | ||
921 : | new line[251],name[33],players[32],num,tid,writen_len | ||
922 : | get_players_ordered(players,num) | ||
923 : | for(new i=1;i<=num;i++){ | ||
924 : | tid=players[i-1] | ||
925 : | if(!is_user_hltv(tid)&&is_user_connected(tid)){ | ||
926 : | get_user_name(tid,name,32) | ||
927 : | htmlspecialchars(name) | ||
928 : | formatex(line,250,"<tr%s><td height=1%>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%d</td><td>%s</td><td>%d</td><td>%d</td><td>%d</td></tr>",i%2?"":" class='o'",timer[tid][TMR_DBUSER]>0?"y":"n",i,name,getuserstatus(tid),parsetime(getusertime(tid)),timer[tid][TMR_CPSCNT],timer[tid][TMR_GCSCNT],parsetime(timer[tid][TMR_BSTTME]),timer[tid][TMR_BSTGCS],timer[tid][TMR_BSTCPS],timer[tid][TMR_MAPFIN]) | ||
929 : | writen_len+=strlen(line) | ||
930 : | if(limit&&writen_len>(1003-strlen(cust_msg)))break | ||
931 : | fprintf(fh,line) | ||
932 : | } | ||
933 : | } | ||
934 : | //1530-150-377=1003 | ||
935 : | fprintf(fh,"<tr><td></td></tr><tr><td class=sb colspan=11></td></tr><tr><th colspan=4 height=1%>") | ||
936 : | fprintf(fh,"climb v%s by: Ian Cammarata</th><th colspan=7>%s</th></tr></table></body></html>",VERSION,cust_msg) | ||
937 : | fclose(fh) | ||
938 : | score_ts=get_systime() | ||
939 : | } | ||
940 : | |||
941 : | if(!limit)fpn=get_url(id,"climb_scores.html") | ||
942 : | show_motd(id,fpn,"Current Scores") | ||
943 : | } | ||
944 : | return PLUGIN_HANDLED | ||
945 : | } | ||
946 : | //Show High Scores | ||
947 : | public highscores(id){ | ||
948 : | new hsurl[150],mapname[33] | ||
949 : | get_pcvar_string(p_stats_hsurl,hsurl,149) | ||
950 : | get_mapname(mapname,32) | ||
951 : | if(strlen(hsurl)){ | ||
952 : | formatex(hsurl,149,hsurl,mapname) | ||
953 : | show_motd(id,hsurl,"High Scores") | ||
954 : | return PLUGIN_HANDLED | ||
955 : | } | ||
956 : | if(get_systime()-hscore_ts>10){ | ||
957 : | new query[250],data[1] | ||
958 : | data[0]=id | ||
959 : | formatex(query,249,"select p.alias, s.fin_time, s.cps, s.gcs, s.fin_cnt from %sscores s, %splayers p where s.map_name='%s' and p.user_id=s.user_id order by s.fin_time, s.gcs, s.cps limit 20;",db_prefix,db_prefix,mapname) | ||
960 : | SQL_ThreadQuery(db_tuple,"hs_handler",query,data,1) | ||
961 : | hscore_ts=get_systime() | ||
962 : | } | ||
963 : | else{ | ||
964 : | new fpn[100],bool:limit=true | ||
965 : | if(!get_limit())limit=false | ||
966 : | fpn=pathname("climb_highscores.html") | ||
967 : | if(!limit)fpn=get_url(id,"climb_highscores.html") | ||
968 : | show_motd(id,fpn,"High Scores") | ||
969 : | } | ||
970 : | |||
971 : | return PLUGIN_HANDLED | ||
972 : | } | ||
973 : | public hs_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime){ | ||
974 : | if(failstate == TQUERY_CONNECT_FAILED) | ||
975 : | return server_print("Climb: Couldn't connect to database.") | ||
976 : | else if(failstate == TQUERY_QUERY_FAILED) | ||
977 : | return server_print("Climb: Query failed: %s",error) | ||
978 : | |||
979 : | if(errnum) | ||
980 : | return server_print("Climb: Query Error: %s",error) | ||
981 : | |||
982 : | new id=data[0],msg[50],num=SQL_NumResults(query) | ||
983 : | if(!num){ | ||
984 : | msg="^x04[Climb] No stats available for the current map." | ||
985 : | return saytext(id,id,msg) | ||
986 : | } | ||
987 : | |||
988 : | new fpn[100],bool:limit=true,cust_msg[129] | ||
989 : | get_pcvar_string(p_stats_msg,cust_msg,128) | ||
990 : | if(!get_limit())limit=false | ||
991 : | fpn=pathname("climb_highscores.html") | ||
992 : | new fh=fopen(fpn,"w") | ||
993 : | fprintf(fh,"<html><head>%s<link rel=stylesheet href=http://ian.cammarata.us/climb/sb.css></head><body><table><tr>",limit?"":"<meta http-equiv=pragma content=no-cache>") | ||
994 : | fprintf(fh,"<th height=1%%>#</th><th width=45%%>Name</th><th width=20%%>Time</th><th width=10%%>CP#</th>") | ||
995 : | fprintf(fh,"<th width=10%%>GC#</th><th width=10%%>Completed</th></tr><tr><td class=st colspan=6></td></tr>") | ||
996 : | //99+88+92=279 | ||
997 : | new name[33],line[151],writen_len | ||
998 : | for(new i=1;i<=num;i++){ | ||
999 : | SQL_ReadResult(query,0,name,32) | ||
1000 : | htmlspecialchars(name) | ||
1001 : | formatex(line,150,"<tr%s><td height=1%>%d</td><td>%s</td><td>%s</td><td>%d</td><td>%d</td><td>%d</td></tr>",i%2?"":" class='o'",i,name,parsetime(SQL_ReadResult(query,1)),SQL_ReadResult(query,2),SQL_ReadResult(query,3),SQL_ReadResult(query,4)) | ||
1002 : | writen_len+=strlen(line) | ||
1003 : | if(limit&&writen_len>(1101-strlen(cust_msg)))break | ||
1004 : | fprintf(fh,line) | ||
1005 : | SQL_NextRow(query) | ||
1006 : | } | ||
1007 : | //1530-150-279=1101 | ||
1008 : | fprintf(fh,"<tr><td></td></tr><tr><td class=sb colspan=6></td></tr><tr><th colspan=2 height=1%>") | ||
1009 : | fprintf(fh,"climb v %s by: Ian Cammarata</th><th colspan=4>%s</th></tr></table></body></html>",VERSION,cust_msg) | ||
1010 : | fclose(fh) | ||
1011 : | |||
1012 : | if(!limit)fpn=get_url(id,"climb_highscores.html") | ||
1013 : | show_motd(id,fpn,"High Scores") | ||
1014 : | |||
1015 : | return PLUGIN_HANDLED | ||
1016 : | } | ||
1017 : | //Convert seconds to time string with zero padded seconds field | ||
1018 : | public parsetime(sec){ | ||
1019 : | new timestr[9],mins | ||
1020 : | mins=sec/60 | ||
1021 : | sec=sec%60 | ||
1022 : | formatex(timestr,8,"%d:%s%d",mins,sec<10?"0":"",sec) | ||
1023 : | return timestr | ||
1024 : | } | ||
1025 : | //Calculate client climb time in seconds | ||
1026 : | public getusertime(id){ | ||
1027 : | new ptime,cflags=timer[id][TMR_CFLAGS] | ||
1028 : | //ptime=timer[id][TMR_FINISH]-timer[id][TMR_STARTD] | ||
1029 : | //if(cflags&CF_STOP&&timer[id][TMR_SESFIN]>0)ptime=ptime<10000?ptime:0 | ||
1030 : | if(cflags&CF_STOP&&timer[id][TMR_SESFIN]>0)ptime=timer[id][TMR_FINISH]-timer[id][TMR_STARTD] | ||
1031 : | else if(cflags&CF_STOP)ptime=0 | ||
1032 : | else if(cflags&CF_START)ptime=get_systime()-timer[id][TMR_STARTD] | ||
1033 : | else if(cflags&CF_PAUSE)ptime=timer[id][TMR_STARTD] | ||
1034 : | return ptime | ||
1035 : | } | ||
1036 : | //Set clock on HUD to current climb time | ||
1037 : | public hudtime(){ | ||
1038 : | if(get_pcvar_num(p_climb)){ | ||
1039 : | new player,players[32],num | ||
1040 : | get_players(players,num,"ac") | ||
1041 : | for(new i=0;i<num;i++){ | ||
1042 : | player=players[i] | ||
1043 : | message_begin(1,get_user_msgid("RoundTime"),{0,0,0},player) | ||
1044 : | write_short(getusertime(player)+1) | ||
1045 : | message_end() | ||
1046 : | if(timer[player][TMR_CFLAGS]&CF_PAUSE)clmsg(player,"PAUSED") | ||
1047 : | } | ||
1048 : | } | ||
1049 : | return 1 | ||
1050 : | } | ||
1051 : | //Return string describing user status | ||
1052 : | public getuserstatus(id){ | ||
1053 : | new msg[12] | ||
1054 : | if(timer[id][TMR_CFLAGS]&CF_STOP&&timer[id][TMR_SESFIN]>0)msg="Finished" | ||
1055 : | /*else switch(timer[id][TMR_CFLAGS]){ | ||
1056 : | case TMR_CFLAGS_STOP: msg="Not Started" | ||
1057 : | case TMR_CFLAGS_STRT: msg="Climbing" | ||
1058 : | case TMR_CFLAGS_PAUS: msg="Paused" | ||
1059 : | }*/ | ||
1060 : | else if(timer[id][TMR_CFLAGS]&CF_STOP)msg="Not Started" | ||
1061 : | else if(timer[id][TMR_CFLAGS]&CF_START)msg="Climbing" | ||
1062 : | else if(timer[id][TMR_CFLAGS]&CF_PAUSE)msg="Paused" | ||
1063 : | return msg | ||
1064 : | } | ||
1065 : | //Show Hud Message | ||
1066 : | public clmsg(id, msg[]){ | ||
1067 : | set_hudmessage(get_pcvar_num(p_msg_r),get_pcvar_num(p_msg_g),get_pcvar_num(p_msg_b),get_pcvar_float(p_msg_x),get_pcvar_float(p_msg_y),0,0.0,5.0,0.5,0.5,4) | ||
1068 : | show_hudmessage(id,msg) | ||
1069 : | return PLUGIN_HANDLED | ||
1070 : | } | ||
1071 : | //Make client solid | ||
1072 : | public solid(id){ | ||
1073 : | set_user_rendering(id,kRenderFxNone,0,0,0,kRenderNormal,255) | ||
1074 : | entity_set_int(id,EV_INT_solid,SOLID_BBOX) | ||
1075 : | return PLUGIN_CONTINUE | ||
1076 : | } | ||
1077 : | //Make client unsolid | ||
1078 : | public unsolid(id){ | ||
1079 : | if(get_pcvar_num(p_render))set_user_rendering(id,kRenderFxPulseSlow,0,0,0,kRenderTransTexture,50) | ||
1080 : | else set_user_rendering(id,kRenderFxHologram,0,0,0,kRenderTransAdd,0) | ||
1081 : | entity_set_int(id,EV_INT_solid,SOLID_NOT) | ||
1082 : | return PLUGIN_CONTINUE | ||
1083 : | } | ||
1084 : | //Check client solid | ||
1085 : | public playersolid(id){ | ||
1086 : | if(entity_get_int(id,EV_INT_solid)==SOLID_BBOX)return 1 | ||
1087 : | return 0 | ||
1088 : | } | ||
1089 : | //Use in IF statements to automatically print error if false | ||
1090 : | public isalive(id){ | ||
1091 : | if(is_user_alive(id))return 1 | ||
1092 : | clmsg(id,"You must be alive to execute this command.") | ||
1093 : | return 0 | ||
1094 : | } | ||
1095 : | //Use in IF statements to automatically print error if false | ||
1096 : | public notpaused(id){ | ||
1097 : | if(!(timer[id][TMR_CFLAGS]&CF_PAUSE))return 1 | ||
1098 : | clmsg(id,"You can't execute this command while paused.") | ||
1099 : | return 0 | ||
1100 : | } | ||
1101 : | //Used in IF statements a lot | ||
1102 : | public isct(id){ | ||
1103 : | if(get_user_team(id)==2)return 1 | ||
1104 : | return 0 | ||
1105 : | } | ||
1106 : | //Called when client takes damage | ||
1107 : | public damage(id){ | ||
1108 : | new ida[1] | ||
1109 : | ida[0]=id | ||
1110 : | set_task(0.1,"damage_handle",_,ida,1) | ||
1111 : | } | ||
1112 : | //Damage hander, delayed to provide HUD consistency | ||
1113 : | public damage_handle(ida[1]){ | ||
1114 : | new id=ida[0] | ||
1115 : | if(get_pcvar_num(p_climb)&&is_user_alive(id)){ | ||
1116 : | new chp=get_user_health(id) | ||
1117 : | if(chp!=hp){ | ||
1118 : | new wpn,atk=get_user_attacker(id,wpn) | ||
1119 : | //Heal hp immediately | ||
1120 : | if((atk==0||(id==atk&&wpn==0))&&!task_exists(50+id))set_user_health(id,hp) | ||
1121 : | //Heal delayed | ||
1122 : | else{ | ||
1123 : | if(task_exists(50+id))remove_task(50+id) | ||
1124 : | set_task(5.0,"heal",50+id,ida,1) | ||
1125 : | //Fix hp display at 0 | ||
1126 : | if(chp==256)set_user_health(id,257) | ||
1127 : | } | ||
1128 : | } | ||
1129 : | else if(task_exists(50+id))remove_task(50+id) | ||
1130 : | } | ||
1131 : | return PLUGIN_HANDLED | ||
1132 : | } | ||
1133 : | //Heal client to predetermined HP required by map | ||
1134 : | public heal(ida[]){ | ||
1135 : | if(is_user_alive(ida[0]))set_user_health(ida[0],hp) | ||
1136 : | return PLUGIN_HANDLED | ||
1137 : | } | ||
1138 : | public pfn_keyvalue(ent){ | ||
1139 : | static bool:first_run=true | ||
1140 : | new temp_ent | ||
1141 : | if(first_run){ | ||
1142 : | for(new i=0;i<32;i++){ | ||
1143 : | temp_ent=create_entity("info_player_start") | ||
1144 : | if(temp_ent>0){ | ||
1145 : | dyn_spawn_count++ | ||
1146 : | dyn_spawn_ids[dyn_spawn_count]=temp_ent | ||
1147 : | entity_set_int(temp_ent,EV_INT_iuser1,1) | ||
1148 : | //DispatchKeyValue(temp_ent,"origin","0 0 0") | ||
1149 : | //DispatchKeyValue(temp_ent,"angles","0 0 0") | ||
1150 : | } | ||
1151 : | } | ||
1152 : | first_run=false | ||
1153 : | } | ||
1154 : | /*static bool:got_first=false,bool:done=false,first_id,first_orig[21],first_angle[21] | ||
1155 : | new class[26],key[26],val[26] | ||
1156 : | copy_keyvalue(class,25,key,25,val,25) | ||
1157 : | |||
1158 : | if(equal(class,"info_player_start")&&is_valid_ent(ent)){ | ||
1159 : | if(!done){ | ||
1160 : | if(!got_first){ | ||
1161 : | console_print(0,"DEBUG: Got First") | ||
1162 : | first_id=ent | ||
1163 : | got_first=true | ||
1164 : | } | ||
1165 : | if(got_first&&!done&&ent==first_id){ | ||
1166 : | if(equal(key,"origin"))copy(first_orig,20,val) | ||
1167 : | else if(equal(key,"angles"))copy(first_angle,20,val) | ||
1168 : | if(strlen(first_orig)&&strlen(first_angle)){ | ||
1169 : | done=true | ||
1170 : | console_print(0,"DEBUG: orig:%s angle:%s",first_orig,first_angle) | ||
1171 : | new i,sp | ||
1172 : | for(i=0;i<31;i++){ | ||
1173 : | sp=create_entity("info_player_start") | ||
1174 : | if(ent>0){ | ||
1175 : | entity_set_int(sp,EV_INT_iuser1,1) | ||
1176 : | DispatchKeyValue(sp,"origin",first_orig) | ||
1177 : | DispatchKeyValue(sp,"angles",first_angle) | ||
1178 : | } | ||
1179 : | } | ||
1180 : | } | ||
1181 : | } | ||
1182 : | } | ||
1183 : | if(done&&entity_get_int(ent,EV_INT_iuser1)!=1)remove_entity(ent) | ||
1184 : | }*/ | ||
1185 : | return PLUGIN_CONTINUE | ||
1186 : | } | ||
1187 : | public plugin_cfg(){ | ||
1188 : | //fix timer built into map | ||
1189 : | set_cvar_num("sv_restartround",1) | ||
1190 : | set_cvar_num("sv_gravity",800) | ||
1191 : | new ent,count=0,tmpstr[32],Float:tmpflt | ||
1192 : | get_mapname(tmpstr,32) | ||
1193 : | //map specific fixes : real gravity in nasa maps instead of trigger_push brush. | ||
1194 : | if(equali(tmpstr,"kz_man_nasa")||equali(tmpstr,"kz_man_eznasa")){ | ||
1195 : | remove_entity_name("trigger_push") | ||
1196 : | set_cvar_num("sv_gravity",500) | ||
1197 : | } | ||
1198 : | //Non-Solid check: *trigger_teleport,trigger_once,trigger_gravity,trigger_push | ||
1199 : | //trigger_teleport | ||
1200 : | ent=find_ent_by_class(-1,"trigger_teleport") | ||
1201 : | while(ent>0){ | ||
1202 : | trig[trignum]=ent | ||
1203 : | trignum++ | ||
1204 : | ent=find_ent_by_class(ent,"trigger_teleport") | ||
1205 : | } | ||
1206 : | //trigger_gravity | ||
1207 : | ent=find_ent_by_class(-1,"trigger_gravity") | ||
1208 : | while(ent>0){ | ||
1209 : | trig[trignum]=ent | ||
1210 : | trignum++ | ||
1211 : | ent=find_ent_by_class(ent,"trigger_gravity") | ||
1212 : | } | ||
1213 : | //trigger_once | ||
1214 : | /* ent=find_ent_by_class(-1,"trigger_once") | ||
1215 : | while(ent>0){ | ||
1216 : | trig[trignum]=ent | ||
1217 : | trignum++ | ||
1218 : | ent=find_ent_by_class(ent,"trigger_once") | ||
1219 : | } | ||
1220 : | //trigger_push | ||
1221 : | ent=find_ent_by_class(-1,"trigger_push") | ||
1222 : | while(ent>0){ | ||
1223 : | trig[trignum]=ent | ||
1224 : | trignum++ | ||
1225 : | ent=find_ent_by_class(ent,"trigger_push") | ||
1226 : | }*/ | ||
1227 : | //server_print("***** %d trigger entities found *****",trignum) | ||
1228 : | //Remove neg dmg: *trigger_hurt,*func_door | ||
1229 : | //func_door neg dmg removal | ||
1230 : | ent=find_ent_by_class(-1,"func_door") | ||
1231 : | while(ent>0){ | ||
1232 : | tmpflt=entity_get_float(ent,EV_FL_dmg) | ||
1233 : | if(tmpflt<0){ | ||
1234 : | count++ | ||
1235 : | hp=floatround(tmpflt) | ||
1236 : | remove_entity(ent) | ||
1237 : | ent=-1 | ||
1238 : | } | ||
1239 : | ent=find_ent_by_class(ent,"func_door") | ||
1240 : | } | ||
1241 : | server_print("***** %d neg dmg func_door entities removed *****",count) | ||
1242 : | //trigger_hurt neg dmg removal | ||
1243 : | count=0 | ||
1244 : | ent=find_ent_by_class(-1,"trigger_hurt") | ||
1245 : | while(ent>0){ | ||
1246 : | tmpflt=entity_get_float(ent,EV_FL_dmg) | ||
1247 : | if(tmpflt<0){ | ||
1248 : | count++ | ||
1249 : | hp=floatround(tmpflt) | ||
1250 : | remove_entity(ent) | ||
1251 : | ent=-1 | ||
1252 : | } | ||
1253 : | ent=find_ent_by_class(ent,"trigger_hurt") | ||
1254 : | } | ||
1255 : | server_print("***** %d neg dmg trigger_hurt entities removed *****",count) | ||
1256 : | hp=abs(hp) | ||
1257 : | hp=clamp(hp,100,511) | ||
1258 : | //Healing door trigger button removal | ||
1259 : | count=0 | ||
1260 : | ent=find_ent_by_class(-1,"func_button") | ||
1261 : | while(ent>0){ | ||
1262 : | entity_get_string(ent,EV_SZ_target,tmpstr,32) | ||
1263 : | if(containi(tmpstr,"heal")>-1||containi(tmpstr,"goddoor")>-1){ | ||
1264 : | count++ | ||
1265 : | remove_entity(ent) | ||
1266 : | ent=-1 | ||
1267 : | } | ||
1268 : | ent=find_ent_by_class(ent,"func_button") | ||
1269 : | } | ||
1270 : | server_print("***** %d healing door buttons entities removed *****",count) | ||
1271 : | //func_breakables | ||
1272 : | ent=find_ent_by_class(-1,"func_breakable") | ||
1273 : | while(ent>0){ | ||
1274 : | if(entity_get_int(ent,EV_INT_spawnflags)==2){ | ||
1275 : | brk[brknum]=ent | ||
1276 : | brknum++ | ||
1277 : | } | ||
1278 : | ent=find_ent_by_class(ent,"func_breakable") | ||
1279 : | } | ||
1280 : | server_print("***** %d func_breakable entities found *****",brknum) | ||
1281 : | //Remove unneeded entities if it's a climbing map. | ||
1282 : | count=0 | ||
1283 : | new bool:has_start_button=false,Float:sb_orig[3] | ||
1284 : | ent=find_ent_by_class(-1,"func_button") | ||
1285 : | while(ent>0){ | ||
1286 : | entity_get_string(ent,EV_SZ_target,tmpstr,32) | ||
1287 : | if(equal(tmpstr,"counter_start")||equal(tmpstr,"clockstartbutton")||equal(tmpstr,"firsttimerelay")){ | ||
1288 : | has_start_button=true | ||
1289 : | get_brush_entity_origin(ent,sb_orig) | ||
1290 : | break | ||
1291 : | } | ||
1292 : | ent=find_ent_by_class(ent,"func_button") | ||
1293 : | } | ||
1294 : | if(has_start_button){ | ||
1295 : | remove_entity_name("player_weaponstrip") | ||
1296 : | remove_entity_name("armoury_entity") | ||
1297 : | remove_entity_name("info_player_deathmatch") | ||
1298 : | get_mapname(tmpstr,32) | ||
1299 : | //Health chargers needed for some maps as climbing platforms, don't remove | ||
1300 : | //if(!(equali(tmpstr,"kz_real_skyscraper")||equali(tmpstr,"kz_northpole_b01")))remove_entities("func_healthcharger") | ||
1301 : | count++ | ||
1302 : | //Remove map built in start button sounds | ||
1303 : | ent=find_ent_by_class(-1,"ambient_generic") | ||
1304 : | while(ent>0){ | ||
1305 : | entity_get_string(ent,EV_SZ_targetname,tmpstr,32) | ||
1306 : | if(equal(tmpstr,"counter_start")||equal(tmpstr,"clockstartbutton")||equal(tmpstr,"firsttimerelay")){ | ||
1307 : | remove_entity(ent) | ||
1308 : | } | ||
1309 : | ent=find_ent_by_class(ent,"ambient_generic") | ||
1310 : | } | ||
1311 : | //Count original map spawns and remove extra dyn created spawns | ||
1312 : | new map_spawns[32][2],map_spawns_count,Float:orig[3] | ||
1313 : | ent=find_ent_by_class(-1,"info_player_start") | ||
1314 : | while(ent>0&&map_spawns_count<32){ | ||
1315 : | if(entity_get_int(ent,EV_INT_iuser1)!=1){ | ||
1316 : | entity_get_vector(ent,EV_VEC_origin,orig) | ||
1317 : | map_spawns[map_spawns_count][0]=floatround(vector_distance(orig,sb_orig)) | ||
1318 : | map_spawns[map_spawns_count][1]=ent | ||
1319 : | map_spawns_count++ | ||
1320 : | while(dyn_spawn_count>=0){ | ||
1321 : | entity_get_string(dyn_spawn_ids[dyn_spawn_count],EV_SZ_classname,tmpstr,31) | ||
1322 : | if(equal(tmpstr,"info_player_start")&&entity_get_int(dyn_spawn_ids[dyn_spawn_count],EV_INT_iuser1)==1){ | ||
1323 : | remove_entity(dyn_spawn_ids[dyn_spawn_count]) | ||
1324 : | dyn_spawn_count-- | ||
1325 : | break | ||
1326 : | } | ||
1327 : | else dyn_spawn_count-- | ||
1328 : | } | ||
1329 : | } | ||
1330 : | ent=find_ent_by_class(ent,"info_player_start") | ||
1331 : | } | ||
1332 : | //Save origin of spawn closest to start and arrange all spawn points to positions of the next 4 closest | ||
1333 : | //SortCustom2D(map_spawns,map_spawns_count,"spawn_distance_sort"); | ||
1334 : | SortStrings(map_spawns,map_spawns_count) | ||
1335 : | entity_get_vector(map_spawns[0][1],EV_VEC_origin,spawn_tp_orig) | ||
1336 : | //remove_entity(map_spawns[0][1]) | ||
1337 : | entity_set_vector(map_spawns[0][1],EV_VEC_origin,Float:{0,0,0}) | ||
1338 : | for(new i=5;i<map_spawns_count;i++)//normal i=5 | ||
1339 : | entity_set_vector(map_spawns[i][1],EV_VEC_origin,Float:{0,0,0}) | ||
1340 : | /*new Float:orig2[3],i | ||
1341 : | entity_get_vector(map_spawns[1][1],EV_VEC_origin,orig) | ||
1342 : | entity_get_vector(map_spawns[2][1],EV_VEC_origin,orig2) | ||
1343 : | for(i=3;i<map_spawns_count;i++){ | ||
1344 : | if((i/2)==(i%2))entity_set_vector(map_spawns[i][1],EV_VEC_origin,orig) | ||
1345 : | else entity_set_vector(map_spawns[i][1],EV_VEC_origin,orig2) | ||
1346 : | }*/ | ||
1347 : | } | ||
1348 : | else{ | ||
1349 : | while(dyn_spawn_count>=0){ | ||
1350 : | ent=dyn_spawn_ids[dyn_spawn_count] | ||
1351 : | entity_get_string(ent,EV_SZ_classname,tmpstr,31) | ||
1352 : | //entity_get_string(dyn_spawn_ids[i],EV_SZ_classname,tmpstr,31) | ||
1353 : | if(equal(tmpstr,"info_player_start")&&entity_get_int(ent,EV_INT_iuser1)==1)remove_entity(ent) | ||
1354 : | dyn_spawn_count-- | ||
1355 : | } | ||
1356 : | } | ||
1357 : | return PLUGIN_CONTINUE | ||
1358 : | } | ||
1359 : | /*public spawn_distance_sort(elem1[],elem2[]){ | ||
1360 : | if(elem1[1]<elem2[1])return -1 | ||
1361 : | if(elem1[1]>elem2[1])return 1 | ||
1362 : | return 0 | ||
1363 : | }*/ | ||
1364 : | //Future use, to block hook, or detect hook cheaters a.k.a. hookers | ||
1365 : | public phook(id){ | ||
1366 : | hooked[id]=1 | ||
1367 : | return PLUGIN_CONTINUE | ||
1368 : | } | ||
1369 : | public mhook(id){ | ||
1370 : | hooked[id]=0 | ||
1371 : | return PLUGIN_CONTINUE | ||
1372 : | } | ||
1373 : | //Make a public viewable help page for this on my web host. | ||
1374 : | public climb_help(id){ | ||
1375 : | if(get_pcvar_num(p_climb)){ | ||
1376 : | show_motd(id,"http://ian.cammarata.us/climb/help/2a2/","Climb Plugin Help") | ||
1377 : | } | ||
1378 : | return PLUGIN_HANDLED | ||
1379 : | } | ||
1380 : | public boost_help(id){ | ||
1381 : | if(get_pcvar_num(p_climb)){ | ||
1382 : | show_motd(id,"http://ian.cammarata.us/climb/help/2a2/boost.html","Climb Plugin Help") | ||
1383 : | } | ||
1384 : | return PLUGIN_HANDLED | ||
1385 : | } | ||
1386 : | //Force client to CT | ||
1387 : | public menuteam(id){ | ||
1388 : | if(get_pcvar_num(p_climb))client_cmd(id,"slot2") | ||
1389 : | return PLUGIN_CONTINUE | ||
1390 : | } | ||
1391 : | //Force client to choose random model | ||
1392 : | public menuclass(id){ | ||
1393 : | if(get_pcvar_num(p_climb)){ | ||
1394 : | client_cmd(id,"slot5") | ||
1395 : | } | ||
1396 : | return PLUGIN_CONTINUE | ||
1397 : | } | ||
1398 : | //Used to teleport clients, prevents client collisions and getting stuck | ||
1399 : | public teleport(id,Float:orig[3]){ | ||
1400 : | new Float:c2[3],player,players[32],num | ||
1401 : | get_players(players,num,"ac") | ||
1402 : | unsolid(id) | ||
1403 : | for(new i=0;i<num;i++){ | ||
1404 : | player=players[i] | ||
1405 : | if(id!=player){ | ||
1406 : | entity_get_vector(player,EV_VEC_origin,c2) | ||
1407 : | if(vector_distance(orig,c2)<74)unsolid(player) | ||
1408 : | } | ||
1409 : | } | ||
1410 : | entity_set_vector(id,EV_VEC_velocity,Float:{0.0, 0.0, 0.0}) | ||
1411 : | entity_set_vector(id,EV_VEC_origin,orig) | ||
1412 : | delay_duck(id) | ||
1413 : | return 1 | ||
1414 : | } | ||
1415 : | //Used by teleport and traceline-timer start, prevents getting stuck | ||
1416 : | public delay_duck(id){ | ||
1417 : | new ida[1] | ||
1418 : | ida[0]=id | ||
1419 : | set_task(0.01,"force_duck",_,ida,1) | ||
1420 : | set_entity_flags(ida[0],FL_DUCKING,1) | ||
1421 : | } | ||
1422 : | //Task for delay_duck | ||
1423 : | public force_duck(ida[1]){ | ||
1424 : | set_entity_flags(ida[0],FL_DUCKING,1) | ||
1425 : | } | ||
1426 : | //Use in IF statements to automatically print error if false | ||
1427 : | public cvar_enabled(id,p_cvar){ | ||
1428 : | if(get_pcvar_num(p_cvar)==0){ | ||
1429 : | clmsg(id,"This command is disabled.") | ||
1430 : | client_print(id,print_chat,"This command has been disabled by the server administrator.") | ||
1431 : | return 0 | ||
1432 : | } | ||
1433 : | return 1 | ||
1434 : | } | ||
1435 : | //Admin command, teleport to client | ||
1436 : | public goto_player(id,level,cid){ | ||
1437 : | if(cmd_access(id,level,cid,2)&&get_pcvar_num(p_climb)){ | ||
1438 : | new tid,arg[24] | ||
1439 : | read_argv(1,arg,sizeof(arg)-1) | ||
1440 : | tid=cmd_target(tid,arg,4) | ||
1441 : | if(tid){ | ||
1442 : | new Float:orig[3] | ||
1443 : | entity_get_vector(tid,EV_VEC_origin,orig) | ||
1444 : | teleport(id,orig) | ||
1445 : | } | ||
1446 : | } | ||
1447 : | return PLUGIN_HANDLED | ||
1448 : | } | ||
1449 : | //Move yourself to spectator | ||
1450 : | public spectate(id){ | ||
1451 : | if(get_pcvar_num(p_climb)&&(get_user_flags(id)&ADMIN_RESERVATION?1:(cvar_enabled(id,p_allow_spectators)))){ | ||
1452 : | cs_set_user_team(id,3) | ||
1453 : | set_msg_block(get_user_msgid("DeathMsg"),1) | ||
1454 : | user_kill(id,1) | ||
1455 : | } | ||
1456 : | return PLUGIN_HANDLED | ||
1457 : | } | ||
1458 : | //Block client kill command | ||
1459 : | public client_kill(id){ | ||
1460 : | if(get_pcvar_num(p_climb)==1)return PLUGIN_HANDLED | ||
1461 : | return PLUGIN_CONTINUE | ||
1462 : | } | ||
1463 : | //Used to block some commands | ||
1464 : | public block_cmd(id){ | ||
1465 : | if(get_pcvar_num(p_climb))return PLUGIN_HANDLED | ||
1466 : | return PLUGIN_CONTINUE | ||
1467 : | } | ||
1468 : | public block_cmd2(id){ | ||
1469 : | return PLUGIN_HANDLED | ||
1470 : | } | ||
1471 : | //Block client trying to switch teams | ||
1472 : | public block_jointeam(id){ | ||
1473 : | if(get_pcvar_num(p_climb)&&isct(id))return PLUGIN_HANDLED | ||
1474 : | return PLUGIN_CONTINUE | ||
1475 : | } | ||
1476 : | //Forward to catch all formats for commands | ||
1477 : | public client_command(id){ | ||
1478 : | if(!get_pcvar_num(p_climb)) | ||
1479 : | return PLUGIN_CONTINUE | ||
1480 : | new cmd[21] | ||
1481 : | read_argv(0,cmd,20) | ||
1482 : | //If say command replace command with say text, abort if more than one word | ||
1483 : | if(equal(cmd,"say")||equal(cmd,"say_team")){ | ||
1484 : | read_argv(1,cmd,20) | ||
1485 : | trim(cmd) | ||
1486 : | if(contain(cmd," ")>-1)return PLUGIN_CONTINUE | ||
1487 : | } | ||
1488 : | //Remove slashes | ||
1489 : | if(equal(cmd,"/",1)||equal(cmd,"\",1)||equal(cmd,".",1)||equal(cmd,"!",1))copy(cmd,20,cmd[1]) | ||
1490 : | //Make a checkpoint | ||
1491 : | if(equali(cmd,"checkpoint")||equali(cmd,"check")||equali(cmd,"cp"))check(id) | ||
1492 : | //Go to checkpoint | ||
1493 : | else if(equali(cmd,"gocheck")||equali(cmd,"gc")||equali(cmd,"tp")||equali(cmd,"tele"))gocheck(id) | ||
1494 : | //Boost help page | ||
1495 : | else if(equali(cmd,"boost"))boost_help(id) | ||
1496 : | //Solid Boost | ||
1497 : | else if(equali(cmd,"solid")||equali(cmd,"semiclip"))change_boost(id,CF_SOLID) | ||
1498 : | //Jump Boost | ||
1499 : | else if(equali(cmd,"superjump")||equali(cmd,"sjump")||equali(cmd,"sj")||equali(cmd,"longjump")||equali(cmd,"ljump")||equali(cmd,"lj"))change_boost(id,CF_SUPER_JUMP) | ||
1500 : | //Double Jump Boost | ||
1501 : | else if(equali(cmd,"doublejump")||equali(cmd,"djump")||equali(cmd,"dj"))change_boost(id,CF_DOUBLE_JUMP) | ||
1502 : | //Stuck | ||
1503 : | else if(equali(cmd,"stuck")||equali(cmd,"unstuck"))stuck(id) | ||
1504 : | //Pause | ||
1505 : | else if(equali(cmd,"pause")||equali(cmd,"unpause"))change_status(id,CF_PAUSE) | ||
1506 : | //Restart | ||
1507 : | else if(equali(cmd,"restart")||equali(cmd,"reset"))reset(id) | ||
1508 : | //Stop | ||
1509 : | else if(equali(cmd,"stop"))stop(id) | ||
1510 : | //Time/Scores | ||
1511 : | else if(equali(cmd,"scoreboard")||equali(cmd,"score")||equali(cmd,"scores"))climbscores(id) | ||
1512 : | //Top Scores | ||
1513 : | else if(equali(cmd,"top10")||equali(cmd,"top15")||equali(cmd,"top")||equali(cmd,"highscores")||equali(cmd,"best")||equali(cmd,"rank"))highscores(id) | ||
1514 : | //Respawn | ||
1515 : | else if(equali(cmd,"respawn")||equali(cmd,"spawn"))frespawn(id) | ||
1516 : | //Spectate | ||
1517 : | else if(equali(cmd,"spectate")||equali(cmd,"spec"))spectate(id) | ||
1518 : | //Climb Help | ||
1519 : | else if(equali(cmd,"help")||equali(cmd,"climbhelp")||equali(cmd,"kzhelp"))climb_help(id) | ||
1520 : | //If none of above conditions met, don't block the command | ||
1521 : | else return PLUGIN_CONTINUE | ||
1522 : | return PLUGIN_HANDLED | ||
1523 : | } | ||
1524 : | public donothing(){ | ||
1525 : | return PLUGIN_CONTINUE | ||
1526 : | } | ||
1527 : | public regwarn(id){ | ||
1528 : | if(timer[id][TMR_DBUSER]<1){ | ||
1529 : | saytext(id,id,"^x04You must register/login for your stats to save. Say /help for more info.") | ||
1530 : | return 1 | ||
1531 : | } | ||
1532 : | return 0 | ||
1533 : | } | ||
1534 : | public db_init(){ | ||
1535 : | //update from old db version | ||
1536 : | //alter table climb_scores add boosts int | ||
1537 : | //alter table climb_scores add wpns int | ||
1538 : | //alter table climb_scores add score int | ||
1539 : | //update climb_scores set boosts=-1 | ||
1540 : | //update climb_scores set wpns=-1 | ||
1541 : | static host[32],user[32],pass[32],name[32],type[12] | ||
1542 : | |||
1543 : | get_cvar_string("climb_db_host",host,31) | ||
1544 : | get_cvar_string("climb_db_user",user,31) | ||
1545 : | get_cvar_string("climb_db_pass",pass,31) | ||
1546 : | get_cvar_string("climb_db_name",name,31) | ||
1547 : | get_cvar_string("climb_db_type",type,11) | ||
1548 : | get_cvar_string("climb_db_prefix",db_prefix,31) | ||
1549 : | |||
1550 : | //SQL_SetAffinity(type) | ||
1551 : | db_tuple=SQL_MakeDbTuple(host,user,pass,name) | ||
1552 : | |||
1553 : | new query[600] | ||
1554 : | formatex(query,599,"\ | ||
1555 : | create table %splayers (\ | ||
1556 : | user_id integer primary key autoincrement,\ | ||
1557 : | steam_id char(25) unique,\ | ||
1558 : | password char(6),\ | ||
1559 : | user_name varchar(20) unique,\ | ||
1560 : | alias varchar(32) unique,\ | ||
1561 : | email varchar(50) unique,\ | ||
1562 : | cflags integer);\ | ||
1563 : | ",db_prefix) | ||
1564 : | SQL_ThreadQuery(db_tuple,"db_generic_handler",query) | ||
1565 : | formatex(query,599,"\ | ||
1566 : | create table %sscores (\ | ||
1567 : | score_id integer primary key autoincrement,\ | ||
1568 : | score integer,\ | ||
1569 : | server_ip char(15),\ | ||
1570 : | user_id integer,\ | ||
1571 : | map_name varchar(32),\ | ||
1572 : | fin_time integer,\ | ||
1573 : | cps integer,\ | ||
1574 : | gcs integer,\ | ||
1575 : | fin_cnt integer,\ | ||
1576 : | boosts integer,\ | ||
1577 : | wpns integer,\ | ||
1578 : | server_time_stamp integer);\ | ||
1579 : | create unique index scores_usermap_idx on %sscores (user_id, map_name);\ | ||
1580 : | create index scores_score on %sscores (score);\ | ||
1581 : | ",db_prefix,db_prefix,db_prefix) | ||
1582 : | SQL_ThreadQuery(db_tuple,"db_generic_handler",query) | ||
1583 : | formatex(query,599,"\ | ||
1584 : | create table %ssessions (\ | ||
1585 : | steam_id char(25) primary key,\ | ||
1586 : | user_id integer unique);\ | ||
1587 : | ",db_prefix) | ||
1588 : | SQL_ThreadQuery(db_tuple,"db_generic_handler",query) | ||
1589 : | return PLUGIN_HANDLED | ||
1590 : | } | ||
1591 : | public db_generic_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime){ | ||
1592 : | if(failstate == TQUERY_CONNECT_FAILED) | ||
1593 : | return server_print("Climb: Couldn't connect to database.") | ||
1594 : | else if(failstate == TQUERY_QUERY_FAILED) | ||
1595 : | return server_print("Climb: Query failed: %s",error) | ||
1596 : | |||
1597 : | if(errnum) | ||
1598 : | return server_print("Climb: Query Error: %s",error) | ||
1599 : | return PLUGIN_HANDLED | ||
1600 : | } | ||
1601 : | public logout(id){ | ||
1602 : | for(new i=0;i<8;i++)origins[id][i]=0.0 | ||
1603 : | for(new i=0;i<11;i++)timer[id][i]=0 | ||
1604 : | } | ||
1605 : | public login(id){ | ||
1606 : | if(get_pcvar_num(p_climb)){ | ||
1607 : | if(climb_save){ | ||
1608 : | if(timer[id][TMR_DBUSER]>0){//Already logged in | ||
1609 : | client_print(id,print_console,"[Climb] Login Error: You are already logged in.") | ||
1610 : | return PLUGIN_HANDLED | ||
1611 : | } | ||
1612 : | new query[99],data[28] | ||
1613 : | data[0]=id | ||
1614 : | if(read_argc()>1){//Client is logging in with a user/pass | ||
1615 : | new user[21],pass[21] | ||
1616 : | read_argv(1,user,20) | ||
1617 : | read_argv(2,pass,20) | ||
1618 : | rotwtf(pass,6) | ||
1619 : | data[1]=1 | ||
1620 : | formatex(query,98,"select user_id from %splayers where user_id='%s' and password='%s';",db_prefix,user,pass) | ||
1621 : | formatex(data[2],25,user) | ||
1622 : | SQL_ThreadQuery(db_tuple,"login_handler",query,data,28) | ||
1623 : | } | ||
1624 : | else{//Client is logging in with SteamID | ||
1625 : | new sid[26] | ||
1626 : | get_user_authid(id,sid,25) | ||
1627 : | data[1]=2 | ||
1628 : | formatex(query,98,"select user_id, password from %splayers where steam_id='%s';",db_prefix,sid) | ||
1629 : | formatex(data[2],25,sid) | ||
1630 : | SQL_ThreadQuery(db_tuple,"login_handler",query,data,28) | ||
1631 : | } | ||
1632 : | } | ||
1633 : | else client_print(id,print_console,"[Climb] Login Error: Can't Login; Stats not enabled.") | ||
1634 : | } | ||
1635 : | return PLUGIN_HANDLED | ||
1636 : | } | ||
1637 : | public login_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime){ | ||
1638 : | new id=data[0] | ||
1639 : | if(failstate == TQUERY_CONNECT_FAILED) | ||
1640 : | return server_print("Climb: Couldn't connect to database.") | ||
1641 : | else if(failstate == TQUERY_QUERY_FAILED) | ||
1642 : | return server_print("Climb: Query failed: %s",error) | ||
1643 : | |||
1644 : | if(errnum) | ||
1645 : | return server_print("Climb: Query Error: %s",error) | ||
1646 : | |||
1647 : | if(SQL_NumResults(query)<1) | ||
1648 : | return client_print(id,print_console,"[Climb] Login Error: Not a valid account.") | ||
1649 : | |||
1650 : | if(data[1]==2){ | ||
1651 : | new pass[7] | ||
1652 : | SQL_ReadResult(query,1,pass,6) | ||
1653 : | if(equali(pass,"shared")){ | ||
1654 : | client_print(id,print_console,"[Climb] Login Error: You are using a shared SteamID. Please login with a username and password.") | ||
1655 : | return PLUGIN_HANDLED | ||
1656 : | } | ||
1657 : | } | ||
1658 : | timer[id][TMR_DBUSER]=SQL_ReadResult(query,0) | ||
1659 : | new msg[100] | ||
1660 : | formatex(msg,99,"[Climb] Login: Success - Account: %s",data[2]) | ||
1661 : | client_print(id,print_console,msg) | ||
1662 : | format(msg,99,"^x04%s",msg) | ||
1663 : | saytext(id,id,msg) | ||
1664 : | db_load(id) | ||
1665 : | return PLUGIN_HANDLED | ||
1666 : | } | ||
1667 : | public db_load(id){ | ||
1668 : | new query[150],mapname[33],data[1] | ||
1669 : | data[0]=id | ||
1670 : | get_mapname(mapname,32) | ||
1671 : | formatex(query,149,"select fin_time, cps, gcs, fin_cnt from %sscores where user_id=%d and map_name='%s';",db_prefix,timer[id][TMR_DBUSER],mapname) | ||
1672 : | SQL_ThreadQuery(db_tuple,"db_load_handler",query,data,1) | ||
1673 : | return PLUGIN_HANDLED | ||
1674 : | } | ||
1675 : | public db_load_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime){ | ||
1676 : | if(failstate == TQUERY_CONNECT_FAILED) | ||
1677 : | return server_print("Climb: Couldn't connect to database.") | ||
1678 : | else if(failstate == TQUERY_QUERY_FAILED) | ||
1679 : | return server_print("Climb: Query failed: %s",error) | ||
1680 : | |||
1681 : | if(errnum) | ||
1682 : | return server_print("Climb: Query Error: %s",error) | ||
1683 : | |||
1684 : | new msg[100],id=data[0] | ||
1685 : | if(!SQL_NumResults(query)) | ||
1686 : | msg="^x04No stats available for this account on the current map." | ||
1687 : | else{ | ||
1688 : | new mapname[33],timestr[9] | ||
1689 : | get_mapname(mapname,32) | ||
1690 : | timer[id][TMR_BSTTME]=SQL_ReadResult(query,0) | ||
1691 : | timer[id][TMR_BSTCPS]=SQL_ReadResult(query,1) | ||
1692 : | timer[id][TMR_BSTGCS]=SQL_ReadResult(query,2) | ||
1693 : | timer[id][TMR_MAPFIN]=SQL_ReadResult(query,3) | ||
1694 : | timestr=parsetime(timer[id][TMR_BSTTME]) | ||
1695 : | formatex(msg,99,"^x04Stats loaded for %s - %s^t(%d CPS/ %d GCS)^tCompleted %d",mapname,timestr,timer[id][TMR_BSTCPS],timer[id][TMR_BSTGCS],timer[id][TMR_MAPFIN]) | ||
1696 : | } | ||
1697 : | saytext(id,id,msg) | ||
1698 : | return PLUGIN_HANDLED | ||
1699 : | } | ||
1700 : | public db_save(id){ | ||
1701 : | new query[150],name[33] | ||
1702 : | get_mapname(name,32) | ||
1703 : | if(timer[id][TMR_MAPFIN]==1) | ||
1704 : | formatex(query,149,"insert into %sscores (user_id, map_name, fin_time, cps, gcs, fin_cnt)\ | ||
1705 : | values (%d, '%s', %d, %d, %d, %d);\ | ||
1706 : | ",db_prefix,timer[id][TMR_DBUSER],name,timer[id][TMR_BSTTME],timer[id][TMR_BSTCPS],timer[id][TMR_BSTGCS],timer[id][TMR_MAPFIN]) | ||
1707 : | else | ||
1708 : | formatex(query,149,"update %sscores set fin_time=%d, cps=%d, gcs=%d, fin_cnt=%d where user_id=%d and map_name='%s';",db_prefix,timer[id][TMR_BSTTME],timer[id][TMR_BSTCPS],timer[id][TMR_BSTGCS],timer[id][TMR_MAPFIN],timer[id][TMR_DBUSER],name) | ||
1709 : | SQL_ThreadQuery(db_tuple,"db_save_handler",query) | ||
1710 : | get_user_name(id,name,32) | ||
1711 : | formatex(query,149,"update %splayers set alias='%s' where user_id=%d;",db_prefix,name,timer[id][TMR_DBUSER]) | ||
1712 : | SQL_ThreadQuery(db_tuple,"db_save_handler",query) | ||
1713 : | return PLUGIN_HANDLED | ||
1714 : | } | ||
1715 : | public db_save_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime){ | ||
1716 : | if(failstate == TQUERY_CONNECT_FAILED) | ||
1717 : | return server_print("Climb: Couldn't connect to database.") | ||
1718 : | else if(failstate == TQUERY_QUERY_FAILED) | ||
1719 : | return server_print("Climb: Query failed: %s",error) | ||
1720 : | |||
1721 : | if(errnum) | ||
1722 : | return server_print("Climb: Query Error: %s",error) | ||
1723 : | |||
1724 : | return PLUGIN_HANDLED | ||
1725 : | } | ||
1726 : | public reg(id){ | ||
1727 : | if(get_pcvar_num(p_climb)){ | ||
1728 : | if(climb_save){ | ||
1729 : | new query[100],sid[26],name[33],data[43] | ||
1730 : | data[0]=id | ||
1731 : | data[1]=0 | ||
1732 : | get_user_authid(id,sid,25) | ||
1733 : | get_user_name(id,name,32) | ||
1734 : | //Register user/pass | ||
1735 : | if(read_argc()>1){ | ||
1736 : | if(read_argc()!=3){ | ||
1737 : | client_print(id,print_console,"[Climb] Registration Error: Invalid number of arguments") | ||
1738 : | return PLUGIN_HANDLED | ||
1739 : | } | ||
1740 : | new user[21],pass[50] | ||
1741 : | //Read password and check length | ||
1742 : | read_argv(2,pass,20) | ||
1743 : | if(strlen(pass)<10){ | ||
1744 : | client_print(id,print_console,"[Climb] Registration Error: Password must be at least 10 characters.") | ||
1745 : | return PLUGIN_HANDLED | ||
1746 : | } | ||
1747 : | //Read user | ||
1748 : | read_argv(1,user,20) | ||
1749 : | //Store user/pass in data array to pass to handler for autologin | ||
1750 : | formatex(data[2],20,user) | ||
1751 : | formatex(data[22],20,pass) | ||
1752 : | //Create password hash | ||
1753 : | rotwtf(pass,6) | ||
1754 : | //Register shared SteamID | ||
1755 : | formatex(query,99,"insert into %splayers (steam_id,password) values ('%s','shared')",db_prefix,sid) | ||
1756 : | SQL_ThreadQuery(db_tuple,"reg_handler",query,data,43) | ||
1757 : | //Register user/pass | ||
1758 : | data[1]=1 | ||
1759 : | formatex(query,99,"insert into %splayers (user_name,password,alias) values ('%s','%s','%s')",db_prefix,user,pass,name) | ||
1760 : | SQL_ThreadQuery(db_tuple,"reg_handler",query,data,43) | ||
1761 : | } | ||
1762 : | //Else register SteamID | ||
1763 : | else{ | ||
1764 : | data[1]=2 | ||
1765 : | formatex(query,99,"insert into %splayers (steam_id,alias) values ('%s','%s')",db_prefix,sid,name) | ||
1766 : | SQL_ThreadQuery(db_tuple,"reg_handler",query,data,43) | ||
1767 : | } | ||
1768 : | } | ||
1769 : | else client_print(id,print_console,"[Climb] Registration Error: Can't Register; Stats not enabled.") | ||
1770 : | } | ||
1771 : | return PLUGIN_HANDLED | ||
1772 : | } | ||
1773 : | public reg_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime){ | ||
1774 : | new id=data[0],flag=data[1],user[21],pass[21] | ||
1775 : | format(user,20,data[2]) | ||
1776 : | format(pass,20,data[22]) | ||
1777 : | if(failstate == TQUERY_CONNECT_FAILED) | ||
1778 : | return server_print("[Climb] Couldn't connect to database.") | ||
1779 : | else if(failstate == TQUERY_QUERY_FAILED) | ||
1780 : | return server_print("[Climb] Query failed: %s",error) | ||
1781 : | |||
1782 : | if(errnum){ | ||
1783 : | client_print(id,print_console,"[Climb] Registration Error: Database error, please notify the server admin.") | ||
1784 : | return server_print("[Climb] Query Error: %s",error) | ||
1785 : | } | ||
1786 : | |||
1787 : | |||
1788 : | if(flag==0)client_print(id,print_console,"[Climb] Recorded shared SteamID.") | ||
1789 : | else{ | ||
1790 : | client_print(id,print_console,"[Climb] Registration Successful.") | ||
1791 : | new cmd[50] | ||
1792 : | formatex(cmd,49,"login %s %s",user,pass) | ||
1793 : | client_cmd(id,cmd) | ||
1794 : | } | ||
1795 : | return PLUGIN_HANDLED | ||
1796 : | } | ||
1797 : | public rotwtf(string[],out_len){ | ||
1798 : | new len=strlen(string),str[99],cnt=0,tok=len-1 | ||
1799 : | copy(str,out_len,string) | ||
1800 : | for(new index=0;index<11;index++){ | ||
1801 : | if('a'<=string[index]<='z') | ||
1802 : | str[index]=(str[index]-'a'+string[tok]+index) | ||
1803 : | else if('A'<=str[index]<='Z') | ||
1804 : | str[index]=(str[index]-'A'+string[tok]+index) | ||
1805 : | else if('0'<=str[index]<='9') | ||
1806 : | str[index]=(str[index]-'0'+string[tok]+index) | ||
1807 : | switch(cnt){ | ||
1808 : | case 0:str[index]=str[index]%26+'a' | ||
1809 : | case 1:str[index]=str[index]%26+'A' | ||
1810 : | case 2:str[index]=str[index]%10+'0' | ||
1811 : | } | ||
1812 : | tok-- | ||
1813 : | if(tok<0)tok=len-1 | ||
1814 : | cnt++ | ||
1815 : | if(cnt==3)cnt=0 | ||
1816 : | } | ||
1817 : | copy(string,out_len,str) | ||
1818 : | return PLUGIN_HANDLED | ||
1819 : | } | ||
1820 : | public plugin_init(){ | ||
1821 : | register_plugin("Climb",VERSION,"Ian Cammarata") | ||
1822 : | register_cvar("climb_version",VERSION,FCVAR_SERVER) | ||
1823 : | |||
1824 : | p_climb= register_cvar("climb","1",FCVAR_SERVER) | ||
1825 : | p_boost= register_cvar("climb_boost","1") | ||
1826 : | p_cpprice=register_cvar("climb_cpprice","0") | ||
1827 : | |||
1828 : | register_cvar("climb_save","1") | ||
1829 : | |||
1830 : | register_cvar("climb_db_type","sqlite") | ||
1831 : | register_cvar("climb_db_host","127.0.0.1") | ||
1832 : | register_cvar("climb_db_user","") | ||
1833 : | register_cvar("climb_db_pass","") | ||
1834 : | register_cvar("climb_db_name","climb") | ||
1835 : | register_cvar("climb_db_prefix","climb_") | ||
1836 : | |||
1837 : | p_msg_r=register_cvar("climb_msg_r","0") | ||
1838 : | p_msg_g=register_cvar("climb_msg_g","150") | ||
1839 : | p_msg_b=register_cvar("climb_msg_b","250") | ||
1840 : | p_msg_x=register_cvar("climb_msg_x","0.05") | ||
1841 : | p_msg_y=register_cvar("climb_msg_y","0.5") | ||
1842 : | |||
1843 : | p_sounds=register_cvar("climb_sounds","1") | ||
1844 : | p_render=register_cvar("climb_unsolid_type","0") | ||
1845 : | |||
1846 : | p_ip_internal=register_cvar("ip_internal","localhost") | ||
1847 : | p_ip_external=register_cvar("ip_external","localhost") | ||
1848 : | p_port=get_cvar_pointer("port") | ||
1849 : | |||
1850 : | p_webmod=register_cvar("climb_webmod","0") | ||
1851 : | p_stats_path= register_cvar("climb_stats_path","") | ||
1852 : | p_stats_url= register_cvar("climb_stats_url","") | ||
1853 : | p_stats_hsurl= register_cvar("climb_stats_hsurl","") //Use %s in place of map name | ||
1854 : | p_stats_msg= register_cvar("climb_stats_msg","") | ||
1855 : | |||
1856 : | p_allow_spectators=get_cvar_pointer("allow_spectators") | ||
1857 : | p_startmoney= register_cvar("climb_startmoney","1337") | ||
1858 : | //General Client Commands | ||
1859 : | //These commands get blocked always. | ||
1860 : | register_clcmd("fullupdate","block_cmd2") | ||
1861 : | //These commands get blocked when climb is enabled. | ||
1862 : | register_clcmd("chooseteam","block_cmd") | ||
1863 : | register_clcmd("buy","block_cmd") | ||
1864 : | register_clcmd("buyammo1","block_cmd") | ||
1865 : | register_clcmd("buyammo2","block_cmd") | ||
1866 : | register_clcmd("buyequip","block_cmd") | ||
1867 : | register_clcmd("jointeam","block_jointeam") | ||
1868 : | //Commands to detect cheats. | ||
1869 : | register_clcmd("+hook","phook") | ||
1870 : | register_clcmd("+rope","phook") | ||
1871 : | register_clcmd("-hook","mhook") | ||
1872 : | register_clcmd("-rope","mhook") | ||
1873 : | //Commands referencing function 'donothing' are picked up by the more flexible code in the client_command forward. | ||
1874 : | register_clcmd("climbhelp","donothing",0,"- Veiw climb help.") | ||
1875 : | register_clcmd("cp","donothing",_,"- Make a checkpoint") | ||
1876 : | register_clcmd("gc","donothing",_,"- Teleport to last checkpoint") | ||
1877 : | register_clcmd("stuck","donothing",_,"- Teleport to previous checkpoint") | ||
1878 : | register_clcmd("restart","donothing",_,"- Stop and respawn.") | ||
1879 : | register_clcmd("stop","donothing",_,"- End current climbing run.") | ||
1880 : | register_clcmd("pause","donothing",_,"- Pause yourself.") | ||
1881 : | register_clcmd("scoreboard","donothing",_,"- View score board.") | ||
1882 : | register_clcmd("respawn","donothing",_,"- Force respawn") | ||
1883 : | register_clcmd("boost","donothing",_,"- Boost.") | ||
1884 : | register_clcmd("spec","donothing",_,"- Spectate mode.") | ||
1885 : | //Commands related to stats account system. | ||
1886 : | register_clcmd("register","reg",_,"- (Console Only) Register for stats tracking.") | ||
1887 : | register_clcmd("login","login",_,"- (Console Only) Login to stats account.") | ||
1888 : | //Admin Commands | ||
1889 : | register_clcmd("amx_goto","goto_player",ADMIN_SLAY) | ||
1890 : | //For scoreboard backend | ||
1891 : | //register_srvcmd("amx_climb_sbrefresh","htmlscoreboard") | ||
1892 : | //Events | ||
1893 : | register_event("DeathMsg","death_msg","a") | ||
1894 : | register_event("ResetHUD","spawned","b") | ||
1895 : | //register_event("Damage","damage","b") | ||
1896 : | register_event("Health","damage","b") | ||
1897 : | register_event("ShowMenu","menuclass","b","4&CT_Select","4&Terrorist_Select") | ||
1898 : | register_event("ShowMenu","menuteam","b","4&Team_Select_Spect","4&Team_Select","4&IG_Team_Select") | ||
1899 : | //Init DB | ||
1900 : | if(get_cvar_num("climb_save"))climb_save=true | ||
1901 : | if(climb_save)db_init() | ||
1902 : | //Init anti flood time stamps | ||
1903 : | score_ts=get_systime() | ||
1904 : | hscore_ts=get_systime() | ||
1905 : | //Task to update time on clients HUD; Task set for half second to minimize flickering of the timer. | ||
1906 : | set_task(0.5,"hudtime",_,_,_,"b") | ||
1907 : | //Register FakeMeta Traceline forward. | ||
1908 : | register_forward(FM_TraceLine, "traceline", 1) | ||
1909 : | //Load Start/Finish Commands | ||
1910 : | new ini[50] | ||
1911 : | get_configsdir(ini,49) | ||
1912 : | format(ini,49,"%s/climb.ini",ini) | ||
1913 : | if(file_exists(ini)){ | ||
1914 : | new line=0,text[50],len | ||
1915 : | while(read_file(ini,line++,text,sizeof(text)-1,len)){ | ||
1916 : | if(!equal(text,";",1)&&!equal(text,"#",1)&&!equal(text,"//",2)){ | ||
1917 : | if(sfcount<SF_MAX){ | ||
1918 : | sfactions[sfcount]=text | ||
1919 : | sfcount++ | ||
1920 : | } | ||
1921 : | } | ||
1922 : | } | ||
1923 : | } | ||
1924 : | return PLUGIN_CONTINUE | ||
1925 : | } | ||
1926 : | public plugin_end() | ||
1927 : | if(climb_save) | ||
1928 : | SQL_FreeHandle(db_tuple) |
Contact | ViewVC Help |
Powered by ViewVC 1.0.4 |