5 REGISTER_MUTATOR(walljump, true);
7 REGISTER_MUTATOR(walljump, autocvar_g_walljump);
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)
16 vector PlayerTouchWall(entity this)
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;
24 float dist = 10, max_normal = 0.2, scaler = 100;
25 vector start = this.origin;
26 vector forward, right, _up;
27 MAKE_VECTORS(this.angles, forward, right, _up);
28 TRACE(start + forward * scaler)
29 TRACE(start - forward * scaler)
30 TRACE(start + right * scaler)
31 TRACE(start - right * scaler)
36 MUTATOR_HOOKFUNCTION(walljump, PlayerJump)
38 entity player = M_ARGV(0, entity);
40 if(PHYS_WALLJUMP(player))
41 if(time - STAT(LASTWJ, player) > PHYS_WALLJUMP_DELAY(player)) // can't do this on client, as it's too stupid to obey counters
42 if(!IS_ONGROUND(player))
43 if(player.move_movetype != MOVETYPE_NONE && player.move_movetype != MOVETYPE_FOLLOW && player.move_movetype != MOVETYPE_FLY && player.move_movetype != MOVETYPE_NOCLIP)
44 if(!IS_JUMP_HELD(player))
45 if(!STAT(FROZEN, player))
48 vector plane_normal = PlayerTouchWall(player);
50 if(plane_normal != '0 0 0')
52 float wj_force = PHYS_WALLJUMP_FORCE(player);
53 float wj_xy_factor = PHYS_WALLJUMP_VELOCITY_XY_FACTOR(player);
54 float wj_z_factor = PHYS_WALLJUMP_VELOCITY_Z_FACTOR(player);
55 player.velocity_x += plane_normal_x * wj_force;
56 player.velocity_x /= wj_xy_factor;
57 player.velocity_y += plane_normal_y * wj_force;
58 player.velocity_y /= wj_xy_factor;
59 player.velocity_z = PHYS_JUMPVELOCITY(player) * wj_z_factor;
60 if(PHYS_INPUT_BUTTON_CROUCH(player)) player.velocity_z *= -1;
63 STAT(LASTWJ, player) = time;
64 player.oldvelocity = player.velocity;
65 Send_Effect(EFFECT_SMOKE_RING, trace_endpos, plane_normal, 5);
66 PlayerSound(player, playersound_jump, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
67 animdecide_setaction(player, ANIMACTION_JUMP, true);
70 M_ARGV(2, bool) = true; // multijump