added cl.movement_velocity to allow view bobbing to match up with cl_movement
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 6 May 2005 00:36:07 +0000 (00:36 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 6 May 2005 00:36:07 +0000 (00:36 +0000)
fixed some bugs in cl_movement timing, it now applies input to the next move not the current one, making it work properly (assuming cl_movement_latency is exact)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5229 d7cf8633-e32d-0410-b094-e92efae38249

cl_input.c
client.h
view.c

index 3d9f0ad..9f92955 100644 (file)
@@ -418,22 +418,43 @@ void CL_UpdatePrydonCursor(void)
 
 void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
 {
-       int i, n, bump, contents, crouch;
+       int i;
+       int n;
+       int bump;
+       int contents;
+       int crouch;
        double edgefriction;
        double simulatedtime;
        double currenttime;
        double newtime;
        double frametime;
        double t;
-       vec_t wishspeed, addspeed, accelspeed, f, *playermins, *playermaxs;
-       client_movementqueue_t *q;
-       vec3_t currentorigin, currentvelocity, forward, right, up, wishvel, wishdir, neworigin, currentorigin2, neworigin2, yawangles;
-       trace_t trace, trace2, trace3;
+       vec_t wishspeed;
+       vec_t addspeed;
+       vec_t accelspeed;
+       vec_t f;
+       vec_t *playermins;
+       vec_t *playermaxs;
+       vec3_t currentorigin;
+       vec3_t currentvelocity;
+       vec3_t forward;
+       vec3_t right;
+       vec3_t up;
+       vec3_t wishvel;
+       vec3_t wishdir;
+       vec3_t neworigin;
+       vec3_t currentorigin2;
+       vec3_t neworigin2;
+       vec3_t yawangles;
+       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
-       simulatedtime = cl.mtime[0] + cl_movement_latency.value / 1000.0;
+       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];
@@ -450,12 +471,7 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                cl.movement_queue[cl.movement_numqueue].crouch = buttoncrouch;
                cl.movement_numqueue++;
        }
-       cl.movement = false;
-       // abort if client movement is disabled
-       if (!cl_movement.integer || cl.stats[STAT_HEALTH] <= 0)
-               return;
        // fetch current starting values
-       currenttime = cl.mtime[0];
        VectorCopy(cl_entities[cl.playerentity].state_current.origin, currentorigin);
        VectorCopy(cl.mvelocity[0], currentvelocity);
        // FIXME: try minor nudges in various directions if startsolid to find a
@@ -466,61 +482,23 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
        //Con_Printf("%f: ", currenttime);
        // replay input queue, and remove any stale queue items
        // note: this relies on the fact there's always one queue item at the end
