now sends player physics variables as stats, including slowmo, gravity,
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 7 May 2007 03:41:11 +0000 (03:41 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 7 May 2007 03:41:11 +0000 (03:41 +0000)
and sys_ticrate, this avoids the need to stuffcmd cl_movement cvars
on servers that provide the ticrate stat the cl_netinputpacketspersecond
cvar is no longer important, this also seems to improve demo recording

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

cl_input.c
cl_main.c
cl_parse.c
client.h
host.c
host_cmd.c
quakedef.h
server.h
sv_main.c
sv_user.c

index ad392f6..c5e1a37 100644 (file)
@@ -640,24 +640,6 @@ typedef struct cl_clientmovement_state_s
        // (this is in seconds and counts down to 0)
        float waterjumptime;
 
-       // movement parameters for physics code
-       float movevars_gravity;
-       float movevars_stopspeed;
-       float movevars_maxspeed;
-       float movevars_spectatormaxspeed;
-       float movevars_accelerate;
-       float movevars_airaccelerate;
-       float movevars_wateraccelerate;
-       float movevars_friction;
-       float movevars_waterfriction;
-       float movevars_entgravity;
-       float movevars_jumpvelocity;
-       float movevars_edgefriction;
-       float movevars_maxairspeed;
-       float movevars_stepheight;
-       float movevars_airaccel_qw;
-       float movevars_airaccel_sideways_friction;
-
        // user command
        client_movementqueue_t q;
 }
