]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
Merge remote branch 'origin/master' into akari/irc
[xonotic/darkplaces.git] / cl_input.c
index d4ab8a01d5bf556a4b7ac01a73a0aa5bd7967753..d449bdf6d062a27eed7a281ed9bf5d339f8ab77c 100644 (file)
@@ -423,6 +423,7 @@ cvar_t cl_pitchspeed = {CVAR_SAVE, "cl_pitchspeed","150","keyboard pitch turning
 cvar_t cl_anglespeedkey = {CVAR_SAVE, "cl_anglespeedkey","1.5","how much +speed multiplies keyboard turning speed"};
 
 cvar_t cl_movement = {CVAR_SAVE, "cl_movement", "0", "enables clientside prediction of your player movement"};
+cvar_t cl_movement_replay = {0, "cl_movement_replay", "1", "use engine prediction"};
 cvar_t cl_movement_nettimeout = {CVAR_SAVE, "cl_movement_nettimeout", "0.3", "stops predicting moves when server is lagging badly (avoids major performance problems), timeout in seconds"};
 cvar_t cl_movement_minping = {CVAR_SAVE, "cl_movement_minping", "0", "whether to use prediction when ping is lower than this value in milliseconds"};
 cvar_t cl_movement_track_canjump = {CVAR_SAVE, "cl_movement_track_canjump", "1", "track if the player released the jump key between two jumps to decide if he is able to jump or not; when off, this causes some \"sliding\" slightly above the floor when the jump key is held too long; if the mod allows repeated jumping by holding space all the time, this has to be set to zero too"};
@@ -456,6 +457,8 @@ cvar_t cl_netimmediatebuttons = {CVAR_SAVE, "cl_netimmediatebuttons", "1", "send
 
 cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-player entities in QW network protocol"};
 
+cvar_t cl_csqc_generatemousemoveevents = {0, "cl_csqc_generatemousemoveevents", "1", "enables calls to CSQC_InputEvent with type 2, for compliance with EXT_CSQC spec"};
+
 extern cvar_t v_flipped;
 
 /*
@@ -515,6 +518,7 @@ CL_Input
 Send the intended movement message to the server
 ================
 */
+extern qboolean CL_VM_InputEvent (int eventtype, int x, int y);
 void CL_Input (void)
 {
        float mx, my;
@@ -561,6 +565,27 @@ void CL_Input (void)
        // allow mice or other external controllers to add to the move
        IN_Move ();
 
+       // send mouse move to csqc
+       if (cl.csqc_loaded && cl_csqc_generatemousemoveevents.integer)
+       {
+               if (cl.csqc_wantsmousemove)
+               {
+                       // event type 3 is a DP_CSQC thing
+                       static int oldwindowmouse[2];
+                       if (oldwindowmouse[0] != in_windowmouse_x || oldwindowmouse[1] != in_windowmouse_y)
+                       {
+                               CL_VM_InputEvent(3, in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height);
+                               oldwindowmouse[0] = in_windowmouse_x;
+                               oldwindowmouse[1] = in_windowmouse_y;
+                       }
+               }
+               else
+               {
+                       if (in_mouse_x || in_mouse_y)
+                               CL_VM_InputEvent(2, in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height);
+               }
+       }
+
        // apply m_accelerate if it is on
        if(m_accelerate.value > 1)
        {
@@ -587,14 +612,7 @@ void CL_Input (void)
                }
                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;
                }
 
@@ -622,17 +640,10 @@ void CL_Input (void)
        }
 
        // if not in menu, apply mouse move to viewangles/movement
-       if (!key_consoleactive && key_dest == key_game && !cl.csqc_wantsmousemove)
+       if (!key_consoleactive && key_dest == key_game && !cl.csqc_wantsmousemove && cl_prydoncursor.integer <= 0)
        {
                float modulatedsensitivity = sensitivity.value * cl.sensitivityscale;
-               if (cl_prydoncursor.integer > 0)
-               {
-                       // mouse interacting with the scene, mostly stationary view
-                       V_StopPitchDrift();
-                       cl.cmd.cursor_screen[0] += in_mouse_x * modulatedsensitivity / vid.width;
-                       cl.cmd.cursor_screen[1] += in_mouse_y * modulatedsensitivity / vid.height;
-               }
-               else if (in_strafe.state & 1)
+               if (in_strafe.state & 1)
                {
                        // strafing mode, all looking is movement
                        V_StopPitchDrift();
@@ -660,7 +671,13 @@ void CL_Input (void)
                }
        }
        else // don't pitch drift when csqc is controlling the mouse
+       {
+               // mouse interacting with the scene, mostly stationary view
                V_StopPitchDrift();
+               // update prydon cursor
+               cl.cmd.cursor_screen[0] = in_windowmouse_x * 2.0 / vid.width - 1.0;
+               cl.cmd.cursor_screen[1] = in_windowmouse_y * 2.0 / vid.height - 1.0;
+       }
 
        if(v_flipped.integer)
        {
@@ -1075,7 +1092,7 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
                                s->velocity[2] =  80;
                        else
                        {
-                               if (gamemode == GAME_NEXUIZ)
+                               if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
                                        s->velocity[2] = 200;
                                else
                                        s->velocity[2] = 100;
@@ -1161,7 +1178,7 @@ float CL_ClientMovement_Physics_AdjustAirAccelQW(float accelqw, float factor)
                bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1);
 }
 
-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 speedlimit)
+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 stretchfactor, vec_t sidefric, vec_t speedlimit)
 {
        vec_t vel_straight;
        vec_t vel_z;
@@ -1170,10 +1187,16 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_
        vec3_t vel_xy;
        vec_t vel_xy_current;
        vec_t vel_xy_backward, vel_xy_forward;
-       qboolean speedclamp;
+       vec_t speedclamp;
 
-       speedclamp = (accelqw < 0);
-       if(speedclamp)
+       if(stretchfactor > 0)
+               speedclamp = stretchfactor;
+       else if(accelqw < 0)
+               speedclamp = 1;
+       else
+               speedclamp = -1; // no clamping
+
+       if(accelqw < 0)
                accelqw = -accelqw;
 
        if(cl.moveflags & MOVEFLAG_Q2AIRACCELERATE)
@@ -1220,13 +1243,15 @@ void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_
 
        VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
 
-       if(speedclamp)
+       if(speedclamp >= 0)
        {
-               vel_xy_current = min(VectorLength(s->velocity), vel_xy_forward);
-               if(vel_xy_current > 0) // prevent division by zero
+               vec_t vel_xy_preclamp;
+               vel_xy_preclamp = VectorLength(s->velocity);
+               if(vel_xy_preclamp > 0) // prevent division by zero
                {
-                       VectorNormalize(s->velocity);
-                       VectorScale(s->velocity, vel_xy_current, s->velocity);
+                       vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
+                       if(vel_xy_current < vel_xy_preclamp)
+                               VectorScale(s->velocity, (vel_xy_current / vel_xy_preclamp), s->velocity);
                }
        }
 
@@ -1349,7 +1374,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                                if (cls.protocol == PROTOCOL_QUAKEWORLD)
                                        trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                                else
-                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+                                       trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false, false);
                                if (trace.fraction == 1 && !trace.startsolid)
                                        friction *= cl.movevars_edgefriction;
                        }