-       for (i = 0, q = cl.movement_queue;i < cl.movement_numqueue;i++, q++)
+       // 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++)
        {
-               //newtime = (i == cl.movement_numqueue) ? simulatedtime : q->time;
-               newtime = q->time;
+               newtime = (i >= cl.movement_numqueue) ? simulatedtime : cl.movement_queue[i].time;
                frametime = newtime - currenttime;
-               if (frametime < 0)
+               if (frametime <= 0)
                        continue;
                //Con_Printf(" %f", frametime);
                currenttime = newtime;
-               if (crouch)
-               {
-                       playermins = cl_playercrouchmins;
-                       playermaxs = cl_playercrouchmaxs;
-               }
-               else
-               {
-                       playermins = cl_playerstandmins;
-                       playermaxs = cl_playerstandmaxs;
-               }
-               for (bump = 0, t = frametime;bump < 8 && VectorLength2(currentvelocity) > 0;bump++)
-               {
-                       VectorMA(currentorigin, t, currentvelocity, neworigin);
-                       trace = CL_TraceBox(currentorigin, playermins, playermaxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
-                       if (trace.fraction < 1 && trace.plane.normal[2] == 0)
-                       {
-                               // may be a step or wall, try stepping up
-                               // first move forward at a higher level
-                               VectorSet(currentorigin2, currentorigin[0], currentorigin[1], currentorigin[2] + cl_movement_stepheight.value);
-                               VectorSet(neworigin2, neworigin[0], neworigin[1], currentorigin[2] + cl_movement_stepheight.value);
-                               trace2 = CL_TraceBox(currentorigin2, playermins, playermaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
-                               // then move down from there
-                               VectorCopy(trace2.endpos, currentorigin2);
-                               VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], currentorigin[2]);
-                               trace3 = CL_TraceBox(currentorigin2, playermins, playermaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
-                               //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
-                               // accept the new trace if it made some progress
-                               if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
-                               {
-                                       trace = trace2;
-                                       VectorCopy(trace3.endpos, trace.endpos);
-                               }
-                       }
-                       if (trace.fraction == 1)
-                       {
-                               VectorCopy(trace.endpos, currentorigin);
-                               break;
-                       }
-                       t *= 1 - trace.fraction;
-                       if (trace.fraction >= 0.001)
-                               VectorCopy(trace.endpos, currentorigin);
-                       f = DotProduct(currentvelocity, trace.plane.normal);
-                       VectorMA(currentvelocity, -f, trace.plane.normal, currentvelocity);
-               }
-               if (i < cl.movement_numqueue)
+               if (i >= 1 && i <= cl.movement_numqueue)
+               if (i > 0 || (cl_movement.integer & 8))
+               if (i < cl.movement_numqueue - 1 || (cl_movement.integer & 16))
                {
+                       client_movementqueue_t *q = cl.movement_queue + i - 1;
                        if (q->crouch)
                        {
                                // wants to crouch, this always works...
@@ -538,6 +516,16 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                                                crouch = false;
                                }
                        }
+                       if (crouch)
+                       {
+                               playermins = cl_playercrouchmins;
+                               playermaxs = cl_playercrouchmaxs;
+                       }
+                       else
+                       {
+                               playermins = cl_playerstandmins;
+                               playermaxs = cl_playerstandmaxs;
+                       }
                        // change velocity according to q->viewangles and q->move
                        contents = CL_PointSuperContents(currentorigin);
                        if (contents & SUPERCONTENTS_LIQUIDSMASK)
@@ -601,7 +589,7 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch)
                                                VectorSet(currentorigin2, currentorigin[0] + currentvelocity[0]*(16/f), currentorigin[1] + currentvelocity[1]*(16/f), currentorigin[2] + playermins[2]);
                                                VectorSet(neworigin2, currentorigin2[0], currentorigin2[1], currentorigin2[2] - 34);
                                                trace = CL_TraceBox(currentorigin2, vec3_origin, vec3_origin, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
-                                               if (trace.fraction < 1)
+                                               if (trace.fraction == 1)
                                                        edgefriction = cl_movement_edgefriction.value;
                                        }
                                        // apply friction
@@ -626,12 +614,60 @@ 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 (crouch)
+                       {
+                               playermins = cl_playercrouchmins;
+                               playermaxs = cl_playercrouchmaxs;
+                       }
+                       else
+                       {
+                               playermins = cl_playerstandmins;
+                               playermaxs = cl_playerstandmaxs;
+                       }
+                       for (bump = 0, t = frametime;bump < 8 && VectorLength2(currentvelocity) > 0;bump++)
+                       {
+                               VectorMA(currentorigin, t, currentvelocity, neworigin);
+                               trace = CL_TraceBox(currentorigin, playermins, playermaxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
+                               if (trace.fraction < 1 && trace.plane.normal[2] == 0)
+                               {
+                                       // may be a step or wall, try stepping up
+                                       // first move forward at a higher level
+                                       VectorSet(currentorigin2, currentorigin[0], currentorigin[1], currentorigin[2] + cl_movement_stepheight.value);
+                                       VectorSet(neworigin2, neworigin[0], neworigin[1], currentorigin[2] + cl_movement_stepheight.value);
+                                       trace2 = CL_TraceBox(currentorigin2, playermins, playermaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
+                                       // then move down from there
+                                       VectorCopy(trace2.endpos, currentorigin2);
+                                       VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], currentorigin[2]);
+                                       trace3 = CL_TraceBox(currentorigin2, playermins, playermaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true);
+                                       //Con_Printf("%f %f %f %f : %f %f %f %f : %f %f %f %f\n", trace.fraction, trace.endpos[0], trace.endpos[1], trace.endpos[2], trace2.fraction, trace2.endpos[0], trace2.endpos[1], trace2.endpos[2], trace3.fraction, trace3.endpos[0], trace3.endpos[1], trace3.endpos[2]);
+                                       // accept the new trace if it made some progress
+                                       if (fabs(trace3.endpos[0] - trace.endpos[0]) >= 0.03125 || fabs(trace3.endpos[1] - trace.endpos[1]) >= 0.03125)
+                                       {
+                                               trace = trace2;
+                                               VectorCopy(trace3.endpos, trace.endpos);
+                                       }
+                               }
+                               if (trace.fraction == 1)
+                               {
+                                       VectorCopy(trace.endpos, currentorigin);
+                                       break;
+                               }
+                               t *= 1 - trace.fraction;
+                               if (trace.fraction >= 0.001)
+                                       VectorCopy(trace.endpos, currentorigin);
+                               f = DotProduct(currentvelocity, trace.plane.normal);
+                               VectorMA(currentvelocity, -f, trace.plane.normal, currentvelocity);
+                       }
+               }
        }
        //Con_Printf(" :%f\n", currenttime);
        // store replay location
