diff --git a/src/g_demo.cpp b/src/g_demo.cpp index f11e6e214..a22595aad 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -161,7 +161,23 @@ demoghost *ghosts = NULL; // - 0x0009 (older staff ghosts) // - Player names, skin names and color names were 16 // bytes. See get_buffer_sizes(). -#define DEMOVERSION 0x000A +// - 0x000A (Ring Racers v2.0) +// - A bug was preventing control after ending a drift. +// Older behavior is kept around for staff ghost compat. + +#define DEMOVERSION 0x000B + +boolean G_CompatLevel(UINT16 level) +{ + if (demo.playback) + { + // Check gameplay differences for older ghosts + return (demo.version <= level); + } + + return false; +} + #define DEMOHEADER "\xF0" "KartReplay" "\x0F" #define DF_ATTACKMASK (ATTACKING_TIME|ATTACKING_LAP|ATTACKING_SPB) // This demo contains time/lap data diff --git a/src/g_demo.h b/src/g_demo.h index feb636640..a881aba3a 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -170,6 +170,8 @@ extern UINT8 demo_writerng; #define DXD_PST_SPECTATING 0x02 #define DXD_PST_LEFT 0x03 +boolean G_CompatLevel(UINT16 level); + // Record/playback tics void G_ReadDemoExtraData(void); void G_WriteDemoExtraData(void); diff --git a/src/k_kart.c b/src/k_kart.c index da4ab32fd..0128a544e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10456,16 +10456,24 @@ INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue) } else { - // Turning dampens as you go faster, but at extremely high speeds, keeping some control is important. - // Dampening is applied in two stages, one harsh and one soft. - // The harsh window is larger for characters with better baseline maneuverability. - // TODO COMPATLEVEL - // Was p_speed = min(stageSpeed, p_maxspeed * 2); - fixed_t stageSpeed = min(currentSpeed, (100 + 2*(9-player->kartweight)) * p_maxspeed/100); - if (stageSpeed < currentSpeed) - stageSpeed += (currentSpeed - stageSpeed) / 3; + if (G_CompatLevel(0x000A)) + { + // Compat level for 2.0 staff ghosts + p_speed = min(currentSpeed, p_maxspeed * 2); + } + else + { + // Turning dampens as you go faster, but at extremely high speeds, keeping some control is important. + // Dampening is applied in two stages, one harsh and one soft. + // The harsh window is larger for characters with better baseline maneuverability. + fixed_t stageSpeed = min(currentSpeed, (100 + 2*(9-player->kartweight)) * p_maxspeed/100); + if (stageSpeed < currentSpeed) + { + stageSpeed += (currentSpeed - stageSpeed) / 3; + } - p_speed = min(stageSpeed, p_maxspeed * 2); + p_speed = min(stageSpeed, p_maxspeed * 2); + } } if (K_PodiumSequence() == true) @@ -10486,20 +10494,34 @@ INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue) if (player->drift != 0 && P_IsObjectOnGround(player->mo)) { - if (player->pflags & PF_DRIFTEND) + if (G_CompatLevel(0x000A)) { - // Sal: K_GetKartDriftValue is short-circuited to give a weird additive magic number, - // instead of an entirely replaced turn value. This gaslit me years ago when I was doing a - // code readability pass, where I missed that fact because it also returned early. - // TODO COMPATLEVEL (I have no fucking clue what's going on here) - turnfixed += K_GetKartDriftValue(player, FRACUNIT) * FRACUNIT; - return (turnfixed / FRACUNIT); + // Compat level for 2.0 staff ghosts + fixed_t countersteer = FixedDiv(turnfixed, KART_FULLTURN * FRACUNIT); + + if (player->pflags & PF_DRIFTEND) + { + countersteer = FRACUNIT; + } + + return K_GetKartDriftValue(player, countersteer); } else { - // If we're drifting we have a completely different turning value - fixed_t countersteer = FixedDiv(turnfixed, KART_FULLTURN * FRACUNIT); - return K_GetKartDriftValue(player, countersteer); + if (player->pflags & PF_DRIFTEND) + { + // Sal: K_GetKartDriftValue is short-circuited to give a weird additive magic number, + // instead of an entirely replaced turn value. This gaslit me years ago when I was doing a + // code readability pass, where I missed that fact because it also returned early. + turnfixed += K_GetKartDriftValue(player, FRACUNIT) * FRACUNIT; + return (turnfixed / FRACUNIT); + } + else + { + // If we're drifting we have a completely different turning value + fixed_t countersteer = FixedDiv(turnfixed, KART_FULLTURN * FRACUNIT); + return K_GetKartDriftValue(player, countersteer); + } } } @@ -10510,8 +10532,19 @@ INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue) fixed_t topspeed = K_GetKartSpeed(player, false, false); if (K_Sliptiding(player)) { - // TODO COMPATLEVEL (was 5*SLIPTIDEHANDLING/4) - finalhandleboost = FixedMul(3*SLIPTIDEHANDLING/4, FixedDiv(player->speed, topspeed)); + fixed_t sliptide_handle; + + if (G_CompatLevel(0x000A)) + { + // Compat level for 2.0 staff ghosts + sliptide_handle = 5 * SLIPTIDEHANDLING / 4; + } + else + { + sliptide_handle = 3 * SLIPTIDEHANDLING / 4; + } + + finalhandleboost = FixedMul(sliptide_handle, FixedDiv(player->speed, topspeed)); } if (finalhandleboost > 0 && player->respawn.state == RESPAWNST_NONE) diff --git a/src/p_user.c b/src/p_user.c index 4595af553..fc0c0bd23 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2338,8 +2338,17 @@ static void P_UpdatePlayerAngle(player_t *player) // That means undoing them takes the same amount of time as doing them. // This can lead to oscillating death spiral states on a multi-tic correction, as we swing past the target angle. // So before we go into death-spirals, if our predicton is _almost_ right... - // TODO COMPATLEVEL (was 4*ANG1/3) - angle_t leniency = (8*ANG1/3) * min(player->cmd.latency, 6); + angle_t leniency_base; + if (G_CompatLevel(0x000A)) + { + // Compat level for 2.0 staff ghosts + leniency_base = 4 * ANG1 / 3; + } + else + { + leniency_base = 8 * ANG1 / 3; + } + angle_t leniency = leniency_base * min(player->cmd.latency, 6); // Don't force another turning tic, just give them the desired angle! if (targetDelta == angleChange || (maxTurnRight == 0 && maxTurnLeft == 0))