Пример #1
0
/*
=================
G_TimeShiftClient

Move a client back to where he was at the specified "time"
=================
*/
void G_TimeShiftClient( gentity_t *ent, int time ) {
	int		j, k;

	if ( time > level.time ) {
		time = level.time;
	}

	// find two entries in the origin trail whose times sandwich "time"
	// assumes no two adjacent trail records have the same timestamp
	j = k = ent->client->trailHead;
	do {
		if ( ent->client->trail[j].time <= time )
			break;

		k = j;
		j--;
		if ( j < 0 ) {
			j = NUM_CLIENT_TRAILS - 1;
		}
	}
	while ( j != ent->client->trailHead );

	// if we got past the first iteration above, we've sandwiched (or wrapped)
	if ( j != k ) {
		// make sure it doesn't get re-saved
		if ( ent->client->saved.leveltime != level.time ) {
			// save the current origin and bounding box
			VectorCopy( &ent->r.mins, &ent->client->saved.mins );
			VectorCopy( &ent->r.maxs, &ent->client->saved.maxs );
			VectorCopy( &ent->r.currentOrigin, &ent->client->saved.currentOrigin );
			VectorCopy( &ent->r.currentAngles, &ent->client->saved.currentAngles );
			ent->client->saved.leveltime = level.time;
		}

		// if we haven't wrapped back to the head, we've sandwiched, so
		// we shift the client's position back to where he was at "time"
		if ( j != ent->client->trailHead )
		{
			float	frac = (float)(ent->client->trail[k].time - time) / (float)(ent->client->trail[k].time - ent->client->trail[j].time);

			// FOR TESTING ONLY
//			Com_Printf( "level time: %d, fire time: %d, j time: %d, k time: %d\n", level.time, time, ent->client->trail[j].time, ent->client->trail[k].time );

			// interpolate between the two origins to give position at time index "time"
			TimeShiftLerp( frac, &ent->client->trail[k].currentOrigin, &ent->client->trail[j].currentOrigin, &ent->r.currentOrigin );
			ent->r.currentAngles.yaw = LerpAngle( ent->client->trail[k].currentAngles.yaw, ent->r.currentAngles.yaw, frac );

			// lerp these too, just for fun (and ducking)
			TimeShiftLerp( frac, &ent->client->trail[k].mins, &ent->client->trail[j].mins, &ent->r.mins );
			TimeShiftLerp( frac, &ent->client->trail[k].maxs, &ent->client->trail[j].maxs, &ent->r.maxs );

			// this will recalculate absmin and absmax
			trap->LinkEntity( (sharedEntity_t *)ent );
		} else {
			// we wrapped, so grab the earliest
			VectorCopy( &ent->client->trail[k].currentAngles, &ent->r.currentAngles );
			VectorCopy( &ent->client->trail[k].currentOrigin, &ent->r.currentOrigin );
			VectorCopy( &ent->client->trail[k].mins, &ent->r.mins );
			VectorCopy( &ent->client->trail[k].maxs, &ent->r.maxs );

			// this will recalculate absmin and absmax
			trap->LinkEntity( (sharedEntity_t *)ent );
		}
	}
}
Пример #2
0
/**
 * @brief G_AdjustSingleClientPosition
 * @param[in,out] ent
 * @param[in] time
 */
