Xonotic
walljump.qc
Go to the documentation of this file.
1 #include "walljump.qh"
2 
3 #ifdef GAMEQC
4 #ifdef CSQC
5 REGISTER_MUTATOR(walljump, true);
6 #elif defined(SVQC)
7 REGISTER_MUTATOR(walljump, autocvar_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 
16 vector 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  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)
32 #undef TRACE
33  return '0 0 0';
34 }
35 
37 {
38  entity player = M_ARGV(0, entity);
39 
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))
46  if(!IS_DEAD(player))
47  {
48  vector plane_normal = PlayerTouchWall(player);
49 
50  if(plane_normal != '0 0 0')
51  {
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;
61 
62 #ifdef SVQC
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);
68 #endif
69 
70  M_ARGV(2, bool) = true; // multijump
71  }
72  }
73 }
74 
75 #endif
float MOVETYPE_NONE
Definition: progsdefs.qc:246
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition: player.qh:150
#define REGISTER_MUTATOR(id, dependence)
Definition: base.qh:263
const int VOICETYPE_PLAYERSOUND
Definition: globalsound.qh:64
const int ANIMACTION_JUMP
Definition: animdecide.qh:141
entity() spawn
#define IS_ONGROUND(s)
Definition: movetypes.qh:16
origin
Definition: ent_cs.qc:114
void animdecide_setaction(entity e, float action, float restart)
Definition: animdecide.qc:338
const float VOL_BASE
Definition: sound.qh:36
vector trace_endpos
Definition: csprogsdefs.qc:37
#define M_ARGV(x, type)
Definition: events.qh:17
#define IS_DEAD(s)
Definition: utils.qh:26
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define PHYS_JUMPVELOCITY(s)
Definition: player.qh:127
float MOVETYPE_NOCLIP
Definition: progsdefs.qc:254
float MOVETYPE_FOLLOW
bool PlayerJump(entity this)
Definition: player.qc:330
const int CH_PLAYER
Definition: sound.qh:20
vector angles
Definition: csprogsdefs.qc:104
#define MUTATOR_HOOKFUNCTION(...)
Definition: base.qh:310
#define IS_JUMP_HELD(s)
Definition: player.qh:199
float time
Definition: csprogsdefs.qc:16
float MOVETYPE_FLY
Definition: progsdefs.qc:251