Xonotic
multijump.qc
Go to the documentation of this file.
1 #include "multijump.qh"
2 
3 #ifdef GAMEQC
4 
5 REPLICATE(cvar_cl_multijump, bool, "cl_multijump");
6 
7 #ifdef SVQC
8  #include <server/antilag.qh>
9 #endif
10 #include <common/physics/player.qh>
11 
12 
13 #if defined(SVQC)
14 REGISTER_MUTATOR(multijump, autocvar_g_multijump);
15 #elif defined(CSQC)
16 REGISTER_MUTATOR(multijump, true);
17 #endif
18 
19 #define PHYS_MULTIJUMP(s) STAT(MULTIJUMP, s)
20 #define PHYS_MULTIJUMP_SPEED(s) STAT(MULTIJUMP_SPEED, s)
21 #define PHYS_MULTIJUMP_ADD(s) STAT(MULTIJUMP_ADD, s)
22 #define PHYS_MULTIJUMP_MAXSPEED(s) STAT(MULTIJUMP_MAXSPEED, s)
23 #define PHYS_MULTIJUMP_DODGING(s) STAT(MULTIJUMP_DODGING, s)
24 #define PHYS_MULTIJUMP_COUNT(s) STAT(MULTIJUMP_COUNT, s)
25 #define PHYS_MULTIJUMP_CLIENTDEFAULT(s) STAT(MULTIJUMP_CLIENT, s)
26 
27 .bool multijump_ready;
28 
29 #ifdef CSQC
30 int autocvar_cl_multijump = -1;
31  #define PHYS_MULTIJUMP_CLIENT(s) autocvar_cl_multijump
32 #elif defined(SVQC)
33  #define PHYS_MULTIJUMP_CLIENT(s) CS_CVAR(s).cvar_cl_multijump
34 #endif
35 
36 MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
37 {
38  entity player = M_ARGV(0, entity);
39 
40 #ifdef CSQC
41  player.multijump_count = PHYS_MULTIJUMP_COUNT(player);
42 #endif
43  if(!PHYS_MULTIJUMP(player)) { return; }
44 
45  if(IS_ONGROUND(player))
46  player.multijump_count = 0;
47 }
48 
50 {
51  entity player = M_ARGV(0, entity);
52 
53  if(!PHYS_MULTIJUMP(player)) { return; }
54 
55  int client_multijump = PHYS_MULTIJUMP_CLIENT(player);
56  if(client_multijump == -1)
57  client_multijump = PHYS_MULTIJUMP_CLIENTDEFAULT(player);
58  if(client_multijump > 1)
59  return; // nope
60 
61  if (!IS_JUMP_HELD(player) && !IS_ONGROUND(player) && client_multijump) // jump button pressed this frame and we are in midair
62  player.multijump_ready = true; // this is necessary to check that we released the jump button and pressed it again
63  else
64  player.multijump_ready = false;
65 
66  int phys_multijump = PHYS_MULTIJUMP(player);
67 
68  if(!M_ARGV(2, bool) && player.multijump_ready && (PHYS_MULTIJUMP_COUNT(player) < phys_multijump || phys_multijump == -1) && player.velocity_z > PHYS_MULTIJUMP_SPEED(player) &&
69  (!PHYS_MULTIJUMP_MAXSPEED(player) || vdist(player.velocity, <=, PHYS_MULTIJUMP_MAXSPEED(player))))
70  {
71  if (PHYS_MULTIJUMP(player))
72  {
73  if (!PHYS_MULTIJUMP_ADD(player)) // in this case we make the z velocity == jumpvelocity
74  {
75  if (player.velocity_z < PHYS_JUMPVELOCITY(player))
76  {
77  M_ARGV(2, bool) = true;
78  player.velocity_z = 0;
79  }
80  }
81  else
82  M_ARGV(2, bool) = true;
83 
84  if(M_ARGV(2, bool))
85  {
86  if(PHYS_MULTIJUMP_DODGING(player))
87  if(PHYS_CS(player).movement_x != 0 || PHYS_CS(player).movement_y != 0) // don't remove all speed if player isnt pressing any movement keys
88  {
89  float curspeed;
90  vector wishvel, wishdir;
91 
92 /*#ifdef SVQC
93  curspeed = max(
94  vlen(vec2(player.velocity)), // current xy speed
95  vlen(vec2(antilag_takebackavgvelocity(player, max(player.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
96  );
97 #elif defined(CSQC)*/
98  curspeed = vlen(vec2(player.velocity));
99 //#endif
100 
101  makevectors(player.v_angle_y * '0 1 0');
102  wishvel = v_forward * PHYS_CS(player).movement_x + v_right * PHYS_CS(player).movement_y;
103  wishdir = normalize(wishvel);
104 
105  player.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
106  player.velocity_y = wishdir_y * curspeed;
107  // keep velocity_z unchanged!
108  }
109  if (PHYS_MULTIJUMP(player) > 0)
110  {
111  player.multijump_count += 1;
112  }
113  }
114  }
115  player.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
116  }
117 }
118 
119 #ifdef SVQC
120 
121 MUTATOR_HOOKFUNCTION(multijump, BuildMutatorsString)
122 {
123  M_ARGV(0, string) = strcat(M_ARGV(0, string), ":multijump");
124 }
125 
126 MUTATOR_HOOKFUNCTION(multijump, BuildMutatorsPrettyString)
127 {
128  M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Multi jump");
129 }
130 
131 #endif
132 
133 #endif
#define REGISTER_MUTATOR(id, dependence)
Definition: base.qh:263
entity() spawn
#define IS_ONGROUND(s)
Definition: movetypes.qh:16
REPLICATE(cvar_cl_casings, bool, "cl_casings")
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define M_ARGV(x, type)
Definition: events.qh:17
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define PHYS_JUMPVELOCITY(s)
Definition: player.qh:127
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
bool PlayerJump(entity this)
Definition: player.qc:330
vector v_right
Definition: csprogsdefs.qc:31
#define vec2(...)
Definition: vector.qh:90
#define MUTATOR_HOOKFUNCTION(...)
Definition: base.qh:310
#define IS_JUMP_HELD(s)
Definition: player.qh:199
#define makevectors
Definition: post.qh:21
vector v_forward
Definition: csprogsdefs.qc:31