@@ -791,8 +773,8 @@ void CL_ClientMovement_Move(cl_clientmovement_state_t *s)
                {
                        // may be a step or wall, try stepping up
                        // first move forward at a higher level
-                       VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + s->movevars_stepheight);
-                       VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + s->movevars_stepheight);
+                       VectorSet(currentorigin2, s->origin[0], s->origin[1], s->origin[2] + cl.movevars_stepheight);
+                       VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + cl.movevars_stepheight);
                        trace2 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (!trace2.startsolid)
                        {
@@ -886,7 +868,7 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
                VectorScale(wishvel, 1 / wishspeed, wishdir);
        else
                VectorSet( wishdir, 0.0, 0.0, 0.0 );
-       wishspeed = min(wishspeed, s->movevars_maxspeed) * 0.7;
+       wishspeed = min(wishspeed, cl.movevars_maxspeed) * 0.7;
 
        if (s->crouched)
                wishspeed *= 0.5;
@@ -894,7 +876,7 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
        if (s->waterjumptime <= 0)
        {
                // water friction
-               f = 1 - s->q.frametime * s->movevars_waterfriction * s->waterlevel;
+               f = 1 - s->q.frametime * cl.movevars_waterfriction * s->waterlevel;
                f = bound(0, f, 1);
                VectorScale(s->velocity, f, s->velocity);
 
@@ -902,7 +884,7 @@ void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s)
                f = wishspeed - DotProduct(s->velocity, wishdir);
                if (f > 0)
                {
-                       f = min(s->movevars_wateraccelerate * s->q.frametime * wishspeed, f);
+                       f = min(cl.movevars_wateraccelerate * s->q.frametime * wishspeed, f);
                        VectorMA(s->velocity, f, wishdir, s->velocity);
                }
 
@@ -947,7 +929,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
        {
                if (s->onground && s->q.canjump)
                {
-                       s->velocity[2] += s->movevars_jumpvelocity;
+                       s->velocity[2] += cl.movevars_jumpvelocity;
                        s->onground = false;
                        s->q.canjump = false;
                }
@@ -966,7 +948,7 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                VectorScale(wishvel, 1 / wishspeed, wishdir);
        else
                VectorSet( wishdir, 0.0, 0.0, 0.0 );
-       wishspeed = min(wishspeed, s->movevars_maxspeed);
+       wishspeed = min(wishspeed, cl.movevars_maxspeed);
        if (s->crouched)
                wishspeed *= 0.5;
 
@@ -975,8 +957,8 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
        {
                // apply edge friction
                f = sqrt(s->velocity[0] * s->velocity[0] + s->velocity[1] * s->velocity[1]);
-               friction = s->movevars_friction;
-               if (f > 0 && s->movevars_edgefriction != 1)
+               friction = cl.movevars_friction;
+               if (f > 0 && cl.movevars_edgefriction != 1)
                {
                        vec3_t neworigin2;
                        vec3_t neworigin3;
@@ -990,16 +972,16 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                        else
                                trace = CL_Move(neworigin2, vec3_origin, vec3_origin, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
                        if (trace.fraction == 1 && !trace.startsolid)
-                               friction *= s->movevars_edgefriction;
+                               friction *= cl.movevars_edgefriction;
                }
                // apply ground friction
-               f = 1 - s->q.frametime * friction * ((f < s->movevars_stopspeed) ? (s->movevars_stopspeed / f) : 1);
+               f = 1 - s->q.frametime * friction * ((f < cl.movevars_stopspeed) ? (cl.movevars_stopspeed / f) : 1);
                f = max(f, 0);
                VectorScale(s->velocity, f, s->velocity);
                addspeed = wishspeed - DotProduct(s->velocity, wishdir);
                if (addspeed > 0)
                {
-                       accelspeed = min(s->movevars_accelerate * s->q.frametime * wishspeed, addspeed);
+                       accelspeed = min(cl.movevars_accelerate * s->q.frametime * wishspeed, addspeed);
                        VectorMA(s->velocity, accelspeed, wishdir, s->velocity);
                }
                s->velocity[2] -= cl_gravity.value * s->q.frametime;
@@ -1018,13 +1000,13 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
                        vec3_t vel_perpend;
 
                        // apply air speed limit
-                       wishspeed = min(wishspeed, s->movevars_maxairspeed);
+                       wishspeed = min(wishspeed, cl.movevars_maxairspeed);
 
                        /*
                        addspeed = wishspeed - DotProduct(s->velocity, wishdir);
                        if (addspeed > 0)
                        {
-                               accelspeed = min(s->movevars_accelerate * s->q.frametime * wishspeed, addspeed);
+                               accelspeed = min(cl.movevars_accelerate * s->q.frametime * wishspeed, addspeed);
                                VectorMA(s->velocity, accelspeed, wishdir, s->velocity);
                        }
                        */
@@ -1036,11 +1018,11 @@ void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s)
 
                        f = wishspeed - vel_straight;
                        if(f > 0)
-                               vel_straight += min(f, s->movevars_accelerate * s->q.frametime * wishspeed) * s->movevars_airaccel_qw;
+                               vel_straight += min(f, cl.movevars_accelerate * s->q.frametime * wishspeed) * cl.movevars_airaccel_qw;
                        if(wishspeed > 0)
-                               vel_straight += min(wishspeed, s->movevars_accelerate * s->q.frametime * wishspeed) * (1 - s->movevars_airaccel_qw);
+                               vel_straight += min(wishspeed, cl.movevars_accelerate * s->q.frametime * wishspeed) * (1 - cl.movevars_airaccel_qw);
 
-                       VectorM(1 - (s->q.frametime * (wishspeed / s->movevars_maxairspeed) * s->movevars_airaccel_sideways_friction), vel_perpend, vel_perpend);
+                       VectorM(1 - (s->q.frametime * (wishspeed / cl.movevars_maxairspeed) * cl.movevars_airaccel_sideways_friction), vel_perpend, vel_perpend);
 
                        VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
                        s->velocity[2] += vel_z;
@@ -1063,6 +1045,53 @@ void CL_ClientMovement_PlayerMove(cl_clientmovement_state_t *s)
                CL_ClientMovement_Physics_Walk(s);
 }
 
+extern cvar_t slowmo;
+void CL_UpdateMoveVars(void)
+{
+       if (cls.protocol == PROTOCOL_QUAKEWORLD)
+               cl.movevars_ticrate = 1.0 / bound(1, cl_netinputpacketspersecond.value, 100);
+       else if (cl.stats[STAT_MOVEVARS_TICRATE])
+       {
+               cl.movevars_ticrate = cl.statsf[STAT_MOVEVARS_TICRATE];
+               cl.movevars_slowmo = cl.statsf[STAT_MOVEVARS_TIMESCALE];
+               cl.movevars_gravity = cl.statsf[STAT_MOVEVARS_GRAVITY];
+               cl.movevars_stopspeed = cl.statsf[STAT_MOVEVARS_STOPSPEED] ;
+               cl.movevars_maxspeed = cl.statsf[STAT_MOVEVARS_MAXSPEED];
+               cl.movevars_spectatormaxspeed = cl.statsf[STAT_MOVEVARS_SPECTATORMAXSPEED];
+               cl.movevars_accelerate = cl.statsf[STAT_MOVEVARS_ACCELERATE];
+               cl.movevars_airaccelerate = cl.statsf[STAT_MOVEVARS_AIRACCELERATE];
+               cl.movevars_wateraccelerate = cl.statsf[STAT_MOVEVARS_WATERACCELERATE];
+               cl.movevars_entgravity = cl.statsf[STAT_MOVEVARS_ENTGRAVITY];
+               cl.movevars_jumpvelocity = cl.statsf[STAT_MOVEVARS_JUMPVELOCITY];
+               cl.movevars_edgefriction = cl.statsf[STAT_MOVEVARS_EDGEFRICTION];
+               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_sideways_friction = cl.statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION];
+       }
+       else
+       {
+               cl.movevars_ticrate = 1.0 / bound(1, cl_netinputpacketspersecond.value, 100);
+               cl.movevars_slowmo = slowmo.value;
+               cl.movevars_gravity = sv_gravity.value;
+               cl.movevars_stopspeed = cl_movement_stopspeed.value;
+               cl.movevars_maxspeed = cl_movement_maxspeed.value;
+               cl.movevars_spectatormaxspeed = cl_movement_maxspeed.value;
+               cl.movevars_accelerate = cl_movement_accelerate.value;
+               cl.movevars_airaccelerate = cl_movement_airaccelerate.value < 0 ? cl_movement_accelerate.value : cl_movement_airaccelerate.value;
+               cl.movevars_wateraccelerate = cl_movement_wateraccelerate.value < 0 ? cl_movement_accelerate.value : cl_movement_wateraccelerate.value;
+               cl.movevars_friction = cl_movement_friction.value;
+               cl.movevars_waterfriction = cl_movement_waterfriction.value < 0 ? cl_movement_friction.value : cl_movement_waterfriction.value;
+               cl.movevars_entgravity = 1;
+               cl.movevars_jumpvelocity = cl_movement_jumpvelocity.value;
+               cl.movevars_edgefriction = cl_movement_edgefriction.value;
+               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_sideways_friction = cl_movement_airaccel_sideways_friction.value;
+       }
+}
+
 void CL_ClientMovement_Replay(void)
 {
        int i;
@@ -1079,46 +1108,6 @@ void CL_ClientMovement_Replay(void)
        s.crouched = true; // will be updated on first move
        //Con_Printf("movement replay starting org %f %f %f vel %f %f %f\n", s.origin[0], s.origin[1], s.origin[2], s.velocity[0], s.velocity[1], s.velocity[2]);
 
-       // set up movement variables
-       if (cls.protocol == PROTOCOL_QUAKEWORLD)
-       {
-               s.movevars_gravity = cl.qw_movevars_gravity;
-               s.movevars_stopspeed = cl.qw_movevars_stopspeed;
-               s.movevars_maxspeed = cl.qw_movevars_maxspeed;
-               s.movevars_spectatormaxspeed = cl.qw_movevars_spectatormaxspeed;
-               s.movevars_accelerate = cl.qw_movevars_accelerate;
-               s.movevars_airaccelerate = cl.qw_movevars_airaccelerate;
-               s.movevars_wateraccelerate = cl.qw_movevars_wateraccelerate;
-               s.movevars_friction = cl.qw_movevars_friction;
-               s.movevars_waterfriction = cl.qw_movevars_waterfriction;
-               s.movevars_entgravity = cl.qw_movevars_entgravity;
-               s.movevars_jumpvelocity = cl_movement_jumpvelocity.value;
-               s.movevars_edgefriction = cl_movement_edgefriction.value;
-               s.movevars_maxairspeed = cl_movement_maxairspeed.value;
-               s.movevars_stepheight = cl_movement_stepheight.value;
-               s.movevars_airaccel_qw = 1.0;
-               s.movevars_airaccel_sideways_friction = 0.0;
-       }
-       else
-       {
-               s.movevars_gravity = sv_gravity.value;
-               s.movevars_stopspeed = cl_movement_stopspeed.value;
-               s.movevars_maxspeed = cl_movement_maxspeed.value;
-               s.movevars_spectatormaxspeed = cl_movement_maxspeed.value;
-               s.movevars_accelerate = cl_movement_accelerate.value;
-               s.movevars_airaccelerate = cl_movement_airaccelerate.value < 0 ? cl_movement_accelerate.value : cl_movement_airaccelerate.value;
-               s.movevars_wateraccelerate = cl_movement_wateraccelerate.value < 0 ? cl_movement_accelerate.value : cl_movement_wateraccelerate.value;
-               s.movevars_friction = cl_movement_friction.value;
-               s.movevars_waterfriction = cl_movement_waterfriction.value < 0 ? cl_movement_friction.value : cl_movement_waterfriction.value;
-               s.movevars_entgravity = 1;
-               s.movevars_jumpvelocity = cl_movement_jumpvelocity.value;
-               s.movevars_edgefriction = cl_movement_edgefriction.value;
-               s.movevars_maxairspeed = cl_movement_maxairspeed.value;
-               s.movevars_stepheight = cl_movement_stepheight.value;
-               s.movevars_airaccel_qw = cl_movement_airaccel_qw.value;
-               s.movevars_airaccel_sideways_friction = cl_movement_airaccel_sideways_friction.value;
-       }
-
        totalmovetime = 0;
        for (i = 0;i < cl.movement_numqueue - 1;i++)
                totalmovetime += cl.movement_queue[i].frametime;
@@ -1268,10 +1257,7 @@ void CL_SendMove(void)
                return;
 
        // don't send too often or else network connections can get clogged by a high renderer framerate
-       if (cl_netinputpacketspersecond.value >= 1)
-               packettime = 1.0 / bound(1, cl_netinputpacketspersecond.value, 1000);
-       else
-               packettime = 0;
+       packettime = cl.movevars_ticrate;
        // quakeworld servers take only frametimes
        // predicted dp7 servers take current interpolation time
        // unpredicted servers take an echo of the latest server timestamp
index 994fe16..d07b186 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -110,6 +110,9 @@ void CL_ClearState(void)
        // reset the view zoom interpolation
        cl.mviewzoom[0] = cl.mviewzoom[1] = 1;
 
+       // set up the float version of the stats array for easier access to float stats
+       cl.statsf = (float *)cl.stats;
+
        cl.num_entities = 0;
        cl.num_static_entities = 0;
        cl.num_temp_entities = 0;
index c77cd25..0542b58 100644 (file)
@@ -1419,16 +1419,24 @@ void CL_ParseServerInfo (void)
                strlcpy (cl.levelname, str, sizeof(cl.levelname));
 
                // get the movevars
-               cl.qw_movevars_gravity            = MSG_ReadFloat();
-               cl.qw_movevars_stopspeed          = MSG_ReadFloat();
-               cl.qw_movevars_maxspeed           = MSG_ReadFloat();
-               cl.qw_movevars_spectatormaxspeed  = MSG_ReadFloat();
-               cl.qw_movevars_accelerate         = MSG_ReadFloat();
-               cl.qw_movevars_airaccelerate      = MSG_ReadFloat();
-               cl.qw_movevars_wateraccelerate    = MSG_ReadFloat();
-               cl.qw_movevars_friction           = MSG_ReadFloat();
-               cl.qw_movevars_waterfriction      = MSG_ReadFloat();
-               cl.qw_movevars_entgravity         = MSG_ReadFloat();
+               cl.movevars_gravity            = MSG_ReadFloat();
+               cl.movevars_stopspeed          = MSG_ReadFloat();
+               cl.movevars_maxspeed           = MSG_ReadFloat();
+               cl.movevars_spectatormaxspeed  = MSG_ReadFloat();
+               cl.movevars_accelerate         = MSG_ReadFloat();
+               cl.movevars_airaccelerate      = MSG_ReadFloat();
+               cl.movevars_wateraccelerate    = MSG_ReadFloat();
+               cl.movevars_friction           = MSG_ReadFloat();
+               cl.movevars_waterfriction      = MSG_ReadFloat();
+               cl.movevars_entgravity         = MSG_ReadFloat();
+               // other movevars not in the protocol...
+               cl.movevars_slowmo = 1;
+               cl.movevars_jumpvelocity = 270;
+               cl.movevars_edgefriction = 2;
+               cl.movevars_maxairspeed = 30;
+               cl.movevars_stepheight = 18;
+               cl.movevars_airaccel_qw = 1.0;
+               cl.movevars_airaccel_sideways_friction = 0.0;
 
                // seperate the printfs so the server message can have a color
                Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n\2%s\n", str);
@@ -2857,9 +2865,9 @@ static void CL_NetworkTimeReceived(double newtime)
                        else if (fabs(cl.time - cl.mtime[1]) > 0.1)
                                cl.time += 0.5 * (cl.mtime[1] - cl.time); // fast
                        else if (cl.time > cl.mtime[1])
-                               cl.time -= 0.002 * slowmo.value; // fall into the past by 2ms
+                               cl.time -= 0.002 * cl.movevars_slowmo; // fall into the past by 2ms
                        else
-                               cl.time += 0.001 * slowmo.value; // creep forward 1ms
+                               cl.time += 0.001 * cl.movevars_slowmo; // creep forward 1ms
                }
        }
        // this packet probably contains a player entity update, so we will need
