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)"};
cvar_t cl_movement_friction = {0, "cl_movement_friction", "4", "how fast you slow down (should match sv_friction)"};
+cvar_t cl_movement_waterfriction = {0, "cl_movement_waterfriction", "-1", "how fast you slow down (should match sv_friction), if less than 0 the cl_movement_friction variable is used instead"};
cvar_t cl_movement_edgefriction = {0, "cl_movement_edgefriction", "2", "how much to slow down when you may be about to fall off a ledge (should match edgefriction)"};
cvar_t cl_movement_stepheight = {0, "cl_movement_stepheight", "18", "how tall a step you can step in one instant (should match sv_stepheight)"};
cvar_t cl_movement_accelerate = {0, "cl_movement_accelerate", "10", "how fast you accelerate (should match sv_accelerate)"};
+cvar_t cl_movement_airaccelerate = {0, "cl_movement_airaccelerate", "-1", "how fast you accelerate while in the air (should match sv_airaccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
+cvar_t cl_movement_wateraccelerate = {0, "cl_movement_wateraccelerate", "-1", "how fast you accelerate while in the air (should match sv_airaccelerate), if less than 0 the cl_movement_accelerate variable is used instead"};
cvar_t cl_movement_jumpvelocity = {0, "cl_movement_jumpvelocity", "270", "how fast you move upward when you begin a jump (should match the quakec code)"};
+cvar_t cl_movement_airaccel_qw = {0, "cl_movement_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration (should match sv_airaccel_qw)"};
+cvar_t cl_movement_airaccel_sideways_friction = {0, "cl_movement_airaccel_sideways_friction", "0", "anti-sideways movement stabilization (should match sv_airaccel_sideways_friction)"};
cvar_t cl_gravity = {0, "cl_gravity", "800", "how much gravity to apply in client physics (should match sv_gravity)"};
cvar_t cl_slowmo = {0, "cl_slowmo", "1", "speed of game time (should match slowmo)"};
n = cl.movement_numqueue;
cl.movement_numqueue = 0;
for (i = 0;i < n;i++)
+ {
if (cl.movement_queue[i].sequence > cls.netcon->qw.incoming_sequence)
cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+ else if (i == 0)
+ cl.movement_replay_canjump = !cl.movement_queue[i].jump; // FIXME: this logic is quite broken
+ }
// add to input queue if there is room
if (cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])))
{
{
int i;
int n;
- double lasttime = cl.movement_numqueue >= 0 ? cl.movement_queue[cl.movement_numqueue - 1].time : 0;
+ double lasttime = (cls.protocol == PROTOCOL_DARKPLACES6 || cls.protocol == PROTOCOL_DARKPLACES7) ? cl.mtime[1] : (cl.movement_numqueue >= 0 ? cl.movement_queue[cl.movement_numqueue - 1].time : 0);
// 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 if (i == 0)
+ cl.movement_replay_canjump = !cl.movement_queue[i].jump; // FIXME: this logic is quite broken
+ }
}
else
{
for (i = 0;i < n;i++)
+ {
if (cl.movement_queue[i].time >= cl.mtime[0] - cl_movement_latency.value / 1000.0 && cl.movement_queue[i].time <= cl.mtime[0])
cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+ else if (i == 0)
+ cl.movement_replay_canjump = !cl.movement_queue[i].jump; // FIXME: this logic is quite broken
+ }
}
// add to input queue if there is room
if (cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])) && cl.mtime[0] > cl.mtime[1])
float movevars_edgefriction;
float movevars_maxairspeed;
float movevars_stepheight;
+ float movevars_airaccel_qw;
+ float movevars_airaccel_sideways_friction;
// user command
client_movementqueue_t q;
// jump if on ground with jump button pressed but only if it has been
// released at least once since the last jump
- if (s->q.jump && s->canjump && s->onground)
+ if (s->q.jump && s->onground)// && s->canjump) // FIXME: canjump doesn't work properly
{
s->velocity[2] += s->movevars_jumpvelocity;
s->onground = false;
{
if (s->waterjumptime <= 0)
{
+ vec_t f;
+ vec_t vel_straight;
+ vec_t vel_z;
+ vec3_t vel_perpend;
+
// apply air speed limit
wishspeed = min(wishspeed, s->movevars_maxairspeed);
- // Nexuiz has no upper bound on air acceleration, but little control
- if (gamemode == GAME_NEXUIZ)
- addspeed = wishspeed;
- else
- addspeed = wishspeed - DotProduct(s->velocity, wishdir);
+
+ /*
+ addspeed = wishspeed - DotProduct(s->velocity, wishdir);
if (addspeed > 0)
{
accelspeed = min(s->movevars_accelerate * s->q.frametime * wishspeed, addspeed);
VectorMA(s->velocity, accelspeed, wishdir, s->velocity);
}
+ */
+
+ vel_straight = DotProduct(s->velocity, wishdir);
+ vel_z = s->velocity[2];
+ VectorMA(s->velocity, -vel_straight, wishdir, vel_perpend);
+ vel_perpend[2] -= vel_z;
+
+ f = wishspeed - vel_straight;
+ if(f > 0)
+ vel_straight += min(f, s->movevars_accelerate * s->q.frametime * wishspeed) * s->movevars_airaccel_qw;
+ if(wishspeed > 0)
+ vel_straight += min(wishspeed, s->movevars_accelerate * s->q.frametime * wishspeed) * (1 - s->movevars_airaccel_qw);
+
+ VectorM(1 - (s->q.frametime * (wishspeed / s->movevars_maxairspeed) * s->movevars_airaccel_sideways_friction), vel_perpend, vel_perpend);
+
+ VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
+ s->velocity[2] += vel_z;
}
s->velocity[2] -= cl_gravity.value * s->q.frametime;
CL_ClientMovement_Move(s);
VectorCopy(cl.entities[cl.playerentity].state_current.origin, s.origin);
VectorCopy(cl.mvelocity[0], s.velocity);
s.crouched = true; // will be updated on first move
- s.canjump = true;
+ s.canjump = cl.movement_replay_canjump;
// set up movement variables
if (cls.protocol == PROTOCOL_QUAKEWORLD)
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_maxspeed = cl_movement_maxspeed.value;
s.movevars_spectatormaxspeed = cl_movement_maxspeed.value;
s.movevars_accelerate = cl_movement_accelerate.value;
- s.movevars_airaccelerate = cl_movement_accelerate.value;
- s.movevars_wateraccelerate = 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_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;
}
- if (cl.movement)
+ cl.movement_predicted = (cl_movement.integer && cls.signon == SIGNONS && cl.stats[STAT_HEALTH] > 0 && !cl.intermission) && ((cls.protocol != PROTOCOL_DARKPLACES6 && cls.protocol != PROTOCOL_DARKPLACES7) || cl.servermovesequence);
+ if (cl.movement_predicted)
{
//Con_Printf("%f: ", cl.mtime[0]);
accumtotal++;
#endif
- cl.movement = cl_movement.integer && cls.signon == SIGNONS && cl.stats[STAT_HEALTH] > 0 && !cl.intermission;
if (cl_movement.integer && cls.signon == SIGNONS && cls.protocol != PROTOCOL_QUAKEWORLD)
{
if (!cl.movement_needupdate)
Cvar_RegisterVariable(&cl_movement_friction);
Cvar_RegisterVariable(&cl_movement_edgefriction);
Cvar_RegisterVariable(&cl_movement_stepheight);
+ Cvar_RegisterVariable(&cl_movement_airaccelerate);
Cvar_RegisterVariable(&cl_movement_accelerate);
Cvar_RegisterVariable(&cl_movement_jumpvelocity);
+ Cvar_RegisterVariable(&cl_movement_airaccel_qw);
+ Cvar_RegisterVariable(&cl_movement_airaccel_sideways_friction);
Cvar_RegisterVariable(&cl_gravity);
Cvar_RegisterVariable(&cl_slowmo);