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 && 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 // old stats
111 // fix some new settings
112 STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor", autocvar_sv_airaccel_qw_stretchfactor);
113 STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed", autocvar_sv_maxairstrafespeed);
115 STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed) * maxspd_mod;
116 else
117 STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed);
118
119 STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate", autocvar_sv_airstrafeaccelerate);
120 STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel", autocvar_sv_warsowbunny_turnaccel);
121 STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction", autocvar_sv_airaccel_sideways_friction);
122 STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol", autocvar_sv_aircontrol);
123 STAT(MOVEVARS_AIRCONTROL_FLAGS, this) = Physics_ClientOption(this, "aircontrol_flags", autocvar_sv_aircontrol_flags);
124 STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power", autocvar_sv_aircontrol_power);
125 STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty", autocvar_sv_aircontrol_penalty);
126 STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel", autocvar_sv_warsowbunny_airforwardaccel);
127 STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed", autocvar_sv_warsowbunny_topspeed);
128 STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel", autocvar_sv_warsowbunny_accel);
129 STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio", autocvar_sv_warsowbunny_backtosideratio);
130 STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction", autocvar_sv_friction);
131 STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate", autocvar_sv_accelerate);
132 STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed", autocvar_sv_stopspeed);
133 STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate", autocvar_sv_airaccelerate);
134 STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate", autocvar_sv_airstopaccelerate);
135 STAT(MOVEVARS_AIRSTOPACCELERATE_FULL, this) = Physics_ClientOption(this, "airstopaccelerate_full", autocvar_sv_airstopaccelerate_full);
136 STAT(MOVEVARS_SLICKACCELERATE, this) = Physics_ClientOption(this, "slickaccelerate", autocvar_sv_slickaccelerate);
137 STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity", autocvar_sv_jumpvelocity);
138 STAT(MOVEVARS_JUMPVELOCITY_CROUCH, this) = Physics_ClientOption(this, "jumpvelocity_crouch", autocvar_sv_jumpvelocity_crouch);
139 STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump", autocvar_sv_track_canjump);
140
141 MUTATOR_CALLHOOK(PlayerPhysics_PostUpdateStats, this, maxspd_mod);
142}
143#endif
144
145float IsMoveInDirection(vector mv, float ang) // key mix factor
146{
147 if (mv_x == 0 && mv_y == 0)
148 return 0; // avoid division by zero
149 ang -= RAD2DEG * atan2(mv_y, mv_x);
150 ang = remainder(ang, 360) / 45;
151 return ang > 1 ? 0 : ang < -1 ? 0 : 1 - fabs(ang);
152}
153
154float GeomLerp(float a, float _lerp, float b)
155{
156 return a == 0 ? (_lerp < 1 ? 0 : b)
157 : b == 0 ? (_lerp > 0 ? 0 : a)
158 : a * (fabs(b / a) ** _lerp);
159}
160
162{
163 if(!IS_PLAYER(this))
164 return;
165
166 bool have_hook = false;
167 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
168 {
169 #if defined(CSQC)
170 entity wepent = viewmodels[slot];
171 #elif defined(SVQC)
172 .entity weaponentity = weaponentities[slot];
173 entity wepent = this.(weaponentity);
174 #endif
175 if(wepent.hook && !wasfreed(wepent.hook))
176 {
177 have_hook = true;
178 break;
179 }
180 }
181
182 bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
183 if(this.viewloc && !(this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && PHYS_CS(this).movement.x < 0)
184 do_crouch = true;
185 if (have_hook)
186 do_crouch = false;
187// else if (this.waterlevel >= WATERLEVEL_SWIMMING)
188// do_crouch = false;
189 else if (PHYS_INVEHICLE(this))
190 do_crouch = false;
191 else if (PHYS_FROZEN(this) || IS_DEAD(this))
192 do_crouch = false;
193
194 MUTATOR_CALLHOOK(PlayerCanCrouch, this, do_crouch);
195 do_crouch = M_ARGV(1, bool);
196
197 // Disable crouching on Q1BSP because it lacks a suitable cliphull (HLBSP added one).
198 if (STAT(PL_CROUCH_MAX, this).z == STAT(PL_MAX, this).z)
199 do_crouch = false;
200
201 if (do_crouch)
202 {
203 if (!IS_DUCKED(this))
204 {
205 SET_DUCKED(this);
206 this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
207 setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
208 // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
209 }
210 }
211 else if (IS_DUCKED(this))
212 {
213 tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, MOVE_NORMAL, this);
214 if (!trace_startsolid)
215 {
216 UNSET_DUCKED(this);
217 this.view_ofs = STAT(PL_VIEW_OFS, this);
218 setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
219 }
220 }
221
222 _Movetype_CheckWater(this); // needs to be run on the client, might as well use the latest on the server too!
223}
224
225void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
226{
227 float movity = IsMoveInDirection(PHYS_CS(this).movement, 0);
228 if(PHYS_AIRCONTROL_FLAGS(this) & BIT(0)) // backwards
229 movity += IsMoveInDirection(PHYS_CS(this).movement, 180);
230 if(PHYS_AIRCONTROL_FLAGS(this) & BIT(1)) // sidewards
231 {
232 movity += IsMoveInDirection(PHYS_CS(this).movement, 90);
233 movity += IsMoveInDirection(PHYS_CS(this).movement, -90);
234 }
235
236 float k = 2 * movity - 1;
237 if (k <= 0)
238 return;
239 if (!(PHYS_AIRCONTROL_FLAGS(this) & BIT(2))) // crouching has an impact
240 k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(this), 1);
241
242 const float zspeed = this.velocity_z;
243 this.velocity_z = 0;
244 float xyspeed = vlen(this.velocity);
245 this.velocity = normalize(this.velocity);
246
247 float dot = this.velocity * wishdir;
248
249 if (dot > 0) // we can't change direction while slowing down
250 {
251 k *= (dot ** PHYS_AIRCONTROL_POWER(this)) * dt;
252 xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k);
253 k *= 32 * fabs(PHYS_AIRCONTROL(this));
254 this.velocity = normalize(this.velocity * xyspeed + wishdir * k);
255 }
256
257 this.velocity = this.velocity * xyspeed;
258 this.velocity_z = zspeed;
259}
260
261float AdjustAirAccelQW(float accelqw, float factor)
262{
263 return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
264}
265
266// example config for alternate speed clamping:
267// sv_airaccel_qw 0.8
268// sv_airaccel_sideways_friction 0
269// prvm_globalset server speedclamp_mode 1
270// (or 2)
271void PM_Accelerate(entity this, float dt, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
272{
273 float speedclamp = stretchfactor > 0 ? stretchfactor
274 : accelqw < 0 ? 1 // full clamping, no stretch
275 : -1; // no clamping
276
277 accelqw = fabs(accelqw);
278
280 wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
281
282 float vel_straight = this.velocity * wishdir;
283 float vel_z = this.velocity_z;
284 vector vel_xy = vec2(this.velocity);
285 vector vel_perpend = vel_xy - vel_straight * wishdir;
286
287 float step = accel * dt * wishspeed0;
288
289 float vel_xy_current = vlen(vel_xy);
290 if (speedlimit)
291 accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
292 float vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
293 float vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
294 vel_xy_backward = max(0, vel_xy_backward); // not that it REALLY occurs that this would cause wrong behaviour afterwards
295 vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
296
297 if (sidefric < 0 && (vel_perpend*vel_perpend))
298 // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
299 {
300 float f = max(0, 1 + dt * wishspeed * sidefric);
301 float themin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
302 // assume: themin > 1
303 // vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
304 // vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
305 // vel_xy_backward*vel_xy_backward > vel_xy * vel_xy
306 // obviously, this cannot be
307 if (themin <= 0)
308 vel_perpend *= f;
309 else
310 {
311 themin = sqrt(themin);
312 vel_perpend *= max(themin, f);
313 }
314 }
315 else
316 vel_perpend *= max(0, 1 - dt * wishspeed * sidefric);
317
318 vel_xy = vel_straight * wishdir + vel_perpend;
319
320 if (speedclamp >= 0)
321 {
322 float vel_xy_preclamp;
323 vel_xy_preclamp = vlen(vel_xy);
324 if (vel_xy_preclamp > 0) // prevent division by zero
325 {
326 vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
327 if (vel_xy_current < vel_xy_preclamp)
328 vel_xy *= (vel_xy_current / vel_xy_preclamp);
329 }
330 }
331
332 this.velocity = vel_xy + vel_z * '0 0 1';
333}
334
335void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
336{
337 if (wishspeed == 0)
338 return;
339
340 vector curvel = this.velocity;
341 curvel_z = 0;
342 float curspeed = vlen(curvel);
343
344 if (wishspeed > curspeed * 1.01)
345 wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL(this) * PHYS_MAXSPEED(this) * dt);
346 else
347 {
348 float f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED(this) - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED(this) - PHYS_MAXSPEED(this)));
349 wishspeed = max(curspeed, PHYS_MAXSPEED(this)) + PHYS_WARSOWBUNNY_ACCEL(this) * f * PHYS_MAXSPEED(this) * dt;
350 }
351 vector wishvel = wishdir * wishspeed;
352 vector acceldir = wishvel - curvel;
353 float addspeed = vlen(acceldir);
354 acceldir = normalize(acceldir);
355
356 float accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL(this) * PHYS_MAXSPEED(this) * dt);
357
359 {
360 vector curdir = normalize(curvel);
361 float dot = acceldir * curdir;
362 if (dot < 0)
363 acceldir -= (1 - PHYS_WARSOWBUNNY_BACKTOSIDERATIO(this)) * dot * curdir;
364 }
365
366 this.velocity += accelspeed * acceldir;
367}
368
369
370/*
371=============
372PlayerJump
373
374When you press the jump key
375returns true if handled
376=============
377*/
379{
380 if (PHYS_FROZEN(this))
381 return true; // no jumping in freezetag when frozen
382
384 return true; // no jumping while typing
385
386#ifdef SVQC
387 if (this.player_blocked)
388 return true; // no jumping while blocked
389#endif
390
391 bool doublejump = false;
392 float mjumpheight = ((PHYS_JUMPVELOCITY_CROUCH(this) && IS_DUCKED(this)) ? PHYS_JUMPVELOCITY_CROUCH(this) : PHYS_JUMPVELOCITY(this));
393 bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
394
395 if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump))
396 return true;
397
398 mjumpheight = M_ARGV(1, float);
399 doublejump = M_ARGV(2, bool);
400
402 {
403 if(this.viewloc)
404 {
405 doublejump = true;
406 mjumpheight *= 0.7;
407 track_jump = true;
408 }
409 else
410 {
411 this.velocity_z = PHYS_MAXSPEED(this) * 0.7;
412 return true;
413 }
414 }
415
416 if (!doublejump)
417 if (!IS_ONGROUND(this))
418 return IS_JUMP_HELD(this);
419
420 if(PHYS_TRACK_CANJUMP(this))
421 track_jump = true;
422
423 if (track_jump)
424 if (IS_JUMP_HELD(this))
425 return true;
426
427 // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
428 // velocity bounds. Final velocity is bound between (jumpheight *
429 // min + jumpheight) and (jumpheight * max + jumpheight);
430
431 if(PHYS_JUMPSPEEDCAP_MIN != "")
432 {
433 float minjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MIN);
434
435 if (this.velocity_z < minjumpspeed)
436 mjumpheight += minjumpspeed - this.velocity_z;
437 }
438
439 if(PHYS_JUMPSPEEDCAP_MAX != "")
440 {
441 // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
442 tracebox(this.origin + '0 0 0.01', this.mins, this.maxs, this.origin - '0 0 0.01', MOVE_NORMAL, this);
443
444 if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS(this)))
445 {
446 float maxjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MAX);
447
448 if (this.velocity_z > maxjumpspeed)
449 mjumpheight -= this.velocity_z - maxjumpspeed;
450 }
451 }
452
453 if (!WAS_ONGROUND(this) && !WAS_ONSLICK(this))
454 {
455#ifdef SVQC
457 LOG_TRACE("landing velocity: ", vtos(this.velocity), " (abs: ", ftos(vlen(this.velocity)), ")");
458#endif
459 if(this.lastground < time - 0.3)
460 {
461 float f = (1 - PHYS_FRICTION_ONLAND(this));
462 f = bound(0, f, 1);
463 this.velocity_x *= f;
464 this.velocity_y *= f;
465 }
466#ifdef SVQC
467 if(this.jumppadcount > 1)
468 LOG_TRACE(ftos(this.jumppadcount), "x jumppad combo");
469 this.jumppadcount = 0;
470#endif
471 }
472
473 this.velocity_z += mjumpheight;
474
475 UNSET_ONGROUND(this);
476 UNSET_ONSLICK(this);
477 SET_JUMP_HELD(this);
478
479#ifdef CSQC
481#endif
482
483#ifdef SVQC
485
487 PlayerSound(this, playersound_jump, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
488#endif
489 return true;
490}
491
493{
494// check for a jump-out-of-water
495 makevectors(this.v_angle);
496 vector start = this.origin;
497 start_z += 8;
498 v_forward_z = 0;
500 vector end = start + v_forward*24;
501 traceline (start, end, true, this);
502 if (trace_fraction < 1)
503 { // solid at waist
504 start_z = start_z + this.maxs_z - 8;
505 end = start + v_forward*24;
506 this.movedir = trace_plane_normal * -50;
507 traceline(start, end, true, this);
508 if (trace_fraction == 1)
509 { // open at eye level
510 this.velocity_z = 225;
511 this.flags |= FL_WATERJUMP;
512 this.teleport_time = time + 2; // safety net
513 SET_JUMP_HELD(this);
514 }
515 }
516}
517
518
519#ifdef SVQC
520 #define JETPACK_JUMP(s) CS_CVAR(s).cvar_cl_jetpack_jump
521#elif defined(CSQC)
522 float autocvar_cl_jetpack_jump;
523 #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump
524#endif
527{
528#ifdef SVQC
529 bool was_flying = boolean(ITEMS_STAT(this) & IT_USING_JETPACK);
530#endif
531 if (JETPACK_JUMP(this) < 2)
533
535 {
536 bool playerjump = PlayerJump(this); // required
537
538 bool air_jump = !playerjump || M_ARGV(2, bool);
539 bool activate = (JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this)) || PHYS_INPUT_BUTTON_JETPACK(this);
540 bool has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || (ITEMS_STAT(this) & IT_UNLIMITED_AMMO);
541
542 if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
543 else if (this.jetpack_stopped) { }
544 else if (!has_fuel)
545 {
546#ifdef SVQC
547 if (was_flying) // TODO: ran out of fuel message
548 Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
549 else if (activate)
550 Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_JETPACK_NOFUEL);
551#endif
552 this.jetpack_stopped = true;
554 }
555 else if (activate && !PHYS_FROZEN(this))
557 }
558 else
559 {
560 this.jetpack_stopped = false;
562 }
563
564 if (!PHYS_INPUT_BUTTON_JUMP(this))
565 UNSET_JUMP_HELD(this);
566
568 CheckWaterJump(this);
569}
570
571#ifdef SVQC
572string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
575{
576 if(autocvar_sv_cheats || this.maycheat)
577 {
578 if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse))
579 LOG_INFO("A hollow voice says \"Plugh\".");
580 }
581}
582#endif
583
584bool PM_check_specialcommand(entity this, int buttons)
585{
586#ifdef SVQC
587 string c;
588 switch (buttons)
589 {
590 // buttons mapped in PHYS_INPUT_BUTTON_MASK
591 case 0: c = "x"; break;
592 case BIT(0): c = "1"; break;
593 case BIT(2): c = " "; break;
594 case BIT(7): c = "s"; break;
595 case BIT(8): c = "w"; break;
596 case BIT(9): c = "a"; break;
597 case BIT(10): c = "d"; break;
598 default: c = "?";
599 }
600
601 if (c == substring(specialcommand, CS(this).specialcommand_pos, 1))
602 {
603 CS(this).specialcommand_pos += 1;
605 {
606 CS(this).specialcommand_pos = 0;
607 SpecialCommand(this);
608 return true;
609 }
610 }
611 else if (CS(this).specialcommand_pos && (c != substring(specialcommand, CS(this).specialcommand_pos - 1, 1)))
612 CS(this).specialcommand_pos = 0;
613#endif
614 return false;
615}
616
617void PM_check_punch(entity this, float dt)
618{
619#ifdef SVQC
620 if (this.punchangle != '0 0 0')
621 {
622 float f = vlen(this.punchangle) - 10 * dt;
623 if (f > 0)
624 this.punchangle = normalize(this.punchangle) * f;
625 else
626 this.punchangle = '0 0 0';
627 }
628
629 if (this.punchvector != '0 0 0')
630 {
631 float f = vlen(this.punchvector) - 30 * dt;
632 if (f > 0)
633 this.punchvector = normalize(this.punchvector) * f;
634 else
635 this.punchvector = '0 0 0';
636 }
637#endif
638}
639
640// predict frozen movement, as frozen players CAN move in some cases
642{
643 if (!PHYS_FROZEN(this))
644 return;
645 if (PHYS_DODGING_FROZEN(this) && IS_CLIENT(this))
646 {
647 // bind movement to a very slow speed so dodging can use .movement for directional calculations
648 PHYS_CS(this).movement_x = bound(-2, PHYS_CS(this).movement.x, 2);
649 PHYS_CS(this).movement_y = bound(-2, PHYS_CS(this).movement.y, 2);
650 PHYS_CS(this).movement_z = bound(-2, PHYS_CS(this).movement.z, 2);
651 }
652 else
653 PHYS_CS(this).movement = '0 0 0';
654}
655
657{
658#ifdef SVQC
659 if (!this.wasFlying) return;
660 this.wasFlying = false;
661 if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
662 if (this.ladder_entity) return;
663 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
664 {
665 .entity weaponentity = weaponentities[slot];
666 if(this.(weaponentity).hook)
667 return;
668 }
669 this.nextstep = time + 0.3 + random() * 0.1;
671 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
674 ? GS_FALL_METAL
675 : GS_FALL;
676 float vol = ((IS_DUCKED(this)) ? VOL_MUFFLED : VOL_BASE);
678#endif
679}
680
682{
683#ifdef SVQC
684 if (!autocvar_g_footsteps) return;
685 if (IS_DUCKED(this)) return;
686 if (time >= this.lastground + 0.2) return;
687 if (vdist(this.velocity, <=, autocvar_sv_maxspeed * 0.6)) return;
688 if ((time > this.nextstep) || (time < (this.nextstep - 10.0)))
689 {
690 this.nextstep = time + 0.3 + random() * 0.1;
692 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
695 ? GS_STEP_METAL
696 : GS_STEP;
698 }
699#endif
700}
701
703{
704 if(!IS_ONGROUND(this))
705 return;
706
708 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
710 SET_ONSLICK(this);
711 else
712 UNSET_ONSLICK(this);
713}
714
716{
718 PHYS_CS(this).movement = '0 0 0';
719#ifdef SVQC
720 if (!this.player_blocked)
721 return;
722 PHYS_CS(this).movement = '0 0 0';
724#endif
725}
726
727void PM_jetpack(entity this, float maxspd_mod, float dt)
728{
729 //makevectors(this.v_angle.y * '0 1 0');
730 makevectors(this.v_angle);
731 vector wishvel = v_forward * PHYS_CS(this).movement_x
732 + v_right * PHYS_CS(this).movement_y;
733 // add remaining speed as Z component
734 float maxairspd = PHYS_MAXAIRSPEED(this) * max(1, maxspd_mod);
735 // fix speedhacks :P
736 wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd);
737 // add the unused velocity as up component
738 wishvel_z = 0;
739
740 // if (PHYS_INPUT_BUTTON_JUMP(this))
741 wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
742
743 // it is now normalized, so...
744 float a_side = PHYS_JETPACK_ACCEL_SIDE(this);
745 float a_up = PHYS_JETPACK_ACCEL_UP(this);
746 float a_add = PHYS_JETPACK_ANTIGRAVITY(this) * PHYS_GRAVITY(this);
747
749
750 wishvel_x *= a_side;
751 wishvel_y *= a_side;
752 wishvel_z *= a_up;
753 wishvel_z += a_add;
754
755 if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { wishvel_z *= -1; }
756
757 float best = 0;
759 // finding the maximum over all vectors of above form
760 // with wishvel having an absolute value of 1
762 // we're finding the maximum over
763 // f(a_side, a_up, a_add, z) := a_side * (1 - z^2) + (a_add + a_up * z)^2;
764 // for z in the range from -1 to 1
766 // maximum is EITHER attained at the single extreme point:
767 float a_diff = a_side * a_side - a_up * a_up;
768 float f;
769 if (a_diff != 0)
770 {
771 f = a_add * a_up / a_diff; // this is the zero of diff(f(a_side, a_up, a_add, z), z)
772 if (f > -1 && f < 1) // can it be attained?
773 {
774 best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
775 //print("middle\n");
776 }
777 }
778 // OR attained at z = 1:
779 f = (a_up + a_add) * (a_up + a_add);
780 if (f > best)
781 {
782 best = f;
783 //print("top\n");
784 }
785 // OR attained at z = -1:
786 f = (a_up - a_add) * (a_up - a_add);
787 if (f > best)
788 {
789 best = f;
790 //print("bottom\n");
791 }
792 best = sqrt(best);
794
795 //print("best possible acceleration: ", ftos(best), "\n");
796
797 float fxy, fz;
798 fxy = bound(0, 1 - (this.velocity * normalize(wishvel_x * '1 0 0' + wishvel_y * '0 1 0')) / PHYS_JETPACK_MAXSPEED_SIDE(this), 1);
799 if (wishvel_z - PHYS_GRAVITY(this) > 0)
800 fz = bound(0, 1 - this.velocity_z / PHYS_JETPACK_MAXSPEED_UP(this), 1);
801 else
802 fz = bound(0, 1 + this.velocity_z / PHYS_JETPACK_MAXSPEED_UP(this), 1);
803
804 float fvel;
805 fvel = vlen(wishvel);
806 wishvel_x *= fxy;
807 wishvel_y *= fxy;
808 wishvel_z = (wishvel_z - PHYS_GRAVITY(this)) * fz + PHYS_GRAVITY(this);
809
810 fvel = min(1, vlen(wishvel) / best);
811 if (PHYS_JETPACK_FUEL(this) && !(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
812 f = min(1, PHYS_AMMO_FUEL(this) / (PHYS_JETPACK_FUEL(this) * dt * fvel));
813 else
814 f = 1;
815
816 //print("this acceleration: ", ftos(vlen(wishvel) * f), "\n");
817
818 if (f > 0 && wishvel != '0 0 0')
819 {
820 this.velocity = this.velocity + wishvel * f * dt;
821 UNSET_ONGROUND(this);
822
823#ifdef SVQC
824 if (!(ITEMS_STAT(this) & IT_UNLIMITED_AMMO))
825 TakeResource(this, RES_FUEL, PHYS_JETPACK_FUEL(this) * dt * fvel * f);
826
828
829 // jetpack also inhibits health regeneration, but only for 1 second
831#endif
832 }
833}
834
835// used for calculating airshots
836bool IsFlying(entity this)
837{
838 if(IS_ONGROUND(this))
839 return false;
841 return false;
842 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 24', MOVE_NORMAL, this);
843 //traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
844 if(trace_fraction < 1)
845 return false;
846 return true;
847}
848
849
850void sys_phys_update(entity this, float dt);
851#if defined(SVQC)
853#elif defined(CSQC)
855#endif
856{
857#ifdef SVQC
858 // needs to be called before physics are run!
859 if(IS_REAL_CLIENT(this))
860 PM_UpdateButtons(this, CS(this));
861#elif defined(CSQC)
862 if(this.last_pushed && !WarpZoneLib_ExactTrigger_Touch(this.last_pushed, this, false))
863 this.last_pushed = NULL;
864#endif
865
867
868#ifdef SVQC
869 CS(this).pm_frametime = frametime;
870#elif defined(CSQC)
871 if((ITEMS_STAT(this) & IT_USING_JETPACK) && !IS_DEAD(this) && !intermission)
873 else
875#endif
876}
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:656
void PM_jetpack(entity this, float maxspd_mod, float dt)
Definition player.qc:727
void PM_check_blocked(entity this)
Definition player.qc:715
float Physics_ClientOption(entity this, string option, float defaultval)
Definition player.qc:23
void PM_check_frozen(entity this)
Definition player.qc:641
void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
Definition player.qc:225
float jetpack_stopped
Definition player.qc:525
void CheckPlayerJump(entity this)
Definition player.qc:526
void sys_phys_update(entity this, float dt)
Definition physics.qc:10
void PM_ClientMovement_UpdateStatus(entity this)
Definition player.qc:161
float specialcommand_pos
Definition player.qc:573
bool Physics_Valid(string thecvar)
Definition player.qc:18
float GeomLerp(float a, float _lerp, float b)
Definition player.qc:154
void PM_check_punch(entity this, float dt)
Definition player.qc:617
void Physics_UpdateStats(entity this)
Definition player.qc:44
bool PM_check_specialcommand(entity this, int buttons)
Definition player.qc:584
void PM_check_slick(entity this)
Definition player.qc:702
bool PlayerJump(entity this)
Definition player.qc:378
float AdjustAirAccelQW(float accelqw, float factor)
Definition player.qc:261
void SpecialCommand(entity this)
Definition player.qc:574
void CheckWaterJump(entity this)
Definition player.qc:492
string specialcommand
Definition player.qc:572
float IsMoveInDirection(vector mv, float ang)
Definition player.qc:145
bool IsFlying(entity this)
Definition player.qc:836
#define JETPACK_JUMP(s)
Definition player.qc:520
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:271
void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
Definition player.qc:335
void PM_Footsteps(entity this)
Definition player.qc:681
#define PHYS_CL_TRACK_CANJUMP(s)
Definition player.qh:285
vector autocvar_sv_player_crouch_viewoffset
Definition player.qh:351
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:154
bool autocvar_g_footsteps
Definition player.qh:54
#define PHYS_JETPACK_FUEL(s)
Definition player.qh:125
entity hook
Definition player.qh:239
vector autocvar_sv_player_viewoffset
Definition player.qh:348
#define PHYS_WARSOWBUNNY_ACCEL(s)
Definition player.qh:142
bool autocvar_g_jump_grunt
Definition player.qh:41
float autocvar_sv_jumpvelocity
Definition player.qh:50
#define PHYS_INPUT_TIMELENGTH
Definition player.qh:254
vector movement
Definition player.qh:229
vector autocvar_sv_player_crouch_mins
Definition player.qh:350
vector autocvar_sv_player_maxs
Definition player.qh:346
#define PHYS_JETPACK_MAXSPEED_UP(s)
Definition player.qh:127
float autocvar_sv_warsowbunny_turnaccel
Definition player.qh:21
float autocvar_sv_friction
Definition player.qh:31
#define PHYS_CS(s)
Definition player.qh:258
#define IS_CLIENT(s)
Definition player.qh:242
#define IS_DEAD(s)
Definition player.qh:245
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:145
#define UNSET_DUCKED(s)
Definition player.qh:212
#define PHYS_INPUT_BUTTON_JUMP(s)
Definition player.qh:151
#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s)
Definition player.qh:143
#define PHYS_AIRCONTROL_PENALTY(s)
Definition player.qh:102
float autocvar_sv_airaccelerate
Definition player.qh:34
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition player.qh:159
float autocvar_sv_accelerate
Definition player.qh:32
#define PHYS_JUMPVELOCITY(s)
Definition player.qh:131
#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s)
Definition player.qh:144
#define PHYS_JUMPSPEEDCAP_MIN
Definition player.qh:282
vector v_angle
Definition player.qh:237
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:162
#define WAS_ONGROUND(s)
Definition player.qh:207
float teleport_time
Definition player.qh:216
float autocvar_sv_airaccel_qw_stretchfactor
Definition player.qh:18
#define WAS_ONSLICK(s)
Definition player.qh:208
#define PHYS_JETPACK_ACCEL_SIDE(s)
Definition player.qh:122
#define PHYS_INVEHICLE(s)
Definition player.qh:280
float autocvar_sv_airstopaccelerate
Definition player.qh:36
float waterlevel
Definition player.qh:226
#define PHYS_TRACK_CANJUMP(s)
Definition player.qh:140
#define ITEMS_STAT(s)
Definition player.qh:214
#define PHYS_MAXAIRSPEED(s)
Definition player.qh:134
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:132
#define IS_JUMP_HELD(s)
Definition player.qh:203
#define PHYS_FROZEN(s)
Definition player.qh:118
#define PHYS_JUMPSPEEDCAP_MAX
Definition player.qh:283
vector autocvar_sv_player_crouch_maxs
Definition player.qh:349
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:210
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:164
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:205
#define PHYS_MAXSPEED(s)
Definition player.qh:136
vector autocvar_sv_player_mins
Definition player.qh:347
#define IS_PLAYER(s)
Definition player.qh:243
#define PHYS_AMMO_FUEL(s)
Definition player.qh:110
#define PHYS_HIGHSPEED(s)
Definition player.qh:120
#define SET_DUCKED(s)
Definition player.qh:211
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_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:146
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:204
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
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
float disableclientprediction
vector punchvector
#define strlen
float jumpheight_min
Definition extra.qh:4
float jumpheight_max
Definition extra.qh:4
#define PlayerSound(this, def, chan, vol, voicetype)
#define GlobalSound(this, def, chan, vol, voicetype)
const int VOICETYPE_PLAYERSOUND
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:212
float copysign(float e, float f)
Definition mathlib.qc:225
float stof(string val,...)
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 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:3058
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