@@ -2892,6 +2900,7 @@ CL_ParseServerMessage
 =====================
 */
 int parsingerror = false;
+extern void CL_UpdateMoveVars(void);
 void CL_ParseServerMessage(void)
 {
        int                     cmd;
@@ -3241,11 +3250,11 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case qw_svc_maxspeed:
-                               cl.qw_movevars_maxspeed = MSG_ReadFloat();
+                               cl.movevars_maxspeed = MSG_ReadFloat();
                                break;
 
                        case qw_svc_entgravity:
-                               cl.qw_movevars_entgravity = MSG_ReadFloat();
+                               cl.movevars_entgravity = MSG_ReadFloat();
                                break;
 
                        case qw_svc_setpause:
@@ -3695,6 +3704,8 @@ void CL_ParseServerMessage(void)
 
        EntityFrameQuake_ISeeDeadEntities();
 
+       CL_UpdateMoveVars();
+
        parsingerror = false;
 
        // LordHavoc: this was at the start of the function before cl_autodemo was
index 139ac55..8f37000 100644 (file)
--- a/client.h
+++ b/client.h
@@ -691,6 +691,7 @@ typedef struct client_state_s
 // information for local display
        // health, etc
        int stats[MAX_CL_STATS];
+       float *statsf; // points to stats[] array
        // last known inventory bit flags, for blinking
        int olditems;
        // cl.time of acquiring item, for blinking
@@ -942,16 +943,24 @@ typedef struct client_state_s
        //qboolean qw_spectator;
 
        // movement parameters for client prediction
-       float qw_movevars_gravity;
-       float qw_movevars_stopspeed;
-       float qw_movevars_maxspeed; // can change during play
-       float qw_movevars_spectatormaxspeed;
-       float qw_movevars_accelerate;
-       float qw_movevars_airaccelerate;
-       float qw_movevars_wateraccelerate;
-       float qw_movevars_friction;
-       float qw_movevars_waterfriction;
-       float qw_movevars_entgravity; // can change during play
+       float movevars_ticrate;
+       float movevars_slowmo;
+       float movevars_gravity;
+       float movevars_stopspeed;
+       float movevars_maxspeed;
+       float movevars_spectatormaxspeed;
+       float movevars_accelerate;
+       float movevars_airaccelerate;
+       float movevars_wateraccelerate;
+       float movevars_friction;
+       float movevars_waterfriction;
+       float movevars_entgravity;
+       float movevars_jumpvelocity;
+       float movevars_edgefriction;
+       float movevars_maxairspeed;
+       float movevars_stepheight;
+       float movevars_airaccel_qw;
+       float movevars_airaccel_sideways_friction;
 
        // models used by qw protocol
        int qw_modelindex_spike;
diff --git a/host.c b/host.c
index 735905c..637c2be 100644 (file)
--- a/host.c
+++ b/host.c
@@ -771,7 +771,7 @@ void Host_Main(void)
                                clframetime = cl.realframetime = 0.1;
 
                        // apply slowmo scaling
-                       clframetime *= slowmo.value;
+                       clframetime *= cl.movevars_slowmo;
 
                        // host_framerate overrides all else
                        if (host_framerate.value)
index 9564788..20b0a9a 100644 (file)
@@ -697,7 +697,6 @@ void Host_Loadgame_f (void)
                                Host_Error("Host_PerformLoadGame: too many edicts in save file (reached MAX_EDICTS %i)", MAX_EDICTS);
                        }
                        while (entnum >= prog->max_edicts)
