]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
eliminated qbyte type, now uses unsigned char throughout the engine for this purpose
[xonotic/darkplaces.git] / cl_input.c
index 3ab19f32b196671ab7e7e359548e0e692d422b26..85bfd8b0c08c4f5f3e64e4d4936b727ec3e88a07 100644 (file)
@@ -56,8 +56,6 @@ kbutton_t     in_button3, in_button4, in_button5, in_button6, in_button7, in_button8
 
 int                    in_impulse;
 
-extern cvar_t sys_ticrate;
-
 
 void KeyDown (kbutton_t *b)
 {
@@ -258,6 +256,7 @@ cvar_t cl_movement_friction = {0, "cl_movement_friction", "4"};
 cvar_t cl_movement_edgefriction = {0, "cl_movement_edgefriction", "2"};
 cvar_t cl_movement_stepheight = {0, "cl_movement_stepheight", "18"};
 cvar_t cl_movement_accelerate = {0, "cl_movement_accelerate", "10"};
+cvar_t cl_movement_jumpvelocity = {0, "cl_movement_jumpvelocity", "270"};
 cvar_t cl_gravity = {0, "cl_gravity", "800"};
 cvar_t cl_slowmo = {0, "cl_slowmo", "1"};
 
@@ -438,6 +437,7 @@ void CL_Move (void)
 
 #include "cl_collision.h"
 
+extern void V_CalcRefdef(void);
 void CL_UpdatePrydonCursor(void)
 {
        vec3_t temp, scale;
@@ -478,27 +478,68 @@ void CL_UpdatePrydonCursor(void)
        // trace distance
        VectorScale(scale, 1000000, scale);
 
-       // FIXME: use something other than renderer variables here
-       // (but they need to match)
-       VectorCopy(r_vieworigin, cl.cmd.cursor_start);
+       // calculate current view matrix
+       V_CalcRefdef();
+       VectorClear(temp);
+       Matrix4x4_Transform(&r_refdef.viewentitymatrix, temp, cl.cmd.cursor_start);
        VectorSet(temp, cl.cmd.cursor_screen[2] * scale[2], cl.cmd.cursor_screen[0] * scale[0], cl.cmd.cursor_screen[1] * scale[1]);
-       Matrix4x4_Transform(&r_view_matrix, temp, cl.cmd.cursor_end);
+       Matrix4x4_Transform(&r_refdef.viewentitymatrix, 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);
        // makes sparks where cursor is
        //CL_SparkShower(cl.cmd.cursor_impact, cl.cmd.cursor_normal, 5, 0);
 }
 
-void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
+void CL_ClientMovement_Input(qboolean buttonjump, qboolean buttoncrouch)
 {
        int i;
        int n;
+       // remove stale queue items
+       n = cl.movement_numqueue;
+       cl.movement_numqueue = 0;
+       if (cl.servermovesequence)
+       {
+               for (i = 0;i < n;i++)
+                       if (cl.movement_queue[i].sequence > cl.servermovesequence)
+                               cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+       }
+       else
+       {
+               double simulatedtime = cl.mtime[0] + cl_movement_latency.value / 1000.0;
+               for (i = 0;i < n;i++)
+                       if (cl.movement_queue[i].time >= cl.mtime[0] && cl.movement_queue[i].time <= simulatedtime)
+                               cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+       }
+       // add to input queue if there is room
+       if (cl_movement.integer && cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])) && cl.mtime[0] > cl.mtime[1])
+       {
+               // add to input queue
+               cl.movement_queue[cl.movement_numqueue].sequence = cl.movesequence;
+               cl.movement_queue[cl.movement_numqueue].time = cl.mtime[0] + cl_movement_latency.value / 1000.0;
+               cl.movement_queue[cl.movement_numqueue].frametime = cl.mtime[0] - cl.mtime[1];
+               VectorCopy(cl.viewangles, cl.movement_queue[cl.movement_numqueue].viewangles);
+               cl.movement_queue[cl.movement_numqueue].move[0] = cl.cmd.forwardmove;
+               cl.movement_queue[cl.movement_numqueue].move[1] = cl.cmd.sidemove;
+               cl.movement_queue[cl.movement_numqueue].move[2] = cl.cmd.upmove;
+               cl.movement_queue[cl.movement_numqueue].jump = buttonjump;
+               cl.movement_queue[cl.movement_numqueue].crouch = buttoncrouch;
+               cl.movement_numqueue++;
+       }
+       cl.movement = cl_movement.integer && cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.intermission;
+       // clear queue if client movement is disabled
+       if (!cl.movement)
+               cl.movement_numqueue = 0;
+       cl.movement_replay = true;
+}
+
+void CL_ClientMovement_Replay(void)
+{
+       int i;
        int bump;
        int contents;
        int crouch;
+       int onground;
        double edgefriction;
-       double simulatedtime;
-       double currenttime;
-       double newtime;
        double frametime;
        double t;
        vec_t wishspeed;
@@ -521,28 +562,10 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
        trace_t trace;
        trace_t trace2;
        trace_t trace3;
-       // remove stale queue items
-       n = cl.movement_numqueue;
-       cl.movement_numqueue = 0;
-       // calculate time to execute for
-       currenttime = cl.mtime[0];
-       simulatedtime = currenttime + cl_movement_latency.value / 1000.0;
-       for (i = 0;i < n;i++)
-               if (cl.movement_queue[i].time >= cl.mtime[0] && cl.movement_queue[i].time <= simulatedtime)
-                       cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
-       // add to input queue if there is room
-       if (cl.movement_numqueue < sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0]))
-       {
-               // add to input queue
-               cl.movement_queue[cl.movement_numqueue].time = simulatedtime;
-               VectorCopy(cl.viewangles, cl.movement_queue[cl.movement_numqueue].viewangles);
-               cl.movement_queue[cl.movement_numqueue].move[0] = cl.cmd.forwardmove;
-               cl.movement_queue[cl.movement_numqueue].move[1] = cl.cmd.sidemove;
-               cl.movement_queue[cl.movement_numqueue].move[2] = cl.cmd.upmove;
-               cl.movement_queue[cl.movement_numqueue].jump = buttonjump;
-               cl.movement_queue[cl.movement_numqueue].crouch = buttoncrouch;
-               cl.movement_numqueue++;
-       }
+       if (!cl.movement_replay)
+               return;
+       cl.movement_replay = false;
+
        // fetch current starting values
        VectorCopy(cl_entities[cl.playerentity].state_current.origin, currentorigin);
        VectorCopy(cl.mvelocity[0], currentvelocity);
