cvar_t cl_anglespeedkey = {CVAR_SAVE, "cl_anglespeedkey","1.5","how much +speed multiplies keyboard turning speed"};
cvar_t cl_movement = {CVAR_SAVE, "cl_movement", "0", "enables clientside prediction of your player movement"};
+cvar_t cl_movement_replay = {0, "cl_movement_replay", "1", "use engine prediction"};
cvar_t cl_movement_nettimeout = {CVAR_SAVE, "cl_movement_nettimeout", "0.3", "stops predicting moves when server is lagging badly (avoids major performance problems), timeout in seconds"};
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"};
s->velocity[2] = 80;
else
{
- if (gamemode == GAME_NEXUIZ)
+ if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
s->velocity[2] = 200;
else
s->velocity[2] = 100;
bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1);
}
-void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t sidefric, vec_t speedlimit)
+void CL_ClientMovement_Physics_PM_Accelerate(cl_clientmovement_state_t *s, vec3_t wishdir, vec_t wishspeed, vec_t wishspeed0, vec_t accel, vec_t accelqw, vec_t stretchfactor, vec_t sidefric, vec_t speedlimit)
{
vec_t vel_straight;
vec_t vel_z;
vec3_t vel_xy;
vec_t vel_xy_current;
vec_t vel_xy_backward, vel_xy_forward;
- qboolean speedclamp;
+ vec_t speedclamp;
- speedclamp = (accelqw < 0);
- if(speedclamp)
+ if(stretchfactor > 0)
+ speedclamp = stretchfactor;
+ else if(accelqw < 0)
+ speedclamp = 1;
+ else
+ speedclamp = -1; // no clamping
+
+ if(accelqw < 0)
accelqw = -accelqw;
if(cl.moveflags & MOVEFLAG_Q2AIRACCELERATE)
VectorMA(vel_perpend, vel_straight, wishdir, s->velocity);
- if(speedclamp)
+ if(speedclamp >= 0)
{
- vel_xy_current = min(VectorLength(s->velocity), vel_xy_forward);
- if(vel_xy_current > 0) // prevent division by zero
+ vec_t vel_xy_preclamp;
+ vel_xy_preclamp = VectorLength(s->velocity);
+ if(vel_xy_preclamp > 0) // prevent division by zero
{
- VectorNormalize(s->velocity);
- VectorScale(s->velocity, vel_xy_current, s->velocity);
+ vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp;
+ if(vel_xy_current < vel_xy_preclamp)
+ VectorScale(s->velocity, (vel_xy_current / vel_xy_preclamp), s->velocity);
}
}
if (cls.protocol == PROTOCOL_QUAKEWORLD)
trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
else
- trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
+ trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false, false);
if (trace.fraction == 1 && !trace.startsolid)
friction *= cl.movevars_edgefriction;
}
if(cl.movevars_warsowbunny_turnaccel && accelerating && s->cmd.sidemove == 0 && s->cmd.forwardmove != 0)
CL_ClientMovement_Physics_PM_AirAccelerate(s, wishdir, wishspeed2);
else
- CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed, cl.movevars_airspeedlimit_nonqw);
+ CL_ClientMovement_Physics_PM_Accelerate(s, wishdir, wishspeed, wishspeed0, accel, accelqw, cl.movevars_airaccel_qw_stretchfactor, cl.movevars_airaccel_sideways_friction / cl.movevars_maxairspeed, cl.movevars_airspeedlimit_nonqw);
if(cl.movevars_aircontrol)
CL_ClientMovement_Physics_CPM_PM_Aircontrol(s, wishdir, wishspeed2);
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_qw_stretchfactor = cl.statsf[STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR];
cl.movevars_airaccel_sideways_friction = cl.statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION];
cl.movevars_friction = cl.statsf[STAT_MOVEVARS_FRICTION];
cl.movevars_wallfriction = cl.statsf[STAT_MOVEVARS_WALLFRICTION];
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_qw_stretchfactor = 0;
cl.movevars_airaccel_sideways_friction = cl_movement_airaccel_sideways_friction.value;
cl.movevars_airstopaccelerate = 0;
cl.movevars_airstrafeaccelerate = 0;
if (cl.movement_predicted && !cl.movement_replay)
return;
+ if (!cl_movement_replay.integer)
+ return;
+
// set up starting state for the series of moves
memset(&s, 0, sizeof(s));
VectorCopy(cl.entities[cl.playerentity].state_current.origin, s.origin);
cl.latestframenumsposition = (cl.latestframenumsposition + 1) % LATESTFRAMENUMS;
}
+void CL_RotateMoves(const matrix4x4_t *m)
+{
+ // rotate viewangles in all previous moves
+ vec3_t v;
+ vec3_t f, r, u;
+ int i;
+ for (i = 0;i < CL_MAX_USERCMDS;i++)
+ {
+ if (cl.movecmd[i].sequence > cls.servermovesequence)
+ {
+ usercmd_t *c = &cl.movecmd[i];
+ AngleVectors(c->viewangles, f, r, u);
+ Matrix4x4_Transform(m, f, v); VectorCopy(v, f);
+ Matrix4x4_Transform(m, u, v); VectorCopy(v, u);
+ AnglesFromVectors(c->viewangles, f, u, false);
+ }
+ }
+}
+
/*
==============
CL_SendMove
break;
case PROTOCOL_DARKPLACES6:
case PROTOCOL_DARKPLACES7:
- // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz specific
+ // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz/Xonotic specific
cl.cmd.crouch = (cl.cmd.buttons & 16) != 0;
break;
case PROTOCOL_UNKNOWN:
// 5 bytes
MSG_WriteByte (&buf, clc_move);
MSG_WriteFloat (&buf, cl.cmd.time); // last server packet time
- // 3 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle8i (&buf, cl.cmd.viewangles[i]);
+ // 3 bytes (6 bytes in proquake)
+ if (cls.proquake_servermod == 1) // MOD_PROQUAKE
+ {
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle16i (&buf, cl.cmd.viewangles[i]);
+ }
+ else
+ {
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle8i (&buf, cl.cmd.viewangles[i]);
+ }
// 6 bytes
MSG_WriteCoord16i (&buf, cl.cmd.forwardmove);
MSG_WriteCoord16i (&buf, cl.cmd.sidemove);
Cvar_RegisterVariable(&cl_movecliptokeyboard);
Cvar_RegisterVariable(&cl_movement);
+ Cvar_RegisterVariable(&cl_movement_replay);
Cvar_RegisterVariable(&cl_movement_nettimeout);
Cvar_RegisterVariable(&cl_movement_minping);
Cvar_RegisterVariable(&cl_movement_track_canjump);