-       cl.movement = true;
        VectorCopy(cl.movement_origin, cl.movement_oldorigin);
        VectorCopy(currentorigin, cl.movement_origin);
+       VectorCopy(currentvelocity, cl.movement_velocity);
        //VectorCopy(currentorigin, cl_entities[cl.playerentity].state_current.origin);
        //VectorSet(cl_entities[cl.playerentity].state_current.angles, 0, cl.viewangles[1], 0);
 }
index cbdd0d1..a5e9f2c 100644 (file)
--- a/client.h
+++ b/client.h
@@ -518,9 +518,10 @@ typedef struct
        // client movement simulation
        // these fields are only updated by CL_ClientMovement (called by CL_SendMove after parsing each network packet)
        qboolean movement;
-       // simulated origin
+       // simulated data (this is valid even if cl.movement is false)
        vec3_t movement_origin;
        vec3_t movement_oldorigin;
+       vec3_t movement_velocity;
        // queue of proposed moves
        int movement_numqueue;
        client_movementqueue_t movement_queue[256];
diff --git a/view.c b/view.c
index b1e2a98..7b1ca6d 100644 (file)
--- a/view.c
+++ b/view.c
@@ -388,7 +388,7 @@ void V_CalcRefdef (void)
                                if (cl.stats[STAT_HEALTH] <= 0 && gamemode != GAME_FNIGGIUM)
                                        viewangles[ROLL] = 80;  // dead view angle
                                VectorAdd(viewangles, cl.punchangle, viewangles);
-                               viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.velocity);
+                               viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.movement_velocity);
                                if (v_dmg_time > 0)
                                {
                                        viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
@@ -413,7 +413,7 @@ void V_CalcRefdef (void)
                                                cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
                                        // bob is proportional to velocity in the xy plane
                                        // (don't count Z, or jumping messes it up)
-                                       bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value;
+                                       bob = sqrt(cl.movement_velocity[0]*cl.movement_velocity[0] + cl.movement_velocity[1]*cl.movement_velocity[1]) * cl_bob.value;
                                        bob = bob*0.3 + bob*0.7*cycle;
                                        vieworg[2] += bound(-7, bob, 4);
                                }