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