@@ -1422,7 +1447,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                        if(cl.movevars_warsowbunny_turnaccel && accelerating && s->cmd.sidemove == 0 && s->cmd.forwardmove != 0)
                                CL_ClientMovement_Physics_PM_AirAccelerate(s, wishdir, wishspeed2);
                        else
-                               CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed, cl.movevars_airspeedlimit_nonqw);
+                               CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, cl.movevars_airaccel_qw_stretchfactor, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed, cl.movevars_airspeedlimit_nonqw);
 
                        if(cl.movevars_aircontrol)
                                CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
@@ -1476,6 +1501,7 @@ void CL_UpdateMoveVars(void)
                cl.movevars_maxairspeed = cl.statsf[STAT_MOVEVARS_MAXAIRSPEED];
                cl.movevars_stepheight = cl.statsf[STAT_MOVEVARS_STEPHEIGHT];
                cl.movevars_airaccel_qw = cl.statsf[STAT_MOVEVARS_AIRACCEL_QW];
+               cl.movevars_airaccel_qw_stretchfactor = cl.statsf[STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR];
                cl.movevars_airaccel_sideways_friction = cl.statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION];
                cl.movevars_friction = cl.statsf[STAT_MOVEVARS_FRICTION];
                cl.movevars_wallfriction = cl.statsf[STAT_MOVEVARS_WALLFRICTION];
@@ -1515,6 +1541,7 @@ void CL_UpdateMoveVars(void)
                cl.movevars_maxairspeed = cl_movement_maxairspeed.value;
                cl.movevars_stepheight = cl_movement_stepheight.value;
                cl.movevars_airaccel_qw = cl_movement_airaccel_qw.value;
+               cl.movevars_airaccel_qw_stretchfactor = 0;
                cl.movevars_airaccel_sideways_friction = cl_movement_airaccel_sideways_friction.value;
                cl.movevars_airstopaccelerate = 0;
                cl.movevars_airstrafeaccelerate = 0;
