Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
player.qc
Go to the documentation of this file.
1#include "player.qh"
2
4#include <common/viewloc.qh>
5
6#ifdef GAMEQC
7REPLICATE(cvar_cl_physics, string, "cl_physics");
8REPLICATE(cvar_cl_jetpack_jump, bool, "cl_jetpack_jump");
9REPLICATE(cvar_cl_movement_track_canjump, bool, "cl_movement_track_canjump");
10#endif
11
12#ifdef SVQC
15#include <server/client.qh>
16
17// client side physics
18bool Physics_Valid(string thecvar)
19{
20 return thecvar != "" && thecvar != "default" && strhasword(autocvar_g_physics_clientselect_options, thecvar);
21}
22
23float Physics_ClientOption(entity this, string option, float defaultval)
24{
26 return defaultval;
27
28 if(IS_REAL_CLIENT(this) && Physics_Valid(CS_CVAR(this).cvar_cl_physics))
29 {
30 string s = strcat("g_physics_", CS_CVAR(this).cvar_cl_physics, "_", option);
31 if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
32 return cvar(s);
33 }
35 {
36 // NOTE: not using Physics_Valid here, so the default can be forced to something normally unavailable
37 string s = strcat("g_physics_", autocvar_g_physics_clientselect_default, "_", option);
38 if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
39 return cvar(s);
40 }
41 return defaultval;
42}
43
45{
46 // update this first, as it's used on all stats (wouldn't want to update them all manually from a mutator hook now, would we?)
47 STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed;
48
49 MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this);
50 float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active == ACTIVE_ACTIVE) ? this.swampslug.swamp_slowdown : 1);
51 STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
53 {
54 STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
55 STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw);
56 STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw);
57 }
58 else
59 {
60 STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw), maxspd_mod);
61 STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw))
62 ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw), maxspd_mod)
63 : 0;
64 STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
65 }
66
68 {
69 /* Q3 uses the following:
70 * MIN '-15 -15 -24'
71 * MAX '15 15 32'
72 * VIEW_OFS '0 0 26'
73 * CROUCH_MIN '-15 -15 -24'
74 * CROUCH_MAX '15 15 16'
75 * CROUCH_VIEW_OFS '0 0 12'
76 * but Xonotic player models have a different z offset to suit origin at 24/69.
77 * At q3compat hitbox dimensions and model scale the equivalent offset is origin at 20/56.
78 * See also: model .scale in PutPlayerInServer().
79 */
81 STAT(PL_MIN, this) = q3hb ? '-15 -15 -20' : autocvar_sv_player_mins;
82 STAT(PL_MAX, this) = q3hb ? '15 15 36' : autocvar_sv_player_maxs;
83 STAT(PL_VIEW_OFS, this) = q3hb ? '0 0 30' : autocvar_sv_player_viewoffset;
84 STAT(PL_CROUCH_MIN, this) = q3hb ? '-15 -15 -20' : autocvar_sv_player_crouch_mins;
85 STAT(PL_CROUCH_MAX, this) = q3hb ? '15 15 20' : autocvar_sv_player_crouch_maxs;
86 STAT(PL_CROUCH_VIEW_OFS, this) = q3hb ? '0 0 16' : autocvar_sv_player_crouch_viewoffset;
87 }
88 else
89 {
90 /* Quake and Q2 use a wider bbox matching the Q1BSP 32x32x56 cliphull:
91 * MIN '-16 -16 -24'
92 * MAX '16 16 32'
93 * VIEW_OFS '0 0 22'
94 * Quake doesn't support crouching, Q2 has a very low crouch:
95 * CROUCH_MIN '-16 -16 -24'
96 * CROUCH_MAX '16 16 4'
97 * CROUCH_VIEW_OFS '0 0 -2'
98 * We probably want a higher VIEW_OFS and Xonotic models don't crouch low enough for Q2 settings
99 * so these are the same heights as for Q3 above.
100 */
101 STAT(PL_MIN, this) = '-16 -16 -20';
102 STAT(PL_MAX, this) = '16 16 36';
103 STAT(PL_VIEW_OFS, this) = '0 0 30';
104 STAT(PL_CROUCH_MIN, this) = '-16 -16 -20';
105 // Q1BSP has no cliphull to support crouching so disable it there, see PM_ClientMovement_UpdateStatus().
106 STAT(PL_CROUCH_MAX, this) = autocvar_sv_mapformat_is_quake2 ? '16 16 20' : STAT(PL_MAX, this);
107 STAT(PL_CROUCH_VIEW_OFS, this) = autocvar_sv_mapformat_is_quake2 ? '0 0 16' : STAT(PL_VIEW_OFS, this);
108 }
109
110 STAT(MOVEVARS_GRAVITY, this) = Physics_ClientOption(this, "gravity", autocvar_sv_gravity);
111
112 // old stats
113 // fix some new settings
114 STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor", autocvar_sv_airaccel_qw_stretchfactor);
115 STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed", autocvar_sv_maxairstrafespeed);
117 STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed) * maxspd_mod;
118 else
119 STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed);
120
121 STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate", autocvar_sv_airstrafeaccelerate);
122 STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel", autocvar_sv_warsowbunny_turnaccel);
123 STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction", autocvar_sv_airaccel_sideways_friction);
124 STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol", autocvar_sv_aircontrol);
125 STAT(MOVEVARS_AIRCONTROL_FLAGS, this) = Physics_ClientOption(this, "aircontrol_flags", autocvar_sv_aircontrol_flags);
126 STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power", autocvar_sv_aircontrol_power);
127 STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty", autocvar_sv_aircontrol_penalty);
128 STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel", autocvar_sv_warsowbunny_airforwardaccel);
129 STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed", autocvar_sv_warsowbunny_topspeed);
130 STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel", autocvar_sv_warsowbunny_accel);
131 STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio", autocvar_sv_warsowbunny_backtosideratio);
132 STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction", autocvar_sv_friction);
133 STAT(MOVEVARS_FRICTION_SLICK, this) = Physics_ClientOption(this, "friction_slick", autocvar_sv_friction_slick);
134 STAT(MOVEVARS_STEPHEIGHT, this) = Physics_ClientOption(this, "stepheight", autocvar_sv_stepheight);
135 STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate", autocvar_sv_accelerate);
136 STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed", autocvar_sv_stopspeed);
137 STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate", autocvar_sv_airaccelerate);
138 STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate", autocvar_sv_airstopaccelerate);
139 STAT(MOVEVARS_AIRSTOPACCELERATE_FULL, this) = Physics_ClientOption(this, "airstopaccelerate_full", autocvar_sv_airstopaccelerate_full);
140 STAT(MOVEVARS_SLICKACCELERATE, this) = Physics_ClientOption(this, "slickaccelerate", autocvar_sv_slickaccelerate);
141 STAT(DOUBLEJUMP, this) = Physics_ClientOption(this, "doublejump", autocvar_sv_doublejump);
142 STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity", autocvar_sv_jumpvelocity);
143 STAT(MOVEVARS_JUMPVELOCITY_CROUCH, this) = Physics_ClientOption(this, "jumpvelocity_crouch", autocvar_sv_jumpvelocity_crouch);
144 STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, this) = Physics_ClientOption(this, "jumpspeedcap_max_disable_on_ramps", autocvar_sv_jumpspeedcap_max_disable_on_ramps);
145 STAT(MOVEVARS_JUMPSPEEDCAP_MIN, this) = Physics_ClientOption(this, "jumpspeedcap_min", autocvar_sv_jumpspeedcap_min);
146 STAT(MOVEVARS_JUMPSPEEDCAP_MAX, this) = Physics_ClientOption(this, "jumpspeedcap_max", autocvar_sv_jumpspeedcap_max);
147 STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump", autocvar_sv_track_canjump);
149
150 MUTATOR_CALLHOOK(PlayerPhysics_PostUpdateStats, this, maxspd_mod);
151}
152#endif
153
154float IsMoveInDirection(vector mv, float ang) // key mix factor
155{
156 if (mv_x == 0 && mv_y == 0)
157 return 0; // avoid division by zero
158 ang -= RAD2DEG * atan2(mv_y, mv_x);
159 ang = remainder(ang, 360) / 45;
160 return ang > 1 ? 0 : ang < -1 ? 0 : 1 - fabs(ang);
161}
162
163float GeomLerp(float a, float _lerp, float b)
164{
165 return a == 0 ? (_lerp < 1 ? 0 : b)
166 : b == 0 ? (_lerp > 0 ? 0 : a)
167 : a * (fabs(b / a) ** _lerp);
168}
169
171{
172 if(!IS_PLAYER(this))
173 return;
174
175 bool have_hook = false;
176 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
177 {
178 #if defined(CSQC)
179 entity wepent = viewmodels[slot];
180 #elif defined(SVQC)
181 .entity weaponentity = weaponentities[slot];
182 entity wepent = this.(weaponentity);
183 #endif
184 if(wepent.hook && !wasfreed(wepent.hook))
185 {
186 have_hook = true;
187 break;
188 }
189 }
190
191 bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
192 if(this.viewloc && !(this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && PHYS_CS(this).movement.x < 0)
193 do_crouch = true;
194 if (have_hook)
195 do_crouch = false;
196// else if (this.waterlevel >= WATERLEVEL_SWIMMING)
197// do_crouch = false;
198 else if (PHYS_INVEHICLE(this))
199 do_crouch = false;
200 else if (PHYS_FROZEN(this) || IS_DEAD(this))
201 do_crouch = false;
202
203 MUTATOR_CALLHOOK(PlayerCanCrouch, this, do_crouch);
204 do_crouch = M_ARGV(1, bool);
205
206 // Disable crouching on Q1BSP because it lacks a suitable cliphull (HLBSP added one).
207 if (STAT(PL_CROUCH_MAX, this).z == STAT(PL_MAX, this).z)
208 do_crouch = false;
209
210 if (do_crouch)
211 {
212 if (!IS_DUCKED(this))
213 {
214 SET_DUCKED(this);
215 this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
216 setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
217 // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
218 }
219 }
220 else if (IS_DUCKED(this))
221 {
222 tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, MOVE_NORMAL, this);
223 if (!trace_startsolid)
224 {
225 UNSET_DUCKED(this);
226 this.view_ofs = STAT(PL_VIEW_OFS, this);
227 setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
228 }
229 }
230
231 _Movetype_CheckWater(this); // needs to be run on the client, might as well use the latest on the server too!
232}
233
234void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
235{
236 float movity = IsMoveInDirection(PHYS_CS(this).movement, 0);
237 if(PHYS_AIRCONTROL_FLAGS(this) & BIT(0)) // backwards
238 movity += IsMoveInDirection(PHYS_CS(this).movement, 180);
239 if(PHYS_AIRCONTROL_FLAGS(this) & BIT(1)) // sidewards
240 {
241 movity += IsMoveInDirection(PHYS_CS(this).movement, 90);
242 movity += IsMoveInDirection(PHYS_CS(this).movement, -90);
243 }
244
245 float k = 2 * movity - 1;
246 if (k <= 0)
247 return;
248 if (!(PHYS_AIRCONTROL_FLAGS(this) & BIT(2))) // crouching has an impact
249 k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(this), 1);
250
251 const float zspeed = this.velocity_z;
252 this.velocity_z = 0;
253 float xyspeed = vlen(this.velocity);
254 this.velocity = normalize(this.velocity);
255
256 float dot = this.velocity * wishdir;
257
258 if (dot > 0) // we can't change direction while slowing down
259 {
260 k *= (dot ** PHYS_AIRCONTROL_POWER(this)) * dt;
261 xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k);
262 k *= 32 * fabs(PHYS_AIRCONTROL(this));
263 this.velocity = normalize(this.velocity * xyspeed + wishdir * k);
264 }
265
266 this.velocity = this.velocity * xyspeed;
267 this.velocity_z = zspeed;
268}
269
270float AdjustAirAccelQW(float accelqw, float factor)
271{
272 return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
273}
274
275// example config for alternate speed clamping:
276// sv_airaccel_qw 0.8
277// sv_airaccel_sideways_friction 0
278// prvm_globalset server speedclamp_mode 1
279// (or 2)
280void PM_Accelerate(entity this, float dt, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
281{
282 float speedclamp = stretchfactor > 0 ? stretchfactor
283 : accelqw < 0 ? 1 // full clamping, no stretch
284 : -1; // no clamping
285
286 accelqw = fabs(accelqw);
287
289 wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
290
291 float vel_straight = this.velocity * wishdir;
292 float vel_z = this.velocity_z;
293 vector vel_xy = vec2(this.velocity);
294 vector vel_perpend = vel_xy - vel_straight * wishdir;
295
296 float step = accel * dt * wishspeed0;
297
298 float vel_xy_current = vlen(vel_xy);
299 if (speedlimit)
300 accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
301 float vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
302 float vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
303 vel_xy_backward = max(0, vel_xy_backward); // not that it REALLY occurs that this would cause wrong behaviour afterwards
304 vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
305
306 if (sidefric < 0 && (vel_perpend*vel_perpend))
307 // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
308 {
309 float f = max(0, 1 + dt * wishspeed * sidefric);
310 float themin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
311 // assume: themin > 1
312 // vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
313 // vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
314 // vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
315 // obviously, this cannot be
316 if (themin <= 0)
317 vel_perpend *= f;
318 else
319 {
320 themin = sqrt(themin);
321 vel_perpend *= max(themin, f);
322 }
323 }
324 else
325 vel_perpend *= max(0, 1 - dt * wishspeed * sidefric);
326
327 vel_xy = vel_straight * wishdir + vel_perpend;
328
329 if (speedclamp >= 0)
330 {
331 float vel_xy_preclamp;
332 vel_xy_preclamp = vlen(vel_xy);
333 if (vel_xy_preclamp > 0) // prevent division by zero
334 {
335 vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
336 if (vel_xy_current < vel_xy_preclamp)
337 vel_xy *= (vel_xy_current / vel_xy_preclamp);
338 }
339 }
340
341 this.velocity = vel_xy + vel_z * '0 0 1';
342}
343
344void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
345{
346 if (wishspeed == 0)
347 return;
348
349 vector curvel = this.velocity;
350 curvel_z = 0;
351 float curspeed = vlen(curvel);
352
353 if (wishspeed > curspeed * 1.01)
354 wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * dt);
355 else
356 {
357 float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED(this) - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED(this) - PHYS_MAXSPEED(this)));
358 wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * dt;
359 }
360 vector wishvel = wishdir * wishspeed;
361 vector acceldir = wishvel - curvel;
362 float addspeed = vlen(acceldir);
363 acceldir = normalize(acceldir);
364
365 float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * dt);
366
368 {
369 vector curdir = normalize(curvel);
370 float dot = acceldir * curdir;
371 if (dot < 0)
372 acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this)) * dot * curdir;
373 }
374
375 this.velocity += accelspeed * acceldir;
376}
377
378
379/*
380=============
381PlayerJump
382
383When you press the jump key
384returns true if handled
385=============
386*/
388{
389 if (PHYS_FROZEN(this))
390 return true; // no jumping in freezetag when frozen
391
393 return true; // no jumping while typing
394
395#ifdef SVQC
396 if (this.player_blocked)
397 return true; // no jumping while blocked
398#endif
399
400 bool doublejump = false;
401 float mjumpheight = ((PHYS_JUMPVELOCITY_CROUCH(this) && IS_DUCKED(this)) ? PHYS_JUMPVELOCITY_CROUCH(this) : PHYS_JUMPVELOCITY(this));
402 bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
403
404 if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump))
405 return true;
406
407 mjumpheight = M_ARGV(1, float);
408 doublejump = M_ARGV(2, bool);
409
411 {
412 if(this.viewloc)
413 {
414 doublejump = true;
415 mjumpheight *= 0.7;
416 track_jump = true;
417 }
418 else
419 {
420 this.velocity_z = PHYS_MAXSPEED(this) * 0.7;
421 return true;
422 }
423 }
424
425 if (!doublejump)
426 if (!IS_ONGROUND(this))
427 return IS_JUMP_HELD(this);
428
429 if(PHYS_TRACK_CANJUMP(this))
430 track_jump = true;
431
432 if (track_jump)
433 if (IS_JUMP_HELD(this))
434 return true;
435
436 // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
437 // velocity bounds. Final velocity is bound between (jumpheight *
438 // min + jumpheight) and (jumpheight * max + jumpheight);
439
440 if (!isnan(PHYS_JUMPSPEEDCAP_MIN(this)))
441 {
442 float minjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MIN(this);
443
444 if (this.velocity_z < minjumpspeed)
445 mjumpheight += minjumpspeed - this.velocity_z;
446 }
447
448 if (!isnan(PHYS_JUMPSPEEDCAP_MAX(this)))
449 {
450 // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
451 tracebox(this.origin + '0 0 0.01', this.mins, this.maxs, this.origin - '0 0 0.01', MOVE_NORMAL, this);
452
453 if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS(this)))
454 {
455 float maxjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MAX(this);
456
457 if (this.velocity_z > maxjumpspeed)
458 mjumpheight -= this.velocity_z - maxjumpspeed;
459 }
460 }
461
462 if (!WAS_ONGROUND(this) && !WAS_ONSLICK(this))
463 {
464#ifdef SVQC
466 LOG_TRACE("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")");
467#endif
468 if(this.lastground < time - 0.3)
469 {
470 float f = (1 - PHYS_FRICTION_ONLAND(this));
471 f = bound(0, f, 1);
472 this.velocity_x *= f;
473 this.velocity_y *= f;
474 }
475#ifdef SVQC
476 if(this.jumppadcount > 1)
477 LOG_TRACE(ftos(this.jumppadcount), "x jumppad combo");
478 this.jumppadcount = 0;
479#endif
480 }
481
482 this.velocity_z += mjumpheight;
483
484 UNSET_ONGROUND(this);
485 UNSET_ONSLICK(this);
486 SET_JUMP_HELD(this);
487
488#ifdef CSQC
490#endif
491
492#ifdef SVQC
494
496 PlayerSound(this, playersound_jump, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND, 1);
497#endif
498 return true;
499}
500
502{
503// check for a jump-out-of-water
504 makevectors(this.v_angle);
505 vector start = this.origin;
506 start_z += 8;
507 v_forward_z = 0;
509 vector end = start + v_forward*24;
510 traceline (start, end, true, this);
511 if (trace_fraction < 1)
512 { // solid at waist
513 start_z = start_z + this.maxs_z - 8;
514 end = start + v_forward*24;
515 this.movedir = trace_plane_normal * -50;
516 traceline(start, end, true, this);
517 if (trace_fraction == 1)
518 { // open at eye level
519 this.velocity_z = 225;
520 this.flags |= FL_WATERJUMP;
521 this.teleport_time = time + 2; // safety net
522 SET_JUMP_HELD(this);
523 }
524 }
525}
526
527
528#ifdef SVQC
529 #define JETPACK_JUMP(s) CS_CVAR(s).cvar_cl_jetpack_jump
530#elif defined(CSQC)
531 float autocvar_cl_jetpack_jump;
532 #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
533#endif
536{
537#ifdef SVQC
538 bool was_flying = boolean(ITEMS_STAT(this) & IT_USING_JETPACK);
539#endif
540 if (JETPACK_JUMP(this) < 2)
542
544 {
545 bool playerjump = PlayerJump(this); // required
546
547 bool air_jump = !playerjump || M_ARGV(2, bool);
548 bool activate = (JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this)) || PHYS_INPUT_BUTTON_JETPACK(this);
549 bool has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || (ITEMS_STAT(this) & IT_UNLIMITED_AMMO);
550
551 if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
552 else if (this.jetpack_stopped) { }
553 else if (!has_fuel)
554 {
555#ifdef SVQC
556 if (was_flying) // TODO: ran out of fuel message
557 Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
558 else if (activate)
559 Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
560#endif
561 this.jetpack_stopped = true;
563 }
564 else if (activate && !PHYS_FROZEN(this))
566 }
567 else
568 {
569 this.jetpack_stopped = false;
571 }
572
573 if (!PHYS_INPUT_BUTTON_JUMP(this))
574 UNSET_JUMP_HELD(this);
575
577 CheckWaterJump(this);
578}
579
580#ifdef SVQC
581string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
584{
585 if(autocvar_sv_cheats || this.maycheat)
586 {
587 if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse))
588 LOG_INFO("A hollow voice says \"Plugh\".");
589 }
590}
591#endif
592
593bool PM_check_specialcommand(entity this, int buttons)
594{
595#ifdef SVQC
596 string c;
597 switch (buttons)
598 {
599 // buttons mapped in PHYS_INPUT_BUTTON_MASK
600 case 0: c = "x"; break;
601 case BIT(0): c = "1"; break;
602 case BIT(2): c = " "; break;
603 case BIT(7): c = "s"; break;
604 case BIT(8): c = "w"; break;
605 case BIT(9): c = "a"; break;
606 case BIT(10): c = "d"; break;
607 default: c = "?";
608 }
609
610 if (c == substring(specialcommand, CS(this).specialcommand_pos, 1))
611 {
612 CS(this).specialcommand_pos += 1;
614 {
615 CS(this).specialcommand_pos = 0;
616 SpecialCommand(this);
617 return true;
618 }
619 }
620 else if (CS(this).specialcommand_pos && (c != substring(specialcommand, CS(this).specialcommand_pos - 1, 1)))
621 CS(this).specialcommand_pos = 0;
622#endif
623 return false;
624}
625
626void PM_check_punch(entity this, float dt)
627{
628#ifdef SVQC
629 if (this.punchangle != '0 0 0')
630 {
631 float f = vlen(this.punchangle) - 10 * dt;
632 if (f > 0)
633 this.punchangle = normalize(this.punchangle) * f;
634 else
635 this.punchangle = '0 0 0';
636 }
637
638 if (this.punchvector != '0 0 0')
639 {
640 float f = vlen(this.punchvector) - 30 * dt;
641 if (f > 0)
642 this.punchvector = normalize(this.punchvector) * f;
643 else
644 this.punchvector = '0 0 0';
645 }
646#endif
647}
648
649// predict frozen movement, as frozen players CAN move in some cases
651{
652 if (!PHYS_FROZEN(this))
653 return;
654 if (PHYS_DODGING_FROZEN(this) && IS_CLIENT(this))
655 {
656 // bind movement to a very slow speed so dodging can use .movement for directional calculations
657 PHYS_CS(this).movement_x = bound(-2, PHYS_CS(this).movement.x, 2);
658 PHYS_CS(this).movement_y = bound(-2, PHYS_CS(this).movement.y, 2);
659 PHYS_CS(this).movement_z = bound(-2, PHYS_CS(this).movement.z, 2);
660 }
661 else
662 PHYS_CS(this).movement = '0 0 0';
663}
664
666{
667#ifdef SVQC
668 if (!this.wasFlying) return;
669 this.wasFlying = false;
670 if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
671 if (this.ladder_entity) return;
672 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
673 {
674 .entity weaponentity = weaponentities[slot];
675 if(this.(weaponentity).hook)
676 return;
677 }
678 this.nextstep = time + 0.3 + random() * 0.1;
680 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
683 ? GS_FALL_METAL
684 : GS_FALL;
685 float vol = ((IS_DUCKED(this)) ? VOL_MUFFLED : VOL_BASE);
687#endif
688}
689
691{
692#ifdef SVQC
693 if (!autocvar_g_footsteps) return;
694 if (IS_DUCKED(this)) return;
695 if (time >= this.lastground + 0.2) return;
696 if (vdist(this.velocity, <=, autocvar_sv_maxspeed * 0.6)) return;
697 if ((time > this.nextstep) || (time < (this.nextstep - 10.0)))
698 {
699 this.nextstep = time + 0.3 + random() * 0.1;
701 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
704 ? GS_STEP_METAL
705 : GS_STEP;
707 }
708#endif
709}
710
712{
713 if(!IS_ONGROUND(this))
714 return;
715
717 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
719 SET_ONSLICK(this);
720 else
721 UNSET_ONSLICK(this);
722}
723
725{
727 PHYS_CS(this).movement = '0 0 0';
728#ifdef SVQC
729 if (!this.player_blocked)
730 return;
731 PHYS_CS(this).movement = '0 0 0';
733#endif
734}
735
736void PM_jetpack(entity this, float maxspd_mod, float dt)
737{
738 //makevectors(this.v_angle.y * '0 1 0');
739 makevectors(this.v_angle);
740 vector wishvel = v_forward * PHYS_CS(this).movement_x
741 + v_right * PHYS_CS(this).movement_y;
742 // add remaining speed as Z component
743 float maxairspd = PHYS_MAXAIRSPEED(this) * max(1, maxspd_mod);
744 // fix speedhacks :P
745 wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
746 // add the unused velocity as up component
747 wishvel_z = 0;
748
749 // if (PHYS_INPUT_BUTTON_JUMP(this))
750 wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
751
752 // it is now normalized, so...
753 float a_side = PHYS_JETPACK_ACCEL_SIDE(this);
754 float a_up = PHYS_JETPACK_ACCEL_UP(this);
755 float a_add = PHYS_JETPACK_ANTIGRAVITY(this) * PHYS_GRAVITY(this);
756
758
759 wishvel_x *= a_side;
760 wishvel_y *= a_side;
761 wishvel_z *= a_up;
762 wishvel_z += a_add;
763
764 if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { wishvel_z *= -1; }
765
766 float best = 0;
768 // finding the maximum over all vectors of above form
769 // with wishvel having an absolute value of 1
771 // we're finding the maximum over
772 // f(a_side, a_up, a_add, z) := a_side * (1 - z^2) + (a_add + a_up * z)^2;
773 // for z in the range from -1 to 1
775 // maximum is EITHER attained at the single extreme point:
776 float a_diff = a_side * a_side - a_up * a_up;
777 float f;
778 if (a_diff != 0)
779 {
780 f = a_add * a_up / a_diff; // this is the zero of diff(f(a_side, a_up, a_add, z), z)
781 if (f > -1 && f < 1) // can it be attained?
782 {
783 best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
784 //print("middle\n");
785 }
786 }
787 // OR attained at z = 1:
788 f = (a_up + a_add) * (a_up + a_add);
789 if (f > best)
790 {
791 best = f;
792 //print("top\n");
793 }
794 // OR attained at z = -1:
795 f = (a_up - a_add) * (a_up - a_add);
796 if (f > best)
797 {
798 best = f;
799 //print("bottom\n");
800 }
801 best = sqrt(best);
803
804 //print("best possible acceleration: ", ftos(best), "\n");
805
806 float fxy, fz;
807 fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE(this), 1);
808 if (wishvel_z - PHYS_GRAVITY(this) > 0)
809 fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP(this), 1);
810 else
811 fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP(this), 1);
812
813 float fvel;
814 fvel = vlen(wishvel);
815 wishvel_x *= fxy;
816 wishvel_y *= fxy;
817 wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
818
819 fvel = min(1, vlen(wishvel) / best);
820 if (PHYS_JETPACK_FUEL(this) && !(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
821 f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL(this) * dt * fvel));
822 else
823 f = 1;
824
825 //print("this acceleration: ", ftos(vlen(wishvel) * f), "\n");
826
827 if (f > 0 && wishvel != '0 0 0')
828 {
829 this.velocity = this.velocity + wishvel * f * dt;
830 UNSET_ONGROUND(this);
831
832#ifdef SVQC
833 if (!(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
834 TakeResource(this, RES_FUEL, PHYS_JETPACK_FUEL(this) * dt * fvel * f);
835
837
838 // jetpack also inhibits health regeneration, but only for 1 second
840#endif
841 }
842}
843
844// used for calculating airshots
845bool IsFlying(entity this)
846{
847 if(IS_ONGROUND(this))
848 return false;
850 return false;
851 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 24', MOVE_NORMAL, this);
852 //traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
853 if(trace_fraction < 1)
854 return false;
855 return true;
856}
857
858
859void sys_phys_update(entity this, float dt);
860#if defined(SVQC)
861void SV_PlayerPhysics(entity this) // called by engine before it calls PlayerPreThink()
862#elif defined(CSQC)
864#endif
865{
866#ifdef SVQC
867 // needs to be called before physics are run!
868 if(IS_REAL_CLIENT(this))
869 PM_UpdateButtons(this, CS(this));
870#elif defined(CSQC)
871 if(this.last_pushed && !WarpZoneLib_ExactTrigger_Touch(this.last_pushed, this, false))
872 this.last_pushed = NULL;
873#endif
874
876
877#ifdef SVQC
878 CS(this).pm_frametime = frametime;
879#elif defined(CSQC)
880 if((ITEMS_STAT(this) & IT_USING_JETPACK) && !IS_DEAD(this) && !intermission)
882 else
884#endif
885}
void animdecide_setaction(entity e, float action, float restart)
const int ANIMACTION_JUMP
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
#define boolean(value)
Definition bool.qh:9
bool maycheat
Definition cheats.qc:44
float CheatImpulse(entity this, int imp)
Definition cheats.qc:138
int autocvar_sv_cheats
Definition cheats.qh:5
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
vector punchangle
void CSQC_ClientMovement_PlayerMove_Frame(entity this)
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
const int IT_USING_JETPACK
Definition item.qh:27
const int IT_UNLIMITED_AMMO
Definition item.qh:23
#define M_ARGV(x, type)
Definition events.qh:17
void PM_check_hitground(entity this)
Definition player.qc:665
void PM_jetpack(entity this, float maxspd_mod, float dt)
Definition player.qc:736
void PM_check_blocked(entity this)
Definition player.qc:724
float Physics_ClientOption(entity this, string option, float defaultval)
Definition player.qc:23
void PM_check_frozen(entity this)
Definition player.qc:650
void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
Definition player.qc:234
float jetpack_stopped
Definition player.qc:534
void CheckPlayerJump(entity this)
Definition player.qc:535
void sys_phys_update(entity this, float dt)
Definition physics.qc:10
void PM_ClientMovement_UpdateStatus(entity this)
Definition player.qc:170
float specialcommand_pos
Definition player.qc:582
bool Physics_Valid(string thecvar)
Definition player.qc:18
float GeomLerp(float a, float _lerp, float b)
Definition player.qc:163
void PM_check_punch(entity this, float dt)
Definition player.qc:626
void Physics_UpdateStats(entity this)
Definition player.qc:44
bool PM_check_specialcommand(entity this, int buttons)
Definition player.qc:593
void PM_check_slick(entity this)
Definition player.qc:711
bool PlayerJump(entity this)
Definition player.qc:387
float AdjustAirAccelQW(float accelqw, float factor)
Definition player.qc:270
void SpecialCommand(entity this)
Definition player.qc:583
void CheckWaterJump(entity this)
Definition player.qc:501
string specialcommand
Definition player.qc:581
float IsMoveInDirection(vector mv, float ang)
Definition player.qc:154
bool IsFlying(entity this)
Definition player.qc:845
#define JETPACK_JUMP(s)
Definition player.qc:529
void PM_Accelerate(entity this, float dt, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
Definition player.qc:280
void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
Definition player.qc:344
void PM_Footsteps(entity this)
Definition player.qc:690
#define PHYS_CL_TRACK_CANJUMP(s)
Definition player.qh:281
vector autocvar_sv_player_crouch_viewoffset
Definition player.qh:340
float autocvar_sv_airstrafeaccel_qw
Definition player.qh:16
float autocvar_sv_warsowbunny_airforwardaccel
Definition player.qh:27
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition player.qh:156
bool autocvar_g_footsteps
Definition player.qh:54
#define PHYS_JETPACK_FUEL(s)
Definition player.qh:125
entity hook
Definition player.qh:238
vector autocvar_sv_player_viewoffset
Definition player.qh:337
#define PHYS_WARSOWBUNNY_ACCEL(s)
Definition player.qh:144
bool autocvar_g_jump_grunt
Definition player.qh:41
float autocvar_sv_jumpvelocity
Definition player.qh:50
#define PHYS_INPUT_TIMELENGTH
Definition player.qh:253
vector movement
Definition player.qh:228
vector autocvar_sv_player_crouch_mins
Definition player.qh:339
vector autocvar_sv_player_maxs
Definition player.qh:335
#define PHYS_JETPACK_MAXSPEED_UP(s)
Definition player.qh:127
#define PHYS_JUMPSPEEDCAP_MAX(s)
Definition player.qh:132
float autocvar_sv_warsowbunny_turnaccel
Definition player.qh:21
float autocvar_sv_friction
Definition player.qh:31
#define PHYS_CS(s)
Definition player.qh:257
#define IS_CLIENT(s)
Definition player.qh:241
#define IS_DEAD(s)
Definition player.qh:244
string autocvar_g_physics_clientselect_options
Definition player.qh:39
#define PHYS_JETPACK_REVERSE_THRUST(s)
Definition player.qh:128
#define PHYS_WARSOWBUNNY_TOPSPEED(s)
Definition player.qh:147
#define UNSET_DUCKED(s)
Definition player.qh:214
#define PHYS_INPUT_BUTTON_JUMP(s)
Definition player.qh:153
#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s)
Definition player.qh:145
#define PHYS_AIRCONTROL_PENALTY(s)
Definition player.qh:102
float autocvar_sv_jumpspeedcap_min
Definition player.qh:49
float autocvar_sv_airaccelerate
Definition player.qh:34
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition player.qh:161
float autocvar_sv_accelerate
Definition player.qh:32
#define PHYS_JUMPVELOCITY(s)
Definition player.qh:133
#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s)
Definition player.qh:146
vector v_angle
Definition player.qh:236
float autocvar_sv_maxspeed
Definition player.qh:53
float autocvar_sv_warsowbunny_accel
Definition player.qh:29
#define PHYS_INPUT_BUTTON_JETPACK(s)
Definition player.qh:164
#define WAS_ONGROUND(s)
Definition player.qh:209
float teleport_time
Definition player.qh:218
bool autocvar_sv_jumpspeedcap_max_disable_on_ramps
Definition player.qh:48
float autocvar_sv_airaccel_qw_stretchfactor
Definition player.qh:18
#define WAS_ONSLICK(s)
Definition player.qh:210
#define PHYS_JETPACK_ACCEL_SIDE(s)
Definition player.qh:122
#define PHYS_INVEHICLE(s)
Definition player.qh:279
float autocvar_sv_airstopaccelerate
Definition player.qh:36
float waterlevel
Definition player.qh:225
#define PHYS_TRACK_CANJUMP(s)
Definition player.qh:142
#define ITEMS_STAT(s)
Definition player.qh:216
#define PHYS_MAXAIRSPEED(s)
Definition player.qh:136
float autocvar_sv_aircontrol_penalty
Definition player.qh:26
float autocvar_sv_warsowbunny_topspeed
Definition player.qh:28
bool wasFlying
Definition player.qh:65
bool autocvar_g_physics_clientselect
Definition player.qh:42
float autocvar_sv_airspeedlimit_nonqw
Definition player.qh:17
#define PHYS_JUMPVELOCITY_CROUCH(s)
Definition player.qh:134
#define IS_JUMP_HELD(s)
Definition player.qh:205
#define PHYS_FROZEN(s)
Definition player.qh:118
vector autocvar_sv_player_crouch_maxs
Definition player.qh:338
bool autocvar_speedmeter
Definition player.qh:46
#define PHYS_JETPACK_ACCEL_UP(s)
Definition player.qh:123
float autocvar_sv_maxairstrafespeed
Definition player.qh:19
bool autocvar_sv_airstopaccelerate_full
Definition player.qh:37
#define IS_DUCKED(s)
Definition player.qh:212
int autocvar_sv_aircontrol_flags
Definition player.qh:24
float autocvar_sv_aircontrol_power
Definition player.qh:25
float lastground
Definition player.qh:64
#define PHYS_INPUT_BUTTON_MINIGAME(s)
Definition player.qh:166
float autocvar_sv_slickaccelerate
Definition player.qh:35
float autocvar_sv_warsowbunny_backtosideratio
Definition player.qh:30
#define PHYS_JETPACK_ANTIGRAVITY(s)
Definition player.qh:124
float autocvar_sv_airstrafeaccelerate
Definition player.qh:20
#define UNSET_JUMP_HELD(s)
Definition player.qh:207
#define PHYS_MAXSPEED(s)
Definition player.qh:138
vector autocvar_sv_player_mins
Definition player.qh:336
#define IS_PLAYER(s)
Definition player.qh:242
#define PHYS_AMMO_FUEL(s)
Definition player.qh:110
#define PHYS_HIGHSPEED(s)
Definition player.qh:120
#define SET_DUCKED(s)
Definition player.qh:213
string autocvar_g_physics_clientselect_default
Definition player.qh:40
float autocvar_sv_track_canjump
Definition player.qh:38
float autocvar_sv_airaccel_qw
Definition player.qh:15
#define PHYS_AIRCONTROL_FLAGS(s)
Definition player.qh:101
float autocvar_sv_maxairspeed
Definition player.qh:52
float autocvar_sv_jumpspeedcap_max
Definition player.qh:47
float autocvar_g_movement_highspeed
Definition player.qh:44
#define PHYS_DODGING_FROZEN(s)
Definition player.qh:112
float autocvar_sv_airaccel_sideways_friction
Definition player.qh:22
#define PHYS_WARSOWBUNNY_TURNACCEL(s)
Definition player.qh:148
float autocvar_sv_jumpvelocity_crouch
Definition player.qh:51
#define PHYS_FRICTION_ONLAND(s)
Definition player.qh:115
bool autocvar_g_movement_highspeed_q3_compat
Definition player.qh:45
#define PHYS_AIRCONTROL_POWER(s)
Definition player.qh:103
#define SET_JUMP_HELD(s)
Definition player.qh:206
float autocvar_sv_aircontrol
Definition player.qh:23
float autocvar_sv_stopspeed
Definition player.qh:33
#define PHYS_AIRCONTROL(s)
Definition player.qh:100
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS(s)
Definition player.qh:130
#define PHYS_JETPACK_MAXSPEED_SIDE(s)
Definition player.qh:126
#define PHYS_JUMPSPEEDCAP_MIN(s)
Definition player.qh:131
#define autocvar_sv_gravity
Definition stats.qh:423
int autocvar_sv_gameplayfix_stepdown
Definition stats.qh:208
var float autocvar_sv_friction_slick
Definition stats.qh:239
float autocvar_sv_stepheight
Definition stats.qh:424
const int FL_WATERJUMP
Definition constants.qh:80
float flags
const float MOVE_NOMONSTERS
float RAD2DEG
float frametime
float Q3SURFACEFLAG_SLICK
const float MOVE_NORMAL
vector mins
vector velocity
float CVAR_TYPEFLAG_EXISTS
float time
float Q3SURFACEFLAG_METALSTEPS
vector v_right
float trace_startsolid
vector maxs
float trace_dphitq3surfaceflags
float intermission
vector v_forward
vector origin
float trace_fraction
float Q3SURFACEFLAG_NOSTEPS
vector trace_plane_normal
const int MF_ROCKET
int csqcmodel_modelflags
const int ACTIVE_ACTIVE
Definition defs.qh:37
bool autocvar_sv_doublejump
Definition doublejump.qh:4
float disableclientprediction
vector punchvector
#define strlen
float jumpheight_min
Definition extra.qh:4
float jumpheight_max
Definition extra.qh:4
#define GlobalSound(this, def, chan, vol, voicetype)
const int VOICETYPE_PLAYERSOUND
#define PlayerSound(this, def, chan, vol, voicetype, pitchscale)
best
Definition all.qh:82
entity last_pushed
Definition jumppads.qh:25
float jumppadcount
Definition jumppads.qh:28
entity ladder_entity
Definition ladder.qh:11
#define SV_PlayerPhysics
Definition _all.inc:262
#define REPLICATE(...)
Replicates a client cvar into a server field.
Definition replicate.qh:23
#define STAT(...)
Definition stats.qh:82
bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher, bool touchfunc)
Definition common.qc:815
#define LOG_INFO(...)
Definition log.qh:65
#define LOG_TRACE(...)
Definition log.qh:76
const int VIEWLOC_FREEMOVE
Definition viewloc.qh:6
vector movedir
Definition viewloc.qh:18
entity viewloc
Definition viewloc.qh:13
float remainder(float e, float f)
Definition mathlib.qc:213
float copysign(float e, float f)
Definition mathlib.qc:226
bool isnan(float e)
Definition mathlib.qc:25
float bound(float min, float value, float max)
string substring(string s, float start, float length)
float cvar(string name)
float random(void)
float vlen(vector v)
float sqrt(float f)
string vtos(vector v)
float min(float f,...)
vector normalize(vector v)
string ftos(float f)
float fabs(float f)
float max(float f,...)
bool _Movetype_CheckWater(entity this)
Definition movetypes.qc:334
const int WATERLEVEL_SWIMMING
Definition movetypes.qh:13
#define GAMEPLAYFIX_STEPDOWN(s)
Definition movetypes.qh:25
#define PHYS_GRAVITY(s)
Definition movetypes.qh:53
#define UNSET_ONSLICK(s)
Definition movetypes.qh:21
#define UNSET_ONGROUND(s)
Definition movetypes.qh:18
#define SET_ONSLICK(s)
Definition movetypes.qh:20
#define GAMEPLAYFIX_Q2AIRACCELERATE
Definition movetypes.qh:51
#define IS_ONGROUND(s)
Definition movetypes.qh:16
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
vector view_ofs
Definition progsdefs.qc:151
q3compat
Definition quake3.qc:59
bool autocvar_sv_q3compat_changehitbox
Definition quake3.qh:7
vector
Definition self.qh:92
vector vector ang
Definition self.qh:92
void PM_UpdateButtons(entity this, entity store)
Definition client.qc:3056
bool player_blocked
Definition client.qh:332
float pauseregen_finished
Definition client.qh:337
const float VOL_BASE
Definition sound.qh:36
const float VOL_MUFFLED
Definition sound.qh:38
const int CH_PLAYER
Definition sound.qh:20
#define CS_CVAR(this)
Definition state.qh:51
ClientState CS(Client this)
Definition state.qh:47
#define strhasword(s, w)
Definition string.qh:370
float autocvar_g_balance_pause_fuel_regen
entity swampslug
Definition swamp.qh:7
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
#define vec2(...)
Definition vector.qh:90
entity viewmodels[MAX_WEAPONSLOTS]
Definition view.qh:108
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
bool autocvar_sv_mapformat_is_quake3
Definition world.qh:32
bool autocvar_sv_mapformat_is_quake2
Definition world.qh:33