#define PHYS_JUMPVELOCITY getstatf(STAT_MOVEVARS_JUMPVELOCITY)
#define PHYS_MAXAIRSPEED getstatf(STAT_MOVEVARS_MAXAIRSPEED)
#define PHYS_MAXAIRSTRAFESPEED getstatf(STAT_MOVEVARS_MAXAIRSTRAFESPEED)
- #define PHYS_MAXSPEED getstatf(STAT_MOVEVARS_MAXSPEED)
+ #define PHYS_MAXSPEED(s) getstatf(STAT_MOVEVARS_MAXSPEED)
#define PHYS_STEPHEIGHT getstatf(STAT_MOVEVARS_STEPHEIGHT)
#define PHYS_STOPSPEED getstatf(STAT_MOVEVARS_STOPSPEED)
#define PHYS_WARSOWBUNNY_ACCEL getstatf(STAT_MOVEVARS_WARSOWBUNNY_ACCEL)
#define PHYS_JUMPVELOCITY autocvar_sv_jumpvelocity
#define PHYS_MAXAIRSPEED autocvar_sv_maxairspeed
#define PHYS_MAXAIRSTRAFESPEED autocvar_sv_maxairstrafespeed
- #define PHYS_MAXSPEED autocvar_sv_maxspeed
+ #define PHYS_MAXSPEED(s) s.stat_sv_maxspeed
#define PHYS_STEPHEIGHT autocvar_sv_stepheight
#define PHYS_STOPSPEED autocvar_sv_stopspeed
#define PHYS_WARSOWBUNNY_ACCEL autocvar_sv_warsowbunny_accel
s.velocity = primalvelocity;
}
-void CSQC_ClientMovement_Physics_CPM_PM_Aircontrol(entity s, vector wishdir, float wishspeed)
+void CPM_PM_Aircontrol(entity s, vector wishdir, float wishspeed)
{
float zspeed, xyspeed, dot, k;
s.velocity_z = zspeed;
}
-float CSQC_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor)
+float AdjustAirAccelQW(float accelqw, float factor)
{
return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
}
-void CSQC_ClientMovement_Physics_PM_Accelerate(entity s, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
+// example config for alternate speed clamping:
+// sv_airaccel_qw 0.8
+// sv_airaccel_sideways_friction 0
+// prvm_globalset server speedclamp_mode 1
+// (or 2)
+void PM_Accelerate(entity s, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
{
float vel_straight;
float vel_z;
vector vel_perpend;
float step;
+
vector vel_xy;
float vel_xy_current;
float vel_xy_backward, vel_xy_forward;
if(stretchfactor > 0)
speedclamp = stretchfactor;
else if(accelqw < 0)
- speedclamp = 1;
+ speedclamp = 1; // full clamping, no stretch
else
speedclamp = -1; // no clamping
if(GAMEPLAYFIX_Q2AIRACCELERATE)
wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
- vel_straight = dotproduct(s.velocity, wishdir);
+ vel_straight = s.velocity * wishdir;
vel_z = s.velocity_z;
- vel_xy = s.velocity;
- vel_xy_z -= vel_z;
+ vel_xy = vec2(s.velocity);
vel_perpend = vel_xy - vel_straight * wishdir;
step = accel * PHYS_INPUT_TIMELENGTH * wishspeed0;
vel_xy_current = vlen(vel_xy);
- if(speedlimit > 0)
- accelqw = CSQC_ClientMovement_Physics_AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
+ if(speedlimit)
+ accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
if(vel_xy_backward < 0)
vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
- if(sidefric < 0 && VLEN2(vel_perpend))
+ if(sidefric < 0 && (vel_perpend*vel_perpend))
// negative: only apply so much sideways friction to stay below the speed you could get by "braking"
{
float f, fmin;
f = max(0, 1 + PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
- fmin = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / VLEN2(vel_perpend);
+ fmin = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / (vel_perpend*vel_perpend);
// assume: fmin > 1
// vel_xy_backward*vel_xy_backward - vel_straight*vel_straight > vel_perpend*vel_perpend
// vel_xy_backward*vel_xy_backward > vel_straight*vel_straight + vel_perpend*vel_perpend
else
vel_perpend *= max(0, 1 - PHYS_INPUT_TIMELENGTH * wishspeed * sidefric);
- s.velocity = vel_perpend + vel_straight * wishdir;
+ vel_xy = vel_straight * wishdir + vel_perpend;
if(speedclamp >= 0)
{
float vel_xy_preclamp;
- vel_xy_preclamp = vlen(s.velocity);
+ vel_xy_preclamp = vlen(vel_xy);
if(vel_xy_preclamp > 0) // prevent division by zero
{
vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
if(vel_xy_current < vel_xy_preclamp)
- s.velocity *= (vel_xy_current / vel_xy_preclamp);
+ vel_xy *= (vel_xy_current / vel_xy_preclamp);
}
}
- s.velocity_z += vel_z;
+ s.velocity = vel_xy + vel_z * '0 0 1';
}
-void CSQC_ClientMovement_Physics_PM_AirAccelerate(entity s, vector wishdir, float wishspeed)
+void PM_AirAccelerate(entity s, vector wishdir, float wishspeed)
{
vector curvel, wishvel, acceldir, curdir;
float addspeed, accelspeed, curspeed, f;
if(wishspeed > curspeed * 1.01)
{
- wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL * PHYS_MAXSPEED * PHYS_INPUT_TIMELENGTH);
+ wishspeed = min(wishspeed, curspeed + PHYS_WARSOWBUNNY_AIRFORWARDACCEL * PHYS_MAXSPEED(s) * PHYS_INPUT_TIMELENGTH);
}
else
{
- f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED - PHYS_MAXSPEED));
- wishspeed = max(curspeed, PHYS_WARSOWBUNNY_ACCEL) + PHYS_WARSOWBUNNY_ACCEL * f * PHYS_WARSOWBUNNY_ACCEL * PHYS_INPUT_TIMELENGTH;
+ f = max(0, (PHYS_WARSOWBUNNY_TOPSPEED - curspeed) / (PHYS_WARSOWBUNNY_TOPSPEED - PHYS_MAXSPEED(s)));
+ wishspeed = max(curspeed, PHYS_MAXSPEED(s)) + PHYS_WARSOWBUNNY_ACCEL * f * PHYS_MAXSPEED(s) * PHYS_INPUT_TIMELENGTH;
}
wishvel = wishdir * wishspeed;
acceldir = wishvel - curvel;
addspeed = vlen(acceldir);
acceldir = normalize(acceldir);
- accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL * PHYS_WARSOWBUNNY_ACCEL * PHYS_INPUT_TIMELENGTH);
+ accelspeed = min(addspeed, PHYS_WARSOWBUNNY_TURNACCEL * PHYS_MAXSPEED(s) * PHYS_INPUT_TIMELENGTH);
if(PHYS_WARSOWBUNNY_BACKTOSIDERATIO < 1)
{
// check if onground
if (IS_ONGROUND(s))
{
- wishspeed = min(wishspeed, PHYS_MAXSPEED);
+ wishspeed = min(wishspeed, PHYS_MAXSPEED(s));
if (IS_DUCKED(s))
wishspeed *= 0.5;
// !CPM
if(PHYS_WARSOWBUNNY_TURNACCEL && accelerating && PHYS_INPUT_MOVEVALUES(s)_y == 0 && PHYS_INPUT_MOVEVALUES(s)_x != 0)
- CSQC_ClientMovement_Physics_PM_AirAccelerate(s, wishdir, wishspeed2);
+ PM_AirAccelerate(s, wishdir, wishspeed2);
else
- CSQC_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR, PHYS_AIRACCEL_SIDEWAYS_FRICTION / PHYS_MAXAIRSPEED, PHYS_AIRSPEEDLIMIT_NONQW);
+ PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR, PHYS_AIRACCEL_SIDEWAYS_FRICTION / PHYS_MAXAIRSPEED, PHYS_AIRSPEEDLIMIT_NONQW);
if(PHYS_AIRCONTROL)
- CSQC_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
+ CPM_PM_Aircontrol(s, wishdir, wishspeed2);
}
g = PHYS_GRAVITY * PHYS_ENTGRAVITY(s) * PHYS_INPUT_TIMELENGTH;
if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
vector wishdir = normalize(wishvel);
float wishspeed = vlen(wishvel);
- if (wishspeed > PHYS_MAXSPEED)
- wishspeed = PHYS_MAXSPEED;
+ if (wishspeed > PHYS_MAXSPEED(s))
+ wishspeed = PHYS_MAXSPEED(s);
wishspeed = wishspeed * 0.7;
// water friction
self.velocity = self.velocity * (1 - PHYS_INPUT_TIMELENGTH * PHYS_FRICTION);
// water acceleration
- CSQC_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE, 1, 0, 0, 0);
+ PM_Accelerate(s, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE, 1, 0, 0, 0);
}
void CSQC_ClientMovement_PlayerMove(entity s)
float GeomLerp(float a, float lerp, float b);
-void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{
- float zspeed, xyspeed, dot, k;
-
-#if 0
- // this doesn't play well with analog input
- if(self.movement_x == 0 || self.movement_y != 0)
- return; // can't control movement if not moving forward or backward
- k = 32;
-#else
- k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
- if(k <= 0)
- return;
-#endif
-
- k *= bound(0, wishspeed / autocvar_sv_maxairspeed, 1);
-
- zspeed = self.velocity_z;
- self.velocity_z = 0;
- xyspeed = vlen(self.velocity); self.velocity = normalize(self.velocity);
-
- dot = self.velocity * wishdir;
-
- if(dot > 0) // we can't change direction while slowing down
- {
- k *= pow(dot, autocvar_sv_aircontrol_power)*frametime;
- xyspeed = max(0, xyspeed - autocvar_sv_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32);
- k *= autocvar_sv_aircontrol;
- self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
- }
-
- self.velocity = self.velocity * xyspeed;
- self.velocity_z = zspeed;
-}
-
-float AdjustAirAccelQW(float accelqw, float factor)
-{
- return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
-}
-
-// example config for alternate speed clamping:
-// sv_airaccel_qw 0.8
-// sv_airaccel_sideways_friction 0
-// prvm_globalset server speedclamp_mode 1
-// (or 2)
-void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{
- float vel_straight;
- float vel_z;
- vector vel_perpend;
- float step;
-
- vector vel_xy;
- float vel_xy_current;
- float vel_xy_backward, vel_xy_forward;
- float speedclamp;
-
- if(stretchfactor > 0)
- speedclamp = stretchfactor;
- else if(accelqw < 0)
- speedclamp = 1; // full clamping, no stretch
- else
- speedclamp = -1; // no clamping
-
- if(accelqw < 0)
- accelqw = -accelqw;
-
- if(autocvar_sv_gameplayfix_q2airaccelerate)
- wishspeed0 = wishspeed;
-
- vel_straight = self.velocity * wishdir;
- vel_z = self.velocity_z;
- vel_xy = vec2(self.velocity);
- vel_perpend = vel_xy - vel_straight * wishdir;
-
- step = accel * frametime * wishspeed0;
-
- vel_xy_current = vlen(vel_xy);
- if(speedlimit)
- accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
- vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
- vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
- if(vel_xy_backward < 0)
- vel_xy_backward = 0; // not that it REALLY occurs that this would cause wrong behaviour afterwards
-
- vel_straight = vel_straight + bound(0, wishspeed - vel_straight, step) * accelqw + step * (1 - accelqw);
-
- if(sidefric < 0 && (vel_perpend*vel_perpend))
- // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
- {
- float f, fminimum;
- f = max(0, 1 + frametime * wishspeed * sidefric);
- fminimum = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / (vel_perpend*vel_perpend);
- // this cannot be > 1
- if(fminimum <= 0)
- vel_perpend = vel_perpend * max(0, f);
- else
- {
- fminimum = sqrt(fminimum);
- vel_perpend = vel_perpend * max(fminimum, f);
- }
- }
- else
- vel_perpend = vel_perpend * max(0, 1 - frametime * wishspeed * sidefric);
-
- vel_xy = vel_straight * wishdir + vel_perpend;
-
- if(speedclamp >= 0)
- {
- float vel_xy_preclamp;
- vel_xy_preclamp = vlen(vel_xy);
- if(vel_xy_preclamp > 0) // prevent division by zero
- {
- vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
- if(vel_xy_current < vel_xy_preclamp)
- vel_xy = vel_xy * (vel_xy_current / vel_xy_preclamp);
- }
- }
+void CPM_PM_Aircontrol(entity s, vector wishdir, float wishspeed);
- self.velocity = vel_xy + vel_z * '0 0 1';
-}
+float AdjustAirAccelQW(float accelqw, float factor);
-void PM_AirAccelerate(vector wishdir, float wishspeed)
-{
- vector curvel, wishvel, acceldir, curdir;
- float addspeed, accelspeed, curspeed, f;
- float dot;
+void PM_Accelerate(entity s, vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit);
- if(wishspeed == 0)
- return;
-
- curvel = self.velocity;
- curvel_z = 0;
- curspeed = vlen(curvel);
-
- if(wishspeed > curspeed * 1.01)
- {
- wishspeed = min(wishspeed, curspeed + autocvar_sv_warsowbunny_airforwardaccel * self.stat_sv_maxspeed * frametime);
- }
- else
- {
- f = max(0, (autocvar_sv_warsowbunny_topspeed - curspeed) / (autocvar_sv_warsowbunny_topspeed - self.stat_sv_maxspeed));
- wishspeed = max(curspeed, self.stat_sv_maxspeed) + autocvar_sv_warsowbunny_accel * f * self.stat_sv_maxspeed * frametime;
- }
- wishvel = wishdir * wishspeed;
- acceldir = wishvel - curvel;
- addspeed = vlen(acceldir);
- acceldir = normalize(acceldir);
-
- accelspeed = min(addspeed, autocvar_sv_warsowbunny_turnaccel * self.stat_sv_maxspeed * frametime);
-
- if(autocvar_sv_warsowbunny_backtosideratio < 1)
- {
- curdir = normalize(curvel);
- dot = acceldir * curdir;
- if(dot < 0)
- acceldir = acceldir - (1 - autocvar_sv_warsowbunny_backtosideratio) * dot * curdir;
- }
-
- self.velocity += accelspeed * acceldir;
-}
+void PM_AirAccelerate(entity s, vector wishdir, float wishspeed);
.vector movement_old;
.float buttons_old;
if (wishspeed > self.stat_sv_maxspeed*maxspd_mod)
wishspeed = self.stat_sv_maxspeed*maxspd_mod;
if (time >= self.teleport_time)
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
+ PM_Accelerate(self, wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
}
else if (self.waterlevel >= WATERLEVEL_SWIMMING)
{
self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction);
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
+ PM_Accelerate(self, wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
}
else if (time < self.ladder_time)
{
if (time >= self.teleport_time)
{
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
+ PM_Accelerate(self, wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
}
}
else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO) && !self.frozen)
if (self.crouch)
wishspeed = wishspeed * 0.5;
if (time >= self.teleport_time)
- PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
+ PM_Accelerate(self, wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0);
}
else
{
// !CPM
if(autocvar_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement_x != 0)
- PM_AirAccelerate(wishdir, wishspeed);
+ PM_AirAccelerate(self, wishdir, wishspeed);
else
- PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw);
+ PM_Accelerate(self, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw);
if(autocvar_sv_aircontrol)
- CPM_PM_Aircontrol(wishdir, wishspeed2);
+ CPM_PM_Aircontrol(self, wishdir, wishspeed2);
}
}