// remove stale queue items
n = cl.movement_numqueue;
cl.movement_numqueue = 0;
- if (cl.servermovesequence)
+ if (cls.servermovesequence)
{
for (i = 0;i < n;i++)
{
- if (cl.movement_queue[i].sequence > cl.servermovesequence)
+ if (cl.movement_queue[i].sequence > cls.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
if (cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])))
{
// add to input queue
- cl.movement_queue[cl.movement_numqueue].sequence = cl.movesequence;
+ cl.movement_queue[cl.movement_numqueue].sequence = cls.movesequence;
cl.movement_queue[cl.movement_numqueue].time = cl.movecmd[0].time;
cl.movement_queue[cl.movement_numqueue].frametime = bound(0, cl.movecmd[0].time - cl.movecmd[1].time, 0.1);
VectorCopy(cl.viewangles, cl.movement_queue[cl.movement_numqueue].viewangles);
for (i = 0;i < NUMOFFSETS;i++)
{
VectorAdd(offsets[i], s->origin, neworigin);
- if (!CL_TraceBox(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true).startsolid)
+ if (!CL_Move(neworigin, cl.playercrouchmins, cl.playercrouchmaxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false).startsolid)
{
VectorCopy(neworigin, s->origin);
return true;
// low ceiling first
if (s->crouched)
{
- trace = CL_TraceBox(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ trace = CL_Move(s->origin, cl.playerstandmins, cl.playerstandmaxs, s->origin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
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] - 2);
- trace = CL_TraceBox(origin1, s->mins, s->maxs, origin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ trace = CL_Move(origin1, s->mins, s->maxs, origin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
s->onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7 && s->velocity[2] < cl_gravity.value * s->q.frametime;
// 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_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK;
+ s->watertype = CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 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_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+ if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
{
s->waterlevel = WATERLEVEL_SWIMMING;
origin1[2] = s->origin[2] + 22;
- if (CL_TraceBox(origin1, vec3_origin, vec3_origin, origin1, true, NULL, 0, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
+ if (CL_Move(origin1, vec3_origin, vec3_origin, origin1, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsupercontents & SUPERCONTENTS_LIQUIDSMASK)
s->waterlevel = WATERLEVEL_SUBMERGED;
}
}
for (bump = 0, t = s->q.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, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ trace = CL_Move(s->origin, s->mins, s->maxs, neworigin, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
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] + s->movevars_stepheight);
VectorSet(neworigin2, neworigin[0], neworigin[1], s->origin[2] + s->movevars_stepheight);
- trace2 = CL_TraceBox(currentorigin2, s->mins, s->maxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ 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)
{
// 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, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ trace3 = CL_Move(currentorigin2, s->mins, s->maxs, neworigin2, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
//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)
AngleVectors(yawangles, forward, NULL, NULL);
VectorMA(s->origin, 24, forward, spot);
spot[2] += 8;
- if (CL_TraceBox(spot, vec3_origin, vec3_origin, spot, true, NULL, 0, false).startsolid)
+ if (CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
{
spot[2] += 24;
- if (!CL_TraceBox(spot, vec3_origin, vec3_origin, spot, true, NULL, 0, false).startsolid)
+ if (!CL_Move(spot, vec3_origin, vec3_origin, spot, MOVE_NOMONSTERS, NULL, 0, true, false, NULL, false).startsolid)
{
VectorScale(forward, 50, s->velocity);
s->velocity[2] = 310;
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, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ trace = CL_Move(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true, true, NULL, false);
else
- trace = CL_TraceBox(neworigin2, vec3_origin, vec3_origin, neworigin3, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, true);
+ 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;
}
s.movevars_airaccel_sideways_friction = cl_movement_airaccel_sideways_friction.value;
}
- cl.movement_predicted = (cl_movement.integer && !cls.demoplayback && cls.signon == SIGNONS && cl.stats[STAT_HEALTH] > 0 && !cl.intermission) && ((cls.protocol != PROTOCOL_DARKPLACES6 && cls.protocol != PROTOCOL_DARKPLACES7) || cl.servermovesequence);
+ cl.movement_predicted = (cl_movement.integer && !cls.demoplayback && cls.signon == SIGNONS && cl.stats[STAT_HEALTH] > 0 && !cl.intermission) && ((cls.protocol != PROTOCOL_DARKPLACES6 && cls.protocol != PROTOCOL_DARKPLACES7) || cls.servermovesequence);
if (cl.movement_predicted)
{
//Con_Printf("%f: ", cl.movecmd[0].time);
sizebuf_t buf;
unsigned char data[1024];
static double lastsendtime = 0;
+ double packettime;
double msectime;
static double oldmsectime;
if (!cls.netcon)
return;
-#if 0
- if (cl.movement_predicted && cls.signon == SIGNONS && cls.protocol != PROTOCOL_QUAKEWORLD)
+ packettime = 1.0 / bound(10, cl_netinputpacketspersecond.value, 100);
+ // on quakeworld servers the server replies to client input, so we send
+ // packets whenever we want to
+ // on non-quakeworld servers the client replies to server updates
+ if (cls.protocol == PROTOCOL_QUAKEWORLD)
{
- if (!cl.movement_needupdate)
+ // don't send too often or else network connections can get clogged by a high renderer framerate
+ if (realtime < lastsendtime + packettime)
return;
- cl.movement_needupdate = false;
+ cl.cmd.time = realtime;
}
- else
-#endif
+ else if (cl.movement_predicted || cls.signon < SIGNONS)
{
- double packettime = 1.0 / bound(10, cl_netinputpacketspersecond.value, 100);
// don't send too often or else network connections can get clogged by a high renderer framerate
if (realtime < lastsendtime + packettime)
return;
- // don't let it fall behind if CL_SendMove hasn't been called recently
- // (such is the case when framerate is too low for instance)
- lastsendtime = max(lastsendtime + packettime, realtime);
+ cl.cmd.time = cls.protocol == PROTOCOL_QUAKEWORLD ? realtime : cl.time;
+ }
+ else
+ {
+ // if not predicted, we should just reply to server packets, and
+ // report the real latest packet time rather than our interpolated
+ // time
+ if (!cl.movement_needupdate && realtime < lastsendtime + packettime)
+ return;
+ cl.cmd.time = cls.protocol == PROTOCOL_QUAKEWORLD ? realtime : cl.mtime[0];
}
+ // don't let it fall behind if CL_SendMove hasn't been called recently
+ // (such is the case when framerate is too low for instance)
+ lastsendtime = bound(realtime, lastsendtime + packettime, realtime + packettime);
+ // clear the note down that we sent a packet recently
+ cl.movement_needupdate = false;
- cl.cmd.time = cls.protocol == PROTOCOL_QUAKEWORLD ? realtime : cl.time;
buf.maxsize = sizeof(data);
buf.cursize = 0;
cl.cmd.msec = 100;
oldmsectime = msectime;
- cl.movesequence++;
+ cls.movesequence++;
if (cl_movement.integer)
- cl.cmd.sequence = cl.movesequence;
+ cl.cmd.sequence = cls.movesequence;
else
cl.cmd.sequence = 0;
CL_UpdatePrydonCursor();
// always dump the first two messages, because they may contain leftover inputs from the last level
- if (cl.movesequence > 2)
+ if (cls.movesequence > 2)
{
// update the cl.movecmd array which holds the most recent moves
for (i = CL_MAX_USERCMDS - 1;i >= 1;i--)
for (j = 0, cmd = &cl.movecmd[maxusercmds-1];j < maxusercmds;j++, cmd--)
{
// don't repeat any stale moves
- if (cmd->sequence && cmd->sequence < cl.servermovesequence)
+ if (cmd->sequence && cmd->sequence < cls.servermovesequence)
continue;
// 5/9 bytes
MSG_WriteByte (&buf, clc_move);