]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Partially merge server and client physics
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 8 Dec 2014 04:11:02 +0000 (15:11 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 8 Dec 2014 04:11:02 +0000 (15:11 +1100)
qcsrc/common/physics.qc
qcsrc/server/cl_physics.qc

index feb799b57740b602523d8911c37b694f7a025912..d6e7f77909c8b529f5c80be257801643e408512a 100644 (file)
@@ -48,7 +48,7 @@
        #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
@@ -349,7 +349,7 @@ void CSQC_ClientMovement_Move(entity s)
                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;
 
@@ -384,17 +384,23 @@ void CSQC_ClientMovement_Physics_CPM_PM_Aircontrol(entity s, vector wishdir, flo
        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;
@@ -403,7 +409,7 @@ void CSQC_ClientMovement_Physics_PM_Accelerate(entity s, vector wishdir, float w
        if(stretchfactor > 0)
                speedclamp = stretchfactor;
        else if(accelqw < 0)
-               speedclamp = 1;
+               speedclamp = 1; // full clamping, no stretch
        else
                speedclamp = -1; // no clamping
 
@@ -413,17 +419,16 @@ void CSQC_ClientMovement_Physics_PM_Accelerate(entity s, vector wishdir, float w
        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)
@@ -431,12 +436,12 @@ void CSQC_ClientMovement_Physics_PM_Accelerate(entity s, vector wishdir, float w
 
        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
@@ -453,24 +458,24 @@ void CSQC_ClientMovement_Physics_PM_Accelerate(entity s, vector wishdir, float w
        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;
@@ -485,19 +490,19 @@ void CSQC_ClientMovement_Physics_PM_AirAccelerate(entity s, vector wishdir, floa
 
        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)
        {
@@ -551,7 +556,7 @@ void CSQC_ClientMovement_Physics_Walk(entity s)
        // 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;
 
@@ -645,12 +650,12 @@ void CSQC_ClientMovement_Physics_Walk(entity s)
                        // !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)
@@ -680,15 +685,15 @@ void CSQC_ClientMovement_Physics_Swim(entity s)
 
        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)
index fbff30684e23bb8cd39ccb2448fcc4db3d368f7e..9b23de976f8119266ab72d91ae96088bcd0a82b0 100644 (file)
@@ -391,167 +391,13 @@ float IsMoveInDirection(vector mv, float angle);
 
 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;
@@ -914,7 +760,7 @@ void SV_PlayerPhysics()
                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)
        {
@@ -937,7 +783,7 @@ void SV_PlayerPhysics()
                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)
        {
@@ -987,7 +833,7 @@ void SV_PlayerPhysics()
                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)
@@ -1169,7 +1015,7 @@ void SV_PlayerPhysics()
                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
        {
@@ -1238,12 +1084,12 @@ void SV_PlayerPhysics()
                        // !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);
                }
        }