Parent Directory | Revision Log
Revision 1 - (view) (download)
1 : | ian | 1 | /* |
2 : | Climb v2.0a4 | ||
3 : | Copyright (C) 2006-2007 Ian (Juan) Cammarata | ||
4 : | |||
5 : | This program is free software; you can redistribute it and/or modify it under | ||
6 : | the terms of the GNU General Public License as published by the Free Software | ||
7 : | Foundation; either version 2 of the License, or (at your option) any later | ||
8 : | version. | ||
9 : | |||
10 : | This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
11 : | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
12 : | PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
13 : | |||
14 : | You should have received a copy of the GNU General Public License along with | ||
15 : | this program; go to http://www.opensource.org/licenses/gpl-license.php | ||
16 : | -------------------------------------------------------------------------------- | ||
17 : | |||
18 : | http://ian.cammarata.us | ||
19 : | Sep 21 18:27 | ||
20 : | |||
21 : | |||
22 : | To do: | ||
23 : | Save user/pass login data for sessions (don't require login ever map change) | ||
24 : | Account management for accounts with user/pass login. email, change password, password recovery | ||
25 : | Unsolid as function of position and velocity | ||
26 : | Recode custom flashlight without temp entities | ||
27 : | |||
28 : | |||
29 : | Description: | ||
30 : | This plugin is designed for use in climbing maps like those available from www.kreedz.com. | ||
31 : | |||
32 : | |||
33 : | Commands: | ||
34 : | say /checkpoint : Save your position. | ||
35 : | say /gocheck : Teleport you to your last saved position. | ||
36 : | say /ungocheck : Undo a gocheck in case you accidentally use one after you make a tough jump. | ||
37 : | say /stuck : Teleport you to your previous checkpoint in case you get stuck in a wall. | ||
38 : | amx_goto : Teleport to another player. (Can't be used while timer is running) | ||
39 : | |||
40 : | A full help page can be found at http://ian.cammarata.us/projects/climb/help/2a3/en/commands | ||
41 : | |||
42 : | |||
43 : | Cvars: | ||
44 : | climb <1|0> : Enables|Disables all plugin functionality. The plugin now enables and disables itself, you should only use this cvar to turn the plugin on in maps which don't have a start button. | ||
45 : | climb_boost <1|0> : Enables|Disables boosting. | ||
46 : | climb_cpprice <0|...> : Set to dollar amount for cost of checkpoints. | ||
47 : | climb_startmoney <1337|0-16000> : Money amount set when players start timer. | ||
48 : | |||
49 : | climb_render <0|1> : Changes unsolid rendering style, 0=classic, other=new more see through rendering. | ||
50 : | climb_sounds <1|0> : Enables|Disables sounds build in to the Climb plugin. | ||
51 : | climb_start_respawn <0|1> : When enabled, eliminates unnecessary respawning. (Defaults to off) | ||
52 : | climb_water_nodraw: <0|1> : When enabled makes func_water entities invisible to help with players FPS issues. (Defaults to off) | ||
53 : | |||
54 : | climb_webmod <0|1> : Disables|Enables web mod interoperability. | ||
55 : | climb_stats_path <NULL|...> : Path to save generated stats pages. (If using WebMod, enter path to WebMod's www folder.) | ||
56 : | climb_stats_url <NULL|...> : URL to send clients to for stats pages. Only use if you have a web server running on the same machine as the game server. IF WEBMOD=1 THIS IS IGNORED. | ||
57 : | climb_stats_hsurl <NULL|...> : "%s" will be replaced with map name. Set to send client to URL if you have a page that automatically generates high scores via direct DB access. IF WEBMOD=1 THIS IS IGNORED. | ||
58 : | climb_stats_msg <NULL|...> : Message to display on scoreboard. Use HTML | ||
59 : | |||
60 : | ip_internal <localhost|...> : Set to internal network IP or hostname. (If server behind NAT) | ||
61 : | ip_external <localhost|...> : Set to external network IP or hostname. | ||
62 : | |||
63 : | climb_msg_r <0|0-255> : Display message red value. | ||
64 : | climb_msg_g <150|0-255> : Display message green value. | ||
65 : | climb_msg_b <250|0-255> : Display message blue value. | ||
66 : | climb_msg_x <0.05|0-1> : Display message x position. | ||
67 : | climb_msg_y <0.5|0-1> : Display message y position. | ||
68 : | |||
69 : | climb_light_r <255|0-255> : Sets the red value for the custom flashlight's color. | ||
70 : | climb_light_g <255|0-255> : Sets the green value for the custom flashlight's color. | ||
71 : | climb_light_b <255|0-255> : Sets the blue value for the custom flashlight's color. | ||
72 : | |||
73 : | *The following cvars are only read at plugin load, changes will not take effect until the map is changed. | ||
74 : | climb_save <1|0> : Enables|Disables saving of stats to a database. | ||
75 : | |||
76 : | climb_db_type <sqlite|mysql> : Database type. | ||
77 : | climb_db_host <127.0.0.1> : Database host name/ip. | ||
78 : | climb_db_user <NULL|...> : Database user name. | ||
79 : | climb_db_pass <NULL|...> : Database password. | ||
80 : | climb_db_name <climb|...> : Database name. | ||
81 : | climb_db_prefix <climb_|...> : Table name prefix. | ||
82 : | |||
83 : | |||
84 : | Requirements: | ||
85 : | AMXX 1.76 or higher | ||
86 : | Engine module | ||
87 : | Fakemeta module | ||
88 : | DB Module (MySQL or SQLite/Only needed if using CLIMB_SAVE 1.) | ||
89 : | |||
90 : | |||
91 : | Notes: | ||
92 : | Make sure you place the climb.txt file in addons\amxmodx\data\lang | ||
93 : | |||
94 : | I highly recommend using All Chat along with this plugin: | ||
95 : | http://forums.alliedmods.net/showthread.php?t=56825 | ||
96 : | |||
97 : | DF Hook Frontend plugin is included with this plugin, but still requires the Hookmod from AdminOP: | ||
98 : | http://www.adminop.net/modules.php?name=Downloads&d_op=viewdownloaddetails&lid=73&ttitle=Hook_Mod_Windows | ||
99 : | |||
100 : | To be able to get a full player listing on the scoreboard, you'll need to install WebMod and set the appropriate cvars for this plugin. | ||
101 : | WebMod site: http://djeyl.net/w.php | ||
102 : | |||
103 : | |||
104 : | Credits: | ||
105 : | Borrowed some code from Space Headed's bot_api.sma | ||
106 : | Borrowed some code from KCE's attack blocking tutorial (http://forums.alliedmods.net/showthread.php?t=41265) | ||
107 : | Thanks to Lola for letting me use her awesome server for testing purposes. | ||
108 : | http://1337bunnies.com | ||
109 : | 66.55.131.63:27015 | ||
110 : | Thanks to r33d and Woofie for testing and suggestions. | ||
111 : | |||
112 : | |||
113 : | Supported Languages: | ||
114 : | Not Applicable... yet. | ||
115 : | |||
116 : | |||
117 : | Change Log: | ||
118 : | Key (+ added | - removed | c changed | f fixed) | ||
119 : | |||
120 : | v2.0a4 (SEPT ??, 2007) | ||
121 : | +: New db admin commands: climb_dbwho, climb_dbmap, climb_dbplayer, climb_dbdelete. | ||
122 : | +: High scores now saves boosts, cps/gcs, and weapon used. | ||
123 : | +: New high scores sorting method. | ||
124 : | +: Breakable objects with health less than 9999 are now removed at map load. | ||
125 : | +: Duplicate names in database are now appended with "(#)" like the game scoreboard. | ||
126 : | +: Client commands 'cp+' and 'cp-' to cycle through checkpoints. | ||
127 : | +: Cvars mp_autoteambalance and mp_limitteams are set to 0 when a start button is found, and reverted when the map changes. | ||
128 : | +: Support for a2 maps start/finish buttons. | ||
129 : | +: Commands measure and measure2. | ||
130 : | +: Multiplayer friendly bhops. | ||
131 : | +: Command 'weapons', gives client one of each speed weapon. | ||
132 : | +: Ranking by weapon speed. ex: If you beat a map with AWP, you'll be ranked above other weapon scores. | ||
133 : | +: Command countdown to have time countdown from your best time instead of counting up. | ||
134 : | +: Instantly switch to spectator without death animation. | ||
135 : | -: Plugin ad on client connect. | ||
136 : | -: WebMod support since it is a huge security vulnerability. | ||
137 : | -: Cvars: climb_webmod, climb_stats_path, climb_stats_url, ip_internal, ip_external | ||
138 : | c: Tweaked semiclip to hopefully eliminate lag problems reported by some people. | ||
139 : | c: Cvar climb_water_nodraw changes take effect without reloading map. | ||
140 : | c: Database now stores multiple records per map per player. | ||
141 : | c: Cvar climb_db_pass is now protected. | ||
142 : | c: Optimized html layout of scoreboards to fit more data without using WebMod. | ||
143 : | c: Command '/stuck' is now an alias for 'cp-' and doesn't deduct from cp count. | ||
144 : | c: Start and restart commands now tp client to the start button (Spawn and respawn still tp to spawn point). | ||
145 : | c: Clients now spawn at start button. | ||
146 : | c: USP and M4 forced to be always silent. | ||
147 : | c: Guns reload with only 2 bullets, admins get unlimited clip for silenced guns. | ||
148 : | c: Timeout on knife slash. (The sound makes my ears bleed) | ||
149 : | c: Set 0.4 second timeout on cp, gc, and ungc commands. | ||
150 : | c: Set 2 second timeout on usp and scout commands. | ||
151 : | c: Re-enabled default flashlight, at least untill I recode the custom one. Custom NVG still in place. | ||
152 : | c: Respawn command now stops your timer, to prevent cheating in some maps. | ||
153 : | f: Bug where maps with built in auto-heal and healing doors didn't give 511 hp. (ex: kz_man_streetclimb) | ||
154 : | f: Showing high scores from previous map if client executes cmd a second time within the timeout period and current map has no scores in the DB. | ||
155 : | f: An exploit that involved a paused player with their view attached to something else. | ||
156 : | f: Bug where respawn command would spawn clients at maps origin if plugin was enabled without running init functions. | ||
157 : | f: Bug where multiple players could connect and get logged in with the same db user id. | ||
158 : | //f: Scoreboard buffer overflow that made players names get replaced with a path string. | ||
159 : | |||
160 : | v2.0a3 (JUNE 21, 2007) | ||
161 : | +: New alias for restart, /start. | ||
162 : | +: HP set to 512 when finished as god mode replacement. God mode prevents people from seeign each others names. | ||
163 : | +: Replicate hud messages and timer to spectators. | ||
164 : | +: Replacement flashlight/nightvision. Change color with cvars climb_light_r, ..._g, ..._b | ||
165 : | +: Cvar climb_start_respawn: eliminates unnecessary respawning, admin can enable if needed | ||
166 : | +: Cvar climb_water_nodraw: Makes func_water entities invisible to help with players FPS issues(off by default). | ||
167 : | +: Fake client added to CT team to prevent round end. Automatically leaves when the server is almost full, and rejoins as it empties. | ||
168 : | +: Two new commands, /scout and /usp, to get a scout or usp if you need one, or more ammo. | ||
169 : | +: New command /ungocheck or /ungc. Takes you to where you were before you last used gocheck. | ||
170 : | +: Can use chooseteam button or kill command to switch between spectating and playing. | ||
171 : | +: Plugin automatically disables on map change. Automatically enables if it finds a start button in new map. Setting the cvar climb to 1 in a map config will force the plugin to run. | ||
172 : | c: Spectators stay listed as CT on CS scoreboard so their rank will always show. | ||
173 : | c: Command amx_goto can be used by any player once they've completed the map. | ||
174 : | c: Players don't spawn with scout or c4 anymore. | ||
175 : | c: Newer unsolid render is default. | ||
176 : | c: New unsolid code provides perfect touch detection and eliminates problems that occurred in some maps. | ||
177 : | c: Decreased the wait time on some of the command timeouts. | ||
178 : | c: Replicated button use code from HL SDK. Start and finish button use detection is now perfect. | ||
179 : | c: In maps with built in healing climb auto heal is disabled(some maps like this have falling areas where you're not supposed to heal). | ||
180 : | f: Lag caused by respawning is pretty much eliminated by new weapon cleanup code and not giving as many weapons on spawn. | ||
181 : | f: MySQL query format problem for auto increment fields. | ||
182 : | f: SQLite query problem. Replaced single quotes around strings with double quotes. | ||
183 : | f: HLTV proxies caused two adjacent rows in scoreboard to be same color. | ||
184 : | f: Spectator lag bug. | ||
185 : | f: Bug where players had 511 HP on every map. | ||
186 : | |||
187 : | v2.0a2 (FEB 16, 2007) | ||
188 : | +: 2 addition boost types. Super jump and double jump. (No partner needed for boosting anymore) | ||
189 : | +: Boosts are counted. (Not logged in DB yet.) | ||
190 : | +: Stats saving in database. MySQL or SQLite. (MySQL not tested yet. Only works with single db module enabled) | ||
191 : | +: Players now get rewarded for finishing even without starting the timer. | ||
192 : | +: Cvars for message color and position. (climb_msg_r, ..._g, ..._b, ..._x, ..._y) | ||
193 : | +: Cvar climb_startmoney - Value to set money to when players start timer. | ||
194 : | +: Cvar climb_stats_msg - Message to display on the HTML scoreboards. | ||
195 : | +: Cvar climb_unsolid_type - Change rendering style for unsolid players. | ||
196 : | +: Cvar climb_sounds - Disabled Climb plugin sounds. | ||
197 : | +: Several cvars for database settings. | ||
198 : | +: All players spawn at spawn point closest to the start button. (Eliminates cheat in maps with a spawn point at the finish button.) | ||
199 : | +: Additional spawns added during map load to fix maps without enough spawns. | ||
200 : | +: Timeouts for respawning and boosting. | ||
201 : | +: Command "help". Displays HTML help pages. | ||
202 : | -: AMX compatibility. (AMX is officially dead) | ||
203 : | c: Cvars now prefixed with climb_ instead of amx_. | ||
204 : | c: Minor code optimizations. | ||
205 : | c: Command "Boost" now takes players to the boost help page instead of activating solid boost. | ||
206 : | c: All internal cvar handling is now done with pointers. (With the acception of cvars used only during init functions.) | ||
207 : | c: Solid boost only lasts 15 seconds at a time now since its usage is being tracked. | ||
208 : | c: Major internal rewrite (Probably added a few bugs. More major rewrites coming in next release.) | ||
209 : | |||
210 : | v1.9.19 (AUG 02, 2006) | ||
211 : | +: New public cvar 'climb_version' to aid in searching for server with this plugin. | ||
212 : | +: Show checkpoints, gochecks, and finish stats (Stats will be more extensive in next version) with finish announcement. | ||
213 : | -: Global chat. Use AllChat plugin instead. | ||
214 : | -: Cvar: amx_climb_globchat | ||
215 : | c: The /spec command now obeys the cvar "allow_spectators", clients with reserved slot always allowed. | ||
216 : | c: Shows number of checks and gocheck on client finish announcement. | ||
217 : | f: Bug caused by using stop command while paused. | ||
218 : | c: 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... | ||
219 : | |||
220 : | v1.9.18 (MAY 15, 2006) | ||
221 : | c: Recoded the way health is handled. Should work for any map now. | ||
222 : | |||
223 : | v1.9.17 (APR 07, 2006) | ||
224 : | c: Plugin is now compatible with both AMX and AMXX. | ||
225 : | c: The /spectate command can now be used by anyone. Admin no longer required. | ||
226 : | |||
227 : | v1.9.16a | ||
228 : | f: Added health fix for kz_cfl_yamakasi. | ||
229 : | c: New CSS theme for html scoreboard. | ||
230 : | |||
231 : | v1.9.16 | ||
232 : | +: Counts usage of CP and GC commands(only displayed on html scoreboard). | ||
233 : | f: Added health fix for kz_lighthouse and kz_phoogi. | ||
234 : | |||
235 : | v1.9.15 | ||
236 : | +: Colorized global chat. ADMIN_RESERVATION has name in green instead of team color. | ||
237 : | +: /stop command. Resets timer to zero, end climbing session. | ||
238 : | c: Reset function. /stop + /respawn. Client is now reset automatically when pressing the start button if they are not already started. | ||
239 : | f: YOU CAN'T GET STUCK ANYMORE!!! (Well almost. Doing gocheck a second time gets you unstuck.) | ||
240 : | f: Global chat is now logged correctly and shows up in HLSW. | ||
241 : | |||
242 : | v1.9.14 | ||
243 : | +: Hook is taken away when client starts timer, given back if they reset. | ||
244 : | +: Max health fixes for several new maps. | ||
245 : | +: Sort clients on CS scoreboard by climb rank. | ||
246 : | +: Cvar amx_climb_boost - enable\disable boosting. | ||
247 : | +: Cvar amx_climb_cpprice - charge money for checkpoints. | ||
248 : | +: Custom configurable commands based on events. (climb.ini) | ||
249 : | +: Global chat. cvar: amx_climb_globchat <1|0> | ||
250 : | +: Client climb time is now shown using the round time HUD sprites. | ||
251 : | -: Command /mytime, not needed because of HUD sprite timer. | ||
252 : | -: Auto time display every 30 seconds, not needed because of HUD sprite timer. | ||
253 : | c: Added another start button sound. | ||
254 : | c: Super healing doors no longer removed. (Needed for shortcuts in some maps.) | ||
255 : | f: Admins can't be alive as spectator even with 3rd party respawn plugin. | ||
256 : | f: Keep godmode after respawning if finished map and not reset. | ||
257 : | f: Admins VIP display on CS scoreboard is now updated whenever clients connect. | ||
258 : | f: Health charger minimaps in kz_real_skyscraper & kz_northpole_b01. | ||
259 : | f: Not teleporting to exact cp position if another client is on your cp. | ||
260 : | f: Respawning outside of maps sometimes immediately after leaving spectator. | ||
261 : | */ | ||
262 : | #include <amxmodx> | ||
263 : | #include <fun> | ||
264 : | #include <amxmisc> | ||
265 : | #include <engine> | ||
266 : | #include <fakemeta> | ||
267 : | #include <sqlx> | ||
268 : | #include <string2> | ||
269 : | #include <cstrike> | ||
270 : | #include <cstrike2> | ||
271 : | |||
272 : | #define VERSION "a3.6.19 Oct 08 04:41 MST" | ||
273 : | |||
274 : | #define IN_ATTACK_EITHER ( IN_ATTACK + IN_ATTACK2 ) | ||
275 : | |||
276 : | #define SF_MAX 50 //Maximum number of start/finish commands in climb.ini | ||
277 : | |||
278 : | #define CPGC_TIMEOUT 0.4 //In seconds, decimal allowed | ||
279 : | #define SPAWN_TIMEOUT 2 //In seconds, whole number only / used for start button also | ||
280 : | #define WPN_TIMEOUT 2 //In seconds, whole number only | ||
281 : | #define BOOST_TIMEOUT 5 //In seconds, whole number only | ||
282 : | #define KNIFE_TIMEOUT 2 //In seconds, whole number only | ||
283 : | |||
284 : | #define NAMELEN 15 | ||
285 : | |||
286 : | #define DBADMIN ADMIN_RCON | ||
287 : | #define VIP ADMIN_RESERVATION | ||
288 : | |||
289 : | new MAXPLAYERS | ||
290 : | |||
291 : | //DB data | ||
292 : | new Handle:DB_TUPLE, DB_PREFIX[11], bool:CLIMB_SAVE, DB_SERVER_ID[16] | ||
293 : | new db_last_del_id | ||
294 : | |||
295 : | //Client flags arrays | ||
296 : | #define ORIGINS_SIZE 48 | ||
297 : | new Float:origins[32][ORIGINS_SIZE] | ||
298 : | #define ORIG_UNGC 40 | ||
299 : | #define ORIG_PAUS 44 | ||
300 : | //#define ORIG_X 0 | ||
301 : | //#define ORIG_Y 1 | ||
302 : | //#define ORIG_Z 2 | ||
303 : | #define ORIG_GRAV 3 | ||
304 : | |||
305 : | new time_stamps[32][5]//time_stamps[id-1][x] | ||
306 : | #define TS_SPAWN 0 | ||
307 : | #define TS_BOOST 1 | ||
308 : | #define TS_WPN 2 | ||
309 : | #define TS_CPGC 3 //This one holds a flag, not a timestamp so it can be < 1 second | ||
310 : | #define TS_KNIFE 4 | ||
311 : | |||
312 : | #define TIMER_SIZE 16 | ||
313 : | new timer[32][TIMER_SIZE]//timer[id-1][x]: | ||
314 : | #define TMR_CFLAGS 0 //Status | ||
315 : | #define TMR_STARTD 1 //Start Time | ||
316 : | #define TMR_FINISH 2 //Finish Time | ||
317 : | #define TMR_CNTCPS 3 //CP Count | ||
318 : | #define TMR_CNTGCS 4 //GC Count | ||
319 : | #define TMR_CNTBST 5 //Boosts | ||
320 : | #define TMR_BSTTME 6 //Best Time | ||
321 : | #define TMR_BSTCPS 7 //Best CP | ||
322 : | #define TMR_BSTGCS 8 //Best GC | ||
323 : | #define TMR_BSTBST 9 //Number of boosts used | ||
324 : | #define TMR_SESFIN 10 //Finished this session | ||
325 : | #define TMR_MAPFIN 11 //Total times finished this map | ||
326 : | #define TMR_DBUSER 12 //Database player ID; 0=not registered; -1=not registered & shared steam id | ||
327 : | #define TMR_CPPOS 13 //Current CP offset, for cycling back and forward through cps | ||
328 : | #define TMR_CNTWPN 14 //Current weapon rank modifier | ||
329 : | #define TMR_BSTWPN 15 //Best score weapon rank modifier | ||
330 : | |||
331 : | //Temp save vars | ||
332 : | new savepos = 0, steamid[32][32], Float:originssave[32][ORIGINS_SIZE], timersave[32][TIMER_SIZE] | ||
333 : | |||
334 : | //Other stuff | ||
335 : | new hooked[32], hp = 100 | ||
336 : | new sfactions[SF_MAX][50], sfcount = 0 | ||
337 : | new ts_score, ts_hscore, bool:has_hscores = false //scoreboard timeouts | ||
338 : | new spec_ids[32][32] | ||
339 : | new beam_sprite | ||
340 : | |||
341 : | new ST_BTNS[9], FN_BTNS[9], ST_BTN_CNT = 0, FN_BTN_CNT = 0 | ||
342 : | new dyn_spawn_ids[32], dyn_spawn_count, Float:spawn_tp_orig[3], Float:start_tp_orig[3] | ||
343 : | |||
344 : | new bool:sclip[32],Float:post_think_vel[32][3],sc_fcount | ||
345 : | |||
346 : | new LIMIT_TEAMS_OLD, TEAM_BALANCE_OLD | ||
347 : | |||
348 : | //Bhop fix vars | ||
349 : | #define MAX_DOORS 500 | ||
350 : | new door_count = 0, func_doors[MAX_DOORS][3], Float:door_tp_pos[MAX_DOORS][3] | ||
351 : | new bhop_failid[32], bool:bhop_fail[32] | ||
352 : | //func_doors[x]{ id, speed, angles } | ||
353 : | |||
354 : | //Cvar Pointers | ||
355 : | new p_climb, p_auto, p_boost, p_cpprice, p_startmoney | ||
356 : | new p_msg_r, p_msg_g, p_msg_b, p_msg_x, p_msg_y | ||
357 : | new p_sounds, p_render | ||
358 : | new p_stats_hsurl, p_stats_msg | ||
359 : | new p_light_r, p_light_g, p_light_b | ||
360 : | new p_start_respawn, p_water_nodraw | ||
361 : | new p_allow_spectators, p_teambalance, p_limitteams | ||
362 : | |||
363 : | //Model size | ||
364 : | //standing 32x32x72 | ||
365 : | //crouched 32x32x36 | ||
366 : | |||
367 : | //Tasks: | ||
368 : | //#define TSK_AUTOHEAL 50 //50+ : Auto Heal | ||
369 : | #define TSK_AUTORSPN 100 //100+: Auto Respawn | ||
370 : | //#define TSK_BOOSTTMR 150 //150+: Solid Boost Timer | ||
371 : | #define TSK_FLIGHT 200 | ||
372 : | #define TSK_BHOP 250 | ||
373 : | #define TSK_CLEAR_FAIL 300 | ||
374 : | #define TSK_MEASURE2 350 | ||
375 : | |||
376 : | //Status timer[id-1][TMR_CFLAGS]&=x | ||
377 : | #define CF_NULL 0 //Passed to change_boost() to remove all boost flags | ||
378 : | #define CF_STOP (1<<0) //STATUS FLAG: Not Started | ||
379 : | #define CF_START (1<<1) //STATUS FLAG: Climbing | ||
380 : | #define CF_PAUSE (1<<2) //STATUS FLAG: Paused | ||
381 : | #define CF_STATUSFLAGS ( CF_STOP + CF_START + CF_PAUSE ) | ||
382 : | #define CF_SOLID (1<<3) //BOOST FLAG | ||
383 : | #define CF_SUPER_JUMP (1<<4) //BOOST FLAG | ||
384 : | #define CF_DOUBLE_JUMP (1<<5) //BOOST FLAG | ||
385 : | #define CF_LIGHT_ON (1<<6) | ||
386 : | //#define CF_NO_VIP (1<<7) | ||
387 : | #define CF_JUST_REGD (1<<8) | ||
388 : | #define CF_MEASURE (1<<9) | ||
389 : | #define CF_MEASURE2 (1<<10) | ||
390 : | #define CF_COUNTDOWN (1<<11) | ||
391 : | #define CF_SUNGLASSES (1<<12) | ||
392 : | |||
393 : | new WPN_CLASS[30][17] = { "weapon_p228", | ||
394 : | "", | ||
395 : | "weapon_scout", | ||
396 : | "", //"weapon_hegrenade", | ||
397 : | "weapon_xm1014", | ||
398 : | "", //"weapon_c4", | ||
399 : | "weapon_mac10", | ||
400 : | "weapon_aug", | ||
401 : | "", //"weapon_smokegrenade", | ||
402 : | "weapon_elite", | ||
403 : | "weapon_fiveseven", | ||
404 : | "weapon_ump45", | ||
405 : | "weapon_sg550", | ||
406 : | "weapon_galil", | ||
407 : | "weapon_famas", | ||
408 : | "weapon_usp", | ||
409 : | "weapon_glock18", | ||
410 : | "weapon_awp", | ||
411 : | "weapon_mp5navy", | ||
412 : | "weapon_m249", | ||
413 : | "weapon_m3", | ||
414 : | "weapon_m4a1", | ||
415 : | "weapon_tmp", | ||
416 : | "weapon_g3sg1", | ||
417 : | "", //"weapon_flashbang", | ||
418 : | "weapon_deagle", | ||
419 : | "weapon_sg552", | ||
420 : | "weapon_ak47", | ||
421 : | "", //"weapon_knife", | ||
422 : | "weapon_p90" } | ||
423 : | |||
424 : | new SVC_STATUSICON, SVC_TEAMINFO, SVC_ROUNDTIME, SVC_FLASHLIGHT, SVC_SCREENFADE | ||
425 : | |||
426 : | new SCORES_PATH[100], HSCORES_PATH[100] | ||
427 : | |||
428 : | //////////////////////////////////////////////////////////////////////////////// | ||
429 : | // Start: Init forwards | ||
430 : | //////////////////////////////////////////////////////////////////////////////// | ||
431 : | public plugin_init( ) | ||
432 : | { | ||
433 : | MAXPLAYERS = get_maxplayers( ) | ||
434 : | register_plugin( "Climb", VERSION, "Ian Cammarata" ) | ||
435 : | register_cvar( "climb_version", VERSION, FCVAR_SERVER ) | ||
436 : | |||
437 : | //This line is for nightly builds only, to keep tracking cvar updated. | ||
438 : | set_cvar_string( "climb_version", VERSION ) | ||
439 : | |||
440 : | p_climb = register_cvar( "climb", "0", FCVAR_SERVER ) | ||
441 : | p_auto = register_cvar( "climb_auto", "1" ) | ||
442 : | p_boost = register_cvar( "climb_boost", "1" ) | ||
443 : | p_cpprice = register_cvar( "climb_cpprice", "0" ) | ||
444 : | p_startmoney = register_cvar( "climb_startmoney", "1337" ) | ||
445 : | |||
446 : | register_cvar( "climb_save", "1" ) | ||
447 : | register_cvar( "climb_db_type", "sqlite" ) | ||
448 : | register_cvar( "climb_db_host", "127.0.0.1" ) | ||
449 : | register_cvar( "climb_db_user", "" ) | ||
450 : | register_cvar( "climb_db_pass", "", FCVAR_PROTECTED ) | ||
451 : | register_cvar( "climb_db_name", "climb" ) | ||
452 : | register_cvar( "climb_db_prefix", "climb_" ) | ||
453 : | register_cvar( "climb_db_serverid", "" ) | ||
454 : | register_cvar( "climb_db_exists", "0" ) | ||
455 : | |||
456 : | p_msg_r = register_cvar( "climb_msg_r", "0" ) | ||
457 : | p_msg_g = register_cvar( "climb_msg_g", "150" ) | ||
458 : | p_msg_b = register_cvar( "climb_msg_b", "250" ) | ||
459 : | p_msg_x = register_cvar( "climb_msg_x", "0.05" ) | ||
460 : | p_msg_y = register_cvar( "climb_msg_y", "0.5" ) | ||
461 : | |||
462 : | p_light_r = register_cvar( "climb_light_r", "255" ) | ||
463 : | p_light_g = register_cvar( "climb_light_g", "255" ) | ||
464 : | p_light_b = register_cvar( "climb_light_b", "255" ) | ||
465 : | |||
466 : | p_sounds = register_cvar( "climb_sounds", "1" ) | ||
467 : | p_render = register_cvar( "climb_unsolid_type", "0" ) | ||
468 : | p_start_respawn = register_cvar( "climb_start_respawn", "0" ) | ||
469 : | p_water_nodraw = register_cvar( "climb_water_nodraw", "0" ) | ||
470 : | |||
471 : | p_stats_hsurl = register_cvar( "climb_stats_hsurl", "" ) //Use %s in place of map name | ||
472 : | p_stats_msg = register_cvar( "climb_stats_msg", "" ) | ||
473 : | |||
474 : | p_allow_spectators = get_cvar_pointer( "allow_spectators" ) | ||
475 : | p_teambalance = get_cvar_pointer( "mp_autoteambalance" ) | ||
476 : | p_limitteams = get_cvar_pointer( "mp_limitteams" ) | ||
477 : | |||
478 : | TEAM_BALANCE_OLD = get_pcvar_num( p_teambalance ) | ||
479 : | LIMIT_TEAMS_OLD = get_pcvar_num( p_limitteams ) | ||
480 : | |||
481 : | //Message Pseudo-Constants | ||
482 : | SVC_STATUSICON = get_user_msgid( "StatusIcon" ) | ||
483 : | SVC_TEAMINFO = get_user_msgid( "TeamInfo" ) | ||
484 : | SVC_ROUNDTIME = get_user_msgid( "RoundTime" ) | ||
485 : | SVC_FLASHLIGHT = get_user_msgid( "Flashlight" ) | ||
486 : | SVC_SCREENFADE = get_user_msgid( "ScreenFade" ) | ||
487 : | |||
488 : | //These commands get blocked always. | ||
489 : | register_clcmd( "fullupdate", "block_cmd2" ) | ||
490 : | |||
491 : | //These commands get blocked when climb is enabled. | ||
492 : | register_clcmd( "chooseteam", "spectate" ) | ||
493 : | register_clcmd( "buy", "block_cmd" ) | ||
494 : | register_clcmd( "buyammo1", "block_cmd" ) | ||
495 : | register_clcmd( "buyammo2", "block_cmd" ) | ||
496 : | register_clcmd( "buyequip", "block_cmd" ) | ||
497 : | |||
498 : | register_clcmd( "jointeam", "block_jointeam" ) | ||
499 : | |||
500 : | //Commands to detect cheats. | ||
501 : | register_clcmd( "+hook", "phook" ) | ||
502 : | register_clcmd( "+rope", "phook" ) | ||
503 : | register_clcmd( "-hook", "mhook" ) | ||
504 : | register_clcmd( "-rope", "mhook" ) | ||
505 : | |||
506 : | //Commands referencing function 'donothing' are picked up by the more flexible code in the client_command forward. | ||
507 : | register_clcmd( "say help", "help_msg" ) | ||
508 : | register_clcmd( "say /help", "help_msg" ) | ||
509 : | register_clcmd( "climbhelp", "donothing", 0, "- Veiw climb help." ) | ||
510 : | register_clcmd( "cp", "donothing", _, "- Make a checkpoint" ) | ||
511 : | register_clcmd( "gc", "donothing", _, "- Teleport to last checkpoint" ) | ||
512 : | register_clcmd( "stuck", "donothing", _, "- Teleport to previous checkpoint" ) | ||
513 : | register_clcmd( "restart","donothing", _, "- Stop and respawn." ) | ||
514 : | register_clcmd( "stop", "donothing", _, "- End current climbing run." ) | ||
515 : | register_clcmd( "pause", "donothing", _, "- Pause yourself." ) | ||
516 : | register_clcmd( "scoreboard", "donothing", _, "- View score board." ) | ||
517 : | register_clcmd( "respawn", "donothing", _, "- Force respawn" ) | ||
518 : | register_clcmd( "boost", "donothing", _, "- Boost." ) | ||
519 : | register_clcmd( "spec", "donothing", _, "- Spectate mode." ) | ||
520 : | register_clcmd( "ungc", "donothing", _, "- Undo last gocheck." ) | ||
521 : | |||
522 : | //Commands related to stats account system. | ||
523 : | //register_clcmd( "register", "reg", _, "- (Console Only) Register for stats tracking." ) | ||
524 : | register_clcmd( "login", "db_login", _, "- (Console Only) Login to stats account." ) | ||
525 : | |||
526 : | register_concmd( "climb_dbwho", "climb_dbwho", DBADMIN, "- List DB ID of current clients." ) | ||
527 : | register_concmd( "climb_dbmap", "climb_dbmap", DBADMIN, "<Map Name> - List high scores for current map." ) | ||
528 : | register_concmd( "climb_dbuser", "climb_dbuser", DBADMIN, "[DB User ID] - List high scores for given DB User ID." ) | ||
529 : | register_concmd( "climb_dbdelete", "climb_dbdelete", DBADMIN, "[DB Score ID] - Delete score for given DB Score ID." ) | ||
530 : | |||
531 : | //temp commands | ||
532 : | register_concmd("climb_dbrecalc","climb_dbrecalc",DBADMIN) | ||
533 : | |||
534 : | //Admin Commands | ||
535 : | register_clcmd("amx_goto","goto_player") | ||
536 : | |||
537 : | //Climb Flashlight | ||
538 : | //register_impulse(100,"tog_flight") | ||
539 : | register_clcmd("nightvision","tog_flight") | ||
540 : | |||
541 : | //Events | ||
542 : | register_event("DeathMsg","DeathMsg","a") | ||
543 : | register_event("ResetHUD","ResetHUD","b") | ||
544 : | register_event("Health","damage","b") | ||
545 : | register_event("ShowMenu","menuclass","b","4&CT_Select","4&Terrorist_Select") | ||
546 : | register_event("ShowMenu","menuteam","b","4&Team_Select_Spect","4&Team_Select","4&IG_Team_Select") | ||
547 : | |||
548 : | //Init DB | ||
549 : | if( get_cvar_num( "climb_save" ) ) CLIMB_SAVE = true | ||
550 : | if( CLIMB_SAVE ) db_init( ) | ||
551 : | |||
552 : | //Init anti flood time stamps | ||
553 : | ts_score = get_systime( ) | ||
554 : | ts_hscore = get_systime( ) | ||
555 : | set_task( 0.5, "hudtime", _, _, _, "b" ) //Task to update time on clients HUD; Task set for half second to minimize flickering of the timer. | ||
556 : | set_task( 1.0, "spec_update", _, _, _, "b" ) //Task to update spectator array | ||
557 : | set_task( 5.0, "run_tasks", _, _, _, "b" ) | ||
558 : | |||
559 : | register_message( get_user_msgid( "CurWeapon" ), "CurWeapon" ) | ||
560 : | register_message( get_user_msgid( "ReqState" ), "bot_msg_block" ) | ||
561 : | register_message( get_user_msgid( "Radar" ), "bot_msg_block" ) | ||
562 : | |||
563 : | register_forward( FM_UpdateClientData, "PostUpdateClientData", 1 ) | ||
564 : | |||
565 : | //register_dictionary("climb.txt") | ||
566 : | |||
567 : | //Make var folder if not exists | ||
568 : | new path[61] | ||
569 : | get_localinfo( "amxx_datadir", path, 60 ) | ||
570 : | format( path, 60, "%s/var", path ) | ||
571 : | if( !dir_exists( path ) ) mkdir( path ) | ||
572 : | formatex( SCORES_PATH, 99, "%s/climb_scores.html", path ) | ||
573 : | formatex( HSCORES_PATH, 99, "%s/climb_highscores.html", path ) | ||
574 : | |||
575 : | //Load Start/Finish Commands | ||
576 : | new ini[50] | ||
577 : | get_configsdir( ini, 49 ) | ||
578 : | format( ini, 49, "%s/climb.ini", ini ) | ||
579 : | if( file_exists( ini ) ) | ||
580 : | { | ||
581 : | new line = 0, text[50], len | ||
582 : | while( read_file( ini, line++, text, sizeof(text)-1 , len ) ) | ||
583 : | { | ||
584 : | if( !equal( text, ";", 1 ) && !equal( text, "#", 1 ) && !equal( text, "//", 2 ) ) | ||
585 : | { | ||
586 : | if( sfcount < SF_MAX ) | ||
587 : | { | ||
588 : | sfactions[sfcount] = text | ||
589 : | sfcount++ | ||
590 : | } | ||
591 : | } | ||
592 : | } | ||
593 : | } | ||
594 : | return PLUGIN_CONTINUE | ||
595 : | } | ||
596 : | |||
597 : | public pfn_keyvalue( ent ) | ||
598 : | { | ||
599 : | //Create more ct spawns so everyone can join team | ||
600 : | if( dyn_spawn_count < 1 ) | ||
601 : | { | ||
602 : | new id | ||
603 : | for( dyn_spawn_count = 0; dyn_spawn_count < 30; dyn_spawn_count++ ) | ||
604 : | { | ||
605 : | id = create_entity( "info_player_start" ) | ||
606 : | if( id > 0 ) | ||
607 : | { | ||
608 : | dyn_spawn_ids[dyn_spawn_count] = id | ||
609 : | entity_set_int( id, EV_INT_iuser1, 1 ) | ||
610 : | } | ||
611 : | } | ||
612 : | } | ||
613 : | |||
614 : | static last_ent | ||
615 : | new class[31], key[31], val[31] | ||
616 : | copy_keyvalue( class, 30, key, 30, val, 30 ) | ||
617 : | |||
618 : | if( ent != last_ent && func_doors[door_count][0] && door_count < MAX_DOORS ) | ||
619 : | door_count++ | ||
620 : | |||
621 : | if( equal( class, "func_door" ) ) | ||
622 : | { | ||
623 : | //func_doors[x]{ id, speed, angles } | ||
624 : | |||
625 : | if( ent != last_ent ) func_doors[door_count][0] = ent | ||
626 : | |||
627 : | if( equal( key, "speed" ) ) | ||
628 : | func_doors[door_count][1] = str_to_num(val) | ||
629 : | if( equal( key, "dmg" ) ) | ||
630 : | func_doors[door_count][0] = 0 | ||
631 : | if( equal( key, "angles" ) ) | ||
632 : | { | ||
633 : | new angles[5] | ||
634 : | parse( val, angles, 4 ) | ||
635 : | func_doors[door_count][2] = str_to_num( angles ) | ||
636 : | } | ||
637 : | last_ent = ent | ||
638 : | } | ||
639 : | |||
640 : | return PLUGIN_CONTINUE | ||
641 : | } | ||
642 : | |||
643 : | public plugin_cfg( ) | ||
644 : | { | ||
645 : | new ent, ent2, tmpstr[33], Float:tmpflt | ||
646 : | |||
647 : | if( func_doors[door_count][0] && door_count < MAX_DOORS ) | ||
648 : | door_count++ | ||
649 : | |||
650 : | //Find tp spots for doors, in case they're used for bhop | ||
651 : | //func_doors[x]{ id, speed, angles } | ||
652 : | for( new i = 0; i < door_count; i++ ) | ||
653 : | { | ||
654 : | ent = func_doors[i][0] | ||
655 : | if( !is_valid_ent( ent ) ) func_doors[i][0] = 0 | ||
656 : | else | ||
657 : | { | ||
658 : | new Float:dmins[3], Float:dmaxs[3] | ||
659 : | entity_get_vector( ent, EV_VEC_mins, dmins ) | ||
660 : | entity_get_vector( ent, EV_VEC_maxs, dmaxs ) | ||
661 : | |||
662 : | new dwid = floatround( dmaxs[0] - dmins[0] ) | ||
663 : | new dlen = floatround( dmaxs[1] - dmins[1] ) | ||
664 : | |||
665 : | //If the door moves up, or is thin, remove it's id from the array | ||
666 : | if( func_doors[i][2] < 0 || dwid < 24 || dlen < 24 ) | ||
667 : | func_doors[i][0] = 0 | ||
668 : | //Otherwise find a safe tp spot in case it's a bhop door | ||
669 : | else | ||
670 : | { | ||
671 : | //If it has a targetname, change the id in array to targeter | ||
672 : | entity_get_string( ent, EV_SZ_targetname, tmpstr, 32 ) | ||
673 : | if( strlen( tmpstr ) ) | ||
674 : | { | ||
675 : | ent2 = find_ent_by_target( -1, tmpstr ) | ||
676 : | if( ent2 ) | ||
677 : | { | ||
678 : | func_doors[i][0] = ent2 | ||
679 : | |||
680 : | //If targeter is a button, remove it's id from the array | ||
681 : | entity_get_string( ent2, EV_SZ_classname, tmpstr, 32 ) | ||
682 : | if( equal( tmpstr, "func_button" ) ) | ||
683 : | func_doors[i][0] = 0 | ||
684 : | } | ||
685 : | } | ||
686 : | |||
687 : | new Float:tmpvec[3], Float:tmpvec2[3] | ||
688 : | |||
689 : | new Float:dr_tc[3] | ||
690 : | dr_tc[0] = ( dmaxs[0] + dmins[0] ) / 2 | ||
691 : | dr_tc[1] = ( dmaxs[1] + dmins[1] ) / 2 | ||
692 : | dr_tc[2] = dmaxs[2] | ||
693 : | |||
694 : | tmpvec[0] = ( dmaxs[0] + dmins[0] ) / 2 | ||
695 : | tmpvec[1] = dmaxs[1] + 20 | ||
696 : | tmpvec[2] = dmaxs[2] + 20 | ||
697 : | trace_line( ent, dr_tc, tmpvec, tmpvec2 ) | ||
698 : | if( !trace_hull( tmpvec, HULL_HUMAN ) && tmpvec2[2] == tmpvec[2] ) | ||
699 : | door_tp_pos[i] = tmpvec | ||
700 : | else | ||
701 : | { | ||
702 : | tmpvec[1] = dmins[1] - 20 | ||
703 : | trace_line( ent, dr_tc, tmpvec, tmpvec2 ) | ||
704 : | if( !trace_hull( tmpvec, HULL_HUMAN ) && tmpvec2[2] == tmpvec[2] ) | ||
705 : | door_tp_pos[i] = tmpvec | ||
706 : | else | ||
707 : | { | ||
708 : | tmpvec[0] = dmaxs[0] + 20 | ||
709 : | tmpvec[1] = ( dmaxs[1] + dmins[1] ) / 2 | ||
710 : | trace_line( ent, dr_tc, tmpvec, tmpvec2 ) | ||
711 : | if( !trace_hull( tmpvec, HULL_HUMAN ) && tmpvec2[2] == tmpvec[2] ) | ||
712 : | door_tp_pos[i] = tmpvec | ||
713 : | else | ||
714 : | { | ||
715 : | tmpvec[0] = dmins[0] - 20 | ||
716 : | door_tp_pos[i] = tmpvec | ||
717 : | } | ||
718 : | } | ||
719 : | } | ||
720 : | } | ||
721 : | } | ||
722 : | } | ||
723 : | |||
724 : | //Store ent id's for start/fin buttons, some maps change target value after timer starts | ||
725 : | ent = find_ent_by_class( -1, "func_button" ) | ||
726 : | while( ent > 0 ) | ||
727 : | { | ||
728 : | entity_get_string( ent, EV_SZ_target, tmpstr, 32 ) | ||
729 : | |||
730 : | if( equal( tmpstr, "counter_start" ) || equal( tmpstr, "clockstartbutton" ) | ||
731 : | || equal( tmpstr, "firsttimerelay" ) || equal( tmpstr, "gogogo" ) ) | ||
732 : | { | ||
733 : | ST_BTNS[ST_BTN_CNT] = ent | ||
734 : | ST_BTN_CNT++ | ||
735 : | } | ||
736 : | else if( equal( tmpstr, "counter_off" ) || equal( tmpstr, "clockstopbutton" ) | ||
737 : | || equal( tmpstr, "clockstop" ) || equal( tmpstr, "stop_counter" ) ) | ||
738 : | { | ||
739 : | FN_BTNS[FN_BTN_CNT] = ent | ||
740 : | FN_BTN_CNT++ | ||
741 : | } | ||
742 : | |||
743 : | ent = find_ent_by_class( ent, "func_button" ) | ||
744 : | } | ||
745 : | |||
746 : | if( ST_BTN_CNT /*|| get_pcvar_num( p_climb )*/ ) | ||
747 : | { | ||
748 : | get_brush_entity_origin( ST_BTNS[0], start_tp_orig ) | ||
749 : | |||
750 : | set_pcvar_num( p_teambalance, 0 ) | ||
751 : | set_pcvar_num( p_limitteams, 0 ) | ||
752 : | |||
753 : | set_cvar_num( "sv_restartround", 1 )//reset timer built into map | ||
754 : | set_cvar_num( "sv_gravity", 800 ) | ||
755 : | set_pcvar_num( p_climb, 1 ) | ||
756 : | |||
757 : | remove_entity_name("player_weaponstrip") | ||
758 : | remove_entity_name("armoury_entity") | ||
759 : | remove_entity_name("info_player_deathmatch") | ||
760 : | remove_entity_name("game_player_equip")//Remove map built in spawn weapons | ||
761 : | |||
762 : | //Remove func_breakables with < 9999 hp | ||
763 : | ent = find_ent_by_class( -1, "func_breakable" ) | ||
764 : | while( ent > 0 ) | ||
765 : | { | ||
766 : | tmpflt = entity_get_float( ent, EV_FL_health ) | ||
767 : | if( tmpflt < 9999 ) remove_entity( ent ) | ||
768 : | ent = find_ent_by_class( ent, "func_breakable" ) | ||
769 : | } | ||
770 : | |||
771 : | //Remove neg dmg func_door that aren't targeted by a button | ||
772 : | ent=find_ent_by_class(-1,"func_door") | ||
773 : | while(ent>0) | ||
774 : | { | ||
775 : | tmpflt=entity_get_float(ent,EV_FL_dmg) | ||
776 : | if(tmpflt<0) | ||
777 : | { | ||
778 : | hp=floatround(tmpflt)//record hp for auto heal | ||
779 : | entity_get_string( ent, EV_SZ_targetname, tmpstr, 32 ) | ||
780 : | if(strlen(tmpstr)) | ||
781 : | { | ||
782 : | ent2=find_ent_by_target(-1,tmpstr) | ||
783 : | //entity_get_string(ent2,EV_SZ_classname,tmpstr,32) | ||
784 : | //if(!equal("func_button",tmpstr)){ | ||
785 : | remove_entity(ent2) | ||
786 : | } | ||
787 : | remove_entity(ent) | ||
788 : | //} | ||
789 : | //if(!strlen(tmpstr))remove_entity(ent) | ||
790 : | //ent=-1 | ||
791 : | } | ||
792 : | ent=find_ent_by_class(ent,"func_door") | ||
793 : | } | ||
794 : | |||
795 : | if( hp < 0 ) hp = 511 | ||
796 : | //Disable climb auto heal if there is a neg dmg trigger hurt | ||
797 : | else | ||
798 : | { | ||
799 : | ent=find_ent_by_class(-1,"trigger_hurt") | ||
800 : | while(ent>0){ | ||
801 : | tmpflt=entity_get_float(ent,EV_FL_dmg) | ||
802 : | if(tmpflt<0){ | ||
803 : | hp=0 | ||
804 : | break | ||
805 : | } | ||
806 : | ent=find_ent_by_class(ent,"trigger_hurt") | ||
807 : | } | ||
808 : | } | ||
809 : | |||
810 : | //If Cvar set, set func_water ents to no draw, helps many peoples FPS | ||
811 : | if( get_pcvar_num( p_water_nodraw ) ) | ||
812 : | { | ||
813 : | ent = find_ent_by_class( -1, "func_water" ) | ||
814 : | while( ent > 0 ) | ||
815 : | { | ||
816 : | set_entity_visibility( ent, 0 ) | ||
817 : | ent=find_ent_by_class( ent, "func_water" ) | ||
818 : | } | ||
819 : | } | ||
820 : | |||
821 : | //Remove map built in start button sounds | ||
822 : | ent = find_ent_by_class( -1, "ambient_generic" ) | ||
823 : | while( ent > 0 ) | ||
824 : | { | ||
825 : | entity_get_string( ent, EV_SZ_targetname, tmpstr, 32 ) | ||
826 : | if( equal( tmpstr, "counter_start" ) || equal( tmpstr, "clockstartbutton" ) | ||
827 : | || equal( tmpstr, "firsttimerelay" ) || equal( tmpstr, "gogogo" ) ) | ||
828 : | remove_entity( ent ) | ||
829 : | ent = find_ent_by_class( ent, "ambient_generic" ) | ||
830 : | } | ||
831 : | |||
832 : | //Count original map spawns and remove extra dyn created spawns | ||
833 : | new map_spawns[32][2], map_spawns_count, Float:orig[3] | ||
834 : | ent = find_ent_by_class( -1, "info_player_start" ) | ||
835 : | while( ent > 0 && map_spawns_count < 32 ) | ||
836 : | { | ||
837 : | if( entity_get_int( ent, EV_INT_iuser1 ) != 1 ) | ||
838 : | { | ||
839 : | entity_get_vector( ent, EV_VEC_origin, orig ) | ||
840 : | map_spawns[map_spawns_count][0] = floatround( vector_distance( orig, start_tp_orig ) ) | ||
841 : | map_spawns[map_spawns_count][1] = ent | ||
842 : | map_spawns_count++ | ||
843 : | while( dyn_spawn_count >= 0 ) | ||
844 : | { | ||
845 : | entity_get_string( dyn_spawn_ids[dyn_spawn_count], EV_SZ_classname, tmpstr, 32 ) | ||
846 : | if( equal( tmpstr, "info_player_start" ) && | ||
847 : | entity_get_int( dyn_spawn_ids[dyn_spawn_count], EV_INT_iuser1 ) == 1 ) | ||
848 : | { | ||
849 : | remove_entity( dyn_spawn_ids[dyn_spawn_count] ) | ||
850 : | dyn_spawn_count-- | ||
851 : | break | ||
852 : | } | ||
853 : | else dyn_spawn_count-- | ||
854 : | } | ||
855 : | } | ||
856 : | ent = find_ent_by_class( ent, "info_player_start" ) | ||
857 : | } | ||
858 : | |||
859 : | //Save origin of spawn closest to start | ||
860 : | SortStrings( map_spawns, map_spawns_count ) | ||
861 : | entity_get_vector( map_spawns[0][1], EV_VEC_origin, spawn_tp_orig ) | ||
862 : | |||
863 : | new Float:tmpvec[3], Float:tmpvec2[3] | ||
864 : | tmpvec = start_tp_orig | ||
865 : | |||
866 : | start_tp_orig[2] += 24 | ||
867 : | |||
868 : | start_tp_orig[0] += 40 | ||
869 : | trace_line( ST_BTNS[0], tmpvec, start_tp_orig, tmpvec2 ) | ||
870 : | if( !trace_hull( start_tp_orig, HULL_HUMAN ) && tmpvec2[2] == start_tp_orig[2] ) | ||
871 : | return PLUGIN_CONTINUE | ||
872 : | |||
873 : | start_tp_orig[0] -= 80 | ||
874 : | trace_line( ST_BTNS[0], tmpvec, start_tp_orig, tmpvec2 ) | ||
875 : | if( !trace_hull( start_tp_orig, HULL_HUMAN ) && tmpvec2[2] == start_tp_orig[2] ) | ||
876 : | return PLUGIN_CONTINUE | ||
877 : | |||
878 : | start_tp_orig[0] += 40 | ||
879 : | start_tp_orig[1] += 40 | ||
880 : | trace_line( ST_BTNS[0], tmpvec, start_tp_orig, tmpvec2 ) | ||
881 : | if( !trace_hull( start_tp_orig, HULL_HUMAN ) && tmpvec2[2] == start_tp_orig[2] ) | ||
882 : | return PLUGIN_CONTINUE | ||
883 : | |||
884 : | start_tp_orig[1] -= 80 | ||
885 : | trace_line( ST_BTNS[0], tmpvec, start_tp_orig, tmpvec2 ) | ||
886 : | if( !trace_hull( start_tp_orig, HULL_HUMAN ) && tmpvec2[2] == start_tp_orig[2] ) | ||
887 : | return PLUGIN_CONTINUE | ||
888 : | |||
889 : | start_tp_orig = spawn_tp_orig | ||
890 : | } | ||
891 : | else | ||
892 : | {//if not kz map remove dyn created spawns | ||
893 : | while( dyn_spawn_count >= 0 ) | ||
894 : | { | ||
895 : | ent = dyn_spawn_ids[dyn_spawn_count] | ||
896 : | entity_get_string( ent, EV_SZ_classname, tmpstr, 32 ) | ||
897 : | //entity_get_string(dyn_spawn_ids[i],EV_SZ_classname,tmpstr,32) | ||
898 : | if( equal( tmpstr, "info_player_start" ) && entity_get_int( ent, EV_INT_iuser1 ) == 1 ) | ||
899 : | remove_entity(ent) | ||
900 : | dyn_spawn_count-- | ||
901 : | } | ||
902 : | } | ||
903 : | return PLUGIN_CONTINUE | ||
904 : | } | ||
905 : | |||
906 : | public plugin_precache( ) | ||
907 : | { | ||
908 : | beam_sprite = precache_model( "sprites/laserbeam.spr" ) | ||
909 : | return PLUGIN_CONTINUE | ||
910 : | } | ||
911 : | |||
912 : | stock Float:float_clamp( Float:curval, Float:minval, Float:maxval ) | ||
913 : | { | ||
914 : | if( curval < minval )return minval | ||
915 : | if( curval > maxval )return maxval | ||
916 : | return curval | ||
917 : | } | ||
918 : | |||
919 : | //////////////////////////////////////////////////////////////////////////////// | ||
920 : | // End: Init forwards | ||
921 : | //////////////////////////////////////////////////////////////////////////////// | ||
922 : | public client_putinserver( id ) | ||
923 : | { | ||
924 : | if( get_pcvar_num( p_climb ) && !is_user_bot( id ) && !is_user_hltv( id ) ) | ||
925 : | { | ||
926 : | timer[id-1][TMR_DBUSER] = 0 | ||
927 : | |||
928 : | //search steamid to position reference for match | ||
929 : | new searchid[32] | ||
930 : | get_user_authid( id, searchid, 31 ) | ||
931 : | for(new i = 0; i < 32; i++ ) | ||
932 : | if( equal( searchid, steamid[i] ) ) | ||
933 : | {//load origins & timer array if match found | ||
934 : | origins[id-1] = originssave[i] | ||
935 : | timer[id-1] = timersave[i] | ||
936 : | return PLUGIN_CONTINUE | ||
937 : | } | ||
938 : | |||
939 : | timer[id-1][TMR_CFLAGS] += CF_STOP | ||
940 : | |||
941 : | new ida[1] | ||
942 : | ida[0]=id | ||
943 : | |||
944 : | if( CLIMB_SAVE && timer[id-1][TMR_DBUSER] < 1 ) | ||
945 : | set_task( 5.0, "auto_login", 0, ida, 1 ) | ||
946 : | } | ||
947 : | return PLUGIN_CONTINUE | ||
948 : | } | ||
949 : | |||
950 : | public client_disconnect( id ) | ||
951 : | { | ||
952 : | if( get_pcvar_num(p_climb) ) | ||
953 : | { | ||
954 : | savepos++ | ||
955 : | if( savepos == 31 ) savepos = 0 | ||
956 : | |||
957 : | new saveid[32] | ||
958 : | get_user_authid( id, saveid, 32 ) | ||
959 : | |||
960 : | //erase previous save if exists | ||
961 : | for( new i=0; i<32; i++ ) | ||
962 : | if( equal( saveid, steamid[i] ) ) steamid[i] = "" | ||
963 : | |||
964 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) change_status( id, CF_PAUSE ) //Pause if running | ||
965 : | steamid[savepos] = saveid //save steamid to position reference | ||
966 : | originssave[savepos] = origins[id-1] //save origins | ||
967 : | timersave[savepos] = timer[id-1] //save timer array | ||
968 : | |||
969 : | //clear data for new client in that slot | ||
970 : | for( new i = 0; i < 48; i++ ) origins[id-1][i] = 0.0 | ||
971 : | for( new i = 0; i < 14; i++ ) timer[id-1][i] = 0 | ||
972 : | hooked[id] = 0 | ||
973 : | sortcssb( ) //Update frags to reorder scoreboard | ||
974 : | } | ||
975 : | return PLUGIN_CONTINUE | ||
976 : | } | ||
977 : | //////////////////////////////////////////////////////////////////////////////// | ||
978 : | // Start: CP/GC functions | ||
979 : | //////////////////////////////////////////////////////////////////////////////// | ||
980 : | public set_cpgc_timeout( id ) | ||
981 : | { | ||
982 : | //Set timeout flag and set_task to clear it | ||
983 : | new ida[1] | ||
984 : | ida[0] = id | ||
985 : | time_stamps[id-1][TS_CPGC] = 1 | ||
986 : | set_task( CPGC_TIMEOUT, "clear_cpgc_timeout", _, ida, 1 ) | ||
987 : | } | ||
988 : | |||
989 : | public clear_cpgc_timeout( ida[1] ) | ||
990 : | return time_stamps[ida[0]-1][TS_CPGC]=0 | ||
991 : | |||
992 : | //Save a checkpoint | ||
993 : | public check( id ) | ||
994 : | { | ||
995 : | if( get_pcvar_num( p_climb ) && isalive( id ) && notpaused( id ) ) | ||
996 : | { | ||
997 : | new cpprice = get_pcvar_num( p_cpprice ) | ||
998 : | if( cpprice > 0 ) | ||
999 : | { | ||
1000 : | new cash = cs_get_user_money(id) | ||
1001 : | if( cpprice > cash ) | ||
1002 : | { | ||
1003 : | clmsg(id,"You don't have enough cash for more checkpoints.") | ||
1004 : | client_print(id,print_chat,"You don't have enough cash for more checkpoints.") | ||
1005 : | return PLUGIN_HANDLED | ||
1006 : | } | ||
1007 : | cs_set_user_money( id, cash - cpprice ) | ||
1008 : | } | ||
1009 : | if( !hooked[id] )//If they're not hooked... | ||
1010 : | { | ||
1011 : | new Float:vel[3] | ||
1012 : | entity_get_vector( id, EV_VEC_velocity, vel ) | ||
1013 : | if( vel[2] >= 0 )//and they're not falling... | ||
1014 : | { | ||
1015 : | new Float:coords[3] | ||
1016 : | entity_get_vector( id, EV_VEC_origin, coords ) | ||
1017 : | if( coords[0] || coords[1] || coords[2] )//and they're not at world origin, then save checkpoint | ||
1018 : | { | ||
1019 : | if( timer[id-1][TMR_CPPOS] > 0 ) timer[id-1][TMR_CPPOS]-- | ||
1020 : | new cppos = timer[id-1][TMR_CPPOS] * 4 | ||
1021 : | |||
1022 : | //If cp position is 0 then bump all cps back before saving. | ||
1023 : | if( !cppos ) for(new i=39; i>3 ;i-- ) origins[id-1][i] = origins[id-1][i-4] | ||
1024 : | |||
1025 : | for( new i=0; i<3; i++ ) origins[id-1][cppos + i] = coords[i] | ||
1026 : | origins[id-1][3]=entity_get_float(id, EV_FL_gravity) | ||
1027 : | |||
1028 : | new msg[100]="Checkpoint saved." | ||
1029 : | if(timer[id-1][TMR_CFLAGS]&CF_START){ | ||
1030 : | timer[id-1][TMR_CNTCPS]++ | ||
1031 : | formatex(msg,99,"Checkpoint saved. (%d CPS/ %d GCS/ %d Boosts)",timer[id-1][TMR_CNTCPS],timer[id-1][TMR_CNTGCS],timer[id-1][TMR_CNTBST]) | ||
1032 : | } | ||
1033 : | clmsg(id,msg) | ||
1034 : | |||
1035 : | set_cpgc_timeout( id ) | ||
1036 : | } | ||
1037 : | else clmsg(id,"Can not save checkpoint at current location.") | ||
1038 : | } | ||
1039 : | else clmsg(id,"You can't make checkpoints while falling.") | ||
1040 : | } | ||
1041 : | else clmsg(id,"You can't make checkpoints while using hook.") | ||
1042 : | } | ||
1043 : | return PLUGIN_HANDLED | ||
1044 : | } | ||
1045 : | |||
1046 : | //Go to most recent checkpoint | ||
1047 : | public gocheck( id ) | ||
1048 : | { | ||
1049 : | if( get_pcvar_num( p_climb ) && isalive( id ) && notpaused( id ) && !time_stamps[id-1][TS_CPGC] ) | ||
1050 : | { | ||
1051 : | if( origins[id-1][0] || origins[id-1][1] || origins[id-1][2] ) | ||
1052 : | { | ||
1053 : | new Float:coords[3] | ||
1054 : | |||
1055 : | //Store ungocheck data | ||
1056 : | entity_get_vector( id, EV_VEC_origin, coords ) | ||
1057 : | for( new i=0; i<3; i++ ) origins[id-1][ORIG_UNGC + i] = coords[i] | ||
1058 : | origins[id-1][ORIG_UNGC + 3] = entity_get_float( id, EV_FL_gravity ) | ||
1059 : | |||
1060 : | //Do gocheck | ||
1061 : | new cppos = timer[id-1][TMR_CPPOS] * 4 | ||
1062 : | for( new i=0; i<3; i++ ) coords[i] = origins[id-1][cppos + i] | ||
1063 : | entity_set_float( id, EV_FL_gravity, origins[id-1][3] ) | ||
1064 : | teleport( id, coords ) | ||
1065 : | |||
1066 : | new msg[100]="Checkpoint restored." | ||
1067 : | if(timer[id-1][TMR_CFLAGS]&CF_START){ | ||
1068 : | timer[id-1][TMR_CNTGCS]++ | ||
1069 : | formatex(msg,99,"Checkpoint restored. (%d CPS/ %d GCS/ %d Boosts)",timer[id-1][TMR_CNTCPS],timer[id-1][TMR_CNTGCS],timer[id-1][TMR_CNTBST]) | ||
1070 : | } | ||
1071 : | clmsg(id,msg) | ||
1072 : | |||
1073 : | set_cpgc_timeout( id ) | ||
1074 : | } | ||
1075 : | else{ | ||
1076 : | clmsg(id,"You must make a checkpoint first.") | ||
1077 : | return 0 | ||
1078 : | } | ||
1079 : | } | ||
1080 : | return 1 | ||
1081 : | } | ||
1082 : | |||
1083 : | //Undo a gocheck | ||
1084 : | public ungocheck( id ) | ||
1085 : | { | ||
1086 : | if( get_pcvar_num(p_climb) && isalive(id) && notpaused(id) && !time_stamps[id-1][TS_CPGC] ) | ||
1087 : | { | ||
1088 : | if( origins[id-1][ORIG_UNGC] || origins[id-1][ORIG_UNGC + 1] || origins[id-1][ORIG_UNGC + 2]) | ||
1089 : | { | ||
1090 : | new Float:coords[3] | ||
1091 : | for( new i=0; i<3; i++ )coords[i] = origins[id-1][ORIG_UNGC + i] | ||
1092 : | teleport( id, coords ) | ||
1093 : | entity_set_float( id, EV_FL_gravity, origins[id-1][ORIG_UNGC + 3] ) | ||
1094 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) timer[id-1][TMR_CNTGCS]++ | ||
1095 : | clmsg( id, "You have been ungochecked." ) | ||
1096 : | |||
1097 : | set_cpgc_timeout( id ) | ||
1098 : | } | ||
1099 : | else clmsg(id,"Cannot ungocheck.") | ||
1100 : | } | ||
1101 : | } | ||
1102 : | |||
1103 : | //Cycle back through CPs | ||
1104 : | public cp_back( id ) | ||
1105 : | { | ||
1106 : | if( get_pcvar_num( p_climb ) && isalive( id ) && notpaused( id ) && !time_stamps[id-1][TS_CPGC] ) | ||
1107 : | { | ||
1108 : | if( timer[id-1][TMR_CPPOS] < 9 ) timer[id-1][TMR_CPPOS]++ | ||
1109 : | new cppos = timer[id-1][TMR_CPPOS] * 4 | ||
1110 : | if( origins[id-1][cppos] || origins[id-1][cppos + 1] || origins[id-1][cppos + 2] ) | ||
1111 : | { | ||
1112 : | new Float:coords[3] | ||
1113 : | //for( new i=0; i<36; i++ ) origins[id-1][i] = origins[id-1][i+4] | ||
1114 : | for( new i=0; i<3; i++ ) coords[i] = origins[id-1][cppos + i] | ||
1115 : | entity_set_float( id, EV_FL_gravity, origins[id-1][cppos + ORIG_GRAV] ) | ||
1116 : | teleport( id, coords ) | ||
1117 : | |||
1118 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) timer[id-1][TMR_CNTGCS]++ | ||
1119 : | |||
1120 : | /*new msg[100]="Previous checkpoint restored." | ||
1121 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) | ||
1122 : | { | ||
1123 : | timer[id-1][TMR_CNTCPS]-- | ||
1124 : | formatex( msg, 99, "Previous checkpoint restored. (%d CPS/ %d GCS/ %d Boosts)",\ | ||
1125 : | timer[id-1][TMR_CNTCPS], timer[id-1][TMR_CNTGCS], timer[id-1][TMR_CNTBST] ) | ||
1126 : | } | ||
1127 : | clmsg( id, msg )*/ | ||
1128 : | |||
1129 : | /*new cpprice = get_pcvar_num( p_cpprice ) | ||
1130 : | if( cpprice > 0 ) | ||
1131 : | { | ||
1132 : | new cash = cs_get_user_money( id ) | ||
1133 : | cs_set_user_money( id, cash + cpprice ) | ||
1134 : | }*/ | ||
1135 : | |||
1136 : | set_cpgc_timeout( id ) | ||
1137 : | } | ||
1138 : | else | ||
1139 : | { | ||
1140 : | clmsg(id,"You have no previous checkpoints remaining.") | ||
1141 : | timer[id-1][TMR_CPPOS]-- | ||
1142 : | } | ||
1143 : | } | ||
1144 : | return PLUGIN_HANDLED | ||
1145 : | } | ||
1146 : | |||
1147 : | //Cycle forward through CPs | ||
1148 : | public cp_forward( id ) | ||
1149 : | { | ||
1150 : | if( get_pcvar_num( p_climb ) && isalive( id ) && notpaused( id ) && !time_stamps[id-1][TS_CPGC] && timer[id-1][TMR_CPPOS] > 0 ) | ||
1151 : | { | ||
1152 : | timer[id-1][TMR_CPPOS]-- | ||
1153 : | new cppos = timer[id-1][TMR_CPPOS] * 4 | ||
1154 : | |||
1155 : | new Float:coords[3] | ||
1156 : | for( new i=0; i<3; i++ ) coords[i] = origins[id-1][cppos + i] | ||
1157 : | entity_set_float( id, EV_FL_gravity, origins[id-1][cppos + ORIG_GRAV] ) | ||
1158 : | teleport( id, coords ) | ||
1159 : | |||
1160 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) timer[id-1][TMR_CNTGCS]++ | ||
1161 : | |||
1162 : | set_cpgc_timeout( id ) | ||
1163 : | } | ||
1164 : | return PLUGIN_HANDLED | ||
1165 : | } | ||
1166 : | //////////////////////////////////////////////////////////////////////////////// | ||
1167 : | // End: CP/GC functions | ||
1168 : | //////////////////////////////////////////////////////////////////////////////// | ||
1169 : | public change_status( id, newstat ) | ||
1170 : | { | ||
1171 : | new cflags_old = timer[id-1][TMR_CFLAGS] | ||
1172 : | new cflags_new = cflags_old & ~CF_STATUSFLAGS | ||
1173 : | |||
1174 : | if( newstat & CF_PAUSE ) | ||
1175 : | { | ||
1176 : | if( cflags_old & CF_PAUSE ) //unpause | ||
1177 : | { | ||
1178 : | cflags_new += CF_START | ||
1179 : | timer[id-1][TMR_STARTD] = get_systime() - timer[id-1][TMR_STARTD] | ||
1180 : | set_entity_flags( id, FL_FROZEN, 0 ) | ||
1181 : | unsolid( id ) | ||
1182 : | entity_set_float( id, EV_FL_gravity, origins[id-1][ORIG_PAUS + ORIG_GRAV] ) | ||
1183 : | clmsg( id, "UNPAUSED" ) | ||
1184 : | sfexec( id, 2 ) | ||
1185 : | } | ||
1186 : | else if( cflags_old & CF_START ) //pause | ||
1187 : | { | ||
1188 : | timer[id-1][TMR_STARTD] = get_systime() - timer[id-1][TMR_STARTD] | ||
1189 : | cl_pause( id ) | ||
1190 : | cflags_new += CF_PAUSE | ||
1191 : | } | ||
1192 : | else | ||
1193 : | { | ||
1194 : | clmsg( id, "You must start the timer before you can pause." ) | ||
1195 : | cflags_new = cflags_old | ||
1196 : | } | ||
1197 : | } | ||
1198 : | else cflags_new += newstat | ||
1199 : | timer[id-1][TMR_CFLAGS] = cflags_new | ||
1200 : | return PLUGIN_HANDLED | ||
1201 : | } | ||
1202 : | |||
1203 : | public cl_pause( id ) | ||
1204 : | { | ||
1205 : | if( is_climber_alive( id ) ) | ||
1206 : | { | ||
1207 : | unsolid( id ) | ||
1208 : | set_rendering( id, kRenderFxGlowShell, 0, 0, 255, kRenderTransColor, 1 ) | ||
1209 : | set_entity_flags( id, FL_FROZEN, 1 ) | ||
1210 : | clmsg( id, "PAUSED - say '/unpause' to resume." ) | ||
1211 : | } | ||
1212 : | return PLUGIN_HANDLED | ||
1213 : | } | ||
1214 : | |||
1215 : | public stop( id ) | ||
1216 : | { | ||
1217 : | if( get_pcvar_num( p_climb ) && timer[id-1][TMR_CFLAGS] & CF_START ) | ||
1218 : | { | ||
1219 : | change_status( id, CF_STOP ) | ||
1220 : | heal(id) | ||
1221 : | //Erase start/finish time stamps, prevents crazy number on scoreboard | ||
1222 : | timer[id-1][TMR_STARTD]=0 | ||
1223 : | timer[id-1][TMR_FINISH]=0 | ||
1224 : | |||
1225 : | sfexec(id,4) //Execute commands from start/finish config | ||
1226 : | } | ||
1227 : | return PLUGIN_HANDLED | ||
1228 : | } | ||
1229 : | |||
1230 : | //Start borrowed code : from KCE's attack blocking tutorial (http://forums.alliedmods.net/showthread.php?t=41265) | ||
1231 : | public PostUpdateClientData( id, sendweapons, cd_handle ) | ||
1232 : | { | ||
1233 : | if( get_pcvar_num( p_climb ) && is_climber_alive( id ) ) | ||
1234 : | { | ||
1235 : | new wpn, clip, ammo | ||
1236 : | wpn = get_user_weapon( id, clip, ammo ) | ||
1237 : | if( wpn == CSW_KNIFE ) | ||
1238 : | { | ||
1239 : | new remain = check_timeout( 0, time_stamps[id-1][TS_KNIFE], KNIFE_TIMEOUT, _, 1 ) | ||
1240 : | if( remain ) | ||
1241 : | { | ||
1242 : | set_cd(cd_handle, CD_flNextAttack, halflife_time() + remain ) | ||
1243 : | return FMRES_HANDLED | ||
1244 : | } | ||
1245 : | } | ||
1246 : | } | ||
1247 : | return FMRES_IGNORED | ||
1248 : | } | ||
1249 : | //End borrowed code | ||
1250 : | |||
1251 : | public CurWeapon( msg_id, msg_dest, id ) | ||
1252 : | { | ||
1253 : | new wpn = get_msg_arg_int( 2 ) | ||
1254 : | if( !get_pcvar_num( p_climb ) || !( 0 < wpn <= 30 ) ) | ||
1255 : | return PLUGIN_CONTINUE | ||
1256 : | |||
1257 : | static client_oldwpn[32] | ||
1258 : | if( wpn != client_oldwpn[id-1] ) | ||
1259 : | rank_mod_update( id ) | ||
1260 : | |||
1261 : | client_oldwpn[id-1] = wpn | ||
1262 : | |||
1263 : | //If it's a gun, update pack and clip ammo & silencer | ||
1264 : | if( strlen( WPN_CLASS[wpn-1] ) ) | ||
1265 : | { | ||
1266 : | new wpn_id = find_ent_by_owner( -1, WPN_CLASS[wpn-1], id ) | ||
1267 : | if( !wpn_id ) return PLUGIN_CONTINUE | ||
1268 : | |||
1269 : | new clip = get_msg_arg_int( 3 ) | ||
1270 : | new maxammo = 2 | ||
1271 : | |||
1272 : | //Force silencer w/o animation | ||
1273 : | if( wpn == CSW_USP || wpn == CSW_M4A1 || wpn == CSW_TMP ) | ||
1274 : | { | ||
1275 : | if( wpn != CSW_TMP ) cs_set_weapon_silen( wpn_id, 1, 0 ) | ||
1276 : | maxammo = 10 | ||
1277 : | |||
1278 : | //Unlimited ammo for VIPs | ||
1279 : | if( get_user_flags(id) & VIP ) | ||
1280 : | { | ||
1281 : | cs_set_weapon_ammo( wpn_id, 12 ) | ||
1282 : | if( clip != 12 )return PLUGIN_HANDLED | ||
1283 : | set_msg_arg_int( 3, ARG_BYTE, 12 ) | ||
1284 : | return PLUGIN_CONTINUE | ||
1285 : | } | ||
1286 : | } | ||
1287 : | |||
1288 : | //Set clip and backpack ammo | ||
1289 : | cs_set_user_bpammo( id, wpn, maxammo - clip ) | ||
1290 : | if( clip > maxammo ) | ||
1291 : | { | ||
1292 : | set_msg_arg_int( 3, ARG_BYTE, maxammo ) | ||
1293 : | cs_set_weapon_ammo( wpn_id, maxammo ) | ||
1294 : | } | ||
1295 : | } | ||
1296 : | |||
1297 : | return PLUGIN_CONTINUE | ||
1298 : | } | ||
1299 : | |||
1300 : | public rank_mod_update( id ) | ||
1301 : | { | ||
1302 : | new rank, maxspeed = pev( id, pev_maxspeed ) | ||
1303 : | switch( maxspeed ) | ||
1304 : | { | ||
1305 : | case 210: | ||
1306 : | rank = 0 | ||
1307 : | case 220: | ||
1308 : | rank = 1 | ||
1309 : | case 230: | ||
1310 : | rank = 2 | ||
1311 : | case 235: | ||
1312 : | rank = 3 | ||
1313 : | case 240: | ||
1314 : | rank = 4 | ||
1315 : | case 245: | ||
1316 : | rank = 5 | ||
1317 : | case 250: | ||
1318 : | rank = 6 | ||
1319 : | case 260: | ||
1320 : | rank = 7 | ||
1321 : | } | ||
1322 : | |||
1323 : | if( rank > timer[id-1][TMR_CNTWPN] ) | ||
1324 : | timer[id-1][TMR_CNTWPN] = rank | ||
1325 : | |||
1326 : | new msg[100] | ||
1327 : | format( msg, 99, "Weapon Max Speed: %d^nRank Modifier: %d", maxspeed, rank ) | ||
1328 : | clmsg( id, msg ) | ||
1329 : | } | ||
1330 : | |||
1331 : | public get_weapon_name( wpn_rank, ret_name[], len ) | ||
1332 : | { | ||
1333 : | new name[21] | ||
1334 : | switch( wpn_rank ) | ||
1335 : | { | ||
1336 : | case 0: | ||
1337 : | name = "AWP" | ||
1338 : | case 1: | ||
1339 : | name = "Para" | ||
1340 : | case 2: | ||
1341 : | name = "M4A1" | ||
1342 : | case 3: | ||
1343 : | name = "SG552" | ||
1344 : | case 4: | ||
1345 : | name = "Famas" | ||
1346 : | case 5: | ||
1347 : | name = "P90" | ||
1348 : | case 6: | ||
1349 : | name = "USP" | ||
1350 : | case 7: | ||
1351 : | name = "Scout" | ||
1352 : | } | ||
1353 : | formatex( ret_name, len, name ) | ||
1354 : | } | ||
1355 : | |||
1356 : | public bot_msg_block(msg_id,msg_dest,id) | ||
1357 : | { | ||
1358 : | if(get_pcvar_num(p_climb)&&is_user_bot(id))return PLUGIN_HANDLED | ||
1359 : | return PLUGIN_CONTINUE | ||
1360 : | } | ||
1361 : | |||
1362 : | public DeathMsg( ) | ||
1363 : | {//Respawn client when they die unless switching to spec | ||
1364 : | if( get_pcvar_num( p_climb ) ) | ||
1365 : | { | ||
1366 : | new id = read_data(2) | ||
1367 : | set_entity_flags( id, FL_FROZEN, 0 )//Unfreeze in case of switch to spectator. | ||
1368 : | new ida[1] | ||
1369 : | ida[0]=id | ||
1370 : | if(task_exists(100+id))remove_task(100+id) | ||
1371 : | if(isct(id)){ | ||
1372 : | set_task(0.2,"respawn_task",100+id,ida,1) | ||
1373 : | } | ||
1374 : | } | ||
1375 : | return PLUGIN_HANDLED | ||
1376 : | } | ||
1377 : | |||
1378 : | public respawn_task(ida[]){//used by death_msg function | ||
1379 : | new id=ida[0] | ||
1380 : | if( !get_user_team( id ) || is_climber_alive( id ) || !isct( id ) ) | ||
1381 : | return PLUGIN_HANDLED | ||
1382 : | //cs_user_spawn(id) | ||
1383 : | climb_user_spawn( id, 0 ) | ||
1384 : | return PLUGIN_HANDLED | ||
1385 : | } | ||
1386 : | |||
1387 : | public frespawn( id ) | ||
1388 : | { | ||
1389 : | stop(id) | ||
1390 : | if( is_climber_alive( id ) ) teleport( id, spawn_tp_orig ) | ||
1391 : | else if( !check_timeout( id, time_stamps[id-1][TS_SPAWN], SPAWN_TIMEOUT ) ) | ||
1392 : | { | ||
1393 : | //if( get_user_team ( id ) == 3 ) cs_set_user_team( id, 2 ) | ||
1394 : | //cs_user_spawn( id ) | ||
1395 : | climb_user_spawn( id ) | ||
1396 : | } | ||
1397 : | return PLUGIN_HANDLED | ||
1398 : | } | ||
1399 : | |||
1400 : | public tp_start_btn( id ) | ||
1401 : | { | ||
1402 : | if ( !is_climber_alive( id ) ) | ||
1403 : | { | ||
1404 : | //if( get_user_team ( id ) == 3 ) cs_set_user_team( id, 2 ) | ||
1405 : | //cs_user_spawn( id ) | ||
1406 : | climb_user_spawn( id ) | ||
1407 : | } | ||
1408 : | if( teleport( id, start_tp_orig ) ) return | ||
1409 : | clmsg( id, "This map doesn't have a start button." ) | ||
1410 : | } | ||
1411 : | |||
1412 : | stock climb_user_spawn( id, give_wpns = 1 ) | ||
1413 : | { | ||
1414 : | cs_user_spawn( id ) | ||
1415 : | |||
1416 : | set_pev( id, pev_movetype, MOVETYPE_WALK ) | ||
1417 : | set_pev( id, pev_solid, SOLID_BBOX ) | ||
1418 : | set_pev( id, pev_effects, 0 ) | ||
1419 : | set_pev( id, pev_deadflag, DEAD_NO ) | ||
1420 : | set_pev( id, pev_takedamage, DAMAGE_AIM ) | ||
1421 : | set_pev( id, pev_health, 100 ) | ||
1422 : | |||
1423 : | cs_set_user_team( id, 2 ) | ||
1424 : | |||
1425 : | if( give_wpns ) | ||
1426 : | { | ||
1427 : | give_item( id, "weapon_knife" ) | ||
1428 : | give_item( id, "weapon_usp" ) | ||
1429 : | } | ||
1430 : | } | ||
1431 : | |||
1432 : | public ResetHUD( id ) | ||
1433 : | {//Spawned | ||
1434 : | if( get_pcvar_num( p_climb ) ) | ||
1435 : | { | ||
1436 : | if( !is_user_bot( id ) && !is_user_hltv( id ) ) | ||
1437 : | { | ||
1438 : | flight_icons( id )//redraw flashlight hud icons | ||
1439 : | set_msg_block( SVC_STATUSICON, 2 )//Block buy menu | ||
1440 : | |||
1441 : | if( is_climber_alive( id ) ) | ||
1442 : | { | ||
1443 : | //set_pev( id, pev_movetype, MOVETYPE_WALK ) | ||
1444 : | //cs_set_user_team( id, 2 ) | ||
1445 : | |||
1446 : | heal( id ) | ||
1447 : | sfexec( id, 1 )//Execute commands from start/finish config | ||
1448 : | if( get_user_flags( id ) & VIP ) cs_set_user_scoreattrib( id, 4 )//Show admin as VIP on Scoreboard. | ||
1449 : | |||
1450 : | if( timer[id-1][TMR_CFLAGS] & CF_PAUSE ) | ||
1451 : | {//If they are paused tp to pause spot and freeze them again. | ||
1452 : | new Float:coords[3] | ||
1453 : | for( new i=0; i<3; i++ ) coords[i] = origins[ id - 1 ][ ORIG_PAUS + i ] | ||
1454 : | teleport( id, coords ) | ||
1455 : | cl_pause( id ) | ||
1456 : | } | ||
1457 : | |||
1458 : | //Teleport to cp, start, or primary spawn position | ||
1459 : | else if( origins[ id - 1 ][ 0 ] || origins[ id - 1][ 1 ] || origins[ id - 1 ][ 2 ]) gocheck( id ) | ||
1460 : | else if( !teleport( id, start_tp_orig ) ) teleport( id, spawn_tp_orig ) | ||
1461 : | } | ||
1462 : | } | ||
1463 : | sortcssb( ) | ||
1464 : | } | ||
1465 : | else set_msg_block( SVC_STATUSICON, 0 ) | ||
1466 : | } | ||
1467 : | |||
1468 : | public run_tasks( ) | ||
1469 : | { | ||
1470 : | updatebot( ) | ||
1471 : | check_cvars( ) | ||
1472 : | } | ||
1473 : | |||
1474 : | public updatebot( ) | ||
1475 : | { | ||
1476 : | if(get_pcvar_num(p_climb)) | ||
1477 : | { | ||
1478 : | //new players[32], cl | ||
1479 : | //get_players( players, cl, "ach" ) | ||
1480 : | new id = find_player( "i" ) | ||
1481 : | //if(0<cl<3&&!id){ | ||
1482 : | new cl = get_playersnum( ) | ||
1483 : | if( cl < MAXPLAYERS - 2 && !id ) | ||
1484 : | { | ||
1485 : | //Start borrowed code : from Space Headed's AMXX Bot(bot_api.sma) v0.5.1 | ||
1486 : | new name[32] | ||
1487 : | format( name, 31, "Climb v%s", VERSION ) | ||
1488 : | id = engfunc( EngFunc_CreateFakeClient, name ) | ||
1489 : | if( pev_valid( id ) ) | ||
1490 : | { | ||
1491 : | engfunc( EngFunc_FreeEntPrivateData, id ) | ||
1492 : | dllfunc( MetaFunc_CallGameEntity, "player", id ) | ||
1493 : | set_user_info( id, "rate", "3500" ) | ||
1494 : | set_user_info( id, "cl_updaterate", "25" ) | ||
1495 : | set_user_info( id, "cl_lw", "1" ) | ||
1496 : | set_user_info( id, "cl_lc", "1" ) | ||
1497 : | set_user_info( id, "cl_dlmax", "128" ) | ||
1498 : | set_user_info( id, "cl_righthand", "1" ) | ||
1499 : | set_user_info( id, "_vgui_menus", "0" ) | ||
1500 : | set_user_info( id, "_ah", "0" ) | ||
1501 : | set_user_info( id, "dm", "0" ) | ||
1502 : | set_user_info( id, "tracker", "0" ) | ||
1503 : | set_user_info( id, "friends", "0" ) | ||
1504 : | set_user_info( id, "*bot", "1" ) | ||
1505 : | set_pev( id, pev_flags, pev( id, pev_flags ) | FL_FAKECLIENT ) | ||
1506 : | set_pev( id, pev_colormap, id ) | ||
1507 : | |||
1508 : | new msg[128] | ||
1509 : | dllfunc( DLLFunc_ClientConnect, id, name, "127.0.0.1", msg ) | ||
1510 : | dllfunc( DLLFunc_ClientPutInServer, id ) | ||
1511 : | engfunc( EngFunc_RunPlayerMove, id, Float:{0.0,0.0,0.0}, 0.0, 0.0, 0.0, 0, 0, 76 ) | ||
1512 : | //End borrowed code | ||
1513 : | |||
1514 : | cs_set_user_team( id, 2 ) | ||
1515 : | cs_user_spawn( id ) | ||
1516 : | } | ||
1517 : | } | ||
1518 : | //else if(cl>2&&id)server_cmd("kick #%d",get_user_userid(id)) | ||
1519 : | else if( cl == MAXPLAYERS - 1 && id ) | ||
1520 : | { | ||
1521 : | set_entity_visibility( id, 1 ) | ||
1522 : | server_cmd( "kick #%d", get_user_userid( id ) ) | ||
1523 : | } | ||
1524 : | else if( is_user_bot( id ) && id ) | ||
1525 : | { | ||
1526 : | set_entity_visibility( id, 0 ) | ||
1527 : | entity_set_int( id, EV_INT_solid, SOLID_NOT ) | ||
1528 : | set_pev( id, pev_takedamage, DAMAGE_NO ) | ||
1529 : | entity_set_vector( id, EV_VEC_origin, Float:{999999,999999,999999} ) | ||
1530 : | call_think( id ) | ||
1531 : | } | ||
1532 : | } | ||
1533 : | } | ||
1534 : | |||
1535 : | public check_cvars( ) | ||
1536 : | { | ||
1537 : | static bool:nodraw | ||
1538 : | if( get_pcvar_num( p_water_nodraw ) && !nodraw ) | ||
1539 : | { | ||
1540 : | new ent = find_ent_by_class( -1, "func_water" ) | ||
1541 : | while( ent > 0 ) | ||
1542 : | { | ||
1543 : | set_entity_visibility( ent, 0 ) | ||
1544 : | ent = find_ent_by_class( ent, "func_water" ) | ||
1545 : | } | ||
1546 : | nodraw = true | ||
1547 : | } | ||
1548 : | else if( !get_pcvar_num( p_water_nodraw ) && nodraw ) | ||
1549 : | { | ||
1550 : | new ent = find_ent_by_class( -1, "func_water" ) | ||
1551 : | while( ent > 0 ) | ||
1552 : | { | ||
1553 : | set_entity_visibility( ent, 1 ) | ||
1554 : | ent = find_ent_by_class( ent, "func_water" ) | ||
1555 : | } | ||
1556 : | nodraw = false | ||
1557 : | } | ||
1558 : | } | ||
1559 : | |||
1560 : | //Calculate a timeout, returns time remaining on timeout | ||
1561 : | stock check_timeout( id, &checktime, freq = 1, curtime = -1, nowrite = 0 ) | ||
1562 : | { | ||
1563 : | if( curtime < 0 ) curtime = get_systime( ) | ||
1564 : | |||
1565 : | new dif = checktime - curtime | ||
1566 : | if( dif > 3600 ) checktime = curtime + freq | ||
1567 : | |||
1568 : | if( curtime >= checktime ) | ||
1569 : | { | ||
1570 : | if( !nowrite ) checktime = curtime + freq | ||
1571 : | return 0 | ||
1572 : | } | ||
1573 : | |||
1574 : | new msg[76] | ||
1575 : | if( id > 0) | ||
1576 : | { | ||
1577 : | format( msg, 75, "You must wait %d more seconds to use this command again.", dif ) | ||
1578 : | clmsg( id, msg ) | ||
1579 : | } | ||
1580 : | |||
1581 : | return dif | ||
1582 : | } | ||
1583 : | |||
1584 : | public change_boost( id, newboost ) | ||
1585 : | {//Change Boost flags | ||
1586 : | if( !( cvar_enabled( id, p_boost ) && isalive( id ) ) && notpaused( id ) ) return PLUGIN_HANDLED | ||
1587 : | |||
1588 : | new msg[151], rmflag, cflags = timer[ id - 1 ][ TMR_CFLAGS ] | ||
1589 : | if( cflags & CF_SOLID ) | ||
1590 : | { | ||
1591 : | if( task_exists( 150 + id ) ) remove_task( 150 + id ) | ||
1592 : | rmflag = CF_SOLID | ||
1593 : | msg = "Solid Boost Disabled.^n" | ||
1594 : | } | ||
1595 : | else if( cflags & CF_SUPER_JUMP ) | ||
1596 : | { | ||
1597 : | rmflag = CF_SUPER_JUMP | ||
1598 : | msg = "Super Jump Disabled.^n" | ||
1599 : | } | ||
1600 : | else if( cflags & CF_DOUBLE_JUMP) | ||
1601 : | { | ||
1602 : | rmflag = CF_DOUBLE_JUMP | ||
1603 : | msg = "Double Jump Disabled.^n" | ||
1604 : | } | ||
1605 : | if( rmflag > 0 ) timer[ id - 1 ][ TMR_CFLAGS ] -= rmflag | ||
1606 : | if( !( rmflag & newboost ) && \ | ||
1607 : | !check_timeout( id, time_stamps[id-1][TS_BOOST], BOOST_TIMEOUT, ( cflags & CF_START ? get_climber_time( id ) : get_systime() ) ) ) | ||
1608 : | { | ||
1609 : | if( newboost == CF_SOLID ) | ||
1610 : | { | ||
1611 : | format( msg, 150, "%sSolid Boost Enabled.", msg ) | ||
1612 : | new ida[1] | ||
1613 : | ida[0] = id | ||
1614 : | set_task( 15.0, "solid_boost_timer", 150 + id, ida, 1 ) | ||
1615 : | if( timer[ id - 1 ][ TMR_CFLAGS ] & CF_START ) timer[ id - 1 ][ TMR_CNTBST ]++ | ||
1616 : | } | ||
1617 : | if( newboost == CF_SUPER_JUMP ) format( msg, 150, "%sSuper Jump Enabled.", msg ) | ||
1618 : | if( newboost == CF_DOUBLE_JUMP ) format( msg, 150, "%sDouble Jump Enabled.", msg ) | ||
1619 : | timer[ id - 1 ][ TMR_CFLAGS ] |= newboost | ||
1620 : | } | ||
1621 : | if(strlen(msg))clmsg(id,msg) | ||
1622 : | return PLUGIN_HANDLED | ||
1623 : | } | ||
1624 : | |||
1625 : | //Task to auto disable solid boost after timeout | ||
1626 : | public solid_boost_timer( ida[] ) | ||
1627 : | change_boost( ida[0], CF_SOLID ) | ||
1628 : | |||
1629 : | /*public server_frame( ) | ||
1630 : | {//Semi-clip | ||
1631 : | if( get_pcvar_num( p_climb ) ) | ||
1632 : | { | ||
1633 : | new players[32], bool:skip[32], num, i, j | ||
1634 : | new Float:orig_i[3], Float:orig_j[3] | ||
1635 : | new Float:vel_i[3], Float:vel_iz[3] | ||
1636 : | new id_i, id_j, cflags_i, cflags_j | ||
1637 : | get_players( players, num, "ac" ) | ||
1638 : | for( i = 0; i < num; i++ ) | ||
1639 : | { | ||
1640 : | id_i = players[i] | ||
1641 : | cflags_i = timer[id_i-1][TMR_CFLAGS] | ||
1642 : | |||
1643 : | if( !( cflags_i & CF_PAUSE ) ) | ||
1644 : | { | ||
1645 : | entity_get_vector( id_i, EV_VEC_origin, orig_i ) | ||
1646 : | entity_get_vector( id_i, EV_VEC_velocity, vel_i ) | ||
1647 : | |||
1648 : | vel_iz[0] = vel_i[0] > 0 ? -70.0 : 70.0 | ||
1649 : | vel_iz[1] = vel_i[1] > 0 ? -70.0 : 70.0 | ||
1650 : | vel_iz[2] = vel_i[2] > 0 ? -120.0 : 120.0 | ||
1651 : | |||
1652 : | if( !vel_i[0] ) vel_i[0] = vel_iz[0] * -1 | ||
1653 : | if( !vel_i[1] ) vel_i[1] = vel_iz[1] * -1 | ||
1654 : | if( !vel_i[2] ) vel_i[2] = vel_iz[2] * -1 | ||
1655 : | |||
1656 : | for( j=0; j<num; j++ ) | ||
1657 : | { | ||
1658 : | if( i != j ) | ||
1659 : | { | ||
1660 : | id_j = players[j] | ||
1661 : | cflags_j = timer[id_j-1][TMR_CFLAGS] | ||
1662 : | |||
1663 : | if( ( !( cflags_i & CF_SOLID && cflags_j & CF_SOLID ) || skip[i] ) && !( cflags_j & CF_PAUSE ) ) | ||
1664 : | { | ||
1665 : | entity_get_vector( id_j, EV_VEC_origin, orig_j ) | ||
1666 : | |||
1667 : | if( is_between_f( orig_j[0], orig_i[0] + vel_iz[0], orig_i[0] + vel_i[0] ) && | ||
1668 : | is_between_f( orig_j[1], orig_i[1] + vel_iz[1], orig_i[1] + vel_i[1] ) && | ||
1669 : | is_between_f( orig_j[2], orig_i[2] + vel_iz[2], orig_i[2] + vel_i[2] ) ) | ||
1670 : | { | ||
1671 : | unsolid( id_i ) | ||
1672 : | unsolid( id_j ) | ||
1673 : | skip[i] = true | ||
1674 : | skip[j] = true | ||
1675 : | //maybe reset j first time i runs this, to unsolid anyone they might be boosting with | ||
1676 : | } | ||
1677 : | } | ||
1678 : | } | ||
1679 : | } | ||
1680 : | if( !skip[i] ) solid( id_i ) | ||
1681 : | } | ||
1682 : | } | ||
1683 : | } | ||
1684 : | return PLUGIN_CONTINUE | ||
1685 : | }*/ | ||
1686 : | public server_frame( ) | ||
1687 : | { | ||
1688 : | if( !get_pcvar_num(p_climb) ) | ||
1689 : | return PLUGIN_CONTINUE | ||
1690 : | |||
1691 : | sc_fcount++ | ||
1692 : | if( sc_fcount > 9 ) sc_fcount = 0 | ||
1693 : | |||
1694 : | //Semi-clip | ||
1695 : | new players[32],num,i,j,Float:c1[3],Float:c2[3] | ||
1696 : | new Float:c1z[3],Float:c2z[3] | ||
1697 : | new id_i,id_j,cflags_i,cflags_j | ||
1698 : | get_players(players,num,"ac") | ||
1699 : | //new Float:c1d[3],Float:c2d[3],xyadd,zadd | ||
1700 : | for(i=0;i<num;i++){ | ||
1701 : | id_i=players[i] | ||
1702 : | cflags_i=timer[id_i-1][TMR_CFLAGS] | ||
1703 : | if(!(cflags_i&CF_PAUSE)){ | ||
1704 : | //solid(players[i]) | ||
1705 : | entity_get_vector(id_i,EV_VEC_origin,c1) | ||
1706 : | //entity_get_vector(players[i],EV_VEC_velocity,c1d) | ||
1707 : | c1z[2]=c1[2] | ||
1708 : | c1[2]=0.0 | ||
1709 : | for(j=0;j<num;j++){ | ||
1710 : | id_j=players[j] | ||
1711 : | cflags_j=timer[id_j-1][TMR_CFLAGS] | ||
1712 : | if(!(cflags_j&CF_SOLID)&&i!=j){ | ||
1713 : | entity_get_vector(id_j,EV_VEC_origin,c2) | ||
1714 : | //entity_get_vector(players[j],EV_VEC_velocity,c2d) | ||
1715 : | c2z[2]=c2[2] | ||
1716 : | c2[2]=0.0 | ||
1717 : | if(vector_distance(c1,c2)<90&&vector_distance(c1z,c2z)<110){ | ||
1718 : | if(!(cflags_i&CF_SOLID&&cflags_j&CF_SOLID)){//&&vector_distance(c1,c2)>25&&vector_distance(c1z,c2z)>30)){ | ||
1719 : | unsolid(id_i) | ||
1720 : | unsolid(id_j) | ||
1721 : | j=num | ||
1722 : | } | ||
1723 : | } | ||
1724 : | } | ||
1725 : | if(j+1==num)solid(id_i) | ||
1726 : | } | ||
1727 : | } | ||
1728 : | } | ||
1729 : | return PLUGIN_CONTINUE | ||
1730 : | } | ||
1731 : | |||
1732 : | stock bool:is_between_f( Float:mid, Float:a, Float:b ) | ||
1733 : | { | ||
1734 : | if( a < b && ( a < mid < b ) ) return true | ||
1735 : | if( a > b && ( a > mid > b ) ) return true | ||
1736 : | return false | ||
1737 : | } | ||
1738 : | |||
1739 : | stock Float:vector_z_distance_f( Float:vec1[3], Float:vec2[3] ) | ||
1740 : | { | ||
1741 : | return Float:floatsqroot( ( vec1[2] - vec2[2] ) ^ 2.0 ) | ||
1742 : | } | ||
1743 : | |||
1744 : | stock Float:vector_xy_distance_f( Float:vec1[3], Float:vec2[3] ) | ||
1745 : | { | ||
1746 : | return Float:floatsqroot( ( ( vec1[0] - vec2[0] ) ^ 2.0 ) + ( ( vec1[1] - vec2[1] ) ^ 2.0 ) ) | ||
1747 : | } | ||
1748 : | |||
1749 : | public client_PreThink( id ) | ||
1750 : | { | ||
1751 : | if( !get_pcvar_num( p_climb ) || is_user_bot( id ) || !is_climber_alive( id ) ) | ||
1752 : | return PLUGIN_CONTINUE | ||
1753 : | |||
1754 : | if( sclip[id-1] && sc_fcount == 9 ) entity_set_int( id, EV_INT_solid, SOLID_BBOX ) | ||
1755 : | |||
1756 : | //Detect button use. Replicated from HL SDK | ||
1757 : | if( get_user_button( id ) & IN_USE && !( get_user_oldbutton( id ) & IN_USE ) ) | ||
1758 : | { | ||
1759 : | new entlist[3], count | ||
1760 : | count = find_sphere_class( id, "func_button", 64.0, entlist, 3 ) | ||
1761 : | if( count ) | ||
1762 : | { | ||
1763 : | new Float:orig[3] | ||
1764 : | for( new i = 0; i < count; i++ ) | ||
1765 : | { | ||
1766 : | get_brush_entity_origin( entlist[i], orig ) | ||
1767 : | if( is_in_viewcone( id, orig ) ) button_used( id, entlist[i] ) | ||
1768 : | } | ||
1769 : | } | ||
1770 : | } | ||
1771 : | |||
1772 : | new cflags = timer[id-1][TMR_CFLAGS] | ||
1773 : | |||
1774 : | //Double and super jump boosts | ||
1775 : | if( get_pcvar_num( p_boost ) ) | ||
1776 : | { | ||
1777 : | new bool:onground = false | ||
1778 : | if( get_entity_flags( id ) & FL_ONGROUND ) onground = true | ||
1779 : | if( get_user_button( id ) & IN_JUMP ) | ||
1780 : | { | ||
1781 : | if( cflags & CF_SUPER_JUMP && onground ) | ||
1782 : | { | ||
1783 : | entity_get_vector( id, EV_VEC_velocity, post_think_vel[id-1] ) | ||
1784 : | if( post_think_vel[id-1][0] != 0.0 || post_think_vel[id-1][1] != 0.0) | ||
1785 : | { | ||
1786 : | velocity_by_aim( id, 400, post_think_vel[id-1] ) | ||
1787 : | if( post_think_vel[id-1][2] < 250.0) post_think_vel[id-1][2] = 250.0 | ||
1788 : | if( post_think_vel[id-1][2] > 350.0) post_think_vel[id-1][2] = 350.0 | ||
1789 : | } | ||
1790 : | else post_think_vel[id-1] = Float:{0.0,0.0,0.0} | ||
1791 : | } | ||
1792 : | else if( cflags & CF_DOUBLE_JUMP ) | ||
1793 : | { | ||
1794 : | if( !onground && !(get_user_oldbutton( id ) & IN_JUMP ) ) | ||
1795 : | { | ||
1796 : | entity_get_vector( id, EV_VEC_velocity, post_think_vel[id-1] ) | ||
1797 : | float_clamp( post_think_vel[id-1][0], -150.0, 150.0 ) | ||
1798 : | float_clamp( post_think_vel[id-1][1], -150.0, 150.0 ) | ||
1799 : | if( is_finished( id ) || post_think_vel[id-1][2] > -500 ) post_think_vel[id-1][2] = 250.0 | ||
1800 : | else post_think_vel[id-1] = Float:{ 0.0, 0.0, 0.0 } | ||
1801 : | } | ||
1802 : | } | ||
1803 : | } | ||
1804 : | } | ||
1805 : | |||
1806 : | //Prevent drowning | ||
1807 : | // waterlevel 0 - not in water | ||
1808 : | // waterlevel 1 - feet in water | ||
1809 : | // waterlevel 2 - waist in water | ||
1810 : | // waterlevel 3 - head in water | ||
1811 : | if( pev( id, pev_waterlevel ) == 3 ) set_pev( id, pev_waterlevel, 2 ) | ||
1812 : | |||
1813 : | new button = pev( id, pev_button ) | ||
1814 : | new oldbutton = pev( id, pev_oldbuttons ) | ||
1815 : | |||
1816 : | //If measure flag is set, call measure function | ||
1817 : | if( !( oldbutton & IN_ATTACK ) && button & IN_ATTACK ) | ||
1818 : | if( cflags & CF_MEASURE ) do_measure( id ) | ||
1819 : | else if( cflags & CF_MEASURE2 ) do_measure2( id, 1 ) | ||
1820 : | |||
1821 : | //Knife attack timeout | ||
1822 : | new wpn, clip, ammo | ||
1823 : | wpn = get_user_weapon( id, clip, ammo ) | ||
1824 : | if( wpn == CSW_KNIFE ) | ||
1825 : | { | ||
1826 : | |||
1827 : | if( button & IN_ATTACK || button & IN_ATTACK2 ) | ||
1828 : | if( check_timeout( 0, time_stamps[id-1][TS_KNIFE], KNIFE_TIMEOUT ) ) | ||
1829 : | set_pev( id, pev_button, pev( id, pev_button ) & ~IN_ATTACK_EITHER ) | ||
1830 : | } | ||
1831 : | return PLUGIN_CONTINUE | ||
1832 : | } | ||
1833 : | |||
1834 : | public client_PostThink(id) | ||
1835 : | { | ||
1836 : | if( !( get_pcvar_num(p_climb) && get_pcvar_num(p_boost) && is_climber_alive( id ) ) || is_user_bot(id) ) | ||
1837 : | return PLUGIN_CONTINUE | ||
1838 : | |||
1839 : | if( sclip[id-1] ) entity_set_int( id, EV_INT_solid, SOLID_NOT ) | ||
1840 : | |||
1841 : | if( _:get_distance( _:post_think_vel[id-1], { 0, 0, 0 } ) ) | ||
1842 : | { | ||
1843 : | entity_set_vector( id, EV_VEC_velocity, post_think_vel[id-1] ) | ||
1844 : | post_think_vel[id-1] = Float:{ 0.0, 0.0, 0.0 } | ||
1845 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) | ||
1846 : | { | ||
1847 : | timer[id-1][TMR_CNTBST]++ //Increment client boost count | ||
1848 : | change_boost( id, CF_NULL ) | ||
1849 : | } | ||
1850 : | else if( !is_finished(id) )change_boost( id, CF_NULL ) | ||
1851 : | } | ||
1852 : | |||
1853 : | //Store pause data | ||
1854 : | if( !( timer[id-1][TMR_CFLAGS] & CF_PAUSE ) ) | ||
1855 : | { | ||
1856 : | new Float:coords[3] | ||
1857 : | entity_get_vector( id, EV_VEC_origin, coords ) | ||
1858 : | for( new i=0; i<3; i++ ) origins[id-1][ORIG_PAUS+i] = coords[i] | ||
1859 : | origins[id-1][ORIG_PAUS+3] = entity_get_float( id, EV_FL_gravity ) | ||
1860 : | } | ||
1861 : | return PLUGIN_CONTINUE | ||
1862 : | } | ||
1863 : | |||
1864 : | public button_used( id, button ) | ||
1865 : | { | ||
1866 : | new btn_type = 0 | ||
1867 : | for( new i = 0; i < ST_BTN_CNT || i < FN_BTN_CNT; i++ ) | ||
1868 : | { | ||
1869 : | if( i < ST_BTN_CNT ) | ||
1870 : | if( button == ST_BTNS[i] ) | ||
1871 : | { | ||
1872 : | btn_type = 1 | ||
1873 : | break | ||
1874 : | } | ||
1875 : | if( i < FN_BTN_CNT ) | ||
1876 : | if( button == FN_BTNS[i] ) | ||
1877 : | { | ||
1878 : | btn_type = 2 | ||
1879 : | break | ||
1880 : | } | ||
1881 : | } | ||
1882 : | |||
1883 : | //new cflags = timer[id-1][TMR_CFLAGS] | ||
1884 : | |||
1885 : | if( btn_type == 1 )//Start Button | ||
1886 : | { | ||
1887 : | new Float:orig[3], bool:need_respawn = true //Float:view[3] | ||
1888 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) need_respawn = false | ||
1889 : | |||
1890 : | for( new i = 0; i < 48; i++ ) origins[id-1][i] = 0.0 //Erase checkpoints | ||
1891 : | |||
1892 : | //Set all associated variables | ||
1893 : | timer[id-1][TMR_STARTD] = get_systime() | ||
1894 : | change_status(id,CF_START) | ||
1895 : | timer[id-1][TMR_CNTCPS] = 0 | ||
1896 : | timer[id-1][TMR_CNTGCS] = 0 | ||
1897 : | timer[id-1][TMR_CNTBST] = 0 | ||
1898 : | timer[id-1][TMR_CPPOS] = 0 | ||
1899 : | timer[id-1][TMR_CNTWPN] = 0 | ||
1900 : | time_stamps[id-1][TS_BOOST] = BOOST_TIMEOUT | ||
1901 : | |||
1902 : | if( timer[id-1][TMR_CFLAGS] & CF_COUNTDOWN ) set_countdown_time( id ) | ||
1903 : | |||
1904 : | //Record starting weapon | ||
1905 : | rank_mod_update( id ) | ||
1906 : | |||
1907 : | //Respawn client to clear items. | ||
1908 : | if( need_respawn && get_pcvar_num( p_start_respawn ) ) | ||
1909 : | { | ||
1910 : | entity_get_vector( id, EV_VEC_origin, orig ) | ||
1911 : | //entity_get_vector( id, EV_VEC_angles, view ) | ||
1912 : | cs_user_spawn( id ) | ||
1913 : | entity_set_vector( id, EV_VEC_origin, orig ) | ||
1914 : | //entity_set_vector( id, EV_VEC_angles, view ) | ||
1915 : | delay_duck( id ) | ||
1916 : | //time_stamps[id-1][TS_SPAWN]=get_systime() | ||
1917 : | } | ||
1918 : | heal( id ) | ||
1919 : | cs_set_user_money( id, get_pcvar_num( p_startmoney ) ) | ||
1920 : | |||
1921 : | //Play random start sound and text messages | ||
1922 : | if( get_pcvar_num( p_sounds ) ) switch( random_num( 0, 2 ) ) | ||
1923 : | { | ||
1924 : | case 0:client_cmd( id, "spk barney/beertopside" ) | ||
1925 : | case 1:client_cmd( id, "spk scientist/c3a2_sci_portopen" ) | ||
1926 : | case 2:client_cmd( id, "spk barney/c1a2_ba_climb" ) | ||
1927 : | } | ||
1928 : | |||
1929 : | change_boost( id, CF_NULL ) //Disable Boosts | ||
1930 : | //time_stamps[id-1][TS_BOOST]=0 | ||
1931 : | clmsg(id,"Timer started. Go Go Go!!!") | ||
1932 : | //client_print(id,print_chat,"Timer started. Go Go Go!!!") | ||
1933 : | |||
1934 : | sfexec( id, 2 ) //Execute commands from start/finish config | ||
1935 : | |||
1936 : | sortcssb( ) //Update frags to reorder scoreboard | ||
1937 : | } | ||
1938 : | else if( btn_type == 2 )//Finish Button | ||
1939 : | { | ||
1940 : | if( timer[id-1][TMR_CFLAGS] & CF_START) | ||
1941 : | { | ||
1942 : | //Set client variables | ||
1943 : | timer[id-1][TMR_FINISH] = get_systime( ) | ||
1944 : | change_status( id, CF_STOP ) | ||
1945 : | timer[id-1][TMR_SESFIN]++ | ||
1946 : | timer[id-1][TMR_MAPFIN]++ | ||
1947 : | |||
1948 : | //Announce to client | ||
1949 : | if( get_pcvar_num( p_sounds ) ) client_cmd( 0, "spk woop" ) | ||
1950 : | clmsg( id, "Congratulations 1337 climber." ) | ||
1951 : | //client_print(id,print_chat,"Congratulations 1337 climber.") | ||
1952 : | new name[32], msg[21] | ||
1953 : | formatex( msg, sizeof( msg ) - 1, "%s^t%s", getuserstatus( id ), parsetime( get_climber_time( id ) ) ) | ||
1954 : | //clmsg(id,msg) | ||
1955 : | //client_print(id,print_chat,msg) | ||
1956 : | |||
1957 : | new wpn[11] | ||
1958 : | get_weapon_name( timer[id-1][TMR_CNTWPN], wpn, 10 ) | ||
1959 : | |||
1960 : | //Announce to all | ||
1961 : | get_user_name( id, name, 32 ) | ||
1962 : | client_print( 0, print_chat, "%s^t%s^t(%s/ %d CPS/ %d GCS/ %d Boosts)^tCompleted (%d, %d)", | ||
1963 : | name, msg, | ||
1964 : | wpn, timer[id-1][TMR_CNTCPS], timer[id-1][TMR_CNTGCS], timer[id-1][TMR_CNTBST], | ||
1965 : | timer[id-1][TMR_SESFIN], timer[id-1][TMR_MAPFIN] ) | ||
1966 : | |||
1967 : | new cnt_score = ( ( ( timer[id-1][TMR_CNTBST] > 0 ? 1 : 0 ) * 1000000 ) + | ||
1968 : | ( ( timer[id-1][TMR_CNTCPS] > 0 ? 1 : 0 ) * 100000 ) + | ||
1969 : | ( timer[id-1][TMR_CNTWPN] * 10000 ) + | ||
1970 : | get_climber_time( id ) ) | ||
1971 : | |||
1972 : | new bst_score = ( ( ( timer[id-1][TMR_BSTBST] > 0 ? 1 : 0 ) * 1000000 ) + | ||
1973 : | ( ( timer[id-1][TMR_BSTCPS] > 0 ? 1 : 0 ) * 100000 ) + | ||
1974 : | ( timer[id-1][TMR_BSTWPN] * 10000 ) + | ||
1975 : | timer[id-1][TMR_BSTTME] ) | ||
1976 : | |||
1977 : | if( cnt_score < bst_score || bst_score == 0 ) | ||
1978 : | { | ||
1979 : | timer[id-1][TMR_BSTTME] = get_climber_time( id ) | ||
1980 : | timer[id-1][TMR_BSTCPS] = timer[id-1][TMR_CNTCPS] | ||
1981 : | timer[id-1][TMR_BSTGCS] = timer[id-1][TMR_CNTGCS] | ||
1982 : | timer[id-1][TMR_BSTBST] = timer[id-1][TMR_CNTBST] | ||
1983 : | timer[id-1][TMR_BSTWPN] = timer[id-1][TMR_CNTWPN] | ||
1984 : | } | ||
1985 : | |||
1986 : | sfexec( id, 2 )//Execute commands from start/finish config | ||
1987 : | |||
1988 : | if( CLIMB_SAVE ) db_save( id ) | ||
1989 : | |||
1990 : | sortcssb( ) //Update frags to reorder scoreboard | ||
1991 : | } | ||
1992 : | else if(timer[id-1][TMR_CFLAGS]&CF_STOP&&timer[id-1][TMR_SESFIN]==0){ | ||
1993 : | //change_status(id,CF_FINISH) | ||
1994 : | timer[id-1][TMR_SESFIN]++ | ||
1995 : | new msg[100]="Congratulations, you finished! But you didn't start the timer. :(" | ||
1996 : | clmsg(id,msg) | ||
1997 : | client_print(id,print_chat,msg) | ||
1998 : | //Execute commands from start/finish config | ||
1999 : | sfexec(id,2) | ||
2000 : | //If stats save enabled warn unregistered clients to register | ||
2001 : | //if(CLIMB_SAVE)regwarn(id) | ||
2002 : | } | ||
2003 : | heal(id) | ||
2004 : | } | ||
2005 : | return PLUGIN_HANDLED | ||
2006 : | } | ||
2007 : | |||
2008 : | //Execute commands from start/finish config | ||
2009 : | public sfexec(id,clevent){ | ||
2010 : | new clstat[3],cflags=timer[id-1][TMR_CFLAGS] | ||
2011 : | /*switch(timer[id-1][TMR_CFLAGS]){ | ||
2012 : | case TMR_CFLAGS_STOP: clstat="ns" | ||
2013 : | case TMR_CFLAGS_STRT: clstat="st" | ||
2014 : | case TMR_CFLAGS_FNSH: clstat="fn" | ||
2015 : | }*/ | ||
2016 : | if(is_finished(id))clstat="fn" | ||
2017 : | else if(cflags&CF_STOP)clstat="ns" | ||
2018 : | else if(cflags&CF_START)clstat="st" | ||
2019 : | //else if(timer[id-1][TMR_CFLAGS]&CF_FINISH)clstat="fn" | ||
2020 : | //if(equal(clstat,"ns")&&(get_user_flags(id)&VIP||timer[id-1][TMR_SESFIN]>0))clstat="fn" | ||
2021 : | |||
2022 : | for(new i=0;i<sfcount;i++){ | ||
2023 : | new cmdstat[3],cmdevent[2],cmdtype[3],cmd[60],idtype[5] | ||
2024 : | parse(sfactions[i],cmdstat,2,cmdevent,1,cmdtype,2,cmd,sizeof(cmd)-1,idtype,4) | ||
2025 : | if((equali(cmdstat,clstat)||equali(cmdstat,"ay"))&&str_to_num(cmdevent)&clevent){ | ||
2026 : | if(equali(cmdtype,"sc")){ | ||
2027 : | if(equali(idtype,"uid"))format(cmd,sizeof(cmd)-1,cmd,get_user_userid(id)) | ||
2028 : | else{ | ||
2029 : | new name[24] | ||
2030 : | get_user_name(id,name,sizeof(name)-1) | ||
2031 : | format(name,sizeof(name),"^"%s^"",name) | ||
2032 : | format(cmd,sizeof(cmd)-1,cmd,name) | ||
2033 : | client_print(id,print_chat,cmd) | ||
2034 : | } | ||
2035 : | server_cmd(cmd) | ||
2036 : | } | ||
2037 : | else{ | ||
2038 : | client_cmd(id,cmd) | ||
2039 : | } | ||
2040 : | } | ||
2041 : | } | ||
2042 : | return PLUGIN_HANDLED | ||
2043 : | } | ||
2044 : | |||
2045 : | //Update frags to reorder scoreboard | ||
2046 : | public sortcssb( ) | ||
2047 : | { | ||
2048 : | new players[32], num, id | ||
2049 : | get_players_ordered( players, num ) | ||
2050 : | for( new i = 0 ; i < num; i++ ) | ||
2051 : | { | ||
2052 : | id = players[i] | ||
2053 : | set_user_frags( id, 0 ) | ||
2054 : | cs_set_user_deaths( id, i + 1 ) | ||
2055 : | |||
2056 : | message_begin( MSG_ALL, SVC_TEAMINFO ) | ||
2057 : | write_byte( id ) | ||
2058 : | write_string( "CT" ) | ||
2059 : | message_end( ) | ||
2060 : | } | ||
2061 : | |||
2062 : | //Show bot as spectator on scoreboard | ||
2063 : | message_begin( MSG_ALL, SVC_TEAMINFO ) | ||
2064 : | write_byte( find_player( "i" ) ) | ||
2065 : | write_string( "SPECTATOR" ) | ||
2066 : | message_end( ) | ||
2067 : | } | ||
2068 : | |||
2069 : | //Returns array of client id's sorted by climb time | ||
2070 : | public get_players_ordered( players[32], &num ) | ||
2071 : | { | ||
2072 : | get_players( players, num, "ch" ) | ||
2073 : | |||
2074 : | new i, id, pdata[32][3] //{ status, score, id } | ||
2075 : | for( i = 0; i < num; i++ ) | ||
2076 : | {//Fill player data sorting array | ||
2077 : | id = players[i] | ||
2078 : | pdata[i][2] = id | ||
2079 : | |||
2080 : | if( timer[id-1][TMR_BSTTME] ) | ||
2081 : | {//Has high score | ||
2082 : | pdata[i][0] = 0 | ||
2083 : | pdata[i][1] = ( ( ( timer[id-1][TMR_BSTBST] > 0 ? 1 : 0 ) * 1000000 ) + | ||
2084 : | ( ( timer[id-1][TMR_BSTCPS] > 0 ? 1 : 0 ) * 100000 ) + | ||
2085 : | ( timer[id-1][TMR_BSTWPN] * 10000 ) + | ||
2086 : | timer[id-1][TMR_BSTTME] ) | ||
2087 : | } | ||
2088 : | else if( timer[id-1][TMR_CFLAGS] & CF_START || timer[id-1][TMR_CFLAGS] & CF_PAUSE ) | ||
2089 : | {//Has time but no high score | ||
2090 : | pdata[i][0] = 1 | ||
2091 : | pdata[i][1] = ( ( ( timer[id-1][TMR_CNTBST] > 0 ? 1 : 0 ) * 1000000 ) + | ||
2092 : | ( ( timer[id-1][TMR_CNTCPS] > 0 ? 1 : 0 ) * 100000 ) + | ||
2093 : | ( timer[id-1][TMR_CNTWPN] * 10000 ) + | ||
2094 : | get_climber_time( id ) ) | ||
2095 : | } | ||
2096 : | else pdata[i][0] = 2 //No time or high score | ||
2097 : | } | ||
2098 : | |||
2099 : | SortStrings( pdata, num ) | ||
2100 : | for( i = 0; i < num; i++ ) | ||
2101 : | players[i] = pdata[i][2] | ||
2102 : | } | ||
2103 : | |||
2104 : | /*public get_limit(){ | ||
2105 : | //if(get_pcvar_num(p_webmod)) | ||
2106 : | //return 0 | ||
2107 : | new url[100] | ||
2108 : | get_pcvar_string(p_stats_url,url,99) | ||
2109 : | if(strlen(url)) | ||
2110 : | return false | ||
2111 : | return true | ||
2112 : | }*/ | ||
2113 : | |||
2114 : | /*public get_url( id, file[] ) | ||
2115 : | { | ||
2116 : | new url[100] | ||
2117 : | get_pcvar_string( p_stats_url, url, 99 ) | ||
2118 : | //if(get_pcvar_num(p_webmod)){ | ||
2119 : | // new ip[10],iip[33],eip[33],port[10] | ||
2120 : | // get_user_ip(id,ip,9) | ||
2121 : | // get_pcvar_string(p_ip_internal,iip,32) | ||
2122 : | // get_pcvar_string(p_ip_external,eip,32) | ||
2123 : | // get_pcvar_string(p_port,port,9) | ||
2124 : | // if(equal(ip,"192.168.",8))format(url,99,"http://%s:%s/%s",iip,port,file) | ||
2125 : | // else format(url,99,"http://%s:%s/%s",eip,port,file) | ||
2126 : | //} | ||
2127 : | if( strlen( url ) ) format( url, 99, "%sclimb_scores.html", url ) | ||
2128 : | return url | ||
2129 : | }*/ | ||
2130 : | |||
2131 : | stock sb_add_tabs( str[], size) | ||
2132 : | { | ||
2133 : | new len = strlen( str )// > 7 ? 1 : 2 | ||
2134 : | add( str[len], size, "^t") | ||
2135 : | if( len < 8 ) add( str[len+1], size, "^t") | ||
2136 : | } | ||
2137 : | |||
2138 : | public climbscores( id ) | ||
2139 : | {//Show scoreboard | ||
2140 : | if( get_pcvar_num( p_climb ) ) | ||
2141 : | { | ||
2142 : | if( get_systime() - ts_score > 2 ) | ||
2143 : | { | ||
2144 : | new fh = fopen( SCORES_PATH, "w" ) | ||
2145 : | |||
2146 : | //Header-8 cols: #, name, status, time, sct/cp/gc/boost, Best, cp/gc/boost, Completed | ||
2147 : | fprintf( fh, "<link rel=stylesheet href=http://ian.cammarata.us/sb><table><tr><td id=a>" ) | ||
2148 : | fprintf( fh, "<pre># Name Status Time Wpn/CP/GC/Bst Best ... Fin</pre>" ) | ||
2149 : | fprintf( fh, "</td></tr><tr id=b><td></td></tr><tr><td><pre>" ) | ||
2150 : | |||
2151 : | new line[251], name[NAMELEN+2], players[32], num, tid, written_len | ||
2152 : | new ctime, cwpn, ccp, cgc, cbst | ||
2153 : | new btime, bwpn, bcp, bgc, bbst | ||
2154 : | new ctime_str[20], btime_str[20] | ||
2155 : | |||
2156 : | get_players_ordered( players, num ) | ||
2157 : | |||
2158 : | for(new i = 1; i <= num; i++ ) | ||
2159 : | { | ||
2160 : | tid = players[i-1] | ||
2161 : | |||
2162 : | get_user_name( tid, name, NAMELEN) | ||
2163 : | sb_add_tabs( name, NAMELEN+2 ) | ||
2164 : | |||
2165 : | ctime = get_climber_time(tid) | ||
2166 : | cwpn = timer[tid-1][TMR_CNTWPN] | ||
2167 : | ccp = timer[tid-1][TMR_CNTCPS] | ||
2168 : | cgc = timer[tid-1][TMR_CNTGCS] | ||
2169 : | cbst = timer[tid-1][TMR_CNTBST] | ||
2170 : | format( ctime_str, 19, "%d/%d/%d/%d", cwpn, ccp, cgc, cbst ) | ||
2171 : | sb_add_tabs( ctime_str, 19 ) | ||
2172 : | |||
2173 : | btime = timer[tid-1][TMR_BSTTME] | ||
2174 : | bwpn = timer[tid-1][TMR_BSTWPN] | ||
2175 : | bcp = timer[tid-1][TMR_BSTCPS] | ||
2176 : | bgc = timer[tid-1][TMR_BSTGCS] | ||
2177 : | bbst = timer[tid-1][TMR_BSTBST] | ||
2178 : | format( btime_str, 19, "%d/%d/%d/%d", bwpn, bcp, bgc, bbst ) | ||
2179 : | sb_add_tabs( btime_str, 19 ) | ||
2180 : | |||
2181 : | formatex( line, 250, | ||
2182 : | "%s%d %s%s %s %s%s %s%d%s", | ||
2183 : | i % 2 ? "" : "<div>", | ||
2184 : | i, htmlspecialchars( name ), | ||
2185 : | getuserstatus( tid ), | ||
2186 : | parsetime( ctime ), ctime_str, | ||
2187 : | parsetime( btime ), btime_str, | ||
2188 : | timer[tid-1][TMR_MAPFIN], | ||
2189 : | i % 2 ? "" : "</div>" ) | ||
2190 : | written_len += strlen( line ) | ||
2191 : | //if( limit && written_len > ( 1263 - strlen( cust_msg ) ) ) break | ||
2192 : | if( written_len > 1263 ) break | ||
2193 : | fprintf( fh, line ) | ||
2194 : | } | ||
2195 : | //1530-150-117=1263 | ||
2196 : | new cust_msg[33] | ||
2197 : | get_pcvar_string( p_stats_msg, cust_msg, 32 ) | ||
2198 : | if( !strlen( cust_msg ) ) formatex( cust_msg, 32, "Climb %s", VERSION ) | ||
2199 : | fprintf( fh, "</pre></td></tr><tr id=d><td></td></tr><tr><td id=e></td></tr><tr>" ) | ||
2200 : | fprintf( fh, "<td id=a>%s</td></tr></table>", cust_msg ) | ||
2201 : | fclose( fh ) | ||
2202 : | ts_score = get_systime() | ||
2203 : | } | ||
2204 : | |||
2205 : | show_motd( id, SCORES_PATH, "Current Scores" ) | ||
2206 : | } | ||
2207 : | return PLUGIN_HANDLED | ||
2208 : | } | ||
2209 : | |||
2210 : | public parsetime(sec){//Convert seconds to time string with zero padded seconds field | ||
2211 : | new timestr[9],mins | ||
2212 : | mins=sec/60 | ||
2213 : | sec=sec%60 | ||
2214 : | formatex(timestr,8,"%d:%s%d",mins,sec<10?"0":"",sec) | ||
2215 : | return timestr | ||
2216 : | } | ||
2217 : | |||
2218 : | public get_climber_time( id ) | ||
2219 : | {//Calculate client climb time in seconds | ||
2220 : | /*new ptime,cflags=timer[id-1][TMR_CFLAGS] | ||
2221 : | ptime=timer[id-1][TMR_FINISH]-timer[id-1][TMR_STARTD] | ||
2222 : | if(cflags&CF_STOP&&timer[id=1][TMR_SESFIN]>0)ptime=timer[id-1][TMR_FINISH]-timer[id-1][TMR_STARTD] | ||
2223 : | else if(cflags&CF_STOP)ptime=0 | ||
2224 : | else if(cflags&CF_START)ptime=get_systime()-timer[id-1][TMR_STARTD] | ||
2225 : | else if(cflags&CF_PAUSE)ptime=timer[id-1][TMR_STARTD]*/ | ||
2226 : | new cflags = timer[id-1][TMR_CFLAGS] | ||
2227 : | if( cflags & CF_START ) return get_systime()-timer[id-1][TMR_STARTD] | ||
2228 : | else if( cflags & CF_PAUSE ) return timer[id-1][TMR_STARTD] | ||
2229 : | return timer[id-1][TMR_FINISH]-timer[id-1][TMR_STARTD] | ||
2230 : | } | ||
2231 : | |||
2232 : | public hudtime( ) | ||
2233 : | {//Set clock on HUD to current climb time | ||
2234 : | if( !get_pcvar_num( p_climb ) ) return | ||
2235 : | |||
2236 : | new id, players[32], num, cltime, cflags | ||
2237 : | get_players( players, num, "ach" ) | ||
2238 : | for( new i = 0; i < num; i++ ) | ||
2239 : | { | ||
2240 : | id = players[i] | ||
2241 : | cflags = timer[id-1][TMR_CFLAGS] | ||
2242 : | cltime = get_climber_time(id) + 1 | ||
2243 : | if( cflags & CF_PAUSE ) | ||
2244 : | { | ||
2245 : | clmsg( id, "PAUSED - say '/unpause' to resume." ) | ||
2246 : | cl_pause( id ) | ||
2247 : | } | ||
2248 : | |||
2249 : | if( !( cflags & CF_COUNTDOWN ) || ( timer[id-1][TMR_BSTTME] - get_climber_time( id ) < 0 ) ) | ||
2250 : | hudtime_msg( id, cltime ) | ||
2251 : | else if( cflags & CF_PAUSE ) | ||
2252 : | hudtime_msg( id, timer[id-1][TMR_BSTTME] - cltime + 1 ) | ||
2253 : | |||
2254 : | for( new j = 1; j <= spec_ids[id-1][0]; j++ ) | ||
2255 : | hudtime_msg( spec_ids[id-1][j], cltime ) | ||
2256 : | } | ||
2257 : | } | ||
2258 : | |||
2259 : | public toggle_countdown( id ) | ||
2260 : | { | ||
2261 : | //Toggle countdown flag and print message | ||
2262 : | timer[id-1][TMR_CFLAGS] ^= CF_COUNTDOWN | ||
2263 : | if( timer[id-1][TMR_CFLAGS] & CF_COUNTDOWN ) | ||
2264 : | { | ||
2265 : | if( set_countdown_time( id ) ) | ||
2266 : | clmsg( id, "Countdown enabled." ) | ||
2267 : | } | ||
2268 : | else | ||
2269 : | clmsg( id, "Countdown disabled." ) | ||
2270 : | } | ||
2271 : | |||
2272 : | public bool:set_countdown_time( id ) | ||
2273 : | { | ||
2274 : | new bsttime = timer[id-1][TMR_BSTTME] | ||
2275 : | if( bsttime > 0 ) | ||
2276 : | { | ||
2277 : | new cflags = timer[id-1][TMR_CFLAGS] | ||
2278 : | if( cflags & CF_START || cflags & CF_PAUSE ) | ||
2279 : | hudtime_msg( id, timer[id-1][TMR_BSTTME] - get_climber_time( id ) ) | ||
2280 : | return true | ||
2281 : | } | ||
2282 : | clmsg( id, "Countdown disabled: No high score available." ) | ||
2283 : | timer[id-1][TMR_CFLAGS] ^= CF_COUNTDOWN | ||
2284 : | return false | ||
2285 : | } | ||
2286 : | |||
2287 : | public hudtime_msg( id, cltime ) | ||
2288 : | { | ||
2289 : | message_begin( MSG_ONE, SVC_ROUNDTIME, _, id ) | ||
2290 : | write_short( cltime ) | ||
2291 : | message_end( ) | ||
2292 : | } | ||
2293 : | |||
2294 : | public getuserstatus( id ) | ||
2295 : | {//Return string describing user status | ||
2296 : | new msg[12], cflags = timer[id-1][TMR_CFLAGS] | ||
2297 : | msg = "PAUSED" | ||
2298 : | if( cflags & CF_STOP && timer[id-1][TMR_SESFIN] > 0 ) | ||
2299 : | msg = "Finished" | ||
2300 : | else if( cflags & CF_STOP ) | ||
2301 : | msg = "Not Started" | ||
2302 : | else if( cflags & CF_START ) | ||
2303 : | msg = "Climbing" | ||
2304 : | //else if( cflags & CF_PAUSE ) msg = "PAUSED" | ||
2305 : | //return "PAUSED" | ||
2306 : | return msg | ||
2307 : | } | ||
2308 : | |||
2309 : | stock clmsg( id, msg[] ) | ||
2310 : | {//Show Hud Message | ||
2311 : | set_hudmessage( get_pcvar_num( p_msg_r ), get_pcvar_num( p_msg_g ), get_pcvar_num( p_msg_b ), | ||
2312 : | get_pcvar_float( p_msg_x ), get_pcvar_float( p_msg_y ), 0, 0.0, 5.0, 0.5, 0.5, 4 ) | ||
2313 : | show_hudmessage( id, msg ) | ||
2314 : | |||
2315 : | //Show to spectators | ||
2316 : | for( new i = 1; i <= spec_ids[id-1][0]; i++ ) | ||
2317 : | show_hudmessage( spec_ids[id-1][i], msg ) | ||
2318 : | |||
2319 : | return PLUGIN_HANDLED | ||
2320 : | } | ||
2321 : | //Fill spectator data array used for msg replication | ||
2322 : | public spec_update(){ | ||
2323 : | if(get_pcvar_num(p_climb)){ | ||
2324 : | new players[32],num,id,id2,i | ||
2325 : | for(i=1;i<33;i++)spec_ids[i-1][0]=0 | ||
2326 : | get_players(players,num,"bch") | ||
2327 : | for(i=0;i<num;i++){ | ||
2328 : | id=players[i] | ||
2329 : | id2=pev(id,pev_iuser2) | ||
2330 : | if(id2){ | ||
2331 : | spec_ids[id2-1][0]++ | ||
2332 : | spec_ids[id2-1][spec_ids[id2-1][0]]=id | ||
2333 : | } | ||
2334 : | } | ||
2335 : | } | ||
2336 : | return PLUGIN_HANDLED | ||
2337 : | } | ||
2338 : | //Make client solid | ||
2339 : | public solid(id) | ||
2340 : | { | ||
2341 : | set_user_rendering(id,kRenderFxNone,0,0,0,kRenderNormal,255) | ||
2342 : | entity_set_int(id,EV_INT_solid,SOLID_BBOX) | ||
2343 : | sclip[id-1]=false | ||
2344 : | return PLUGIN_CONTINUE | ||
2345 : | } | ||
2346 : | //Make client unsolid | ||
2347 : | public unsolid(id) | ||
2348 : | { | ||
2349 : | if(get_pcvar_num(p_render))set_user_rendering(id,kRenderFxHologram,0,0,0,kRenderTransAdd,0) | ||
2350 : | else set_user_rendering(id,kRenderFxPulseSlow,0,0,0,kRenderTransTexture,50) | ||
2351 : | entity_set_int(id,EV_INT_solid,SOLID_NOT) | ||
2352 : | sclip[id-1]=true | ||
2353 : | return PLUGIN_CONTINUE | ||
2354 : | } | ||
2355 : | //////////////////////////////////////////////////////////////////////////////// | ||
2356 : | // Start: Functions for use in if statements | ||
2357 : | //////////////////////////////////////////////////////////////////////////////// | ||
2358 : | public is_climber_alive( id ) | ||
2359 : | { | ||
2360 : | new movetype = pev( id, pev_movetype ) | ||
2361 : | if( movetype == MOVETYPE_WALK || movetype == MOVETYPE_FLY ) | ||
2362 : | return 1 | ||
2363 : | return 0 | ||
2364 : | } | ||
2365 : | |||
2366 : | public playersolid( id ) | ||
2367 : | { | ||
2368 : | if(entity_get_int(id,EV_INT_solid)==SOLID_BBOX)return 1 | ||
2369 : | return 0 | ||
2370 : | } | ||
2371 : | |||
2372 : | public isct(id){//Used in IF statements a lot | ||
2373 : | if(get_user_team(id)==2)return 1 | ||
2374 : | return 0 | ||
2375 : | } | ||
2376 : | |||
2377 : | public is_finished( id ) | ||
2378 : | { | ||
2379 : | new cflags = timer[id-1][TMR_CFLAGS] | ||
2380 : | if( cflags & CF_STOP && ( get_user_flags( id ) & VIP || timer[id-1][TMR_SESFIN] > 0 ) ) | ||
2381 : | return 1 | ||
2382 : | return 0 | ||
2383 : | } | ||
2384 : | |||
2385 : | public isalive(id){//Use in IF statements to automatically print error if false | ||
2386 : | if( is_climber_alive( id ) )return 1 | ||
2387 : | clmsg(id,"You must be alive to execute this command.") | ||
2388 : | return 0 | ||
2389 : | } | ||
2390 : | |||
2391 : | public notpaused(id){//Use in IF statements to automatically print error if false | ||
2392 : | if(!(timer[id-1][TMR_CFLAGS]&CF_PAUSE))return 1 | ||
2393 : | clmsg(id,"You can't execute this command while paused.") | ||
2394 : | return 0 | ||
2395 : | } | ||
2396 : | |||
2397 : | /*public regwarn(id){ | ||
2398 : | if(timer[id-1][TMR_DBUSER]<1){ | ||
2399 : | saytext(id,id,"^x04You must register/login for your stats to save. Say /climbhelp for more info.") | ||
2400 : | return 1 | ||
2401 : | } | ||
2402 : | return 0 | ||
2403 : | }*/ | ||
2404 : | //////////////////////////////////////////////////////////////////////////////// | ||
2405 : | // End: Functions for use in if statements | ||
2406 : | //////////////////////////////////////////////////////////////////////////////// | ||
2407 : | // Start: Auto Heal functions | ||
2408 : | //////////////////////////////////////////////////////////////////////////////// | ||
2409 : | public damage(id){//Called when client takes damage | ||
2410 : | new ida[1] | ||
2411 : | ida[0]=id | ||
2412 : | set_task(0.1,"damage_handle",_,ida,1) | ||
2413 : | } | ||
2414 : | |||
2415 : | public damage_handle( ida[1] ) | ||
2416 : | {//Damage hander, delayed to provide HUD consistency | ||
2417 : | new id = ida[0] | ||
2418 : | if( get_pcvar_num( p_climb )&& is_climber_alive( id ) ) | ||
2419 : | { | ||
2420 : | new chp = get_user_health( id ) | ||
2421 : | if( chp != hp ) | ||
2422 : | { | ||
2423 : | heal( id ) | ||
2424 : | /*new wpn, atk = get_user_attacker( id, wpn ) | ||
2425 : | |||
2426 : | //Heal hp immediately | ||
2427 : | if( ( atk == 0 || ( id == atk && wpn == 0) ) && !task_exists( 50 + id ) ) | ||
2428 : | heal(id) | ||
2429 : | |||
2430 : | //Heal delayed | ||
2431 : | else | ||
2432 : | { | ||
2433 : | if( task_exists( 50 + id ) ) remove_task( 50 + id ) | ||
2434 : | set_task( 5.0, "task_heal", 50 + id, ida, 1 ) | ||
2435 : | |||
2436 : | //Fix hp display at 0 | ||
2437 : | if( chp == 256 ) set_user_health( id, 257 ) | ||
2438 : | }*/ | ||
2439 : | } | ||
2440 : | else if( task_exists( 50 + id ) ) remove_task( 50 + id ) | ||
2441 : | } | ||
2442 : | return PLUGIN_HANDLED | ||
2443 : | } | ||
2444 : | |||
2445 : | public task_heal(ida[]){//Heal client to predetermined HP required by map | ||
2446 : | heal(ida[0]) | ||
2447 : | return PLUGIN_HANDLED | ||
2448 : | } | ||
2449 : | |||
2450 : | public heal(id){ | ||
2451 : | if( is_climber_alive( id ) ) | ||
2452 : | { | ||
2453 : | if(is_finished(id))set_user_health(id,511) | ||
2454 : | else if(hp)set_user_health(id,hp) | ||
2455 : | else if(get_user_health(id)>100)set_user_health(id,100) | ||
2456 : | } | ||
2457 : | } | ||
2458 : | //////////////////////////////////////////////////////////////////////////////// | ||
2459 : | // End: Auto Heal functions | ||
2460 : | //////////////////////////////////////////////////////////////////////////////// | ||
2461 : | // Start: Multiplay Bunny Hop functions | ||
2462 : | //////////////////////////////////////////////////////////////////////////////// | ||
2463 : | public pfn_touch( ent, id ) | ||
2464 : | { | ||
2465 : | if( !get_pcvar_num( p_climb ) ) | ||
2466 : | return PLUGIN_CONTINUE | ||
2467 : | |||
2468 : | //Clean up dropped stuff | ||
2469 : | new str[21] | ||
2470 : | entity_get_string( ent, EV_SZ_classname, str, 20 ) | ||
2471 : | if( equal( str, "weaponbox" ) || equal( str, "item_thighpack" ) ) | ||
2472 : | { | ||
2473 : | remove_entity( ent ) | ||
2474 : | return PLUGIN_HANDLED | ||
2475 : | } | ||
2476 : | if( pev_valid( id ) ) | ||
2477 : | { | ||
2478 : | entity_get_string( id, EV_SZ_classname, str, 20 ) | ||
2479 : | if( equal( str, "weaponbox" ) || equal( str, "item_thighpack" ) ) | ||
2480 : | { | ||
2481 : | remove_entity( id ) | ||
2482 : | return PLUGIN_HANDLED | ||
2483 : | } | ||
2484 : | } | ||
2485 : | else return PLUGIN_HANDLED | ||
2486 : | |||
2487 : | if ( !ent || !id ) | ||
2488 : | return PLUGIN_CONTINUE | ||
2489 : | |||
2490 : | //Make sure id is player and ent is object | ||
2491 : | if( 0 < ent <= MAXPLAYERS ) | ||
2492 : | { | ||
2493 : | new tmp = id | ||
2494 : | id = ent | ||
2495 : | ent = tmp | ||
2496 : | } | ||
2497 : | else if( !( 0 < id <= MAXPLAYERS ) ) | ||
2498 : | return PLUGIN_CONTINUE | ||
2499 : | |||
2500 : | //Bhop stuff | ||
2501 : | new dpos = door_in_array( ent ) | ||
2502 : | if( dpos > -1 ) | ||
2503 : | { | ||
2504 : | //Finished can stand on bhop blocks | ||
2505 : | if( is_finished( id ) ) | ||
2506 : | return PLUGIN_HANDLED | ||
2507 : | |||
2508 : | if( bhop_failid[id-1] != ent ) | ||
2509 : | { | ||
2510 : | bhop_failid[id-1] = ent | ||
2511 : | bhop_fail[id-1] = false | ||
2512 : | |||
2513 : | new tskid = TSK_BHOP + id | ||
2514 : | if( task_exists( tskid ) ) | ||
2515 : | remove_task( tskid ) | ||
2516 : | set_task( 0.2, "bhop_set_fail", tskid ) | ||
2517 : | tskid = TSK_CLEAR_FAIL + id | ||
2518 : | if( task_exists( tskid ) ) | ||
2519 : | remove_task( tskid ) | ||
2520 : | set_task( 0.7, "bhop_clear_fail", tskid ) | ||
2521 : | } | ||
2522 : | else if( bhop_fail[id-1] ) | ||
2523 : | { | ||
2524 : | teleport( id, door_tp_pos[dpos] ) | ||
2525 : | bhop_failid[id-1] = 0 | ||
2526 : | bhop_fail[id-1] = false | ||
2527 : | } | ||
2528 : | return PLUGIN_HANDLED | ||
2529 : | } | ||
2530 : | |||
2531 : | return PLUGIN_CONTINUE | ||
2532 : | } | ||
2533 : | |||
2534 : | public door_in_array( door ) | ||
2535 : | { | ||
2536 : | for( new i = 0; i < door_count; i++ ) | ||
2537 : | if( func_doors[i][0] == door ) | ||
2538 : | return i | ||
2539 : | return -1 | ||
2540 : | } | ||
2541 : | |||
2542 : | public bhop_set_fail( tskid ) | ||
2543 : | { | ||
2544 : | bhop_fail[tskid-TSK_BHOP-1] = true | ||
2545 : | return PLUGIN_HANDLED | ||
2546 : | } | ||
2547 : | |||
2548 : | public bhop_clear_fail( tskid ) | ||
2549 : | { | ||
2550 : | new id = tskid - TSK_CLEAR_FAIL | ||
2551 : | bhop_failid[id-1] = 0 | ||
2552 : | bhop_fail[id-1] = false | ||
2553 : | return PLUGIN_HANDLED | ||
2554 : | } | ||
2555 : | |||
2556 : | //////////////////////////////////////////////////////////////////////////////// | ||
2557 : | // End: Multiplay Bunny Hop functions | ||
2558 : | //////////////////////////////////////////////////////////////////////////////// | ||
2559 : | |||
2560 : | /*public spawn_distance_sort(elem1[],elem2[]){ | ||
2561 : | if(elem1[1]<elem2[1])return -1 | ||
2562 : | if(elem1[1]>elem2[1])return 1 | ||
2563 : | return 0 | ||
2564 : | }*/ | ||
2565 : | |||
2566 : | //Future use, to block hook, or detect hook cheaters a.k.a. hookers | ||
2567 : | public phook( id ) | ||
2568 : | { | ||
2569 : | hooked[id] = 1 | ||
2570 : | return PLUGIN_CONTINUE | ||
2571 : | } | ||
2572 : | |||
2573 : | public mhook( id ) | ||
2574 : | { | ||
2575 : | hooked[id] = 0 | ||
2576 : | return PLUGIN_CONTINUE | ||
2577 : | } | ||
2578 : | |||
2579 : | //////////////////////////////////////////////////////////////////////////////// | ||
2580 : | // Start: Flashlight functions | ||
2581 : | //////////////////////////////////////////////////////////////////////////////// | ||
2582 : | public flight_icons( id ) | ||
2583 : | { | ||
2584 : | if( timer[id-1][TMR_CFLAGS] & CF_LIGHT_ON ) | ||
2585 : | { | ||
2586 : | if( !task_exists( TSK_FLIGHT + id ) ) | ||
2587 : | set_task( 0.1, "flight_msg", TSK_FLIGHT + id, _, _, "b" ) | ||
2588 : | |||
2589 : | message_begin( MSG_ONE, SVC_FLASHLIGHT, _, id ) | ||
2590 : | write_byte( 1 ) | ||
2591 : | write_byte( 100 ) | ||
2592 : | message_end( ) | ||
2593 : | |||
2594 : | message_begin( MSG_ONE, SVC_STATUSICON, _, id ) | ||
2595 : | write_byte( 1 ) //on | ||
2596 : | write_string( "flash_beam" ) | ||
2597 : | write_byte( get_pcvar_num( p_light_r ) ) //r | ||
2598 : | write_byte( get_pcvar_num( p_light_g ) ) //g | ||
2599 : | write_byte( get_pcvar_num( p_light_b ) ) //b | ||
2600 : | message_end( ) | ||
2601 : | } | ||
2602 : | else | ||
2603 : | { | ||
2604 : | message_begin( MSG_ONE, SVC_FLASHLIGHT, _, id ) | ||
2605 : | write_byte( 0 ) | ||
2606 : | write_byte( 100 ) | ||
2607 : | message_end( ) | ||
2608 : | |||
2609 : | message_begin( MSG_ONE, SVC_STATUSICON, _, id ) | ||
2610 : | write_byte( 0 ) //off | ||
2611 : | write_string( "flash_beam" ) | ||
2612 : | message_end( ) | ||
2613 : | } | ||
2614 : | } | ||
2615 : | public tog_flight(id){ | ||
2616 : | if(!get_pcvar_num(p_climb))return PLUGIN_CONTINUE | ||
2617 : | if(!(timer[id-1][TMR_CFLAGS]&CF_LIGHT_ON)){ | ||
2618 : | timer[id-1][TMR_CFLAGS]+=CF_LIGHT_ON | ||
2619 : | set_task(0.1,"flight_msg",TSK_FLIGHT+id,_,_,"b") | ||
2620 : | } | ||
2621 : | else timer[id-1][TMR_CFLAGS]-=CF_LIGHT_ON | ||
2622 : | flight_icons(id) | ||
2623 : | return PLUGIN_HANDLED | ||
2624 : | } | ||
2625 : | |||
2626 : | public flight_msg(tskid){ | ||
2627 : | if(get_pcvar_num(p_climb)){ | ||
2628 : | new orig[3],id=tskid-TSK_FLIGHT | ||
2629 : | if(!(timer[id-1][TMR_CFLAGS]&CF_LIGHT_ON))remove_task(tskid) | ||
2630 : | get_user_origin(id,orig) | ||
2631 : | message_begin(MSG_ONE_UNRELIABLE,SVC_TEMPENTITY,_,id) | ||
2632 : | write_byte(TE_DLIGHT) | ||
2633 : | write_coord(orig[0])//x | ||
2634 : | write_coord(orig[1])//y | ||
2635 : | write_coord(orig[2])//z | ||
2636 : | write_byte(60)//radius | ||
2637 : | write_byte(get_pcvar_num(p_light_r))//r | ||
2638 : | write_byte(get_pcvar_num(p_light_g))//g | ||
2639 : | write_byte(get_pcvar_num(p_light_b))//b | ||
2640 : | write_byte(4)//life | ||
2641 : | write_byte(2)//decay | ||
2642 : | message_end() | ||
2643 : | } | ||
2644 : | return PLUGIN_HANDLED | ||
2645 : | } | ||
2646 : | //////////////////////////////////////////////////////////////////////////////// | ||
2647 : | // End: Flashlight functions | ||
2648 : | //////////////////////////////////////////////////////////////////////////////// | ||
2649 : | public teleport( id, Float:orig[3] ) | ||
2650 : | {//Used to teleport clients, prevents client collisions and getting stuck | ||
2651 : | //Don't tp if vector is all zeros | ||
2652 : | if( !( orig[0] || orig[1] || orig[2] ) ) return 0 | ||
2653 : | |||
2654 : | new Float:c2[3], player, players[32], num | ||
2655 : | get_players( players, num, "ac" ) | ||
2656 : | unsolid( id ) | ||
2657 : | for( new i = 0; i < num; i++ ) | ||
2658 : | { | ||
2659 : | player = players[i] | ||
2660 : | if( id != player ) | ||
2661 : | { | ||
2662 : | entity_get_vector( player, EV_VEC_origin, c2 ) | ||
2663 : | if( vector_distance( orig, c2 ) < 90 ) unsolid( player ) | ||
2664 : | } | ||
2665 : | } | ||
2666 : | entity_set_vector( id, EV_VEC_velocity, Float:{0.0, 0.0, 0.0} ) | ||
2667 : | entity_set_vector( id, EV_VEC_origin, orig ) | ||
2668 : | delay_duck( id ) | ||
2669 : | return 1 | ||
2670 : | } | ||
2671 : | |||
2672 : | public delay_duck(id){//Used by teleport and timer start respawn, prevents getting stuck | ||
2673 : | new ida[1] | ||
2674 : | ida[0]=id | ||
2675 : | set_task(0.01,"force_duck",_,ida,1) | ||
2676 : | set_entity_flags(ida[0],FL_DUCKING,1) | ||
2677 : | } | ||
2678 : | |||
2679 : | public force_duck(ida[1]){//Task for delay_duck | ||
2680 : | set_entity_flags(ida[0],FL_DUCKING,1) | ||
2681 : | } | ||
2682 : | |||
2683 : | public cvar_enabled(id,p_cvar){//Used in IF statements to automatically print error if false | ||
2684 : | if(get_pcvar_num(p_cvar)==0){ | ||
2685 : | clmsg(id,"This command is disabled.") | ||
2686 : | client_print(id,print_chat,"This command has been disabled by the server administrator.") | ||
2687 : | return 0 | ||
2688 : | } | ||
2689 : | return 1 | ||
2690 : | } | ||
2691 : | //////////////////////////////////////////////////////////////////////////////// | ||
2692 : | // Start: Climb command handling functions | ||
2693 : | //////////////////////////////////////////////////////////////////////////////// | ||
2694 : | |||
2695 : | public sunglasses( id ) | ||
2696 : | { | ||
2697 : | //Toggle flag for this measure and print message | ||
2698 : | timer[id-1][TMR_CFLAGS] ^= CF_SUNGLASSES | ||
2699 : | if( timer[id-1][TMR_CFLAGS] & CF_SUNGLASSES ) | ||
2700 : | { | ||
2701 : | message_begin( MSG_ONE, SVC_SCREENFADE, _, id ) | ||
2702 : | write_short( 1 ) //total duration | ||
2703 : | write_short( 0 ) //time it stays one color | ||
2704 : | write_short( 5 ) //fade type | ||
2705 : | write_byte( 0 ) //r | ||
2706 : | write_byte( 0 ) //g | ||
2707 : | write_byte( 0 ) //b | ||
2708 : | write_byte( 127 ) //a | ||
2709 : | message_end( ) | ||
2710 : | } | ||
2711 : | else | ||
2712 : | { | ||
2713 : | message_begin( MSG_ONE, SVC_SCREENFADE, _, id ) | ||
2714 : | write_short( 1 ) //total duration | ||
2715 : | write_short( 0 ) //time it stays one color | ||
2716 : | write_short( 0 ) //fade type | ||
2717 : | write_byte( 0 ) //r | ||
2718 : | write_byte( 0 ) //g | ||
2719 : | write_byte( 0 ) //b | ||
2720 : | write_byte( 127 ) //a | ||
2721 : | message_end( ) | ||
2722 : | } | ||
2723 : | } | ||
2724 : | |||
2725 : | public give_scout( id ) | ||
2726 : | if( !check_timeout( id, time_stamps[id-1][TS_WPN], WPN_TIMEOUT ) ) | ||
2727 : | give_item( id, "weapon_scout" ) | ||
2728 : | |||
2729 : | public give_usp( id ) | ||
2730 : | if( !check_timeout( id, time_stamps[id-1][TS_WPN], WPN_TIMEOUT ) ) | ||
2731 : | give_item( id, "weapon_usp" ) | ||
2732 : | |||
2733 : | public give_weapons( id ) | ||
2734 : | if( !check_timeout( id, time_stamps[id-1][TS_WPN], WPN_TIMEOUT ) ) | ||
2735 : | { | ||
2736 : | give_item( id, "weapon_awp" ) | ||
2737 : | give_item( id, "weapon_m249" ) | ||
2738 : | give_item( id, "weapon_m4a1" ) | ||
2739 : | give_item( id, "weapon_sg552" ) | ||
2740 : | give_item( id, "weapon_famas" ) | ||
2741 : | give_item( id, "weapon_p90" ) | ||
2742 : | give_item( id, "weapon_usp" ) | ||
2743 : | give_item( id, "weapon_scout" ) | ||
2744 : | } | ||
2745 : | |||
2746 : | |||
2747 : | public help_msg(id) | ||
2748 : | { | ||
2749 : | client_print( id, print_chat, "Say /climbhelp to get help with the Climb kz plugin." ) | ||
2750 : | return PLUGIN_CONTINUE | ||
2751 : | } | ||
2752 : | |||
2753 : | public climb_help(id) | ||
2754 : | if( get_pcvar_num( p_climb ) ) | ||
2755 : | show_motd( id, "http://ian.cammarata.us/projects/climb/help/2a3/en/commands?agent=hl", "Climb Plugin Help" ) | ||
2756 : | |||
2757 : | public boost_help(id) | ||
2758 : | if( get_pcvar_num( p_climb ) ) | ||
2759 : | show_motd( id, "http://ian.cammarata.us/projects/climb/help/2a3/en/boosts?agent=hl", "Climb Plugin Help" ) | ||
2760 : | |||
2761 : | public goto_player( id ) | ||
2762 : | {//Admin command, teleport to client | ||
2763 : | if( is_finished( id ) && get_pcvar_num( p_climb ) ) | ||
2764 : | { | ||
2765 : | new tid, arg[24] | ||
2766 : | read_argv( 1, arg, sizeof( arg ) - 1 ) | ||
2767 : | tid = cmd_target( tid, arg, 4 ) | ||
2768 : | if( tid ) | ||
2769 : | { | ||
2770 : | new Float:orig[3] | ||
2771 : | entity_get_vector( tid, EV_VEC_origin, orig ) | ||
2772 : | teleport( id, orig ) | ||
2773 : | } | ||
2774 : | } | ||
2775 : | return PLUGIN_HANDLED | ||
2776 : | } | ||
2777 : | |||
2778 : | public spectate( id ) | ||
2779 : | {//Client switch to spectator | ||
2780 : | if( get_pcvar_num( p_climb ) && !is_user_bot( id ) && !is_user_hltv( id ) ) | ||
2781 : | { | ||
2782 : | if( !is_climber_alive( id ) ) | ||
2783 : | { | ||
2784 : | /* | ||
2785 : | cs_set_user_team(id,3)//fixes respawn bug? | ||
2786 : | frespawn( id ) | ||
2787 : | */ | ||
2788 : | |||
2789 : | climb_user_spawn( id ) | ||
2790 : | |||
2791 : | if( timer[id-1][TMR_CFLAGS] & CF_PAUSE ) | ||
2792 : | {//If they are paused tp to pause spot and freeze them again. | ||
2793 : | new Float:coords[3] | ||
2794 : | for( new i=0; i<3; i++ ) coords[i] = origins[ id - 1 ][ ORIG_PAUS + i ] | ||
2795 : | teleport( id, coords ) | ||
2796 : | cl_pause( id ) | ||
2797 : | } | ||
2798 : | |||
2799 : | } | ||
2800 : | else if( get_user_flags( id ) & VIP ? 1 : ( cvar_enabled( id, p_allow_spectators ) ) ) | ||
2801 : | { | ||
2802 : | //Move client way outside the map so we don't have to see their retarded model | ||
2803 : | new Float:orig[3] | ||
2804 : | entity_get_vector( id, EV_VEC_origin, orig ) | ||
2805 : | entity_set_vector( id, EV_VEC_origin, Float:{ 99999.9, 99999.9, 99999.9 } ) | ||
2806 : | |||
2807 : | //Set a task to move them back to where they were originally | ||
2808 : | new ida[4] | ||
2809 : | ida[0] = id | ||
2810 : | ida[1] = _:orig[0] | ||
2811 : | ida[2] = _:orig[1] | ||
2812 : | ida[3] = _:orig[2] | ||
2813 : | set_task( 0.1, "tsk_spec_tp_back", _, ida, 4 ) | ||
2814 : | |||
2815 : | set_pev( id, pev_movetype, MOVETYPE_NOCLIP ) | ||
2816 : | set_pev( id, pev_solid, SOLID_NOT ) | ||
2817 : | set_pev( id, pev_effects, EF_NODRAW ) | ||
2818 : | set_pev( id, pev_deadflag, DEAD_DEAD ) | ||
2819 : | set_pev( id, pev_takedamage, DAMAGE_NO ) | ||
2820 : | set_entity_flags( id, FL_FROZEN, 0 ) | ||
2821 : | |||
2822 : | if( timer[id-1][TMR_CFLAGS] & CF_START ) change_status( id, CF_PAUSE ) | ||
2823 : | } | ||
2824 : | return PLUGIN_HANDLED | ||
2825 : | } | ||
2826 : | return PLUGIN_CONTINUE | ||
2827 : | } | ||
2828 : | |||
2829 : | public tsk_spec_tp_back( ida[4] ) | ||
2830 : | { | ||
2831 : | new Float:orig[3] | ||
2832 : | orig[0] = Float:ida[1] | ||
2833 : | orig[1] = Float:ida[2] | ||
2834 : | orig[2] = Float:ida[3] | ||
2835 : | entity_set_vector( ida[0], EV_VEC_origin, orig ) | ||
2836 : | } | ||
2837 : | |||
2838 : | public client_command( id ) | ||
2839 : | {//Forward to catch all formats for commands | ||
2840 : | if(!get_pcvar_num(p_climb)) | ||
2841 : | return PLUGIN_CONTINUE | ||
2842 : | new cmd[21] | ||
2843 : | read_argv(0,cmd,20) | ||
2844 : | |||
2845 : | //If say command, trim "say", abort if more than one word | ||
2846 : | if(equal(cmd,"say")||equal(cmd,"say_team")){ | ||
2847 : | read_argv(1,cmd,20) | ||
2848 : | trim(cmd) | ||
2849 : | if(contain(cmd," ")>-1)return PLUGIN_CONTINUE | ||
2850 : | } | ||
2851 : | |||
2852 : | //Remove slashes | ||
2853 : | if( equal(cmd,"/",1) || equal(cmd,"\",1) || equal(cmd,".",1) || equal(cmd,"!",1) ) | ||
2854 : | copy(cmd,20,cmd[1]) | ||
2855 : | |||
2856 : | //Make a checkpoint | ||
2857 : | if( equali(cmd,"checkpoint") || equali(cmd,"check") || equali(cmd,"cp") ) | ||
2858 : | check(id) | ||
2859 : | |||
2860 : | //Go to checkpoint | ||
2861 : | else if( equali(cmd,"gocheck") || equali(cmd,"gc") || equali(cmd,"tp") || equali(cmd,"tele") ) | ||
2862 : | gocheck(id) | ||
2863 : | |||
2864 : | //Ungocheck | ||
2865 : | else if( equali(cmd,"ungc") || equali(cmd,"ungocheck") ) | ||
2866 : | ungocheck(id) | ||
2867 : | |||
2868 : | //Boost help page | ||
2869 : | else if( equali(cmd,"boost") ) | ||
2870 : | boost_help(id) | ||
2871 : | |||
2872 : | //Solid Boost | ||
2873 : | else if( equali(cmd,"solid") || equali(cmd,"semiclip") ) | ||
2874 : | change_boost(id,CF_SOLID) | ||
2875 : | |||
2876 : | //Jump Boost | ||
2877 : | else if( equali(cmd,"superjump") || equali(cmd,"sjump") || equali(cmd,"sj") || equali(cmd,"longjump") ||\ | ||
2878 : | equali(cmd,"ljump") || equali(cmd,"lj") ) | ||
2879 : | change_boost(id,CF_SUPER_JUMP) | ||
2880 : | |||
2881 : | //Double Jump Boost | ||
2882 : | else if( equali(cmd,"doublejump") || equali(cmd,"djump") || equali(cmd,"dj") ) | ||
2883 : | change_boost(id,CF_DOUBLE_JUMP) | ||
2884 : | |||
2885 : | //Cycle CPs reverse | ||
2886 : | else if( equali(cmd,"cp-") || equali(cmd,"stuck") || equali(cmd,"unstuck") ) | ||
2887 : | { | ||
2888 : | cp_back( id ) | ||
2889 : | return PLUGIN_CONTINUE | ||
2890 : | } | ||
2891 : | |||
2892 : | //Cycle CPs forward | ||
2893 : | else if( equali(cmd,"cp+") ) | ||
2894 : | { | ||
2895 : | cp_forward( id ) | ||
2896 : | return PLUGIN_CONTINUE | ||
2897 : | } | ||
2898 : | |||
2899 : | //Pause | ||
2900 : | else if( equali(cmd,"pause") || equali(cmd,"unpause") ) | ||
2901 : | change_status(id,CF_PAUSE) | ||
2902 : | |||
2903 : | //Stop | ||
2904 : | else if( equali(cmd,"stop") ) | ||
2905 : | stop(id) | ||
2906 : | |||
2907 : | //Time/Scores | ||
2908 : | else if( equali(cmd,"scoreboard") || equali(cmd,"score") || equali(cmd,"scores") ) | ||
2909 : | climbscores(id) | ||
2910 : | |||
2911 : | //High Scores | ||
2912 : | else if( equali(cmd,"top10") || equali(cmd,"top15") || equali(cmd,"top") || equali(cmd,"highscores") ||\ | ||
2913 : | equali(cmd,"best") || equali(cmd,"rank") || equali(cmd,"pro15") || equali(cmd,"nub15") ) | ||
2914 : | highscores(id) | ||
2915 : | |||
2916 : | //Respawn | ||
2917 : | else if( equali( cmd, "respawn" ) || equali( cmd, "spawn" ) ) | ||
2918 : | frespawn( id ) | ||
2919 : | |||
2920 : | //TP to start button | ||
2921 : | else if( equali( cmd, "restart" ) || equali( cmd, "start" ) || equali( cmd, "reset" ) ) | ||
2922 : | tp_start_btn( id ) | ||
2923 : | |||
2924 : | //Spectate | ||
2925 : | else if( equali(cmd,"spectate") || equali(cmd,"spec") ) | ||
2926 : | spectate(id) | ||
2927 : | |||
2928 : | //Get scout | ||
2929 : | else if( equali( cmd, "scout" ) ) | ||
2930 : | give_scout( id ) | ||
2931 : | |||
2932 : | //Get usp | ||
2933 : | else if( equali( cmd, "usp" ) ) | ||
2934 : | give_usp( id ) | ||
2935 : | |||
2936 : | else if( equali( cmd, "weapons" ) ) | ||
2937 : | { | ||
2938 : | give_weapons( id ) | ||
2939 : | return PLUGIN_CONTINUE | ||
2940 : | } | ||
2941 : | |||
2942 : | else if( equali( cmd, "measure" ) ) | ||
2943 : | { | ||
2944 : | toggle_measure( id ) | ||
2945 : | return PLUGIN_CONTINUE | ||
2946 : | } | ||
2947 : | |||
2948 : | else if( equali( cmd, "measure2" ) ) | ||
2949 : | { | ||
2950 : | toggle_measure2( id ) | ||
2951 : | return PLUGIN_CONTINUE | ||
2952 : | } | ||
2953 : | |||
2954 : | else if( equali( cmd, "countdown" ) || equali( cmd, "countup" ) ) | ||
2955 : | { | ||
2956 : | toggle_countdown( id ) | ||
2957 : | return PLUGIN_CONTINUE | ||
2958 : | } | ||
2959 : | |||
2960 : | else if( equali( cmd, "sunglasses" ) ) | ||
2961 : | { | ||
2962 : | sunglasses( id ) | ||
2963 : | return PLUGIN_CONTINUE | ||
2964 : | } | ||
2965 : | |||
2966 : | //Climb Help | ||
2967 : | else if( equali( cmd, "climbhelp" ) || equali( cmd, "kzhelp" ) ) | ||
2968 : | climb_help( id ) | ||
2969 : | |||
2970 : | //If none of above conditions met, don't block the command | ||
2971 : | else return PLUGIN_CONTINUE | ||
2972 : | return PLUGIN_HANDLED | ||
2973 : | } | ||
2974 : | |||
2975 : | //////////////////////////////////////////////////////////////////////////////// | ||
2976 : | // End: Climb command handling functions | ||
2977 : | //////////////////////////////////////////////////////////////////////////////// | ||
2978 : | // Start: Measure functions | ||
2979 : | //////////////////////////////////////////////////////////////////////////////// | ||
2980 : | |||
2981 : | public toggle_measure( id ) | ||
2982 : | { | ||
2983 : | //Remove flag for other measure | ||
2984 : | new cflags = timer[id-1][TMR_CFLAGS] | ||
2985 : | if( cflags & CF_MEASURE2 ) timer[id-1][TMR_CFLAGS] = cflags & ~CF_MEASURE2 | ||
2986 : | |||
2987 : | //Toggle flag for this measure and print message | ||
2988 : | timer[id-1][TMR_CFLAGS] ^= CF_MEASURE | ||
2989 : | if( cflags & CF_MEASURE ) | ||
2990 : | clmsg( id, "Measure disabled." ) | ||
2991 : | else | ||
2992 : | clmsg( id, "Measure enabled, use attack to measure." ) | ||
2993 : | } | ||
2994 : | |||
2995 : | public do_measure( id ) | ||
2996 : | { | ||
2997 : | new Float:orig[3], Float:look[3], Float:end[3], Float:ret[3] | ||
2998 : | new Float:ln_st[3], Float:ln_fn[3] | ||
2999 : | |||
3000 : | entity_get_vector( id, EV_VEC_origin, orig ) | ||
3001 : | entity_get_vector( id, EV_VEC_view_ofs, ret ) | ||
3002 : | for( new i = 0; i < 3; i++ ) orig[i] += ret[i] | ||
3003 : | |||
3004 : | velocity_by_aim( id, 1, ret ) | ||
3005 : | for( new i = 0; i < 3; i++ ) end[i] = orig[i] + ( ret[i] * 9999 ) | ||
3006 : | |||
3007 : | trace_line( id, orig, end, ln_st ) | ||
3008 : | trace_normal( id, orig, end, look ) | ||
3009 : | |||
3010 : | for( new i = 0; i < 3; i++ ) end[i] = ln_st[i] + ( look[i] * 9999 ) | ||
3011 : | |||
3012 : | trace_line( id, ln_st, end, ln_fn ) | ||
3013 : | |||
3014 : | end[0] = ln_st[0] + ( ret[0] * -9999 ) | ||
3015 : | end[1] = ln_st[1] + ( ret[1] * -9999 ) | ||
3016 : | end[2] = ln_st[2] | ||
3017 : | |||
3018 : | trace_line( id, ln_st, end, orig ) | ||
3019 : | |||
3020 : | new msg[101] | ||
3021 : | format( msg, 100, "Distance: red %d / blue %d", | ||
3022 : | floatround( vector_distance( ln_st, ln_fn ), floatround_ceil ), | ||
3023 : | floatround( vector_distance( ln_st, orig ), floatround_ceil ) ) | ||
3024 : | clmsg( id, msg ) | ||
3025 : | console_print( id, msg ) | ||
3026 : | |||
3027 : | message_begin( MSG_ONE, SVC_TEMPENTITY, _, id ) | ||
3028 : | write_byte( TE_BEAMPOINTS ) | ||
3029 : | write_coord( floatround( ln_st[0] ) ) | ||
3030 : | write_coord( floatround( ln_st[1] ) ) | ||
3031 : | write_coord( floatround( ln_st[2] ) ) | ||
3032 : | write_coord( floatround( ln_fn[0] ) ) | ||
3033 : | write_coord( floatround( ln_fn[1] ) ) | ||
3034 : | write_coord( floatround( ln_fn[2] ) ) | ||
3035 : | write_short( beam_sprite ) // sprite index | ||
3036 : | write_byte( 0 ) // starting frame | ||
3037 : | write_byte( 10 ) // frame rate in 0.1's | ||
3038 : | write_byte( 100 ) // life in 0.1's | ||
3039 : | write_byte( 10 ) // line width in 0.1's | ||
3040 : | write_byte( 2 ) // noise amplitude in 0.01's | ||
3041 : | write_byte( 255 ) // Red | ||
3042 : | write_byte( 0 ) // Green | ||
3043 : | write_byte( 0 ) // Blue | ||
3044 : | write_byte( 127 ) // brightness | ||
3045 : | write_byte( 50 ) // scroll speed in 0.1's | ||
3046 : | message_end( ) | ||
3047 : | |||
3048 : | message_begin( MSG_ONE, SVC_TEMPENTITY, _, id ) | ||
3049 : | write_byte( TE_BEAMPOINTS ) | ||
3050 : | write_coord( floatround( ln_st[0] ) ) | ||
3051 : | write_coord( floatround( ln_st[1] ) ) | ||
3052 : | write_coord( floatround( ln_st[2] ) ) | ||
3053 : | write_coord( floatround( orig[0] ) ) | ||
3054 : | write_coord( floatround( orig[1] ) ) | ||
3055 : | write_coord( floatround( orig[2] ) ) | ||
3056 : | write_short( beam_sprite ) // sprite index | ||
3057 : | write_byte( 0 ) // starting frame | ||
3058 : | write_byte( 10 ) // frame rate in 0.1's | ||
3059 : | write_byte( 100 ) // life in 0.1's | ||
3060 : | write_byte( 10 ) // line width in 0.1's | ||
3061 : | write_byte( 2 ) // noise amplitude in 0.01's | ||
3062 : | write_byte( 0 ) // Red | ||
3063 : | write_byte( 0 ) // Green | ||
3064 : | write_byte( 255 ) // Blue | ||
3065 : | write_byte( 127 ) // brightness | ||
3066 : | write_byte( 50 ) // scroll speed in 0.1's | ||
3067 : | message_end( ) | ||
3068 : | } | ||
3069 : | |||
3070 : | public toggle_measure2( id ) | ||
3071 : | { | ||
3072 : | //Remove flag for other measure | ||
3073 : | new cflags = timer[id-1][TMR_CFLAGS] | ||
3074 : | if( cflags & CF_MEASURE ) timer[id-1][TMR_CFLAGS] = cflags & ~CF_MEASURE | ||
3075 : | |||
3076 : | //Toggle flag for this measure and print message | ||
3077 : | timer[id-1][TMR_CFLAGS] ^= CF_MEASURE2 | ||
3078 : | if( cflags & CF_MEASURE2 ) | ||
3079 : | clmsg( id, "Measure 2 disabled." ) | ||
3080 : | else | ||
3081 : | clmsg( id, "Measure 2 enabled, use attack to measure." ) | ||
3082 : | } | ||
3083 : | |||
3084 : | public tsk_do_measure2( tskid ) | ||
3085 : | do_measure2( tskid - TSK_MEASURE2 ) | ||
3086 : | |||
3087 : | stock do_measure2( id, set = 0 ) | ||
3088 : | { | ||
3089 : | new tskid = TSK_MEASURE2 + id | ||
3090 : | |||
3091 : | static Float:ln_st_static[32][3] | ||
3092 : | |||
3093 : | new Float:orig[3], Float:ret[3], Float:end[3] | ||
3094 : | |||
3095 : | entity_get_vector( id, EV_VEC_origin, orig ) | ||
3096 : | entity_get_vector( id, EV_VEC_view_ofs, ret ) | ||
3097 : | for( new i = 0; i < 3; i++ ) orig[i] += ret[i] | ||
3098 : | |||
3099 : | velocity_by_aim( id, 1, ret ) | ||
3100 : | |||
3101 : | for( new i = 0; i < 3; i++ ) end[i] = orig[i] + ( ret[i] * 9999 ) | ||
3102 : | trace_line( id, orig, end, ret ) | ||
3103 : | |||
3104 : | new Float:ln_st[3] | ||
3105 : | ln_st = ln_st_static[id-1] | ||
3106 : | |||
3107 : | //If first iteration, save point to static and return | ||
3108 : | if( !( ln_st[0] || ln_st[0] || ln_st[0] ) ) | ||
3109 : | { | ||
3110 : | ln_st_static[id-1] = ret | ||
3111 : | set_task( 0.1, "tsk_do_measure2", tskid, _, _, "b" ) | ||
3112 : | return | ||
3113 : | } | ||
3114 : | |||
3115 : | new Float:ln_fn[3], Float:ln_stmid[3], Float:ln_fnmid[3] | ||
3116 : | ln_fn = ret | ||
3117 : | |||
3118 : | ln_stmid[0] = ln_st[0] | ||
3119 : | ln_stmid[1] = ln_st[1] | ||
3120 : | ln_stmid[2] = ln_fn[2] | ||
3121 : | |||
3122 : | ln_fnmid[0] = ln_fn[0] | ||
3123 : | ln_fnmid[1] = ln_st[1] | ||
3124 : | ln_fnmid[2] = ln_fn[2] | ||
3125 : | |||
3126 : | new msg[101] | ||
3127 : | format( msg, 100, "Distance: r %d / g %d / b %d", | ||
3128 : | floatround( vector_distance( ln_st, ln_stmid ), floatround_ceil ), | ||
3129 : | floatround( vector_distance( ln_stmid, ln_fnmid ), floatround_ceil ), | ||
3130 : | floatround( vector_distance( ln_fnmid, ln_fn ), floatround_ceil ) ) | ||
3131 : | clmsg( id, msg ) | ||
3132 : | |||
3133 : | new life = 1, dest = MSG_ONE_UNRELIABLE | ||
3134 : | if( set ) | ||
3135 : | { | ||
3136 : | life = 125 | ||
3137 : | dest = MSG_ONE | ||
3138 : | console_print( id, msg ) | ||
3139 : | } | ||
3140 : | |||
3141 : | message_begin( dest, SVC_TEMPENTITY, _, id ) | ||
3142 : | write_byte( TE_BEAMPOINTS ) | ||
3143 : | write_coord( floatround( ln_st[0] ) ) | ||
3144 : | write_coord( floatround( ln_st[1] ) ) | ||
3145 : | write_coord( floatround( ln_st[2] ) ) | ||
3146 : | write_coord( floatround( ln_stmid[0] ) ) | ||
3147 : | write_coord( floatround( ln_stmid[1] ) ) | ||
3148 : | write_coord( floatround( ln_stmid[2] ) ) | ||
3149 : | write_short( beam_sprite ) // sprite index | ||
3150 : | write_byte( 0 ) // starting frame | ||
3151 : | write_byte( 10 ) // frame rate in 0.1's | ||
3152 : | write_byte( life ) // life in 0.1's | ||
3153 : | write_byte( 10 ) // line width in 0.1's | ||
3154 : | write_byte( 2 ) // noise amplitude in 0.01's | ||
3155 : | write_byte( 255 ) // Red | ||
3156 : | write_byte( 0 ) // Green | ||
3157 : | write_byte( 0 ) // Blue | ||
3158 : | write_byte( 127 ) // brightness | ||
3159 : | write_byte( 50 ) // scroll speed in 0.1's | ||
3160 : | message_end( ) | ||
3161 : | |||
3162 : | message_begin( dest, SVC_TEMPENTITY, _, id ) | ||
3163 : | write_byte( TE_BEAMPOINTS ) | ||
3164 : | write_coord( floatround( ln_stmid[0] ) ) | ||
3165 : | write_coord( floatround( ln_stmid[1] ) ) | ||
3166 : | write_coord( floatround( ln_stmid[2] ) ) | ||
3167 : | write_coord( floatround( ln_fnmid[0] ) ) | ||
3168 : | write_coord( floatround( ln_fnmid[1] ) ) | ||
3169 : | write_coord( floatround( ln_fnmid[2] ) ) | ||
3170 : | write_short( beam_sprite ) // sprite index | ||
3171 : | write_byte( 0 ) // starting frame | ||
3172 : | write_byte( 10 ) // frame rate in 0.1's | ||
3173 : | write_byte( life ) // life in 0.1's | ||
3174 : | write_byte( 10 ) // line width in 0.1's | ||
3175 : | write_byte( 2 ) // noise amplitude in 0.01's | ||
3176 : | write_byte( 0 ) // Red | ||
3177 : | write_byte( 255 ) // Green | ||
3178 : | write_byte( 0 ) // Blue | ||
3179 : | write_byte( 127 ) // brightness | ||
3180 : | write_byte( 50 ) // scroll speed in 0.1's | ||
3181 : | message_end( ) | ||
3182 : | |||
3183 : | message_begin( dest, SVC_TEMPENTITY, _, id ) | ||
3184 : | write_byte( TE_BEAMPOINTS ) | ||
3185 : | write_coord( floatround( ln_fnmid[0] ) ) | ||
3186 : | write_coord( floatround( ln_fnmid[1] ) ) | ||
3187 : | write_coord( floatround( ln_fnmid[2] ) ) | ||
3188 : | write_coord( floatround( ln_fn[0] ) ) | ||
3189 : | write_coord( floatround( ln_fn[1] ) ) | ||
3190 : | write_coord( floatround( ln_fn[2] ) ) | ||
3191 : | write_short( beam_sprite ) // sprite index | ||
3192 : | write_byte( 0 ) // starting frame | ||
3193 : | write_byte( 10 ) // frame rate in 0.1's | ||
3194 : | write_byte( life ) // life in 0.1's | ||
3195 : | write_byte( 10 ) // line width in 0.1's | ||
3196 : | write_byte( 2 ) // noise amplitude in 0.01's | ||
3197 : | write_byte( 0 ) // Red | ||
3198 : | write_byte( 0 ) // Green | ||
3199 : | write_byte( 255 ) // Blue | ||
3200 : | write_byte( 127 ) // brightness | ||
3201 : | write_byte( 50 ) // scroll speed in 0.1's | ||
3202 : | message_end( ) | ||
3203 : | |||
3204 : | //Remove task if flag has been removed | ||
3205 : | if( task_exists( tskid ) && !( timer[id-1][TMR_CFLAGS] & CF_MEASURE2 ) ) remove_task( tskid ) | ||
3206 : | |||
3207 : | //If a second point hasn't been set then end here | ||
3208 : | if( !set ) return | ||
3209 : | |||
3210 : | //If it gets this far it's the second iteration, /*so disable flag and*/ reset static var | ||
3211 : | //timer[id-1][TMR_CFLAGS] ^= CF_MEASURE2 | ||
3212 : | ln_st_static[id-1] = Float:{ 0.0, 0.0, 0.0 } | ||
3213 : | if( task_exists( tskid ) ) remove_task( tskid ) | ||
3214 : | } | ||
3215 : | |||
3216 : | //////////////////////////////////////////////////////////////////////////////// | ||
3217 : | // End: Measure functions | ||
3218 : | //////////////////////////////////////////////////////////////////////////////// | ||
3219 : | // Start: Blocked/Forwarded default CS commands | ||
3220 : | //////////////////////////////////////////////////////////////////////////////// | ||
3221 : | public client_kill( id ) | ||
3222 : | {//Block kill, forward to spectate command | ||
3223 : | if( get_pcvar_num( p_climb ) ) | ||
3224 : | { | ||
3225 : | spectate( id ) | ||
3226 : | return PLUGIN_HANDLED | ||
3227 : | } | ||
3228 : | return PLUGIN_CONTINUE | ||
3229 : | } | ||
3230 : | |||
3231 : | public block_cmd(id){//Block some commands if climb enabled | ||
3232 : | if(get_pcvar_num(p_climb))return PLUGIN_HANDLED | ||
3233 : | return PLUGIN_CONTINUE | ||
3234 : | } | ||
3235 : | |||
3236 : | public block_cmd2(id){//Used to block fullupdate always | ||
3237 : | return PLUGIN_HANDLED | ||
3238 : | } | ||
3239 : | |||
3240 : | public block_jointeam(id){//Block client trying to switch teams | ||
3241 : | if(get_pcvar_num(p_climb)&&isct(id))return PLUGIN_HANDLED | ||
3242 : | return PLUGIN_CONTINUE | ||
3243 : | } | ||
3244 : | |||
3245 : | public donothing(){//register_clcmd reference this function, but are picked up by the more flexible code in the client_command forward. | ||
3246 : | return PLUGIN_CONTINUE | ||
3247 : | } | ||
3248 : | |||
3249 : | public menuteam(id){//Connect choose team menu - force client to select CT | ||
3250 : | if(get_pcvar_num(p_climb))client_cmd(id,"slot2") | ||
3251 : | return PLUGIN_CONTINUE | ||
3252 : | } | ||
3253 : | |||
3254 : | public menuclass(id){//Force client to choose random model | ||
3255 : | if(get_pcvar_num(p_climb)){ | ||
3256 : | client_cmd(id,"slot5") | ||
3257 : | } | ||
3258 : | return PLUGIN_CONTINUE | ||
3259 : | } | ||
3260 : | |||
3261 : | //////////////////////////////////////////////////////////////////////////////// | ||
3262 : | // End: Blocked/Forwarded default CS commands | ||
3263 : | //////////////////////////////////////////////////////////////////////////////// | ||
3264 : | // Start: Database functions | ||
3265 : | //////////////////////////////////////////////////////////////////////////////// | ||
3266 : | public db_init( ) | ||
3267 : | { | ||
3268 : | |||
3269 : | static host[32], user[32], pass[32], name[32], type[12] | ||
3270 : | |||
3271 : | get_cvar_string( "climb_db_host", host, 31 ) | ||
3272 : | get_cvar_string( "climb_db_user", user, 31 ) | ||
3273 : | get_cvar_string( "climb_db_pass", pass, 31 ) | ||
3274 : | get_cvar_string( "climb_db_name", name, 31 ) | ||
3275 : | get_cvar_string( "climb_db_type", type, 11 ) | ||
3276 : | get_cvar_string( "climb_db_prefix", DB_PREFIX, 10 ) | ||
3277 : | get_cvar_string( "climb_db_serverid", DB_SERVER_ID, 15 ) | ||
3278 : | |||
3279 : | //SQL_SetAffinity(type) | ||
3280 : | DB_TUPLE=SQL_MakeDbTuple(host,user,pass,name) | ||
3281 : | |||
3282 : | if( !get_cvar_num( "climb_db_exists" ) ) | ||
3283 : | { | ||
3284 : | new autoinc[15]="autoincrement" | ||
3285 : | if(equal(type,"mysql"))autoinc="auto_increment" | ||
3286 : | new query[600] | ||
3287 : | |||
3288 : | formatex( query, 599, | ||
3289 : | "create table if not exists %splayers (\ | ||
3290 : | user_id integer primary key %s,\ | ||
3291 : | steam_id char(25) unique,\ | ||
3292 : | password char(6),\ | ||
3293 : | user_name varchar(20) unique,\ | ||
3294 : | alias varchar(32) unique,\ | ||
3295 : | email varchar(50) unique,\ | ||
3296 : | cflags integer)", | ||
3297 : | DB_PREFIX, autoinc ) | ||
3298 : | SQL_ThreadQuery( DB_TUPLE, "db_generic_handler", query ) | ||
3299 : | |||
3300 : | formatex( query, 599, | ||
3301 : | "create table if not exists %sscores (\ | ||
3302 : | score_id integer primary key %s,\ | ||
3303 : | score integer,\ | ||
3304 : | server_ip char(15),\ | ||
3305 : | user_id integer,\ | ||
3306 : | map_name varchar(32),\ | ||
3307 : | fin_time integer,\ | ||
3308 : | cps integer,\ | ||
3309 : | gcs integer,\ | ||
3310 : | boosts integer,\ | ||
3311 : | wpns integer,\ | ||
3312 : | server_time_stamp integer)", | ||
3313 : | DB_PREFIX, autoinc ) | ||
3314 : | SQL_ThreadQuery(DB_TUPLE,"db_generic_handler",query) | ||
3315 : | |||
3316 : | formatex( query, 599, "create index scores_score on %sscores (score)", DB_PREFIX ) | ||
3317 : | SQL_ThreadQuery( DB_TUPLE, "db_generic_handler", query ) | ||
3318 : | |||
3319 : | formatex( query, 599, | ||
3320 : | "create table if not exists %ssessions (\ | ||
3321 : | steam_id char(25) primary key,\ | ||
3322 : | user_id integer unique)", | ||
3323 : | DB_PREFIX ) | ||
3324 : | SQL_ThreadQuery( DB_TUPLE, "db_generic_handler", query ) | ||
3325 : | |||
3326 : | set_cvar_num( "climb_db_exists", 1 ) | ||
3327 : | } | ||
3328 : | } | ||
3329 : | |||
3330 : | public db_generic_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) | ||
3331 : | return query_failed( failstate, error, errnum ) | ||
3332 : | |||
3333 : | public auto_login(ida[1]) | ||
3334 : | { | ||
3335 : | new id=ida[0] | ||
3336 : | |||
3337 : | //debug | ||
3338 : | new name[33],sid[33],data[2],query[151] | ||
3339 : | get_user_name( id, name, 32 ) | ||
3340 : | get_user_authid( id, sid, 32 ) | ||
3341 : | //log_amx( "CLIMB: auto_login( %d ) / %s / %s", id, name, sid ) | ||
3342 : | |||
3343 : | data[0] = id | ||
3344 : | data[1] = 2 | ||
3345 : | formatex( query, 150, | ||
3346 : | "select user_id, steam_id, password from %splayers where steam_id=^"%s^"", | ||
3347 : | DB_PREFIX, sid ) | ||
3348 : | //formatex( data[2], 24, sid) | ||
3349 : | SQL_ThreadQuery( DB_TUPLE, "login_handler", query, data, 2 ) | ||
3350 : | |||
3351 : | //log_amx( "CLIMB: Login Query for id=%d - ^"%s^";", id, query ) | ||
3352 : | |||
3353 : | //return client_cmd( id, "login" ) | ||
3354 : | //return db_login( id ) | ||
3355 : | } | ||
3356 : | |||
3357 : | public db_login( id ) | ||
3358 : | { | ||
3359 : | //log_amx( "CLIMB: Function entry - login( %d )", id ) | ||
3360 : | if( get_pcvar_num( p_climb ) ) | ||
3361 : | { | ||
3362 : | if( CLIMB_SAVE ) | ||
3363 : | { | ||
3364 : | //log_amx( "CLIMB: Begin login client id=%d.", id ) | ||
3365 : | //log_amx( "CLIMB: timer[id-1][TMR_DBUSER]=%d.", timer[id-1][TMR_DBUSER] ) | ||
3366 : | |||
3367 : | if( timer[id-1][TMR_DBUSER] > 0 ) //Already logged in | ||
3368 : | { | ||
3369 : | client_print( id, print_console, "[Climb] Login Error: You are already logged in." ) | ||
3370 : | return PLUGIN_HANDLED | ||
3371 : | } | ||
3372 : | new query[151], data[2] //data[28] | ||
3373 : | data[0] = id | ||
3374 : | |||
3375 : | /*if( read_argc() > 1 ) //Client is logging in with a user/pass | ||
3376 : | { | ||
3377 : | new user[21], pass[21] | ||
3378 : | read_argv( 1, user, 20 ) | ||
3379 : | read_argv( 2, pass, 20 ) | ||
3380 : | rotwtf( pass, 6 ) | ||
3381 : | data[1] = 1 | ||
3382 : | formatex( query, 150, | ||
3383 : | "select user_id, steam_id, from %splayers where user_id=^"%s^" and password=^"%s^";", | ||
3384 : | DB_PREFIX, user, pass ) | ||
3385 : | //formatex( data[2], 24, user) | ||
3386 : | SQL_ThreadQuery( DB_TUPLE, "login_handler", query, data, 2 ) | ||
3387 : | } | ||
3388 : | else //Client is logging in with SteamID | ||
3389 : | {*/ | ||
3390 : | new sid[32] | ||
3391 : | get_user_authid( id, sid, 31 ) | ||
3392 : | data[1] = 2 | ||
3393 : | formatex( query, 150, | ||
3394 : | "select user_id, steam_id, password from %splayers where steam_id=^"%s^"", | ||
3395 : | DB_PREFIX, sid ) | ||
3396 : | //formatex( data[2], 24, sid) | ||
3397 : | SQL_ThreadQuery( DB_TUPLE, "login_handler", query, data, 2 ) | ||
3398 : | |||
3399 : | //log_amx( "CLIMB: Login Query for id=%d - ^"%s^";", id, query ) | ||
3400 : | //} | ||
3401 : | } | ||
3402 : | else client_print( id, print_console, "[Climb] Login Error: Can't Login; Stats not enabled." ) | ||
3403 : | } | ||
3404 : | return PLUGIN_HANDLED | ||
3405 : | } | ||
3406 : | |||
3407 : | public login_handler( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3408 : | { | ||
3409 : | new id = data[0] | ||
3410 : | //log_amx( "CLIMB: Function entry - login_handler( %d )", id ) | ||
3411 : | //If they've disonnected since the login attempt initiated, abort | ||
3412 : | if( !is_user_connected( id ) ) return log_amx( "CLIMB: Login Error id=%d - Client no longer exists.", id ) | ||
3413 : | |||
3414 : | if( SQL_NumResults( query ) < 1 ) | ||
3415 : | { | ||
3416 : | //log_amx( "CLIMB: Login Error id=%d - Not a valid account. 0 result returned", id ) | ||
3417 : | return client_print( id, print_console, "[Climb] Login Error: Not a valid account." ) | ||
3418 : | } | ||
3419 : | |||
3420 : | if( !query_failed( failstate, error, errnum) ) | ||
3421 : | { | ||
3422 : | //If database steamid doesn't match client steamid, abort | ||
3423 : | new db_sid[32], sid[32] | ||
3424 : | SQL_ReadResult( query, 1, db_sid, 31 ) | ||
3425 : | get_user_authid( id, sid, 31 ) | ||
3426 : | if( !equal( sid, db_sid ) ) return log_amx( "CLIMB: Login Error id=%d - SteamID mismatch.", id ) | ||
3427 : | |||
3428 : | //Fail if steamid login attempt, and steamid is registered as shared | ||
3429 : | if( data[1] == 2 ) | ||
3430 : | { | ||
3431 : | new pass[7] | ||
3432 : | SQL_ReadResult( query, 2, pass, 6 ) | ||
3433 : | if( equali( pass, "shared" ) ) | ||
3434 : | { | ||
3435 : | //log_amx( "CLIMB: Login Error id=%d - Shared SteamID.", id ) | ||
3436 : | return client_print( id, print_console,\ | ||
3437 : | "[Climb] Login Error: You are using a shared SteamID. Please login with a username and password." ) | ||
3438 : | } | ||
3439 : | } | ||
3440 : | |||
3441 : | //Everything is ok, add db userid to timer info, display login messages | ||
3442 : | timer[id-1][TMR_DBUSER] = SQL_ReadResult( query, 0 ) | ||
3443 : | new msg[100] | ||
3444 : | formatex( msg, 99, "[Climb] Login: Success - Account: %s", sid ) | ||
3445 : | //log_amx( "CLIMB: Login Success id=%d", id ) | ||
3446 : | client_print(id,print_console,msg ) | ||
3447 : | format( msg, 99, "^x04%s", msg ) | ||
3448 : | saytext( id, id, msg ) | ||
3449 : | |||
3450 : | //If they just registered and logged in, save score, else load score | ||
3451 : | if( timer[id-1][TMR_CFLAGS] & CF_JUST_REGD ) | ||
3452 : | { | ||
3453 : | db_save( id ) | ||
3454 : | timer[id-1][TMR_CFLAGS] -= CF_JUST_REGD | ||
3455 : | } | ||
3456 : | else db_load(id) | ||
3457 : | } | ||
3458 : | return PLUGIN_HANDLED | ||
3459 : | } | ||
3460 : | |||
3461 : | /*public logout(id) | ||
3462 : | { | ||
3463 : | for(new i=0;i<8;i++)origins[id-1][i]=0.0 | ||
3464 : | for(new i=0;i<11;i++)timer[id-1][i]=0 | ||
3465 : | }*/ | ||
3466 : | |||
3467 : | public db_load( id ) | ||
3468 : | { | ||
3469 : | new query[351], mapname[33], data[1] | ||
3470 : | data[0] = id | ||
3471 : | get_mapname( mapname, 32 ) | ||
3472 : | /*formatex( query, 149, | ||
3473 : | "select fin_time, cps, gcs, fin_cnt, boosts, wpns from %sscores where user_id=%d and map_name=^"%s^";", | ||
3474 : | DB_PREFIX, timer[id-1][TMR_DBUSER], mapname )*/ | ||
3475 : | formatex( query, 350, | ||
3476 : | "select s.fin_time, s.cps, s.gcs, g.fin_cnt, s.boosts, s.wpns from %sscores s, (select user_id, count(*) fin_cnt from %sscores where map_name = ^"%s^" group by user_id) g where map_name = ^"%s^" and s.user_id = %d and g.user_id = %d", | ||
3477 : | DB_PREFIX, DB_PREFIX, mapname, mapname, timer[id-1][TMR_DBUSER], timer[id-1][TMR_DBUSER] ) | ||
3478 : | SQL_ThreadQuery( DB_TUPLE, "db_load_handler", query, data, 1 ) | ||
3479 : | } | ||
3480 : | |||
3481 : | public db_load_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) | ||
3482 : | { | ||
3483 : | new id=data[0] | ||
3484 : | if( !query_failed( failstate, error, errnum) ) | ||
3485 : | { | ||
3486 : | new msg[100] | ||
3487 : | if(!SQL_NumResults(query)) | ||
3488 : | msg="^x04No stats available for this account on the current map." | ||
3489 : | else | ||
3490 : | { | ||
3491 : | new mapname[33],timestr[9] | ||
3492 : | get_mapname(mapname,32) | ||
3493 : | timer[id-1][TMR_BSTTME] = SQL_ReadResult( query, 0 ) | ||
3494 : | timer[id-1][TMR_BSTCPS] = SQL_ReadResult( query, 1 ) | ||
3495 : | timer[id-1][TMR_BSTGCS] = SQL_ReadResult( query, 2 ) | ||
3496 : | timer[id-1][TMR_MAPFIN] = SQL_ReadResult( query, 3 ) | ||
3497 : | timer[id-1][TMR_BSTBST] = SQL_ReadResult( query, 4 ) | ||
3498 : | timer[id-1][TMR_BSTWPN] = SQL_ReadResult( query, 5 ) | ||
3499 : | //timer[id-1][TMR_CFLAGS]+=SQL_ReadResult(query,5)?CF_BSTSCT:0 | ||
3500 : | |||
3501 : | timestr = parsetime(timer[id-1][TMR_BSTTME]) | ||
3502 : | formatex( msg, 99, | ||
3503 : | "^x04Stats loaded for %s - %s^t(%d/ %d CP/%d GC/%d Boost)^tCompleted %d", | ||
3504 : | mapname, timestr, timer[id-1][TMR_BSTWPN], timer[id-1][TMR_BSTCPS], | ||
3505 : | timer[id-1][TMR_BSTGCS], timer[id-1][TMR_BSTBST], timer[id-1][TMR_MAPFIN] ) | ||
3506 : | } | ||
3507 : | saytext( id, id, msg ) | ||
3508 : | } | ||
3509 : | else client_print( id, print_chat, "[Climb] DB Read Error: Please notify a server admin." ) | ||
3510 : | return PLUGIN_HANDLED | ||
3511 : | } | ||
3512 : | |||
3513 : | public db_save( id ) | ||
3514 : | { | ||
3515 : | if( timer[id-1][TMR_DBUSER] < 1 ) | ||
3516 : | { | ||
3517 : | auto_reg( id ) | ||
3518 : | return PLUGIN_HANDLED | ||
3519 : | } | ||
3520 : | new query[351], name[33], data[2] | ||
3521 : | data[0] = id | ||
3522 : | get_mapname( name, 32 ) | ||
3523 : | strtolower( name ) | ||
3524 : | |||
3525 : | new user_id = timer[id-1][TMR_DBUSER] | ||
3526 : | new fin_time = get_climber_time( id ) | ||
3527 : | |||
3528 : | new wpn_rank = timer[id-1][TMR_CNTWPN] | ||
3529 : | |||
3530 : | new score = ( ( ( timer[id-1][TMR_CNTBST] > 0 ? 1 : 0 ) * 1000000 ) + | ||
3531 : | ( ( timer[id-1][TMR_CNTCPS] > 0 ? 1 : 0 ) * 100000 ) + | ||
3532 : | ( wpn_rank * 10000 ) + | ||
3533 : | fin_time ) | ||
3534 : | |||
3535 : | /*if( timer[id-1][TMR_MAPFIN] == 1 ) | ||
3536 : | formatex( query, 350, | ||
3537 : | "insert into %sscores (user_id, map_name, fin_time, cps, gcs, fin_cnt, boosts, wpns, score, server_time_stamp) values (%d, ^"%s^", %d, %d, %d, %d, %d, %d, %d, %d);",\ | ||
3538 : | DB_PREFIX, user_id, name, fin_time, timer[id-1][TMR_BSTCPS], timer[id-1][TMR_BSTGCS], timer[id-1][TMR_MAPFIN], timer[id-1][TMR_BSTBST], sctd, sort, get_systime() ) | ||
3539 : | else*/ | ||
3540 : | formatex( query, 350, | ||
3541 : | "insert into %sscores (server_ip, user_id, map_name, fin_time, cps, gcs, boosts, wpns, score, server_time_stamp) values (^"%s^", %d, ^"%s^", %d, %d, %d, %d, %d, %d, %d)",\ | ||
3542 : | DB_PREFIX, DB_SERVER_ID, user_id, name, fin_time, timer[id-1][TMR_CNTCPS], timer[id-1][TMR_CNTGCS], timer[id-1][TMR_CNTBST], wpn_rank, score, get_systime() ) | ||
3543 : | SQL_ThreadQuery(DB_TUPLE,"db_save_handler",query,data,2) | ||
3544 : | |||
3545 : | data[1] = 0 | ||
3546 : | get_user_name( id, name, 32 ) | ||
3547 : | formatex( query, 350, "update %splayers set alias=^"%s^" where user_id=%d;", DB_PREFIX, name, timer[id-1][TMR_DBUSER] ) | ||
3548 : | SQL_ThreadQuery( DB_TUPLE, "db_name_update_handler", query, data, 2 ) | ||
3549 : | return PLUGIN_HANDLED | ||
3550 : | } | ||
3551 : | |||
3552 : | public db_save_handler( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3553 : | { | ||
3554 : | if( query_failed( failstate, error, errnum ) ) | ||
3555 : | { | ||
3556 : | new id=data[0] | ||
3557 : | client_print(id,print_chat,"[Climb] DB Write Error: Could not update your score. Please notify a server admin.") | ||
3558 : | } | ||
3559 : | |||
3560 : | return PLUGIN_HANDLED | ||
3561 : | } | ||
3562 : | |||
3563 : | public db_name_update_handler( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3564 : | { | ||
3565 : | if( query_failed( failstate, error, errnum ) ) | ||
3566 : | { | ||
3567 : | new id = data[0] | ||
3568 : | |||
3569 : | if( data[1] > 9 ) | ||
3570 : | client_print(id,print_chat,"[Climb] DB Write Error: Could not update your name. Please notify a server admin.") | ||
3571 : | else | ||
3572 : | { | ||
3573 : | new query[250] | ||
3574 : | new data2[2] | ||
3575 : | data2[0] = id | ||
3576 : | data2[1] = data[1] + 1 | ||
3577 : | |||
3578 : | |||
3579 : | new name[33] | ||
3580 : | get_user_name( id, name, 29 ) | ||
3581 : | format( name, 32, "%s(%d)", name, data2[1] ) | ||
3582 : | |||
3583 : | formatex( query, 249,\ | ||
3584 : | "update %splayers set alias=^"%s^" where user_id=%d;",\ | ||
3585 : | DB_PREFIX, name, timer[id-1][TMR_DBUSER] ) | ||
3586 : | SQL_ThreadQuery(DB_TUPLE,"db_name_update_handler",query,data2,2) | ||
3587 : | } | ||
3588 : | } | ||
3589 : | |||
3590 : | return PLUGIN_HANDLED | ||
3591 : | } | ||
3592 : | |||
3593 : | public reg(id) | ||
3594 : | { | ||
3595 : | if(get_pcvar_num(p_climb)){ | ||
3596 : | if(CLIMB_SAVE){ | ||
3597 : | new query[100],sid[26],name[33],data[43] | ||
3598 : | data[0]=id | ||
3599 : | data[1]=0 | ||
3600 : | get_user_authid(id,sid,25) | ||
3601 : | get_user_name(id,name,32) | ||
3602 : | //Register user/pass | ||
3603 : | if(read_argc()>1){ | ||
3604 : | if(read_argc()!=3){ | ||
3605 : | client_print(id,print_console,"[Climb] Registration Error: Invalid number of arguments") | ||
3606 : | return PLUGIN_HANDLED | ||
3607 : | } | ||
3608 : | new user[21],pass[50] | ||
3609 : | //Read password and check length | ||
3610 : | read_argv(2,pass,20) | ||
3611 : | if(strlen(pass)<10){ | ||
3612 : | client_print(id,print_console,"[Climb] Registration Error: Password must be at least 10 characters.") | ||
3613 : | return PLUGIN_HANDLED | ||
3614 : | } | ||
3615 : | //Read user | ||
3616 : | read_argv(1,user,20) | ||
3617 : | //Store user/pass in data array to pass to handler for autologin | ||
3618 : | formatex(data[2],20,user) | ||
3619 : | formatex(data[22],20,pass) | ||
3620 : | //Create password hash | ||
3621 : | rotwtf(pass,6) | ||
3622 : | //Register shared SteamID | ||
3623 : | formatex(query,99,"insert into %splayers (steam_id,password) values (^"%s^",'shared')",DB_PREFIX,sid) | ||
3624 : | SQL_ThreadQuery(DB_TUPLE,"reg_handler",query,data,43) | ||
3625 : | //Register user/pass | ||
3626 : | data[1]=1 | ||
3627 : | formatex(query,99,"insert into %splayers (user_name,password,alias) values (^"%s^",^"%s^",^"%s^")",DB_PREFIX,user,pass,name) | ||
3628 : | SQL_ThreadQuery(DB_TUPLE,"reg_handler",query,data,43) | ||
3629 : | } | ||
3630 : | //Else register SteamID | ||
3631 : | /*else if(timer[id-1][TMR_DBUSER]<1){ | ||
3632 : | data[1]=2 | ||
3633 : | formatex(query,99,"insert into %splayers (steam_id,alias) values (^"%s^",^"%s^")",DB_PREFIX,sid,name) | ||
3634 : | SQL_ThreadQuery(DB_TUPLE,"reg_handler",query,data,43) | ||
3635 : | }*/ | ||
3636 : | } | ||
3637 : | else client_print(id,print_console,"[Climb] Registration Error: Can't Register; Stats not enabled.") | ||
3638 : | } | ||
3639 : | return PLUGIN_HANDLED | ||
3640 : | } | ||
3641 : | |||
3642 : | public auto_reg(id) | ||
3643 : | { | ||
3644 : | new query[100],sid[26],name[33],data[43] | ||
3645 : | data[0]=id | ||
3646 : | data[1]=2 | ||
3647 : | get_user_authid(id,sid,25) | ||
3648 : | get_user_name(id,name,32) | ||
3649 : | formatex(query,99,"insert into %splayers (steam_id,alias) values (^"%s^",^"%s^")",DB_PREFIX,sid,name) | ||
3650 : | SQL_ThreadQuery(DB_TUPLE,"reg_handler",query,data,43) | ||
3651 : | return PLUGIN_HANDLED | ||
3652 : | } | ||
3653 : | |||
3654 : | public reg_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) | ||
3655 : | { | ||
3656 : | new id=data[0] | ||
3657 : | if( !query_failed( failstate, error, errnum) ) | ||
3658 : | { | ||
3659 : | new flag=data[1],user[21],pass[21] | ||
3660 : | format(user,20,data[2]) | ||
3661 : | format(pass,20,data[22]) | ||
3662 : | |||
3663 : | if(flag==0)client_print(id,print_console,"[Climb] Recorded shared SteamID.") | ||
3664 : | else if(flag==1){ | ||
3665 : | client_print(id,print_console,"[Climb] Registration Successful.") | ||
3666 : | |||
3667 : | new cmd[50] | ||
3668 : | formatex(cmd,49,"login %s %s",user,pass) | ||
3669 : | client_cmd(id,cmd) | ||
3670 : | } | ||
3671 : | else if(flag==2){ | ||
3672 : | timer[id-1][TMR_CFLAGS]+=CF_JUST_REGD | ||
3673 : | client_cmd(id,"login") | ||
3674 : | } | ||
3675 : | } | ||
3676 : | else client_print(id,print_chat,"[Climb] DB Registration Error: Please notify a server admin.") | ||
3677 : | return PLUGIN_HANDLED | ||
3678 : | } | ||
3679 : | |||
3680 : | public highscores(id) | ||
3681 : | {//Show High Scores | ||
3682 : | if( !CLIMB_SAVE ) return clmsg( id, "Stats not enabled.") | ||
3683 : | |||
3684 : | new hsurl[150], mapname[33] | ||
3685 : | get_pcvar_string( p_stats_hsurl, hsurl, 149 ) | ||
3686 : | get_mapname( mapname, 32 ) | ||
3687 : | if( strlen( hsurl ) ) | ||
3688 : | { | ||
3689 : | format( hsurl, 149, hsurl, mapname ) | ||
3690 : | show_motd( id, hsurl, "High Scores" ) | ||
3691 : | return PLUGIN_HANDLED | ||
3692 : | } | ||
3693 : | if( get_systime() - ts_hscore > 10 ) | ||
3694 : | { | ||
3695 : | new query[501], data[1] | ||
3696 : | data[0] = id | ||
3697 : | /*formatex( query, 249,\ | ||
3698 : | "select p.alias, s.fin_time, s.cps, s.gcs, s.fin_cnt, s.boosts, s.wpns from %sscores s, %splayers p where s.map_name=^"%s^" and p.user_id=s.user_id order by s.score, s.fin_time limit 20;",\ | ||
3699 : | DB_PREFIX, DB_PREFIX, mapname )*/ | ||
3700 : | formatex( query, 500, | ||
3701 : | "select distinct p.alias, s.fin_time, s.cps, s.gcs, g.fin_cnt, s.boosts, s.wpns, s.score from %sscores s join %splayers p on s.user_id = p.user_id join (select user_id, min(score) minscore, count(*) fin_cnt from %sscores where map_name=^"%s^" group by user_id, wpns) g on p.user_id=g.user_id where map_name=^"%s^" and s.score=g.minscore order by s.score limit 20", | ||
3702 : | DB_PREFIX, DB_PREFIX, DB_PREFIX, mapname, mapname ) | ||
3703 : | SQL_ThreadQuery( DB_TUPLE, "hs_handler", query, data, 1 ) | ||
3704 : | ts_hscore = get_systime() | ||
3705 : | } | ||
3706 : | else | ||
3707 : | { | ||
3708 : | if( has_hscores ) | ||
3709 : | show_motd( id, HSCORES_PATH, "High Scores" ) | ||
3710 : | else | ||
3711 : | { | ||
3712 : | new msg[101] | ||
3713 : | format( msg, 100, "^x04[Climb] No stats available for the current map." ) | ||
3714 : | return saytext( id, id, msg ) | ||
3715 : | } | ||
3716 : | } | ||
3717 : | |||
3718 : | return PLUGIN_HANDLED | ||
3719 : | } | ||
3720 : | |||
3721 : | public hs_handler(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime) | ||
3722 : | { | ||
3723 : | if( !query_failed( failstate, error, errnum) ) | ||
3724 : | { | ||
3725 : | new id=data[0],msg[101],num=SQL_NumResults(query) | ||
3726 : | if(!num){ | ||
3727 : | format(msg,100,"^x04[Climb] No stats available for the current map.") | ||
3728 : | return saytext(id,id,msg) | ||
3729 : | } | ||
3730 : | |||
3731 : | has_hscores = true | ||
3732 : | |||
3733 : | new fh = fopen( HSCORES_PATH, "w" ) | ||
3734 : | |||
3735 : | fprintf( fh, "<link rel=stylesheet href=http://ian.cammarata.us/sb><table><tr><td id=a>" ) | ||
3736 : | fprintf( fh, "<pre># Name Time Wpn/CP/GC/Boost Fin</pre>" ) | ||
3737 : | fprintf( fh, "</td></tr><tr id=b><td></td></tr><tr><td><pre>" ) | ||
3738 : | |||
3739 : | new name[NAMELEN+2], line[151], written_len, btime_str[20] | ||
3740 : | for( new i = 1; i <= num; i++ ) | ||
3741 : | { | ||
3742 : | SQL_ReadResult( query, 0, name, NAMELEN ) | ||
3743 : | sb_add_tabs( name, NAMELEN+2 ) | ||
3744 : | |||
3745 : | |||
3746 : | format( btime_str, 19, "%d/%d/%d/%d",\ | ||
3747 : | SQL_ReadResult( query, 6 ),\ | ||
3748 : | SQL_ReadResult( query, 2 ),\ | ||
3749 : | SQL_ReadResult( query, 3 ),\ | ||
3750 : | SQL_ReadResult( query, 5 ) ) | ||
3751 : | sb_add_tabs( btime_str, 19 ) | ||
3752 : | |||
3753 : | formatex( line, 150,\ | ||
3754 : | "%s%d %s%s %s %d%s", | ||
3755 : | i % 2 ? "" : "<div>", | ||
3756 : | i, htmlspecialchars( name ), | ||
3757 : | parsetime( SQL_ReadResult( query, 1 ) ), | ||
3758 : | btime_str, | ||
3759 : | SQL_ReadResult( query, 4 ), | ||
3760 : | i % 2 ? "" : "</div>" ) | ||
3761 : | written_len += strlen( line ) | ||
3762 : | if( written_len > 1263 ) break | ||
3763 : | fprintf( fh, line ) | ||
3764 : | SQL_NextRow( query ) | ||
3765 : | } | ||
3766 : | |||
3767 : | //1530-150-117=1263 | ||
3768 : | new cust_msg[33] | ||
3769 : | get_pcvar_string( p_stats_msg, cust_msg, 32 ) | ||
3770 : | if( !strlen( cust_msg ) ) formatex( cust_msg, 32, "Climb %s", VERSION ) | ||
3771 : | fprintf( fh, "</pre></td></tr><tr id=d><td></td></tr><tr><td id=e></td></tr><tr>" ) | ||
3772 : | fprintf( fh, "<td id=a>%s</td></tr></table>", cust_msg ) | ||
3773 : | fclose( fh ) | ||
3774 : | |||
3775 : | show_motd( id, HSCORES_PATH, "High Scores" ) | ||
3776 : | } | ||
3777 : | return PLUGIN_HANDLED | ||
3778 : | } | ||
3779 : | |||
3780 : | public climb_dbwho(id,level,cid) | ||
3781 : | { | ||
3782 : | if(cmd_access(id,level,cid,0)) | ||
3783 : | { | ||
3784 : | console_print(id,"^n# DB ID (<0=Not in DB), Name") | ||
3785 : | |||
3786 : | new players[32],count,name[21],id2 | ||
3787 : | get_players( players, count, "ch" ) | ||
3788 : | for( new i=0; i<count; i++ ) | ||
3789 : | { | ||
3790 : | id2=players[i] | ||
3791 : | get_user_name(id2,name,20) | ||
3792 : | console_print(id,"# %d, %s",timer[id2-1][TMR_DBUSER],name) | ||
3793 : | } | ||
3794 : | console_print( id, "%d Players", count ) | ||
3795 : | } | ||
3796 : | return PLUGIN_HANDLED | ||
3797 : | } | ||
3798 : | |||
3799 : | public climb_dbmap( id, level, cid ) | ||
3800 : | { | ||
3801 : | if( cmd_access( id, level, cid, 0 ) ) | ||
3802 : | { | ||
3803 : | new mapname[33] | ||
3804 : | if( read_argc()>1 )read_argv( 1, mapname, 32 ) | ||
3805 : | if( !strlen(mapname) )get_mapname( mapname, 32 ) | ||
3806 : | |||
3807 : | new query[501], data[1] | ||
3808 : | data[0]=id | ||
3809 : | |||
3810 : | /*formatex( query, 500, | ||
3811 : | "select p.alias, s.score_id, s.fin_time, s.cps, s.gcs, s.boosts, s.wpns from %sscores s, %splayers p where s.map_name=^"%s^" and p.user_id=s.user_id order by s.score, s.fin_time limit 20;", | ||
3812 : | DB_PREFIX, DB_PREFIX, mapname)*/ | ||
3813 : | formatex( query, 500, | ||
3814 : | "select distinct p.alias, s.score_id, s.fin_time, s.cps, s.gcs, s.boosts, s.wpns from %sscores s join %splayers p on s.user_id = p.user_id join (select user_id, min(score) minscore, count(*) fin_cnt from %sscores where map_name=^"%s^" group by user_id, wpns) g on p.user_id=g.user_id where map_name=^"%s^" and s.score=g.minscore order by s.score limit 20", | ||
3815 : | DB_PREFIX, DB_PREFIX, DB_PREFIX, mapname, mapname ) | ||
3816 : | SQL_ThreadQuery( DB_TUPLE, "climb_dbmap_handler", query, data, 1 ) | ||
3817 : | } | ||
3818 : | return PLUGIN_HANDLED | ||
3819 : | } | ||
3820 : | |||
3821 : | public climb_dbmap_handler( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3822 : | { | ||
3823 : | if( !query_failed( failstate, error, errnum) ) | ||
3824 : | { | ||
3825 : | new id=data[0] | ||
3826 : | new count=SQL_NumResults( query ) | ||
3827 : | if( count ) | ||
3828 : | { | ||
3829 : | new name[21] | ||
3830 : | console_print( id, "^n# Alias, Score ID, Time, cps/gcs/boosts, Scout" ) | ||
3831 : | for( new i=0; i<count; i++ ) | ||
3832 : | { | ||
3833 : | SQL_ReadResult( query, 0, name, 20 ) | ||
3834 : | console_print( id, "# %s, %d, %d, %d/%d/%d, %s",\ | ||
3835 : | name,\ | ||
3836 : | SQL_ReadResult( query, 1 ),\ | ||
3837 : | SQL_ReadResult( query, 2 ),\ | ||
3838 : | SQL_ReadResult( query, 3 ),\ | ||
3839 : | SQL_ReadResult( query, 4 ),\ | ||
3840 : | SQL_ReadResult( query, 5 ),\ | ||
3841 : | SQL_ReadResult( query, 6 )?"y":"n") | ||
3842 : | SQL_NextRow( query ) | ||
3843 : | } | ||
3844 : | console_print( id, "%d Result(s)", count ) | ||
3845 : | } | ||
3846 : | else console_print( id, "Query returned no results." ) | ||
3847 : | } | ||
3848 : | return PLUGIN_HANDLED | ||
3849 : | } | ||
3850 : | |||
3851 : | public climb_dbuser( id, level, cid ) | ||
3852 : | { | ||
3853 : | if( cmd_access( id, level, cid, 1 ) ) | ||
3854 : | { | ||
3855 : | new db_user_id[10] | ||
3856 : | read_argv( 1, db_user_id, 9 ) | ||
3857 : | |||
3858 : | new query[250], data[1] | ||
3859 : | data[0]=id | ||
3860 : | |||
3861 : | formatex( query, 249,\ | ||
3862 : | "select map_name, score_id, fin_time, cps, gcs, boosts, wpns from %sscores where user_id=%d;",\ | ||
3863 : | DB_PREFIX, str_to_num( db_user_id ) ) | ||
3864 : | SQL_ThreadQuery( DB_TUPLE, "climb_dbuser_handler", query, data, 1 ) | ||
3865 : | } | ||
3866 : | return PLUGIN_HANDLED | ||
3867 : | } | ||
3868 : | |||
3869 : | public climb_dbuser_handler( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3870 : | { | ||
3871 : | if( !query_failed( failstate, error, errnum ) ) | ||
3872 : | { | ||
3873 : | new id=data[0] | ||
3874 : | new count=SQL_NumResults( query ) | ||
3875 : | if( count ) | ||
3876 : | { | ||
3877 : | new name[21] | ||
3878 : | console_print(id,"^n# Map, Score ID, Time, cps/gcs/boosts, Scout") | ||
3879 : | for( new i=0; i<count; i++ ) | ||
3880 : | { | ||
3881 : | SQL_ReadResult( query, 0, name, 20 ) | ||
3882 : | console_print( id, "# %s, %d, %d, %d/%d/%d, %s",\ | ||
3883 : | name,\ | ||
3884 : | SQL_ReadResult(query,1),\ | ||
3885 : | SQL_ReadResult(query,2),\ | ||
3886 : | SQL_ReadResult(query,3),\ | ||
3887 : | SQL_ReadResult(query,4),\ | ||
3888 : | SQL_ReadResult(query,5),\ | ||
3889 : | SQL_ReadResult(query,6) ? "y" : "n" ) | ||
3890 : | SQL_NextRow( query ) | ||
3891 : | } | ||
3892 : | console_print( id, "%d Result(s)", count ) | ||
3893 : | } | ||
3894 : | else console_print( id, "Query returned no results.") | ||
3895 : | } | ||
3896 : | return PLUGIN_HANDLED | ||
3897 : | } | ||
3898 : | |||
3899 : | public climb_dbdelete( id, level, cid ) | ||
3900 : | { | ||
3901 : | if(cmd_access(id,level,cid,1)) | ||
3902 : | { | ||
3903 : | new db_user_id[10] | ||
3904 : | read_argv( 1, db_user_id, 9 ) | ||
3905 : | |||
3906 : | new query[250], data[2], del_id | ||
3907 : | data[1]=del_id=str_to_num( db_user_id ) | ||
3908 : | data[0]=id | ||
3909 : | |||
3910 : | if(db_last_del_id!=del_id) | ||
3911 : | {//First time show data to be deleted and ask if they're sure. | ||
3912 : | formatex( query, 249,\ | ||
3913 : | "select p.alias, s.map_name, s.fin_time, s.cps, s.gcs, s.boosts, s.wpns from %sscores s, %splayers p where p.user_id=s.user_id and s.score_id=%d;",\ | ||
3914 : | DB_PREFIX, DB_PREFIX, del_id ) | ||
3915 : | SQL_ThreadQuery( DB_TUPLE, "climb_dbdelete_verify", query, data, 2 ) | ||
3916 : | } | ||
3917 : | else | ||
3918 : | {//Second time execute the delete | ||
3919 : | formatex( query, 249,\ | ||
3920 : | "delete from %sscores where score_id=%d;",\ | ||
3921 : | DB_PREFIX, del_id ) | ||
3922 : | SQL_ThreadQuery( DB_TUPLE, "climb_dbdelete_handler", query, data, 2 ) | ||
3923 : | db_last_del_id=0 | ||
3924 : | } | ||
3925 : | } | ||
3926 : | return PLUGIN_HANDLED | ||
3927 : | } | ||
3928 : | |||
3929 : | //For nightly builds | ||
3930 : | public climb_dbrecalc( id, level, cid ) | ||
3931 : | { | ||
3932 : | if( cmd_access( id, level, cid, 0 ) ) | ||
3933 : | SQL_ThreadQuery( DB_TUPLE, "db_generic_handler", | ||
3934 : | "update %sscores set score = ( ( (boosts>0) * 1000000 ) + ( (cps>0) * 100000 ) + ( wpns * 10000 ) + fin_time )", | ||
3935 : | DB_PREFIX ) | ||
3936 : | return PLUGIN_HANDLED | ||
3937 : | } | ||
3938 : | |||
3939 : | public climb_dbdelete_verify( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3940 : | { | ||
3941 : | if( !query_failed( failstate, error, errnum ) ) | ||
3942 : | { | ||
3943 : | new id=data[0] | ||
3944 : | new del_id=data[1] | ||
3945 : | new count=SQL_NumResults( query ) | ||
3946 : | if( count ) | ||
3947 : | { | ||
3948 : | new name[21],map[33] | ||
3949 : | console_print( id, "^n# Name, Map, Time, cps/gcs/boosts, Scout" ) | ||
3950 : | |||
3951 : | SQL_ReadResult( query, 0, name, 20 ) | ||
3952 : | SQL_ReadResult( query, 1, map, 32 ) | ||
3953 : | console_print( id, "# %s, %s, %d, %d/%d/%d, %s",\ | ||
3954 : | name,\ | ||
3955 : | map,\ | ||
3956 : | SQL_ReadResult(query,2),\ | ||
3957 : | SQL_ReadResult(query,3),\ | ||
3958 : | SQL_ReadResult(query,4),\ | ||
3959 : | SQL_ReadResult(query,5),\ | ||
3960 : | SQL_ReadResult(query,6) ? "y" : "n" ) | ||
3961 : | |||
3962 : | console_print( id, "%d Result(s)", count )//debug | ||
3963 : | console_print( id, "If you're sure you want to delete this record, execute the command again." ) | ||
3964 : | db_last_del_id=del_id | ||
3965 : | } | ||
3966 : | else console_print( id, "No record exists with given DB Score ID." ) | ||
3967 : | } | ||
3968 : | return PLUGIN_HANDLED | ||
3969 : | } | ||
3970 : | |||
3971 : | public climb_dbdelete_handler( failstate, Handle:query, error[], errnum, data[], size, Float:queuetime ) | ||
3972 : | { | ||
3973 : | new id=data[0] | ||
3974 : | if( !query_failed( failstate, error, errnum ) ) | ||
3975 : | console_print( id, "Record has been deleted." ) | ||
3976 : | else console_print( id, "Record could not be deleted." ) | ||
3977 : | return PLUGIN_HANDLED | ||
3978 : | } | ||
3979 : | |||
3980 : | public query_failed( failstate, error[], errnum ) | ||
3981 : | { | ||
3982 : | if( failstate == TQUERY_CONNECT_FAILED ) | ||
3983 : | { | ||
3984 : | log_amx( "Climb: Couldn't connect to database: %s", error ) | ||
3985 : | return 1 | ||
3986 : | } | ||
3987 : | else if( failstate == TQUERY_QUERY_FAILED ) | ||
3988 : | { | ||
3989 : | log_amx( "Climb: Query failed: %s", error ) | ||
3990 : | return 1 | ||
3991 : | } | ||
3992 : | |||
3993 : | if( errnum ) | ||
3994 : | { | ||
3995 : | log_amx( "Climb: Query Error: %s", error ) | ||
3996 : | return 1 | ||
3997 : | } | ||
3998 : | |||
3999 : | return 0 | ||
4000 : | } | ||
4001 : | //////////////////////////////////////////////////////////////////////////////// | ||
4002 : | // End: Database functions | ||
4003 : | //////////////////////////////////////////////////////////////////////////////// | ||
4004 : | public rotwtf( string[], out_len ) | ||
4005 : | {//Simple Password Encryption | ||
4006 : | new len=strlen( string ),str[99],cnt=0,tok=len-1 | ||
4007 : | copy( str, out_len, string ) | ||
4008 : | for( new index=0; index<11; index++ ) | ||
4009 : | { | ||
4010 : | if('a' <= string[index] <= 'z') | ||
4011 : | str[index]=( str[index]-'a'+string[tok]+index ) | ||
4012 : | else if('A' <= str[index] <= 'Z') | ||
4013 : | str[index]=( str[index]-'A'+string[tok]+index ) | ||
4014 : | else if( '0' <= str[index] <= '9' ) | ||
4015 : | str[index]=( str[index]-'0'+string[tok]+index ) | ||
4016 : | switch( cnt ){ | ||
4017 : | case 0:str[index]=str[index]%26+'a' | ||
4018 : | case 1:str[index]=str[index]%26+'A' | ||
4019 : | case 2:str[index]=str[index]%10+'0' | ||
4020 : | } | ||
4021 : | tok-- | ||
4022 : | if( tok<0 )tok=len-1 | ||
4023 : | cnt++ | ||
4024 : | if( cnt==3 )cnt=0 | ||
4025 : | } | ||
4026 : | copy( string, out_len, str ) | ||
4027 : | return PLUGIN_HANDLED | ||
4028 : | } | ||
4029 : | |||
4030 : | public plugin_end() | ||
4031 : | { | ||
4032 : | if( CLIMB_SAVE )SQL_FreeHandle( DB_TUPLE ) | ||
4033 : | if( get_pcvar_num( p_auto ) ) | ||
4034 : | { | ||
4035 : | set_pcvar_num( p_climb, 0 ) | ||
4036 : | set_pcvar_num( p_teambalance, TEAM_BALANCE_OLD ) | ||
4037 : | set_pcvar_num( p_limitteams, LIMIT_TEAMS_OLD ) | ||
4038 : | } | ||
4039 : | return PLUGIN_CONTINUE | ||
4040 : | } |
Contact | ViewVC Help |
Powered by ViewVC 1.0.4 |