From 7c08634f7ed517ec23dbb70d743f765efea18065 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 24 Feb 2023 16:59:22 -0700 Subject: [PATCH 01/12] WIP: Turn towards local camera (midgame join broken right now) --- src/d_clisrv.h | 8 ++++---- src/d_ticcmd.h | 1 + src/g_demo.c | 37 ++++++++++++++++++++++++------------- src/g_game.c | 37 ++++++++++++++++++++----------------- src/p_user.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 34 deletions(-) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index a648b07ae..0b51846ca 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -359,10 +359,10 @@ struct doomdata_t UINT8 reserved; // Padding union { - clientcmd_pak clientpak; // 145 bytes - client2cmd_pak client2pak; // 202 bytes - client3cmd_pak client3pak; // 258 bytes(?) - client4cmd_pak client4pak; // 316 bytes(?) + clientcmd_pak clientpak; // 147 bytes + client2cmd_pak client2pak; // 206 bytes + client3cmd_pak client3pak; // 264 bytes(?) + client4cmd_pak client4pak; // 324 bytes(?) servertics_pak serverpak; // 132495 bytes (more around 360, no?) serverconfig_pak servercfg; // 773 bytes UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index c7a37614c..a3cdf4d9b 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -71,6 +71,7 @@ struct ticcmd_t { SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50) INT16 turning; // Turn speed + INT16 angle; // Predicted angle, use me if you can! INT16 throwdir; // Aiming direction INT16 aiming; // vertical aiming, see G_BuildTicCmd UINT16 buttons; diff --git a/src/g_demo.c b/src/g_demo.c index 36a6f6c63..a2c8373ff 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -136,14 +136,15 @@ demoghost *ghosts = NULL; #define DEMO_BOT 0x08 // For demos -#define ZT_FWD 0x01 -#define ZT_SIDE 0x02 -#define ZT_TURNING 0x04 -#define ZT_THROWDIR 0x08 -#define ZT_BUTTONS 0x10 -#define ZT_AIMING 0x20 -#define ZT_LATENCY 0x40 -#define ZT_FLAGS 0x80 +#define ZT_FWD 1 +#define ZT_SIDE 2 +#define ZT_TURNING 4 +#define ZT_ANGLE 8 +#define ZT_THROWDIR 16 +#define ZT_BUTTONS 32 +#define ZT_AIMING 64 +#define ZT_LATENCY 128 +#define ZT_FLAGS 256 // OUT OF ZIPTICS... #define DEMOMARKER 0x80 // demobuf.end @@ -530,17 +531,19 @@ void G_WriteDemoExtraData(void) void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) { - UINT8 ziptic; + UINT16 ziptic; if (!demobuf.p || !demo.deferstart) return; - ziptic = READUINT8(demobuf.p); + ziptic = READUINT16(demobuf.p); if (ziptic & ZT_FWD) oldcmd[playernum].forwardmove = READSINT8(demobuf.p); if (ziptic & ZT_TURNING) oldcmd[playernum].turning = READINT16(demobuf.p); + if (ziptic & ZT_ANGLE) + oldcmd[playernum].angle = READINT16(demobuf.p); if (ziptic & ZT_THROWDIR) oldcmd[playernum].throwdir = READINT16(demobuf.p); if (ziptic & ZT_BUTTONS) @@ -564,13 +567,14 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) { - char ziptic = 0; + UINT16 ziptic = 0; UINT8 *ziptic_p; (void)playernum; if (!demobuf.p) 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) { @@ -586,6 +590,13 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) ziptic |= ZT_TURNING; } + if (cmd->angle != oldcmd[playernum].angle) + { + WRITEINT16(demobuf.p,cmd->angle); + oldcmd[playernum].turning = cmd->angle; + ziptic |= ZT_ANGLE; + } + if (cmd->throwdir != oldcmd[playernum].throwdir) { WRITEINT16(demobuf.p,cmd->throwdir); @@ -621,7 +632,7 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) ziptic |= ZT_FLAGS; } - *ziptic_p = ziptic; + WRITEUINT16(ziptic_p, ziptic); // attention here for the ticcmd size! // latest demos with mouse aiming byte in ticcmd diff --git a/src/g_game.c b/src/g_game.c index e522d82e2..ad7f2f888 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1080,6 +1080,8 @@ INT32 localaiming[MAXSPLITSCREENPLAYERS]; angle_t localangle[MAXSPLITSCREENPLAYERS]; INT32 localsteering[MAXSPLITSCREENPLAYERS]; +INT32 localdrift[MAXSPLITSCREENPLAYERS]; +INT32 localdriftend[MAXSPLITSCREENPLAYERS]; INT32 localdelta[MAXSPLITSCREENPLAYERS]; INT32 localstoredeltas[MAXSPLITSCREENPLAYERS][TICCMD_LATENCYMASK + 1]; UINT8 locallatency[MAXSPLITSCREENPLAYERS][TICRATE]; @@ -1113,25 +1115,21 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p localtic = cmd->latency; - if (player->pflags & PF_DRIFTEND) + while (realtics > 0) { - // Otherwise, your angle slingshots off to the side violently... - G_ResetAnglePrediction(player); - } - else - { - while (realtics > 0) - { - localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning); - angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE; + pflags_t oldflags = player->pflags; - // 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; + localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning); + angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE; - realtics--; - } + player->pflags = oldflags; + + // 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... @@ -1141,6 +1139,7 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p diff = destAngle - localangle[ssplayer - 1]; + /* if (diff > ANGLE_180) { diff = InvAngle(InvAngle(diff) / 2); @@ -1151,9 +1150,10 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p } localangle[ssplayer - 1] += diff; + */ // In case of angle debugging, break glass - // localangle[ssplayer - 1] = destAngle; + localangle[ssplayer - 1] = destAngle; } void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) @@ -1292,6 +1292,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->throwdir -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE; } } + + cmd->angle = localangle[forplayer] >> TICCMD_REDUCE; // drift if (G_PlayerInputDown(forplayer, gc_drift, 0)) @@ -1422,6 +1424,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) { dest[i].forwardmove = src[i].forwardmove; 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].aiming = (INT16)SHORT(src[i].aiming); dest[i].buttons = (UINT16)SHORT(src[i].buttons); diff --git a/src/p_user.c b/src/p_user.c index bc5d699d8..27bc41edd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2136,6 +2136,42 @@ static void P_UpdatePlayerAngle(player_t *player) player->steering = K_UpdateSteeringValue(player->steering, player->cmd.turning); angleChange = K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE; + INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN); + angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE; + INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -1 * KART_FULLTURN); + angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE; + + angle_t targetAngle = (player->cmd.angle) << TICCMD_REDUCE; + + angle_t targetDelta = targetAngle - (player->mo->angle); + + //CONS_Printf("%u, steering by %u but we want %u, MTL %d %u, MTR %d %u\n", targetAngle, angleChange, targetDelta, steeringLeft, maxTurnLeft, steeringRight, maxTurnRight); + + if (targetDelta == angleChange) + { + //CONS_Printf("Facing correct, thank god\n"); + } + else if (targetDelta >= ANGLE_180 && maxTurnLeft >= targetDelta) + { + //CONS_Printf("undershoot left\n"); + angleChange = targetDelta; + } + else if (targetDelta <= ANGLE_180 && maxTurnRight <= targetDelta) + { + //CONS_Printf("undershoot right\n"); + angleChange = targetDelta; + } + else if (targetDelta >= ANGLE_180 && maxTurnLeft < targetDelta) + { + //CONS_Printf("overshoot left\n"); + angleChange = maxTurnLeft; + } + else if (targetDelta <= ANGLE_180 && maxTurnRight < targetDelta) + { + //CONS_Printf("overshoot right\n"); + angleChange = maxTurnRight; + } + if (p == UINT8_MAX) { // When F12ing players, set local angle directly. @@ -2144,6 +2180,8 @@ static void P_UpdatePlayerAngle(player_t *player) } 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. @@ -2157,10 +2195,16 @@ static void P_UpdatePlayerAngle(player_t *player) UINT8 lateTic = ((leveltime - maxlatency) & TICCMD_LATENCYMASK); UINT8 clearTic = ((localtic + 1) & TICCMD_LATENCYMASK); + */ + /* player->angleturn += angleChange; player->mo->angle = player->angleturn; + */ + player->mo->angle += angleChange; + + /* // Undo the ticcmd's old emulated angle, // now that we added the actual game logic angle. @@ -2171,6 +2215,7 @@ static void P_UpdatePlayerAngle(player_t *player) lateTic = (lateTic - 1) & TICCMD_LATENCYMASK; } + */ } if (!cv_allowmlook.value || player->spectator == false) From 432be46a2fe5acc8336d2ca15862f17585b291c4 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 24 Feb 2023 20:04:36 -0700 Subject: [PATCH 02/12] Please god just fucking work --- src/d_clisrv.c | 2 ++ src/g_demo.c | 2 +- src/g_game.c | 64 ++++---------------------------------------------- src/g_game.h | 5 ---- src/p_user.c | 39 +++--------------------------- 5 files changed, 10 insertions(+), 102 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f53d1f35a..972be5ce4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1333,6 +1333,7 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i <= r_splitscreen; i++) { P_ForceLocalAngle(&players[displayplayers[i]], players[displayplayers[i]].angleturn); + //P_ForceLocalAngle(&players[displayplayers[i]], players[displayplayers[i]].cmd.angle); } for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) @@ -3648,6 +3649,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) } P_ForceLocalAngle(newplayer, newplayer->angleturn); + //P_ForceLocalAngle(newplayer, newplayer->cmd.angle); D_SendPlayerConfig(splitscreenplayer); addedtogame = true; diff --git a/src/g_demo.c b/src/g_demo.c index a2c8373ff..228b0f09d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -593,7 +593,7 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) if (cmd->angle != oldcmd[playernum].angle) { WRITEINT16(demobuf.p,cmd->angle); - oldcmd[playernum].turning = cmd->angle; + oldcmd[playernum].angle = cmd->angle; ziptic |= ZT_ANGLE; } diff --git a/src/g_game.c b/src/g_game.c index ad7f2f888..c1028d4aa 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1080,80 +1080,24 @@ INT32 localaiming[MAXSPLITSCREENPLAYERS]; angle_t localangle[MAXSPLITSCREENPLAYERS]; INT32 localsteering[MAXSPLITSCREENPLAYERS]; -INT32 localdrift[MAXSPLITSCREENPLAYERS]; -INT32 localdriftend[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. // This brings back the camera prediction that was lost. static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, player_t *player) { angle_t angleChange = 0; - angle_t destAngle = player->angleturn; - angle_t diff = 0; - - localtic = cmd->latency; while (realtics > 0) { - pflags_t oldflags = player->pflags; - localsteering[ssplayer - 1] = K_UpdateSteeringValue(localsteering[ssplayer - 1], cmd->turning); angleChange = K_GetKartTurnValue(player, localsteering[ssplayer - 1]) << TICCMD_REDUCE; - player->pflags = oldflags; - - // 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; + localangle[ssplayer - 1] += angleChange; + //player->angleturn = localangle[ssplayer - 1]; } void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) @@ -1189,6 +1133,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) break; } + cmd->angle = localangle[forplayer] >> TICCMD_REDUCE; + // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN)) @@ -1292,8 +1238,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->throwdir -= (joystickvector.yaxis * KART_FULLTURN) / JOYAXISRANGE; } } - - cmd->angle = localangle[forplayer] >> TICCMD_REDUCE; // drift if (G_PlayerInputDown(forplayer, gc_drift, 0)) diff --git a/src/g_game.h b/src/g_game.h index 78b484a69..fac245c9a 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -101,7 +101,6 @@ extern consvar_t cv_resume; const char *G_BuildMapName(INT32 map); INT32 G_MapNumber(const char *mapname); -void G_ResetAnglePrediction(player_t *player); void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer); // copy ticcmd_t to and fro the normal way @@ -116,10 +115,6 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming); extern angle_t localangle[MAXSPLITSCREENPLAYERS]; extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed 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); boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers); diff --git a/src/p_user.c b/src/p_user.c index 27bc41edd..3510af96f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2120,7 +2120,6 @@ static void P_3dMovement(player_t *player) static void P_UpdatePlayerAngle(player_t *player) { angle_t angleChange = ANGLE_MAX; - UINT8 maxlatency; UINT8 p = UINT8_MAX; UINT8 i; @@ -2147,7 +2146,7 @@ static void P_UpdatePlayerAngle(player_t *player) //CONS_Printf("%u, steering by %u but we want %u, MTL %d %u, MTR %d %u\n", targetAngle, angleChange, targetDelta, steeringLeft, maxTurnLeft, steeringRight, maxTurnRight); - if (targetDelta == angleChange) + if (targetDelta == angleChange || player->pflags & PF_DRIFTEND) { //CONS_Printf("Facing correct, thank god\n"); } @@ -2180,42 +2179,10 @@ static void P_UpdatePlayerAngle(player_t *player) } 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->mo->angle = player->angleturn; - */ - player->mo->angle += angleChange; - - /* - // 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; - } - */ + // player->mo->angle += angleChange; } if (!cv_allowmlook.value || player->spectator == false) @@ -4523,7 +4490,7 @@ void P_ForceLocalAngle(player_t *player, angle_t angle) if (player == &players[displayplayers[i]]) { localangle[i] = angle; - G_ResetAnglePrediction(player); + break; } } From e3e567f30366a5522618b64aeafce1f660ba9e38 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 24 Feb 2023 20:38:36 -0700 Subject: [PATCH 03/12] Don't use localangle aim for bots --- src/p_user.c | 63 +++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 3510af96f..9ba6beb07 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2135,40 +2135,43 @@ static void P_UpdatePlayerAngle(player_t *player) player->steering = K_UpdateSteeringValue(player->steering, player->cmd.turning); angleChange = K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE; - INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN); - angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE; - INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -1 * KART_FULLTURN); - angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE; + if (!K_PlayerUsesBotMovement(player)) + { + INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN); + angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE; + INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -1 * KART_FULLTURN); + angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE; - angle_t targetAngle = (player->cmd.angle) << TICCMD_REDUCE; + angle_t targetAngle = (player->cmd.angle) << TICCMD_REDUCE; - angle_t targetDelta = targetAngle - (player->mo->angle); + angle_t targetDelta = targetAngle - (player->mo->angle); - //CONS_Printf("%u, steering by %u but we want %u, MTL %d %u, MTR %d %u\n", targetAngle, angleChange, targetDelta, steeringLeft, maxTurnLeft, steeringRight, maxTurnRight); + //CONS_Printf("%u, steering by %u but we want %u, MTL %d %u, MTR %d %u\n", targetAngle, angleChange, targetDelta, steeringLeft, maxTurnLeft, steeringRight, maxTurnRight); - if (targetDelta == angleChange || player->pflags & PF_DRIFTEND) - { - //CONS_Printf("Facing correct, thank god\n"); - } - else if (targetDelta >= ANGLE_180 && maxTurnLeft >= targetDelta) - { - //CONS_Printf("undershoot left\n"); - angleChange = targetDelta; - } - else if (targetDelta <= ANGLE_180 && maxTurnRight <= targetDelta) - { - //CONS_Printf("undershoot right\n"); - angleChange = targetDelta; - } - else if (targetDelta >= ANGLE_180 && maxTurnLeft < targetDelta) - { - //CONS_Printf("overshoot left\n"); - angleChange = maxTurnLeft; - } - else if (targetDelta <= ANGLE_180 && maxTurnRight < targetDelta) - { - //CONS_Printf("overshoot right\n"); - angleChange = maxTurnRight; + if (targetDelta == angleChange || player->pflags & PF_DRIFTEND) + { + //CONS_Printf("Facing correct, thank god\n"); + } + else if (targetDelta >= ANGLE_180 && maxTurnLeft >= targetDelta) + { + //CONS_Printf("undershoot left\n"); + angleChange = targetDelta; + } + else if (targetDelta <= ANGLE_180 && maxTurnRight <= targetDelta) + { + //CONS_Printf("undershoot right\n"); + angleChange = targetDelta; + } + else if (targetDelta >= ANGLE_180 && maxTurnLeft < targetDelta) + { + //CONS_Printf("overshoot left\n"); + angleChange = maxTurnLeft; + } + else if (targetDelta <= ANGLE_180 && maxTurnRight < targetDelta) + { + //CONS_Printf("overshoot right\n"); + angleChange = maxTurnRight; + } } if (p == UINT8_MAX) From c17f5c22ffabd5a6aa0e9c7cdda60a3a1d5a24b6 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 24 Feb 2023 21:16:53 -0700 Subject: [PATCH 04/12] Suspend local camera during DRIFTEND kickout --- src/g_game.c | 11 ++++++++--- src/p_user.c | 24 ++++++++++++------------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index c1028d4aa..b0b01098a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1095,9 +1095,14 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p realtics--; } - // In case of angle debugging, break glass - localangle[ssplayer - 1] += angleChange; - //player->angleturn = localangle[ssplayer - 1]; + if (player->pflags & PF_DRIFTEND) + { + localangle[ssplayer - 1] = player->mo->angle; + } + else + { + localangle[ssplayer - 1] += angleChange; + } } void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) diff --git a/src/p_user.c b/src/p_user.c index 9ba6beb07..b27bbb815 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2137,39 +2137,39 @@ static void P_UpdatePlayerAngle(player_t *player) 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, -1 * 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); - //CONS_Printf("%u, steering by %u but we want %u, MTL %d %u, MTR %d %u\n", targetAngle, angleChange, targetDelta, steeringLeft, maxTurnLeft, steeringRight, maxTurnRight); - if (targetDelta == angleChange || player->pflags & PF_DRIFTEND) { - //CONS_Printf("Facing correct, thank god\n"); + // We are where we need to be. :) + + // 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) + else if (targetDelta >= ANGLE_180 && maxTurnLeft >= targetDelta) // Overshot, so just fudge it. { - //CONS_Printf("undershoot left\n"); angleChange = targetDelta; } - else if (targetDelta <= ANGLE_180 && maxTurnRight <= targetDelta) + else if (targetDelta <= ANGLE_180 && maxTurnRight <= targetDelta) // Overshot, so just fudge it. { - //CONS_Printf("undershoot right\n"); angleChange = targetDelta; } - else if (targetDelta >= ANGLE_180 && maxTurnLeft < targetDelta) + else if (targetDelta >= ANGLE_180 && maxTurnLeft < targetDelta) // Undershot, slam the stick. { - //CONS_Printf("overshoot left\n"); angleChange = maxTurnLeft; } - else if (targetDelta <= ANGLE_180 && maxTurnRight < targetDelta) + else if (targetDelta <= ANGLE_180 && maxTurnRight < targetDelta) // Undershot, slam the stick. { - //CONS_Printf("overshoot right\n"); angleChange = maxTurnRight; } } From a3831ccf4873c1eb55074d8d8bae00fcb4341212 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 25 Feb 2023 00:55:25 -0700 Subject: [PATCH 05/12] Disable local driftend snap for testing --- src/g_game.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index a4fb89569..9d2d34454 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1095,7 +1095,8 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p realtics--; } - if (player->pflags & PF_DRIFTEND) + //if (player->pflags & PF_DRIFTEND) + if (false) { localangle[ssplayer - 1] = player->mo->angle; } From 69d100ac538dd441779d23fb9db3f1bf6251898b Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 25 Feb 2023 03:16:27 -0700 Subject: [PATCH 06/12] We are no longer out of ziptics --- src/g_demo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_demo.c b/src/g_demo.c index 228b0f09d..d99c8b2cf 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -145,7 +145,7 @@ demoghost *ghosts = NULL; #define ZT_AIMING 64 #define ZT_LATENCY 128 #define ZT_FLAGS 256 -// OUT OF ZIPTICS... +// Ziptics are UINT16 now, go nuts #define DEMOMARKER 0x80 // demobuf.end From 3e2d7ff7e7ef78c7b1fe68c8e127f58dc783c983 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 25 Feb 2023 04:52:22 -0700 Subject: [PATCH 07/12] Correctly apply steering for easing purposes, fix sign on undershots --- src/p_user.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index b27bbb815..6db125a3b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2132,7 +2132,8 @@ 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. + INT16 targetsteering = K_UpdateSteeringValue(player->steering, player->cmd.turning); angleChange = K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE; if (!K_PlayerUsesBotMovement(player)) @@ -2140,7 +2141,7 @@ static void P_UpdatePlayerAngle(player_t *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, -1 * KART_FULLTURN); + 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? @@ -2150,7 +2151,7 @@ static void P_UpdatePlayerAngle(player_t *player) if (targetDelta == angleChange || player->pflags & PF_DRIFTEND) { // We are where we need to be. :) - + 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. @@ -2159,20 +2160,29 @@ static void P_UpdatePlayerAngle(player_t *player) 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. + 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) { From 6b3d6ed40651744c091ba62167b308f66f2a5e98 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 25 Feb 2023 15:54:06 -0700 Subject: [PATCH 08/12] Fix incorrect visual angle changes at race start Old ticcmds were trying to set angle, and didn't care whether the player was actually able to steer. The bug is always in your code. --- src/p_user.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 6db125a3b..6ca61d9f8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2134,7 +2134,7 @@ static void P_UpdatePlayerAngle(player_t *player) // Don't apply steering just yet. If we make a correction, we'll need to adjust it. INT16 targetsteering = K_UpdateSteeringValue(player->steering, player->cmd.turning); - angleChange = K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE; + angleChange = K_GetKartTurnValue(player, targetsteering) << TICCMD_REDUCE; if (!K_PlayerUsesBotMovement(player)) { @@ -2148,9 +2148,10 @@ static void P_UpdatePlayerAngle(player_t *player) angle_t targetAngle = (player->cmd.angle) << TICCMD_REDUCE; angle_t targetDelta = targetAngle - (player->mo->angle); - if (targetDelta == angleChange || player->pflags & PF_DRIFTEND) + if (targetDelta == angleChange || player->pflags & PF_DRIFTEND || (maxTurnRight == 0 && maxTurnLeft == 0)) { - // We are where we need to be. :) + // 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, @@ -2194,8 +2195,6 @@ static void P_UpdatePlayerAngle(player_t *player) { player->angleturn += angleChange; player->mo->angle = player->angleturn; - - // player->mo->angle += angleChange; } if (!cv_allowmlook.value || player->spectator == false) From 6647ed4b14fbba7a53e55a45067060d662644ab3 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 25 Feb 2023 15:56:38 -0700 Subject: [PATCH 09/12] Final cleanup of old experiments --- src/d_clisrv.c | 2 -- src/g_game.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 972be5ce4..f53d1f35a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1333,7 +1333,6 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i <= r_splitscreen; i++) { P_ForceLocalAngle(&players[displayplayers[i]], players[displayplayers[i]].angleturn); - //P_ForceLocalAngle(&players[displayplayers[i]], players[displayplayers[i]].cmd.angle); } for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) @@ -3649,7 +3648,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) } P_ForceLocalAngle(newplayer, newplayer->angleturn); - //P_ForceLocalAngle(newplayer, newplayer->cmd.angle); D_SendPlayerConfig(splitscreenplayer); addedtogame = true; diff --git a/src/g_game.c b/src/g_game.c index 9d2d34454..a1f9c560d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1096,7 +1096,7 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p } //if (player->pflags & PF_DRIFTEND) - if (false) + if (false) // Left here in case it needs unsealing later. This tried to replicate an old localcam function, but this behavior was unpopular in tests. { localangle[ssplayer - 1] = player->mo->angle; } From 95317d635df9013e0044fa155dfeca0c833a6f3e Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sat, 25 Feb 2023 23:04:39 -0700 Subject: [PATCH 10/12] Fix upward wind harlem shaking your camera This has not worked for an unknown period of time, but in this branch it was broken enough that it spun your turning intent out of control. --- src/p_spec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index e252bf374..0317599e4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -9100,15 +9100,17 @@ void T_Pusher(pusher_t *p) thing->player->carry = CR_SLIDING; thing->angle = R_PointToAngle2(0, 0, xspeed, yspeed); + if (!demo.playback) { - angle_t angle = thing->player->angleturn; + angle_t angle = thing->player->boostangle; if (thing->angle - angle > ANGLE_180) - P_SetPlayerAngle(thing->player, angle - (angle - thing->angle) / 8); + thing->player->boostangle = angle - (angle - thing->angle) / 8; else - P_SetPlayerAngle(thing->player, angle + (thing->angle - angle) / 8); + thing->player->boostangle = angle + (thing->angle - angle) / 8; //P_SetPlayerAngle(thing->player, thing->angle); } + } if (p->exclusive) From be4a2be1da061af8aaa7194b56f439a582b95336 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 26 Feb 2023 04:29:13 -0700 Subject: [PATCH 11/12] Fix unsteady camera movement in demos --- src/p_user.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 6ca61d9f8..a19437d0a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3186,7 +3186,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall 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 > starttime) + focusangle = player->cmd.angle << TICCMD_REDUCE; + else + focusangle = mo->angle; // Just use something known sane. focusaiming = 0; } else From 7788fa116f123977838f47064c13c16df3838640 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 26 Feb 2023 14:55:41 -0700 Subject: [PATCH 12/12] Review fixes --- src/g_demo.c | 18 +++++++++--------- src/g_game.c | 4 +++- src/p_user.c | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/g_demo.c b/src/g_demo.c index d99c8b2cf..c94386d31 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -136,15 +136,15 @@ demoghost *ghosts = NULL; #define DEMO_BOT 0x08 // For demos -#define ZT_FWD 1 -#define ZT_SIDE 2 -#define ZT_TURNING 4 -#define ZT_ANGLE 8 -#define ZT_THROWDIR 16 -#define ZT_BUTTONS 32 -#define ZT_AIMING 64 -#define ZT_LATENCY 128 -#define ZT_FLAGS 256 +#define ZT_FWD 0x0001 +#define ZT_SIDE 0x0002 +#define ZT_TURNING 0x0004 +#define ZT_ANGLE 0x0008 +#define ZT_THROWDIR 0x0010 +#define ZT_BUTTONS 0x0020 +#define ZT_AIMING 0x0040 +#define ZT_LATENCY 0x0080 +#define ZT_FLAGS 0x0100 // Ziptics are UINT16 now, go nuts #define DEMOMARKER 0x80 // demobuf.end diff --git a/src/g_game.c b/src/g_game.c index 12445cc50..d1689421e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1095,12 +1095,14 @@ static void G_DoAnglePrediction(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer, p 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) - if (false) // Left here in case it needs unsealing later. This tried to replicate an old localcam function, but this behavior was unpopular in tests. { localangle[ssplayer - 1] = player->mo->angle; } else +#endif { localangle[ssplayer - 1] += angleChange; } diff --git a/src/p_user.c b/src/p_user.c index a19437d0a..223af8f47 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3189,7 +3189,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // 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 > starttime) + if (leveltime > introtime) focusangle = player->cmd.angle << TICCMD_REDUCE; else focusangle = mo->angle; // Just use something known sane.