]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
fix two typos in Mod_Q3BSP_LoadTriangles errors
[xonotic/darkplaces.git] / cl_input.c
index f6d90d4f18b6fd14e2cef3eb6a1a7da134814f7a..9f75a36fbc4571c39d75aaa09572ad9e1de0f374 100644 (file)
@@ -438,8 +438,8 @@ cvar_t cl_movement_accelerate = {0, "cl_movement_accelerate", "10", "how fast yo
 cvar_t cl_movement_airaccelerate = {0, "cl_movement_airaccelerate", "-1", "how fast you accelerate while in the air (should match sv_airaccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
 cvar_t cl_movement_wateraccelerate = {0, "cl_movement_wateraccelerate", "-1", "how fast you accelerate while in water (should match sv_wateraccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
 cvar_t cl_movement_jumpvelocity = {0, "cl_movement_jumpvelocity", "270", "how fast you move upward when you begin a jump (should match the quakec code)"};
-cvar_t cl_movement_airaccel_qw = {0, "cl_movement_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration (should match sv_airaccel_qw)"};
-cvar_t cl_movement_airaccel_sideways_friction = {0, "cl_movement_airaccel_sideways_friction", "0", "anti-sideways movement stabilization (should match sv_airaccel_sideways_friction)"};
+cvar_t cl_movement_airaccel_qw = {0, "cl_movement_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration (reduces speed gain when zigzagging) (should match sv_airaccel_qw); when < 0, the speed is clamped against the maximum allowed forward speed after the move"};
+cvar_t cl_movement_airaccel_sideways_friction = {0, "cl_movement_airaccel_sideways_friction", "0", "anti-sideways movement stabilization (should match sv_airaccel_sideways_friction); when < 0, only so much friction is applied that braking (by accelerating backwards) cannot be stronger"};
 
 cvar_t in_pitch_min = {0, "in_pitch_min", "-90", "how far downward you can aim (quake used -70"};
 cvar_t in_pitch_max = {0, "in_pitch_max", "90", "how far upward you can aim (quake used 80"};
@@ -450,7 +450,7 @@ cvar_t m_accelerate_minspeed = {CVAR_SAVE, "m_accelerate_minspeed","5000", "belo
 cvar_t m_accelerate_maxspeed = {CVAR_SAVE, "m_accelerate_maxspeed","10000", "above this speed, full acceleration is done"};
 cvar_t m_accelerate_filter = {CVAR_SAVE, "m_accelerate_filter","0.1", "mouse acceleration factor filtering"};
 
-cvar_t cl_netfps = {CVAR_SAVE, "cl_netfps","20", "how many input packets to send to server each second"};
+cvar_t cl_netfps = {CVAR_SAVE, "cl_netfps","72", "how many input packets to send to server each second"};
 cvar_t cl_netrepeatinput = {CVAR_SAVE, "cl_netrepeatinput", "1", "how many packets in a row can be lost without movement issues when using cl_movement (technically how many input messages to repeat in each packet that have not yet been acknowledged by the server), only affects DP7 and later servers (Quake uses 0, QuakeWorld uses 2, and just for comparison Quake3 uses 1)"};
 cvar_t cl_netimmediatebuttons = {CVAR_SAVE, "cl_netimmediatebuttons", "1", "sends extra packets whenever your buttons change or an impulse is used (basically: whenever you click fire or change weapon)"};
 
@@ -1078,19 +1078,41 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
        CL_ClientMovement_Move(s);
 }
 
+static vec_t CL_IsMoveInDirection(vec_t forward, vec_t side, vec_t angle)
+{
+       if(forward == 0 && side == 0)
+               return 0; // avoid division by zero
+       angle -= RAD2DEG(atan2(side, forward));
+       angle = (ANGLEMOD(angle + 180) - 180) / 45;
+       if(angle >  1)
+               return 0;
+       if(angle < -1)
+               return 0;
+       return 1 - fabs(angle);
+}
+
 void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed)
 {
        vec_t zspeed, speed, dot, k;
 
+#if 0
+       // this doesn't play well with analog input
        if(s->cmd.forwardmove == 0 || s->cmd.sidemove != 0)
                return;
-       
+       k = 32;
+#else
+       k = 32 * (2 * CL_IsMoveInDirection(s->cmd.forwardmove, s->cmd.sidemove, 0) - 1);
+       if(k <= 0)
+               return;
+#endif
+
+       k *= bound(0, wishspeed / cl.movevars_maxairspeed, 1);
+
        zspeed = s->velocity[2];
        s->velocity[2] = 0;
        speed = VectorNormalizeLength(s->velocity);
 
        dot = DotProduct(s->velocity, wishdir);
-       k = 32;
        k *= cl.movevars_aircontrol*dot*dot*s->cmd.frametime;
 
        if(dot > 0) { // we can't change direction while slowing down
@@ -1104,40 +1126,66 @@ void CL_ClientMovement_Physics_CPM_PM_Aircontrol(cl_clientmovement_state_t *s, v
 
 void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t sidefric)
 {
-       vec_t vel_straight, vel_z;
+       vec_t vel_straight;
+       vec_t vel_z;
        vec3_t vel_perpend;
-       vec_t addspeed;
-       vec_t savespeed;
+       vec_t step;
+       vec3_t vel_xy;
+       vec_t vel_xy_current;
+       vec_t vel_xy_backward, vel_xy_forward;
+       qboolean speedclamp;
+
+       speedclamp = (accelqw < 0);
+       if(speedclamp)
+               accelqw = -accelqw;
 
        if(cl.moveflags & MOVEFLAG_Q2AIRACCELERATE)
                wishspeed0 = wishspeed; // don't need to emulate this Q1 bug
 
-       savespeed = VectorLength2(s->velocity);
-
        vel_straight = DotProduct(s->velocity, wishdir);
        vel_z = s->velocity[2];
-       VectorMA(s->velocity, -vel_straight, wishdir, vel_perpend); vel_perpend[2] -= vel_z;
-
-       addspeed = wishspeed - vel_straight;
-       if(addspeed > 0)
-               vel_straight = vel_straight + min(addspeed, accel * s->cmd.frametime * wishspeed0) * accelqw;
-       if(wishspeed > 0)
-               vel_straight = vel_straight + min(wishspeed, accel * s->cmd.frametime * wishspeed0) * (1 - accelqw);
-       
+       VectorCopy(s->velocity, vel_xy); vel_xy[2] -= vel_z;
+       VectorMA(vel_xy, -vel_straight, wishdir, vel_perpend);
+
+       step = accel * s->cmd.frametime * wishspeed0;
+
+       vel_xy_current  = VectorLength(vel_xy);
+       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 && VectorLength2(vel_perpend))
+               // negative: only apply so much sideways friction to stay below the speed you could get by "braking"
        {
                vec_t f, fmin;
                f = 1 - s->cmd.frametime * wishspeed * sidefric;
-               fmin = (savespeed - vel_straight*vel_straight) / VectorLength2(vel_perpend);
+               fmin = (vel_xy_backward*vel_xy_backward - vel_straight*vel_straight) / VectorLength2(vel_perpend);
                if(fmin <= 0)
                        VectorScale(vel_perpend, f, vel_perpend);
                else
-                       VectorScale(vel_perpend, min(1.0f, max(fmin, f)), vel_perpend);
+               {
+                       fmin = sqrt(fmin);
+                       VectorScale(vel_perpend, bound(fmin, f, 1.0f), vel_perpend);
+               }
        }
        else
                VectorScale(vel_perpend, 1 - s->cmd.frametime * wishspeed * sidefric, vel_perpend);
 
        VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
+
+       if(speedclamp)
+       {
+               vel_xy_current = min(VectorLength(s->velocity), vel_xy_forward);
+               if(vel_xy_current > 0) // prevent division by zero
+               {
+                       VectorNormalize(s->velocity);
+                       VectorScale(s->velocity, vel_xy_current, s->velocity);
+               }
+       }
+
        s->velocity[2] += vel_z;
 }
 
@@ -1299,6 +1347,9 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                        if(cl.movevars_airstopaccelerate != 0)
                                if(DotProduct(s->velocity, wishdir) < 0)
                                        accel = cl.movevars_airstopaccelerate;
+                       // this doesn't play well with analog input, but can't really be
+                       // fixed like the AirControl can. So, don't set the maxairstrafe*
+                       // cvars when you want to support analog input.
                        if(s->cmd.forwardmove == 0 && s->cmd.sidemove != 0)
                        {
                                if(cl.movevars_maxairstrafespeed)