Turn solver refinements

This commit is contained in:
AJ Martinez 2025-05-03 16:00:14 -04:00
parent 93a4414802
commit 677b92b86a
3 changed files with 41 additions and 53 deletions

View file

@ -3451,10 +3451,6 @@ static fixed_t K_RingDurationBoost(const player_t *player)
return ret;
}
// v2 almost broke sliptiding when it fixed turning bugs!
// This value is fine-tuned to feel like v1 again without reverting any of those changes.
#define SLIPTIDEHANDLING 7*FRACUNIT/8
// sets boostpower, speedboost, accelboost, and handleboost to whatever we need it to be
static void K_GetKartBoostPower(player_t *player)
{
@ -3496,7 +3492,7 @@ static void K_GetKartBoostPower(player_t *player)
UINT8 i;
for (i = 0; i < player->numsneakers; i++)
{
ADDBOOST(FRACUNIT*85/100, 8*FRACUNIT, SLIPTIDEHANDLING+SLIPTIDEHANDLING/3); // + 50% top speed, + 800% acceleration, +50% handling
ADDBOOST(FRACUNIT*85/100, 8*FRACUNIT, HANDLESCALING+HANDLESCALING/3); // + 50% top speed, + 800% acceleration, +50% handling
}
}
@ -3505,7 +3501,7 @@ static void K_GetKartBoostPower(player_t *player)
UINT8 i;
for (i = 0; i < player->numpanelsneakers; i++)
{
ADDBOOST(FRACUNIT/2, 8*FRACUNIT, SLIPTIDEHANDLING); // + 50% top speed, + 800% acceleration, +50% handling
ADDBOOST(FRACUNIT/2, 8*FRACUNIT, HANDLESCALING); // + 50% top speed, + 800% acceleration, +50% handling
}
}
@ -3513,12 +3509,12 @@ static void K_GetKartBoostPower(player_t *player)
{
// S-Monitor: no extra %
fixed_t extra = FRACUNIT / 1400 * (player->invincibilitytimer - K_PowerUpRemaining(player, POWERUP_SMONITOR));
ADDBOOST(3*FRACUNIT/8 + extra, 3*FRACUNIT, SLIPTIDEHANDLING/2); // + 37.5 + ?% top speed, + 300% acceleration, +25% handling
ADDBOOST(3*FRACUNIT/8 + extra, 3*FRACUNIT, HANDLESCALING/2); // + 37.5 + ?% top speed, + 300% acceleration, +25% handling
}
if (player->growshrinktimer > 0) // Grow
{
ADDBOOST(0, 0, SLIPTIDEHANDLING/2); // + 0% top speed, + 0% acceleration, +25% handling
ADDBOOST(0, 0, HANDLESCALING/2); // + 0% top speed, + 0% acceleration, +25% handling
}
if (player->flamedash) // Flame Shield dash
@ -3527,7 +3523,7 @@ static void K_GetKartBoostPower(player_t *player)
ADDBOOST(
dash, // + infinite top speed
3*FRACUNIT, // + 300% acceleration
FixedMul(FixedDiv(dash, FRACUNIT/2), SLIPTIDEHANDLING/2) // + infinite handling
FixedMul(FixedDiv(dash, FRACUNIT/2), HANDLESCALING/2) // + infinite handling
);
}
@ -3537,13 +3533,13 @@ static void K_GetKartBoostPower(player_t *player)
ADDBOOST(
dash, // + infinite top speed
3*FRACUNIT, // + 300% acceleration
FixedMul(FixedDiv(dash, FRACUNIT/2), SLIPTIDEHANDLING/2) // + infinite handling
FixedMul(FixedDiv(dash, FRACUNIT/2), HANDLESCALING/2) // + infinite handling
);
}
if (player->wavedashboost)
{
// NB: This is intentionally under the 25% handleboost threshold required to initiate a sliptide
// NB: This is intentionally under the handleboost threshold required to initiate a sliptide
ADDBOOST(
Easing_InCubic(
player->wavedashpower,
@ -3555,7 +3551,7 @@ static void K_GetKartBoostPower(player_t *player)
0,
4*FRACUNIT
),
2*SLIPTIDEHANDLING/5
2*HANDLESCALING/5
); // + 80% top speed (peak), +400% acceleration (peak), +20% handling
}
@ -3572,7 +3568,7 @@ static void K_GetKartBoostPower(player_t *player)
0,
3*FRACUNIT
),
1*SLIPTIDEHANDLING/5
1*HANDLESCALING/5
); // + 80% top speed (peak), +400% acceleration (peak), +20% handling
}
@ -3591,12 +3587,12 @@ static void K_GetKartBoostPower(player_t *player)
if (player->startboost) // Startup Boost
{
ADDBOOST(FRACUNIT, 4*FRACUNIT, SLIPTIDEHANDLING); // + 100% top speed, + 400% acceleration, +50% handling
ADDBOOST(FRACUNIT, 4*FRACUNIT, HANDLESCALING); // + 100% top speed, + 400% acceleration, +50% handling
}
if (player->dropdashboost) // Drop dash
{
ADDBOOST(FRACUNIT/3, 4*FRACUNIT, SLIPTIDEHANDLING); // + 33% top speed, + 400% acceleration, +50% handling
ADDBOOST(FRACUNIT/3, 4*FRACUNIT, HANDLESCALING); // + 33% top speed, + 400% acceleration, +50% handling
}
if (player->driftboost) // Drift Boost
@ -3634,7 +3630,7 @@ static void K_GetKartBoostPower(player_t *player)
if (player->gateBoost) // SPB Juicebox boost
{
ADDBOOST(3*FRACUNIT/4, 4*FRACUNIT, SLIPTIDEHANDLING/2); // + 75% top speed, + 400% acceleration, +25% handling
ADDBOOST(3*FRACUNIT/4, 4*FRACUNIT, HANDLESCALING/2); // + 75% top speed, + 400% acceleration, +25% handling
}
if (player->ringboost) // Ring Boost
@ -3648,7 +3644,7 @@ static void K_GetKartBoostPower(player_t *player)
ADDBOOST(
ringboost_base + FixedMul(FRACUNIT / 1750, rb),
4*FRACUNIT,
Easing_InCubic(min(FRACUNIT, rb / (TICRATE*12)), 0, 2*SLIPTIDEHANDLING/5)
Easing_InCubic(min(FRACUNIT, rb / (TICRATE*12)), 0, 2*HANDLESCALING/5)
); // + 20% + ???% top speed, + 400% acceleration, +???% handling
}
@ -3715,7 +3711,7 @@ static void K_GetKartBoostPower(player_t *player)
{
// NB: This is an acceleration-only boost.
// If this is applied earlier in the chain, it will diminish real speed boosts.
ADDBOOST(0, FRACUNIT, 2*SLIPTIDEHANDLING/10); // 0% speed 100% accel 20% handle
ADDBOOST(0, FRACUNIT, 2*HANDLESCALING/10); // 0% speed 100% accel 20% handle
}
// This should always remain the last boost stack before tethering
@ -11274,11 +11270,11 @@ INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue)
if (G_CompatLevel(0x000A))
{
// Compat level for 2.0 staff ghosts
sliptide_handle = 5 * SLIPTIDEHANDLING / 4;
sliptide_handle = 5 * HANDLESCALING / 4;
}
else
{
sliptide_handle = 3 * SLIPTIDEHANDLING / 4;
sliptide_handle = 3 * HANDLESCALING / 4;
}
finalhandleboost = FixedMul(sliptide_handle, FixedDiv(player->speed, topspeed));
@ -11689,7 +11685,7 @@ static void K_KartDrift(player_t *player, boolean onground)
boolean extendedSliptide = false;
// We don't meet sliptide conditions!
if ((player->handleboost < (SLIPTIDEHANDLING/2))
if ((player->handleboost < SLIPTIDEHANDLING)
|| (!player->steering)
|| (!player->aizdriftstrat)
|| (player->steering > 0) != (player->aizdriftstrat > 0))

View file

@ -81,6 +81,13 @@ Make sure this matches the actual number of states
#define MAXTOPACCEL (12*FRACUNIT)
#define TOPACCELREGEN (FRACUNIT/16)
// Handling boosts and sliptide conditions got weird.
// You must be under a handling boost of at least SLIPTIDEHANDLING to sliptide.
// HANDLESCALING is used to adjust all handling boosts simultaneously (weight factors in the future?)
// If you need to touch this in an involved way later, please just make sliptide eligibility a flag LMAO
#define HANDLESCALING (7*FRACUNIT/8)
#define SLIPTIDEHANDLING (HANDLESCALING/2)
// Mispredicted turns can generate phantom sliptide inputs for a few tics.
// Delay the wavedash visuals until we're reasonably sure that it's a deliberate turn.
#define HIDEWAVEDASHCHARGE (60)

View file

@ -2337,9 +2337,10 @@ static void P_UpdatePlayerAngle(player_t *player)
else
{
// With a full slam on the analog stick, how far could we steer in either direction?
INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN);
INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -KART_FULLTURN);
INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN);
INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -KART_FULLTURN);
#ifdef SOLVERANGLECHEATS
// When entering/leaving drifts, allow all legal turns with no easing.
// This is the hardest case for the turn solver, because your handling properties on
// client side are very different than your handling properties on server side—at least,
@ -2349,6 +2350,7 @@ static void P_UpdatePlayerAngle(player_t *player)
steeringRight = KART_FULLTURN;
steeringLeft = -KART_FULLTURN;
}
#endif
angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE;
angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE;
@ -2357,47 +2359,31 @@ static void P_UpdatePlayerAngle(player_t *player)
angle_t targetAngle = (player->cmd.angle) << TICCMD_REDUCE;
angle_t targetDelta = targetAngle - (player->mo->angle);
#ifdef SOLVERANGLECHEATS
// Corrections via fake turn go through easing.
// 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...
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;
}
// Gross. Take a look at sliptide starts properly for 2.4.
// Yell at Tyron!
if (!G_CompatLevel(0x000C))
{
leniency_base = 6 * ANG1 / 3;
}
angle_t leniency_base = 2 * ANG1;
angle_t leniency = leniency_base * min(player->cmd.latency, 6);
// Don't force another turning tic, just give them the desired angle!
#endif
#if 0 // Old sliptide preservation behavior
if (K_Sliptiding(player) && P_IsObjectOnGround(player->mo) && (player->cmd.turning != 0) && ((player->cmd.turning > 0) == (player->aizdriftstrat > 0)))
if (!(player->cmd.buttons & BT_DRIFT) && (abs(player->drift) == 1) && ((player->cmd.turning > 0) == (player->drift > 0)) && player->handleboost > SLIPTIDEHANDLING)
{
// Don't change handling direction if someone's inputs are sliptiding, you'll break the sliptide!
if (player->cmd.turning > 0)
// This drift release is eligible to start a sliptide. Don't do lag-compensation countersteer behavior that could destroy it!
if (player->cmd.turning >= 0)
{
steeringLeft = max(steeringLeft, 1);
steeringRight = max(steeringRight, steeringLeft);
}
else
else if (player->cmd.turning <= 0)
{
steeringRight = min(steeringRight, -1);
steeringLeft = min(steeringLeft, steeringRight);
}
}
#else // Digital-friendly sliptide preservation behavior
if (K_Sliptiding(player) && P_IsObjectOnGround(player->mo))
{
// Unless someone explicitly inputs a turn that would break their sliptide, keep sliptiding.
@ -2411,12 +2397,7 @@ static void P_UpdatePlayerAngle(player_t *player)
steeringRight = min(steeringRight, -1);
steeringLeft = min(steeringLeft, steeringRight);
}
else
{
// :V
}
}
#endif
if (maxTurnRight == 0 && maxTurnLeft == 0)
{
@ -2426,13 +2407,17 @@ static void P_UpdatePlayerAngle(player_t *player)
else
{
// We're off. Try to legally steer the player towards their camera.
player->steering = P_FindClosestTurningForAngle(player, targetDelta, steeringLeft, steeringRight);
//CONS_Printf("aiz %d - dr %d - hb %d\n", player->aizdriftstrat, player->drift, player->handleboost);
//CONS_Printf("st %d - ts %d - t %d\n", player->steering, targetsteering, player->cmd.turning);
//CONS_Printf("%d\n", player->steering - targetsteering);
angleChange = K_GetKartTurnValue(player, player->steering) << TICCMD_REDUCE;
#ifdef SOLVERANGLECHEATS
// And if the resulting steering input is close enough, snap them exactly.
if (min(targetDelta - angleChange, angleChange - targetDelta) <= leniency)
angleChange = targetDelta;
#endif
}
}