]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
[04:31:11] <@LordHavoc> div0: 9179 (if (msecdelta <= 0) return;) wrecked connect...
[xonotic/darkplaces.git] / cl_input.c
index 2e87ef2c2bab853444448ec9f98dd3043225566a..e58dad4b1b90bacb046cf3219f569aa78a7ad4fc 100644 (file)
@@ -301,6 +301,7 @@ void IN_BestWeapon (void)
        // if we couldn't find any of the weapons, there's nothing more we can do...
 }
 
+#if 0
 void IN_CycleWeapon (void)
 {
        int i, n;
@@ -347,6 +348,7 @@ void IN_CycleWeapon (void)
        }
        // if we couldn't find any of the weapons, there's nothing more we can do...
 }
+#endif
 
 /*
 ===============
@@ -413,6 +415,7 @@ cvar_t cl_backspeed = {CVAR_SAVE, "cl_backspeed","400","backward movement speed"
 cvar_t cl_sidespeed = {CVAR_SAVE, "cl_sidespeed","350","strafe movement speed"};
 
 cvar_t cl_movespeedkey = {CVAR_SAVE, "cl_movespeedkey","2.0","how much +speed multiplies keyboard movement speed"};
+cvar_t cl_movecliptokeyboard = {0, "cl_movecliptokeyboard", "0", "if set to 1, any move is clipped to the nine keyboard states; if set to 2, only the direction is clipped, not the amount"};
 
 cvar_t cl_yawspeed = {CVAR_SAVE, "cl_yawspeed","140","keyboard yaw turning speed"};
 cvar_t cl_pitchspeed = {CVAR_SAVE, "cl_pitchspeed","150","keyboard pitch turning speed"};
@@ -441,6 +444,10 @@ cvar_t in_pitch_min = {0, "in_pitch_min", "-90", "how far downward you can aim (
 cvar_t in_pitch_max = {0, "in_pitch_max", "90", "how far upward you can aim (quake used 80"};
 
 cvar_t m_filter = {CVAR_SAVE, "m_filter","0", "smoothes mouse movement, less responsive but smoother aiming"};
+cvar_t m_accelerate = {CVAR_SAVE, "m_accelerate","1", "mouse acceleration factor (try 2)"};
+cvar_t m_accelerate_minspeed = {CVAR_SAVE, "m_accelerate_minspeed","5000", "below this speed, no acceleration is done"};
+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_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)"};
@@ -553,6 +560,47 @@ void CL_Input (void)
        // allow mice or other external controllers to add to the move
        IN_Move ();
 
+       // apply m_accelerate if it is on
+       if(m_accelerate.value > 1)
+       {
+               static float averagespeed = 0;
+               float speed, f, mi, ma;
+
+               speed = sqrt(in_mouse_x * in_mouse_x + in_mouse_y * in_mouse_y) / cl.realframetime;
+               if(m_accelerate_filter.value > 0)
+                       f = bound(0, cl.realframetime / m_accelerate_filter.value, 1);
+               else
+                       f = 1;
+               averagespeed = speed * f + averagespeed * (1 - f);
+
+               mi = max(1, m_accelerate_minspeed.value);
+               ma = max(m_accelerate_minspeed.value + 1, m_accelerate_maxspeed.value);
+
+               if(averagespeed <= mi)
+               {
+                       f = 1;
+               }
+               else if(averagespeed >= ma)
+               {
+                       f = m_accelerate.value;
+               }
+               else
+               {
+                       /*
+                       f = log(averagespeed);
+                       mi = log(mi);
+                       ma = log(ma);
+                       */
+                       f = averagespeed;
+                       mi = mi;
+                       ma = ma;
+                       f = (f - mi) / (ma - mi) * (m_accelerate.value - 1) + 1;
+               }
+
+               in_mouse_x *= f;
+               in_mouse_y *= f;
+       }
+
        // apply m_filter if it is on
        mx = in_mouse_x;
        my = in_mouse_y;
@@ -621,6 +669,71 @@ void CL_Input (void)
 
        // clamp after the move to prevent rendering with bad angles
        CL_AdjustAngles ();
