7 REPLICATE(cvar_cl_physics,
string,
"cl_physics");
8 REPLICATE(cvar_cl_jetpack_jump,
bool,
"cl_jetpack_jump");
9 REPLICATE(cvar_cl_movement_track_canjump,
bool,
"cl_movement_track_canjump");
18 bool Physics_Valid(
string thecvar)
20 return thecvar !=
"" && thecvar && thecvar !=
"default" &&
strhasword(autocvar_g_physics_clientselect_options, thecvar);
23 float Physics_ClientOption(
entity this,
string option,
float defaultval)
25 if(!autocvar_g_physics_clientselect)
30 string s =
strcat(
"g_physics_",
CS_CVAR(
this).cvar_cl_physics,
"_", option);
34 if(autocvar_g_physics_clientselect_default && autocvar_g_physics_clientselect_default !=
"" && autocvar_g_physics_clientselect_default !=
"default")
37 string s =
strcat(
"g_physics_", autocvar_g_physics_clientselect_default,
"_", option);
44 void Physics_UpdateStats(
entity this)
47 STAT(MOVEVARS_HIGHSPEED,
this) = autocvar_g_movement_highspeed;
51 STAT(MOVEVARS_MAXSPEED,
this) = Physics_ClientOption(
this,
"maxspeed", autocvar_sv_maxspeed) * maxspd_mod;
52 if (autocvar_g_movement_highspeed_q3_compat) {
53 STAT(MOVEVARS_AIRACCEL_QW,
this) = Physics_ClientOption(
this,
"airaccel_qw", autocvar_sv_airaccel_qw);
54 STAT(MOVEVARS_AIRSTRAFEACCEL_QW,
this) = Physics_ClientOption(
this,
"airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw);
55 STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW,
this) = Physics_ClientOption(
this,
"airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw);
57 STAT(MOVEVARS_AIRACCEL_QW,
this) =
AdjustAirAccelQW(Physics_ClientOption(
this,
"airaccel_qw", autocvar_sv_airaccel_qw), maxspd_mod);
58 STAT(MOVEVARS_AIRSTRAFEACCEL_QW,
this) = (Physics_ClientOption(
this,
"airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw))
59 ?
AdjustAirAccelQW(Physics_ClientOption(
this,
"airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw), maxspd_mod)
61 STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW,
this) = Physics_ClientOption(
this,
"airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
64 STAT(PL_MIN,
this) = (q3hb) ?
'-15 -15 -20' : autocvar_sv_player_mins;
65 STAT(PL_MAX,
this) = (q3hb) ?
'15 15 36' : autocvar_sv_player_maxs;
66 STAT(PL_VIEW_OFS,
this) = (q3hb) ?
'0 0 30' : autocvar_sv_player_viewoffset;
67 STAT(PL_CROUCH_MIN,
this) = (q3hb) ?
'-15 -15 -20' : autocvar_sv_player_crouch_mins;
68 STAT(PL_CROUCH_MAX,
this) = (q3hb) ?
'15 15 20' : autocvar_sv_player_crouch_maxs;
69 STAT(PL_CROUCH_VIEW_OFS,
this) = (q3hb) ?
'0 0 16' : autocvar_sv_player_crouch_viewoffset;
73 STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR,
this) = Physics_ClientOption(
this,
"airaccel_qw_stretchfactor", autocvar_sv_airaccel_qw_stretchfactor);
74 STAT(MOVEVARS_MAXAIRSTRAFESPEED,
this) = Physics_ClientOption(
this,
"maxairstrafespeed", autocvar_sv_maxairstrafespeed);
75 if (autocvar_g_movement_highspeed_q3_compat) {
76 STAT(MOVEVARS_MAXAIRSPEED,
this) = Physics_ClientOption(
this,
"maxairspeed", autocvar_sv_maxairspeed) * maxspd_mod;
78 STAT(MOVEVARS_MAXAIRSPEED,
this) = Physics_ClientOption(
this,
"maxairspeed", autocvar_sv_maxairspeed);
81 STAT(MOVEVARS_AIRSTRAFEACCELERATE,
this) = Physics_ClientOption(
this,
"airstrafeaccelerate", autocvar_sv_airstrafeaccelerate);
82 STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL,
this) = Physics_ClientOption(
this,
"warsowbunny_turnaccel", autocvar_sv_warsowbunny_turnaccel);
83 STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION,
this) = Physics_ClientOption(
this,
"airaccel_sideways_friction", autocvar_sv_airaccel_sideways_friction);
84 STAT(MOVEVARS_AIRCONTROL,
this) = Physics_ClientOption(
this,
"aircontrol", autocvar_sv_aircontrol);
85 STAT(MOVEVARS_AIRCONTROL_POWER,
this) = Physics_ClientOption(
this,
"aircontrol_power", autocvar_sv_aircontrol_power);
86 STAT(MOVEVARS_AIRCONTROL_BACKWARDS,
this) = Physics_ClientOption(
this,
"aircontrol_backwards", autocvar_sv_aircontrol_backwards);
87 STAT(MOVEVARS_AIRCONTROL_SIDEWARDS,
this) = Physics_ClientOption(
this,
"aircontrol_sidewards", autocvar_sv_aircontrol_sidewards);
88 STAT(MOVEVARS_AIRCONTROL_PENALTY,
this) = Physics_ClientOption(
this,
"aircontrol_penalty", autocvar_sv_aircontrol_penalty);
89 STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL,
this) = Physics_ClientOption(
this,
"warsowbunny_airforwardaccel", autocvar_sv_warsowbunny_airforwardaccel);
90 STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED,
this) = Physics_ClientOption(
this,
"warsowbunny_topspeed", autocvar_sv_warsowbunny_topspeed);
91 STAT(MOVEVARS_WARSOWBUNNY_ACCEL,
this) = Physics_ClientOption(
this,
"warsowbunny_accel", autocvar_sv_warsowbunny_accel);
92 STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO,
this) = Physics_ClientOption(
this,
"warsowbunny_backtosideratio", autocvar_sv_warsowbunny_backtosideratio);
93 STAT(MOVEVARS_FRICTION,
this) = Physics_ClientOption(
this,
"friction", autocvar_sv_friction);
94 STAT(MOVEVARS_ACCELERATE,
this) = Physics_ClientOption(
this,
"accelerate", autocvar_sv_accelerate);
95 STAT(MOVEVARS_STOPSPEED,
this) = Physics_ClientOption(
this,
"stopspeed", autocvar_sv_stopspeed);
96 STAT(MOVEVARS_AIRACCELERATE,
this) = Physics_ClientOption(
this,
"airaccelerate", autocvar_sv_airaccelerate);
97 STAT(MOVEVARS_AIRSTOPACCELERATE,
this) = Physics_ClientOption(
this,
"airstopaccelerate", autocvar_sv_airstopaccelerate);
98 STAT(MOVEVARS_JUMPVELOCITY,
this) = Physics_ClientOption(
this,
"jumpvelocity", autocvar_sv_jumpvelocity);
99 STAT(MOVEVARS_JUMPVELOCITY_CROUCH,
this) = Physics_ClientOption(
this,
"jumpvelocity_crouch", autocvar_sv_jumpvelocity_crouch);
100 STAT(MOVEVARS_TRACK_CANJUMP,
this) = Physics_ClientOption(
this,
"track_canjump", autocvar_sv_track_canjump);
108 if (mv_x == 0 && mv_y == 0)
110 ang -=
RAD2DEG * atan2(mv_y, mv_x);
112 return ang > 1 ? 0 : ang < -1 ? 0 : 1 -
fabs(ang);
117 return a == 0 ? (_lerp < 1 ? 0 : b)
118 : b == 0 ? (_lerp > 0 ? 0 : a)
119 : a * (
fabs(b / a) ** _lerp);
127 bool have_hook =
false;
134 entity wepent = this.(weaponentity);
136 if(wepent.hook && !wasfreed(wepent.hook))
149 }
else if (PHYS_INVEHICLE(
this)) {
151 }
else if (STAT(FROZEN,
this) ||
IS_DEAD(
this)) {
156 do_crouch =
M_ARGV(1,
bool);
161 this.
view_ofs = STAT(PL_CROUCH_VIEW_OFS,
this);
162 setsize(
this, STAT(PL_CROUCH_MIN,
this), STAT(PL_CROUCH_MAX,
this));
166 tracebox(this.
origin, STAT(PL_MIN,
this), STAT(PL_MAX,
this), this.
origin,
false,
this);
169 this.
view_ofs = STAT(PL_VIEW_OFS,
this);
170 setsize(
this, STAT(PL_MIN,
this), STAT(PL_MAX,
this));
188 float k = 32 * (2 * movity - 1);
194 float zspeed = this.velocity_z;
199 float dot = this.
velocity * wishdir;
210 this.velocity_z = zspeed;
223 void PM_Accelerate(
entity this,
float dt,
vector wishdir,
float wishspeed,
float wishspeed0,
float accel,
float accelqw,
float stretchfactor,
float sidefric,
float speedlimit)
225 float speedclamp = stretchfactor > 0 ? stretchfactor
229 accelqw =
fabs(accelqw);
231 if (GAMEPLAYFIX_Q2AIRACCELERATE)
232 wishspeed0 = wishspeed;
234 float vel_straight = this.
velocity * wishdir;
235 float vel_z = this.velocity_z;
237 vector vel_perpend = vel_xy - vel_straight * wishdir;
239 float step = accel * dt * wishspeed0;
241 float vel_xy_current =
vlen(vel_xy);
243 accelqw =
AdjustAirAccelQW(accelqw, (speedlimit -
bound(wishspeed, vel_xy_current, speedlimit)) /
max(1, speedlimit - wishspeed));
244 float vel_xy_forward = vel_xy_current +
bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
245 float vel_xy_backward = vel_xy_current -
bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
246 vel_xy_backward =
max(0, vel_xy_backward);
247 vel_straight = vel_straight +
bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
249 if (sidefric < 0 && (vel_perpend*vel_perpend))
252 float f =
max(0, 1 + dt * wishspeed * sidefric);
253 float themin = (vel_xy_backward * vel_xy_backward - vel_straight * vel_straight) / (vel_perpend * vel_perpend);
263 themin =
sqrt(themin);
264 vel_perpend *=
max(themin, f);
268 vel_perpend *=
max(0, 1 - dt * wishspeed * sidefric);
270 vel_xy = vel_straight * wishdir + vel_perpend;
274 float vel_xy_preclamp;
275 vel_xy_preclamp =
vlen(vel_xy);
276 if (vel_xy_preclamp > 0)
278 vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
279 if (vel_xy_current < vel_xy_preclamp)
280 vel_xy *= (vel_xy_current / vel_xy_preclamp);
284 this.
velocity = vel_xy + vel_z *
'0 0 1';
294 float curspeed =
vlen(curvel);
296 if (wishspeed > curspeed * 1.01)
303 vector wishvel = wishdir * wishspeed;
304 vector acceldir = wishvel - curvel;
305 float addspeed =
vlen(acceldir);
313 float dot = acceldir * curdir;
318 this.
velocity += accelspeed * acceldir;
343 bool doublejump =
false;
345 bool track_jump = PHYS_CL_TRACK_CANJUMP(
this);
350 mjumpheight =
M_ARGV(1,
float);
351 doublejump =
M_ARGV(2,
bool);
383 if(PHYS_JUMPSPEEDCAP_MIN !=
"")
385 float minjumpspeed = mjumpheight *
stof(PHYS_JUMPSPEEDCAP_MIN);
387 if (this.velocity_z < minjumpspeed)
388 mjumpheight += minjumpspeed - this.velocity_z;
391 if(PHYS_JUMPSPEEDCAP_MAX !=
"")
398 float maxjumpspeed = mjumpheight *
stof(PHYS_JUMPSPEEDCAP_MAX);
400 if (this.velocity_z > maxjumpspeed)
401 mjumpheight -= this.velocity_z - maxjumpspeed;
408 if(autocvar_speedmeter)
414 this.velocity_x *= f;
415 this.velocity_y *= f;
424 this.velocity_z += mjumpheight;
433 if (autocvar_g_jump_grunt)
448 traceline (start, end,
true,
this);
451 start_z = start_z + this.maxs_z - 8;
452 end = start + v_forward*24;
454 traceline(start, end,
true,
this);
457 this.velocity_z = 225;
467 #define JETPACK_JUMP(s) CS_CVAR(s).cvar_cl_jetpack_jump 469 float autocvar_cl_jetpack_jump;
470 #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump 478 if (JETPACK_JUMP(
this) < 2)
485 bool air_jump = !playerjump ||
M_ARGV(2,
bool);
489 if (!(
ITEMS_STAT(
this) & ITEM_Jetpack.m_itemid)) { }
495 Send_Notification(NOTIF_ONE,
this, MSG_INFO, INFO_JETPACK_NOFUEL);
497 Send_Notification(NOTIF_ONE,
this, MSG_INFO, INFO_JETPACK_NOFUEL);
518 string specialcommand =
"xwxwxsxsxaxdxaxdx1x ";
519 .float specialcommand_pos;
520 void SpecialCommand(
entity this)
525 LOG_INFO(
"A hollow voice says \"Plugh\".");
537 case 0: c =
"x";
break;
538 case BIT(0): c =
"1";
break;
539 case BIT(2): c =
" ";
break;
540 case BIT(7): c =
"s";
break;
541 case BIT(8): c =
"w";
break;
542 case BIT(9): c =
"a";
break;
543 case BIT(10): c =
"d";
break;
547 if (c ==
substring(specialcommand,
CS(
this).specialcommand_pos, 1))
549 CS(
this).specialcommand_pos += 1;
550 if (
CS(
this).specialcommand_pos >=
strlen(specialcommand))
552 CS(
this).specialcommand_pos = 0;
553 SpecialCommand(
this);
557 else if (
CS(
this).specialcommand_pos && (c !=
substring(specialcommand,
CS(
this).specialcommand_pos - 1, 1)))
558 CS(
this).specialcommand_pos = 0;
568 if (this.
nickspamcount >= autocvar_g_nick_flood_penalty_yellow)
571 PHYS_CS(
this).movement = -1 * PHYS_CS(
this).movement;
576 this.v_angle_x =
random() * 360;
577 this.v_angle_y =
random() * 360;
616 PHYS_CS(
this).movement_x =
bound(-2, PHYS_CS(
this).
movement.x, 2);
617 PHYS_CS(
this).movement_y =
bound(-2, PHYS_CS(
this).
movement.y, 2);
618 PHYS_CS(
this).movement_z =
bound(-2, PHYS_CS(
this).
movement.z, 2);
621 PHYS_CS(
this).movement =
'0 0 0';
634 if(this.(weaponentity).
hook)
652 if (!autocvar_g_footsteps)
return;
655 if (
vdist(this.
velocity, <=, autocvar_sv_maxspeed * 0.6))
return;
656 if ((
time > this.nextstep) || (
time < (this.nextstep - 10.0)))
686 PHYS_CS(
this).movement =
'0 0 0';
690 PHYS_CS(
this).movement =
'0 0 0';
700 +
v_right * PHYS_CS(
this).movement_y;
709 wishvel_z =
sqrt(
max(0, 1 - wishvel * wishvel));
735 float a_diff = a_side * a_side - a_up * a_up;
739 f = a_add * a_up / a_diff;
742 best = (a_diff + a_add * a_add) * (a_diff + a_up * a_up) / a_diff;
747 f = (a_up + a_add) * (a_up + a_add);
754 f = (a_up - a_add) * (a_up - a_add);
767 if (wishvel_z - PHYS_GRAVITY(
this) > 0)
773 fvel =
vlen(wishvel);
776 wishvel_z = (wishvel_z - PHYS_GRAVITY(
this)) * fz + PHYS_GRAVITY(
this);
778 fvel =
min(1,
vlen(wishvel) / best);
786 if (f > 0 && wishvel !=
'0 0 0')
820 void SV_PlayerPhysics(
entity this)
#define PHYS_INPUT_BUTTON_ATCK2(s)
#define PHYS_INPUT_BUTTON_JUMP(s)
#define PHYS_INPUT_BUTTON_CHAT(s)
#define PHYS_INPUT_BUTTON_CROUCH(s)
void CheckPlayerJump(entity this)
#define PHYS_MAXAIRSPEED(s)
#define PHYS_JETPACK_MAXSPEED_UP(s)
void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
#define PHYS_INPUT_BUTTON_HOOK(s)
#define PHYS_JETPACK_REVERSE_THRUST(s)
#define PHYS_AMMO_FUEL(s)
float trace_dphitq3surfaceflags
#define PHYS_WARSOWBUNNY_AIRFORWARDACCEL(s)
const int VOICETYPE_PLAYERSOUND
bool _Movetype_CheckWater(entity this)
const int ANIMACTION_JUMP
void PM_check_slick(entity this)
void PM_Accelerate(entity this, float dt, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
void PM_check_hitground(entity this)
entity viewmodels[MAX_WEAPONSLOTS]
float CVAR_TYPEFLAG_EXISTS
float CheatImpulse(entity this, int imp)
ClientState CS(Client this)
#define PHYS_WARSOWBUNNY_BACKTOSIDERATIO(s)
float copysign(float e, float f)
#define PHYS_WARSOWBUNNY_TOPSPEED(s)
void CSQC_ClientMovement_PlayerMove_Frame(entity this)
#define PHYS_INPUT_BUTTON_ZOOM(s)
REPLICATE(cvar_cl_casings, bool, "cl_casings")
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS(s)
#define PHYS_JETPACK_FUEL(s)
#define PHYS_DODGING_FROZEN(s)
#define PHYS_AIRCONTROL_SIDEWARDS(s)
void PM_ClientMovement_UpdateStatus(entity this)
float Q3SURFACEFLAG_SLICK
float Q3SURFACEFLAG_METALSTEPS
float autocvar_g_balance_pause_fuel_regen
float IsMoveInDirection(vector mv, float ang)
#define UNSET_ONGROUND(s)
#define PHYS_AIRCONTROL_POWER(s)
#define IS_REAL_CLIENT(v)
void PM_AirAccelerate(entity this, float dt, vector wishdir, float wishspeed)
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
void PM_check_punch(entity this, float dt)
#define UNSET_JUMP_HELD(s)
float Q3SURFACEFLAG_NOSTEPS
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
#define PHYS_JETPACK_ANTIGRAVITY(s)
const float MOVE_NOMONSTERS
bool PM_check_specialcommand(entity this, int buttons)
#define PHYS_WARSOWBUNNY_TURNACCEL(s)
void PM_Footsteps(entity this)
float GeomLerp(float a, float _lerp, float b)
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
const int MAX_WEAPONSLOTS
#define PHYS_INPUT_BUTTON_USE(s)
void animdecide_setaction(entity e, float action, float restart)
void PM_check_frozen(entity this)
bool autocvar_sv_q3compat_changehitbox
void PM_jetpack(entity this, float maxspd_mod, float dt)
#define PHYS_INPUT_BUTTON_ATCK(s)
void PM_check_blocked(entity this)
float disableclientprediction
#define PHYS_JETPACK_ACCEL_UP(s)
bool IsFlying(entity this)
void PM_UpdateButtons(entity this, entity store)
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define PHYS_JUMPVELOCITY(s)
float AdjustAirAccelQW(float accelqw, float factor)
#define PHYS_JETPACK_MAXSPEED_SIDE(s)
#define PHYS_WARSOWBUNNY_ACCEL(s)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
#define PHYS_AIRCONTROL(s)
bool PlayerJump(entity this)
const int VIEWLOC_FREEMOVE
float remainder(float e, float f)
#define PHYS_INPUT_BUTTON_JETPACK(s)
const int WATERLEVEL_SWIMMING
#define PHYS_HIGHSPEED(s)
#define MUTATOR_CALLHOOK(id,...)
entity weaponentities[MAX_WEAPONSLOTS]
float pauseregen_finished
vector trace_plane_normal
#define PHYS_AIRCONTROL_BACKWARDS(s)
void sys_phys_update(entity this, float dt)
#define PHYS_JETPACK_ACCEL_SIDE(s)
#define PHYS_AIRCONTROL_PENALTY(s)
void CheckWaterJump(entity this)
#define PHYS_JUMPVELOCITY_CROUCH(s)
#define PHYS_INPUT_BUTTON_MINIGAME(s)
#define PHYS_TRACK_CANJUMP(s)
void PM_check_nickspam(entity this)
#define PHYS_FRICTION_ONLAND(s)