From 7069c920dfde6db6c727d4b70793a1cfae461474 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 21 Mar 2025 12:12:23 -0400 Subject: [PATCH 1/9] Stacking pt 1 --- src/d_netcmd.c | 31 ++++++++++++--- src/d_netcmd.h | 1 + src/d_player.h | 2 + src/k_kart.c | 100 ++++++++++++++++++++++++++++++++++++++++--------- src/p_mobj.h | 1 + src/p_saveg.c | 2 + src/p_setup.c | 6 +++ 7 files changed, 120 insertions(+), 23 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index d08112fe6..d3fb124e0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -150,6 +150,7 @@ static void KartEncore_OnChange(void); static void KartComeback_OnChange(void); static void KartEliminateLast_OnChange(void); static void KartRings_OnChange(void); +static void KartStacking_OnChange(void); static void Schedule_OnChange(void); @@ -430,20 +431,21 @@ static CV_PossibleValue_t kartbot_cons_t[] = { }; consvar_t cv_kartbot = CVAR_INIT ("kartbot", "0", CV_NETVAR, kartbot_cons_t, NULL); -consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL, CV_YesNo, KartEliminateLast_OnChange); +consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVAR|CV_CALL, CV_YesNo, KartEliminateLast_OnChange); // Toggles for new features -consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange); +consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange); +consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartStacking_OnChange); consvar_t cv_kartwalltransfer = CVAR_INIT ("BG_forcewalltransfer", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); -consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_kartusepwrlv = CVAR_INIT ("kartusepwrlv", "Yes", CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_kartpurpledrift = CVAR_INIT ("kartpurpledrift", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_kartpurpledrift = CVAR_INIT ("kartpurpledrift", "No", CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_kartbumpspark = CVAR_INIT ("kartbumpspark", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_kartbumpspark = CVAR_INIT ("kartbumpspark", "No", CV_NETVAR, CV_YesNo, NULL); -consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); +consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "No", CV_NETVAR, CV_YesNo, NULL); static CV_PossibleValue_t kartdebugitem_cons_t[] = { @@ -6903,6 +6905,23 @@ static void KartRings_OnChange(void) } } +static void KartStacking_OnChange(void) +{ + if (K_CanChangeRules() == false) + { + return; + } + + if (cv_kartstacking.value) + { + CONS_Printf(M_GetText("Boost Stacking will be turned \"On\" Next Round.\n")); + } + else + { + CONS_Printf(M_GetText("Boost Stacking will be turned \"Off\" Next Round.\n")); + } +} + static void Schedule_OnChange(void) { size_t i; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 285d4b19c..7f1b80249 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -96,6 +96,7 @@ extern consvar_t cv_kartbot; extern consvar_t cv_karteliminatelast; extern consvar_t cv_kartusepwrlv; extern consvar_t cv_kartrings; +extern consvar_t cv_kartstacking; extern consvar_t cv_kartwalltransfer; extern consvar_t cv_kartpurpledrift; extern consvar_t cv_kartbumpspark; diff --git a/src/d_player.h b/src/d_player.h index d57f9e1f2..d5d4292ed 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -581,6 +581,8 @@ struct player_t fixed_t boostpower; // Base boost value, for offroad fixed_t speedboost; // Boost value smoothing for max speed + INT32 numsneakers; // Number of stacked sneakers + INT32 numboosts; // Number of Boosts stacking this frame fixed_t accelboost; // Boost value smoothing for acceleration 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. diff --git a/src/k_kart.c b/src/k_kart.c index 6cc84af15..9842cd613 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -251,6 +251,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_lessflicker); CV_RegisterVar(&cv_kartrings); + CV_RegisterVar(&cv_kartstacking); CV_RegisterVar(&cv_newspeedometer); CV_RegisterVar(&cv_showinput); @@ -3297,11 +3298,26 @@ static inline fixed_t K_GetSneakerBoostSpeed(void) } } +// Precalculated constants for stacked boost diminishing +// *Somewhat* matches old calc but doesn't use arrays, which makes it faster and more memory efficent +#define CALC_ARG_OFFSET 32*FRACUNIT/100 +#define CALC_RET_OFFSET FixedSqrt(CALC_ARG_OFFSET) +#define MAXVANILLABOOST 3*FRACUNIT/8 +#define SPEEDBOOSTDROPOFF FloatToFixed(0.01) +#define SPEEDBOOSTDROPOFF_BRAKE FloatToFixed(0.05) + +static fixed_t diminish(fixed_t speedboost) +{ + return FixedSqrt(speedboost + CALC_ARG_OFFSET) - CALC_RET_OFFSET; +} + // sets boostpower, speedboost and accelboost to whatever we need it to be static void K_GetKartBoostPower(player_t *player) { fixed_t boostpower = FRACUNIT; - fixed_t speedboost = 0, accelboost = 0; + fixed_t nonstack_speedboost = 0, speedboost = 0, accelboost = 0; + INT32 numboosts = 0; + fixed_t prevspeedboost = player->speedboost ? player->speedboost : 0; if (player->spinouttimer && player->wipeoutslow == 1) // Slow down after you've been bumped { @@ -3327,26 +3343,40 @@ static void K_GetKartBoostPower(player_t *player) S_StartSound(player->mo, sfx_cdfm70); } -#define ADDBOOST(s,a) { \ - speedboost = max(speedboost,s); \ - accelboost = max(accelboost,a); \ +#define ADDBOOST(s,a,st) { \ + if (stackingactive) \ + { \ + if (st) \ + { \ + numboosts++; \ + speedboost += s; \ + } \ + else \ + nonstack_speedboost = max(speedboost,s); \ + accelboost = max(accelboost,a); \ + } \ + else \ + { \ + speedboost = max(speedboost,s); \ + accelboost = max(accelboost,a); \ + } \ } if (player->sneakertimer) // Sneaker { fixed_t sneakerspeedboost = K_GetSneakerBoostSpeed(); - ADDBOOST(sneakerspeedboost, 8*FRACUNIT); // + ???% top speed, + 800% acceleration + ADDBOOST(sneakerspeedboost, 8*FRACUNIT, true); // + ???% top speed, + 800% acceleration } if (player->invincibilitytimer) // Invincibility { - ADDBOOST(3*FRACUNIT/8, 3*FRACUNIT); // + 37.5% top speed, + 300% acceleration + ADDBOOST(3*FRACUNIT/8, 3*FRACUNIT, false); // + 37.5% top speed, + 300% acceleration } if (player->growshrinktimer > 0) // Grow { - ADDBOOST(FRACUNIT/5, 0); // + 20% top speed, + 0% acceleration + ADDBOOST(FRACUNIT/5, 0, false); // + 20% top speed, + 0% acceleration } if (player->flamestore) // Flame Shield dash @@ -3360,43 +3390,77 @@ static void K_GetKartBoostPower(player_t *player) intermediate = FixedDiv(FixedMul(val, FRACUNIT*-1/2) - FRACUNIT/4,-val+FRACUNIT/2); boost = FixedMul(val,(FRACUNIT-FixedDiv(FRACUNIT,(dash+intermediate)))); - ADDBOOST(boost, accel); + ADDBOOST(boost, accel, false); } if (player->startboost) // Startup Boost { - ADDBOOST(FRACUNIT/4, 6*FRACUNIT); // + 25% top speed, + 300% acceleration + ADDBOOST(FRACUNIT/4, 6*FRACUNIT, true); // + 25% top speed, + 300% acceleration } if (player->driftboost) // Drift Boost { - ADDBOOST(FRACUNIT/4, 4*FRACUNIT); // + 25% top speed, + 400% acceleration + ADDBOOST(FRACUNIT/4, 4*FRACUNIT, true); // + 25% top speed, + 400% acceleration } if (player->ringboost) // Ring Boost { - ADDBOOST(FRACUNIT/5, 4*FRACUNIT); // + 20% top speed, + 400% acceleration + ADDBOOST(FRACUNIT/5, 4*FRACUNIT, true); // + 20% top speed, + 400% acceleration } - // This should always remain the last boost stack before tethering + // This should always remain the last boost if (player->botvars.rubberband > FRACUNIT && K_PlayerUsesBotMovement(player) == true) { - ADDBOOST(player->botvars.rubberband - FRACUNIT, 0); + ADDBOOST(player->botvars.rubberband - FRACUNIT, 0, false); } player->boostpower = boostpower; - // value smoothing - if (speedboost > player->speedboost) + if (stackingactive) { - player->speedboost = speedboost; + // Combine nonstack and stacking boosts here. + speedboost = max(nonstack_speedboost ? nonstack_speedboost : 0, diminish(speedboost)); + } + + // value smoothing + if (stackingactive) + { + // value smoothing + if (player->offroad && K_ApplyOffroad(player)) + { + player->speedboost = max(speedboost, player->speedboost)/2; + player->accelboost = max(accelboost, player->accelboost)/2; + } + else if (speedboost >= prevspeedboost) + { + player->speedboost = max(player->speedboost, speedboost); + player->accelboost = max(accelboost, player->accelboost); + } + else if ((player->aizdriftstrat && abs((player->drift) < 5)) || (K_GetKartButtons(player) & BT_BRAKE)) + { + player->speedboost = max(prevspeedboost - SPEEDBOOSTDROPOFF_BRAKE, min(player->speedboost, MAXVANILLABOOST)); + player->accelboost = max(accelboost, player->accelboost); + } + else + { + player->speedboost = max(prevspeedboost - SPEEDBOOSTDROPOFF, player->speedboost); + player->accelboost = max(accelboost, player->accelboost); + } } else { - player->speedboost += (speedboost - player->speedboost) / (TICRATE/2); + if (speedboost > player->speedboost) + { + player->speedboost = speedboost; + } + else + { + player->speedboost += (speedboost - player->speedboost) / (TICRATE/2); + } } player->accelboost = accelboost; + player->numboosts = numboosts; } // Returns value based on being Grown or Shrunk otherwise returns FRACUNIT @@ -5177,6 +5241,7 @@ void K_DoSneaker(player_t *player, INT32 type) } player->sneakertimer = sneakertime; + player->numsneakers++; // set angle for spun out players: player->boostangle = player->mo->angle; @@ -5207,6 +5272,7 @@ void K_DoWaterRunPanel(player_t *player) } player->sneakertimer = TICRATE*2; + player->numsneakers++; player->mo->flags2 |= MF2_WATERRUN; // set angle for spun out players: diff --git a/src/p_mobj.h b/src/p_mobj.h index 7244ce061..587308d39 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -578,6 +578,7 @@ extern UINT16 emeraldspawndelay; extern INT32 numstarposts; extern INT32 numbosswaypoints; extern boolean ringsactive; +extern boolean stackingactive; extern UINT16 bossdisabled; extern boolean stoppedclock; diff --git a/src/p_saveg.c b/src/p_saveg.c index 86f2b8125..af8bd7fae 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5022,6 +5022,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEINT16(save->p, lastmap); WRITEUINT16(save->p, bossdisabled); WRITEUINT8(save->p, ringsactive); + WRITEUINT8(save->p, stackingactive); for (i = 0; i < 4; i++) { @@ -5191,6 +5192,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool lastmap = READINT16(save->p); bossdisabled = READUINT16(save->p); ringsactive = READUINT8(save->p); + stackingactive = READUINT8(save->p); for (i = 0; i < 4; i++) { diff --git a/src/p_setup.c b/src/p_setup.c index 8aeb9fd97..2d80ad9ad 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -143,6 +143,7 @@ side_t *spawnsides; INT32 numstarposts; INT32 numbosswaypoints; boolean ringsactive; +boolean stackingactive; UINT16 bossdisabled; boolean stoppedclock; boolean levelloading; @@ -7883,6 +7884,11 @@ static void P_InitLevelSettings(boolean reloadinggamestate) else ringsactive = false; + if (cv_kartstacking.value) + stackingactive = true; + else + stackingactive = false; + // emerald hunt hunt1 = hunt2 = hunt3 = NULL; From 7091195a955987a7d48b2660a7c85d41869d957f Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 25 Mar 2025 15:06:35 -0400 Subject: [PATCH 2/9] stacking pt.2: finish stacking --- src/d_player.h | 12 +++- src/k_kart.c | 180 +++++++++++++++++++++++++--------------------- src/k_kart.h | 5 ++ src/lua_baselib.c | 32 ++++++++- src/p_saveg.c | 16 +++++ src/typedef.h | 1 + 6 files changed, 161 insertions(+), 85 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 084751d11..d954c52cc 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -452,6 +452,13 @@ struct sonicloopvars_t sonicloopcamvars_t camera; }; +struct boostinfo_t { + fixed_t stackspeedboost; + fixed_t nonstackspeedboost; + fixed_t accelboost; + UINT8 grade; +}; + // ======================================================================== // PLAYER STRUCTURE // ======================================================================== @@ -579,10 +586,11 @@ struct player_t fixed_t boostpower; // Base boost value, for offroad fixed_t speedboost; // Boost value smoothing for max speed - INT32 numsneakers; // Number of stacked sneakers - INT32 numboosts; // Number of Boosts stacking this frame fixed_t accelboost; // Boost value smoothing for acceleration 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 + UINT8 numboosts; // Number of Boosts stacking this frame UINT8 tripwireState; // see tripwirestate_t UINT8 tripwirePass; // see tripwirepass_t diff --git a/src/k_kart.c b/src/k_kart.c index a07f59027..6a69df303 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3314,13 +3314,38 @@ static fixed_t diminish(fixed_t speedboost) return FixedSqrt(speedboost + CALC_ARG_OFFSET) - CALC_RET_OFFSET; } +void K_DoBoost(player_t *player, fixed_t speedboost, fixed_t accelboost, boolean stack, boolean visible) +{ + if (stack && stackingactive) + { + player->boostinfo.stackspeedboost += speedboost; + } + + player->boostinfo.nonstackspeedboost = max(player->boostinfo.nonstackspeedboost, speedboost); + player->boostinfo.accelboost = max(player->boostinfo.accelboost, accelboost); + + if (visible) + { + player->boostinfo.grade = CLAMP(player->boostinfo.grade+1, 0, stackingactive ? UINT8_MAX : 1); + } +} + +void K_ClearBoost(player_t *player) +{ + player->boostinfo.stackspeedboost = 0; + player->boostinfo.nonstackspeedboost = 0; + player->boostinfo.accelboost = 0; + player->boostinfo.grade = 0; +} + // sets boostpower, speedboost and accelboost to whatever we need it to be static void K_GetKartBoostPower(player_t *player) { fixed_t boostpower = FRACUNIT; - fixed_t nonstack_speedboost = 0, speedboost = 0, accelboost = 0; - INT32 numboosts = 0; - fixed_t prevspeedboost = player->speedboost ? player->speedboost : 0; + fixed_t finalspeedboost = 0; + fixed_t finalaccelboost = 0; + UINT8 finalgrade = 0; + fixed_t prevspeedboost = player->speedboost; if (player->spinouttimer && player->wipeoutslow == 1) // Slow down after you've been bumped { @@ -3346,40 +3371,24 @@ static void K_GetKartBoostPower(player_t *player) S_StartSound(player->mo, sfx_cdfm70); } -#define ADDBOOST(s,a,st) { \ - if (stackingactive) \ - { \ - if (st) \ - { \ - numboosts++; \ - speedboost += s; \ - } \ - else \ - nonstack_speedboost = max(speedboost,s); \ - accelboost = max(accelboost,a); \ - } \ - else \ - { \ - speedboost = max(speedboost,s); \ - accelboost = max(accelboost,a); \ - } \ -} - if (player->sneakertimer) // Sneaker { + UINT8 i; fixed_t sneakerspeedboost = K_GetSneakerBoostSpeed(); - ADDBOOST(sneakerspeedboost, 8*FRACUNIT, true); // + ???% top speed, + 800% acceleration - + for (i = 0; i < player->numsneakers; i++) + { + K_DoBoost(player, sneakerspeedboost, 8*FRACUNIT, true, true); // + ???% top speed, + 800% acceleration + } } if (player->invincibilitytimer) // Invincibility { - ADDBOOST(3*FRACUNIT/8, 3*FRACUNIT, false); // + 37.5% top speed, + 300% acceleration + K_DoBoost(player, 3*FRACUNIT/8, 3*FRACUNIT, false, false); // + 37.5% top speed, + 300% acceleration } if (player->growshrinktimer > 0) // Grow { - ADDBOOST(FRACUNIT/5, 0, false); // + 20% top speed, + 0% acceleration + K_DoBoost(player, FRACUNIT/5, 0, false, false); // + 20% top speed, + 0% acceleration } if (player->flamestore) // Flame Shield dash @@ -3393,77 +3402,76 @@ static void K_GetKartBoostPower(player_t *player) intermediate = FixedDiv(FixedMul(val, FRACUNIT*-1/2) - FRACUNIT/4,-val+FRACUNIT/2); boost = FixedMul(val,(FRACUNIT-FixedDiv(FRACUNIT,(dash+intermediate)))); - ADDBOOST(boost, accel, false); + K_DoBoost(player, boost, accel, false, false); } if (player->startboost) // Startup Boost { - ADDBOOST(FRACUNIT/4, 6*FRACUNIT, true); // + 25% top speed, + 300% acceleration + K_DoBoost(player, FRACUNIT/4, 6*FRACUNIT, true, true); // + 25% top speed, + 300% acceleration } if (player->driftboost) // Drift Boost { - ADDBOOST(FRACUNIT/4, 4*FRACUNIT, true); // + 25% top speed, + 400% acceleration + K_DoBoost(player, FRACUNIT/4, 4*FRACUNIT, true, true); // + 25% top speed, + 400% acceleration } if (player->ringboost) // Ring Boost { - ADDBOOST(FRACUNIT/5, 4*FRACUNIT, true); // + 20% top speed, + 400% acceleration + K_DoBoost(player, FRACUNIT/5, 4*FRACUNIT, true, true); // + 20% top speed, + 400% acceleration } // This should always remain the last boost if (player->botvars.rubberband > FRACUNIT && K_PlayerUsesBotMovement(player) == true) { - ADDBOOST(player->botvars.rubberband - FRACUNIT, 0, false); + K_DoBoost(player, player->botvars.rubberband - FRACUNIT, 0, false, false); } player->boostpower = boostpower; - if (stackingactive) - { - // Combine nonstack and stacking boosts here. - speedboost = max(nonstack_speedboost ? nonstack_speedboost : 0, diminish(speedboost)); - } + // Combine nonstack and stacking boosts here. + finalspeedboost = max(player->boostinfo.nonstackspeedboost, diminish(player->boostinfo.stackspeedboost)); + finalaccelboost = player->boostinfo.accelboost; + finalgrade = player->boostinfo.grade; // value smoothing if (stackingactive) { - // value smoothing if (player->offroad && K_ApplyOffroad(player)) { - player->speedboost = max(speedboost, player->speedboost)/2; - player->accelboost = max(accelboost, player->accelboost)/2; + player->speedboost = max(finalspeedboost, player->speedboost)/2; + player->accelboost = max(finalaccelboost, player->accelboost)/2; } - else if (speedboost >= prevspeedboost) + else if (finalspeedboost >= prevspeedboost) { - player->speedboost = max(player->speedboost, speedboost); - player->accelboost = max(accelboost, player->accelboost); + player->speedboost = max(player->speedboost, finalspeedboost); + player->accelboost = max(finalaccelboost, player->accelboost); } else if ((player->aizdriftstrat && abs((player->drift) < 5)) || (K_GetKartButtons(player) & BT_BRAKE)) { player->speedboost = max(prevspeedboost - SPEEDBOOSTDROPOFF_BRAKE, min(player->speedboost, MAXVANILLABOOST)); - player->accelboost = max(accelboost, player->accelboost); + player->accelboost = max(finalaccelboost, player->accelboost); } else { - player->speedboost = max(prevspeedboost - SPEEDBOOSTDROPOFF, player->speedboost); - player->accelboost = max(accelboost, player->accelboost); + player->speedboost = prevspeedboost - SPEEDBOOSTDROPOFF; + player->accelboost = max(finalaccelboost, player->accelboost); } } else { - if (speedboost > player->speedboost) + if (finalspeedboost > player->speedboost) { - player->speedboost = speedboost; + player->speedboost = finalspeedboost; } else { - player->speedboost += (speedboost - player->speedboost) / (TICRATE/2); + player->speedboost += (finalspeedboost - player->speedboost) / (TICRATE/2); } } - player->accelboost = accelboost; - player->numboosts = numboosts; + player->accelboost = finalaccelboost; + player->numboosts = finalgrade; + K_ClearBoost(player); } // Returns value based on being Grown or Shrunk otherwise returns FRACUNIT @@ -5192,22 +5200,27 @@ static void K_DoHyudoroSteal(player_t *player) } } -void K_DoSneaker(player_t *player, INT32 type) +// Handle these else where to reduce code duplication between panels and sneakers +static void K_SneakerPanelStackSound(player_t *player) { - const fixed_t intendedboost = K_GetSneakerBoostSpeed(); + const sfxenum_t normalsfx = sfx_cdfm01; + const sfxenum_t smallsfx = sfx_cdfm40; + sfxenum_t sfx = normalsfx; - if (player->floorboost == 0 || player->floorboost == 3) + if ((player->numsneakers > 0) && stackingactive) { - S_StopSoundByID(player->mo, sfx_cdfm01); - S_StartSound(player->mo, sfx_cdfm01); - - K_SpawnDashDustRelease(player); - if (intendedboost > player->speedboost) - player->karthud[khud_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->speedboost), intendedboost)); - + // Use a less annoying sound when stacking sneakers. + sfx = smallsfx; } - if (player->sneakertimer == 0) + S_StopSoundByID(player->mo, normalsfx); + S_StopSoundByID(player->mo, smallsfx); + S_StartSound(player->mo, sfx); +} + +static void K_SneakerPanelEffect(player_t *player, INT32 type) +{ + if (!player->sneakertimer) { if (type == 2) { @@ -5236,6 +5249,22 @@ void K_DoSneaker(player_t *player, INT32 type) K_FlipFromObject(overlay, player->mo); } } +} + +void K_DoSneaker(player_t *player, INT32 type) +{ + const fixed_t intendedboost = K_GetSneakerBoostSpeed(); + + if (player->floorboost == 0 || player->floorboost == 3) + { + K_SneakerPanelStackSound(player); + K_SpawnDashDustRelease(player); + if (intendedboost > player->speedboost) + player->karthud[khud_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->speedboost), intendedboost)); + + } + + K_SneakerPanelEffect(player, type); if (type != 0) { @@ -5243,7 +5272,7 @@ void K_DoSneaker(player_t *player, INT32 type) } player->sneakertimer = sneakertime; - player->numsneakers++; + player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); // set angle for spun out players: player->boostangle = player->mo->angle; @@ -5255,26 +5284,16 @@ void K_DoWaterRunPanel(player_t *player) if (player->floorboost == 0 || player->floorboost == 3) { - S_StopSoundByID(player->mo, sfx_cdfm01); - S_StopSoundByID(player->mo, sfx_kc3c); - S_StartSound(player->mo, sfx_cdfm01); - S_StartSound(player->mo, sfx_kc3c); - + K_SneakerPanelStackSound(player); K_SpawnDashDustRelease(player); if (intendedboost > player->speedboost) player->karthud[khud_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->speedboost), intendedboost)); } - if (player->sneakertimer == 0) - { - mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME); - P_SetTarget(&overlay->target, player->mo); - P_SetScale(overlay, (overlay->destscale = player->mo->scale)); - K_FlipFromObject(overlay, player->mo); - } + K_SneakerPanelEffect(player, 0); player->sneakertimer = TICRATE*2; - player->numsneakers++; + player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); player->mo->flags2 |= MF2_WATERRUN; // set angle for spun out players: @@ -7189,6 +7208,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->sneakertimer) { player->sneakertimer--; + if (player->sneakertimer <= 0) + { + player->mo->flags2 &= ~MF2_WATERRUN; + player->numsneakers = 0; + } } if (player->sneakertimer && player->wipeoutslow > 0 && player->wipeoutslow < wipeoutslowtime+1) @@ -7197,12 +7221,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->floorboost > 0) player->floorboost--; - if (player->sneakertimer == 0) - { - // No more waterrunning for you pal! - player->mo->flags2 &= ~MF2_WATERRUN; - } - if (player->driftboost) player->driftboost--; diff --git a/src/k_kart.h b/src/k_kart.h index c4d9bae67..fd1a8a712 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -31,6 +31,8 @@ Make sure this matches the actual number of states #define FLAMESTOREMAX TICRATE*2 +#define MAXSNEAKERSTACK 3 + // Used for respawning checks. typedef struct respawnresult_s @@ -196,6 +198,9 @@ boolean K_UsingLegacyCheckpoints(void); void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount); +void K_DoBoost(player_t *player, fixed_t speedboost, fixed_t accelboost, boolean stack, boolean visible); +void K_ClearBoost(player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/lua_baselib.c b/src/lua_baselib.c index c54a4a09a..35cc252e5 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3958,7 +3958,7 @@ static int lib_kSetIndirectItemCountdown(lua_State *L) return 0; } -// Sets the item cooldown before another shrink / SPB can be rolled +// Sets the item cooldown before another hyudoro can be rolled static int lib_kSetHyuCountdown(lua_State *L) { tic_t c = (tic_t)luaL_checkinteger(L, 1); @@ -3992,6 +3992,32 @@ static int lib_kUsingLegacyCheckpoints(lua_State *L) return 1; } +static int lib_kDoBoost(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + fixed_t speedboost = luaL_checkfixed(L, 2); + fixed_t accelboost = luaL_checkfixed(L, 3); + boolean stacking = lua_optboolean(L, 4); + boolean visible = lua_isnoneornil(L, 5) ? true : luaL_checkboolean(L, 5); + + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_DoBoost(player, speedboost, accelboost, stacking, visible); + return 0; +} + +static int lib_kClearBoost(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_ClearBoost(player); + return 0; +} + static int lib_getTimeMicros(lua_State *L) { lua_pushinteger(L, I_GetPreciseTime() / (I_GetPrecisePrecision() / 1000000)); @@ -4286,12 +4312,14 @@ static luaL_Reg lib[] = { {"K_SetExitCountdown",lib_kSetExitCountdown}, {"K_SetIndirectItemCooldown",lib_kSetIndirectItemCountdown}, {"K_SetHyudoroCooldown",lib_kSetHyuCountdown}, - {"K_SafeRespawnPosition", lib_kSafeRespawnPosition}, + {"K_SafeRespawnPosition",lib_kSafeRespawnPosition}, {"K_GetCollideAngle",lib_kGetCollideAngle}, {"K_RingsActive",lib_kRingsActive}, {"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints}, + {"K_DoBoost",lib_kDoBoost}, + {"K_ClearBoost",lib_kClearBoost}, // k_boss {"K_InitBossHealthBar", lib_kInitBossHealthBar}, diff --git a/src/p_saveg.c b/src/p_saveg.c index e5db21ef2..0251cdd19 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -272,6 +272,14 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEFIXED(save->p, players[i].speedboost); WRITEFIXED(save->p, players[i].accelboost); WRITEANGLE(save->p, players[i].boostangle); + WRITEUINT8(save->p, players[i].numsneakers); + WRITEUINT8(save->p, players[i].numboosts); + + // boostinfo_t + WRITEFIXED(save->p, players[i].boostinfo.stackspeedboost); + WRITEFIXED(save->p, players[i].boostinfo.nonstackspeedboost); + WRITEFIXED(save->p, players[i].boostinfo.accelboost); + WRITEUINT8(save->p, players[i].boostinfo.grade); WRITEUINT8(save->p, players[i].tripwireState); WRITEUINT8(save->p, players[i].tripwirePass); @@ -576,6 +584,14 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].speedboost = READFIXED(save->p); players[i].accelboost = READFIXED(save->p); players[i].boostangle = READANGLE(save->p); + players[i].numsneakers = READUINT8(save->p); + players[i].numboosts = READUINT8(save->p); + + // boostinfo_t + players[i].boostinfo.stackspeedboost = READFIXED(save->p); + players[i].boostinfo.nonstackspeedboost = READFIXED(save->p); + players[i].boostinfo.accelboost = READFIXED(save->p); + players[i].boostinfo.grade = READUINT8(save->p); players[i].tripwireState = READUINT8(save->p); players[i].tripwirePass = READUINT8(save->p); diff --git a/src/typedef.h b/src/typedef.h index ca33b24e9..467352019 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -43,6 +43,7 @@ TYPEDEF (discordRequest_t); // d_player.h TYPEDEF (botvars_t); +TYPEDEF (boostinfo_t); TYPEDEF (player_t); TYPEDEF (sonicloopcamvars_t); TYPEDEF (sonicloopvars_t); From f0b6ef89eba85c5b67534d9b9c1399e58c9f2dd2 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 25 Mar 2025 18:01:18 -0400 Subject: [PATCH 3/9] stacking pt.3: start work on chaining --- src/d_netcmd.c | 72 ++++++++++++++++++++--- src/d_netcmd.h | 1 + src/d_player.h | 1 + src/k_kart.c | 138 ++++++++++++++++++++++++++++++++++++++++---- src/k_kart.h | 2 + src/lua_baselib.c | 16 +++++ src/lua_playerlib.c | 32 ++++++++++ src/lua_script.c | 15 +++++ src/p_mobj.h | 1 + src/p_saveg.c | 4 ++ src/p_setup.c | 6 ++ 11 files changed, 269 insertions(+), 19 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index fe08bcf11..5bfebc63f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -152,6 +152,7 @@ static void KartComeback_OnChange(void); static void KartEliminateLast_OnChange(void); static void KartRings_OnChange(void); static void KartStacking_OnChange(void); +static void KartChaining_OnChange(void); static void KartItemBreaker_OnChange(void); static void Schedule_OnChange(void); @@ -442,6 +443,7 @@ consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVA // Toggles for new features consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange); consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartStacking_OnChange); +consvar_t cv_kartchaining = CVAR_INIT ("kartchaining", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartChaining_OnChange); consvar_t cv_kartitembreaker = CVAR_INIT ("kartitembreaker", "No", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_YesNo, KartItemBreaker_OnChange); @@ -6943,11 +6945,11 @@ static void KartRings_OnChange(void) return; } - if (cv_kartrings.value) + if (!K_RingsActive() && cv_kartrings.value) { CONS_Printf(M_GetText("Rings will be turned \"On\" Next Round.\n")); } - else + else if (K_RingsActive() && !cv_kartrings.value) { CONS_Printf(M_GetText("Rings will be turned \"Off\" Next Round.\n")); } @@ -6960,13 +6962,62 @@ static void KartStacking_OnChange(void) return; } - if (cv_kartstacking.value) + if (!stackingactive && cv_kartstacking.value) { - CONS_Printf(M_GetText("Boost Stacking will be turned \"On\" Next Round.\n")); + if (leveltime < starttime) + { + stackingactive = true; + CONS_Printf(M_GetText("Boost Stacking has been turned \"On\".\n")); + } + else + { + CONS_Printf(M_GetText("Boost Stacking will be turned \"On\" next round.\n")); + } } - else + else if (stackingactive && !cv_kartstacking.value) { - CONS_Printf(M_GetText("Boost Stacking will be turned \"Off\" Next Round.\n")); + if (leveltime < starttime) + { + stackingactive = false; + CONS_Printf(M_GetText("Boost Stacking has been turned \"Off\".\n")); + } + else + { + CONS_Printf(M_GetText("Boost Stacking will be turned \"Off\" next round.\n")); + } + } +} + +static void KartChaining_OnChange(void) +{ + if (K_CanChangeRules() == false) + { + return; + } + + if (!chainingactive && cv_kartchaining.value) + { + if (leveltime < starttime) + { + chainingactive = true; + CONS_Printf(M_GetText("Boost Chaining has been turned \"On\".\n")); + } + else + { + CONS_Printf(M_GetText("Boost Chaining will be turned \"On\" Next Round.\n")); + } + } + else if (chainingactive && !cv_kartstacking.value) + { + if (leveltime < starttime) + { + chainingactive = false; + CONS_Printf(M_GetText("Boost Chaining has been turned \"Off\".\n")); + } + else + { + CONS_Printf(M_GetText("Boost Chaining will be turned \"Off\" next round.\n")); + } } } @@ -6977,11 +7028,16 @@ static void KartItemBreaker_OnChange(void) return; } - if (cv_kartitembreaker.value) + if (!multiplayer) + { + return; + } + + if (!itembreaker && cv_kartitembreaker.value) { CONS_Printf(M_GetText("Singleplayer Item Breaker will be turned \"On\" Next Round.\n")); } - else + else if (itembreaker && !cv_kartitembreaker.value) { CONS_Printf(M_GetText("Singleplayer Item Breaker will be turned \"Off\" Next Round.\n")); } diff --git a/src/d_netcmd.h b/src/d_netcmd.h index b0c118248..35914b448 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -97,6 +97,7 @@ extern consvar_t cv_karteliminatelast; extern consvar_t cv_kartusepwrlv; extern consvar_t cv_kartrings; extern consvar_t cv_kartstacking; +extern consvar_t cv_kartchaining; extern consvar_t cv_kartitembreaker; extern consvar_t cv_kartwalltransfer; extern consvar_t cv_kartpurpledrift; diff --git a/src/d_player.h b/src/d_player.h index d954c52cc..0866cc122 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -633,6 +633,7 @@ struct player_t UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters) UINT8 floorboost; // (0 to 3) - Prevents Sneaker sounds for a brief duration when triggered by a floor panel + UINT16 chaintimer; // Stores current chain timer length. UINT8 boostcharge; // Charge during race start diff --git a/src/k_kart.c b/src/k_kart.c index 6a69df303..e5f939e95 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -254,6 +254,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartrings); CV_RegisterVar(&cv_kartstacking); + CV_RegisterVar(&cv_kartchaining); CV_RegisterVar(&cv_kartitembreaker); CV_RegisterVar(&cv_newspeedometer); @@ -7007,6 +7008,101 @@ static void K_TireGreaseEffect(player_t *player) S_StartSound(player->mo, sfx_screec); } +boolean K_BoostChain(player_t *player, INT32 timer) +{ + if (!chainingactive) + { + // You can't chain why bother? + return false; + } + + if (timer > player->chaintimer) + { + // Just what I needed! - Toad + player->chaintimer = timer; + } + + if (player->chaintimer) + { + // You can continue chaining! + return true; + } + + // Aw shucks, time to drop the chain.... + return false; +} + +INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement) +{ + if (K_BoostChain(player, timer)) + { + // Its time to chain. + return max(1, timer - deincrement); + } + + // Continue to drain the timer as normal. + return timer - deincrement; +} + +// Get the tic inverse sum using kartspeed, kartweight and your number of boosts. +static INT32 ticinversesum(UINT8 kartspeed, UINT8 kartweight, UINT8 grade) +{ + return (TICRATE / kartspeed) + (TICRATE / CLAMP(kartweight, 1, 5)) + grade; +} + +// Get the maximum required stacks needed for the ringnerf based on kartspeed and kartweight +static INT32 statrangemap(UINT8 kartspeed, UINT8 kartweight) +{ + INT32 scaledsw = (9 - kartspeed) + (9 - kartweight); + + fixed_t scaled_input = (scaledsw)*FRACUNIT/16; + + // Scale the result to be within range [2, 4] + fixed_t result = 4*FRACUNIT - (FixedMul(scaled_input, 2*FRACUNIT)); + + // Stay within range please! + if (result < 2*FRACUNIT) + result = 2*FRACUNIT; + if (result > 4*FRACUNIT) + result = 4*FRACUNIT; + + result = result >> FRACBITS; + + return result; +} + +static void K_HandleRingDeincrement(player_t *player, boolean chainnerf) +{ + // Aggressively reduce extreme ringboost duration. + // Less aggressive for accel types. + UINT8 roller = TICRATE; + UINT16 finalringtimer; + roller += 4*(8-player->kartspeed); + + finalringtimer = max((player->ringboost / roller), 1); + + if (chainnerf) + { + UINT8 requiredgrade = statrangemap(player->kartspeed, player->kartweight); + + if (player->numboosts >= requiredgrade) + { + INT32 insum = ticinversesum(player->kartspeed, player->kartweight, player->numboosts); + INT32 subring = (player->ringboost*2)/insum; + + if (player->kartspeed == 1) + { + // fuck off chao you aren't chaining an entire race. + subring = (player->ringboost*4)/insum; + } + + finalringtimer -= subring; + } + } + + player->ringboost = K_ChainOrDeincrementTime(player, player->ringboost, finalringtimer); +} + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -7196,18 +7292,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->ringboost = 0; else if (player->ringboost) { - // Aggressively reduce extreme ringboost duration. - // Less aggressive for accel types. - - UINT8 roller = TICRATE; - roller += 4*(8-player->kartspeed); - - player->ringboost -= max((player->ringboost / roller), 1); + K_HandleRingDeincrement(player, chainingactive); } if (player->sneakertimer) { - player->sneakertimer--; + player->sneakertimer = K_ChainOrDeincrementTime(player, player->sneakertimer, 1); + if (player->sneakertimer <= 0) { player->mo->flags2 &= ~MF2_WATERRUN; @@ -7222,10 +7313,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->floorboost--; if (player->driftboost) - player->driftboost--; + player->driftboost = K_ChainOrDeincrementTime(player, player->driftboost, 1); if (player->startboost > 0) - player->startboost--; + player->startboost = K_ChainOrDeincrementTime(player, player->startboost, 1); if (player->invincibilitytimer) player->invincibilitytimer--; @@ -7324,7 +7415,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->outruntime--; if (player->tiregrease > 0) - player->tiregrease--;; + player->tiregrease--; + + if (player->chaintimer) + player->chaintimer--; if (player->itemblink && player->itemblink-- <= 0) { @@ -10434,6 +10528,28 @@ boolean K_RingsActive(void) return true; } +boolean K_StackingActive(void) +{ + if (stackingactive) + { + // Booststacking is enabled! + return true; + } + + return false; +} + +boolean K_ChainingActive(void) +{ + if (chainingactive) + { + // Boostchaining is enabled! + return true; + } + + return false; +} + boolean K_UsingLegacyCheckpoints(void) { if (numbosswaypoints > 0) diff --git a/src/k_kart.h b/src/k_kart.h index fd1a8a712..db8b09002 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -194,6 +194,8 @@ void K_UnsetItemOut(player_t *player); boolean K_SafeRespawnPosition(mobj_t * mo); boolean K_RingsActive(void); +boolean K_StackingActive(void); +boolean K_ChainingActive(void); boolean K_UsingLegacyCheckpoints(void); void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 35cc252e5..f5527f5c3 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3985,6 +3985,20 @@ static int lib_kRingsActive(lua_State *L) return 1; } +// Checks if Stacking is active. +static int lib_kStackingActive(lua_State *L) +{ + lua_pushboolean(L, K_StackingActive()); + return 1; +} + +// Checks if Chaining is active. +static int lib_kChainingActive(lua_State *L) +{ + lua_pushboolean(L, K_ChainingActive()); + return 1; +} + // Checks if current map is using legacy boss3 bassed checkpoints. Useful for map compat. static int lib_kUsingLegacyCheckpoints(lua_State *L) { @@ -4317,6 +4331,8 @@ static luaL_Reg lib[] = { {"K_GetCollideAngle",lib_kGetCollideAngle}, {"K_RingsActive",lib_kRingsActive}, + {"K_StackingActive",lib_kStackingActive}, + {"K_ChainingActive",lib_kChainingActive}, {"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints}, {"K_DoBoost",lib_kDoBoost}, {"K_ClearBoost",lib_kClearBoost}, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 32a302a82..0dc5ccf63 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -229,6 +229,9 @@ enum player_e player_speedboost, player_accelboost, player_boostangle, + player_boostinfo, + player_numsneakers, + player_numboosts, player_tripwireState, player_tripwirePass, player_tripwireLeniency, @@ -261,6 +264,7 @@ enum player_e player_stolentimer, player_sneakertimer, player_floorboost, + player_chaintimer, player_growshrinktimer, player_growcancel, player_squishedtimer, @@ -398,6 +402,9 @@ static const char *const player_opt[] = { "speedboost", "accelboost", "boostangle", + "boostinfo", + "numsneakers", + "numboosts", "tripwireState", "tripwirePass", "tripwireLeniency", @@ -430,6 +437,7 @@ static const char *const player_opt[] = { "stolentimer", "sneakertimer", "floorboost", + "chaintimer", "growshrinktimer", "growcancel", "squishedtimer", @@ -699,6 +707,15 @@ static int player_get(lua_State *L) case player_boostangle: lua_pushangle(L, plr->boostangle); break; + case player_boostinfo: + luaL_error(L, "Don't directly read boostinfo. Use speedboost, accelboost and numboosts instead,\n"); + break; + case player_numsneakers: + lua_pushinteger(L, plr->numsneakers); + break; + case player_numboosts: + lua_pushinteger(L, plr->numboosts); + break; case player_tripwireState: lua_pushinteger(L, plr->tripwireState); break; @@ -795,6 +812,9 @@ static int player_get(lua_State *L) case player_floorboost: lua_pushinteger(L, plr->floorboost); break; + case player_chaintimer: + lua_pushinteger(L, plr->chaintimer); + break; case player_growshrinktimer: lua_pushinteger(L, plr->growshrinktimer); break; @@ -1281,6 +1301,15 @@ static int player_set(lua_State *L) case player_boostangle: plr->boostangle = luaL_checkangle(L, 3); break; + case player_boostinfo: + NOSET; + break; + case player_numsneakers: + plr->numsneakers = luaL_checkinteger(L, 3); + break; + case player_numboosts: + plr->numboosts = luaL_checkinteger(L, 3); + break; case player_tripwireState: plr->tripwireState = luaL_checkinteger(L, 3); break; @@ -1377,6 +1406,9 @@ static int player_set(lua_State *L) case player_floorboost: plr->floorboost = luaL_checkinteger(L, 3); break; + case player_chaintimer: + plr->chaintimer = luaL_checkinteger(L, 3); + break; case player_growshrinktimer: plr->growshrinktimer = luaL_checkinteger(L, 3); break; diff --git a/src/lua_script.c b/src/lua_script.c index f203d765c..ac0966b1a 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -360,6 +360,15 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"battleprisons")) { lua_pushinteger(L, itembreaker); return 1; + } else if (fastcmp(word,"ringsactive")) { + lua_pushinteger(L, ringsactive); + return 1; + } else if (fastcmp(word,"stackingactive")) { + lua_pushinteger(L, stackingactive); + return 1; + } else if (fastcmp(word,"chainingactive")) { + lua_pushinteger(L, chainingactive); + return 1; } else if (fastcmp(word,"hyubgone")) { lua_pushinteger(L, hyubgone); return 1; @@ -481,6 +490,12 @@ int LUA_WriteGlobals(lua_State *L, const char *word) introtime = (tic_t)luaL_checkinteger(L, 2); else if (fastcmp(word,"itembreaker")) itembreaker = (boolean)luaL_checkinteger(L, 2); + else if (fastcmp(word,"battleprisons")) + itembreaker = (boolean)luaL_checkinteger(L, 2); + else if (fastcmp(word,"chainingactive")) + stackingactive = (boolean)luaL_checkinteger(L, 2); + else if (fastcmp(word,"chainingactive")) + chainingactive = (boolean)luaL_checkinteger(L, 2); else if (fastcmp(word,"gamespeed")) gamespeed = (UINT8)luaL_checkinteger(L, 2); else if (fastcmp(word,"nummapboxes")) diff --git a/src/p_mobj.h b/src/p_mobj.h index 0b69fda9c..dc7c1e75d 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -579,6 +579,7 @@ extern INT32 numstarposts; extern INT32 numbosswaypoints; extern boolean ringsactive; extern boolean stackingactive; +extern boolean chainingactive; extern UINT16 bossdisabled; extern boolean stoppedclock; diff --git a/src/p_saveg.c b/src/p_saveg.c index 0251cdd19..3a6bd771a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -319,6 +319,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].sneakertimer); WRITEUINT8(save->p, players[i].floorboost); + WRITEUINT16(save->p, players[i].chaintimer); WRITEUINT8(save->p, players[i].boostcharge); @@ -631,6 +632,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].sneakertimer = READUINT16(save->p); players[i].floorboost = READUINT8(save->p); + players[i].chaintimer = READUINT16(save->p); players[i].boostcharge = READUINT8(save->p); @@ -5084,6 +5086,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT16(save->p, bossdisabled); WRITEUINT8(save->p, ringsactive); WRITEUINT8(save->p, stackingactive); + WRITEUINT8(save->p, chainingactive); for (i = 0; i < 4; i++) { @@ -5254,6 +5257,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool bossdisabled = READUINT16(save->p); ringsactive = READUINT8(save->p); stackingactive = READUINT8(save->p); + chainingactive = READUINT8(save->p); for (i = 0; i < 4; i++) { diff --git a/src/p_setup.c b/src/p_setup.c index 2d80ad9ad..f45142c36 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -144,6 +144,7 @@ INT32 numstarposts; INT32 numbosswaypoints; boolean ringsactive; boolean stackingactive; +boolean chainingactive; UINT16 bossdisabled; boolean stoppedclock; boolean levelloading; @@ -7889,6 +7890,11 @@ static void P_InitLevelSettings(boolean reloadinggamestate) else stackingactive = false; + if (cv_kartchaining.value) + chainingactive = true; + else + chainingactive = false; + // emerald hunt hunt1 = hunt2 = hunt3 = NULL; From 0ae44e0fa0cc455a1d80cc41236f2fcf64d66a1c Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 25 Mar 2025 19:13:06 -0400 Subject: [PATCH 4/9] stacking pt.4: Finish Chaining Again thanks to Indev for helping me figure out why the last tick wouldn't deincrement --- src/k_kart.c | 23 +++++++++++++++++------ src/k_kart.h | 2 ++ src/lua_baselib.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e5f939e95..14e887e47 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5273,7 +5273,11 @@ void K_DoSneaker(player_t *player, INT32 type) } player->sneakertimer = sneakertime; - player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); + + if (player->sneakertimer && (player->floorboost == 0 || player->floorboost == 3)) + { + player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); + } // set angle for spun out players: player->boostangle = player->mo->angle; @@ -5294,7 +5298,12 @@ void K_DoWaterRunPanel(player_t *player) K_SneakerPanelEffect(player, 0); player->sneakertimer = TICRATE*2; - player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); + + if (player->sneakertimer && (player->floorboost == 0 || player->floorboost == 3)) + { + player->numsneakers = CLAMP(player->numsneakers+1, 0, stackingactive ? MAXSNEAKERSTACK : 1); + } + player->mo->flags2 |= MF2_WATERRUN; // set angle for spun out players: @@ -7034,14 +7043,16 @@ boolean K_BoostChain(player_t *player, INT32 timer) INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement) { + timer -= deincrement; + if (K_BoostChain(player, timer)) { // Its time to chain. - return max(1, timer - deincrement); + return max(1, timer); } // Continue to drain the timer as normal. - return timer - deincrement; + return timer; } // Get the tic inverse sum using kartspeed, kartweight and your number of boosts. @@ -7096,11 +7107,11 @@ static void K_HandleRingDeincrement(player_t *player, boolean chainnerf) subring = (player->ringboost*4)/insum; } - finalringtimer -= subring; + finalringtimer += subring; } } - player->ringboost = K_ChainOrDeincrementTime(player, player->ringboost, finalringtimer); + player->ringboost = max(0, K_ChainOrDeincrementTime(player, player->ringboost, finalringtimer)); } /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c diff --git a/src/k_kart.h b/src/k_kart.h index db8b09002..45e80b903 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -196,6 +196,8 @@ boolean K_SafeRespawnPosition(mobj_t * mo); boolean K_RingsActive(void); boolean K_StackingActive(void); boolean K_ChainingActive(void); +boolean K_BoostChain(player_t *player, INT32 timer); +INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement); boolean K_UsingLegacyCheckpoints(void); void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index f5527f5c3..6bcccd642 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4032,6 +4032,31 @@ static int lib_kClearBoost(lua_State *L) return 0; } +static int lib_kBoostChain(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INT32 timer = luaL_checkinteger(L, 2); + + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushboolean(L, K_BoostChain(player, timer)); + return 1; +} + +static int lib_kChainOrDeincrementTime(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INT32 timer = luaL_checkinteger(L, 2); + INT32 deincrement = luaL_checkinteger(L, 3); + + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushinteger(L, K_ChainOrDeincrementTime(player, timer, deincrement)); + return 1; +} + static int lib_getTimeMicros(lua_State *L) { lua_pushinteger(L, I_GetPreciseTime() / (I_GetPrecisePrecision() / 1000000)); @@ -4336,6 +4361,9 @@ static luaL_Reg lib[] = { {"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints}, {"K_DoBoost",lib_kDoBoost}, {"K_ClearBoost",lib_kClearBoost}, + {"K_BoostChain",lib_kBoostChain}, + {"K_ChainOrDeincrementTime",lib_kChainOrDeincrementTime}, + // k_boss {"K_InitBossHealthBar", lib_kInitBossHealthBar}, From 64eb425b789f7cb2cae4d3a201e1d7f1cf0e6eaa Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 25 Mar 2025 23:26:48 -0400 Subject: [PATCH 5/9] stacking pt.4.5: Ring Adjustments Rings are now capped for all modes to around chao's max duration. Ringboost affect on chaintimer has been capped to prevent them from desynching too much due to ring chaining nerf --- src/k_kart.c | 8 +++++++- src/p_enemy.c | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 14e887e47..5a96b65fd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7109,9 +7109,15 @@ static void K_HandleRingDeincrement(player_t *player, boolean chainnerf) finalringtimer += subring; } + + if (player->ringboost - finalringtimer > player->chaintimer) + { + // Cap this to prevent displacement between chaintimer and ringtimer. + player->chaintimer = min(player->ringboost, (TICRATE - TICRATE/4)); + } } - player->ringboost = max(0, K_ChainOrDeincrementTime(player, player->ringboost, finalringtimer)); + player->ringboost = max(player->chaintimer ? 1: 0, player->ringboost - finalringtimer); } /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c diff --git a/src/p_enemy.c b/src/p_enemy.c index b03409253..e79b11c4e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3583,6 +3583,9 @@ void A_AttractChase(mobj_t *actor) actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true) + 3; S_StartSoundAtVolume(actor->target, sfx_s1b5, actor->target->player->ringvolume); + if (actor->target->player->ringboost > (4*TICRATE + TICRATE/2)) + actor->target->player->ringboost = (4*TICRATE + TICRATE/2); + actor->target->player->ringvolume -= RINGVOLUMEUSEPENALTY; P_KillMobj(actor, actor->target, actor->target, DMG_NORMAL); @@ -3607,6 +3610,9 @@ void A_AttractChase(mobj_t *actor) if (!P_GivePlayerRings(actor->target->player, 1)) // returns 0 if addition failed actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true) + 3; + if (actor->target->player->ringboost > (4*TICRATE + TICRATE/2)) + actor->target->player->ringboost = (4*TICRATE + TICRATE/2); + if (actor->cvmem) // caching S_StartSound(actor->target, sfx_s1c5); else From a68eb5146537332008d2a1bc9d08a74e7e6a2075 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 26 Mar 2025 09:29:05 -0400 Subject: [PATCH 6/9] stacking part 5: Implement stacking visual --- src/info/mobjs.h | 2 ++ src/info/sprites.h | 2 ++ src/info/states.h | 2 ++ src/k_kart.c | 34 ++++++++++++++++------------------ src/p_mobj.c | 28 ++++++++++++++++++++++++++-- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/info/mobjs.h b/src/info/mobjs.h index 420089a39..5a4646cfa 100644 --- a/src/info/mobjs.h +++ b/src/info/mobjs.h @@ -1058,6 +1058,8 @@ _(TUMBLECOIN) _(KARMAFIREWORK) _(GAINAX) +_(BOOSTSTACK) + _(FOLLOWER) _(FOLLOWERBUBBLE_FRONT) _(FOLLOWERBUBBLE_BACK) diff --git a/src/info/sprites.h b/src/info/sprites.h index 55922f37c..718540c9c 100644 --- a/src/info/sprites.h +++ b/src/info/sprites.h @@ -715,6 +715,8 @@ _(WTRU) // Water Trail Underlay _(GCHA) // follower: generic chao _(CHEZ) // follower: cheese +_(BSSS) // Stacking effect + _(TRCK) // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later diff --git a/src/info/states.h b/src/info/states.h index 4cfb6fb4e..ef8581667 100644 --- a/src/info/states.h +++ b/src/info/states.h @@ -4200,6 +4200,8 @@ _(GAINAX_HUGE) _(GAINAX_MID1) _(GAINAX_MID2) +_(BOOSTSTACK) + _(WAYPOINTORB) _(WAYPOINTSPLAT) _(EGOORB) diff --git a/src/k_kart.c b/src/k_kart.c index 5a96b65fd..6ecb25d65 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2301,6 +2301,17 @@ void K_SpawnInvincibilitySpeedLines(mobj_t *mo) fast->destscale = 6*((mo->player->invincibilitytimer/TICRATE)*FRACUNIT)/8; } +static void K_SpawnStackingEffect(player_t *player) +{ + // Thanks to 1ndev for code used for booststack->scale and boosttack->frame! (taken and modified from BoostStack) + mobj_t *booststack = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTSTACK); + P_SetTarget(&booststack->target, player->mo); + P_SetScale(booststack, FixedMul(FRACUNIT + FixedMul(2*FRACUNIT - FRACUNIT, FixedDiv(min(player->numboosts,4)*FRACUNIT, 4*FRACUNIT)), mapobjectscale)); + + booststack->angle = player->mo->angle + ANGLE_90; + booststack->color = player->mo->color; +} + void K_SpawnBumpEffect(mobj_t *mo) { mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); @@ -7194,25 +7205,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - /*if (gametype == GT_RACE && player->rings <= 0 && (K_RingsActive() == true)) // spawn ring debt indicator + // Stacking Effect + if (stackingactive && player->numboosts > 1) { - mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, - player->mo->z + P_GetMobjZMovement(player->mo) + player->mo->height + (24*player->mo->scale), MT_THOK); - - P_SetMobjState(debtflag, S_RINGDEBT); - P_SetScale(debtflag, (debtflag->destscale = player->mo->scale)); - - K_MatchGenericExtraFlags(debtflag, player->mo); - debtflag->frame += (leveltime % 4); - - if ((leveltime/12) & 1) - debtflag->frame += 4; - - debtflag->color = player->skincolor; - debtflag->fuse = 2; - - debtflag->renderflags = K_GetPlayerDontDrawFlag(player); - }*/ + K_SpawnStackingEffect(player); + } } if (player->itemtype == KITEM_NONE) @@ -8812,6 +8809,7 @@ INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage) 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); P_SetTarget(&overlay->target, player->mo); P_SetScale(overlay, (overlay->destscale = player->mo->scale)); K_FlipFromObject(overlay, player->mo); diff --git a/src/p_mobj.c b/src/p_mobj.c index 799bcf73c..ee531b4ff 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7081,11 +7081,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->angle = mobj->extravalue1 && p ? p->drawangle : mobj->target->angle; P_MoveOrigin(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z); + K_FlipFromObject(mobj, mobj->target); P_SetScale(mobj, mobj->target->scale); mobj->roll = mobj->target->roll; mobj->pitch = mobj->target->pitch; + mobj->sloperoll = mobj->target->sloperoll; + mobj->slopepitch = mobj->target->slopepitch; + if (p) { if (mobj->extravalue1) @@ -7129,7 +7133,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (mobj->extravalue1) { - if (leveltime % 2 == 1) { mobj->frame |= FF_TRANS60; @@ -7143,7 +7146,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { mobj->color = K_RainbowColor(leveltime); } - } if (mobj->state == &states[S_BOOSTSMOKESPAWNER]) @@ -7307,6 +7309,28 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } break; + case MT_BOOSTSTACK: + { + if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->health || (mobj->target->player && !mobj->target->player->numboosts)) + { + P_RemoveMobj(mobj); + return false; + } + + mobj->roll = mobj->target->roll; + mobj->pitch = mobj->target->pitch; + + mobj->sloperoll = mobj->target->sloperoll; + mobj->slopepitch = mobj->target->slopepitch; + + // Thx Indev! (taken and modified from BoostStack) + P_MoveOrigin(mobj, mobj->target->x + FixedMul(cos(mobj->target->angle), FixedMul(30*FRACUNIT, mapobjectscale)), mobj->target->y + FixedMul(sin(mobj->target->angle), FixedMul(30*FRACUNIT, mapobjectscale)), mobj->target->z); + K_FlipFromObject(mobj, mobj->target); + + // Leveltime based animation + mobj->frame = states[S_BOOSTSTACK].frame + (leveltime / 3) % 5; + break; + } case MT_THUNDERSHIELD: { if (!mobj->target || !mobj->target->health || !mobj->target->player From 945704849f825bc13701f272cf8d84a0dcc68dda Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 26 Mar 2025 11:42:56 -0400 Subject: [PATCH 7/9] stacking part 6: Implement customization cvars --- src/command.c | 1 + src/command.h | 1 + src/d_netcmd.c | 33 ++++++++++ src/d_netcmd.h | 32 +++++++++ src/d_player.h | 1 + src/doomdef.h | 2 +- src/info/sounds.h | 3 + src/k_kart.c | 151 ++++++++++++++++++++++++++++++++----------- src/k_kart.h | 39 ++++++++++- src/lua_baselib.c | 6 +- src/lua_consolelib.c | 2 + src/lua_playerlib.c | 8 +++ src/p_mobj.c | 35 +++++++++- src/p_saveg.c | 2 + src/p_setup.c | 6 +- 15 files changed, 274 insertions(+), 48 deletions(-) diff --git a/src/command.c b/src/command.c index 133bcfd69..66a5e0182 100644 --- a/src/command.c +++ b/src/command.c @@ -74,6 +74,7 @@ static char * COM_Purge (char *text, int *lenp); CV_PossibleValue_t CV_OnOff[] = {{0, "Off"}, {1, "On"}, {0, NULL}}; CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}}; +CV_PossibleValue_t CV_Signed[] = {{-999999999, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}}; CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; diff --git a/src/command.h b/src/command.h index 9aba7d707..1e5a1a19c 100644 --- a/src/command.h +++ b/src/command.h @@ -170,6 +170,7 @@ struct consvar_t //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NULL extern CV_PossibleValue_t CV_OnOff[]; extern CV_PossibleValue_t CV_YesNo[]; +extern CV_PossibleValue_t CV_Signed[]; extern CV_PossibleValue_t CV_Unsigned[]; extern CV_PossibleValue_t CV_Natural[]; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5bfebc63f..a80c36e5c 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -442,8 +442,41 @@ consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVA // Toggles for new features consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange); + +// Stacking related consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartStacking_OnChange); +consvar_t cv_kartstacking_calc_arg_offset = CVAR_INIT ("kartstacking_calcargoffset", "0.32", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_maxvanillaboost = CVAR_INIT ("kartstacking_maxvanillaboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_speedboostdropoff = CVAR_INIT ("kartstacking_speedboostdropoff", "0.01", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_speedboostdropoff_brake = CVAR_INIT ("kartstacking_speedboostdropoff_brake", "0.05", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + +// Vanilla Stacking boosts. +consvar_t cv_kartstacking_sneaker_easyspeedboost = CVAR_INIT ("vanillaboost_sneaker_easyspeedboost", "0.8317", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_sneaker_normalspeedboost = CVAR_INIT ("vanillaboost_sneaker_normalspeedboost", "0.5", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_sneaker_hardspeedboost = CVAR_INIT ("vanillaboost_sneaker_hardspeedboost", "0.2756", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_sneaker_accelboost = CVAR_INIT ("vanillaboost_sneaker_accelboost", "8.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_sneaker_maxgrade = CVAR_INIT ("vanillaboost_sneaker_maxgrade", "3", CV_NETVAR|CV_CHEAT, CV_Natural, NULL); + +consvar_t cv_kartstacking_invincibility_speedboost = CVAR_INIT ("vanillaboost_invincibility_speedboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_invincibility_accelboost = CVAR_INIT ("vanillaboost_invincibility_accelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_grow_speedboost = CVAR_INIT ("vanillaboost_grow_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_grow_accelboost = CVAR_INIT ("vanillaboost_grow_accelboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_flame_speedval = CVAR_INIT ("vanillaboost_flame_speedval", "0.80", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_flame_accelboost = CVAR_INIT ("vanillaboost_flame_accelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_start_speedboost = CVAR_INIT ("vanillaboost_start_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_start_accelboost = CVAR_INIT ("vanillaboost_start_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_drift_speedboost = CVAR_INIT ("vanillaboost_drift_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_drift_accelboost = CVAR_INIT ("vanillaboost_drift_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + +consvar_t cv_kartstacking_ring_speedboost = CVAR_INIT ("vanillaboost_ring_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); +consvar_t cv_kartstacking_ring_accelboost = CVAR_INIT ("vanillaboost_ring_accelboost", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL); + consvar_t cv_kartchaining = CVAR_INIT ("kartchaining", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartChaining_OnChange); +consvar_t cv_kartchainingoffroad = CVAR_INIT ("kartchaining_chainoffroad", "No", CV_NETVAR, CV_YesNo, NULL); consvar_t cv_kartitembreaker = CVAR_INIT ("kartitembreaker", "No", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_YesNo, KartItemBreaker_OnChange); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 35914b448..0fc16f637 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -96,8 +96,40 @@ extern consvar_t cv_kartbot; extern consvar_t cv_karteliminatelast; extern consvar_t cv_kartusepwrlv; extern consvar_t cv_kartrings; + extern consvar_t cv_kartstacking; +extern consvar_t cv_kartstacking_calc_arg_offset; +extern consvar_t cv_kartstacking_maxvanillaboost; +extern consvar_t cv_kartstacking_speedboostdropoff; +extern consvar_t cv_kartstacking_speedboostdropoff_brake; + +extern consvar_t cv_kartstacking_sneaker_easyspeedboost; +extern consvar_t cv_kartstacking_sneaker_normalspeedboost; +extern consvar_t cv_kartstacking_sneaker_hardspeedboost; +extern consvar_t cv_kartstacking_sneaker_accelboost; +extern consvar_t cv_kartstacking_sneaker_maxgrade; + +extern consvar_t cv_kartstacking_invincibility_speedboost; +extern consvar_t cv_kartstacking_invincibility_accelboost; + +extern consvar_t cv_kartstacking_flame_speedval; +extern consvar_t cv_kartstacking_flame_accelboost; + +extern consvar_t cv_kartstacking_grow_speedboost; +extern consvar_t cv_kartstacking_grow_accelboost; + +extern consvar_t cv_kartstacking_start_speedboost; +extern consvar_t cv_kartstacking_start_accelboost; + +extern consvar_t cv_kartstacking_drift_speedboost; +extern consvar_t cv_kartstacking_drift_accelboost; + +extern consvar_t cv_kartstacking_ring_speedboost; +extern consvar_t cv_kartstacking_ring_accelboost; + extern consvar_t cv_kartchaining; +extern consvar_t cv_kartchainingoffroad; + extern consvar_t cv_kartitembreaker; extern consvar_t cv_kartwalltransfer; extern consvar_t cv_kartpurpledrift; diff --git a/src/d_player.h b/src/d_player.h index 0866cc122..9c337042b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -632,6 +632,7 @@ struct player_t SINT8 stolentimer; // you are being stolen from UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters) + UINT16 realsneakertimer;// Duration of a Sneaker Boosts acutal time that doesn't get chained.(used for chainoffroad and tripwires) UINT8 floorboost; // (0 to 3) - Prevents Sneaker sounds for a brief duration when triggered by a floor panel UINT16 chaintimer; // Stores current chain timer length. diff --git a/src/doomdef.h b/src/doomdef.h index 9888fe66e..34d131872 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -101,7 +101,7 @@ extern "C" { #endif -//#define NOMD5 +#define NOMD5 // Uncheck this to compile debugging code //#define RANGECHECK diff --git a/src/info/sounds.h b/src/info/sounds.h index f349a98e4..a1a04fa5e 100644 --- a/src/info/sounds.h +++ b/src/info/sounds.h @@ -1054,6 +1054,9 @@ _(kdtrg1) _(kdtrg2) _(kdtrg3) +// Chaining Sound +_(bstchn) + // Shout message sound effect _(sysmsg) diff --git a/src/k_kart.c b/src/k_kart.c index 6ecb25d65..32f6617d0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -49,6 +49,12 @@ #include "k_follower.h" #include "k_grandprix.h" +consvar_t cv_kartstacking_colorflame = CVAR_INIT ("kartstacking_colorflame", "On", 0, CV_OnOff, NULL); +consvar_t cv_kartstacking_sneakerstacksound = CVAR_INIT ("kartstacking_sneakerstacksound", "On", 0, CV_OnOff, NULL); +consvar_t cv_kartchainingsound = CVAR_INIT ("kartchaining_chainsound", "On", 0, CV_OnOff, NULL); +consvar_t cv_kartdriftsounds = CVAR_INIT ("kartdriftsounds", "On", 0, CV_OnOff, NULL); +consvar_t cv_kartdriftefx = CVAR_INIT ("kartdriftefx", "On", 0, CV_OnOff, NULL); + // SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H: // gamespeed is cc (0 for easy, 1 for normal, 2 for hard) // franticitems is Frantic Mode items, bool @@ -253,8 +259,44 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_lessflicker); CV_RegisterVar(&cv_kartrings); + + // Stacking CV_RegisterVar(&cv_kartstacking); + CV_RegisterVar(&cv_kartstacking_calc_arg_offset); + CV_RegisterVar(&cv_kartstacking_speedboostdropoff); + CV_RegisterVar(&cv_kartstacking_speedboostdropoff_brake); + CV_RegisterVar(&cv_kartstacking_colorflame); + CV_RegisterVar(&cv_kartstacking_sneakerstacksound); + + // Vanilla Boosts + CV_RegisterVar(&cv_kartstacking_sneaker_easyspeedboost); + CV_RegisterVar(&cv_kartstacking_sneaker_normalspeedboost); + CV_RegisterVar(&cv_kartstacking_sneaker_hardspeedboost); + CV_RegisterVar(&cv_kartstacking_sneaker_accelboost); + CV_RegisterVar(&cv_kartstacking_sneaker_maxgrade); + + CV_RegisterVar(&cv_kartstacking_invincibility_speedboost); + CV_RegisterVar(&cv_kartstacking_invincibility_accelboost); + + CV_RegisterVar(&cv_kartstacking_grow_speedboost); + CV_RegisterVar(&cv_kartstacking_grow_accelboost); + + CV_RegisterVar(&cv_kartstacking_flame_speedval); + CV_RegisterVar(&cv_kartstacking_flame_accelboost); + + CV_RegisterVar(&cv_kartstacking_start_speedboost); + CV_RegisterVar(&cv_kartstacking_start_accelboost); + + CV_RegisterVar(&cv_kartstacking_drift_speedboost); + CV_RegisterVar(&cv_kartstacking_drift_accelboost); + + CV_RegisterVar(&cv_kartstacking_ring_speedboost); + CV_RegisterVar(&cv_kartstacking_ring_accelboost); + CV_RegisterVar(&cv_kartchaining); + CV_RegisterVar(&cv_kartchainingoffroad); + CV_RegisterVar(&cv_kartchainingsound); + CV_RegisterVar(&cv_kartitembreaker); CV_RegisterVar(&cv_newspeedometer); @@ -267,6 +309,10 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartbumpspark); CV_RegisterVar(&cv_kartbumpspring); + + CV_RegisterVar(&cv_kartdriftsounds); + + CV_RegisterVar(&cv_kartdriftefx); } //} @@ -3070,7 +3116,9 @@ void K_MomentumToFacing(player_t *player) boolean K_ApplyOffroad(player_t *player) { - if (player->invincibilitytimer || player->hyudorotimer || player->sneakertimer) + boolean sneakertimer = CANTCHAINOFFROAD ? (player->sneakertimer && player->realsneakertimer) : player->sneakertimer; + + if (player->invincibilitytimer || player->hyudorotimer || sneakertimer) return false; return true; } @@ -3110,7 +3158,7 @@ tripwirepass_t K_TripwirePassConditions(player_t *player) { if ( player->invincibilitytimer || - player->sneakertimer + (player->sneakertimer && player->realsneakertimer) ) return TRIPWIRE_BLASTER; @@ -3302,25 +3350,17 @@ static inline fixed_t K_GetSneakerBoostSpeed(void) switch (gamespeed) { case 0: - return 53740+768; + return EASYSNEAKERSPEEDBOOST; break; case 2: - return 17294+768; + return HARDSNEAKERSPEEDBOOST; break; default: - return 32768; + return NORMALSNEAKERSPEEDBOOST; break; } } -// Precalculated constants for stacked boost diminishing -// *Somewhat* matches old calc but doesn't use arrays, which makes it faster and more memory efficent -#define CALC_ARG_OFFSET 32*FRACUNIT/100 -#define CALC_RET_OFFSET FixedSqrt(CALC_ARG_OFFSET) -#define MAXVANILLABOOST 3*FRACUNIT/8 -#define SPEEDBOOSTDROPOFF FloatToFixed(0.01) -#define SPEEDBOOSTDROPOFF_BRAKE FloatToFixed(0.05) - static fixed_t diminish(fixed_t speedboost) { return FixedSqrt(speedboost + CALC_ARG_OFFSET) - CALC_RET_OFFSET; @@ -3387,20 +3427,22 @@ static void K_GetKartBoostPower(player_t *player) { UINT8 i; fixed_t sneakerspeedboost = K_GetSneakerBoostSpeed(); - for (i = 0; i < player->numsneakers; i++) + UINT8 numsneakers = player->numsneakers ? player->numsneakers : 1; + + for (i = 0; i < numsneakers; i++) { - K_DoBoost(player, sneakerspeedboost, 8*FRACUNIT, true, true); // + ???% top speed, + 800% acceleration + K_DoBoost(player, sneakerspeedboost, SNEAKERACCELBOOST, true, true); // + ???% top speed, + 800% acceleration } } if (player->invincibilitytimer) // Invincibility { - K_DoBoost(player, 3*FRACUNIT/8, 3*FRACUNIT, false, false); // + 37.5% top speed, + 300% acceleration + K_DoBoost(player, INVINSPEEDBOOST, INVINACCELBOOST, false, false); // + 37.5% top speed, + 300% acceleration } if (player->growshrinktimer > 0) // Grow { - K_DoBoost(player, FRACUNIT/5, 0, false, false); // + 20% top speed, + 0% acceleration + K_DoBoost(player, GROWSPEEDBOOST, GROWACCELBOOST, false, false); // + 20% top speed, + 0% acceleration } if (player->flamestore) // Flame Shield dash @@ -3408,28 +3450,27 @@ static void K_GetKartBoostPower(player_t *player) fixed_t dash = K_FlameShieldDashVar(player->flamedash); fixed_t intermediate = 0; fixed_t boost = 0; - fixed_t val = 52428; // Rim idea: diminish starts around 1.2x sneaker speed and plateaus around 1.4-1.5x - fixed_t accel = 3*FRACUNIT; + fixed_t val = FLAMESPEEDVAL; // Rim idea: diminish starts around 1.2x sneaker speed and plateaus around 1.4-1.5x intermediate = FixedDiv(FixedMul(val, FRACUNIT*-1/2) - FRACUNIT/4,-val+FRACUNIT/2); boost = FixedMul(val,(FRACUNIT-FixedDiv(FRACUNIT,(dash+intermediate)))); - K_DoBoost(player, boost, accel, false, false); + K_DoBoost(player, boost, FLAMEACCELBOOST, false, false); } if (player->startboost) // Startup Boost { - K_DoBoost(player, FRACUNIT/4, 6*FRACUNIT, true, true); // + 25% top speed, + 300% acceleration + K_DoBoost(player, STARTSPEEDBOOST, STARTACCELBOOST, true, true); // + 25% top speed, + 600% acceleration } if (player->driftboost) // Drift Boost { - K_DoBoost(player, FRACUNIT/4, 4*FRACUNIT, true, true); // + 25% top speed, + 400% acceleration + K_DoBoost(player, DRIFTSPEEDBOOST, DRIFTACCELBOOST, true, true); // + 25% top speed, + 400% acceleration } if (player->ringboost) // Ring Boost { - K_DoBoost(player, FRACUNIT/5, 4*FRACUNIT, true, true); // + 20% top speed, + 400% acceleration + K_DoBoost(player, RINGSPEEDBOOST, RINGACCELBOOST, true, true); // + 20% top speed, + 400% acceleration } // This should always remain the last boost @@ -5284,6 +5325,7 @@ void K_DoSneaker(player_t *player, INT32 type) } player->sneakertimer = sneakertime; + player->realsneakertimer = sneakertime; if (player->sneakertimer && (player->floorboost == 0 || player->floorboost == 3)) { @@ -5309,6 +5351,7 @@ void K_DoWaterRunPanel(player_t *player) K_SneakerPanelEffect(player, 0); player->sneakertimer = TICRATE*2; + player->realsneakertimer = TICRATE*2; if (player->sneakertimer && (player->floorboost == 0 || player->floorboost == 3)) { @@ -7028,7 +7071,7 @@ static void K_TireGreaseEffect(player_t *player) S_StartSound(player->mo, sfx_screec); } -boolean K_BoostChain(player_t *player, INT32 timer) +boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound) { if (!chainingactive) { @@ -7039,6 +7082,15 @@ boolean K_BoostChain(player_t *player, INT32 timer) if (timer > player->chaintimer) { // Just what I needed! - Toad + if (cv_kartchainingsound.value && chainsound && player->chaintimer && player->sneakertimer) + { + if (player->mo) + { + // Chain Sound! + S_StartSound(player->mo, sfx_bstchn); + } + } + player->chaintimer = timer; } @@ -7052,11 +7104,11 @@ boolean K_BoostChain(player_t *player, INT32 timer) return false; } -INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement) +INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement, boolean chainsound) { timer -= deincrement; - if (K_BoostChain(player, timer)) + if (K_BoostChain(player, timer, chainsound)) { // Its time to chain. return max(1, timer); @@ -7140,8 +7192,6 @@ static void K_HandleRingDeincrement(player_t *player, boolean chainnerf) */ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { - const boolean onground = P_IsObjectOnGround(player->mo); - /* reset sprite offsets :) */ player->mo->sprxoff = 0; player->mo->spryoff = 0; @@ -7311,7 +7361,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->sneakertimer) { - player->sneakertimer = K_ChainOrDeincrementTime(player, player->sneakertimer, 1); + player->sneakertimer = K_ChainOrDeincrementTime(player, player->sneakertimer, 1, false); if (player->sneakertimer <= 0) { @@ -7320,6 +7370,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } + if (player->realsneakertimer) + player->realsneakertimer--; + if (player->sneakertimer && player->wipeoutslow > 0 && player->wipeoutslow < wipeoutslowtime+1) player->wipeoutslow = wipeoutslowtime+1; @@ -7327,10 +7380,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->floorboost--; if (player->driftboost) - player->driftboost = K_ChainOrDeincrementTime(player, player->driftboost, 1); + player->driftboost = K_ChainOrDeincrementTime(player, player->driftboost, 1, true); if (player->startboost > 0) - player->startboost = K_ChainOrDeincrementTime(player, player->startboost, 1); + player->startboost = K_ChainOrDeincrementTime(player, player->startboost, 1, false); if (player->invincibilitytimer) player->invincibilitytimer--; @@ -8808,6 +8861,12 @@ INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage) static void K_SpawnDriftEFX(player_t *player,SINT8 level) { + if (!cv_kartdriftefx.value) + { + // Not wanted sorry! + return; + } + mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME); P_SetMobjState(overlay, S_DRIFTBOOSTFLAME); P_SetTarget(&overlay->target, player->mo); @@ -8865,8 +8924,11 @@ static void K_KartDrift(player_t *player, boolean onground) { if (player->driftboost < 50) player->driftboost = 50; + + if (cv_kartdriftsounds.value) + S_StartSound(player->mo, sfx_kc5b); S_StartSound(player->mo, sfx_s23c); - S_StartSound(player->mo, sfx_kc5b); + K_SpawnDriftEFX(player, 2); player->driftcharge = 0; } @@ -8876,9 +8938,16 @@ static void K_KartDrift(player_t *player, boolean onground) { if (player->driftboost < 80) player->driftboost = 80; - S_StartSound(player->mo, sfx_kc5b); - S_StartSound(player->mo, sfx_kc3c); - S_StartSound(player->mo, sfx_s3k47); + if (cv_kartdriftsounds.value) + { + S_StartSound(player->mo, sfx_kc5b); + S_StartSound(player->mo, sfx_kc3c); + S_StartSound(player->mo, sfx_s3k47); + } + else + { + S_StartSound(player->mo, sfx_s23c); + } K_SpawnDriftEFX(player, 3); player->driftcharge = 0; } @@ -8888,8 +8957,16 @@ static void K_KartDrift(player_t *player, boolean onground) { if (player->driftboost < 125) player->driftboost = 125; - S_StartSound(player->mo, sfx_kc5b); - S_StartSound(player->mo, sfx_kc4d); + if (cv_kartdriftsounds.value) + { + S_StartSound(player->mo, sfx_kc5b); + S_StartSound(player->mo, sfx_kc4d); + } + else + { + S_StartSound(player->mo, sfx_s23c); + } + K_SpawnDriftEFX(player, 4); player->driftcharge = 0; } diff --git a/src/k_kart.h b/src/k_kart.h index 45e80b903..45a1e6d8a 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -14,6 +14,12 @@ extern "C" { #endif +extern consvar_t cv_kartstacking_colorflame; +extern consvar_t cv_kartstacking_sneakerstacksound; +extern consvar_t cv_kartchainingsound; +extern consvar_t cv_kartdriftsounds; +extern consvar_t cv_kartdriftefx; + #define KART_FULLTURN 800 /* @@ -31,7 +37,34 @@ Make sure this matches the actual number of states #define FLAMESTOREMAX TICRATE*2 -#define MAXSNEAKERSTACK 3 +// Precalculated constants for stacked boost diminishing +// *Somewhat* matches old calc but doesn't use arrays, which makes it faster and more memory efficent +#define CALC_ARG_OFFSET cv_kartstacking_calc_arg_offset.value +#define CALC_RET_OFFSET FixedSqrt(CALC_ARG_OFFSET) +#define MAXVANILLABOOST cv_kartstacking_maxvanillaboost.value +#define SPEEDBOOSTDROPOFF cv_kartstacking_speedboostdropoff.value +#define SPEEDBOOSTDROPOFF_BRAKE cv_kartstacking_speedboostdropoff_brake.value + +// Vanilla Boosts +#define EASYSNEAKERSPEEDBOOST cv_kartstacking_sneaker_easyspeedboost.value +#define NORMALSNEAKERSPEEDBOOST cv_kartstacking_sneaker_normalspeedboost.value +#define HARDSNEAKERSPEEDBOOST cv_kartstacking_sneaker_hardspeedboost.value +#define SNEAKERACCELBOOST cv_kartstacking_sneaker_accelboost.value +#define MAXSNEAKERSTACK cv_kartstacking_sneaker_maxgrade.value +#define INVINSPEEDBOOST cv_kartstacking_invincibility_speedboost.value +#define INVINACCELBOOST cv_kartstacking_invincibility_accelboost.value +#define GROWSPEEDBOOST cv_kartstacking_grow_speedboost.value +#define GROWACCELBOOST cv_kartstacking_grow_accelboost.value +#define FLAMESPEEDVAL cv_kartstacking_flame_speedval.value +#define FLAMEACCELBOOST cv_kartstacking_flame_accelboost.value +#define STARTSPEEDBOOST cv_kartstacking_start_speedboost.value +#define STARTACCELBOOST cv_kartstacking_start_accelboost.value +#define DRIFTSPEEDBOOST cv_kartstacking_drift_speedboost.value +#define DRIFTACCELBOOST cv_kartstacking_drift_accelboost.value +#define RINGSPEEDBOOST cv_kartstacking_ring_speedboost.value +#define RINGACCELBOOST cv_kartstacking_ring_accelboost.value + +#define CANTCHAINOFFROAD (cv_kartchaining.value && !cv_kartchainingoffroad.value) // Used for respawning checks. @@ -196,8 +229,8 @@ boolean K_SafeRespawnPosition(mobj_t * mo); boolean K_RingsActive(void); boolean K_StackingActive(void); boolean K_ChainingActive(void); -boolean K_BoostChain(player_t *player, INT32 timer); -INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement); +boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound); +INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement, boolean chainsound); boolean K_UsingLegacyCheckpoints(void); void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 6bcccd642..eb69ae4df 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4036,11 +4036,12 @@ static int lib_kBoostChain(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 timer = luaL_checkinteger(L, 2); + INT32 chainsound = lua_optboolean(L, 3); //HUDSAFE if (!player) return LUA_ErrInvalid(L, "player_t"); - lua_pushboolean(L, K_BoostChain(player, timer)); + lua_pushboolean(L, K_BoostChain(player, timer, chainsound)); return 1; } @@ -4049,11 +4050,12 @@ static int lib_kChainOrDeincrementTime(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 timer = luaL_checkinteger(L, 2); INT32 deincrement = luaL_checkinteger(L, 3); + INT32 chainsound = lua_optboolean(L, 4); //HUDSAFE if (!player) return LUA_ErrInvalid(L, "player_t"); - lua_pushinteger(L, K_ChainOrDeincrementTime(player, timer, deincrement)); + lua_pushinteger(L, K_ChainOrDeincrementTime(player, timer, deincrement, chainsound)); return 1; } diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 233a7ee4c..d9cb4ef36 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -590,6 +590,8 @@ int LUA_ConsoleLib(lua_State *L) lua_setglobal(L, "CV_YesNo"); lua_pushlightuserdata(L, CV_Unsigned); lua_setglobal(L, "CV_Unsigned"); + lua_pushlightuserdata(L, CV_Signed); + lua_setglobal(L, "CV_Signed"); lua_pushlightuserdata(L, CV_Natural); lua_setglobal(L, "CV_Natural"); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0dc5ccf63..515c84032 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -263,6 +263,7 @@ enum player_e player_stealingtimer, player_stolentimer, player_sneakertimer, + player_realsneakertimer, player_floorboost, player_chaintimer, player_growshrinktimer, @@ -436,6 +437,7 @@ static const char *const player_opt[] = { "stealingtimer", "stolentimer", "sneakertimer", + "realsneakertimer", "floorboost", "chaintimer", "growshrinktimer", @@ -809,6 +811,9 @@ static int player_get(lua_State *L) case player_sneakertimer: lua_pushinteger(L, plr->sneakertimer); break; + case player_realsneakertimer: + lua_pushinteger(L, plr->realsneakertimer); + break; case player_floorboost: lua_pushinteger(L, plr->floorboost); break; @@ -1403,6 +1408,9 @@ static int player_set(lua_State *L) case player_sneakertimer: plr->sneakertimer = luaL_checkinteger(L, 3); break; + case player_realsneakertimer: + plr->realsneakertimer = luaL_checkinteger(L, 3); + break; case player_floorboost: plr->floorboost = luaL_checkinteger(L, 3); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index ee531b4ff..2c3efefd2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7070,7 +7070,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } - { player_t *p = NULL; if (mobj->target->target && mobj->target->target->player) @@ -7080,7 +7079,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->angle = mobj->extravalue1 && p ? p->drawangle : mobj->target->angle; P_MoveOrigin(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius), - mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z); + mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z+5*mapobjectscale); K_FlipFromObject(mobj, mobj->target); P_SetScale(mobj, mobj->target->scale); @@ -7124,6 +7123,38 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } else { + if (stackingactive && cv_kartstacking_colorflame.value) + { + switch(p->numsneakers) + { + case 0: + case 1: + mobj->colorized = false; + break; + case 2: + mobj->colorized = true; + mobj->color = SKINCOLOR_BLUEBERRY; + break; + case 3: + mobj->colorized = true; + mobj->color = SKINCOLOR_PURPLE; + break; + case 4: + mobj->colorized = true; + mobj->color = SKINCOLOR_MOONSLAM; + break; + case 5: + mobj->colorized = true; + mobj->color = SKINCOLOR_WHITE; + break; + default: + mobj->colorized = true; + mobj->color = SKINCOLOR_WHITE; + break; + + } + } + if (p->sneakertimer > mobj->movecount) P_SetMobjState(mobj, S_BOOSTFLAME); mobj->movecount = p->sneakertimer; diff --git a/src/p_saveg.c b/src/p_saveg.c index 3a6bd771a..d05c02553 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -318,6 +318,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITESINT8(save->p, players[i].stealingtimer); WRITEUINT16(save->p, players[i].sneakertimer); + WRITEUINT16(save->p, players[i].realsneakertimer); WRITEUINT8(save->p, players[i].floorboost); WRITEUINT16(save->p, players[i].chaintimer); @@ -631,6 +632,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].stealingtimer = READSINT8(save->p); players[i].sneakertimer = READUINT16(save->p); + players[i].realsneakertimer = READUINT16(save->p); players[i].floorboost = READUINT8(save->p); players[i].chaintimer = READUINT16(save->p); diff --git a/src/p_setup.c b/src/p_setup.c index f45142c36..9977e7bf2 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -142,9 +142,9 @@ line_t *spawnlines; side_t *spawnsides; INT32 numstarposts; INT32 numbosswaypoints; -boolean ringsactive; -boolean stackingactive; -boolean chainingactive; +boolean ringsactive = false; +boolean stackingactive = false; +boolean chainingactive = false; UINT16 bossdisabled; boolean stoppedclock; boolean levelloading; From 39da5497604de2524f7e2d6789b86415f0b387dc Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 26 Mar 2025 14:06:04 -0400 Subject: [PATCH 8/9] Almost forgot to give perfect start mowing privilages --- src/k_kart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.c b/src/k_kart.c index 32f6617d0..9aa561d04 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7003,6 +7003,7 @@ static void K_RaceStart(player_t *player) player->startboost = 0; K_DoSneaker(player, 0); player->sneakertimer = 70; // PERFECT BOOST!! + player->realsneakertimer = 70; if (!player->floorboost || player->floorboost == 3) // Let everyone hear this one S_StartSound(player->mo, sfx_s25f); From d225476b9b32d95cb6661e2960943568a8d4bb1d Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 26 Mar 2025 14:12:49 -0400 Subject: [PATCH 9/9] Redisable NOMD5 --- src/doomdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index 34d131872..9888fe66e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -101,7 +101,7 @@ extern "C" { #endif -#define NOMD5 +//#define NOMD5 // Uncheck this to compile debugging code //#define RANGECHECK