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