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