Parent Directory | Revision Log
Revision 46 - (view) (download)
1 : | ian | 1 | /* |
2 : | ian | 46 | Grab+ v1.2.5 |
3 : | Copyright (C) 2011 Ian (Juan) Cammarata | ||
4 : | ian | 1 | |
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/projects/grab_plus | ||
20 : | ian | 46 | ?19 ?February, ?2011 |
21 : | ian | 1 | |
22 : | |||
23 : | Description: | ||
24 : | This is a remake from scratch of SpaceDude's Jedi Force Grab plugin. It has many additional features and optimizations, is less spammy, multilingual and requires fewer binds. | ||
25 : | |||
26 : | |||
27 : | Features: | ||
28 : | Multilingual | ||
29 : | Screenfade to indicate grab activity instead of chat spam. | ||
30 : | Can grab players off a ladder. | ||
31 : | Automatically choke by holding down +pull while at min distance. | ||
32 : | Choke with use key. | ||
33 : | Throw with drop. | ||
34 : | Can't have mutliple admins grabbing the same player. | ||
35 : | Auto drop on death. | ||
36 : | Grab entities other than players, such as bombs, weapons, and hostages. | ||
37 : | |||
38 : | |||
39 : | Commands: | ||
40 : | |||
41 : | +grab : Grab something for as long as you hold down the key. | ||
42 : | grab_toggle : Same as +grab but toggles. | ||
43 : | amx_grab <name> : Grab client by name or id and teleport them to you. Use +grab or grab_toggle key to release. | ||
44 : | |||
45 : | +pull/+push (or invnext/invprev): Pulls/pushes the grabbed towards/away from you as you hold the button. | ||
46 : | |||
47 : | ian | 10 | +use : Chokes the grabbed (it damages the grabbed with 5 (cvar: gp_choke_dmg) hp per 1.5 (cvar: gp_choke_time) seconds) |
48 : | drop - Throws the grabbed with 1500 velocity. (cvar: gp_throw_force) | ||
49 : | ian | 1 | |
50 : | |||
51 : | Cvars (First value is default): | ||
52 : | gp_enabled <1|0> Enables all plugin functionality. | ||
53 : | ian | 10 | gp_players_only <0|1> Disables admins grabbing entities other than players. |
54 : | ian | 1 | |
55 : | gp_min_dist <90|...> Min distance between the grabber and grabbed. | ||
56 : | ian | 10 | gp_grab_force <8|...> Sets the amount of force used when grabbing players. |
57 : | gp_throw_force <1500|...> Sets the power used when throwing players. | ||
58 : | ian | 1 | gp_speed <5|...> How fast the grabbed moves when using push and pull. |
59 : | |||
60 : | ian | 10 | gp_choke_time <1.5|...> Time frequency for choking. |
61 : | gp_choke_dmg <5|...> Amount of damage done with each choke. | ||
62 : | gp_auto_choke <1|0> Enable/disable choking automatically with +pull command. | ||
63 : | ian | 1 | |
64 : | ian | 10 | gp_screen_fade <1|0> Enables/disables screenfade when grabbing. |
65 : | ian | 9 | gp_glow <1|0> Enables/disables glowing for grabbed objects. |
66 : | ian | 1 | |
67 : | ian | 9 | gp_glow_r <50|0-255> Sets red amount for glow and screenfade. |
68 : | gp_glow_g <0|0-255> Sets green amount for glow and screenfade. | ||
69 : | gp_glow_b <0|0-255> Sets blue amount for glow and screenfade. | ||
70 : | gp_glow_a <0|0-255> Sets alpha for glow and screenfade. | ||
71 : | ian | 1 | |
72 : | ian | 9 | |
73 : | ian | 1 | Notes: |
74 : | Make sure you place the grab_plus.txt file in addons\amxmodx\data\lang | ||
75 : | |||
76 : | |||
77 : | Credits: | ||
78 : | ian | 5 | Thanks to vittu for contributing code (changed all engine/fun module stuff to fakemeta). |
79 : | |||
80 : | ian | 1 | Thanks to all the coders who worked on the original Jedi Force Grab plugin for all their ideas: |
81 : | SpaceDude | ||
82 : | KCE | ||
83 : | KRoTaL | ||
84 : | BOB_SLAYER | ||
85 : | kosmo111 | ||
86 : | |||
87 : | |||
88 : | Supported Languages: | ||
89 : | 1337 (100%) - Thanks to l337newb | ||
90 : | Brazilian Portuguese (100%) - Thanks to Arion | ||
91 : | Danish (100%) - Thanks to nellerbabz | ||
92 : | Dutch (100%) - Thanks to BlackMilk | ||
93 : | English (100%) | ||
94 : | Finnish (100%) - Thanks to Pro Patria Finland | ||
95 : | French (100%) - Thanks to connorr | ||
96 : | German (100%) - Thanks to SchlumPF* | ||
97 : | Russian (100%) - Thanks to `666 | ||
98 : | ian | 31 | Spanish (100%) - Thanks to RenXO |
99 : | ian | 1 | Swedish (100%) - Thanks to Bend3r |
100 : | |||
101 : | |||
102 : | Change Log: | ||
103 : | Key (+ added | - removed | c changed | f fixed) | ||
104 : | |||
105 : | ian | 46 | v1.2.5 (Feb 19, 2011) |
106 : | f: Applied fix mailed to me on Allied Modders site several years ago. (Maybe I should sign up for new mail notifications.) | ||
107 : | Thanks to ConnorMcLeod | ||
108 : | |||
109 : | ian | 39 | v1.2.4 (Feb 18, 2007) |
110 : | f: Killing player with choke in some mods bugged out really bad. | ||
111 : | |||
112 : | ian | 28 | v1.2.3 (Nov 21, 2007) |
113 : | ian | 27 | c: A few more small optimizations. |
114 : | ian | 28 | f: Bloodstream for choke wasn't aligned with player. |
115 : | f: Bad message disconnect error when players were choked. ( stupid SVC_DAMAGE define ) | ||
116 : | ian | 27 | |
117 : | ian | 20 | v1.2.2 (Nov 16, 2007) |
118 : | ian | 16 | c: A few small code optimizations. |
119 : | |||
120 : | ian | 15 | v1.2.1 (Nov 12, 2007) |
121 : | ian | 16 | f: Eliminated two run time warnings in the player prethink function. |
122 : | ian | 15 | |
123 : | ian | 11 | v1.2 (Nov 06, 2007) |
124 : | ian | 10 | +: Cvars gp_screen_fade and gp_glow to enable/disable these features. |
125 : | ian | 5 | +: Cvar gp_glow_a controls to control alpha of screenfade and glow. |
126 : | ian | 10 | +: Cvar gp_auto_choke to enable/disable choking automatically with +pull command. |
127 : | ian | 11 | c: Removed dependency of engine and fun modules. Thanks to vittu for doing most of the work. |
128 : | ian | 10 | c: Made cvar names more consistent by adding more underscores. |
129 : | ian | 11 | f: Fixed compile bug with amxx 1.8.0 (Compiles with 1.7.x as well). |
130 : | ian | 5 | |
131 : | ian | 1 | v1.1 (Oct 16, 2007) |
132 : | +: Grab a few types of entities other than players. | ||
133 : | ian | 10 | +: Cvar gp_players_only. |
134 : | ian | 1 | |
135 : | v1.0 (Oct 13, 2007) | ||
136 : | !: Initial release | ||
137 : | |||
138 : | */ | ||
139 : | |||
140 : | #include <amxmodx> | ||
141 : | #include <amxmisc> | ||
142 : | #include <fakemeta> | ||
143 : | |||
144 : | ian | 39 | new const VERSION[ ] = "1.2.4b1" |
145 : | ian | 27 | new const TRKCVAR[ ] = "grab_plus_version" |
146 : | ian | 1 | #define ADMIN ADMIN_LEVEL_A |
147 : | |||
148 : | #define TSK_CHKE 50 | ||
149 : | |||
150 : | #define SF_FADEOUT 0 | ||
151 : | |||
152 : | new client_data[33][4] | ||
153 : | #define GRABBED 0 | ||
154 : | #define GRABBER 1 | ||
155 : | #define GRAB_LEN 2 | ||
156 : | #define FLAGS 3 | ||
157 : | |||
158 : | ian | 46 | #define m_bitsDamageType 76 |
159 : | |||
160 : | ian | 1 | #define CDF_IN_PUSH (1<<0) |
161 : | #define CDF_IN_PULL (1<<1) | ||
162 : | #define CDF_NO_CHOKE (1<<2) | ||
163 : | |||
164 : | //Cvar Pointers | ||
165 : | ian | 10 | new p_enabled, p_players_only |
166 : | new p_throw_force, p_min_dist, p_speed, p_grab_force | ||
167 : | new p_choke_time, p_choke_dmg, p_auto_choke | ||
168 : | ian | 5 | new p_glow_r, p_glow_b, p_glow_g, p_glow_a |
169 : | new p_fade, p_glow | ||
170 : | ian | 1 | |
171 : | //Pseudo Constants | ||
172 : | new MAXPLAYERS | ||
173 : | ian | 27 | new SVC_SCREENFADE, SVC_SCREENSHAKE, WTF_DAMAGE |
174 : | ian | 1 | |
175 : | public plugin_init( ) | ||
176 : | { | ||
177 : | register_plugin( "Grab+", VERSION, "Ian Cammarata" ) | ||
178 : | ian | 27 | register_cvar( TRKCVAR, VERSION, FCVAR_SERVER ) |
179 : | set_cvar_string( TRKCVAR, VERSION ) | ||
180 : | ian | 1 | |
181 : | p_enabled = register_cvar( "gp_enabled", "1" ) | ||
182 : | ian | 10 | p_players_only = register_cvar( "gp_players_only", "0" ) |
183 : | ian | 1 | |
184 : | ian | 10 | p_min_dist = register_cvar ( "gp_min_dist", "90" ) |
185 : | p_throw_force = register_cvar( "gp_throw_force", "1500" ) | ||
186 : | p_grab_force = register_cvar( "gp_grab_force", "8" ) | ||
187 : | ian | 1 | p_speed = register_cvar( "gp_speed", "5" ) |
188 : | |||
189 : | ian | 10 | p_choke_time = register_cvar( "gp_choke_time", "1.5" ) |
190 : | p_choke_dmg = register_cvar( "gp_choke_dmg", "5" ) | ||
191 : | p_auto_choke = register_cvar( "gp_auto_choke", "1" ) | ||
192 : | ian | 1 | |
193 : | p_glow_r = register_cvar( "gp_glow_r", "50" ) | ||
194 : | p_glow_g = register_cvar( "gp_glow_g", "0" ) | ||
195 : | p_glow_b = register_cvar( "gp_glow_b", "0" ) | ||
196 : | ian | 5 | p_glow_a = register_cvar( "gp_glow_a", "200" ) |
197 : | ian | 1 | |
198 : | ian | 10 | p_fade = register_cvar( "gp_screen_fade", "1" ) |
199 : | ian | 5 | p_glow = register_cvar( "gp_glow", "1" ) |
200 : | |||
201 : | ian | 1 | register_clcmd( "amx_grab", "force_grab", ADMIN, "Grab client & teleport to you." ) |
202 : | register_clcmd( "grab_toggle", "grab_toggle", ADMIN, "press once to grab and again to release" ) | ||
203 : | register_clcmd( "+grab", "grab", ADMIN, "bind a key to +grab" ) | ||
204 : | register_clcmd( "-grab", "unset_grabbed" ) | ||
205 : | |||
206 : | register_clcmd( "+push", "push", ADMIN, "bind a key to +push" ) | ||
207 : | register_clcmd( "-push", "push" ) | ||
208 : | register_clcmd( "+pull", "pull", ADMIN, "bind a key to +pull" ) | ||
209 : | register_clcmd( "-pull", "pull" ) | ||
210 : | register_clcmd( "push", "push2" ) | ||
211 : | register_clcmd( "pull", "pull2" ) | ||
212 : | |||
213 : | register_clcmd( "drop" ,"throw" ) | ||
214 : | |||
215 : | register_event( "DeathMsg", "DeathMsg", "a" ) | ||
216 : | |||
217 : | ian | 8 | register_forward( FM_PlayerPreThink, "fm_player_prethink" ) |
218 : | |||
219 : | ian | 1 | register_dictionary( "grab_plus.txt" ) |
220 : | |||
221 : | MAXPLAYERS = get_maxplayers() | ||
222 : | |||
223 : | SVC_SCREENFADE = get_user_msgid( "ScreenFade" ) | ||
224 : | SVC_SCREENSHAKE = get_user_msgid( "ScreenShake" ) | ||
225 : | ian | 27 | WTF_DAMAGE = get_user_msgid( "Damage" ) |
226 : | ian | 1 | } |
227 : | |||
228 : | public plugin_precache( ) | ||
229 : | { | ||
230 : | precache_sound( "player/PL_PAIN2.WAV" ) | ||
231 : | } | ||
232 : | |||
233 : | ian | 8 | public fm_player_prethink( id ) |
234 : | ian | 1 | { |
235 : | ian | 27 | new target |
236 : | ian | 1 | //Search for a target |
237 : | if ( client_data[id][GRABBED] == -1 ) | ||
238 : | { | ||
239 : | new Float:orig[3], Float:ret[3] | ||
240 : | ian | 11 | get_view_pos( id, orig ) |
241 : | ret = vel_by_aim( id, 9999 ) | ||
242 : | ian | 1 | |
243 : | ian | 16 | ret[0] += orig[0] |
244 : | ret[1] += orig[1] | ||
245 : | ret[2] += orig[2] | ||
246 : | |||
247 : | ian | 27 | target = traceline( orig, ret, id, ret ) |
248 : | ian | 1 | |
249 : | if( 0 < target <= MAXPLAYERS ) | ||
250 : | { | ||
251 : | ian | 15 | if( is_grabbed( target, id ) ) return FMRES_IGNORED |
252 : | ian | 1 | set_grabbed( id, target ) |
253 : | } | ||
254 : | ian | 10 | else if( !get_pcvar_num( p_players_only ) ) |
255 : | ian | 1 | { |
256 : | new movetype | ||
257 : | ian | 15 | if( target && pev_valid( target ) ) |
258 : | ian | 1 | { |
259 : | movetype = pev( target, pev_movetype ) | ||
260 : | if( !( movetype == MOVETYPE_WALK || movetype == MOVETYPE_STEP || movetype == MOVETYPE_TOSS ) ) | ||
261 : | ian | 15 | return FMRES_IGNORED |
262 : | ian | 1 | } |
263 : | else | ||
264 : | { | ||
265 : | ian | 15 | target = 0 |
266 : | ian | 5 | new ent = engfunc( EngFunc_FindEntityInSphere, -1, ret, 12.0 ) |
267 : | ian | 1 | while( !target && ent > 0 ) |
268 : | { | ||
269 : | movetype = pev( ent, pev_movetype ) | ||
270 : | if( ( movetype == MOVETYPE_WALK || movetype == MOVETYPE_STEP || movetype == MOVETYPE_TOSS ) | ||
271 : | && ent != id ) | ||
272 : | target = ent | ||
273 : | ian | 5 | ent = engfunc( EngFunc_FindEntityInSphere, ent, ret, 12.0 ) |
274 : | ian | 1 | } |
275 : | } | ||
276 : | if( target ) | ||
277 : | { | ||
278 : | ian | 15 | if( is_grabbed( target, id ) ) return FMRES_IGNORED |
279 : | ian | 1 | set_grabbed( id, target ) |
280 : | } | ||
281 : | } | ||
282 : | } | ||
283 : | ian | 27 | |
284 : | target = client_data[id][GRABBED] | ||
285 : | ian | 1 | //If they've grabbed something |
286 : | ian | 27 | if( target > 0 ) |
287 : | ian | 1 | { |
288 : | if( !pev_valid( target ) || ( pev( target, pev_health ) < 1 && pev( target, pev_max_health ) ) ) | ||
289 : | { | ||
290 : | unset_grabbed( id ) | ||
291 : | ian | 15 | return FMRES_IGNORED |
292 : | ian | 1 | } |
293 : | |||
294 : | //Use key choke | ||
295 : | if( pev( id, pev_button ) & IN_USE ) | ||
296 : | do_choke( id ) | ||
297 : | |||
298 : | //Push and pull | ||
299 : | ian | 27 | new cdf = client_data[id][FLAGS] |
300 : | if ( cdf & CDF_IN_PULL ) | ||
301 : | ian | 1 | do_pull( id ) |
302 : | ian | 27 | else if ( cdf & CDF_IN_PUSH ) |
303 : | ian | 1 | do_push( id ) |
304 : | |||
305 : | ian | 27 | if( target > MAXPLAYERS ) grab_think( id ) |
306 : | ian | 1 | } |
307 : | |||
308 : | ian | 27 | //If they're grabbed |
309 : | target = client_data[id][GRABBER] | ||
310 : | if( target > 0 ) grab_think( target ) | ||
311 : | |||
312 : | ian | 15 | return FMRES_IGNORED |
313 : | ian | 1 | } |
314 : | |||
315 : | ian | 27 | public grab_think( id ) //id of the grabber |
316 : | ian | 1 | { |
317 : | new target = client_data[id][GRABBED] | ||
318 : | |||
319 : | //Keep grabbed clients from sticking to ladders | ||
320 : | if( pev( target, pev_movetype ) == MOVETYPE_FLY && !(pev( target, pev_button ) & IN_JUMP ) ) client_cmd( target, "+jump;wait;-jump" ) | ||
321 : | |||
322 : | //Move targeted client | ||
323 : | ian | 12 | new Float:tmpvec[3], Float:tmpvec2[3], Float:torig[3], Float:tvel[3] |
324 : | ian | 1 | |
325 : | ian | 11 | get_view_pos( id, tmpvec ) |
326 : | ian | 10 | |
327 : | ian | 11 | tmpvec2 = vel_by_aim( id, client_data[id][GRAB_LEN] ) |
328 : | ian | 10 | |
329 : | ian | 1 | torig = get_target_origin_f( target ) |
330 : | |||
331 : | ian | 10 | new force = get_pcvar_num( p_grab_force ) |
332 : | ian | 1 | |
333 : | ian | 16 | tvel[0] = ( ( tmpvec[0] + tmpvec2[0] ) - torig[0] ) * force |
334 : | tvel[1] = ( ( tmpvec[1] + tmpvec2[1] ) - torig[1] ) * force | ||
335 : | tvel[2] = ( ( tmpvec[2] + tmpvec2[2] ) - torig[2] ) * force | ||
336 : | ian | 1 | |
337 : | ian | 5 | set_pev( target, pev_velocity, tvel ) |
338 : | ian | 1 | } |
339 : | |||
340 : | stock Float:get_target_origin_f( id ) | ||
341 : | { | ||
342 : | new Float:orig[3] | ||
343 : | ian | 5 | pev( id, pev_origin, orig ) |
344 : | ian | 1 | |
345 : | //If grabbed is not a player, move origin to center | ||
346 : | if( id > MAXPLAYERS ) | ||
347 : | { | ||
348 : | new Float:mins[3], Float:maxs[3] | ||
349 : | ian | 5 | pev( id, pev_mins, mins ) |
350 : | pev( id, pev_maxs, maxs ) | ||
351 : | ian | 1 | |
352 : | if( !mins[2] ) orig[2] += maxs[2] / 2 | ||
353 : | } | ||
354 : | |||
355 : | return orig | ||
356 : | } | ||
357 : | |||
358 : | public grab_toggle( id, level, cid ) | ||
359 : | { | ||
360 : | if( !client_data[id][GRABBED] ) grab( id, level, cid ) | ||
361 : | else unset_grabbed( id ) | ||
362 : | |||
363 : | return PLUGIN_HANDLED | ||
364 : | } | ||
365 : | |||
366 : | public grab( id, level, cid ) | ||
367 : | { | ||
368 : | if( !cmd_access( id, level, cid, 1 ) || !get_pcvar_num( p_enabled ) ) return PLUGIN_HANDLED | ||
369 : | |||
370 : | if ( !client_data[id][GRABBED] ) client_data[id][GRABBED] = -1 | ||
371 : | screenfade_in( id ) | ||
372 : | |||
373 : | return PLUGIN_HANDLED | ||
374 : | } | ||
375 : | |||
376 : | public screenfade_in( id ) | ||
377 : | { | ||
378 : | ian | 5 | if( get_pcvar_num( p_fade ) ) |
379 : | { | ||
380 : | message_begin( MSG_ONE, SVC_SCREENFADE, _, id ) | ||
381 : | write_short( 10000 ) //duration | ||
382 : | write_short( 0 ) //hold | ||
383 : | write_short( SF_FADE_IN + SF_FADE_ONLYONE ) //flags | ||
384 : | write_byte( get_pcvar_num( p_glow_r ) ) //r | ||
385 : | write_byte( get_pcvar_num( p_glow_g ) ) //g | ||
386 : | write_byte( get_pcvar_num( p_glow_b ) ) //b | ||
387 : | write_byte( get_pcvar_num( p_glow_a ) / 2 ) //a | ||
388 : | message_end( ) | ||
389 : | } | ||
390 : | ian | 1 | } |
391 : | |||
392 : | public throw( id ) | ||
393 : | { | ||
394 : | new target = client_data[id][GRABBED] | ||
395 : | if( target > 0 ) | ||
396 : | { | ||
397 : | ian | 11 | set_pev( target, pev_velocity, vel_by_aim( id, get_pcvar_num(p_throw_force) ) ) |
398 : | ian | 1 | unset_grabbed( id ) |
399 : | return PLUGIN_HANDLED | ||
400 : | } | ||
401 : | ian | 11 | |
402 : | ian | 1 | return PLUGIN_CONTINUE |
403 : | } | ||
404 : | |||
405 : | public unset_grabbed( id ) | ||
406 : | { | ||
407 : | new target = client_data[id][GRABBED] | ||
408 : | if( target > 0 && pev_valid( target ) ) | ||
409 : | { | ||
410 : | ian | 5 | set_pev( target, pev_renderfx, kRenderFxNone ) |
411 : | set_pev( target, pev_rendercolor, {255.0, 255.0, 255.0} ) | ||
412 : | set_pev( target, pev_rendermode, kRenderNormal ) | ||
413 : | set_pev( target, pev_renderamt, 16.0 ) | ||
414 : | |||
415 : | ian | 1 | if( 0 < target <= MAXPLAYERS ) |
416 : | client_data[target][GRABBER] = 0 | ||
417 : | } | ||
418 : | client_data[id][GRABBED] = 0 | ||
419 : | |||
420 : | ian | 5 | if( get_pcvar_num( p_fade ) ) |
421 : | { | ||
422 : | message_begin( MSG_ONE, SVC_SCREENFADE, _, id ) | ||
423 : | write_short( 10000 ) //duration | ||
424 : | write_short( 0 ) //hold | ||
425 : | write_short( SF_FADEOUT ) //flags | ||
426 : | write_byte( get_pcvar_num( p_glow_r ) ) //r | ||
427 : | write_byte( get_pcvar_num( p_glow_g ) ) //g | ||
428 : | write_byte( get_pcvar_num( p_glow_b ) ) //b | ||
429 : | write_byte( get_pcvar_num( p_glow_a ) / 2 ) //a | ||
430 : | message_end( ) | ||
431 : | } | ||
432 : | ian | 1 | } |
433 : | |||
434 : | //Grabs onto someone | ||
435 : | public set_grabbed( id, target ) | ||
436 : | { | ||
437 : | ian | 5 | if( get_pcvar_num( p_glow ) ) |
438 : | { | ||
439 : | new Float:color[3] | ||
440 : | color[0] = get_pcvar_float( p_glow_r ) | ||
441 : | color[1] = get_pcvar_float( p_glow_g ) | ||
442 : | color[2] = get_pcvar_float( p_glow_b ) | ||
443 : | ian | 6 | set_pev( target, pev_renderfx, kRenderFxGlowShell ) |
444 : | set_pev( target, pev_rendercolor, color ) | ||
445 : | set_pev( target, pev_rendermode, kRenderTransColor ) | ||
446 : | set_pev( target, pev_renderamt, get_pcvar_float( p_glow_a ) ) | ||
447 : | ian | 5 | } |
448 : | ian | 1 | |
449 : | if( 0 < target <= MAXPLAYERS ) | ||
450 : | client_data[target][GRABBER] = id | ||
451 : | client_data[id][FLAGS] = 0 | ||
452 : | client_data[id][GRABBED] = target | ||
453 : | ian | 5 | new Float:torig[3], Float:orig[3] |
454 : | pev( target, pev_origin, torig ) | ||
455 : | pev( id, pev_origin, orig ) | ||
456 : | client_data[id][GRAB_LEN] = floatround( get_distance_f( torig, orig ) ) | ||
457 : | ian | 10 | if( client_data[id][GRAB_LEN] < get_pcvar_num( p_min_dist ) ) client_data[id][GRAB_LEN] = get_pcvar_num( p_min_dist ) |
458 : | ian | 1 | } |
459 : | |||
460 : | public push( id ) | ||
461 : | { | ||
462 : | client_data[id][FLAGS] ^= CDF_IN_PUSH | ||
463 : | return PLUGIN_HANDLED | ||
464 : | } | ||
465 : | |||
466 : | public pull( id ) | ||
467 : | { | ||
468 : | client_data[id][FLAGS] ^= CDF_IN_PULL | ||
469 : | return PLUGIN_HANDLED | ||
470 : | } | ||
471 : | |||
472 : | public push2( id ) | ||
473 : | { | ||
474 : | if( client_data[id][GRABBED] > 0 ) | ||
475 : | { | ||
476 : | do_push( id ) | ||
477 : | return PLUGIN_HANDLED | ||
478 : | } | ||
479 : | return PLUGIN_CONTINUE | ||
480 : | } | ||
481 : | |||
482 : | public pull2( id ) | ||
483 : | { | ||
484 : | if( client_data[id][GRABBED] > 0 ) | ||
485 : | { | ||
486 : | do_pull( id ) | ||
487 : | return PLUGIN_HANDLED | ||
488 : | } | ||
489 : | return PLUGIN_CONTINUE | ||
490 : | } | ||
491 : | |||
492 : | public do_push( id ) | ||
493 : | if( client_data[id][GRAB_LEN] < 9999 ) | ||
494 : | client_data[id][GRAB_LEN] += get_pcvar_num( p_speed ) | ||
495 : | |||
496 : | public do_pull( id ) | ||
497 : | { | ||
498 : | ian | 10 | new mindist = get_pcvar_num( p_min_dist ) |
499 : | ian | 1 | new len = client_data[id][GRAB_LEN] |
500 : | |||
501 : | if( len > mindist ) | ||
502 : | { | ||
503 : | len -= get_pcvar_num( p_speed ) | ||
504 : | if( len < mindist ) len = mindist | ||
505 : | client_data[id][GRAB_LEN] = len | ||
506 : | } | ||
507 : | ian | 10 | else if( get_pcvar_num( p_auto_choke ) ) |
508 : | do_choke( id ) | ||
509 : | ian | 1 | } |
510 : | |||
511 : | public do_choke( id ) | ||
512 : | { | ||
513 : | new target = client_data[id][GRABBED] | ||
514 : | ian | 28 | if( client_data[id][FLAGS] & CDF_NO_CHOKE || id == target || target > MAXPLAYERS) return |
515 : | ian | 1 | |
516 : | ian | 10 | new dmg = get_pcvar_num( p_choke_dmg ) |
517 : | ian | 28 | new vec[3] |
518 : | FVecIVec( get_target_origin_f( target ), vec ) | ||
519 : | ian | 1 | |
520 : | message_begin( MSG_ONE, SVC_SCREENSHAKE, _, target ) | ||
521 : | write_short( 999999 ) //amount | ||
522 : | write_short( 9999 ) //duration | ||
523 : | write_short( 999 ) //frequency | ||
524 : | message_end( ) | ||
525 : | |||
526 : | message_begin( MSG_ONE, SVC_SCREENFADE, _, target ) | ||
527 : | write_short( 9999 ) //duration | ||
528 : | write_short( 100 ) //hold | ||
529 : | write_short( SF_FADE_MODULATE ) //flags | ||
530 : | write_byte( get_pcvar_num( p_glow_r ) ) //r | ||
531 : | write_byte( get_pcvar_num( p_glow_g ) ) //g | ||
532 : | write_byte( get_pcvar_num( p_glow_b ) ) //b | ||
533 : | write_byte( 200 ) //a | ||
534 : | message_end( ) | ||
535 : | |||
536 : | ian | 27 | message_begin( MSG_ONE, WTF_DAMAGE, _, target ) |
537 : | ian | 1 | write_byte( 0 ) //damage armor |
538 : | write_byte( dmg ) //damage health | ||
539 : | write_long( DMG_CRUSH ) //damage type | ||
540 : | ian | 28 | write_coord( vec[0] ) //origin[x] |
541 : | write_coord( vec[1] ) //origin[y] | ||
542 : | write_coord( vec[2] ) //origin[z] | ||
543 : | ian | 1 | message_end( ) |
544 : | |||
545 : | message_begin( MSG_BROADCAST, SVC_TEMPENTITY ) | ||
546 : | write_byte( TE_BLOODSTREAM ) | ||
547 : | ian | 28 | write_coord( vec[0] ) //pos.x |
548 : | write_coord( vec[1] ) //pos.y | ||
549 : | write_coord( vec[2] + 15 ) //pos.z | ||
550 : | ian | 1 | write_coord( random_num( 0, 255 ) ) //vec.x |
551 : | write_coord( random_num( 0, 255 ) ) //vec.y | ||
552 : | write_coord( random_num( 0, 255 ) ) //vec.z | ||
553 : | write_byte( 70 ) //col index | ||
554 : | write_byte( random_num( 50, 250 ) ) //speed | ||
555 : | message_end( ) | ||
556 : | |||
557 : | ian | 46 | //Thanks to ConnorMcLeod for making this block of code more proper |
558 : | new Float:health | ||
559 : | pev( target, pev_health , health) | ||
560 : | health -= dmg | ||
561 : | ian | 1 | if( health < 1 ) dllfunc( DLLFunc_ClientKill, target ) |
562 : | ian | 39 | else { |
563 : | ian | 46 | set_pev( target, pev_health, health ) |
564 : | set_pdata_int(target, m_bitsDamageType, DMG_CRUSH) // m_bitsDamageType = 76 // found by VEN | ||
565 : | set_pev(target, pev_dmg_take, dmg) | ||
566 : | set_pev(target, pev_dmg_inflictor, id) | ||
567 : | ian | 39 | } |
568 : | ian | 1 | |
569 : | client_data[id][FLAGS] ^= CDF_NO_CHOKE | ||
570 : | ian | 10 | set_task( get_pcvar_float( p_choke_time ), "clear_no_choke", TSK_CHKE + id ) |
571 : | ian | 1 | } |
572 : | |||
573 : | public clear_no_choke( tskid ) | ||
574 : | { | ||
575 : | new id = tskid - TSK_CHKE | ||
576 : | client_data[id][FLAGS] ^= CDF_NO_CHOKE | ||
577 : | } | ||
578 : | |||
579 : | //Grabs the client and teleports them to the admin | ||
580 : | public force_grab(id, level, cid) | ||
581 : | { | ||
582 : | if( !cmd_access( id, level, cid, 1 ) || !get_pcvar_num( p_enabled ) ) return PLUGIN_HANDLED | ||
583 : | |||
584 : | new arg[33] | ||
585 : | read_argv( 1, arg, 32 ) | ||
586 : | |||
587 : | new targetid = cmd_target( id, arg, 1 ) | ||
588 : | |||
589 : | if( is_grabbed( targetid, id ) ) return PLUGIN_HANDLED | ||
590 : | if( !is_user_alive( targetid ) ) | ||
591 : | { | ||
592 : | client_print( id, print_console, "[AMXX] %L", id, "COULDNT" ) | ||
593 : | return PLUGIN_HANDLED | ||
594 : | } | ||
595 : | |||
596 : | //Safe to tp target to aim spot? | ||
597 : | ian | 11 | new Float:tmpvec[3], Float:orig[3], Float:torig[3], Float:trace_ret[3] |
598 : | ian | 1 | new bool:safe = false, i |
599 : | |||
600 : | ian | 11 | get_view_pos( id, orig ) |
601 : | tmpvec = vel_by_aim( id, get_pcvar_num( p_min_dist ) ) | ||
602 : | ian | 1 | |
603 : | for( new j = 1; j < 11 && !safe; j++ ) | ||
604 : | { | ||
605 : | ian | 16 | torig[0] = orig[0] + tmpvec[i] * j |
606 : | torig[1] = orig[1] + tmpvec[i] * j | ||
607 : | torig[2] = orig[2] + tmpvec[i] * j | ||
608 : | |||
609 : | ian | 11 | traceline( tmpvec, torig, id, trace_ret ) |
610 : | ian | 5 | |
611 : | ian | 1 | if( get_distance_f( trace_ret, torig ) ) break |
612 : | ian | 8 | |
613 : | engfunc( EngFunc_TraceHull, torig, torig, 0, HULL_HUMAN, 0, 0 ) | ||
614 : | if ( !get_tr2( 0, TR_StartSolid ) && !get_tr2( 0, TR_AllSolid ) && get_tr2( 0, TR_InOpen ) ) | ||
615 : | safe = true | ||
616 : | ian | 1 | } |
617 : | |||
618 : | //Still not safe? Then find another safe spot somewhere around the grabber | ||
619 : | ian | 11 | pev( id, pev_origin, orig ) |
620 : | ian | 1 | new try[3] |
621 : | orig[2] += 2 | ||
622 : | while( try[2] < 3 && !safe ) | ||
623 : | { | ||
624 : | for( i = 0; i < 3; i++ ) | ||
625 : | switch( try[i] ) | ||
626 : | { | ||
627 : | case 0 : torig[i] = orig[i] + ( i == 2 ? 80 : 40 ) | ||
628 : | case 1 : torig[i] = orig[i] | ||
629 : | case 2 : torig[i] = orig[i] - ( i == 2 ? 80 : 40 ) | ||
630 : | } | ||
631 : | |||
632 : | ian | 11 | traceline( tmpvec, torig, id, trace_ret ) |
633 : | ian | 1 | |
634 : | ian | 8 | engfunc( EngFunc_TraceHull, torig, torig, 0, HULL_HUMAN, 0, 0 ) |
635 : | if ( !get_tr2( 0, TR_StartSolid ) && !get_tr2( 0, TR_AllSolid ) && get_tr2( 0, TR_InOpen ) | ||
636 : | && !get_distance_f( trace_ret, torig ) ) safe = true | ||
637 : | ian | 5 | |
638 : | ian | 1 | try[0]++ |
639 : | if( try[0] == 3 ) | ||
640 : | { | ||
641 : | try[0] = 0 | ||
642 : | try[1]++ | ||
643 : | if( try[1] == 3 ) | ||
644 : | { | ||
645 : | try[1] = 0 | ||
646 : | try[2]++ | ||
647 : | } | ||
648 : | } | ||
649 : | } | ||
650 : | |||
651 : | if( safe ) | ||
652 : | { | ||
653 : | ian | 5 | set_pev( targetid, pev_origin, torig ) |
654 : | ian | 1 | set_grabbed( id, targetid ) |
655 : | screenfade_in( id ) | ||
656 : | } | ||
657 : | else client_print( id, print_chat, "[AMXX] %L", id, "COULDNT" ) | ||
658 : | |||
659 : | return PLUGIN_HANDLED | ||
660 : | } | ||
661 : | |||
662 : | public is_grabbed( target, grabber ) | ||
663 : | { | ||
664 : | for( new i = 1; i <= MAXPLAYERS; i++ ) | ||
665 : | if( client_data[i][GRABBED] == target ) | ||
666 : | { | ||
667 : | client_print( grabber, print_chat, "[AMXX] %L", grabber, "ALREADY" ) | ||
668 : | unset_grabbed( grabber ) | ||
669 : | return true | ||
670 : | } | ||
671 : | return false | ||
672 : | } | ||
673 : | |||
674 : | public DeathMsg( ) | ||
675 : | kill_grab( read_data( 2 ) ) | ||
676 : | |||
677 : | public client_disconnect( id ) | ||
678 : | { | ||
679 : | kill_grab( id ) | ||
680 : | return PLUGIN_CONTINUE | ||
681 : | } | ||
682 : | |||
683 : | public kill_grab( id ) | ||
684 : | { | ||
685 : | //If given client has grabbed, or has a grabber, unset it | ||
686 : | if( client_data[id][GRABBED] ) | ||
687 : | unset_grabbed( id ) | ||
688 : | else if( client_data[id][GRABBER] ) | ||
689 : | unset_grabbed( client_data[id][GRABBER] ) | ||
690 : | } | ||
691 : | ian | 11 | |
692 : | stock traceline( const Float:vStart[3], const Float:vEnd[3], const pIgnore, Float:vHitPos[3] ) | ||
693 : | { | ||
694 : | engfunc( EngFunc_TraceLine, vStart, vEnd, 0, pIgnore, 0 ) | ||
695 : | get_tr2( 0, TR_vecEndPos, vHitPos ) | ||
696 : | return get_tr2( 0, TR_pHit ) | ||
697 : | } | ||
698 : | |||
699 : | stock get_view_pos( const id, Float:vViewPos[3] ) | ||
700 : | { | ||
701 : | ian | 27 | new Float:vOfs[3] |
702 : | ian | 11 | pev( id, pev_origin, vViewPos ) |
703 : | ian | 27 | pev( id, pev_view_ofs, vOfs ) |
704 : | ian | 16 | |
705 : | ian | 27 | vViewPos[0] += vOfs[0] |
706 : | vViewPos[1] += vOfs[1] | ||
707 : | vViewPos[2] += vOfs[2] | ||
708 : | ian | 11 | } |
709 : | |||
710 : | stock Float:vel_by_aim( id, speed = 1 ) | ||
711 : | { | ||
712 : | new Float:v1[3], Float:vBlah[3] | ||
713 : | pev( id, pev_v_angle, v1 ) | ||
714 : | engfunc( EngFunc_AngleVectors, v1, v1, vBlah, vBlah ) | ||
715 : | ian | 16 | |
716 : | v1[0] *= speed | ||
717 : | v1[1] *= speed | ||
718 : | v1[2] *= speed | ||
719 : | |||
720 : | ian | 11 | return v1 |
721 : | } |
Contact | ViewVC Help |
Powered by ViewVC 1.0.4 |