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 *= 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 = vlen(vel_xy);
332 if (vel_xy_preclamp > 0) // prevent division by zero
333 {
334 vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
335 if (vel_xy_current < vel_xy_preclamp)
336 vel_xy *= (vel_xy_current / vel_xy_preclamp);
337 }
338 }
339
340 this.velocity = vel_xy + vel_z * '0 0 1';
341}
342
343void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
344{
345 if (wishspeed == 0)
346 return;
347
348 vector curvel = this.velocity;
349 curvel_z = 0;
350 float curspeed = vlen(curvel);
351
352 if (wishspeed > curspeed * 1.01)
353 wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * dt);
354 else
355 {
356 float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED(this) - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED(this) - PHYS_MAXSPEED(this)));
357 wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * dt;
358 }
359 vector wishvel = wishdir * wishspeed;
360 vector acceldir = wishvel - curvel;
361 float addspeed = vlen(acceldir);
362 acceldir = normalize(acceldir);
363
364 float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * dt);
365
367 {
368 vector curdir = normalize(curvel);
369 float dot = acceldir * curdir;
370 if (dot < 0)
371 acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this)) * dot * curdir;
372 }
373
374 this.velocity += accelspeed * acceldir;
375}
376
377
378/*
379=============
380PlayerJump
381
382When you press the jump key
383returns true if handled
384=============
385*/
387{
388 if (PHYS_FROZEN(this))
389 return true; // no jumping in freezetag when frozen
390
392 return true; // no jumping while typing
393
394#ifdef SVQC
395 if (this.player_blocked)
396 return true; // no jumping while blocked
397#endif
398
399 bool doublejump = false;
400 float mjumpheight = ((PHYS_JUMPVELOCITY_CROUCH(this) && IS_DUCKED(this)) ? PHYS_JUMPVELOCITY_CROUCH(this) : PHYS_JUMPVELOCITY(this));
401 bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
402
403 if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump))
404 return true;
405
406 mjumpheight = M_ARGV(1, float);
407 doublejump = M_ARGV(2, bool);
408
410 {
411 if(this.viewloc)
412 {
413 doublejump = true;
414 mjumpheight *= 0.7;
415 track_jump = true;
416 }
417 else
418 {
419 this.velocity_z = PHYS_MAXSPEED(this) * 0.7;
420 return true;
421 }
422 }
423
424 if (!doublejump)
425 if (!IS_ONGROUND(this))
426 return IS_JUMP_HELD(this);
427
428 if(PHYS_TRACK_CANJUMP(this))
429 track_jump = true;
430
431 if (track_jump)
432 if (IS_JUMP_HELD(this))
433 return true;
434
435 // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
436 // velocity bounds. Final velocity is bound between (jumpheight *
437 // min + jumpheight) and (jumpheight * max + jumpheight);
438
439 if (!isnan(PHYS_JUMPSPEEDCAP_MIN(this)))
440 {
441 float minjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MIN(this);
442
443 if (this.velocity_z < minjumpspeed)
444 mjumpheight += minjumpspeed - this.velocity_z;
445 }
446
447 if (!isnan(PHYS_JUMPSPEEDCAP_MAX(this)))
448 {
449 // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
450 tracebox(this.origin + '0 0 0.01', this.mins, this.maxs, this.origin - '0 0 0.01', MOVE_NORMAL, this);
451
452 if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS(this)))
453 {
454 float maxjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MAX(this);
455
456 if (this.velocity_z > maxjumpspeed)
457 mjumpheight -= this.velocity_z - maxjumpspeed;
458 }
459 }
460
461 if (!WAS_ONGROUND(this) && !WAS_ONSLICK(this))
462 {
463#ifdef SVQC
465 LOG_TRACE("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")");
466#endif
467 if(this.lastground < time - 0.3)
468 {
469 float f = (1 - PHYS_FRICTION_ONLAND(this));
470 f = bound(0, f, 1);
471 this.velocity_x *= f;
472 this.velocity_y *= f;
473 }
474#ifdef SVQC
475 if(this.jumppadcount > 1)
476 LOG_TRACE(ftos(this.jumppadcount), "x jumppad combo");
477 this.jumppadcount = 0;
478#endif
479 }
480
481 this.velocity_z += mjumpheight;
482
483 UNSET_ONGROUND(this);
484 UNSET_ONSLICK(this);
485 SET_JUMP_HELD(this);
486
487#ifdef CSQC
489#endif
490
491#ifdef SVQC
493
495 PlayerSound(this, playersound_jump, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND, 1);
496#endif
497 return true;
498}
499
501{
502// check for a jump-out-of-water
503 makevectors(this.v_angle);
504 vector start = this.origin;
505 start_z += 8;
506 v_forward_z = 0;
508 vector end = start + v_forward*24;
509 traceline (start, end, true, this);
510 if (trace_fraction < 1)
511 { // solid at waist
512 start_z = start_z + this.maxs_z - 8;
513 end = start + v_forward*24;
514 this.movedir = trace_plane_normal * -50;
515 traceline(start, end, true, this);
516 if (trace_fraction == 1)
517 { // open at eye level
518 this.velocity_z = 225;
519 this.flags |= FL_WATERJUMP;
520 this.teleport_time = time + 2; // safety net
521 SET_JUMP_HELD(this);
522 }
523 }
524}
525
526
527#ifdef SVQC
528 #define JETPACK_JUMP(s) CS_CVAR(s).cvar_cl_jetpack_jump
529#elif defined(CSQC)
530 float autocvar_cl_jetpack_jump;
531 #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
532#endif
535{
536#ifdef SVQC
537 bool was_flying = boolean(ITEMS_STAT(this) & IT_USING_JETPACK);
538#endif
539 if (JETPACK_JUMP(this) < 2)
541
543 {
544 bool playerjump = PlayerJump(this); // required
545
546 bool air_jump = !playerjump || M_ARGV(2, bool);
547 bool activate = (JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this)) || PHYS_INPUT_BUTTON_JETPACK(this);
548 bool has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || (ITEMS_STAT(this) & IT_UNLIMITED_AMMO);
549
550 if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
551 else if (this.jetpack_stopped) { }
552 else if (!has_fuel)
553 {
554#ifdef SVQC
555 if (was_flying) // TODO: ran out of fuel message
556 Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
557 else if (activate)
558 Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
559#endif
560 this.jetpack_stopped = true;
562 }
563 else if (activate && !PHYS_FROZEN(this))
565 }
566 else
567 {
568 this.jetpack_stopped = false;
570 }
571
572 if (!PHYS_INPUT_BUTTON_JUMP(this))
573 UNSET_JUMP_HELD(this);
574
576 CheckWaterJump(this);
577}
578
579#ifdef SVQC
580string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
583{
584 if(autocvar_sv_cheats || this.maycheat)
585 {
586 if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse))
587 LOG_INFO("A hollow voice says \"Plugh\".");
588 }
589}
590#endif
591
592bool PM_check_specialcommand(entity this, int buttons)
593{
594#ifdef SVQC
595 string c;
596 switch (buttons)
597 {
598 // buttons mapped in PHYS_INPUT_BUTTON_MASK
599 case 0: c = "x"; break;
600 case BIT(0): c = "1"; break;
601 case BIT(2): c = " "; break;
602 case BIT(7): c = "s"; break;
603 case BIT(8): c = "w"; break;
604 case BIT(9): c = "a"; break;
605 case BIT(10): c = "d"; break;
606 default: c = "?";
607 }
608
609 if (c == substring(specialcommand, CS(this).specialcommand_pos, 1))
610 {
611 ++CS(this).specialcommand_pos;
613 {
614 CS(this).specialcommand_pos = 0;
615 SpecialCommand(this);
616 return true;
617 }
618 }
619 else if (CS(this).specialcommand_pos && (c != substring(specialcommand, CS(this).specialcommand_pos - 1, 1)))
620 CS(this).specialcommand_pos = 0;
621#endif
622 return false;
623}
624
625void PM_check_punch(entity this, float dt)
626{
627#ifdef SVQC
628 if (this.punchangle != '0 0 0')
629 {
630 float f = vlen(this.punchangle) - 10 * dt;
631 if (f > 0)
632 this.punchangle = normalize(this.punchangle) * f;
633 else
634 this.punchangle = '0 0 0';
635 }
636
637 if (this.punchvector != '0 0 0')
638 {
639 float f = vlen(this.punchvector) - 30 * dt;
640 if (f > 0)
641 this.punchvector = normalize(this.punchvector) * f;
642 else
643 this.punchvector = '0 0 0';
644 }
645#endif
646}
647
648// predict frozen movement, as frozen players CAN move in some cases
650{
651 if (!PHYS_FROZEN(this))
652 return;
653 if (PHYS_DODGING_FROZEN(this) && IS_CLIENT(this))
654 {
655 // bind movement to a very slow speed so dodging can use .movement for directional calculations
656 PHYS_CS(this).movement_x = bound(-2, PHYS_CS(this).movement.x, 2);
657 PHYS_CS(this).movement_y = bound(-2, PHYS_CS(this).movement.y, 2);
658 PHYS_CS(this).movement_z = bound(-2, PHYS_CS(this).movement.z, 2);
659 }
660 else
661 PHYS_CS(this).movement = '0 0 0';
662}
663
665{
666#ifdef SVQC
667 if (!this.wasFlying) return;
668 this.wasFlying = false;
669 if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
670 if (this.ladder_entity) return;
671 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
672 {
673 .entity weaponentity = weaponentities[slot];
674 if(this.(weaponentity).hook)
675 return;
676 }
677 this.nextstep = time + 0.3 + random() * 0.1;
679 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
682 ? GS_FALL_METAL
683 : GS_FALL;
684 float vol = ((IS_DUCKED(this)) ? VOL_MUFFLED : VOL_BASE);
686#endif
687}
688
690{
691#ifdef SVQC
692 if (!autocvar_g_footsteps) return;
693 if (IS_DUCKED(this)) return;
694 if (time >= this.lastground + 0.2) return;
695 if (vdist(this.velocity, <=, autocvar_sv_maxspeed * 0.6)) return;
696 if ((time > this.nextstep) || (time < (this.nextstep - 10.0)))
697 {
698 this.nextstep = time + 0.3 + random() * 0.1;
700 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
703 ? GS_STEP_METAL
704 : GS_STEP;
706 }
707#endif
708}
709
711{
712 if(!IS_ONGROUND(this))
713 return;
714
716 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
718 SET_ONSLICK(this);
719 else
720 UNSET_ONSLICK(this);
721}
722
724{
726 PHYS_CS(this).movement = '0 0 0';
727#ifdef SVQC
728 if (!this.player_blocked)
729 return;
730 PHYS_CS(this).movement = '0 0 0';
732#endif
733}
734
735void PM_jetpack(entity this, float maxspd_mod, float dt)
736{
737 //makevectors(this.v_angle.y * '0 1 0');
738 makevectors(this.v_angle);
739 vector wishvel = v_forward * PHYS_CS(this).movement_x
740 + v_right * PHYS_CS(this).movement_y;
741 // add remaining speed as Z component
742 float maxairspd = PHYS_MAXAIRSPEED(this) * max(1, maxspd_mod);
743 // fix speedhacks :P
744 wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
745 // add the unused velocity as up component
746 wishvel_z = 0;
747
748 // if (PHYS_INPUT_BUTTON_JUMP(this))
749 wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
750
751 // it is now normalized, so...
752 float a_side = PHYS_JETPACK_ACCEL_SIDE(this);
753 float a_up = PHYS_JETPACK_ACCEL_UP(this);
754 float a_add = PHYS_JETPACK_ANTIGRAVITY(this) * PHYS_GRAVITY(this);
755
757
758 wishvel_x *= a_side;
759 wishvel_y *= a_side;
760 wishvel_z *= a_up;
761 wishvel_z += a_add;
762
763 if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { wishvel_z *= -1; }
764
765 float best = 0;
767 // finding the maximum over all vectors of above form
768 // with wishvel having an absolute value of 1
770 // we're finding the maximum over
771 // f(a_side, a_up, a_add, z) := a_side * (1 - z^2) + (a_add + a_up * z)^2;
772 // for z in the range from -1 to 1
774 // maximum is EITHER attained at the single extreme point:
775 float a_diff = a_side * a_side - a_up * a_up;
776 float f;
777 if (a_diff != 0)
778 {
779 f = a_add * a_up / a_diff; // this is the zero of diff(f(a_side, a_up, a_add, z), z)
780 if (f > -1 && f < 1) // can it be attained?
781 {
782 best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
783 //print("middle\n");
784 }
785 }
786 // OR attained at z = 1:
787 f = (a_up + a_add) * (a_up + a_add);
788 if (f > best)
789 {
790 best = f;
791 //print("top\n");
792 }
793 // OR attained at z = -1:
794 f = (a_up - a_add) * (a_up - a_add);
795 if (f > best)
796 {
797 best = f;
798 //print("bottom\n");
799 }
800 best = sqrt(best);
802
803 //print("best possible acceleration: ", ftos(best), "\n");
804
805 float fxy, fz;
806 fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE(this), 1);
807 if (wishvel_z - PHYS_GRAVITY(this) > 0)
808 fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP(this), 1);
809 else
810 fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP(this), 1);
811
812 float fvel = vlen(wishvel);
813 wishvel_x *= fxy;
814 wishvel_y *= fxy;
815 wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
816
817 fvel = min(1, vlen(wishvel) / best);
818 if (PHYS_JETPACK_FUEL(this) && !(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
819 f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL(this) * dt * fvel));
820 else
821 f = 1;
822
823 //print("this acceleration: ", ftos(vlen(wishvel) * f), "\n");
824
825 if (f > 0 && wishvel != '0 0 0')
826 {
827 this.velocity += wishvel * f * dt;
828 UNSET_ONGROUND(this);
829
830#ifdef SVQC
831 if (!(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
832 TakeResource(this, RES_FUEL, PHYS_JETPACK_FUEL(this) * dt * fvel * f);
833
835
836 // jetpack also inhibits health regeneration, but only for 1 second
838#endif
839 }
840}
841
842// used for calculating airshots
843bool IsFlying(entity this)
844{
845 if(IS_ONGROUND(this))
846 return false;
848 return false;
849 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 24', MOVE_NORMAL, this);
850 //traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
851 if(trace_fraction < 1)
852 return false;
853 return true;
854}
855
856
857void sys_phys_update(entity this, float dt);
858#if defined(SVQC)
859void SV_PlayerPhysics(entity this) // called by engine before it calls PlayerPreThink()
860#elif defined(CSQC)
862#endif
863{
864#ifdef SVQC
865 // needs to be called before physics are run!
866 if(IS_REAL_CLIENT(this))
867 PM_UpdateButtons(this, CS(this));
868#elif defined(CSQC)
869 if(this.last_pushed && !WarpZoneLib_ExactTrigger_Touch(this.last_pushed, this, false))
870 this.last_pushed = NULL;
871#endif
872
874
875#ifdef SVQC
876 CS(this).pm_frametime = frametime;
877#elif defined(CSQC)
878 if((ITEMS_STAT(this) & IT_USING_JETPACK) && !IS_DEAD(this) && !intermission)
880 else
882#endif
883}
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:137
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:664
void PM_jetpack(entity this, float maxspd_mod, float dt)
Definition player.qc:735
void PM_check_blocked(entity this)
Definition player.qc:723
float Physics_ClientOption(entity this, string option, float defaultval)
Definition player.qc:23
void PM_check_frozen(entity this)
Definition player.qc:649
void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
Definition player.qc:234
float jetpack_stopped
Definition player.qc:533
void CheckPlayerJump(entity this)
Definition player.qc:534
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:581
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:625
void Physics_UpdateStats(entity this)
Definition player.qc:44
bool PM_check_specialcommand(entity this, int buttons)
Definition player.qc:592
void PM_check_slick(entity this)
Definition player.qc:710
bool PlayerJump(entity this)
Definition player.qc:386
float AdjustAirAccelQW(float accelqw, float factor)
Definition player.qc:270
void SpecialCommand(entity this)
Definition player.qc:582
void CheckWaterJump(entity this)
Definition player.qc:500
string specialcommand
Definition player.qc:580
float IsMoveInDirection(vector mv, float ang)
Definition player.qc:154
bool IsFlying(entity this)
Definition player.qc:843
#define JETPACK_JUMP(s)
Definition player.qc:528
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:343
void PM_Footsteps(entity this)
Definition player.qc:689
#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:84
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:813
#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:211
float copysign(float e, float f)
Definition mathlib.qc:224
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:3060
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