-                               //SV_IncreaseEdicts();
                                PRVM_MEM_IncreaseEdicts();
                        ent = PRVM_EDICT_NUM(entnum);
                        memset (ent->fields.server, 0, prog->progs->entityfields * 4);
index 936ec17..fed34ab 100644 (file)
@@ -94,6 +94,22 @@ extern char engineversion[128];
 //#define STAT_TIME                    17 // FTE
 //#define STAT_VIEW2           20 // FTE
 #define STAT_VIEWZOOM          21 // DP
+#define STAT_MOVEVARS_TICRATE                                          240 // DP
+#define STAT_MOVEVARS_TIMESCALE                                                241 // DP
+#define STAT_MOVEVARS_GRAVITY                                          242 // DP
+#define STAT_MOVEVARS_STOPSPEED                                                243 // DP
+#define STAT_MOVEVARS_MAXSPEED                                         244 // DP
+#define STAT_MOVEVARS_SPECTATORMAXSPEED                                245 // DP
+#define STAT_MOVEVARS_ACCELERATE                                       246 // DP
+#define STAT_MOVEVARS_AIRACCELERATE                                    247 // DP
+#define STAT_MOVEVARS_WATERACCELERATE                          248 // DP
+#define STAT_MOVEVARS_ENTGRAVITY                                       249 // DP
+#define STAT_MOVEVARS_JUMPVELOCITY                                     250 // DP
+#define STAT_MOVEVARS_EDGEFRICTION                                     251 // DP
+#define STAT_MOVEVARS_MAXAIRSPEED                                      252 // DP
+#define STAT_MOVEVARS_STEPHEIGHT                                       253 // DP
+#define STAT_MOVEVARS_AIRACCEL_QW                                      254 // DP
+#define STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION       255 // DP
 
 // stock defines
 