+
+       if(cl_movecliptokeyboard.integer)
+       {
+               vec_t f = 1;
+               if (in_speed.state & 1)
+                       f *= cl_movespeedkey.value;
+               if(cl_movecliptokeyboard.integer == 2)
+               {
+                       // digital direction, analog amount
+                       vec_t wishvel_x, wishvel_y;
+                       f *= max(cl_sidespeed.value, max(cl_forwardspeed.value, cl_backspeed.value));
+                       wishvel_x = fabs(cl.cmd.forwardmove);
+                       wishvel_y = fabs(cl.cmd.sidemove);
+                       if(wishvel_x != 0 && wishvel_y != 0 && wishvel_x != wishvel_y)
+                       {
+                               vec_t wishspeed = sqrt(wishvel_x * wishvel_x + wishvel_y * wishvel_y);
+                               if(wishvel_x >= 2 * wishvel_y)
+                               {
+                                       // pure X motion
+                                       if(cl.cmd.forwardmove > 0)
+                                               cl.cmd.forwardmove = wishspeed;
+                                       else
+                                               cl.cmd.forwardmove = -wishspeed;
+                                       cl.cmd.sidemove = 0;
+                               }
+                               else if(wishvel_y >= 2 * wishvel_x)
+                               {
+                                       // pure Y motion
+                                       cl.cmd.forwardmove = 0;
+                                       if(cl.cmd.sidemove > 0)
+                                               cl.cmd.sidemove = wishspeed;
+                                       else
+                                               cl.cmd.sidemove = -wishspeed;
+                               }
+                               else
+                               {
+                                       // diagonal
+                                       if(cl.cmd.forwardmove > 0)
+                                               cl.cmd.forwardmove = 0.70710678118654752440 * wishspeed;
+                                       else
+                                               cl.cmd.forwardmove = -0.70710678118654752440 * wishspeed;
+                                       if(cl.cmd.sidemove > 0)
+                                               cl.cmd.sidemove = 0.70710678118654752440 * wishspeed;
+                                       else
+                                               cl.cmd.sidemove = -0.70710678118654752440 * wishspeed;
+                               }
+                       }
+               }
+               else if(cl_movecliptokeyboard.integer)
+               {
+                       // digital direction, digital amount
+                       if(cl.cmd.sidemove >= cl_sidespeed.value * f * 0.5)
+                               cl.cmd.sidemove = cl_sidespeed.value * f;
+                       else if(cl.cmd.sidemove <= -cl_sidespeed.value * f * 0.5)
+                               cl.cmd.sidemove = -cl_sidespeed.value * f;
+                       else
+                               cl.cmd.sidemove = 0;
+                       if(cl.cmd.forwardmove >= cl_forwardspeed.value * f * 0.5)
+                               cl.cmd.forwardmove = cl_forwardspeed.value * f;
+                       else if(cl.cmd.forwardmove <= -cl_backspeed.value * f * 0.5)
+                               cl.cmd.forwardmove = -cl_backspeed.value * f;
+                       else
+                               cl.cmd.forwardmove = 0;
+               }
+       }
 }
 
 #include "cl_collision.h"
@@ -781,7 +894,7 @@ void CL_ClientMovement_UpdateStatus(cl_clientmovement_state_t *s)
 
        // set onground
        VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