@@ -1550,6 +1577,9 @@ void CL_ClientMovement_Replay(void)
        if (cl.movement_predicted && !cl.movement_replay)
                return;
 
+       if (!cl_movement_replay.integer)
+               return;
+
        // set up starting state for the series of moves
        memset(&s, 0, sizeof(s));
        VectorCopy(cl.entities[cl.playerentity].state_current.origin, s.origin);
@@ -1694,6 +1724,25 @@ void CL_NewFrameReceived(int num)
        cl.latestframenumsposition = (cl.latestframenumsposition + 1) % LATESTFRAMENUMS;
 }
 
+void CL_RotateMoves(const matrix4x4_t *m)
+{
+       // rotate viewangles in all previous moves
+       vec3_t v;
+       vec3_t f, r, u;
+       int i;
+       for (i = 0;i < CL_MAX_USERCMDS;i++)
+       {
+               if (cl.movecmd[i].sequence > cls.servermovesequence)
+               {
+                       usercmd_t *c = &cl.movecmd[i];
+                       AngleVectors(c->viewangles, f, r, u);
+                       Matrix4x4_Transform(m, f, v); VectorCopy(v, f);
+                       Matrix4x4_Transform(m, u, v); VectorCopy(v, u);
+                       AnglesFromVectors(c->viewangles, f, u, false);
+               }
+       }
+}
+
 /*
 ==============
 CL_SendMove
@@ -1751,10 +1800,13 @@ void CL_SendMove(void)
        if (in_button16.state  & 3) bits |= 262144;
        // button bits 19-31 unused currently
        // rotate/zoom view serverside if PRYDON_CLIENTCURSOR cursor is at edge of screen
-       if (cl.cmd.cursor_screen[0] <= -1) bits |= 8;
-       if (cl.cmd.cursor_screen[0] >=  1) bits |= 16;
-       if (cl.cmd.cursor_screen[1] <= -1) bits |= 32;
-       if (cl.cmd.cursor_screen[1] >=  1) bits |= 64;
+       if(cl_prydoncursor.integer > 0)
+       {
+               if (cl.cmd.cursor_screen[0] <= -1) bits |= 8;
+               if (cl.cmd.cursor_screen[0] >=  1) bits |= 16;
+               if (cl.cmd.cursor_screen[1] <= -1) bits |= 32;
+               if (cl.cmd.cursor_screen[1] >=  1) bits |= 64;
+       }
 
        // set buttons and impulse
        cl.cmd.buttons = bits;
@@ -1796,7 +1848,7 @@ void CL_SendMove(void)
                break;
        case PROTOCOL_DARKPLACES6:
        case PROTOCOL_DARKPLACES7:
-               // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz specific
+               // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz/Xonotic specific
                cl.cmd.crouch = (cl.cmd.buttons & 16) != 0;
                break;
        case PROTOCOL_UNKNOWN:
@@ -1908,9 +1960,17 @@ void CL_SendMove(void)
                        // 5 bytes
                        MSG_WriteByte (&buf, clc_move);
                        MSG_WriteFloat (&buf, cl.cmd.time); // last server packet time
-                       // 3 bytes
-                       for (i = 0;i < 3;i++)
-                               MSG_WriteAngle8i (&buf, cl.cmd.viewangles[i]);
+                       // 3 bytes (6 bytes in proquake)
+                       if (cls.proquake_servermod == 1) // MOD_PROQUAKE
+                       {
+                               for (i = 0;i < 3;i++)
+                                       MSG_WriteAngle16i (&buf, cl.cmd.viewangles[i]);
+                       }
+                       else
+                       {
+                               for (i = 0;i < 3;i++)
+                                       MSG_WriteAngle8i (&buf, cl.cmd.viewangles[i]);
+                       }
                        // 6 bytes
                        MSG_WriteCoord16i (&buf, cl.cmd.forwardmove);
                        MSG_WriteCoord16i (&buf, cl.cmd.sidemove);
@@ -2166,6 +2226,7 @@ void CL_InitInput (void)
 
        Cvar_RegisterVariable(&cl_movecliptokeyboard);
        Cvar_RegisterVariable(&cl_movement);
+       Cvar_RegisterVariable(&cl_movement_replay);
        Cvar_RegisterVariable(&cl_movement_nettimeout);
        Cvar_RegisterVariable(&cl_movement_minping);
        Cvar_RegisterVariable(&cl_movement_track_canjump);
@@ -2197,5 +2258,7 @@ void CL_InitInput (void)
        Cvar_RegisterVariable(&cl_netimmediatebuttons);
 
        Cvar_RegisterVariable(&cl_nodelta);
+
+       Cvar_RegisterVariable(&cl_csqc_generatemousemoveevents);
 }