@@ -551,26 +574,24 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
        // protocols this starts in solid)
        //currentorigin[2] += (1.0 / 32.0); // slight nudge to get out of the floor
        crouch = false; // this will be updated on first move
-       //Con_Printf("%f: ", currenttime);
-       // replay input queue, and remove any stale queue items
+
+       // check if onground
+       VectorSet(currentorigin2, currentorigin[0], currentorigin[1], currentorigin[2] + 1);
+       VectorSet(neworigin2, currentorigin[0], currentorigin[1], currentorigin[2] - 1);
+       trace = CL_TraceBox(currentorigin2, cl_playercrouchmins, cl_playercrouchmaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
+       onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7;
+       //Con_Printf("%f: ", cl.mtime[0]);
+
+       // replay the input queue to predict current location
        // note: this relies on the fact there's always one queue item at the end
-       // abort if client movement is disabled
-       cl.movement = cl_movement.integer && cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback;
-       if (!cl.movement)
-               cl.movement_numqueue = 0;
-       for (i = 0;i <= cl.movement_numqueue;i++)
+
+       for (i = 0;i < cl.movement_numqueue;i++)
        {
-               newtime = (i >= cl.movement_numqueue) ? simulatedtime : cl.movement_queue[i].time;
-               frametime = newtime - currenttime;
-               if (frametime <= 0)
-                       continue;
+               client_movementqueue_t *q = cl.movement_queue + bound(0, i, cl.movement_numqueue - 1);
+               frametime = q->frametime;
                //Con_Printf(" %f", frametime);
-               currenttime = newtime;
-               if (i >= 1 && i <= cl.movement_numqueue)
-               if (i > 0 || (cl_movement.integer & 8))
-               if (i < cl.movement_numqueue - 1 || (cl_movement.integer & 16))
+               //if (frametime > 0)
                {
-                       client_movementqueue_t *q = cl.movement_queue + i - 1;
                        if (q->crouch)
                        {
                                // wants to crouch, this always works...
@@ -609,6 +630,8 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                                wishspeed = VectorLength(wishvel);
                                if (wishspeed)
                                        VectorScale(wishvel, 1 / wishspeed, wishdir);
+                               else
+                                       VectorSet( wishdir, 0.0, 0.0, 0.0 );
                                wishspeed = min(wishspeed, cl_movement_maxspeed.value);
                                if (crouch)
                                        wishspeed *= 0.5;
@@ -638,20 +661,24 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                        else
                        {
                                // walk
-                               VectorSet(yawangles, 0, cl.viewangles[1], 0);
+                               if (onground && q->jump)
+                               {
+                                       currentvelocity[2] += cl_movement_jumpvelocity.value;
+                                       onground = false;
+                               }
+                               VectorSet(yawangles, 0, q->viewangles[1], 0);
                                AngleVectors(yawangles, forward, right, up);
                                VectorMAM(q->move[0], forward, q->move[1], right, wishvel);
                                wishspeed = VectorLength(wishvel);
                                if (wishspeed)
                                        VectorScale(wishvel, 1 / wishspeed, wishdir);
+                               else
+                                       VectorSet( wishdir, 0.0, 0.0, 0.0 );
                                wishspeed = min(wishspeed, cl_movement_maxspeed.value);
                                if (crouch)
                                        wishspeed *= 0.5;
                                // check if onground
-                               VectorSet(currentorigin2, currentorigin[0], currentorigin[1], currentorigin[2] + 1);
-                               VectorSet(neworigin2, currentorigin[0], currentorigin[1], currentorigin[2] - 1);
-                               trace = CL_TraceBox(currentorigin2, playermins, playermaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
-                               if (trace.fraction < 1 && trace.plane.normal[2] > 0.7)
+                               if (onground)
                                {
                                        // apply ground friction
                                        f = sqrt(currentvelocity[0] * currentvelocity[0] + currentvelocity[1] * currentvelocity[1]);
@@ -686,8 +713,7 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                                currentvelocity[2] -= cl_gravity.value * frametime;
                        }
                }
-               if (i > 0 || (cl_movement.integer & 2))
-               if (i < cl.movement_numqueue - 1 || (cl_movement.integer & 4))
+               //if (i < cl.movement_numqueue - 1 || (cl_movement.integer & 4))
                {
                        if (crouch)
                        {
@@ -699,6 +725,7 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                                playermins = cl_playerstandmins;
                                playermaxs = cl_playerstandmaxs;
                        }
+                       onground = false;
                        for (bump = 0, t = frametime;bump < 8 && VectorLength2(currentvelocity) > 0;bump++)
                        {
                                VectorMA(currentorigin, t, currentvelocity, neworigin);
@@ -727,6 +754,8 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                                        VectorCopy(trace.endpos, currentorigin);
                                        break;
                                }
+                               if (trace.plane.normal[2] > 0.7)
+                                       onground = true;
                                t *= 1 - trace.fraction;
                                if (trace.fraction >= 0.001)
                                        VectorCopy(trace.endpos, currentorigin);
@@ -735,7 +764,6 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                        }
                }
        }
-       //Con_Printf(" :%f\n", currenttime);
        // store replay location
        VectorCopy(cl.movement_origin, cl.movement_oldorigin);
        VectorCopy(currentorigin, cl.movement_origin);
@@ -754,7 +782,7 @@ void CL_SendMove(void)
        int i;
        int bits;
        sizebuf_t buf;
-       qbyte data[128];
+       unsigned char data[128];
 #define MOVEAVERAGING 0
 #if MOVEAVERAGING
        static float forwardmove, sidemove, upmove, total; // accumulation
@@ -785,6 +813,8 @@ void CL_SendMove(void)
        upmove = cl.cmd.upmove;
 #endif
 
+       CL_UpdatePrydonCursor();
+
        buf.maxsize = 128;
        buf.cursize = 0;
        buf.data = data;
@@ -814,18 +844,79 @@ void CL_SendMove(void)
        if (++cl.movemessages >= 2)
        {
                // send the movement message
-               // PROTOCOL_QUAKE       clc_move = 16 bytes total
-               // PROTOCOL_DARKPLACES1 clc_move = 19 bytes total
-               // PROTOCOL_DARKPLACES2 clc_move = 25 bytes total
-               // PROTOCOL_DARKPLACES3 clc_move = 25 bytes total
-               // PROTOCOL_DARKPLACES4 clc_move = 19 bytes total
-               // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total
-               // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total
-               // 5 bytes
-               MSG_WriteByte (&buf, clc_move);
-               MSG_WriteFloat (&buf, cl.mtime[0]);     // so server can get ping times
-               if (cl.protocol == PROTOCOL_DARKPLACES6)
+               // PROTOCOL_QUAKE        clc_move = 16 bytes total
+               // PROTOCOL_QUAKEDP      clc_move = 16 bytes total
+               // PROTOCOL_NEHAHRAMOVIE clc_move = 16 bytes total
+               // PROTOCOL_DARKPLACES1  clc_move = 19 bytes total
+               // PROTOCOL_DARKPLACES2  clc_move = 25 bytes total
+               // PROTOCOL_DARKPLACES3  clc_move = 25 bytes total
+               // PROTOCOL_DARKPLACES4  clc_move = 19 bytes total
+               // PROTOCOL_DARKPLACES5  clc_move = 19 bytes total
+               // PROTOCOL_DARKPLACES6  clc_move = 52 bytes total
+               // PROTOCOL_DARKPLACES7  clc_move = 56 bytes total
+               if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
                {
+                       // 5 bytes
+                       MSG_WriteByte (&buf, clc_move);
+                       MSG_WriteFloat (&buf, cl.mtime[0]);     // so server can get ping times
+                       // 3 bytes
+                       for (i = 0;i < 3;i++)
+                               MSG_WriteAngle8i (&buf, cl.viewangles[i]);
+                       // 6 bytes
+                       MSG_WriteCoord16i (&buf, forwardmove);
+                       MSG_WriteCoord16i (&buf, sidemove);
+                       MSG_WriteCoord16i (&buf, upmove);
+                       // 2 bytes
+                       MSG_WriteByte (&buf, bits);
+                       MSG_WriteByte (&buf, in_impulse);
+               }
+               else if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
+               {
+                       // 5 bytes
+                       MSG_WriteByte (&buf, clc_move);
+                       MSG_WriteFloat (&buf, cl.mtime[0]);     // so server can get ping times
+                       // 12 bytes
+                       for (i = 0;i < 3;i++)
+                               MSG_WriteAngle32f (&buf, cl.viewangles[i]);
+                       // 6 bytes
+                       MSG_WriteCoord16i (&buf, forwardmove);
+                       MSG_WriteCoord16i (&buf, sidemove);
+                       MSG_WriteCoord16i (&buf, upmove);
+                       // 2 bytes
+                       MSG_WriteByte (&buf, bits);
+                       MSG_WriteByte (&buf, in_impulse);
+               }
+               else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+               {
+                       // 5 bytes
+                       MSG_WriteByte (&buf, clc_move);
+                       MSG_WriteFloat (&buf, cl.mtime[0]);     // so server can get ping times
+                       // 6 bytes
+                       for (i = 0;i < 3;i++)
+                               MSG_WriteAngle16i (&buf, cl.viewangles[i]);
+                       // 6 bytes
+                       MSG_WriteCoord16i (&buf, forwardmove);
+                       MSG_WriteCoord16i (&buf, sidemove);
+                       MSG_WriteCoord16i (&buf, upmove);
+                       // 2 bytes
+                       MSG_WriteByte (&buf, bits);
+                       MSG_WriteByte (&buf, in_impulse);
+               }
+               else
+               {
+                       // 5 bytes
+                       MSG_WriteByte (&buf, clc_move);
+                       if (cl.protocol != PROTOCOL_DARKPLACES6)
+                       {
+                               if (cl_movement.integer)
+                               {
+                                       cl.movesequence++;
+                                       MSG_WriteLong (&buf, cl.movesequence);
+                               }
+                               else
+                                       MSG_WriteLong (&buf, 0);
+                       }
+                       MSG_WriteFloat (&buf, cl.mtime[0]);     // so server can get ping times
                        // 6 bytes
                        for (i = 0;i < 3;i++)
                                MSG_WriteAngle16i (&buf, cl.viewangles[i]);
@@ -848,36 +939,6 @@ void CL_SendMove(void)
                        MSG_WriteFloat (&buf, cl.cmd.cursor_impact[2]);
                        MSG_WriteShort (&buf, cl.cmd.cursor_entitynumber);
                }
-               else
-               {
-                       if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
-                       {
-                               // 3 bytes
-                               for (i = 0;i < 3;i++)
-                                       MSG_WriteAngle8i (&buf, cl.viewangles[i]);
-                       }
-                       else if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
-                       {
-                               // 12 bytes
-                               for (i = 0;i < 3;i++)
-                                       MSG_WriteAngle32f (&buf, cl.viewangles[i]);
-                       }
-                       else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
-                       {
-                               // 6 bytes
-                               for (i = 0;i < 3;i++)
-                                       MSG_WriteAngle16i (&buf, cl.viewangles[i]);
-                       }
-                       else
-                               Host_Error("CL_SendMove: unknown cl.protocol %i\n", cl.protocol);
-                       // 6 bytes
-                       MSG_WriteCoord16i (&buf, forwardmove);
-                       MSG_WriteCoord16i (&buf, sidemove);
-                       MSG_WriteCoord16i (&buf, upmove);
-                       // 2 bytes
-                       MSG_WriteByte (&buf, bits);
-                       MSG_WriteByte (&buf, in_impulse);
-               }
        }
 
 #if MOVEAVERAGING
@@ -900,6 +961,7 @@ void CL_SendMove(void)
        }
 
        // PROTOCOL_DARKPLACES6 = 67 bytes per packet
+       // PROTOCOL_DARKPLACES7 = 71 bytes per packet
 
        // deliver the message
        if (cls.demoplayback)
@@ -908,8 +970,8 @@ void CL_SendMove(void)
        if (!buf.cursize)
                return;
 
-       // FIXME: bits & 64 is +button5, Nexuiz specific
-       CL_ClientMovement((bits & 2) != 0, (bits & 64) != 0);
+       // FIXME: bits & 16 is +button5, Nexuiz specific
+       CL_ClientMovement_Input((bits & 2) != 0, (bits & 16) != 0);
 
        if (NetConn_SendUnreliableMessage(cls.netcon, &buf) == -1)
        {
@@ -987,6 +1049,7 @@ void CL_InitInput (void)
        Cvar_RegisterVariable(&cl_movement_edgefriction);
        Cvar_RegisterVariable(&cl_movement_stepheight);
        Cvar_RegisterVariable(&cl_movement_accelerate);
+       Cvar_RegisterVariable(&cl_movement_jumpvelocity);
        Cvar_RegisterVariable(&cl_gravity);
        Cvar_RegisterVariable(&cl_slowmo);