-       VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 2);
+       VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 1); // -2 causes clientside doublejump bug at above 150fps, raising that to 300fps :)
        trace = CL_Move(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
        s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7;
 
@@ -993,6 +1106,9 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_
        vec_t vel_straight, vel_z;
        vec3_t vel_perpend;
        vec_t addspeed;
+       vec_t savespeed;
+
+       savespeed = VectorLength2(s->velocity);
 
        vel_straight = DotProduct(s->velocity, wishdir);
        vel_z = s->velocity[2];
@@ -1004,7 +1120,18 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_
        if(wishspeed > 0)
                vel_straight = vel_straight + min(wishspeed, accel * s->cmd.frametime * wishspeed) * (1 - accelqw);
        
-       VectorScale(vel_perpend, 1 - s->cmd.frametime * wishspeed * sidefric, vel_perpend);
+       if(sidefric < 0 && VectorLength2(vel_perpend))
+       {
+               vec_t f, fmin;
+               f = 1 + s->cmd.frametime * wishspeed * sidefric;
+               fmin = (savespeed - 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);
+       }
+       else
+               VectorScale(vel_perpend, 1 - s->cmd.frametime * wishspeed * sidefric, vel_perpend);
 
        VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
        s->velocity[2] += vel_z;
@@ -1151,69 +1278,53 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                if (s->waterjumptime <= 0)
                {
                        // apply air speed limit
-                       vec_t accel, wishspeed2;
+                       vec_t accel, wishspeed2, accelqw;
+                       qboolean accelerating;
+
+                       accelqw = cl.movevars_airaccel_qw;
                        wishspeed = min(wishspeed, cl.movevars_maxairspeed);
                        if (s->crouched)
                                wishspeed *= 0.5;
                        accel = cl.movevars_airaccelerate;
+
+                       accelerating = (DotProduct(s->velocity, wishdir) > 0);
                        wishspeed2 = wishspeed;
 
-                       if(cl.movevars_warsowbunny_turnaccel)
+                       // CPM: air control
+                       if(cl.movevars_airstopaccelerate != 0)
+                               if(DotProduct(s->velocity, wishdir) < 0)
+                                       accel = cl.movevars_airstopaccelerate;
+                       if(s->cmd.forwardmove == 0 && s->cmd.sidemove != 0)
                        {
-                               qboolean accelerating, decelerating;
-                               //qboolean aircontrol;
-                               accelerating = (DotProduct(s->velocity, wishdir) > 0);
-                               decelerating = (DotProduct(s->velocity, wishdir) < 0);
-                               //aircontrol = false;
-
-                               if(accelerating && s->cmd.sidemove == 0 && s->cmd.forwardmove != 0)
+                               if(cl.movevars_maxairstrafespeed)
                                {
-                                       CL_ClientMovement_Physics_PM_AirAccelerate(s, wishdir, wishspeed2);
+                                       if(wishspeed > cl.movevars_maxairstrafespeed)
+                                               wishspeed = cl.movevars_maxairstrafespeed;
+                                       if(cl.movevars_maxairstrafespeed < cl.movevars_maxairspeed)
+                                               accelqw = 1;
+                                               // otherwise, CPMA-style air acceleration misbehaves a lot
+                                               // if partially non-QW acceleration is used (as in, strafing
+                                               // would get faster than moving forward straight)
                                }
-                               else
+                               if(cl.movevars_airstrafeaccelerate)
                                {
-                                       // CPM: air control
-                                       if(cl.movevars_airstopaccelerate != 0)
-                                               if(DotProduct(s->velocity, wishdir) < 0)
-                                                       accel = cl.movevars_airstopaccelerate;
-                                       if(s->cmd.forwardmove == 0 && s->cmd.sidemove != 0)
-                                       {
-                                               if(cl.movevars_maxairstrafespeed)
-                                                       if(wishspeed > cl.movevars_maxairstrafespeed)
-                                                               wishspeed = cl.movevars_maxairstrafespeed;
-                                               if(cl.movevars_airstrafeaccelerate)
-                                                       accel = cl.movevars_airstrafeaccelerate;
-                                               //if(cl.movevars_aircontrol)
-                                                       //aircontrol = true;
-                                       }
-                                       // !CPM
-                                       
-                                       CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, accel, cl.movevars_airaccel_qw, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed);
-                                       //if(aircontrol)
-                                               //CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
-                                               // div0: this never kicks in, as aircontrol is only set to TRUE if self.movement_x == 0 && self.movement_y != 0, but then the function does nothing
+                                       accel = cl.movevars_airstrafeaccelerate;
+                                       if(cl.movevars_airstrafeaccelerate > cl.movevars_airaccelerate)
+                                               accelqw = 1;
+                                               // otherwise, CPMA-style air acceleration misbehaves a lot
+                                               // if partially non-QW acceleration is used (as in, strafing
+                                               // would get faster than moving forward straight)
                                }
                        }
+                       // !CPM
+
+                       if(cl.movevars_warsowbunny_turnaccel && accelerating && s->cmd.sidemove == 0 && s->cmd.forwardmove != 0)
+                               CL_ClientMovement_Physics_PM_AirAccelerate(s, wishdir, wishspeed2);
                        else
-                       {
-                               // CPM: air control
-                               if(cl.movevars_airstopaccelerate != 0)
-                                       if(DotProduct(s->velocity, wishdir) < 0)
-                                               accel = cl.movevars_airstopaccelerate;
-                               if(s->cmd.forwardmove == 0 && s->cmd.sidemove != 0)
-                               {
-                                       if(cl.movevars_maxairstrafespeed)
-                                               if(wishspeed > cl.movevars_maxairstrafespeed)
-                                                       wishspeed = cl.movevars_maxairstrafespeed;
-                                       if(cl.movevars_airstrafeaccelerate)
-                                               accel = cl.movevars_airstrafeaccelerate;
-                               }
-                               // !CPM
+                               CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, accel, accelqw, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed);
 
-                               CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, accel, cl.movevars_airaccel_qw, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed);
-                               if(cl.movevars_aircontrol)
-                                       CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
-                       }
+                       if(cl.movevars_aircontrol)
+                               CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
                }
                s->velocity[2] -= cl.movevars_gravity * cl.movevars_entgravity * s->cmd.frametime;
                CL_ClientMovement_Move(s);
