cvar_t cl_movement_airaccel_qw = {0, "cl_movement_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration (reduces speed gain when zigzagging) (should match sv_airaccel_qw); when < 0, the speed is clamped against the maximum allowed forward speed after the move"};
cvar_t cl_movement_airaccel_sideways_friction = {0, "cl_movement_airaccel_sideways_friction", "0", "anti-sideways movement stabilization (should match sv_airaccel_sideways_friction); when < 0, only so much friction is applied that braking (by accelerating backwards) cannot be stronger"};
-cvar_t in_pitch_min = {0, "in_pitch_min", "-90", "how far downward you can aim (quake used -70"};
-cvar_t in_pitch_max = {0, "in_pitch_max", "90", "how far upward you can aim (quake used 80"};
+cvar_t in_pitch_min = {0, "in_pitch_min", "-90", "how far you can aim upward (quake used -70)"};
+cvar_t in_pitch_max = {0, "in_pitch_max", "90", "how far you can aim downward (quake used 80)"};
cvar_t m_filter = {CVAR_SAVE, "m_filter","0", "smoothes mouse movement, less responsive but smoother aiming"};
cvar_t m_accelerate = {CVAR_SAVE, "m_accelerate","1", "mouse acceleration factor (try 2)"};
static int oldwindowmouse[2];
if (oldwindowmouse[0] != in_windowmouse_x || oldwindowmouse[1] != in_windowmouse_y)
{
- CL_VM_InputEvent(3, in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height);
+ CL_VM_InputEvent(3, in_windowmouse_x * vid_conwidth.value / vid.width, in_windowmouse_y * vid_conheight.value / vid.height);
oldwindowmouse[0] = in_windowmouse_x;
oldwindowmouse[1] = in_windowmouse_y;
}
else
{
if (in_mouse_x || in_mouse_y)
- CL_VM_InputEvent(2, in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height);
+ CL_VM_InputEvent(2, in_mouse_x, in_mouse_y);
}
}
{
// digital direction, analog amount
vec_t wishvel_x, wishvel_y;
- f *= max(cl_sidespeed.value, max(cl_forwardspeed.value, cl_backspeed.value));
wishvel_x = fabs(cl.cmd.forwardmove);
wishvel_y = fabs(cl.cmd.sidemove);
if(wishvel_x != 0 && wishvel_y != 0 && wishvel_x != wishvel_y)
for (i = 0;i < NUMOFFSETS;i++)
{
VectorAdd(offsets[i], s->origin, neworigin);
- if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true).startsolid)
+ if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true).startsolid)
{
VectorCopy(neworigin, s->origin);
return true;
// low ceiling first
if (s->crouched)
{
- trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+ trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
if (!trace.startsolid)
s->crouched = false;
}
// set onground
VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + 1);
VectorSet(origin2, s->origin[0], s->origin[1], s->origin[2] - 1); // -2 causes clientside doublejump bug at above 150fps, raising that to 300fps :)
- trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+ trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
if(trace.fraction < 1 && trace.plane.normal[2] > 0.7)
{
s->onground = true;
// set watertype/waterlevel
VectorSet(origin1, s->origin[0], s->origin[1], s->origin[2] + s->mins[2] + 1);
s->waterlevel = WATERLEVEL_NONE;
- s->watertype = CL_TracePoint(origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
+ s->watertype = CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
if (s->watertype)
{
s->waterlevel = WATERLEVEL_WETFEET;
origin1[2] = s->origin[2] + (s->mins[2] + s->maxs[2]) * 0.5f;
- if (CL_TracePoint(origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+ if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
{
s->waterlevel = WATERLEVEL_SWIMMING;
origin1[2] = s->origin[2] + 22;
- if (CL_TracePoint(origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+ if (CL_TracePoint(origin1, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
s->waterlevel = WATERLEVEL_SUBMERGED;
}
}
for (bump = 0, t = s->cmd.frametime;bump < 8 && VectorLength2(s->velocity) > 0;bump++)
{
VectorMA(s->origin, t, s->velocity, neworigin);
- trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+ trace = CL_TraceBox(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, 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, 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_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+ trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
if (!trace2.startsolid)
{
// then move down from there
VectorCopy(trace2.endpos, currentorigin2);
VectorSet(neworigin2, trace2.endpos[0], trace2.endpos[1], s->origin[2]);
- trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true);
+ trace3 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, 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)
if (trace.fraction == 1)
break;
- //if (trace.plane.normal[2] > 0.7)
- // s->onground = true;
+ // this is only really needed for nogravityonground combined with gravityunaffectedbyticrate
+ // <LordHavoc> I'm pretty sure I commented it out solely because it seemed redundant
+ // this got commented out in a change that supposedly makes the code match QW better
+ // so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block
+ if (trace.plane.normal[2] > 0.7)
+ s->onground = true;
t -= t * trace.fraction;
AngleVectors(yawangles, forward, NULL, NULL);
VectorMA(s->origin, 24, forward, spot);
spot[2] += 8;
- if (CL_TracePoint(spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
+ if (CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsolid)
{
spot[2] += 24;
- if (!CL_TracePoint(spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
+ if (!CL_TracePoint(spot, MOVE_NOMONSTERS, s->self, 0, true, false, NULL, false).startsolid)
{
VectorScale(forward, 50, s->velocity);
s->velocity[2] = 310;
s->velocity[2] = 80;
else
{
- if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
+ if (IS_NEXUIZ_DERIVED(gamemode))
s->velocity[2] = 200;
else
s->velocity[2] = 100;
VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]);
VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34);
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, true);
+ trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true);
else
- trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, true, false);
+ trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, collision_extendmovelength.value, true, true, NULL, true, false);
if (trace.fraction == 1 && !trace.startsolid)
friction *= cl.movevars_edgefriction;
}
accelspeed = min(cl.movevars_accelerate * s->cmd.frametime * wishspeed, addspeed);
VectorMA(s->velocity, accelspeed, wishdir, s->velocity);
}
- if(cl.moveflags & MOVEFLAG_NOGRAVITYONGROUND)
- gravity = 0;
- else
- gravity = cl.movevars_gravity * cl.movevars_entgravity * s->cmd.frametime;
- if(cl.moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
- s->velocity[2] -= gravity * 0.5f;
- else
- s->velocity[2] -= gravity;
+ gravity = cl.movevars_gravity * cl.movevars_entgravity * s->cmd.frametime;
+ if(!(cl.moveflags & MOVEFLAG_NOGRAVITYONGROUND))
+ {
+ if(cl.moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
+ s->velocity[2] -= gravity * 0.5f;
+ else
+ s->velocity[2] -= gravity;
+ }
if (cls.protocol == PROTOCOL_QUAKEWORLD)
s->velocity[2] = 0;
if (VectorLength2(s->velocity))
CL_ClientMovement_Move(s);
- if(cl.moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
- s->velocity[2] -= gravity * 0.5f;
+ if(!(cl.moveflags & MOVEFLAG_NOGRAVITYONGROUND) || !s->onground)
+ {
+ if(cl.moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
+ s->velocity[2] -= gravity * 0.5f;
+ }
}
else
{
else
s->velocity[2] -= gravity;
CL_ClientMovement_Move(s);
- if(cl.moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
- s->velocity[2] -= gravity * 0.5f;
+ if(!(cl.moveflags & MOVEFLAG_NOGRAVITYONGROUND) || !s->onground)
+ {
+ if(cl.moveflags & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
+ s->velocity[2] -= gravity * 0.5f;
+ }
}
}
-void CL_ClientMovement_PlayerMove(cl_clientmovement_state_t *s)
+static void CL_ClientMovement_PlayerMove(cl_clientmovement_state_t *s)
{
//Con_Printf(" %f", frametime);
if (!s->cmd.jump)
else
{
cl.moveflags = 0;
- cl.movevars_ticrate = slowmo.value / bound(1.0f, cl_netfps.value, 1000.0f);
- cl.movevars_timescale = slowmo.value;
+ cl.movevars_ticrate = (cls.demoplayback ? 1.0f : slowmo.value) / bound(1.0f, cl_netfps.value, 1000.0f);
+ cl.movevars_timescale = (cls.demoplayback ? 1.0f : slowmo.value);
cl.movevars_gravity = sv_gravity.value;
cl.movevars_stopspeed = cl_movement_stopspeed.value;
cl.movevars_maxspeed = cl_movement_maxspeed.value;
if(!(cl.moveflags & MOVEFLAG_VALID))
{
- if(gamemode == GAME_NEXUIZ)
+ if(gamemode == GAME_NEXUIZ) // Legacy hack to work with old servers of Nexuiz.
cl.moveflags = MOVEFLAG_Q2AIRACCELERATE;
}
cl.movevars_aircontrol_power = 2; // CPMA default
}
+void CL_ClientMovement_PlayerMove_Frame(cl_clientmovement_state_t *s)
+{
+ // if a move is more than 50ms, do it as two moves (matching qwsv)
+ //Con_Printf("%i ", s.cmd.msec);
+ if(s->cmd.frametime > 0.0005)
+ {
+ if (s->cmd.frametime > 0.05)
+ {
+ s->cmd.frametime /= 2;
+ CL_ClientMovement_PlayerMove(s);
+ }
+ CL_ClientMovement_PlayerMove(s);
+ }
+ else
+ {
+ // we REALLY need this handling to happen, even if the move is not executed
+ if (!s->cmd.jump)
+ s->cmd.canjump = true;
+ }
+}
+
void CL_ClientMovement_Replay(void)
{
int i;
if (cl.movecmd[i].sequence > cls.servermovesequence)
totalmovemsec += cl.movecmd[i].msec;
cl.movement_predicted = totalmovemsec >= cl_movement_minping.value && cls.servermovesequence && (cl_movement.integer && !cls.demoplayback && cls.signon == SIGNONS && cl.stats[STAT_HEALTH] > 0 && !cl.intermission);
- //Con_Printf("%i = %.0f >= %.0f && %i && (%i && %i && %i == %i && %i > 0 && %i\n", cl.movement_predicted, totalmovemsec, cl_movement_minping.value, cls.servermovesequence, cl_movement.integer, !cls.demoplayback, cls.signon, SIGNONS, cl.stats[STAT_HEALTH], !cl.intermission);
+ //Con_Printf("%i = %.0f >= %.0f && %u && (%i && %i && %i == %i && %i > 0 && %i\n", cl.movement_predicted, totalmovemsec, cl_movement_minping.value, cls.servermovesequence, cl_movement.integer, !cls.demoplayback, cls.signon, SIGNONS, cl.stats[STAT_HEALTH], !cl.intermission);
if (cl.movement_predicted)
{
//Con_Printf("%ims\n", cl.movecmd[0].msec);
if (i < CL_MAX_USERCMDS - 1)
s.cmd.canjump = cl.movecmd[i+1].canjump;
- // if a move is more than 50ms, do it as two moves (matching qwsv)
- //Con_Printf("%i ", s.cmd.msec);
- if(s.cmd.frametime > 0.0005)
- {
- if (s.cmd.frametime > 0.05)
- {
- s.cmd.frametime /= 2;
- CL_ClientMovement_PlayerMove(&s);
- }
- CL_ClientMovement_PlayerMove(&s);
- }
- else
- {
- // we REALLY need this handling to happen, even if the move is not executed
- if (!s.cmd.jump)
- s.cmd.canjump = true;
- }
+ CL_ClientMovement_PlayerMove_Frame(&s);
+
cl.movecmd[i].canjump = s.cmd.canjump;
}
//Con_Printf("\n");
if (s.onground)
cl.onground = true;
}
-
- // react to onground state changes (for gun bob)
- if (cl.onground)
- {
- if (!cl.oldonground)
- cl.hitgroundtime = cl.movecmd[0].time;
- cl.lastongroundtime = cl.movecmd[0].time;
- }
- cl.oldonground = cl.onground;
}
static void QW_MSG_WriteDeltaUsercmd(sizebuf_t *buf, usercmd_t *from, usercmd_t *to)
// framerate, this is 10 bytes, if client framerate is lower this
// will be more...
int i, j;
- int oldsequence = cl.cmd.sequence - bound(1, cl_netrepeatinput.integer + 1, 3);
- if (oldsequence < 1)
+ unsigned int oldsequence = cl.cmd.sequence;
+ unsigned int delta = bound(1, cl_netrepeatinput.integer + 1, 3);
+ if (oldsequence > delta)
+ oldsequence = oldsequence - delta;
+ else
oldsequence = 1;
for (i = 0;i < LATESTFRAMENUMS;i++)
{
// send the reliable message (forwarded commands) if there is one
if (buf.cursize || cls.netcon->message.cursize)
- NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, max(20*(buf.cursize+40), cl_rate.integer), false);
+ NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, max(20*(buf.cursize+40), cl_rate.integer), cl_rate_burstsize.integer, false);
if (quemove)
{