From 0beaae5f55567430f39243c79695b1fcf3e37551 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 27 Jan 2026 02:07:47 -0500 Subject: [PATCH 01/14] start spindash/ssmt --- src/d_netcmd.c | 4 ++++ src/d_netcmd.h | 4 ++++ src/d_player.h | 7 ++++++- src/k_kart.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/k_kart.h | 4 ++++ src/p_inter.c | 2 ++ 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 1c00dac5e..ea3f00b28 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -549,6 +549,10 @@ consvar_t cv_kartstacking_ring_accelboost = CVAR_INIT ("vanillaboost_ring_accelb consvar_t cv_kartstacking_ring_handleboost = CVAR_INIT ("vanillaboost_ring_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_OnOff, NULL); +consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.1", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "65535.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); + consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_brakemod = CVAR_INIT ("vanillaboost_slope_brakemod", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_speedboost_max = CVAR_INIT ("vanillaboost_slope_speedboost_max", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 92aa7df48..1123d3a71 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -167,6 +167,10 @@ extern consvar_t cv_kartstacking_ring_accelboost; extern consvar_t cv_kartstacking_ring_handleboost; extern consvar_t cv_kartstacking_ring_stackable; +extern consvar_t cv_kartstacking_ssmt_speedboost; +extern consvar_t cv_kartstacking_ssmt_accelboost; +extern consvar_t cv_kartstacking_ssmt_handleboost; + extern consvar_t cv_kartstacking_slope_decay; extern consvar_t cv_kartstacking_slope_brakemod; extern consvar_t cv_kartstacking_slope_speedboost_max; diff --git a/src/d_player.h b/src/d_player.h index b6b7bb4e6..2ecf2cf8b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -103,8 +103,9 @@ typedef enum PF_SHRINKACTIVE = 1<<26, // "Shrink me" cheat is in effect. (Can't be disabled mid-race) PF_JUSTFLIPPED = 1<<27, // Just got flipped over, handle the bump interaction. + + PF_CHARGINGSSMT = 1<<28, // Player was charging SSMT last tick - // up to 1<<28 is free PF_USEDOWN = 1<<29, // For lua compat, don't use! PF_ATTACKDOWN = 1<<30, // For lua compat, don't use! PF_SLIDING = 1<<31, // For lua compat, don't use! @@ -598,6 +599,9 @@ struct player_t // Potentially influenced by player lag. tic_t driftdelay; + tic_t ssmtcharge; // Time spent charging SSMT + UINT16 ssmtboost; // SSMT boost timer (weak boost that ignores offroad) + fixed_t spinoutrot; // When a player spins out, this value increments modulus 360. SINT8 aizdriftstrat; // (-1 to 1) - Let go of your drift while boosting? Helper for the SICK STRATZ (sliptiding!) you have just unlocked @@ -619,6 +623,7 @@ struct player_t fixed_t prevspeedboost; // Max speed boost value from the last frame fixed_t accelboost; // Boost value smoothing for acceleration fixed_t handleboost; // Boost value smoothing for handling + fixed_t forcedtopspeed; // Force this top speed while charging SSMT angle_t boostangle; // angle set when not spun out OR boosted to determine what direction you should keep going at if you're spun out and boosted. boostinfo_t boostinfo; // Stores values used for setting speed and accel boosts. UINT8 numsneakers; // Number of stacked sneakers diff --git a/src/k_kart.c b/src/k_kart.c index 22e880273..f65770105 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2832,6 +2832,11 @@ static void K_GetKartBoostPower(player_t *player) K_DoBoost(player, RINGSPEEDBOOST, RINGACCELBOOST, RINGHANDLEBOOST, RINGSTACKABLE, RINGSTACKABLE); // + 20% top speed, + 400% acceleration } + if (player->ssmtboost) // Ring Boost + { + K_DoBoost(player, SSMTSPEEDBOOST, SSMTACCELBOOST, SSMTHANDLEBOOST, false, true); // + 10% top speed, + ♾️% acceleration + } + if (player->slopeboost || player->slopeaccel) { K_DoBoost(player, player->slopeboost, player->slopeaccel, 0, SLOPESTACKABLE, false); // + ???% top speed, + 300% acceleration @@ -2964,6 +2969,9 @@ fixed_t K_GetKartSpeed(const player_t *player, boolean doboostpower, boolean dor boolean karmabomb = ((gametyperules & GTR_BUMPERS) && player->bumper <= 0); fixed_t finalspeed; + if (player->forcedtopspeed > 0) + return FixedMul(player->forcedtopspeed, player->mo->scale); + if (doboostpower && !player->pogospring && !P_IsObjectOnGround(player->mo) && (player->airdriftspeed == 0)) return (75*mapobjectscale); // air speed cap @@ -3093,7 +3101,7 @@ SINT8 K_GetForwardMove(const player_t *player) player->flipovertimer) // pw_introcam? { forwardmove = 0; - if (player->sneakertimer) + if (player->sneakertimer || player->ssmtboost) forwardmove = MAXPLMOVE; } @@ -7041,6 +7049,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Speed lines if (player->sneakertimer || player->ringboost || player->driftboost || player->startboost + || player->ssmtboost || player->walltransferboost || player->bubbleboost) { @@ -7239,6 +7248,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->realsneakertimer) player->realsneakertimer--; + if (player->ssmtboost) + player->ssmtboost--; + if (player->sneakertimer && player->wipeoutslow > 0 && player->wipeoutslow < wipeoutslowtime+1) player->wipeoutslow = wipeoutslowtime+1; @@ -9611,6 +9623,41 @@ static void K_KartSlipdash(player_t *player, boolean onground) } } +static void K_StandStillMiniTurbo(player_t *player, boolean onground) +{ + if (player->speed <= 8*player->mo->scale && onground) + { + if (player->cmd.buttons & BT_ACCELERATE|BT_BRAKE) + { + player->pflags |= PF_CHARGINGSSMT; + player->forcedtopspeed = 8*FRACUNIT; + player->ssmtcharge += 1; + K_SpawnDashDustRelease(player, true); + if (player->ssmtcharge >= 3*TICRATE/2) + { + K_SpawnBoostTrail(player); + } + + return; + } + else if (player->pflags & PF_CHARGINGSSMT) + { + player->pflags &= ~PF_CHARGINGSSMT; + player->forcedtopspeed = 0; + if (player->ssmtcharge >= 3*TICRATE/2) + { + player->ssmtboost = TICRATE; + } + player->ssmtcharge = 0; + + return; + } + } + player->pflags &= ~PF_CHARGINGSSMT; + player->forcedtopspeed = 0; + player->ssmtcharge = 0; +} + INT32 K_GetDriftAngleOffset(player_t *player) { INT32 a = 0; @@ -11058,10 +11105,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_KartSlipdash(player, onground); + K_StandStillMiniTurbo(player, onground); + // Quick Turning // You can't turn your kart when you're not moving. // So now it's time to burn some rubber! - if (player->speed < 2 && leveltime > starttime && player->cmd.buttons & BT_ACCELERATE && player->cmd.buttons & BT_BRAKE && player->cmd.turning != 0) + if (player->speed < 2 && leveltime > starttime && (player->cmd.buttons & BT_ACCELERATE|BT_BRAKE) && player->cmd.turning != 0) { if (leveltime % 8 == 0) S_StartSound(player->mo, sfx_s224); diff --git a/src/k_kart.h b/src/k_kart.h index 8eb01ef09..564ebec8e 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -163,6 +163,10 @@ extern vector3_t clusterpoint, clusterdtf; #define RINGHANDLEBOOST CV_Get(&cv_kartstacking_ring_handleboost) #define RINGSTACKABLE CV_Get(&cv_kartstacking_ring_stackable) +#define SSMTSPEEDBOOST CV_Get(&cv_kartstacking_ssmt_speedboost) +#define SSMTACCELBOOST CV_Get(&cv_kartstacking_ssmt_accelboost) +#define SSMTHANDLEBOOST CV_Get(&cv_kartstacking_ssmt_handleboost) + #define SLOPEDECAY CV_Get(&cv_kartstacking_slope_decay) #define SLOPEBRAKEMOD CV_Get(&cv_kartstacking_slope_brakemod) #define SLOPESPEEDBOOSTMAX CV_Get(&cv_kartstacking_slope_speedboost_max) diff --git a/src/p_inter.c b/src/p_inter.c index 7d9613a14..ce51ade36 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2337,6 +2337,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } player->driftboost = 0; + player->ssmtboost = 0; + player->ssmtcharge = 0; player->airdriftspeed = 0; player->ringboost = 0; player->glanceDir = 0; From d2062ae680629f899a5d83847a0c91c8c51f08cc Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 27 Jan 2026 02:21:05 -0500 Subject: [PATCH 02/14] make ssmt boost ignore offroad, charging ssmt resist offroad --- src/k_kart.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index f65770105..96e9201f2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1050,6 +1050,11 @@ static void K_UpdateOffroad(player_t *player) offroadstrength *= 2; } } + else if (player->pflags & PF_CHARGINGSSMT) + { + offroad = offroad/2; + offroadstrength = offroadstrength/2; + } player->offroad += offroad; } @@ -2167,7 +2172,9 @@ boolean K_ApplyOffroad(const player_t *player) if (modeattacking != ATTACKING_NONE) sneakertimer = player->sneakertimer > 0; - if (player->hyudorotimer || sneakertimer || (cv_kartbubble_boost_offroadignore.value && player->bubbleboost)) + if (player->hyudorotimer || sneakertimer || + (cv_kartbubble_boost_offroadignore.value && player->bubbleboost) || + player->ssmtboost) return false; return true; } From d068c1dfc5d8d6e8f691de1a706640b04d43f38b Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 27 Jan 2026 03:21:42 -0500 Subject: [PATCH 03/14] control tweaks, give boost values --- src/d_netcmd.c | 4 ++-- src/g_game.c | 7 +++++-- src/k_kart.c | 32 +++++++++++++++++++------------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index ea3f00b28..2ec00e0cb 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -550,8 +550,8 @@ consvar_t cv_kartstacking_ring_handleboost = CVAR_INIT ("vanillaboost_ring_handl consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_OnOff, NULL); consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.1", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "65535.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "10.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_brakemod = CVAR_INIT ("vanillaboost_slope_brakemod", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); diff --git a/src/g_game.c b/src/g_game.c index 4e5bc2cc1..853357cbb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1540,14 +1540,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) forward += (value * MAXPLMOVE) / JOYAXISRANGE; } - if (player->sneakertimer) + if (player->sneakertimer || player->ssmtboost) forward = MAXPLMOVE; // 50 value = G_PlayerInputAnalog(forplayer, gc_brake, false, DEADZONE_BUTTON); if (value != 0) { cmd->buttons |= BT_BRAKE; - forward -= (value * 25) / JOYAXISRANGE; + if (!(player->pflags & PF_CHARGINGSSMT)) + { + forward -= (value * 25) / JOYAXISRANGE; + } } // But forward/backward IS used for aiming. diff --git a/src/k_kart.c b/src/k_kart.c index 96e9201f2..f8b75534f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -357,6 +357,10 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartstacking_ring_handleboost); CV_RegisterVar(&cv_kartstacking_ring_stackable); + CV_RegisterVar(&cv_kartstacking_ssmt_speedboost); + CV_RegisterVar(&cv_kartstacking_ssmt_accelboost); + CV_RegisterVar(&cv_kartstacking_ssmt_handleboost); + CV_RegisterVar(&cv_kartstacking_slope_decay); CV_RegisterVar(&cv_kartstacking_slope_brakemod); CV_RegisterVar(&cv_kartstacking_slope_speedboost_max); @@ -1050,11 +1054,6 @@ static void K_UpdateOffroad(player_t *player) offroadstrength *= 2; } } - else if (player->pflags & PF_CHARGINGSSMT) - { - offroad = offroad/2; - offroadstrength = offroadstrength/2; - } player->offroad += offroad; } @@ -2174,7 +2173,7 @@ boolean K_ApplyOffroad(const player_t *player) if (player->hyudorotimer || sneakertimer || (cv_kartbubble_boost_offroadignore.value && player->bubbleboost) || - player->ssmtboost) + player->ssmtboost || (player->pflags & PF_CHARGINGSSMT)) return false; return true; } @@ -3108,7 +3107,7 @@ SINT8 K_GetForwardMove(const player_t *player) player->flipovertimer) // pw_introcam? { forwardmove = 0; - if (player->sneakertimer || player->ssmtboost) + if (player->sneakertimer) forwardmove = MAXPLMOVE; } @@ -9632,14 +9631,18 @@ static void K_KartSlipdash(player_t *player, boolean onground) static void K_StandStillMiniTurbo(player_t *player, boolean onground) { - if (player->speed <= 8*player->mo->scale && onground) + if (player->speed <= 12*player->mo->scale && onground && leveltime > starttime) { - if (player->cmd.buttons & BT_ACCELERATE|BT_BRAKE) + if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { player->pflags |= PF_CHARGINGSSMT; - player->forcedtopspeed = 8*FRACUNIT; + player->forcedtopspeed = 12*FRACUNIT; player->ssmtcharge += 1; - K_SpawnDashDustRelease(player, true); + if (leveltime % 8 == 0) + { + K_SpawnDashDustRelease(player, true); + S_StartSound(player->mo, sfx_s224); + } if (player->ssmtcharge >= 3*TICRATE/2) { K_SpawnBoostTrail(player); @@ -9653,7 +9656,10 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) player->forcedtopspeed = 0; if (player->ssmtcharge >= 3*TICRATE/2) { - player->ssmtboost = TICRATE; + player->outruntime = TICRATE/4; + player->ssmtboost = TICRATE/2; + player->tiregrease = TICRATE; + S_StartSound(player->mo, sfx_s23c); } player->ssmtcharge = 0; @@ -11117,7 +11123,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Quick Turning // You can't turn your kart when you're not moving. // So now it's time to burn some rubber! - if (player->speed < 2 && leveltime > starttime && (player->cmd.buttons & BT_ACCELERATE|BT_BRAKE) && player->cmd.turning != 0) + if (player->speed < 2 && leveltime > starttime && (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE) && player->cmd.turning != 0) { if (leveltime % 8 == 0) S_StartSound(player->mo, sfx_s224); From 21e1ebc0bca5b07f2d1481f1d86117704775da0c Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 27 Jan 2026 18:13:54 -0500 Subject: [PATCH 04/14] reorder some logic, more effects and visual cues --- src/d_netcmd.c | 2 +- src/k_kart.c | 121 ++++++++++++++++++++++++++++++++++++------------- src/p_mobj.c | 2 +- src/p_user.c | 6 +-- 4 files changed, 95 insertions(+), 36 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2ec00e0cb..d5fe821de 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -550,7 +550,7 @@ consvar_t cv_kartstacking_ring_handleboost = CVAR_INIT ("vanillaboost_ring_handl consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_OnOff, NULL); consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.1", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "10.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "25.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); diff --git a/src/k_kart.c b/src/k_kart.c index f8b75534f..fad8513d2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9150,7 +9150,7 @@ UINT8 K_GetKartDriftSparkStageForValue(const player_t *player, INT32 value) } } -static void K_SpawnDriftEFX(player_t *player,SINT8 level) +static void K_SpawnDriftEFX(player_t *player, SINT8 level) { mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME); P_SetMobjState(overlay, S_DRIFTBOOSTFLAME); @@ -9285,6 +9285,10 @@ static void K_KartDrift(player_t *player, boolean onground) // This fixes this problem. if (player->pogospring == 2 && player->mo->scale > mapobjectscale) minspeed = FixedMul(10<pflags & PF_CHARGINGSSMT) + minspeed = (player->speed+1); // air thrust drag if (K_AirThrustActive()) @@ -9482,7 +9486,7 @@ static void K_KartDrift(player_t *player, boolean onground) // Stop drifting // experiment: wall transfers should allow zero speed // reasoning: when driving right into a half pipe face-on, there is no h-speed for the entire launch - if (player->walltransfered || player->dashRingPullTics || player->dashRingPushTics) + if ((player->walltransfered || player->dashRingPullTics || player->dashRingPushTics) && !(player->pflags & PF_CHARGINGSSMT)) { minspeed = 0; } @@ -9629,46 +9633,94 @@ static void K_KartSlipdash(player_t *player, boolean onground) } } +static boolean K_PlayerCanStartSsmt(player_t *player) +{ + return (player->speed <= 12*player->mo->scale && (!(player->pflags & PF_CHARGINGSSMT)) && + (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)); +} + +static boolean K_PlayerCanChargeSsmt(player_t *player) +{ + return (P_IsObjectOnGround(player->mo) && leveltime > starttime); +} + static void K_StandStillMiniTurbo(player_t *player, boolean onground) { - if (player->speed <= 12*player->mo->scale && onground && leveltime > starttime) + if (K_PlayerCanChargeSsmt(player)) { - if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) + if (K_PlayerCanStartSsmt(player)) { player->pflags |= PF_CHARGINGSSMT; - player->forcedtopspeed = 12*FRACUNIT; - player->ssmtcharge += 1; - if (leveltime % 8 == 0) - { - K_SpawnDashDustRelease(player, true); - S_StartSound(player->mo, sfx_s224); - } - if (player->ssmtcharge >= 3*TICRATE/2) - { - K_SpawnBoostTrail(player); - } - - return; + S_StartSound(player->mo, sfx_cdfm20); } - else if (player->pflags & PF_CHARGINGSSMT) + if (player->pflags & PF_CHARGINGSSMT) { - player->pflags &= ~PF_CHARGINGSSMT; - player->forcedtopspeed = 0; - if (player->ssmtcharge >= 3*TICRATE/2) + if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { - player->outruntime = TICRATE/4; - player->ssmtboost = TICRATE/2; - player->tiregrease = TICRATE; - S_StartSound(player->mo, sfx_s23c); - } - player->ssmtcharge = 0; + player->ssmtcharge += 1; + player->forcedtopspeed = FixedMul(K_GetKartSpeedFromStat(player->kartspeed, false) + 2, player->mo->scale) / 3; + K_SpawnWipeoutTrail(player->mo, (player->ssmtcharge < 3*TICRATE/2)); - return; + if (leveltime % 6 == 0) + { + if (player->ssmtcharge < 3*TICRATE/2) + { + S_StartSound(player->mo, sfx_s225); + } + } + if (player->ssmtcharge >= 3*TICRATE/2) + { + if (player->ssmtcharge == 3*TICRATE/2) + { + S_StartSound(player->mo, sfx_s3ka2); + } + if (leveltime & 1) + { + fixed_t newx; + fixed_t newy; + mobj_t *spark; + angle_t travelangle; + travelangle = player->mo->angle; + for (INT32 i = 0; i < 2; i++) + { + newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); + newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); + spark = P_SpawnMobj(newx, newy, player->mo->z, MT_DRIFTSPARK); + spark->momx = player->mo->momx/2; + spark->momy = player->mo->momy/2; + + P_SetTarget(&spark->target, player->mo); + spark->angle = travelangle; + spark->color = SKINCOLOR_WHITE; + + P_SetMobjState(spark, S_DRIFTSPARK_A1); + K_MatchGenericExtraFlags(spark, player->mo); + } + } + } + } + else + { + player->pflags &= ~PF_CHARGINGSSMT; + player->forcedtopspeed = 0; + if (player->ssmtcharge >= 3*TICRATE/2) + { + player->outruntime = TICRATE/3; + player->ssmtboost = TICRATE/2; + player->tiregrease = TICRATE; + S_StartSound(player->mo, sfx_s23c); + K_SpawnDashDustRelease(player, true); + } + player->ssmtcharge = 0; + } } } - player->pflags &= ~PF_CHARGINGSSMT; - player->forcedtopspeed = 0; - player->ssmtcharge = 0; + else + { + player->pflags &= ~PF_CHARGINGSSMT; + player->forcedtopspeed = 0; + player->ssmtcharge = 0; + } } INT32 K_GetDriftAngleOffset(player_t *player) @@ -10677,6 +10729,13 @@ static void K_AdjustPlayerFriction(player_t *player) player->mo->friction = prevfriction; + if (player->pflags & PF_CHARGINGSSMT) + { + player->mo->friction += 1280; + + K_RecalculateMovefactor(player->mo); + } + // Reduce friction after exiting a loop. if (player->tiregrease) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 2a35f9c72..49281650d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8923,7 +8923,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (p) { - if (mobj->extravalue1) + if (mobj->extravalue1 > 0) { if (p->driftboost > mobj->movecount) { diff --git a/src/p_user.c b/src/p_user.c index fa1006847..086b19833 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2296,13 +2296,13 @@ void P_MovePlayer(player_t *player) // Drifting sound // Start looping the sound now. - if (leveltime % 50 == 0 && onground && player->drift != 0) + if (leveltime % 50 == 0 && onground && (player->drift != 0 || (player->pflags & PF_CHARGINGSSMT))) S_StartSound(player->mo, sfx_drift); // Leveltime being 50 might take a while at times. We'll start it up once, isntantly. - else if (!S_SoundPlaying(player->mo, sfx_drift) && onground && player->drift != 0) + else if (!S_SoundPlaying(player->mo, sfx_drift) && onground && (player->drift != 0 || (player->pflags & PF_CHARGINGSSMT))) S_StartSound(player->mo, sfx_drift); // Ok, we'll stop now. - else if (player->drift == 0 || !onground) + else if ((player->drift == 0 && !(player->pflags & PF_CHARGINGSSMT)) || (!onground)) S_StopSoundByID(player->mo, sfx_drift); K_MoveKartPlayer(player, onground); From a536af526e75088c05140c81caaa3bab1acd0db7 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 27 Jan 2026 18:46:07 -0500 Subject: [PATCH 05/14] some adjustment need to do more but will have to hold --- src/d_netcmd.c | 4 ++-- src/k_kart.c | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d5fe821de..a6aad1bfe 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -549,8 +549,8 @@ consvar_t cv_kartstacking_ring_accelboost = CVAR_INIT ("vanillaboost_ring_accelb consvar_t cv_kartstacking_ring_handleboost = CVAR_INIT ("vanillaboost_ring_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_OnOff, NULL); -consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.1", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "25.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.05", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); diff --git a/src/k_kart.c b/src/k_kart.c index fad8513d2..70b1dfa9a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2838,9 +2838,14 @@ static void K_GetKartBoostPower(player_t *player) K_DoBoost(player, RINGSPEEDBOOST, RINGACCELBOOST, RINGHANDLEBOOST, RINGSTACKABLE, RINGSTACKABLE); // + 20% top speed, + 400% acceleration } - if (player->ssmtboost) // Ring Boost + if (player->ssmtboost) // SSMT Boost { - K_DoBoost(player, SSMTSPEEDBOOST, SSMTACCELBOOST, SSMTHANDLEBOOST, false, true); // + 10% top speed, + ♾️% acceleration + K_DoBoost(player, SSMTSPEEDBOOST, SSMTACCELBOOST, SSMTHANDLEBOOST, false, true); // + 10% top speed, + ?% acceleration + } + + if (player->pflags & PF_CHARGINGSSMT) + { + K_DoBoost(player, 0, 2*FRACUNIT, FRACUNIT/2, false, false); //+ 200% acceleration } if (player->slopeboost || player->slopeaccel) @@ -9658,19 +9663,19 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { player->ssmtcharge += 1; - player->forcedtopspeed = FixedMul(K_GetKartSpeedFromStat(player->kartspeed, false) + 2, player->mo->scale) / 3; + player->forcedtopspeed = FixedMul(K_GetKartSpeedFromStat(player->kartspeed, false) + 4, player->mo->scale) / 3; K_SpawnWipeoutTrail(player->mo, (player->ssmtcharge < 3*TICRATE/2)); if (leveltime % 6 == 0) { - if (player->ssmtcharge < 3*TICRATE/2) + if (player->ssmtcharge < 2*TICRATE) { S_StartSound(player->mo, sfx_s225); } } - if (player->ssmtcharge >= 3*TICRATE/2) + if (player->ssmtcharge >= 2*TICRATE) { - if (player->ssmtcharge == 3*TICRATE/2) + if (player->ssmtcharge == 2*TICRATE) { S_StartSound(player->mo, sfx_s3ka2); } @@ -9703,11 +9708,10 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) { player->pflags &= ~PF_CHARGINGSSMT; player->forcedtopspeed = 0; - if (player->ssmtcharge >= 3*TICRATE/2) + if (player->ssmtcharge >= 2*TICRATE) { - player->outruntime = TICRATE/3; - player->ssmtboost = TICRATE/2; - player->tiregrease = TICRATE; + player->ssmtboost = TICRATE; + player->tiregrease = 2*TICRATE; S_StartSound(player->mo, sfx_s23c); K_SpawnDashDustRelease(player, true); } From 92e74dca272c85341f036b571c35bc01b611a39a Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 27 Jan 2026 21:45:10 -0500 Subject: [PATCH 06/14] lots of performance tuning for recovery dash crawling: accelerates faster when in flashtics, capped at a fixed 22 fu/t for all stats, is slipperier recovery dash: accelerates much slower, lasts longer ssmt charge is maintained when going airborne instead of being completely lost --- src/d_player.h | 4 ++-- src/g_game.c | 2 +- src/k_kart.c | 62 ++++++++++++++++++++++++++++++-------------------- src/p_inter.c | 4 ++-- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 2ecf2cf8b..a3c843ac3 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -599,8 +599,8 @@ struct player_t // Potentially influenced by player lag. tic_t driftdelay; - tic_t ssmtcharge; // Time spent charging SSMT - UINT16 ssmtboost; // SSMT boost timer (weak boost that ignores offroad) + tic_t recoverydashcharge; // Time spent charging SSMT + UINT16 recoverydash; // SSMT boost timer (weak boost that ignores offroad) fixed_t spinoutrot; // When a player spins out, this value increments modulus 360. diff --git a/src/g_game.c b/src/g_game.c index 853357cbb..5cf06a093 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1540,7 +1540,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) forward += (value * MAXPLMOVE) / JOYAXISRANGE; } - if (player->sneakertimer || player->ssmtboost) + if (player->sneakertimer || player->recoverydash) forward = MAXPLMOVE; // 50 value = G_PlayerInputAnalog(forplayer, gc_brake, false, DEADZONE_BUTTON); diff --git a/src/k_kart.c b/src/k_kart.c index 70b1dfa9a..95b8a363f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2173,7 +2173,7 @@ boolean K_ApplyOffroad(const player_t *player) if (player->hyudorotimer || sneakertimer || (cv_kartbubble_boost_offroadignore.value && player->bubbleboost) || - player->ssmtboost || (player->pflags & PF_CHARGINGSSMT)) + player->recoverydash || (player->pflags & PF_CHARGINGSSMT)) return false; return true; } @@ -2838,14 +2838,21 @@ static void K_GetKartBoostPower(player_t *player) K_DoBoost(player, RINGSPEEDBOOST, RINGACCELBOOST, RINGHANDLEBOOST, RINGSTACKABLE, RINGSTACKABLE); // + 20% top speed, + 400% acceleration } - if (player->ssmtboost) // SSMT Boost + if (player->recoverydash) // SSMT Boost { K_DoBoost(player, SSMTSPEEDBOOST, SSMTACCELBOOST, SSMTHANDLEBOOST, false, true); // + 10% top speed, + ?% acceleration } - if (player->pflags & PF_CHARGINGSSMT) + if ((player->pflags & PF_CHARGINGSSMT)) { - K_DoBoost(player, 0, 2*FRACUNIT, FRACUNIT/2, false, false); //+ 200% acceleration + if (player->flashing || player->recoverydashcharge >= TICRATE) + { + K_DoBoost(player, 1, 4*FRACUNIT, FRACUNIT/4, false, false); // + 400% acceleration, + 25% handling + } + else + { + K_DoBoost(player, 1, 2*FRACUNIT, FRACUNIT/4, false, false);// + 200% acceleration, + 25% handling + } } if (player->slopeboost || player->slopeaccel) @@ -7060,7 +7067,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Speed lines if (player->sneakertimer || player->ringboost || player->driftboost || player->startboost - || player->ssmtboost + || player->recoverydash || player->walltransferboost || player->bubbleboost) { @@ -7259,8 +7266,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->realsneakertimer) player->realsneakertimer--; - if (player->ssmtboost) - player->ssmtboost--; + if (player->recoverydash) + player->recoverydash--; if (player->sneakertimer && player->wipeoutslow > 0 && player->wipeoutslow < wipeoutslowtime+1) player->wipeoutslow = wipeoutslowtime+1; @@ -9640,13 +9647,14 @@ static void K_KartSlipdash(player_t *player, boolean onground) static boolean K_PlayerCanStartSsmt(player_t *player) { - return (player->speed <= 12*player->mo->scale && (!(player->pflags & PF_CHARGINGSSMT)) && + return (P_IsObjectOnGround(player->mo) && player->speed <= 10*player->mo->scale && (!(player->pflags & PF_CHARGINGSSMT)) && (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)); } static boolean K_PlayerCanChargeSsmt(player_t *player) { - return (P_IsObjectOnGround(player->mo) && leveltime > starttime); + return (leveltime > starttime && + !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || player->exiting)); } static void K_StandStillMiniTurbo(player_t *player, boolean onground) @@ -9662,20 +9670,23 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) { if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { - player->ssmtcharge += 1; - player->forcedtopspeed = FixedMul(K_GetKartSpeedFromStat(player->kartspeed, false) + 4, player->mo->scale) / 3; - K_SpawnWipeoutTrail(player->mo, (player->ssmtcharge < 3*TICRATE/2)); - - if (leveltime % 6 == 0) + player->forcedtopspeed = 22*FRACUNIT; + if (P_IsObjectOnGround(player->mo)) { - if (player->ssmtcharge < 2*TICRATE) + player->recoverydashcharge += 1; + K_SpawnWipeoutTrail(player->mo, (player->recoverydashcharge < 3*TICRATE/2)); + + if (leveltime % 6 == 0) { - S_StartSound(player->mo, sfx_s225); + if (player->recoverydashcharge < 2*TICRATE) + { + S_StartSound(player->mo, sfx_s225); + } } } - if (player->ssmtcharge >= 2*TICRATE) + if (player->recoverydashcharge >= 2*TICRATE) { - if (player->ssmtcharge == 2*TICRATE) + if (player->recoverydashcharge == 2*TICRATE) { S_StartSound(player->mo, sfx_s3ka2); } @@ -9708,14 +9719,16 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) { player->pflags &= ~PF_CHARGINGSSMT; player->forcedtopspeed = 0; - if (player->ssmtcharge >= 2*TICRATE) + player->tiregrease = 2*TICRATE; + if (player->recoverydashcharge >= 2*TICRATE && (player->cmd.buttons & BT_ACCELERATE)) { - player->ssmtboost = TICRATE; - player->tiregrease = 2*TICRATE; + player->outrun = TICRATE/4; + player->recoverydash = TICRATE; + player->flashing = 0; S_StartSound(player->mo, sfx_s23c); K_SpawnDashDustRelease(player, true); } - player->ssmtcharge = 0; + player->recoverydashcharge = 0; } } } @@ -9723,7 +9736,7 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) { player->pflags &= ~PF_CHARGINGSSMT; player->forcedtopspeed = 0; - player->ssmtcharge = 0; + player->recoverydashcharge = 0; } } @@ -10735,8 +10748,7 @@ static void K_AdjustPlayerFriction(player_t *player) if (player->pflags & PF_CHARGINGSSMT) { - player->mo->friction += 1280; - + player->mo->friction += 1500; K_RecalculateMovefactor(player->mo); } diff --git a/src/p_inter.c b/src/p_inter.c index ce51ade36..97b0add7a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2337,8 +2337,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } player->driftboost = 0; - player->ssmtboost = 0; - player->ssmtcharge = 0; + player->recoverydash = 0; + player->recoverydashcharge = 0; player->airdriftspeed = 0; player->ringboost = 0; player->glanceDir = 0; From dd15f7cc67b0ee9df9a70ef53c3ac8c48f788653 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 02:00:11 -0500 Subject: [PATCH 07/14] billion config cvars, add recovery dash to menus --- src/d_main.cpp | 2 +- src/d_netcmd.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- src/d_netcmd.h | 11 +++++++++++ src/k_kart.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- src/k_kart.h | 9 +++++++++ src/p_mobj.h | 1 + src/p_setup.c | 1 + 7 files changed, 110 insertions(+), 13 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index c98a9b2cd..e1e6c3722 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -93,7 +93,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0xbfb32f5c97ecf875 +#define ASSET_HASH_MAIN_PK3 0x74f5f90d7c8b863d #define ASSET_HASH_MAPPATCH_PK3 0xbbc2c6a7a685da3a #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a6aad1bfe..df85b273b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -170,6 +170,7 @@ static void KartSlopeBoost_OnChange(void); static void KartDrafting_OnChange(void); static void KartAirDrop_OnChange(void); static void KartAirThrust_OnChange(void); +static void KartRecoveryDash_OnChange(void); static void KartWaterSkipLock_OnChange(void); static void KartItemLitter_OnChange(void); static void KartItemPush_OnChange(void); @@ -549,9 +550,17 @@ consvar_t cv_kartstacking_ring_accelboost = CVAR_INIT ("vanillaboost_ring_accelb consvar_t cv_kartstacking_ring_handleboost = CVAR_INIT ("vanillaboost_ring_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_ring_stackable = CVAR_INIT ("vanillaboost_ring_stackable", "On", CV_NETVAR|CV_CHEAT|CV_GUARD, CV_OnOff, NULL); -consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.05", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_speedboost = CVAR_INIT ("vanillaboost_ssmt_speedboost", "0.1", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_ssmt_accelboost = CVAR_INIT ("vanillaboost_ssmt_accelboost", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ssmt_handleboost = CVAR_INIT ("vanillaboost_ssmt_handleboost", "0.1", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_recspin_speedboost_lo = CVAR_INIT ("vanillaboost_recspin_speedboost_lo", "0.0001", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_recspin_accelboost_lo = CVAR_INIT ("vanillaboost_recspin_accelboost_lo", "2.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_recspin_handleboost_lo = CVAR_INIT ("vanillaboost_recspin_handleboost_lo", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_recspin_speedboost_hi = CVAR_INIT ("vanillaboost_recspin_speedboost_hi", "0.0001", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_recspin_accelboost_hi = CVAR_INIT ("vanillaboost_recspin_accelboost_hi", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_recspin_handleboost_hi = CVAR_INIT ("vanillaboost_recspin_handleboost_hi", "0.3", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_brakemod = CVAR_INIT ("vanillaboost_slope_brakemod", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); @@ -621,6 +630,9 @@ consvar_t cv_kartforcelegacyodds = CVAR_INIT ("kartforcelegacyodds", "Off", CV_N consvar_t cv_handleboostslip = CVAR_INIT ("karthandleboostsliptide", "Off", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_kartrecoverydash = CVAR_INIT ("kartrecoverydash", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartRecoveryDash_OnChange); +consvar_t cv_kartrecoverydash_spinspeed = CVAR_INIT ("kartrecoverydash_spinspeed", "22.0", CV_NETVAR|CV_FLOAT|CV_CHEAT|CV_GUARD, CV_Unsigned, NULL); + #define ANTIBUMP_MAX (UINT32_MAX / TICRATE) static CV_PossibleValue_t antibump_cons_t[] = {{0, "MIN"}, {ANTIBUMP_MAX, "MAX"}, {0, NULL}}; consvar_t cv_kartantibump = CVAR_INIT ("kartantibump", "0", CV_NETVAR|CV_CALL|CV_NOINIT, antibump_cons_t, KartAntiBump_OnChange); @@ -8504,6 +8516,39 @@ static void KartAirThrust_OnChange(void) } } +static void KartRecoveryDash_OnChange(void) +{ + if (K_CanChangeRules(false) == false) + { + return; + } + + if (!K_RecoveryDashActive() && cv_kartrecoverydash.value) + { + if (leveltime < starttime) + { + recoverydashactive = true; + CONS_Printf(M_GetText("Recovery Dash has been turned \"On\".\n")); + } + else + { + CONS_Printf(M_GetText("Recovery Dash will be turned \"On\" Next Round.\n")); + } + } + else if (K_RecoveryDashActive() && !cv_kartrecoverydash.value) + { + if (leveltime < starttime) + { + recoverydashactive = false; + CONS_Printf(M_GetText("Recovery Dash has been turned \"Off\".\n")); + } + else + { + CONS_Printf(M_GetText("Recovery Dash will be turned \"Off\" next round.\n")); + } + } +} + static void KartWaterSkipLock_OnChange(void) { if (K_CanChangeRules(false) == false) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 1123d3a71..8b5b1cc66 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -171,6 +171,14 @@ extern consvar_t cv_kartstacking_ssmt_speedboost; extern consvar_t cv_kartstacking_ssmt_accelboost; extern consvar_t cv_kartstacking_ssmt_handleboost; +extern consvar_t cv_kartstacking_recspin_speedboost_lo; +extern consvar_t cv_kartstacking_recspin_accelboost_lo; +extern consvar_t cv_kartstacking_recspin_handleboost_lo; + +extern consvar_t cv_kartstacking_recspin_speedboost_hi; +extern consvar_t cv_kartstacking_recspin_accelboost_hi; +extern consvar_t cv_kartstacking_recspin_handleboost_hi; + extern consvar_t cv_kartstacking_slope_decay; extern consvar_t cv_kartstacking_slope_brakemod; extern consvar_t cv_kartstacking_slope_speedboost_max; @@ -234,6 +242,9 @@ extern consvar_t cv_kartforcelegacyodds; extern consvar_t cv_handleboostslip; +extern consvar_t cv_kartrecoverydash; +extern consvar_t cv_kartrecoverydash_spinspeed; + extern consvar_t cv_kartoddsdist; extern consvar_t cv_kartlegacyoddsdist; diff --git a/src/k_kart.c b/src/k_kart.c index 95b8a363f..0695a6f9d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -361,6 +361,13 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartstacking_ssmt_accelboost); CV_RegisterVar(&cv_kartstacking_ssmt_handleboost); + CV_RegisterVar(&cv_kartstacking_recspin_speedboost_lo); + CV_RegisterVar(&cv_kartstacking_recspin_accelboost_lo); + CV_RegisterVar(&cv_kartstacking_recspin_handleboost_lo); + CV_RegisterVar(&cv_kartstacking_recspin_speedboost_hi); + CV_RegisterVar(&cv_kartstacking_recspin_accelboost_hi); + CV_RegisterVar(&cv_kartstacking_recspin_handleboost_hi); + CV_RegisterVar(&cv_kartstacking_slope_decay); CV_RegisterVar(&cv_kartstacking_slope_brakemod); CV_RegisterVar(&cv_kartstacking_slope_speedboost_max); @@ -411,6 +418,9 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartslopeboost); + CV_RegisterVar(&cv_kartrecoverydash); + CV_RegisterVar(&cv_kartrecoverydash_spinspeed); + CV_RegisterVar(&cv_kartaltshrinktime); CV_RegisterVar(&cv_kartinvintheme); @@ -2847,11 +2857,11 @@ static void K_GetKartBoostPower(player_t *player) { if (player->flashing || player->recoverydashcharge >= TICRATE) { - K_DoBoost(player, 1, 4*FRACUNIT, FRACUNIT/4, false, false); // + 400% acceleration, + 25% handling + K_DoBoost(player, RECSPINSPEEDBOOSTHI, RECSPINACCELBOOSTHI, RECSPINHANDLEBOOSTHI, false, false); // + 500% acceleration, + 25% handling } else { - K_DoBoost(player, 1, 2*FRACUNIT, FRACUNIT/4, false, false);// + 200% acceleration, + 25% handling + K_DoBoost(player, RECSPINSPEEDBOOSTLO, RECSPINACCELBOOSTLO, RECSPINHANDLEBOOSTLO, false, false);// + 200% acceleration, + 25% handling } } @@ -9647,17 +9657,18 @@ static void K_KartSlipdash(player_t *player, boolean onground) static boolean K_PlayerCanStartSsmt(player_t *player) { - return (P_IsObjectOnGround(player->mo) && player->speed <= 10*player->mo->scale && (!(player->pflags & PF_CHARGINGSSMT)) && + return (K_RecoveryDashActive() && P_IsObjectOnGround(player->mo) && + player->speed <= 12*player->mo->scale && (!(player->pflags & PF_CHARGINGSSMT)) && (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)); } static boolean K_PlayerCanChargeSsmt(player_t *player) { - return (leveltime > starttime && + return (K_RecoveryDashActive() && leveltime > starttime && !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || player->exiting)); } -static void K_StandStillMiniTurbo(player_t *player, boolean onground) +static void K_StandStillMiniTurbo(player_t *player) { if (K_PlayerCanChargeSsmt(player)) { @@ -9670,7 +9681,7 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) { if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { - player->forcedtopspeed = 22*FRACUNIT; + player->forcedtopspeed = cv_kartrecoverydash_spinspeed.value; if (P_IsObjectOnGround(player->mo)) { player->recoverydashcharge += 1; @@ -9695,8 +9706,9 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) fixed_t newx; fixed_t newy; mobj_t *spark; - angle_t travelangle; + angle_t travelangle, sparkangle; travelangle = player->mo->angle; + sparkangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); for (INT32 i = 0; i < 2; i++) { newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(32*FRACUNIT, player->mo->scale)); @@ -9706,10 +9718,17 @@ static void K_StandStillMiniTurbo(player_t *player, boolean onground) spark->momy = player->mo->momy/2; P_SetTarget(&spark->target, player->mo); - spark->angle = travelangle; + spark->angle = sparkangle; spark->color = SKINCOLOR_WHITE; - P_SetMobjState(spark, S_DRIFTSPARK_A1); + if (player->recoverydashcharge >= 2*TICRATE + TICRATE/4) + { + P_SetMobjState(spark, S_DRIFTSPARK_B1); + } + else + { + P_SetMobjState(spark, S_DRIFTSPARK_A1); + } K_MatchGenericExtraFlags(spark, player->mo); } } @@ -11193,7 +11212,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_KartSlipdash(player, onground); - K_StandStillMiniTurbo(player, onground); + K_StandStillMiniTurbo(player); // Quick Turning // You can't turn your kart when you're not moving. @@ -11558,6 +11577,17 @@ boolean K_AirThrustActive(void) return false; } +boolean K_RecoveryDashActive(void) +{ + if (recoverydashactive) + { + // Recovery Dash is enabled! + return true; + } + + return false; +} + boolean K_WaterskipBricksActive(void) { if (waterskipbricks) diff --git a/src/k_kart.h b/src/k_kart.h index 564ebec8e..5b4d9830c 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -167,6 +167,14 @@ extern vector3_t clusterpoint, clusterdtf; #define SSMTACCELBOOST CV_Get(&cv_kartstacking_ssmt_accelboost) #define SSMTHANDLEBOOST CV_Get(&cv_kartstacking_ssmt_handleboost) +#define RECSPINSPEEDBOOSTLO CV_Get(&cv_kartstacking_recspin_speedboost_lo) +#define RECSPINACCELBOOSTLO CV_Get(&cv_kartstacking_recspin_accelboost_lo) +#define RECSPINHANDLEBOOSTLO CV_Get(&cv_kartstacking_recspin_handleboost_lo) + +#define RECSPINSPEEDBOOSTHI CV_Get(&cv_kartstacking_recspin_speedboost_hi) +#define RECSPINACCELBOOSTHI CV_Get(&cv_kartstacking_recspin_accelboost_hi) +#define RECSPINHANDLEBOOSTHI CV_Get(&cv_kartstacking_recspin_handleboost_hi) + #define SLOPEDECAY CV_Get(&cv_kartstacking_slope_decay) #define SLOPEBRAKEMOD CV_Get(&cv_kartstacking_slope_brakemod) #define SLOPESPEEDBOOSTMAX CV_Get(&cv_kartstacking_slope_speedboost_max) @@ -375,6 +383,7 @@ boolean K_SlopeBoostActive(void); boolean K_DraftingActive(void); boolean K_AirDropActive(void); boolean K_AirThrustActive(void); +boolean K_RecoveryDashActive(void); boolean K_WaterskipBricksActive(void); boolean K_ItemLitterActive(void); boolean K_ItemListActive(void); diff --git a/src/p_mobj.h b/src/p_mobj.h index 4f828cf25..80f0447ba 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -619,6 +619,7 @@ extern boolean slopeboostactive; extern boolean draftingactive; extern boolean airdropactive; extern boolean airthrustactive; +extern boolean recoverydashactive; extern boolean waterskipbricks; extern boolean itemlittering; extern boolean itempushing; diff --git a/src/p_setup.c b/src/p_setup.c index 112378981..80ff25a52 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -162,6 +162,7 @@ boolean slopeboostactive; boolean draftingactive; boolean airdropactive; boolean airthrustactive; +boolean recoverydashactive; boolean waterskipbricks; boolean itemlittering; boolean itempushing; From 030fc9909981299edd1d87a977e65bb476464570 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 02:19:16 -0500 Subject: [PATCH 08/14] netsync and expose to lua --- src/lua_playerlib.c | 18 ++++++++++++++++-- src/p_saveg.c | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 7a1622492..8570a8589 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -455,7 +455,9 @@ static int lib_lenLocalplayers(lua_State *L) X(loop) \ X(prevonground) \ X(walltransfered) \ - X(walltransferboost) + X(walltransferboost) \ + X(recoverydashcharge) \ + X(recoverydash) enum player_e { @@ -1185,6 +1187,12 @@ static int player_get(lua_State *L) case player_walltransferboost: lua_pushinteger(L, plr->walltransferboost); break; + case player_recoverydashcharge: + lua_pushinteger(L, plr->recoverydashcharge); + break; + case player_recoverydash: + lua_pushinteger(L, plr->recoverydash); + break; #ifdef HWRENDER case player_fovadd: lua_pushfixed(L, plr->fovadd); @@ -1936,7 +1944,13 @@ static int player_set(lua_State *L) plr->walltransfered = lua_toboolean(L, 3); break; case player_walltransferboost: - plr->walltransferboost= lua_tointeger(L, 3); + plr->walltransferboost = lua_tointeger(L, 3); + break; + case player_recoverydashcharge: + plr->recoverydashcharge = lua_tointeger(L, 3); + break; + case player_recoverydash: + plr->recoverydash = lua_tointeger(L, 3); break; #ifdef HWRENDER case player_fovadd: diff --git a/src/p_saveg.c b/src/p_saveg.c index b2343b002..5973d51a7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -614,6 +614,9 @@ static void P_NetSyncPlayers(savebuffer_t *save) SYNC(players[i].driftboost); SYNC(players[i].airdriftspeed); + SYNC(players[i].recoverydashcharge); + SYNC(players[i].recoverydash); + SYNC(players[i].aizdriftstrat); SYNC(players[i].aizdrifttilt); SYNC(players[i].aizdriftturn); From 7ae5065b612cf8eadd7b7284e76e19fd207c9475 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 14:08:45 -0500 Subject: [PATCH 09/14] synch this too --- src/p_saveg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 5973d51a7..2623a7956 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -636,6 +636,7 @@ static void P_NetSyncPlayers(savebuffer_t *save) SYNC(players[i].prevspeedboost); SYNC(players[i].accelboost); SYNC(players[i].handleboost); + SYNC(players[i].forcedtopspeed); SYNC(players[i].boostangle); SYNC(players[i].numsneakers); SYNC(players[i].numpanels); From 52aa5543b13b4cdb207a29135e2de93715024d85 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 15:26:29 -0500 Subject: [PATCH 10/14] time to be semantically correct --- src/d_player.h | 2 +- src/g_game.c | 2 +- src/k_kart.c | 42 +++++++++++++++++++++--------------------- src/p_user.c | 6 +++--- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index a3c843ac3..bd615c632 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -104,7 +104,7 @@ typedef enum PF_JUSTFLIPPED = 1<<27, // Just got flipped over, handle the bump interaction. - PF_CHARGINGSSMT = 1<<28, // Player was charging SSMT last tick + PF_RECOVERYSPIN = 1<<28, // Player was charging SSMT last tick PF_USEDOWN = 1<<29, // For lua compat, don't use! PF_ATTACKDOWN = 1<<30, // For lua compat, don't use! diff --git a/src/g_game.c b/src/g_game.c index 5cf06a093..71adedadb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1547,7 +1547,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (value != 0) { cmd->buttons |= BT_BRAKE; - if (!(player->pflags & PF_CHARGINGSSMT)) + if (!(player->pflags & PF_RECOVERYSPIN)) { forward -= (value * 25) / JOYAXISRANGE; } diff --git a/src/k_kart.c b/src/k_kart.c index 0695a6f9d..a60b8b04a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2183,7 +2183,7 @@ boolean K_ApplyOffroad(const player_t *player) if (player->hyudorotimer || sneakertimer || (cv_kartbubble_boost_offroadignore.value && player->bubbleboost) || - player->recoverydash || (player->pflags & PF_CHARGINGSSMT)) + player->recoverydash || (player->pflags & PF_RECOVERYSPIN)) return false; return true; } @@ -2853,7 +2853,7 @@ static void K_GetKartBoostPower(player_t *player) K_DoBoost(player, SSMTSPEEDBOOST, SSMTACCELBOOST, SSMTHANDLEBOOST, false, true); // + 10% top speed, + ?% acceleration } - if ((player->pflags & PF_CHARGINGSSMT)) + if ((player->pflags & PF_RECOVERYSPIN)) { if (player->flashing || player->recoverydashcharge >= TICRATE) { @@ -9309,7 +9309,7 @@ static void K_KartDrift(player_t *player, boolean onground) minspeed = FixedMul(10<pflags & PF_CHARGINGSSMT) + if (player->pflags & PF_RECOVERYSPIN) minspeed = (player->speed+1); // air thrust drag @@ -9508,7 +9508,7 @@ static void K_KartDrift(player_t *player, boolean onground) // Stop drifting // experiment: wall transfers should allow zero speed // reasoning: when driving right into a half pipe face-on, there is no h-speed for the entire launch - if ((player->walltransfered || player->dashRingPullTics || player->dashRingPushTics) && !(player->pflags & PF_CHARGINGSSMT)) + if ((player->walltransfered || player->dashRingPullTics || player->dashRingPushTics) && !(player->pflags & PF_RECOVERYSPIN)) { minspeed = 0; } @@ -9655,33 +9655,33 @@ static void K_KartSlipdash(player_t *player, boolean onground) } } -static boolean K_PlayerCanStartSsmt(player_t *player) +static boolean K_PlayerCanStartRecoverySpin(player_t *player) { - return (K_RecoveryDashActive() && P_IsObjectOnGround(player->mo) && - player->speed <= 12*player->mo->scale && (!(player->pflags & PF_CHARGINGSSMT)) && - (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)); + return (K_RecoveryDashActive() && P_IsObjectOnGround(player->mo) && (!(player->pflags & PF_STASIS)) && (player->carry == CR_NONE) && + player->speed <= 12*player->mo->scale && (!(player->pflags & PF_RECOVERYSPIN)) && + (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE) && !(player->cmd.buttons & BT_DRIFT)); } -static boolean K_PlayerCanChargeSsmt(player_t *player) +static boolean K_PlayerCanRecoverySpin(player_t *player) { - return (K_RecoveryDashActive() && leveltime > starttime && + return (K_RecoveryDashActive() && leveltime > starttime && (!(player->pflags & PF_STASIS)) && (player->carry == CR_NONE) && !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || player->exiting)); } -static void K_StandStillMiniTurbo(player_t *player) +static void K_RecoveryDash(player_t *player) { - if (K_PlayerCanChargeSsmt(player)) + if (K_PlayerCanRecoverySpin(player)) { - if (K_PlayerCanStartSsmt(player)) + if (K_PlayerCanStartRecoverySpin(player)) { - player->pflags |= PF_CHARGINGSSMT; + player->pflags |= PF_RECOVERYSPIN; S_StartSound(player->mo, sfx_cdfm20); } - if (player->pflags & PF_CHARGINGSSMT) + if (player->pflags & PF_RECOVERYSPIN) { if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { - player->forcedtopspeed = cv_kartrecoverydash_spinspeed.value; + player->forcedtopspeed = cv_kartrecoverydash_spinspeed.value + 1; if (P_IsObjectOnGround(player->mo)) { player->recoverydashcharge += 1; @@ -9736,7 +9736,7 @@ static void K_StandStillMiniTurbo(player_t *player) } else { - player->pflags &= ~PF_CHARGINGSSMT; + player->pflags &= ~PF_RECOVERYSPIN; player->forcedtopspeed = 0; player->tiregrease = 2*TICRATE; if (player->recoverydashcharge >= 2*TICRATE && (player->cmd.buttons & BT_ACCELERATE)) @@ -9753,7 +9753,7 @@ static void K_StandStillMiniTurbo(player_t *player) } else { - player->pflags &= ~PF_CHARGINGSSMT; + player->pflags &= ~PF_RECOVERYSPIN; player->forcedtopspeed = 0; player->recoverydashcharge = 0; } @@ -10765,7 +10765,7 @@ static void K_AdjustPlayerFriction(player_t *player) player->mo->friction = prevfriction; - if (player->pflags & PF_CHARGINGSSMT) + if (player->pflags & PF_RECOVERYSPIN) { player->mo->friction += 1500; K_RecalculateMovefactor(player->mo); @@ -11212,12 +11212,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) K_KartSlipdash(player, onground); - K_StandStillMiniTurbo(player); + K_RecoveryDash(player); // Quick Turning // You can't turn your kart when you're not moving. // So now it's time to burn some rubber! - if (player->speed < 2 && leveltime > starttime && (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE) && player->cmd.turning != 0) + if (player->speed < 2 && leveltime > starttime && player->cmd.buttons & BT_ACCELERATE && player->cmd.buttons & BT_BRAKE && player->cmd.turning != 0) { if (leveltime % 8 == 0) S_StartSound(player->mo, sfx_s224); diff --git a/src/p_user.c b/src/p_user.c index 086b19833..a58cb63be 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2296,13 +2296,13 @@ void P_MovePlayer(player_t *player) // Drifting sound // Start looping the sound now. - if (leveltime % 50 == 0 && onground && (player->drift != 0 || (player->pflags & PF_CHARGINGSSMT))) + if (leveltime % 50 == 0 && onground && (player->drift != 0 || (player->pflags & PF_RECOVERYSPIN))) S_StartSound(player->mo, sfx_drift); // Leveltime being 50 might take a while at times. We'll start it up once, isntantly. - else if (!S_SoundPlaying(player->mo, sfx_drift) && onground && (player->drift != 0 || (player->pflags & PF_CHARGINGSSMT))) + else if (!S_SoundPlaying(player->mo, sfx_drift) && onground && (player->drift != 0 || (player->pflags & PF_RECOVERYSPIN))) S_StartSound(player->mo, sfx_drift); // Ok, we'll stop now. - else if ((player->drift == 0 && !(player->pflags & PF_CHARGINGSSMT)) || (!onground)) + else if ((player->drift == 0 && !(player->pflags & PF_RECOVERYSPIN)) || (!onground)) S_StopSoundByID(player->mo, sfx_drift); K_MoveKartPlayer(player, onground); From 6a43983da69e742a9c00b4af46535e1af7e9737d Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 15:56:13 -0500 Subject: [PATCH 11/14] =?UTF-8?q?bro=20=F0=9F=A5=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/p_saveg.c | 1 + src/p_setup.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 2623a7956..0b8fb89dc 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4241,6 +4241,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNCBOOLEAN(draftingactive); SYNCBOOLEAN(airdropactive); SYNCBOOLEAN(airthrustactive); + SYNCBOOLEAN(recoverydashactive); SYNCBOOLEAN(waterskipbricks); SYNCBOOLEAN(itemlittering); SYNCBOOLEAN(itempushing); diff --git a/src/p_setup.c b/src/p_setup.c index 80ff25a52..35dc4b2f6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8185,6 +8185,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) draftingactive = false; airdropactive = false; airthrustactive = false; + recoverydashactive = false; waterskipbricks = false; itemlittering = false; itempushing = false; @@ -8219,6 +8220,9 @@ static void P_InitLevelSettings(boolean reloadinggamestate) if (cv_kartairthrust.value) airthrustactive = true; + if (cv_kartrecoverydash.value) + recoverydashactive = true; + if (cv_kartwaterskiplock.value) waterskipbricks = true; From 7a3b3407b57dc6894ad56d5410a3683b3925b02d Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 16:52:51 -0500 Subject: [PATCH 12/14] final(?) tuning --- src/d_netcmd.c | 2 +- src/k_kart.c | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index df85b273b..92b8d9bb8 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -631,7 +631,7 @@ consvar_t cv_kartforcelegacyodds = CVAR_INIT ("kartforcelegacyodds", "Off", CV_N consvar_t cv_handleboostslip = CVAR_INIT ("karthandleboostsliptide", "Off", CV_NETVAR, CV_OnOff, NULL); consvar_t cv_kartrecoverydash = CVAR_INIT ("kartrecoverydash", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartRecoveryDash_OnChange); -consvar_t cv_kartrecoverydash_spinspeed = CVAR_INIT ("kartrecoverydash_spinspeed", "22.0", CV_NETVAR|CV_FLOAT|CV_CHEAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartrecoverydash_spinspeed = CVAR_INIT ("kartrecoverydash_spinspeed", "24.0", CV_NETVAR|CV_FLOAT|CV_CHEAT|CV_GUARD, CV_Unsigned, NULL); #define ANTIBUMP_MAX (UINT32_MAX / TICRATE) static CV_PossibleValue_t antibump_cons_t[] = {{0, "MIN"}, {ANTIBUMP_MAX, "MAX"}, {0, NULL}}; diff --git a/src/k_kart.c b/src/k_kart.c index a60b8b04a..1c76c336c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9658,14 +9658,14 @@ static void K_KartSlipdash(player_t *player, boolean onground) static boolean K_PlayerCanStartRecoverySpin(player_t *player) { return (K_RecoveryDashActive() && P_IsObjectOnGround(player->mo) && (!(player->pflags & PF_STASIS)) && (player->carry == CR_NONE) && - player->speed <= 12*player->mo->scale && (!(player->pflags & PF_RECOVERYSPIN)) && + player->speed < 10*player->mo->scale && (!(player->pflags & PF_RECOVERYSPIN)) && (player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE) && !(player->cmd.buttons & BT_DRIFT)); } static boolean K_PlayerCanRecoverySpin(player_t *player) { - return (K_RecoveryDashActive() && leveltime > starttime && (!(player->pflags & PF_STASIS)) && (player->carry == CR_NONE) && - !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || player->exiting)); + return (K_RecoveryDashActive() && leveltime > starttime && (player->carry == CR_NONE) && + !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || player->exiting || (player->pflags & PF_STASIS))); } static void K_RecoveryDash(player_t *player) @@ -9681,7 +9681,7 @@ static void K_RecoveryDash(player_t *player) { if ((player->cmd.buttons & BT_ACCELERATE) && (player->cmd.buttons & BT_BRAKE)) { - player->forcedtopspeed = cv_kartrecoverydash_spinspeed.value + 1; + player->forcedtopspeed = cv_kartrecoverydash_spinspeed.value + 8; if (P_IsObjectOnGround(player->mo)) { player->recoverydashcharge += 1; @@ -10767,7 +10767,10 @@ static void K_AdjustPlayerFriction(player_t *player) if (player->pflags & PF_RECOVERYSPIN) { - player->mo->friction += 1500; + if (player->cmd.turning) + player->mo->friction += 2048; + else + player->mo->friction += 1228; K_RecalculateMovefactor(player->mo); } From 7696bb37cc543fc72bfcc0b987c6cbed4c2e2959 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 18:49:06 -0500 Subject: [PATCH 13/14] fix friction related issues --- src/d_netcmd.c | 4 ++-- src/k_kart.c | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 92b8d9bb8..f13b53579 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -559,8 +559,8 @@ consvar_t cv_kartstacking_recspin_accelboost_lo = CVAR_INIT ("vanillaboost_recsp consvar_t cv_kartstacking_recspin_handleboost_lo = CVAR_INIT ("vanillaboost_recspin_handleboost_lo", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_recspin_speedboost_hi = CVAR_INIT ("vanillaboost_recspin_speedboost_hi", "0.0001", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_recspin_accelboost_hi = CVAR_INIT ("vanillaboost_recspin_accelboost_hi", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); -consvar_t cv_kartstacking_recspin_handleboost_hi = CVAR_INIT ("vanillaboost_recspin_handleboost_hi", "0.3", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_recspin_accelboost_hi = CVAR_INIT ("vanillaboost_recspin_accelboost_hi", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_recspin_handleboost_hi = CVAR_INIT ("vanillaboost_recspin_handleboost_hi", "0.5", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_decay = CVAR_INIT ("vanillaboost_slope_decay", "0.004", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_slope_brakemod = CVAR_INIT ("vanillaboost_slope_brakemod", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); diff --git a/src/k_kart.c b/src/k_kart.c index 1c76c336c..5ace447d3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9665,7 +9665,10 @@ static boolean K_PlayerCanStartRecoverySpin(player_t *player) static boolean K_PlayerCanRecoverySpin(player_t *player) { return (K_RecoveryDashActive() && leveltime > starttime && (player->carry == CR_NONE) && - !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || player->exiting || (player->pflags & PF_STASIS))); + !(player->sneakertimer || K_IsPlayerDamaged(player) || player->squishedtimer || + player->exiting || (player->pflags & PF_STASIS) || player->dashpadcooldown || + player->walltransferboost || player->loop.radius + )); } static void K_RecoveryDash(player_t *player) @@ -10765,10 +10768,10 @@ static void K_AdjustPlayerFriction(player_t *player) player->mo->friction = prevfriction; - if (player->pflags & PF_RECOVERYSPIN) + if ((player->pflags & PF_RECOVERYSPIN) && player->speed < K_GetKartSpeedFromStat(player->kartspeed, false)) { if (player->cmd.turning) - player->mo->friction += 2048; + player->mo->friction += 1800; else player->mo->friction += 1228; K_RecalculateMovefactor(player->mo); From 92c4c8c21aface429b0e96eeca80257b78b1aab6 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 28 Jan 2026 21:44:05 -0500 Subject: [PATCH 14/14] skid overlay note: needs cleaning up, overlay doesn't seem to position itself correctly? --- src/d_main.cpp | 2 +- src/info/sprites.h | 3 +++ src/info/states.h | 3 +++ src/k_kart.c | 41 +++++++++++++++++++++++++++++++++++++++-- src/p_mobj.c | 2 ++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index e1e6c3722..d00bdf210 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -93,7 +93,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x74f5f90d7c8b863d +#define ASSET_HASH_MAIN_PK3 0x6a399991c4467fe6 #define ASSET_HASH_MAPPATCH_PK3 0xbbc2c6a7a685da3a #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/info/sprites.h b/src/info/sprites.h index 0f8c11cbb..74b3bfa27 100644 --- a/src/info/sprites.h +++ b/src/info/sprites.h @@ -653,5 +653,8 @@ _(SSWG) // Arrow Bullet _(AWBT) +// Recovery Spin Skid +_(RCSP) + // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later _(VIEW) diff --git a/src/info/states.h b/src/info/states.h index c58c239e9..7440fdeff 100644 --- a/src/info/states.h +++ b/src/info/states.h @@ -3621,3 +3621,6 @@ _(GHORIZ4) // Arrow Bullet _(ALTSHRINK_ARROWBULLET) +// Recovery Spin Skid +_(RECSPIN_SKID) + diff --git a/src/k_kart.c b/src/k_kart.c index 5ace447d3..500e6ee11 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9697,6 +9697,43 @@ static void K_RecoveryDash(player_t *player) S_StartSound(player->mo, sfx_s225); } } + if (leveltime % 4 == 0) + { + fixed_t newx; + fixed_t newy; + mobj_t *skid; + angle_t travelangle; + travelangle = player->mo->angle; + for (INT32 i = 0; i < 2; i++) + { + newx = P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(28*FRACUNIT, player->mo->scale)); + newy = P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(28*FRACUNIT, player->mo->scale)); + skid = P_SpawnMobjFromMobj(player->mo, newx, newy, (10*player->mo->scale), MT_OVERLAY); + P_SetTarget(&skid->target, player->mo); + skid->sprxoff = newx; + skid->spryoff = newy; + skid->sprzoff = (10*player->mo->scale); + + P_SetScale(skid, player->mo->scale); + skid->destscale = player->mo->destscale; + skid->scalespeed = player->mo->scalespeed; + skid->movefactor = FRACUNIT; + skid->angle = travelangle; + + + P_SetMobjState(skid, S_RECSPIN_SKID); + K_MatchGenericExtraFlags(skid, player->mo); + if (player->recoverydashcharge >= 2*TICRATE) + { + skid->renderflags |= RF_TRANS20; + } + else + { + skid->renderflags |= RF_TRANS40; + } + if (i) skid->renderflags |= RF_HORIZONTALFLIP; + } + } } if (player->recoverydashcharge >= 2*TICRATE) { @@ -10771,9 +10808,9 @@ static void K_AdjustPlayerFriction(player_t *player) if ((player->pflags & PF_RECOVERYSPIN) && player->speed < K_GetKartSpeedFromStat(player->kartspeed, false)) { if (player->cmd.turning) - player->mo->friction += 1800; + player->mo->friction += 1880; else - player->mo->friction += 1228; + player->mo->friction += 1280; K_RecalculateMovefactor(player->mo); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 49281650d..2a72acfff 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6764,6 +6764,8 @@ void P_RunOverlays(void) if (!(mo->threshold & OV_DONTROLL)) { + mo->slopepitch = mo->target->slopepitch; + mo->sloperoll = mo->target->sloperoll; mo->rollangle = mo->target->rollangle; mo->pitch = mo->target->pitch; mo->roll = mo->target->roll;