@@ -1241,6 +1352,7 @@ void CL_UpdateMoveVars(void)
        }
        else if (cl.stats[STAT_MOVEVARS_TICRATE])
        {
+               cl.movevars_ticrate = cl.statsf[STAT_MOVEVARS_TICRATE];
                cl.movevars_timescale = cl.statsf[STAT_MOVEVARS_TIMESCALE];
                cl.movevars_gravity = cl.statsf[STAT_MOVEVARS_GRAVITY];
                cl.movevars_stopspeed = cl.statsf[STAT_MOVEVARS_STOPSPEED] ;
@@ -1271,6 +1383,7 @@ void CL_UpdateMoveVars(void)
        }
        else
        {
+               cl.movevars_ticrate = slowmo.value / bound(1.0f, cl_netfps.value, 1000.0f);
                cl.movevars_timescale = slowmo.value;
                cl.movevars_gravity = sv_gravity.value;
                cl.movevars_stopspeed = cl_movement_stopspeed.value;
@@ -1558,9 +1671,18 @@ void CL_SendMove(void)
        // don't send too often or else network connections can get clogged by a
        // high renderer framerate
        packettime = 1.0 / bound(1, cl_netfps.value, 1000);
+       if (cl.movevars_timescale && cl.movevars_ticrate)
+       {
+               float maxtic = cl.movevars_ticrate / cl.movevars_timescale;
+               packettime = min(packettime, maxtic);
+       }
        // send input every frame in singleplayer
        if (cl.islocalgame)
                packettime = 0;
+
+       // do not send if we do not have anything useful to send
+       if(msecdelta <= 0 && cls.signon == SIGNONS && !cl.paused)
+               return;
        // always send if buttons changed or an impulse is pending
        // even if it violates the rate limit!
        if (!cl.movecmd[0].impulse && (!cl_netimmediatebuttons.integer || cl.movecmd[0].buttons == cl.movecmd[1].buttons))
@@ -1688,7 +1810,7 @@ void CL_SendMove(void)
                case PROTOCOL_DARKPLACES6:
                case PROTOCOL_DARKPLACES7:
                        // set the maxusercmds variable to limit how many should be sent
-                       maxusercmds = bound(1, cl_netrepeatinput.integer + 1, CL_MAX_USERCMDS);
+                       maxusercmds = bound(1, cl_netrepeatinput.integer + 1, min(3, CL_MAX_USERCMDS));
                        // when movement prediction is off, there's not much point in repeating old input as it will just be ignored
                        if (!cl.cmd.predicted)
                                maxusercmds = 1;
@@ -1883,9 +2005,12 @@ void CL_InitInput (void)
 
        // LordHavoc: added bestweapon command
        Cmd_AddCommand ("bestweapon", IN_BestWeapon, "send an impulse number to server to select the first usable weapon out of several (example: 8 7 6 5 4 3 2 1)");
+#if 0
        Cmd_AddCommand ("cycleweapon", IN_CycleWeapon, "send an impulse number to server to select the next usable weapon out of several (example: 9 4 8) if you are holding one of these, and choose the first one if you are holding none of these");
+#endif
        Cmd_AddCommand ("register_bestweapon", IN_BestWeapon_Register_f, "(for QC usage only) change weapon parameters to be used by bestweapon; stuffcmd this in ClientConnect");
 
+       Cvar_RegisterVariable(&cl_movecliptokeyboard);
        Cvar_RegisterVariable(&cl_movement);
        Cvar_RegisterVariable(&cl_movement_minping);
        Cvar_RegisterVariable(&cl_movement_track_canjump);
@@ -1907,6 +2032,10 @@ void CL_InitInput (void)
        Cvar_RegisterVariable(&in_pitch_min);
        Cvar_RegisterVariable(&in_pitch_max);
        Cvar_RegisterVariable(&m_filter);
+       Cvar_RegisterVariable(&m_accelerate);
+       Cvar_RegisterVariable(&m_accelerate_minspeed);
+       Cvar_RegisterVariable(&m_accelerate_maxspeed);
+       Cvar_RegisterVariable(&m_accelerate_filter);
 
        Cvar_RegisterVariable(&cl_netfps);
        Cvar_RegisterVariable(&cl_netrepeatinput);