mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 20:41:46 +00:00
Merge branch 'local-camera-fudge' into 'master'
Turn towards your local camera See merge request KartKrew/Kart!972
This commit is contained in:
commit
a6d0edc5a0
7 changed files with 112 additions and 118 deletions
|
|
@ -359,10 +359,10 @@ struct doomdata_t
|
||||||
UINT8 reserved; // Padding
|
UINT8 reserved; // Padding
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
clientcmd_pak clientpak; // 145 bytes
|
clientcmd_pak clientpak; // 147 bytes
|
||||||
client2cmd_pak client2pak; // 202 bytes
|
client2cmd_pak client2pak; // 206 bytes
|
||||||
client3cmd_pak client3pak; // 258 bytes(?)
|
client3cmd_pak client3pak; // 264 bytes(?)
|
||||||
client4cmd_pak client4pak; // 316 bytes(?)
|
client4cmd_pak client4pak; // 324 bytes(?)
|
||||||
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
|
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
|
||||||
serverconfig_pak servercfg; // 773 bytes
|
serverconfig_pak servercfg; // 773 bytes
|
||||||
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ struct ticcmd_t
|
||||||
{
|
{
|
||||||
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50)
|
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50)
|
||||||
INT16 turning; // Turn speed
|
INT16 turning; // Turn speed
|
||||||
|
INT16 angle; // Predicted angle, use me if you can!
|
||||||
INT16 throwdir; // Aiming direction
|
INT16 throwdir; // Aiming direction
|
||||||
INT16 aiming; // vertical aiming, see G_BuildTicCmd
|
INT16 aiming; // vertical aiming, see G_BuildTicCmd
|
||||||
UINT16 buttons;
|
UINT16 buttons;
|
||||||
|
|
|
||||||
39
src/g_demo.c
39
src/g_demo.c
|
|
@ -136,15 +136,16 @@ demoghost *ghosts = NULL;
|
||||||
#define DEMO_BOT 0x08
|
#define DEMO_BOT 0x08
|
||||||
|
|
||||||
// For demos
|
// For demos
|
||||||
#define ZT_FWD 0x01
|
#define ZT_FWD 0x0001
|
||||||
#define ZT_SIDE 0x02
|
#define ZT_SIDE 0x0002
|
||||||
#define ZT_TURNING 0x04
|
#define ZT_TURNING 0x0004
|
||||||
#define ZT_THROWDIR 0x08
|
#define ZT_ANGLE 0x0008
|
||||||
#define ZT_BUTTONS 0x10
|
#define ZT_THROWDIR 0x0010
|
||||||
#define ZT_AIMING 0x20
|
#define ZT_BUTTONS 0x0020
|
||||||
#define ZT_LATENCY 0x40
|
#define ZT_AIMING 0x0040
|
||||||
#define ZT_FLAGS 0x80
|
#define ZT_LATENCY 0x0080
|
||||||
// OUT OF ZIPTICS...
|
#define ZT_FLAGS 0x0100
|
||||||
|
// Ziptics are UINT16 now, go nuts
|
||||||
|
|
||||||
#define DEMOMARKER 0x80 // demobuf.end
|
#define DEMOMARKER 0x80 // demobuf.end
|
||||||
|
|
||||||
|
|
@ -530,17 +531,19 @@ void G_WriteDemoExtraData(void)
|
||||||
|
|
||||||
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
{
|
{
|
||||||
UINT8 ziptic;
|
UINT16 ziptic;
|
||||||
|
|
||||||
if (!demobuf.p || !demo.deferstart)
|
if (!demobuf.p || !demo.deferstart)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ziptic = READUINT8(demobuf.p);
|
ziptic = READUINT16(demobuf.p);
|
||||||
|
|
||||||
if (ziptic & ZT_FWD)
|
if (ziptic & ZT_FWD)
|
||||||
oldcmd[playernum].forwardmove = READSINT8(demobuf.p);
|
oldcmd[playernum].forwardmove = READSINT8(demobuf.p);
|
||||||
if (ziptic & ZT_TURNING)
|
if (ziptic & ZT_TURNING)
|
||||||
oldcmd[playernum].turning = READINT16(demobuf.p);
|
oldcmd[playernum].turning = READINT16(demobuf.p);
|
||||||
|
if (ziptic & ZT_ANGLE)
|
||||||
|
oldcmd[playernum].angle = READINT16(demobuf.p);
|
||||||
if (ziptic & ZT_THROWDIR)
|
if (ziptic & ZT_THROWDIR)
|
||||||
oldcmd[playernum].throwdir = READINT16(demobuf.p);
|
oldcmd[playernum].throwdir = READINT16(demobuf.p);
|
||||||
if (ziptic & ZT_BUTTONS)
|
if (ziptic & ZT_BUTTONS)
|
||||||
|
|
@ -564,13 +567,14 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
|
|
||||||
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
{
|
{
|
||||||
char ziptic = 0;
|
UINT16 ziptic = 0;
|
||||||
UINT8 *ziptic_p;
|
UINT8 *ziptic_p;
|
||||||
(void)playernum;
|
(void)playernum;
|
||||||
|
|
||||||
if (!demobuf.p)
|
if (!demobuf.p)
|
||||||
return;
|
return;
|
||||||
ziptic_p = demobuf.p++; // the ziptic, written at the end of this function
|
ziptic_p = demobuf.p; // the ziptic, written at the end of this function
|
||||||
|
demobuf.p += 2;
|
||||||
|
|
||||||
if (cmd->forwardmove != oldcmd[playernum].forwardmove)
|
if (cmd->forwardmove != oldcmd[playernum].forwardmove)
|
||||||
{
|
{
|
||||||
|
|
@ -586,6 +590,13 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
ziptic |= ZT_TURNING;
|
ziptic |= ZT_TURNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd->angle != oldcmd[playernum].angle)
|
||||||
|
{
|
||||||
|
WRITEINT16(demobuf.p,cmd->angle);
|
||||||
|
oldcmd[playernum].angle = cmd->angle;
|
||||||
|
ziptic |= ZT_ANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->throwdir != oldcmd[playernum].throwdir)
|
if (cmd->throwdir != oldcmd[playernum].throwdir)
|
||||||
{
|
{
|
||||||
WRITEINT16(demobuf.p,cmd->throwdir);
|
WRITEINT16(demobuf.p,cmd->throwdir);
|
||||||
|
|
@ -621,7 +632,7 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
ziptic |= ZT_FLAGS;
|
ziptic |= ZT_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ziptic_p = ziptic;
|
WRITEUINT16(ziptic_p, ziptic);
|
||||||
|
|
||||||
// attention here for the ticcmd size!
|
// attention here for the ticcmd size!
|
||||||
// latest demos with mouse aiming byte in ticcmd
|
// latest demos with mouse aiming byte in ticcmd
|
||||||
|
|
|
||||||
79
src/g_game.c
79
src/g_game.c
|
|
@ -1080,80 +1080,32 @@ INT32 localaiming[MAXSPLITSCREENPLAYERS];
|
||||||
angle_t localangle[MAXSPLITSCREENPLAYERS];
|
angle_t localangle[MAXSPLITSCREENPLAYERS];
|
||||||
|
|
||||||
INT32 localsteering[MAXSPLITSCREENPLAYERS];
|
INT32 localsteering[MAXSPLITSCREENPLAYERS];
|
||||||
INT32 localdelta[MAXSPLITSCREENPLAYERS];
|
|
||||||
INT32 localstoredeltas[MAXSPLITSCREENPLAYERS][TICCMD_LATENCYMASK + 1];
|
|
||||||
UINT8 locallatency[MAXSPLITSCREENPLAYERS][TICRATE];
|
|
||||||
UINT8 localtic;
|
|
||||||
|
|
||||||
void G_ResetAnglePrediction(player_t *player)
|
|
||||||
{
|
|
||||||
UINT16 i, j;
|
|
||||||
|
|
||||||
for (i = 0; i <= r_splitscreen; i++)
|
|
||||||
{
|
|
||||||
if (&players[displayplayers[i]] == player)
|
|
||||||
{
|
|
||||||
localdelta[i] = 0;
|
|
||||||
for (j = 0; j < TICCMD_LATENCYMASK; j++)
|
|
||||||
{
|
|
||||||
localstoredeltas[i][j] = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turning was removed from G_BuildTiccmd to prevent easy client hacking.
|
// Turning was removed from G_BuildTiccmd to prevent easy client hacking.
|
||||||
// This brings back the camera prediction that was lost.
|
// This brings back the camera prediction that was lost.
|
||||||
static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, player_t *player)
|
static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, player_t *player)
|
||||||
{
|
{
|
||||||
angle_t angleChange = 0;
|
angle_t angleChange = 0;
|
||||||
angle_t destAngle = player->angleturn;
|
|
||||||
angle_t diff = 0;
|
|
||||||
|
|
||||||
localtic = cmd->latency;
|
while (realtics > 0)
|
||||||
|
|
||||||
if (player->pflags & PF_DRIFTEND)
|
|
||||||
{
|
{
|
||||||
// Otherwise, your angle slingshots off to the side violently...
|
localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning);
|
||||||
G_ResetAnglePrediction(player);
|
angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE;
|
||||||
|
|
||||||
|
realtics--;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Left here in case it needs unsealing later. This tried to replicate an old localcam function, but this behavior was unpopular in tests.
|
||||||
|
//if (player->pflags & PF_DRIFTEND)
|
||||||
|
{
|
||||||
|
localangle[ssplayer - 1] = player->mo->angle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
while (realtics > 0)
|
localangle[ssplayer - 1] += angleChange;
|
||||||
{
|
|
||||||
localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning);
|
|
||||||
angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE;
|
|
||||||
|
|
||||||
// Store the angle we applied to this tic, so we can revert it later.
|
|
||||||
// If we trust the camera to do all of the work, then it can get out of sync fast.
|
|
||||||
localstoredeltas[ssplayer - 1][cmd->latency] += angleChange;
|
|
||||||
localdelta[ssplayer - 1] += angleChange;
|
|
||||||
|
|
||||||
realtics--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We COULD set it to destAngle directly...
|
|
||||||
// but this causes incredible jittering when the prediction turns out to be wrong. So we ease into it.
|
|
||||||
// Slight increased camera lag in all scenarios > Mostly lagless camera but with jittering
|
|
||||||
destAngle = player->angleturn + localdelta[ssplayer - 1];
|
|
||||||
|
|
||||||
diff = destAngle - localangle[ssplayer - 1];
|
|
||||||
|
|
||||||
if (diff > ANGLE_180)
|
|
||||||
{
|
|
||||||
diff = InvAngle(InvAngle(diff) / 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
localangle[ssplayer - 1] += diff;
|
|
||||||
|
|
||||||
// In case of angle debugging, break glass
|
|
||||||
// localangle[ssplayer - 1] = destAngle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
|
|
@ -1189,6 +1141,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd->angle = localangle[forplayer] >> TICCMD_REDUCE;
|
||||||
|
|
||||||
// why build a ticcmd if we're paused?
|
// why build a ticcmd if we're paused?
|
||||||
// Or, for that matter, if we're being reborn.
|
// Or, for that matter, if we're being reborn.
|
||||||
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
|
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
|
||||||
|
|
@ -1422,6 +1376,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
|
||||||
{
|
{
|
||||||
dest[i].forwardmove = src[i].forwardmove;
|
dest[i].forwardmove = src[i].forwardmove;
|
||||||
dest[i].turning = (INT16)SHORT(src[i].turning);
|
dest[i].turning = (INT16)SHORT(src[i].turning);
|
||||||
|
dest[i].angle = (INT16)SHORT(src[i].angle);
|
||||||
dest[i].throwdir = (INT16)SHORT(src[i].throwdir);
|
dest[i].throwdir = (INT16)SHORT(src[i].throwdir);
|
||||||
dest[i].aiming = (INT16)SHORT(src[i].aiming);
|
dest[i].aiming = (INT16)SHORT(src[i].aiming);
|
||||||
dest[i].buttons = (UINT16)SHORT(src[i].buttons);
|
dest[i].buttons = (UINT16)SHORT(src[i].buttons);
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,6 @@ extern consvar_t cv_resume;
|
||||||
const char *G_BuildMapName(INT32 map);
|
const char *G_BuildMapName(INT32 map);
|
||||||
INT32 G_MapNumber(const char *mapname);
|
INT32 G_MapNumber(const char *mapname);
|
||||||
|
|
||||||
void G_ResetAnglePrediction(player_t *player);
|
|
||||||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
|
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
|
||||||
|
|
||||||
// copy ticcmd_t to and fro the normal way
|
// copy ticcmd_t to and fro the normal way
|
||||||
|
|
@ -116,10 +115,6 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
|
||||||
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
|
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
|
||||||
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
|
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
|
||||||
extern INT32 localsteering[MAXSPLITSCREENPLAYERS];
|
extern INT32 localsteering[MAXSPLITSCREENPLAYERS];
|
||||||
extern INT32 localdelta[MAXSPLITSCREENPLAYERS];
|
|
||||||
extern INT32 localstoredeltas[MAXSPLITSCREENPLAYERS][TICCMD_LATENCYMASK + 1];
|
|
||||||
extern UINT8 locallatency[MAXSPLITSCREENPLAYERS][TICRATE];
|
|
||||||
extern UINT8 localtic;
|
|
||||||
|
|
||||||
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers);
|
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers);
|
||||||
boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers);
|
boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers);
|
||||||
|
|
|
||||||
|
|
@ -9100,15 +9100,17 @@ void T_Pusher(pusher_t *p)
|
||||||
thing->player->carry = CR_SLIDING;
|
thing->player->carry = CR_SLIDING;
|
||||||
thing->angle = R_PointToAngle2(0, 0, xspeed, yspeed);
|
thing->angle = R_PointToAngle2(0, 0, xspeed, yspeed);
|
||||||
|
|
||||||
|
|
||||||
if (!demo.playback)
|
if (!demo.playback)
|
||||||
{
|
{
|
||||||
angle_t angle = thing->player->angleturn;
|
angle_t angle = thing->player->boostangle;
|
||||||
if (thing->angle - angle > ANGLE_180)
|
if (thing->angle - angle > ANGLE_180)
|
||||||
P_SetPlayerAngle(thing->player, angle - (angle - thing->angle) / 8);
|
thing->player->boostangle = angle - (angle - thing->angle) / 8;
|
||||||
else
|
else
|
||||||
P_SetPlayerAngle(thing->player, angle + (thing->angle - angle) / 8);
|
thing->player->boostangle = angle + (thing->angle - angle) / 8;
|
||||||
//P_SetPlayerAngle(thing->player, thing->angle);
|
//P_SetPlayerAngle(thing->player, thing->angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->exclusive)
|
if (p->exclusive)
|
||||||
|
|
|
||||||
90
src/p_user.c
90
src/p_user.c
|
|
@ -2120,7 +2120,6 @@ static void P_3dMovement(player_t *player)
|
||||||
static void P_UpdatePlayerAngle(player_t *player)
|
static void P_UpdatePlayerAngle(player_t *player)
|
||||||
{
|
{
|
||||||
angle_t angleChange = ANGLE_MAX;
|
angle_t angleChange = ANGLE_MAX;
|
||||||
UINT8 maxlatency;
|
|
||||||
UINT8 p = UINT8_MAX;
|
UINT8 p = UINT8_MAX;
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
||||||
|
|
@ -2133,8 +2132,58 @@ static void P_UpdatePlayerAngle(player_t *player)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player->steering = K_UpdateSteeringValue(player->steering, player->cmd.turning);
|
// Don't apply steering just yet. If we make a correction, we'll need to adjust it.
|
||||||
angleChange = K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE;
|
INT16 targetsteering = K_UpdateSteeringValue(player->steering, player->cmd.turning);
|
||||||
|
angleChange = K_GetKartTurnValue(player, targetsteering) << TICCMD_REDUCE;
|
||||||
|
|
||||||
|
if (!K_PlayerUsesBotMovement(player))
|
||||||
|
{
|
||||||
|
// With a full slam on the analog stick, how far could we steer in either direction?
|
||||||
|
INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN);
|
||||||
|
angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE;
|
||||||
|
INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -KART_FULLTURN);
|
||||||
|
angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE;
|
||||||
|
|
||||||
|
// Grab local camera angle from ticcmd. Where do we actually want to go?
|
||||||
|
angle_t targetAngle = (player->cmd.angle) << TICCMD_REDUCE;
|
||||||
|
angle_t targetDelta = targetAngle - (player->mo->angle);
|
||||||
|
|
||||||
|
if (targetDelta == angleChange || player->pflags & PF_DRIFTEND || (maxTurnRight == 0 && maxTurnLeft == 0))
|
||||||
|
{
|
||||||
|
// We are where we need to be.
|
||||||
|
// ...Or we aren't, but shouldn't be able to steer.
|
||||||
|
player->steering = targetsteering;
|
||||||
|
// Alternatively, while in DRIFTEND we want to trust inputs for a bit, not camera.
|
||||||
|
// The game client doesn't know we're DRIFTEND until after a response gets back,
|
||||||
|
// so we momentarily ignore the camera angle and let the server trust our inputs instead.
|
||||||
|
// That way, even if you're steering blind, you get the intended "kick-out" effect.
|
||||||
|
}
|
||||||
|
else if (targetDelta >= ANGLE_180 && maxTurnLeft >= targetDelta) // Overshot, so just fudge it.
|
||||||
|
{
|
||||||
|
angleChange = targetDelta;
|
||||||
|
player->steering = targetsteering;
|
||||||
|
}
|
||||||
|
else if (targetDelta <= ANGLE_180 && maxTurnRight <= targetDelta) // Overshot, so just fudge it.
|
||||||
|
{
|
||||||
|
angleChange = targetDelta;
|
||||||
|
player->steering = targetsteering;
|
||||||
|
}
|
||||||
|
else if (targetDelta >= ANGLE_180 && maxTurnLeft < targetDelta) // Undershot, slam the stick.
|
||||||
|
{
|
||||||
|
angleChange = maxTurnLeft;
|
||||||
|
player->steering = steeringLeft;
|
||||||
|
}
|
||||||
|
else if (targetDelta <= ANGLE_180 && maxTurnRight > targetDelta) // Undershot, slam the stick.
|
||||||
|
{
|
||||||
|
angleChange = maxTurnRight;
|
||||||
|
player->steering = steeringRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// You're a bot. Go where you're supposed to go
|
||||||
|
player->steering = targetsteering;
|
||||||
|
}
|
||||||
|
|
||||||
if (p == UINT8_MAX)
|
if (p == UINT8_MAX)
|
||||||
{
|
{
|
||||||
|
|
@ -2144,33 +2193,8 @@ static void P_UpdatePlayerAngle(player_t *player)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// During standard play, our latency can vary by up to 1 tic in either direction, even on a stable connection.
|
|
||||||
// This probably comes from differences in ticcmd dispatch vs consumption rate. Probably.
|
|
||||||
// Uncorrected, this 2-tic "wobble" causes camera corrections to sometimes be skipped or batched.
|
|
||||||
// So just use the highest recent value for the furthest possible search.
|
|
||||||
// We unset the correction after applying, anyway.
|
|
||||||
locallatency[p][leveltime%TICRATE] = maxlatency = player->cmd.latency;
|
|
||||||
for (i = 0; i < TICRATE; i++)
|
|
||||||
{
|
|
||||||
maxlatency = max(locallatency[p][i], maxlatency);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8 lateTic = ((leveltime - maxlatency) & TICCMD_LATENCYMASK);
|
|
||||||
UINT8 clearTic = ((localtic + 1) & TICCMD_LATENCYMASK);
|
|
||||||
|
|
||||||
player->angleturn += angleChange;
|
player->angleturn += angleChange;
|
||||||
player->mo->angle = player->angleturn;
|
player->mo->angle = player->angleturn;
|
||||||
|
|
||||||
// Undo the ticcmd's old emulated angle,
|
|
||||||
// now that we added the actual game logic angle.
|
|
||||||
|
|
||||||
while (lateTic != clearTic)
|
|
||||||
{
|
|
||||||
localdelta[p] -= localstoredeltas[p][lateTic];
|
|
||||||
localstoredeltas[p][lateTic] = 0;
|
|
||||||
|
|
||||||
lateTic = (lateTic - 1) & TICCMD_LATENCYMASK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cv_allowmlook.value || player->spectator == false)
|
if (!cv_allowmlook.value || player->spectator == false)
|
||||||
|
|
@ -3162,7 +3186,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
||||||
|
|
||||||
if (demo.playback)
|
if (demo.playback)
|
||||||
{
|
{
|
||||||
focusangle = mo->angle;
|
// Hack-adjacent.
|
||||||
|
// Sometimes stale ticcmds send a weird angle at the start of the race.
|
||||||
|
// P_UpdatePlayerAngle knows to ignore cmd angle when you literally can't turn, so we do the same here.
|
||||||
|
if (leveltime > introtime)
|
||||||
|
focusangle = player->cmd.angle << TICCMD_REDUCE;
|
||||||
|
else
|
||||||
|
focusangle = mo->angle; // Just use something known sane.
|
||||||
focusaiming = 0;
|
focusaiming = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -4478,7 +4508,7 @@ void P_ForceLocalAngle(player_t *player, angle_t angle)
|
||||||
if (player == &players[displayplayers[i]])
|
if (player == &players[displayplayers[i]])
|
||||||
{
|
{
|
||||||
localangle[i] = angle;
|
localangle[i] = angle;
|
||||||
G_ResetAnglePrediction(player);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue