]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/multijump/multijump.qc
Merge branch 'divVerent/simpler-clipped-rectangle' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / multijump / multijump.qc
1 #include "multijump.qh"
2
3 #ifdef GAMEQC
4
5 #ifdef SVQC
6         #include <server/antilag.qh>
7 #endif
8 #include <common/physics/player.qh>
9
10
11 #if defined(SVQC)
12 REGISTER_MUTATOR(multijump, autocvar_g_multijump);
13 #elif defined(CSQC)
14 REGISTER_MUTATOR(multijump, true);
15 #endif
16
17 #define PHYS_MULTIJUMP(s)                               STAT(MULTIJUMP, s)
18 #define PHYS_MULTIJUMP_SPEED(s)                 STAT(MULTIJUMP_SPEED, s)
19 #define PHYS_MULTIJUMP_ADD(s)                   STAT(MULTIJUMP_ADD, s)
20 #define PHYS_MULTIJUMP_MAXSPEED(s)              STAT(MULTIJUMP_MAXSPEED, s)
21 #define PHYS_MULTIJUMP_DODGING(s)               STAT(MULTIJUMP_DODGING, s)
22 #define PHYS_MULTIJUMP_COUNT(s)                 STAT(MULTIJUMP_COUNT, s)
23 #define PHYS_MULTIJUMP_CLIENTDEFAULT(s) STAT(MULTIJUMP_CLIENT, s)
24
25 .bool multijump_ready;
26
27 #ifdef CSQC
28 int cvar_cl_multijump;
29 int autocvar_cl_multijump = -1;
30
31         #define PHYS_MULTIJUMP_CLIENT(s)        autocvar_cl_multijump
32 #elif defined(SVQC)
33 .int cvar_cl_multijump;
34
35         #define PHYS_MULTIJUMP_CLIENT(s)        CS(s).cvar_cl_multijump
36 #endif
37
38 MUTATOR_HOOKFUNCTION(multijump, PlayerPhysics)
39 {
40     entity player = M_ARGV(0, entity);
41
42 #ifdef CSQC
43         player.multijump_count = PHYS_MULTIJUMP_COUNT(player);
44 #endif
45         if(!PHYS_MULTIJUMP(player)) { return; }
46
47         if(IS_ONGROUND(player))
48                 player.multijump_count = 0;
49 }
50
51 MUTATOR_HOOKFUNCTION(multijump, PlayerJump)
52 {
53         entity player = M_ARGV(0, entity);
54
55         if(!PHYS_MULTIJUMP(player)) { return; }
56
57         int client_multijump = PHYS_MULTIJUMP_CLIENT(player);
58         if(client_multijump == -1)
59                 client_multijump = PHYS_MULTIJUMP_CLIENTDEFAULT(player);
60         if(client_multijump > 1)
61                 return; // nope
62
63         if (!IS_JUMP_HELD(player) && !IS_ONGROUND(player) && client_multijump) // jump button pressed this frame and we are in midair
64                 player.multijump_ready = true;  // this is necessary to check that we released the jump button and pressed it again
65         else
66                 player.multijump_ready = false;
67
68         int phys_multijump = PHYS_MULTIJUMP(player);
69
70         if(!M_ARGV(2, bool) && player.multijump_ready && (PHYS_MULTIJUMP_COUNT(player) < phys_multijump || phys_multijump == -1) && player.velocity_z > PHYS_MULTIJUMP_SPEED(player) &&
71                 (!PHYS_MULTIJUMP_MAXSPEED(player) || vdist(player.velocity, <=, PHYS_MULTIJUMP_MAXSPEED(player))))
72         {
73                 if (PHYS_MULTIJUMP(player))
74                 {
75                         if (!PHYS_MULTIJUMP_ADD(player)) // in this case we make the z velocity == jumpvelocity
76                         {
77                                 if (player.velocity_z < PHYS_JUMPVELOCITY(player))
78                                 {
79                                         M_ARGV(2, bool) = true;
80                                         player.velocity_z = 0;
81                                 }
82                         }
83                         else
84                                 M_ARGV(2, bool) = true;
85
86                         if(M_ARGV(2, bool))
87                         {
88                                 if(PHYS_MULTIJUMP_DODGING(player))
89                                 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
90                                 {
91                                         float curspeed;
92                                         vector wishvel, wishdir;
93
94 /*#ifdef SVQC
95                                         curspeed = max(
96                                                 vlen(vec2(player.velocity)), // current xy speed
97                                                 vlen(vec2(antilag_takebackavgvelocity(player, max(player.lastteleporttime + sys_frametime, time - 0.25), time))) // average xy topspeed over the last 0.25 secs
98                                         );
99 #elif defined(CSQC)*/
100                                         curspeed = vlen(vec2(player.velocity));
101 //#endif
102
103                                         makevectors(player.v_angle_y * '0 1 0');
104                                         wishvel = v_forward * PHYS_CS(player).movement_x + v_right * PHYS_CS(player).movement_y;
105                                         wishdir = normalize(wishvel);
106
107                                         player.velocity_x = wishdir_x * curspeed; // allow "dodging" at a multijump
108                                         player.velocity_y = wishdir_y * curspeed;
109                                         // keep velocity_z unchanged!
110                                 }
111                                 if (PHYS_MULTIJUMP(player) > 0)
112                                 {
113                                         player.multijump_count += 1;
114                                 }
115                         }
116                 }
117                 player.multijump_ready = false; // require releasing and pressing the jump button again for the next jump
118         }
119 }
120
121 REPLICATE(cvar_cl_multijump, int, "cl_multijump");
122
123 #ifdef SVQC
124
125 MUTATOR_HOOKFUNCTION(multijump, BuildMutatorsString)
126 {
127         M_ARGV(0, string) = strcat(M_ARGV(0, string), ":multijump");
128 }
129
130 MUTATOR_HOOKFUNCTION(multijump, BuildMutatorsPrettyString)
131 {
132         M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Multi jump");
133 }
134
135 #endif
136
137 #endif