]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
added GAME_BLADEMASTER
[xonotic/darkplaces.git] / cl_input.c
index d65d60fc36ee5fc5b2e1ae18807c0b5eaebcd5bb..1d5127db6203ddf80e392d9eed4536368effed56 100644 (file)
@@ -421,6 +421,7 @@ cvar_t cl_anglespeedkey = {CVAR_SAVE, "cl_anglespeedkey","1.5","how much +speed
 
 cvar_t cl_movement = {CVAR_SAVE, "cl_movement", "0", "enables clientside prediction of your player movement"};
 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"};
 cvar_t cl_movement_maxspeed = {0, "cl_movement_maxspeed", "320", "how fast you can move (should match sv_maxspeed)"};
 cvar_t cl_movement_maxairspeed = {0, "cl_movement_maxairspeed", "30", "how fast you can move while in the air (should match sv_maxairspeed)"};
 cvar_t cl_movement_stopspeed = {0, "cl_movement_stopspeed", "100", "speed below which you will be slowed rapidly to a stop rather than sliding endlessly (should match sv_stopspeed)"};
@@ -502,7 +503,7 @@ void CL_AdjustAngles (void)
        cl.viewangles[ROLL] = bound(-50, cl.viewangles[ROLL], 50);
 }
 
-qboolean cl_ignoremousemove = false;
+int cl_ignoremousemoves = 2;
 
 /*
 ================
@@ -561,9 +562,9 @@ void CL_Input (void)
        IN_Move ();
 
        // ignore a mouse move if mouse was activated/deactivated this frame
-       if (cl_ignoremousemove)
+       if (cl_ignoremousemoves)
        {
-               cl_ignoremousemove = false;
+               cl_ignoremousemoves--;
                in_mouse_x = 0;
                in_mouse_y = 0;
        }
@@ -582,38 +583,39 @@ void CL_Input (void)
        // if not in menu, apply mouse move to viewangles/movement
        if (!cl.csqc_wantsmousemove && in_client_mouse)
        {
+               float modulatedsensitivity = sensitivity.value * cl.sensitivityscale;
                if (cl_prydoncursor.integer)
                {
                        // mouse interacting with the scene, mostly stationary view
                        V_StopPitchDrift();
-                       cl.cmd.cursor_screen[0] += in_mouse_x * sensitivity.value / vid.width;
-                       cl.cmd.cursor_screen[1] += in_mouse_y * sensitivity.value / vid.height;
+                       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)
                {
                        // strafing mode, all looking is movement
                        V_StopPitchDrift();
-                       cl.cmd.sidemove += m_side.value * in_mouse_x * sensitivity.value;
+                       cl.cmd.sidemove += m_side.value * in_mouse_x * modulatedsensitivity;
                        if (noclip_anglehack)
-                               cl.cmd.upmove -= m_forward.value * in_mouse_y * sensitivity.value;
+                               cl.cmd.upmove -= m_forward.value * in_mouse_y * modulatedsensitivity;
                        else
-                               cl.cmd.forwardmove -= m_forward.value * in_mouse_y * sensitivity.value;
+                               cl.cmd.forwardmove -= m_forward.value * in_mouse_y * modulatedsensitivity;
                }
                else if ((in_mlook.state & 1) || freelook.integer)
                {
                        // mouselook, lookstrafe causes turning to become strafing
                        V_StopPitchDrift();
                        if (lookstrafe.integer)
-                               cl.cmd.sidemove += m_side.value * in_mouse_x * sensitivity.value;
+                               cl.cmd.sidemove += m_side.value * in_mouse_x * modulatedsensitivity;
                        else
-                               cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * sensitivity.value * cl.viewzoom;
-                       cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * sensitivity.value * cl.viewzoom;
+                               cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * modulatedsensitivity * cl.viewzoom;
+                       cl.viewangles[PITCH] += m_pitch.value * in_mouse_y * modulatedsensitivity * cl.viewzoom;
                }
                else
                {
                        // non-mouselook, yaw turning and forward/back movement
-                       cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * sensitivity.value * cl.viewzoom;
-                       cl.cmd.forwardmove -= m_forward.value * in_mouse_y * sensitivity.value;
+                       cl.viewangles[YAW] -= m_yaw.value * in_mouse_x * modulatedsensitivity * cl.viewzoom;
+                       cl.cmd.forwardmove -= m_forward.value * in_mouse_y * modulatedsensitivity;
                }
        }
 
@@ -663,10 +665,10 @@ void CL_UpdatePrydonCursor(void)
        cl.cmd.cursor_screen[2] = 1;
 
        // calculate current view matrix
-       Matrix4x4_OriginFromMatrix(&r_view.matrix, cl.cmd.cursor_start);
+       Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, cl.cmd.cursor_start);
        // calculate direction vector of cursor in viewspace by using frustum slopes
-       VectorSet(temp, cl.cmd.cursor_screen[2] * 1000000, (v_flipped.integer ? -1 : 1) * cl.cmd.cursor_screen[0] * -r_view.frustum_x * 1000000, cl.cmd.cursor_screen[1] * -r_view.frustum_y * 1000000);
-       Matrix4x4_Transform(&r_view.matrix, temp, cl.cmd.cursor_end);
+       VectorSet(temp, cl.cmd.cursor_screen[2] * 1000000, (v_flipped.integer ? -1 : 1) * cl.cmd.cursor_screen[0] * -r_refdef.view.frustum_x * 1000000, cl.cmd.cursor_screen[1] * -r_refdef.view.frustum_y * 1000000);
+       Matrix4x4_Transform(&r_refdef.view.matrix, temp, cl.cmd.cursor_end);
        // trace from view origin to the cursor
        cl.cmd.cursor_fraction = CL_SelectTraceLine(cl.cmd.cursor_start, cl.cmd.cursor_end, cl.cmd.cursor_impact, cl.cmd.cursor_normal, &cl.cmd.cursor_entitynumber, (chase_active.integer || cl.intermission) ? &cl.entities[cl.playerentity].render : NULL);
 }
@@ -1030,7 +1032,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
        // released at least once since the last jump
        if (s->q.jump)
        {
-               if (s->onground && s->q.canjump)
+               if (s->onground && (s->q.canjump || !cl_movement_track_canjump.integer)) // FIXME remove this cvar again when canjump logic actually works, or maybe keep it for mods that allow "pogo-ing"
                {
                        s->velocity[2] += cl.movevars_jumpvelocity;
                        s->onground = false;
@@ -1152,10 +1154,10 @@ extern cvar_t slowmo;
 void CL_UpdateMoveVars(void)
 {
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
-               cl.movevars_ticrate = 1.0 / bound(1, cl_netinputpacketspersecond_qw.value, 100);
+               cl.movevars_packetinterval = 1.0 / bound(1, cl_netinputpacketspersecond_qw.value, 100);
        else if (cl.stats[STAT_MOVEVARS_TICRATE])
        {
-               cl.movevars_ticrate = cl.statsf[STAT_MOVEVARS_TICRATE];
+               cl.movevars_packetinterval = cl.statsf[STAT_MOVEVARS_TICRATE] * cl.statsf[STAT_MOVEVARS_TIMESCALE] / bound(1, cl_netinputpacketsperserverpacket.value, 10);
                cl.movevars_timescale = cl.statsf[STAT_MOVEVARS_TIMESCALE];
                cl.movevars_gravity = cl.statsf[STAT_MOVEVARS_GRAVITY];
                cl.movevars_stopspeed = cl.statsf[STAT_MOVEVARS_STOPSPEED] ;
@@ -1177,7 +1179,7 @@ void CL_UpdateMoveVars(void)
        }
        else
        {
-               cl.movevars_ticrate = 1.0 / bound(1, cl_netinputpacketspersecond.value, 100);
+               cl.movevars_packetinterval = slowmo.value / bound(1, cl_netinputpacketspersecond.value, 100);
                cl.movevars_timescale = slowmo.value;
                cl.movevars_gravity = sv_gravity.value;
                cl.movevars_stopspeed = cl_movement_stopspeed.value;
@@ -1267,6 +1269,8 @@ void CL_ClientMovement_Replay(void)
                VectorCopy(s.origin, cl.movement_origin);
                VectorCopy(s.velocity, cl.movement_velocity);
        }
+       else if(cls.demoplayback) // for bob, speedometer
+               VectorCopy(cl.mvelocity[0], cl.movement_velocity);
 
        // update the onground flag if appropriate
        if (cl.movement_predicted)
@@ -1353,7 +1357,6 @@ void CL_SendMove(void)
        int bits;
        sizebuf_t buf;
        unsigned char data[1024];
-       static double lastsendtime = 0;
        double packettime;
        int msecdelta;
 
@@ -1364,34 +1367,22 @@ void CL_SendMove(void)
                return;
 
        // don't send too often or else network connections can get clogged by a high renderer framerate
-       packettime = cl.movevars_ticrate;
-       if (cls.protocol != PROTOCOL_QUAKEWORLD)
-               packettime /= (double)bound(1, cl_netinputpacketsperserverpacket.value, 10);
+       packettime = cl.movevars_packetinterval;
        // send input every frame in singleplayer
        if (cl.islocalgame)
                packettime = 0;
-       // quakeworld servers take only frametimes
-       // predicted dp7 servers take current interpolation time
-       // unpredicted servers take an echo of the latest server timestamp
+       // send the current interpolation time
        cl.cmd.time = cl.time;
-       cl.cmd.sequence = cls.movesequence;
-       if (cls.protocol == PROTOCOL_QUAKEWORLD)
-       {
-               if (realtime < lastsendtime + packettime)
-                       return;
-               cl.cmd.sequence = cls.netcon->qw.outgoing_sequence;
-       }
+       cl.cmd.sequence = cls.netcon->outgoing_unreliable_sequence;
+       if (cl.cmd.time < cl.lastpackettime + packettime && (cl.mtime[0] != cl.mtime[1] || !cl.movement_needupdate))
+               return;
+       // try to round off the lastpackettime to a multiple of the packet interval
+       // (this causes it to emit packets at a steady beat, and takes advantage
+       //  of the time drift compensation in the cl.time code)
+       if (packettime > 0)
+               cl.lastpackettime = floor(cl.cmd.time / packettime) * packettime;
        else
-       {
-               // movement should be sent immediately whenever a server
-               // packet is received, to minimize ping times
-               if (!cl.movement_needupdate && realtime < lastsendtime + packettime)
-                       return;
-       }
-
-       // don't let it fall behind if CL_SendMove hasn't been called recently
-       // (such is the case when framerate is too low for instance)
-       lastsendtime = bound(realtime, lastsendtime + packettime, realtime + packettime);
+               cl.lastpackettime = cl.cmd.time;
        // set the flag indicating that we sent a packet recently
        cl.movement_needupdate = false;
 
@@ -1408,9 +1399,6 @@ void CL_SendMove(void)
        if ((cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS) && !NetConn_CanSend(cls.netcon) && !cl.islocalgame)
                return;
 
-       // increase the move counter since we intend to send a move
-       cls.movesequence++;
-
        // send the movement message
        // PROTOCOL_QUAKE        clc_move = 16 bytes total
        // PROTOCOL_QUAKEDP      clc_move = 16 bytes total
@@ -1504,19 +1492,19 @@ void CL_SendMove(void)
                QW_MSG_WriteDeltaUsercmd(&buf, &cl.movecmd[2], &cl.movecmd[1]);
                QW_MSG_WriteDeltaUsercmd(&buf, &cl.movecmd[1], &cl.movecmd[0]);
                // calculate the checksum
-               buf.data[checksumindex] = COM_BlockSequenceCRCByteQW(buf.data + checksumindex + 1, buf.cursize - checksumindex - 1, cls.netcon->qw.outgoing_sequence);
+               buf.data[checksumindex] = COM_BlockSequenceCRCByteQW(buf.data + checksumindex + 1, buf.cursize - checksumindex - 1, cls.netcon->outgoing_unreliable_sequence);
                // if delta compression history overflows, request no delta
-               if (cls.netcon->qw.outgoing_sequence - cl.qw_validsequence >= QW_UPDATE_BACKUP-1)
+               if (cls.netcon->outgoing_unreliable_sequence - cl.qw_validsequence >= QW_UPDATE_BACKUP-1)
                        cl.qw_validsequence = 0;
                // request delta compression if appropriate
                if (cl.qw_validsequence && !cl_nodelta.integer && cls.state == ca_connected && !cls.demorecording)
                {
-                       cl.qw_deltasequence[cls.netcon->qw.outgoing_sequence & QW_UPDATE_MASK] = cl.qw_validsequence;
+                       cl.qw_deltasequence[cls.netcon->outgoing_unreliable_sequence & QW_UPDATE_MASK] = cl.qw_validsequence;
                        MSG_WriteByte(&buf, qw_clc_delta);
                        MSG_WriteByte(&buf, cl.qw_validsequence & 255);
                }
                else
-                       cl.qw_deltasequence[cls.netcon->qw.outgoing_sequence & QW_UPDATE_MASK] = -1;
+                       cl.qw_deltasequence[cls.netcon->outgoing_unreliable_sequence & QW_UPDATE_MASK] = -1;
        }
        else if (cls.signon == SIGNONS)
        {
@@ -1752,6 +1740,7 @@ void CL_InitInput (void)
 
        Cvar_RegisterVariable(&cl_movement);
        Cvar_RegisterVariable(&cl_movement_minping);
+       Cvar_RegisterVariable(&cl_movement_track_canjump);
        Cvar_RegisterVariable(&cl_movement_maxspeed);
        Cvar_RegisterVariable(&cl_movement_maxairspeed);
        Cvar_RegisterVariable(&cl_movement_stopspeed);