]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_dodging.qc
- added threshold to dodging code (to make dodging on stairs easier)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_dodging.qc
1
2 .float cvar_cl_dodging_timeout;
3
4
5 // these are used to store the last key press time for each of the keys..
6 .float last_FORWARD_KEY_time;
7 .float last_BACKWARD_KEY_time;
8 .float last_LEFT_KEY_time;
9 .float last_RIGHT_KEY_time;
10
11 // these store the movement direction at the time of the dodge action happening.
12 .float dodging_direction_x;
13 .float dodging_direction_y;
14
15 // this indicates the last time a dodge was executed. used to check if another one is allowed
16 // and to ramp up the dodge acceleration in the physics hook.
17 .float last_dodging_time;
18
19 // set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
20 .float dodging_action;
21
22 // the jump part of the dodge cannot be ramped
23 .float dodging_single_action;
24
25 void dodging_Initialize() {
26         // print("dodging_Initialize\n");
27
28         self.last_FORWARD_KEY_time = 0;
29         self.last_BACKWARD_KEY_time = 0;
30         self.last_RIGHT_KEY_time = 0;
31         self.last_LEFT_KEY_time = 0;
32         self.last_dodging_time = 0;
33         self.dodging_action = 0;
34         self.dodging_single_action = 0;
35         self.dodging_direction_x = 0;
36         self.dodging_direction_y = 0;
37 }
38
39 MUTATOR_HOOKFUNCTION(dodging_GetCvars) {
40         // print("dodging_GetCvars\n");
41
42         string s;
43         s = strcat1(argv(get_cvars_f));
44
45         GetCvars_handleFloat(s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
46
47         return 0;
48 }
49
50 MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
51         // print("dodging_PlayerPhysics\n");
52
53         float common_factor;
54
55         // is dodging enabled at all? if not, do nothing..
56         if (g_dodging == 0)
57                 return 0;
58
59         // make sure v_up, v_right and v_forward are sane
60         makevectors(self.angles);
61
62         // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code 
63         // will be called ramp_time/frametime times = 2 times. so, we need to 
64         // add 0.5 * the total speed each frame until the dodge action is done..
65         common_factor = sys_frametime / cvar("sv_dodging_ramp_time");
66
67         // if ramp time is smaller than frametime we get problems ;D
68         if (common_factor > 1) 
69                 common_factor = 1;
70
71
72         // ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
73         if (self.dodging_action == 1) {
74                 //disable jump key during dodge accel phase
75                 if (self.movement_z > 0) self.movement_z = 0;
76
77                 self.velocity = 
78                           self.velocity 
79                         + (common_factor * (self.dodging_direction_y * cvar("sv_dodging_horiz_speed")) * v_right) 
80                         + (common_factor * (self.dodging_direction_x * cvar("sv_dodging_horiz_speed")) * v_forward);
81         }
82
83         // the up part of the dodge is a single shot action
84         if (self.dodging_single_action == 1) {
85                 self.velocity = 
86                           self.velocity 
87                         + (cvar("sv_dodging_up_speed") * v_up);
88
89                 self.dodging_single_action = 0;
90         }
91
92         // are we done with the dodging ramp yet?
93         if((self.dodging_action == 1) && ((time - self.last_dodging_time) > cvar("sv_dodging_ramp_time")))
94         {
95                 // reset state so next dodge can be done correctly
96                 self.dodging_action = 0;
97                 self.dodging_direction_x = 0;
98                 self.dodging_direction_y = 0;
99         }
100
101         return 0;
102 }
103
104 MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
105         // print("dodging_PlayerPhysics\n");
106
107         float length;
108         float dodge_detected;
109         vector trace_start;
110         vector trace_end;
111         float height_above_ground;
112
113         if (g_dodging == 0)
114                 return 0;
115
116         dodge_detected = 0;
117
118         // no dodging and jumping at the same time..
119         if (self.BUTTON_JUMP)
120                 return 0;
121
122         // first check if the last dodge is far enough back in time so we can dodge again
123         if ((time - self.last_dodging_time) < cvar("sv_dodging_delay"))
124                 return 0;
125
126         // determine height above ground is below a threshold
127         trace_start = self.origin;
128         trace_end = self.origin - (100*v_up);
129
130         traceline(trace_start, trace_end, TRUE, self);
131         height_above_ground = self.origin_z - trace_endpos_z;
132
133         if (height_above_ground > (fabs(PL_MIN_z) + cvar("sv_dodging_height_threshold")))
134                 return 0;
135
136         // check if our feet are on the ground or at least close :D
137         //if (!(self.lastflags & FL_ONGROUND))
138         //      return 0;
139
140         if (self.movement_x > 0) {
141                 // is this a state change?
142                 if (!(self.pressedkeys & KEY_FORWARD)) {
143                         if ((time - self.last_FORWARD_KEY_time) < self.cvar_cl_dodging_timeout) { 
144                                 dodge_detected = 1;
145                                 self.dodging_direction_x = 1.0;
146                         }
147                         self.last_FORWARD_KEY_time = time;
148                 }
149         }
150
151         if (self.movement_x < 0) {
152                 // is this a state change?
153                 if (!(self.pressedkeys & KEY_BACKWARD)) {
154                         if ((time - self.last_BACKWARD_KEY_time) < self.cvar_cl_dodging_timeout)        { 
155                                 dodge_detected = 1;
156                                 self.dodging_direction_x = -1.0;
157                         }
158                         self.last_BACKWARD_KEY_time = time;
159                 }
160         }
161
162         if (self.movement_y > 0) {
163                 // is this a state change?
164                 if (!(self.pressedkeys & KEY_RIGHT)) {
165                         if ((time - self.last_RIGHT_KEY_time) < self.cvar_cl_dodging_timeout)   { 
166                                 dodge_detected = 1;
167                                 self.dodging_direction_y = 1.0;
168                         }
169                         self.last_RIGHT_KEY_time = time;
170                 }
171         }
172
173         if (self.movement_y < 0) {
174                 // is this a state change?
175                 if (!(self.pressedkeys & KEY_LEFT)) {
176                         if ((time - self.last_LEFT_KEY_time) < self.cvar_cl_dodging_timeout)    { 
177                                 dodge_detected = 1;
178                                 self.dodging_direction_y = -1.0;
179                         }
180                         self.last_LEFT_KEY_time = time;
181                 }
182         }
183
184
185
186         if (dodge_detected == 1) {
187                 if (self.movement_z > 0)
188                         self.movement_z = 0;
189
190                 self.last_dodging_time = time;
191
192                 self.dodging_action = 1;
193                 self.dodging_single_action = 1;
194
195                 // normalize the dodging_direction vector.. (unlike UT99) XD
196                 length = length + self.dodging_direction_x * self.dodging_direction_x;
197                 length = length + self.dodging_direction_y * self.dodging_direction_y;
198                 length = sqrt(length);
199
200                 self.dodging_direction_x = self.dodging_direction_x * 1.0/length;
201                 self.dodging_direction_y = self.dodging_direction_y * 1.0/length;
202         }
203
204         return 0;
205 }
206
207 MUTATOR_DEFINITION(dodging)
208 {
209         // we need to be called before GetPressedKey does its thing so we can
210         // detect state changes and therefore dodging actions..
211         MUTATOR_HOOK(GetPressedKeys, dodging_GetPressedKeys, CBC_ORDER_ANY);
212
213         // in the physics hook we actually implement the dodge..
214         MUTATOR_HOOK(PlayerPhysics, dodging_PlayerPhysics, CBC_ORDER_ANY);
215
216         MUTATOR_HOOK(GetCvars, dodging_GetCvars, CBC_ORDER_ANY);
217
218         // this just turns on the cvar.
219         MUTATOR_ONADD
220         {
221                 g_dodging = 1;
222                 dodging_Initialize();
223         }
224
225         // this just turns off the cvar.
226         MUTATOR_ONREMOVE
227         {        
228                 g_dodging = 0;
229         }
230
231         return 0;
232 }