index 0eda633..34c9585 100644 (file)
--- a/server.h
+++ b/server.h
@@ -294,6 +294,9 @@ extern cvar_t sv_maxairspeed;
 extern cvar_t sv_accelerate;
 extern cvar_t sv_airaccelerate;
 extern cvar_t sv_wateraccelerate;
+extern cvar_t sv_jumpvelocity;
+extern cvar_t sv_airaccel_qw;
+extern cvar_t sv_airaccel_sideways_friction;
 extern cvar_t sv_idealpitchscale;
 extern cvar_t sv_aim;
 extern cvar_t sv_stepheight;
index 7b89111..73d2edd 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -123,6 +123,9 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_accelerate);
        Cvar_RegisterVariable (&sv_airaccelerate);
        Cvar_RegisterVariable (&sv_wateraccelerate);
+       Cvar_RegisterVariable (&sv_jumpvelocity);
+       Cvar_RegisterVariable (&sv_airaccel_qw);
+       Cvar_RegisterVariable (&sv_airaccel_sideways_friction);
        Cvar_RegisterVariable (&sv_clmovement_enable);
        Cvar_RegisterVariable (&sv_clmovement_minping);
        Cvar_RegisterVariable (&sv_clmovement_minping_disabletime);
@@ -1078,6 +1081,8 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        vec3_t  punchvector;
        int             viewzoom;
        const char *s;