static void G_AdjustSingleClientPosition(gentity_t *ent, int time)
{
	int i, j;

	if (time > level.time)
	{
		time = level.time;
	} // no lerping forward....

	if (!G_AntilagSafe(ent))
	{
		return;
	}

	// find a pair of markers which bound the requested time
	i = j = ent->client->topMarker;
	do
	{
		if (ent->client->clientMarkers[i].time <= time)
		{
			break;
		}

		j = i;
		i--;
		if (i < 0)
		{
			i = MAX_CLIENT_MARKERS - 1;
		}
	}
	while (i != ent->client->topMarker);

	if (i == j)     // oops, no valid stored markers
	{
		return;
	}

	// save current position to backup
	if (ent->client->backupMarker.time != level.time)
	{
		VectorCopy(ent->r.currentOrigin, ent->client->backupMarker.origin);
		VectorCopy(ent->r.mins, ent->client->backupMarker.mins);
		VectorCopy(ent->r.maxs, ent->client->backupMarker.maxs);
		// Head, Legs
		VectorCopy(ent->client->ps.viewangles, ent->client->backupMarker.viewangles);
		ent->client->backupMarker.eFlags     = ent->client->ps.eFlags;
		ent->client->backupMarker.pm_flags   = ent->client->ps.pm_flags;
		ent->client->backupMarker.viewheight = ent->client->ps.viewheight;

		ent->client->backupMarker.time = level.time;

		// Torso Markers
		ent->client->backupMarker.torsoOldFrameModel = ent->torsoFrame.oldFrameModel;
		ent->client->backupMarker.torsoFrameModel    = ent->torsoFrame.frameModel;
		ent->client->backupMarker.torsoOldFrame      = ent->torsoFrame.oldFrame;
		ent->client->backupMarker.torsoFrame         = ent->torsoFrame.frame;
		ent->client->backupMarker.torsoOldFrameTime  = ent->torsoFrame.oldFrameTime;
		ent->client->backupMarker.torsoFrameTime     = ent->torsoFrame.frameTime;
		ent->client->backupMarker.torsoYawAngle      = ent->torsoFrame.yawAngle;
		ent->client->backupMarker.torsoPitchAngle    = ent->torsoFrame.pitchAngle;
		ent->client->backupMarker.torsoYawing        = ent->torsoFrame.yawing;
		ent->client->backupMarker.torsoPitching      = ent->torsoFrame.pitching;

		// Legs Markers
		ent->client->backupMarker.legsOldFrameModel = ent->legsFrame.oldFrameModel;
		ent->client->backupMarker.legsFrameModel    = ent->legsFrame.frameModel;
		ent->client->backupMarker.legsOldFrame      = ent->legsFrame.oldFrame;
		ent->client->backupMarker.legsFrame         = ent->legsFrame.frame;
		ent->client->backupMarker.legsOldFrameTime  = ent->legsFrame.oldFrameTime;
		ent->client->backupMarker.legsFrameTime     = ent->legsFrame.frameTime;
		ent->client->backupMarker.legsYawAngle      = ent->legsFrame.yawAngle;
		ent->client->backupMarker.legsPitchAngle    = ent->legsFrame.pitchAngle;
		ent->client->backupMarker.legsYawing        = ent->legsFrame.yawing;
		ent->client->backupMarker.legsPitching      = ent->legsFrame.pitching;
	}

	if (i != ent->client->topMarker)
	{
		float frac = (float)(time - ent->client->clientMarkers[i].time) /
		             (float)(ent->client->clientMarkers[j].time - ent->client->clientMarkers[i].time);

		//LerpPosition(ent->client->clientMarkers[i].origin, ent->client->clientMarkers[j].origin, frac, ent->r.currentOrigin);
		//LerpPosition(ent->client->clientMarkers[i].mins, ent->client->clientMarkers[j].mins, frac, ent->r.mins);
		//LerpPosition(ent->client->clientMarkers[i].maxs, ent->client->clientMarkers[j].maxs, frac, ent->r.maxs);

		// Using TimeShiftLerp since it follows the client exactly meaning less roundoff error
		TimeShiftLerp(
		    ent->client->clientMarkers[i].origin,
		    ent->client->clientMarkers[j].origin,
		    frac,
		    ent->r.currentOrigin);
		TimeShiftLerp(
		    ent->client->clientMarkers[i].mins,
		    ent->client->clientMarkers[j].mins,
		    frac,
		    ent->r.mins);
		TimeShiftLerp(
		    ent->client->clientMarkers[i].maxs,
		    ent->client->clientMarkers[j].maxs,
		    frac,
		    ent->r.maxs);

		// These are for Head / Legs
		ent->client->ps.viewangles[0] = LerpAngle(
		    ent->client->clientMarkers[i].viewangles[0],
		    ent->client->clientMarkers[j].viewangles[0],
		    frac);
		ent->client->ps.viewangles[1] = LerpAngle(
		    ent->client->clientMarkers[i].viewangles[1],
		    ent->client->clientMarkers[j].viewangles[1],
		    frac);
		ent->client->ps.viewangles[2] = LerpAngle(
		    ent->client->clientMarkers[i].viewangles[2],
		    ent->client->clientMarkers[j].viewangles[2],
		    frac);
		// Set the ints to the closest ones in time since you can't lerp them.
		if ((ent->client->clientMarkers[j].time - time) < (time - ent->client->clientMarkers[i].time))
		{
			ent->client->ps.eFlags     = ent->client->clientMarkers[j].eFlags;
			ent->client->ps.pm_flags   = ent->client->clientMarkers[j].pm_flags;
			ent->client->ps.viewheight = ent->client->clientMarkers[j].viewheight;

			// Torso Markers
			ent->torsoFrame.oldFrameModel = ent->client->clientMarkers[j].torsoOldFrameModel;
			ent->torsoFrame.frameModel    = ent->client->clientMarkers[j].torsoFrameModel;
			ent->torsoFrame.oldFrame      = ent->client->clientMarkers[j].torsoOldFrame;
			ent->torsoFrame.frame         = ent->client->clientMarkers[j].torsoFrame;
			ent->torsoFrame.oldFrameTime  = ent->client->clientMarkers[j].torsoOldFrameTime;
			ent->torsoFrame.frameTime     = ent->client->clientMarkers[j].torsoFrameTime;
			ent->torsoFrame.yawAngle      = ent->client->clientMarkers[j].torsoYawAngle;
			ent->torsoFrame.pitchAngle    = ent->client->clientMarkers[j].torsoPitchAngle;
			ent->torsoFrame.yawing        = ent->client->clientMarkers[j].torsoYawing;
			ent->torsoFrame.pitching      = ent->client->clientMarkers[j].torsoPitching;

			// Legs Markers
			ent->legsFrame.oldFrameModel = ent->client->clientMarkers[j].legsOldFrameModel;
			ent->legsFrame.frameModel    = ent->client->clientMarkers[j].legsFrameModel;
			ent->legsFrame.oldFrame      = ent->client->clientMarkers[j].legsOldFrame;
			ent->legsFrame.frame         = ent->client->clientMarkers[j].legsFrame;
			ent->legsFrame.oldFrameTime  = ent->client->clientMarkers[j].legsOldFrameTime;
			ent->legsFrame.frameTime     = ent->client->clientMarkers[j].legsFrameTime;
			ent->legsFrame.yawAngle      = ent->client->clientMarkers[j].legsYawAngle;
			ent->legsFrame.pitchAngle    = ent->client->clientMarkers[j].legsPitchAngle;
			ent->legsFrame.yawing        = ent->client->clientMarkers[j].legsYawing;
			ent->legsFrame.pitching      = ent->client->clientMarkers[j].legsPitching;

			// time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[j].time;

		}
		else
		{
			ent->client->ps.eFlags     = ent->client->clientMarkers[i].eFlags;
			ent->client->ps.pm_flags   = ent->client->clientMarkers[i].pm_flags;
			ent->client->ps.viewheight = ent->client->clientMarkers[i].viewheight;

			// Torso Markers
			ent->torsoFrame.oldFrameModel = ent->client->clientMarkers[i].torsoOldFrameModel;
			ent->torsoFrame.frameModel    = ent->client->clientMarkers[i].torsoFrameModel;
			ent->torsoFrame.oldFrame      = ent->client->clientMarkers[i].torsoOldFrame;
			ent->torsoFrame.frame         = ent->client->clientMarkers[i].torsoFrame;
			ent->torsoFrame.oldFrameTime  = ent->client->clientMarkers[i].torsoOldFrameTime;
			ent->torsoFrame.frameTime     = ent->client->clientMarkers[i].torsoFrameTime;
			ent->torsoFrame.yawAngle      = ent->client->clientMarkers[i].torsoYawAngle;
			ent->torsoFrame.pitchAngle    = ent->client->clientMarkers[i].torsoPitchAngle;
			ent->torsoFrame.yawing        = ent->client->clientMarkers[i].torsoYawing;
			ent->torsoFrame.pitching      = ent->client->clientMarkers[i].torsoPitching;

			// Legs Markers
			ent->legsFrame.oldFrameModel = ent->client->clientMarkers[i].legsOldFrameModel;
			ent->legsFrame.frameModel    = ent->client->clientMarkers[i].legsFrameModel;
			ent->legsFrame.oldFrame      = ent->client->clientMarkers[i].legsOldFrame;
			ent->legsFrame.frame         = ent->client->clientMarkers[i].legsFrame;
			ent->legsFrame.oldFrameTime  = ent->client->clientMarkers[i].legsOldFrameTime;
			ent->legsFrame.frameTime     = ent->client->clientMarkers[i].legsFrameTime;
			ent->legsFrame.yawAngle      = ent->client->clientMarkers[i].legsYawAngle;
			ent->legsFrame.pitchAngle    = ent->client->clientMarkers[i].legsPitchAngle;
			ent->legsFrame.yawing        = ent->client->clientMarkers[i].legsYawing;
			ent->legsFrame.pitching      = ent->client->clientMarkers[i].legsPitching;

			// time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[i].time;
		}

		/* FIXME
		if ( debugger && debugger->client) {
		    // print some debugging stuff exactly like what the client does
		    // it starts with "Rec:" to let you know it backward-reconciled
		    char msg[2048];
		    Com_sprintf( msg, sizeof(msg),
		        "print \"^1Rec: time: %d, j: %d, k: %d, origin: %0.2f %0.2f %0.2f\n"
		        "^2frac: %0.4f, origin1: %0.2f %0.2f %0.2f, origin2: %0.2f %0.2f %0.2f\n"
		        "^7level.time: %d, est time: %d, level.time delta: %d, est real ping: %d\n\"",
		        time, ent->client->clientMarkers[i].time, ent->client->clientMarkers[j].time,
		        ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
		        frac,
		        ent->client->clientMarkers[i].origin[0],
		        ent->client->clientMarkers[i].origin[1],
		        ent->client->clientMarkers[i].origin[2],
		        ent->client->clientMarkers[j].origin[0],
		        ent->client->clientMarkers[j].origin[1],
		        ent->client->clientMarkers[j].origin[2],
		        level.time, level.time + debugger->client->frameOffset,
		        level.time - time, level.time + debugger->client->frameOffset - time);

		    trap_SendServerCommand( debugger - g_entities, msg );
		}
		*/
	}
	else
	{
		VectorCopy(ent->client->clientMarkers[j].origin, ent->r.currentOrigin);
		VectorCopy(ent->client->clientMarkers[j].mins, ent->r.mins);
		VectorCopy(ent->client->clientMarkers[j].maxs, ent->r.maxs);

		// BuildHead/Legs uses these
		VectorCopy(ent->client->clientMarkers[j].viewangles, ent->client->ps.viewangles);
		ent->client->ps.eFlags     = ent->client->clientMarkers[j].eFlags;
		ent->client->ps.pm_flags   = ent->client->clientMarkers[j].pm_flags;
		ent->client->ps.viewheight = ent->client->clientMarkers[j].viewheight;

		// Torso Markers
		ent->torsoFrame.oldFrameModel = ent->client->clientMarkers[j].torsoOldFrameModel;
		ent->torsoFrame.frameModel    = ent->client->clientMarkers[j].torsoFrameModel;
		ent->torsoFrame.oldFrame      = ent->client->clientMarkers[j].torsoOldFrame;
		ent->torsoFrame.frame         = ent->client->clientMarkers[j].torsoFrame;
		ent->torsoFrame.oldFrameTime  = ent->client->clientMarkers[j].torsoOldFrameTime;
		ent->torsoFrame.frameTime     = ent->client->clientMarkers[j].torsoFrameTime;
		ent->torsoFrame.yawAngle      = ent->client->clientMarkers[j].torsoYawAngle;
		ent->torsoFrame.pitchAngle    = ent->client->clientMarkers[j].torsoPitchAngle;
		ent->torsoFrame.yawing        = ent->client->clientMarkers[j].torsoYawing;
		ent->torsoFrame.pitching      = ent->client->clientMarkers[j].torsoPitching;

		// Legs Markers
		ent->legsFrame.oldFrameModel = ent->client->clientMarkers[j].legsOldFrameModel;
		ent->legsFrame.frameModel    = ent->client->clientMarkers[j].legsFrameModel;
		ent->legsFrame.oldFrame      = ent->client->clientMarkers[j].legsOldFrame;
		ent->legsFrame.frame         = ent->client->clientMarkers[j].legsFrame;
		ent->legsFrame.oldFrameTime  = ent->client->clientMarkers[j].legsOldFrameTime;
		ent->legsFrame.frameTime     = ent->client->clientMarkers[j].legsFrameTime;
		ent->legsFrame.yawAngle      = ent->client->clientMarkers[j].legsYawAngle;
		ent->legsFrame.pitchAngle    = ent->client->clientMarkers[j].legsPitchAngle;
		ent->legsFrame.yawing        = ent->client->clientMarkers[j].legsYawing;
		ent->legsFrame.pitching      = ent->client->clientMarkers[j].legsPitching;

		// time stamp for BuildHead/Leg
		ent->timeShiftTime = ent->client->clientMarkers[j].time;
	}

	trap_LinkEntity(ent);
}
Пример #3
0
/*
=================
G_TimeShiftClient

Move a client back to where he was at the specified "time"
=================
*/
void G_TimeShiftClient( gentity_t *ent, int time, qboolean debug, gentity_t *debugger ) {
	int		j, k;
	char msg[2048];

	// this will dump out the head index, and the time for all the stored positions
/*
	if ( debug ) {
		char	str[MAX_STRING_CHARS];

		Com_sprintf(str, sizeof(str), "print \"head: %d, %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\"",
			ent->client->historyHead,
			ent->client->history[0].leveltime,
			ent->client->history[1].leveltime,
			ent->client->history[2].leveltime,
			ent->client->history[3].leveltime,
			ent->client->history[4].leveltime,
			ent->client->history[5].leveltime,
			ent->client->history[6].leveltime,
			ent->client->history[7].leveltime,
			ent->client->history[8].leveltime,
			ent->client->history[9].leveltime,
			ent->client->history[10].leveltime,
			ent->client->history[11].leveltime,
			ent->client->history[12].leveltime,
			ent->client->history[13].leveltime,
			ent->client->history[14].leveltime,
			ent->client->history[15].leveltime,
			ent->client->history[16].leveltime);

		trap_SendServerCommand( debugger - g_entities, str );
	}
*/

	// find two entries in the history whose times sandwich "time"
	// assumes no two adjacent records have the same timestamp
	j = k = ent->client->historyHead;
	do {
		if ( ent->client->history[j].leveltime <= time )
			break;

		k = j;
		j--;
		if ( j < 0 ) {
			j = NUM_CLIENT_HISTORY - 1;
		}
	}
	while ( j != ent->client->historyHead );

	// if we got past the first iteration above, we've sandwiched (or wrapped)
	if ( j != k ) {
		// make sure it doesn't get re-saved
		if ( ent->client->saved.leveltime != level.time ) {
			// save the current origin and bounding box
			VectorCopy( ent->r.mins, ent->client->saved.mins );
			VectorCopy( ent->r.maxs, ent->client->saved.maxs );
			VectorCopy( ent->r.currentOrigin, ent->client->saved.currentOrigin );
			ent->client->saved.leveltime = level.time;
		}

		// if we haven't wrapped back to the head, we've sandwiched, so
		// we shift the client's position back to where he was at "time"
		if ( j != ent->client->historyHead ) {
			float	frac = (float)(time - ent->client->history[j].leveltime) /
				(float)(ent->client->history[k].leveltime - ent->client->history[j].leveltime);

			// interpolate between the two origins to give position at time index "time"
			TimeShiftLerp( frac,
				ent->client->history[j].currentOrigin, ent->client->history[k].currentOrigin,
				ent->r.currentOrigin );

			// lerp these too, just for fun (and ducking)
			TimeShiftLerp( frac,
				ent->client->history[j].mins, ent->client->history[k].mins,
				ent->r.mins );

			TimeShiftLerp( frac,
				ent->client->history[j].maxs, ent->client->history[k].maxs,
				ent->r.maxs );

			if ( debug && debugger != NULL ) {
				// print some debugging stuff exactly like what the client does

				// it starts with "Rec:" to let you know it backward-reconciled
				Com_sprintf( msg, sizeof(msg),
					"print \"^1Rec: time: %d, j: %d, k: %d, origin: %0.2f %0.2f %0.2f\n"
					"^2frac: %0.4f, origin1: %0.2f %0.2f %0.2f, origin2: %0.2f %0.2f %0.2f\n"
					"^7level.time: %d, est time: %d, level.time delta: %d, est real ping: %d\n\"",
					time, ent->client->history[j].leveltime, ent->client->history[k].leveltime,
					ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
					frac,
					ent->client->history[j].currentOrigin[0],
					ent->client->history[j].currentOrigin[1],
					ent->client->history[j].currentOrigin[2], 
					ent->client->history[k].currentOrigin[0],
					ent->client->history[k].currentOrigin[1],
					ent->client->history[k].currentOrigin[2],
					level.time, level.time + debugger->client->frameOffset,
					level.time - time, level.time + debugger->client->frameOffset - time);

				trap_SendServerCommand( debugger - g_entities, msg );
			}

			// this will recalculate absmin and absmax
			trap_LinkEntity( ent );
		} else {
			// we wrapped, so grab the earliest
			VectorCopy( ent->client->history[k].currentOrigin, ent->r.currentOrigin );
			VectorCopy( ent->client->history[k].mins, ent->r.mins );
			VectorCopy( ent->client->history[k].maxs, ent->r.maxs );

			// this will recalculate absmin and absmax
			trap_LinkEntity( ent );
		}
	}
	else {
		// this only happens when the client is using a negative timenudge, because that
		// number is added to the command time

		// print some debugging stuff exactly like what the client does

		// it starts with "No rec:" to let you know it didn't backward-reconcile
		if ( debug && debugger != NULL ) {
			Com_sprintf( msg, sizeof(msg),
				"print \"^1No rec: time: %d, j: %d, k: %d, origin: %0.2f %0.2f %0.2f\n"
				"^2frac: %0.4f, origin1: %0.2f %0.2f %0.2f, origin2: %0.2f %0.2f %0.2f\n"
				"^7level.time: %d, est time: %d, level.time delta: %d, est real ping: %d\n\"",
				time, level.time, level.time,
				ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
				0.0f,
				ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2], 
				ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
				level.time, level.time + debugger->client->frameOffset,
				level.time - time, level.time + debugger->client->frameOffset - time);

			trap_SendServerCommand( debugger - g_entities, msg );
		}
	}
}
Пример #4
0
void G_AdjustSingleClientPosition( gentity_t* ent, int time, gentity_t* debugger) {
	int	i, j;
	// unlagged analogies: antilag i = unlagged j, antilag j = unlagged k

	if( time > level.time ) {
		time = level.time;
	} // no lerping forward.... You mean extrapolating, not lerping (inter)

	if(!G_AntilagSafe(ent)) return;

	// find a pair of markers which bound the requested time
	i = j = ent->client->topMarker;
	do {
		if( ent->client->clientMarkers[i].time <= time ) {
			break;
		}

		j = i;
		i--;
		if( i < 0 ) {
			i = MAX_CLIENT_MARKERS - 1;
		}
	} while( i != ent->client->topMarker );

	if( i == j ) { // oops, no valid stored markers
		return;
	}

	// josh: from unlagged make sure it doesn't get backed-up twice
	if ( ent->client->backupMarker.time != level.time ) {
		VectorCopy(ent->r.currentOrigin,	ent->client->backupMarker.origin);
		VectorCopy(ent->r.mins,				ent->client->backupMarker.mins);
		VectorCopy(ent->r.maxs,				ent->client->backupMarker.maxs);
		//josh: for Head, Legs
		VectorCopy(ent->client->ps.viewangles,
			ent->client->backupMarker.viewangles);
		ent->client->backupMarker.eFlags = ent->client->ps.eFlags;
		ent->client->backupMarker.pm_flags = ent->client->ps.pm_flags;
		ent->client->backupMarker.viewheight = ent->client->ps.viewheight;
		// josh: This was missing, but needed or else no readjustment
		ent->client->backupMarker.time = level.time;

		// forty - realistic hitboxes - Torso Markers
		ent->client->backupMarker.torsoOldFrameModel	= ent->torsoFrame.oldFrameModel;
		ent->client->backupMarker.torsoFrameModel 	= ent->torsoFrame.frameModel;
		ent->client->backupMarker.torsoOldFrame		= ent->torsoFrame.oldFrame;
		ent->client->backupMarker.torsoFrame		= ent->torsoFrame.frame;
		ent->client->backupMarker.torsoOldFrameTime	= ent->torsoFrame.oldFrameTime;
		ent->client->backupMarker.torsoFrameTime	= ent->torsoFrame.frameTime;
		ent->client->backupMarker.torsoYawAngle		= ent->torsoFrame.yawAngle; 
		ent->client->backupMarker.torsoPitchAngle	= ent->torsoFrame.pitchAngle;
		ent->client->backupMarker.torsoYawing		= ent->torsoFrame.yawing;
		ent->client->backupMarker.torsoPitching		= ent->torsoFrame.pitching;

 		// forty - realistic hitboxes - Legs Markers
		ent->client->backupMarker.legsOldFrameModel	= ent->legsFrame.oldFrameModel;
		ent->client->backupMarker.legsFrameModel 	= ent->legsFrame.frameModel;
		ent->client->backupMarker.legsOldFrame		= ent->legsFrame.oldFrame;
		ent->client->backupMarker.legsFrame		= ent->legsFrame.frame;
		ent->client->backupMarker.legsOldFrameTime	= ent->legsFrame.oldFrameTime;
		ent->client->backupMarker.legsFrameTime		= ent->legsFrame.frameTime;
		ent->client->backupMarker.legsYawAngle		= ent->legsFrame.yawAngle; 
		ent->client->backupMarker.legsPitchAngle	= ent->legsFrame.pitchAngle;
		ent->client->backupMarker.legsYawing		= ent->legsFrame.yawing;
		ent->client->backupMarker.legsPitching		= ent->legsFrame.pitching;
	}

	if(i != ent->client->topMarker) {
		//float frac = ((float)(ent->client->clientMarkers[j].time - time)) / (ent->client->clientMarkers[j].time - ent->client->clientMarkers[i].time);
		//josh: reversing the order to better match the client and prevent 
		//roundoff error
		float	frac = (float)(time - ent->client->clientMarkers[i].time) /
				(float)(ent->client->clientMarkers[j].time - ent->client->clientMarkers[i].time);

		//LerpPosition(ent->client->clientMarkers[i].origin,		ent->client->clientMarkers[j].origin,	frac,	ent->r.currentOrigin);
		//LerpPosition(ent->client->clientMarkers[i].mins,		ent->client->clientMarkers[j].mins,		frac,	ent->r.mins);
		//LerpPosition(ent->client->clientMarkers[i].maxs,		ent->client->clientMarkers[j].maxs,		frac,	ent->r.maxs);
		//josh: Using TimeShiftLerp since it follows the client exactly
		//meaning less roundoff error
		TimeShiftLerp(
				ent->client->clientMarkers[i].origin,		
				ent->client->clientMarkers[j].origin,	
				frac,	
				ent->r.currentOrigin);
		TimeShiftLerp(
				ent->client->clientMarkers[i].mins,
				ent->client->clientMarkers[j].mins,
				frac,
				ent->r.mins);
		TimeShiftLerp(
				ent->client->clientMarkers[i].maxs,
				ent->client->clientMarkers[j].maxs,
				frac,
				ent->r.maxs);

		// These are for Head / Legs
		ent->client->ps.viewangles[0] = LerpAngle(
				ent->client->clientMarkers[i].viewangles[0],
				ent->client->clientMarkers[j].viewangles[0],
				frac);
		ent->client->ps.viewangles[1] = LerpAngle(
				ent->client->clientMarkers[i].viewangles[1],
				ent->client->clientMarkers[j].viewangles[1],
				frac);
		ent->client->ps.viewangles[2] = LerpAngle(
				ent->client->clientMarkers[i].viewangles[2],
				ent->client->clientMarkers[j].viewangles[2],
				frac);
		// josh: Set the ints to the closest ones in time since you can't
		//       lerp them.
		if((ent->client->clientMarkers[j].time - time)
			< (time - ent->client->clientMarkers[i].time)) {

			ent->client->ps.eFlags =
				ent->client->clientMarkers[j].eFlags;
			ent->client->ps.pm_flags =
				ent->client->clientMarkers[j].pm_flags;
			ent->client->ps.viewheight =
				ent->client->clientMarkers[j].viewheight;

			// forty - realistic hitboxes - Torso Markers
			ent->torsoFrame.oldFrameModel	= ent->client->clientMarkers[j].torsoOldFrameModel;
			ent->torsoFrame.frameModel	= ent->client->clientMarkers[j].torsoFrameModel;
			ent->torsoFrame.oldFrame	= ent->client->clientMarkers[j].torsoOldFrame;
			ent->torsoFrame.frame		= ent->client->clientMarkers[j].torsoFrame;
			ent->torsoFrame.oldFrameTime	= ent->client->clientMarkers[j].torsoOldFrameTime;
			ent->torsoFrame.frameTime	= ent->client->clientMarkers[j].torsoFrameTime;
			ent->torsoFrame.yawAngle	= ent->client->clientMarkers[j].torsoYawAngle; 
			ent->torsoFrame.pitchAngle	= ent->client->clientMarkers[j].torsoPitchAngle;
			ent->torsoFrame.yawing		= ent->client->clientMarkers[j].torsoYawing;
			ent->torsoFrame.pitching	= ent->client->clientMarkers[j].torsoPitching;
	
			// forty - realistic hitboxes - Legs Markers
			ent->legsFrame.oldFrameModel	= ent->client->clientMarkers[j].legsOldFrameModel;
			ent->legsFrame.frameModel	= ent->client->clientMarkers[j].legsFrameModel;
			ent->legsFrame.oldFrame		= ent->client->clientMarkers[j].legsOldFrame;
			ent->legsFrame.frame		= ent->client->clientMarkers[j].legsFrame;
			ent->legsFrame.oldFrameTime	= ent->client->clientMarkers[j].legsOldFrameTime;
			ent->legsFrame.frameTime	= ent->client->clientMarkers[j].legsFrameTime;
			ent->legsFrame.yawAngle		= ent->client->clientMarkers[j].legsYawAngle; 
			ent->legsFrame.pitchAngle	= ent->client->clientMarkers[j].legsPitchAngle;
			ent->legsFrame.yawing		= ent->client->clientMarkers[j].legsYawing;
			ent->legsFrame.pitching		= ent->client->clientMarkers[j].legsPitching;

			// forty - realistic hitboxes - time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[j].time;

		} else {
			ent->client->ps.eFlags =
				ent->client->clientMarkers[i].eFlags;
			ent->client->ps.pm_flags =
				ent->client->clientMarkers[i].pm_flags;
			ent->client->ps.viewheight =
				ent->client->clientMarkers[i].viewheight;

			// forty - realistic hitboxes - Torso Markers
			ent->torsoFrame.oldFrameModel	= ent->client->clientMarkers[i].torsoOldFrameModel;
			ent->torsoFrame.frameModel	= ent->client->clientMarkers[i].torsoFrameModel;
			ent->torsoFrame.oldFrame	= ent->client->clientMarkers[i].torsoOldFrame;
			ent->torsoFrame.frame		= ent->client->clientMarkers[i].torsoFrame;
			ent->torsoFrame.oldFrameTime	= ent->client->clientMarkers[i].torsoOldFrameTime;
			ent->torsoFrame.frameTime	= ent->client->clientMarkers[i].torsoFrameTime;
			ent->torsoFrame.yawAngle	= ent->client->clientMarkers[i].torsoYawAngle; 
			ent->torsoFrame.pitchAngle	= ent->client->clientMarkers[i].torsoPitchAngle;
			ent->torsoFrame.yawing		= ent->client->clientMarkers[i].torsoYawing;
			ent->torsoFrame.pitching	= ent->client->clientMarkers[i].torsoPitching;
	
			// forty - realistic hitboxes - Legs Markers
			ent->legsFrame.oldFrameModel	= ent->client->clientMarkers[i].legsOldFrameModel;
			ent->legsFrame.frameModel	= ent->client->clientMarkers[i].legsFrameModel;
			ent->legsFrame.oldFrame		= ent->client->clientMarkers[i].legsOldFrame;
			ent->legsFrame.frame		= ent->client->clientMarkers[i].legsFrame;
			ent->legsFrame.oldFrameTime	= ent->client->clientMarkers[i].legsOldFrameTime;
			ent->legsFrame.frameTime	= ent->client->clientMarkers[i].legsFrameTime;
			ent->legsFrame.yawAngle		= ent->client->clientMarkers[i].legsYawAngle; 
			ent->legsFrame.pitchAngle	= ent->client->clientMarkers[i].legsPitchAngle;
			ent->legsFrame.yawing		= ent->client->clientMarkers[i].legsYawing;
			ent->legsFrame.pitching		= ent->client->clientMarkers[i].legsPitching;
		
			// forty - realistic hitboxes - time stamp for BuildHead/Leg
			ent->timeShiftTime = ent->client->clientMarkers[i].time;

		}
		if ( debugger && debugger->client) {
			// print some debugging stuff exactly like what the client does
			// it starts with "Rec:" to let you know it backward-reconciled
			char msg[2048];
			Com_sprintf( msg, sizeof(msg),
				"print \"^1Rec: time: %d, j: %d, k: %d, origin: %0.2f %0.2f %0.2f\n"
				"^2frac: %0.4f, origin1: %0.2f %0.2f %0.2f, origin2: %0.2f %0.2f %0.2f\n"
				"^7level.time: %d, est time: %d, level.time delta: %d, est real ping: %d\n\"",
				time, ent->client->clientMarkers[i].time, ent->client->clientMarkers[j].time,
				ent->r.currentOrigin[0], ent->r.currentOrigin[1], ent->r.currentOrigin[2],
				frac,
				ent->client->clientMarkers[i].origin[0],
				ent->client->clientMarkers[i].origin[1],
				ent->client->clientMarkers[i].origin[2], 
				ent->client->clientMarkers[j].origin[0],
				ent->client->clientMarkers[j].origin[1],
				ent->client->clientMarkers[j].origin[2],
				level.time, level.time + debugger->client->frameOffset,
				level.time - time, level.time + debugger->client->frameOffset - time);

			trap_SendServerCommand( debugger - g_entities, msg );
		}
	} else {
		VectorCopy( ent->client->clientMarkers[j].origin, ent->r.currentOrigin );
		VectorCopy( ent->client->clientMarkers[j].mins,	ent->r.mins );
		VectorCopy( ent->client->clientMarkers[j].maxs,	ent->r.maxs );
		//// josh: BuildHead/Legs uses these
		VectorCopy(ent->client->clientMarkers[j].viewangles,
			ent->client->ps.viewangles);
		ent->client->ps.eFlags =
			ent->client->clientMarkers[j].eFlags;
		ent->client->ps.pm_flags =
			ent->client->clientMarkers[j].pm_flags;
		ent->client->ps.viewheight =
			ent->client->clientMarkers[j].viewheight;

		// forty - realistic hitboxes - Torso Markers
		ent->torsoFrame.oldFrameModel	= ent->client->clientMarkers[j].torsoOldFrameModel;
		ent->torsoFrame.frameModel	= ent->client->clientMarkers[j].torsoFrameModel;
		ent->torsoFrame.oldFrame	= ent->client->clientMarkers[j].torsoOldFrame;
		ent->torsoFrame.frame		= ent->client->clientMarkers[j].torsoFrame;
		ent->torsoFrame.oldFrameTime	= ent->client->clientMarkers[j].torsoOldFrameTime;
		ent->torsoFrame.frameTime	= ent->client->clientMarkers[j].torsoFrameTime;
		ent->torsoFrame.yawAngle	= ent->client->clientMarkers[j].torsoYawAngle; 
		ent->torsoFrame.pitchAngle	= ent->client->clientMarkers[j].torsoPitchAngle;
		ent->torsoFrame.yawing		= ent->client->clientMarkers[j].torsoYawing;
		ent->torsoFrame.pitching	= ent->client->clientMarkers[j].torsoPitching;

		// forty - realistic hitboxes - Legs Markers
		ent->legsFrame.oldFrameModel	= ent->client->clientMarkers[j].legsOldFrameModel;
		ent->legsFrame.frameModel	= ent->client->clientMarkers[j].legsFrameModel;
		ent->legsFrame.oldFrame		= ent->client->clientMarkers[j].legsOldFrame;
		ent->legsFrame.frame		= ent->client->clientMarkers[j].legsFrame;
		ent->legsFrame.oldFrameTime	= ent->client->clientMarkers[j].legsOldFrameTime;
		ent->legsFrame.frameTime	= ent->client->clientMarkers[j].legsFrameTime;
		ent->legsFrame.yawAngle		= ent->client->clientMarkers[j].legsYawAngle; 
		ent->legsFrame.pitchAngle	= ent->client->clientMarkers[j].legsPitchAngle;
		ent->legsFrame.yawing		= ent->client->clientMarkers[j].legsYawing;
		ent->legsFrame.pitching		= ent->client->clientMarkers[j].legsPitching;

		// forty - realistic hitboxes - time stamp for BuildHead/Leg
		ent->timeShiftTime = ent->client->clientMarkers[j].time;

	}

	trap_LinkEntity( ent );
}