1#include "walljump.qh" 2 3#ifdef GAMEQC 4#ifdef CSQC 5REGISTER_MUTATOR(walljump, true); 6#elif defined(SVQC) 7REGISTER_MUTATOR(walljump, cvar("g_walljump")); 8#endif 9 10#define PHYS_WALLJUMP(s) STAT(WALLJUMP, s) 11#define PHYS_WALLJUMP_VELOCITY_Z_FACTOR(s) STAT(WALLJUMP_VELOCITY_Z_FACTOR, s) 12#define PHYS_WALLJUMP_VELOCITY_XY_FACTOR(s) STAT(WALLJUMP_VELOCITY_XY_FACTOR, s) 13#define PHYS_WALLJUMP_DELAY(s) STAT(WALLJUMP_DELAY, s) 14#define PHYS_WALLJUMP_FORCE(s) STAT(WALLJUMP_FORCE, s) 15 16vector PlayerTouchWall(entity this) 17{ 18#define TRACE(newvec) \ 19 tracebox (start, this.mins, this.maxs, (newvec), true, this); \ 20 if (trace_fraction < 1 && vdist(this.origin - trace_endpos, <, dist) && trace_plane_normal_z < max_normal) \ 21 if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) \ 22 return trace_plane_normal; 23 24 float dist = 10, max_normal = 0.2, scaler = 100; 25 vector start = this.origin; 26 TRACE(start + v_forward * scaler) 27 TRACE(start - v_forward * scaler) 28 TRACE(start + v_right * scaler) 29 TRACE(start - v_right * scaler) 30#undef TRACE 31 return '0 0 0'; 32} 33 34MUTATOR_HOOKFUNCTION(walljump, PlayerJump) 35{ 36 entity player = M_ARGV(0, entity); 37 38 if(PHYS_WALLJUMP(player)) 39 if(time - STAT(LASTWJ, player) > PHYS_WALLJUMP_DELAY(player)) // can't do this on client, as it's too stupid to obey counters 40 if(!IS_ONGROUND(player)) 41 if(player.move_movetype != MOVETYPE_NONE && player.move_movetype != MOVETYPE_FOLLOW && player.move_movetype != MOVETYPE_FLY && player.move_movetype != MOVETYPE_NOCLIP) 42 if(!IS_JUMP_HELD(player)) 43 if(!STAT(FROZEN, player)) 44 if(!IS_DEAD(player)) 45 { 46 vector plane_normal = PlayerTouchWall(player); 47 48 if(plane_normal != '0 0 0') 49 { 50 float wj_force = PHYS_WALLJUMP_FORCE(player); 51 float wj_xy_factor = PHYS_WALLJUMP_VELOCITY_XY_FACTOR(player); 52 float wj_z_factor = PHYS_WALLJUMP_VELOCITY_Z_FACTOR(player); 53 player.velocity_x += plane_normal_x * wj_force; 54 player.velocity_x /= wj_xy_factor; 55 player.velocity_y += plane_normal_y * wj_force; 56 player.velocity_y /= wj_xy_factor; 57 player.velocity_z = PHYS_JUMPVELOCITY(player) * wj_z_factor; 58 if(PHYS_INPUT_BUTTON_CROUCH(player)) player.velocity_z *= -1; 59 60#ifdef SVQC 61 STAT(LASTWJ, player) = time; 62 player.oldvelocity = player.velocity; 63 Send_Effect(EFFECT_SMOKE_RING, trace_endpos, plane_normal, 5); 64 PlayerSound(player, playersound_jump, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND); 65 animdecide_setaction(player, ANIMACTION_JUMP, true); 66#endif 67 68 M_ARGV(2, bool) = true; // multijump 69 } 70 } 71} 72 73#endif 74