+       float   *statsf = (float *)stats;
+extern cvar_t slowmo;
 
 //
 // send a damage message
@@ -1188,6 +1193,25 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        //stats[STAT_SECRETS] = prog->globals.server->found_secrets;
        //stats[STAT_MONSTERS] = prog->globals.server->killed_monsters;
 
+       // movement settings for prediction
+       statsf[STAT_MOVEVARS_TICRATE] = sys_ticrate.value;
+       statsf[STAT_MOVEVARS_TIMESCALE] = slowmo.value;
+       statsf[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
+       statsf[STAT_MOVEVARS_STOPSPEED] = sv_stopspeed.value;
+       statsf[STAT_MOVEVARS_MAXSPEED] = sv_maxspeed.value;
+       statsf[STAT_MOVEVARS_SPECTATORMAXSPEED] = sv_maxspeed.value; // FIXME: QW has a separate cvar for this
+       statsf[STAT_MOVEVARS_ACCELERATE] = sv_accelerate.value;
+       statsf[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value >= 0 ? sv_airaccelerate.value : sv_accelerate.value;
+       statsf[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value >= 0 ? sv_wateraccelerate.value : sv_accelerate.value;
+       val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.gravity);
+       statsf[STAT_MOVEVARS_ENTGRAVITY] = val ? val->_float : 1.0f;
+       statsf[STAT_MOVEVARS_JUMPVELOCITY] = sv_jumpvelocity.value;
+       statsf[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
+       statsf[STAT_MOVEVARS_MAXAIRSPEED] = sv_maxairspeed.value;
+       statsf[STAT_MOVEVARS_STEPHEIGHT] = sv_stepheight.value;
+       statsf[STAT_MOVEVARS_AIRACCEL_QW] = sv_airaccel_qw.value;
+       statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_airaccel_sideways_friction.value;
+
        if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
        {
                if (stats[STAT_VIEWHEIGHT] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT;
index f00cc3a..df8e90e 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // sv_user.c -- server code for moving users
 
 #include "quakedef.h"
+#define DEBUGMOVES 0
 
 cvar_t sv_edgefriction = {0, "edgefriction", "2", "how much you slow down when nearing a ledge you might fall off"};
 cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"};
@@ -28,6 +29,9 @@ cvar_t sv_maxairspeed = {0, "sv_maxairspeed", "30", "maximum speed a player can
 cvar_t sv_accelerate = {0, "sv_accelerate", "10", "rate at which a player accelerates to sv_maxspeed"};
 cvar_t sv_airaccelerate = {0, "sv_airaccelerate", "-1", "rate at which a player accelerates to sv_maxairspeed while in the air, if less than 0 the sv_accelerate variable is used instead"};
 cvar_t sv_wateraccelerate = {0, "sv_wateraccelerate", "-1", "rate at which a player accelerates to sv_maxspeed while in the air, if less than 0 the sv_accelerate variable is used instead"};
+cvar_t sv_jumpvelocity = {0, "sv_jumpvelocity", "270", "cvar that can be used by QuakeC code for jump velocity"};
+cvar_t sv_airaccel_qw = {0, "sv_airaccelerate", "1", "ratio of QW-style air control as opposed to simple acceleration"};
+cvar_t sv_airaccel_sideways_friction = {0, "sv_airaccelerate", "", "anti-sideways movement stabilization (reduces speed gain when zigzagging)"};
 cvar_t sv_clmovement_enable = {0, "sv_clmovement_enable", "1", "whether to allow clients to use cl_movement prediction, which can cause choppy movement on the server which may annoy other players"};
 cvar_t sv_clmovement_minping = {0, "sv_clmovement_minping", "0", "if client ping is below this time in milliseconds, then their ability to use cl_movement prediction is disabled for a while (as they don't need it)"};
 cvar_t sv_clmovement_minping_disabletime = {0, "sv_clmovement_minping_disabletime", "1000", "when client falls below minping, disable their prediction for this many milliseconds (should be at least 1000 or else their prediction may turn on/off frequently)"};