From 8f4a698a35debeba817070d59a340be75f297cfc Mon Sep 17 00:00:00 2001 From: Oni VelocitOni Date: Fri, 26 Sep 2025 17:58:02 +0000 Subject: [PATCH] Subsonic Adjustments --- src/d_player.h | 3 +- src/deh_tables.c | 3 ++ src/info.c | 29 ++++++++++++++ src/info.h | 3 ++ src/k_kart.c | 52 +++++++++++++++++++----- src/k_kart.h | 2 +- src/lua_playerlib.c | 4 ++ src/p_mobj.c | 97 ++++++++++++++++++++++++++++++++++++++++----- src/p_saveg.cpp | 2 + src/sounds.c | 6 +++ src/sounds.h | 5 +++ 11 files changed, 185 insertions(+), 21 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 9a1e441b9..d9288ae77 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -383,7 +383,7 @@ typedef enum #define TUMBLEBOUNCES 3 #define TUMBLEGRAVITY (4*FRACUNIT) -#define TRIPWIRETIME (15) +#define TRIPWIRETIME (50) #define BALLHOGINCREMENT (7) @@ -821,6 +821,7 @@ struct player_t UINT16 tripwireLeniency; // When reaching a state that lets you go thru tripwire, you get an extra second leniency after it ends to still go through it. UINT8 tripwireAirLeniency; // Timer that elongates tripwire leniency when in midair. UINT8 fakeBoost; // Some items need to grant tripwire pass briefly, even when their effect is thrust/instathrust. This is a fake boost type to control that. + UINT16 subsonicleniency; // Keep the subsonic visual for just a little bit when your sonic boom is visible itemroulette_t itemRoulette; // Item roulette data diff --git a/src/deh_tables.c b/src/deh_tables.c index dcf940920..4350bd243 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1599,6 +1599,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_AMPBURST", // Tripwire VFX on player for bumping it or passing it + + "S_SONICBOOM", "S_TRIPWIREOK", "S_TRIPWIRELOCKOUT", @@ -3597,6 +3599,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_AMPAURA", "MT_AMPBURST", + "MT_SONICBOOM", "MT_TRIPWIREOK", "MT_TRIPWIRELOCKOUT", diff --git a/src/info.c b/src/info.c index 64eaf7976..bb5d7549e 100644 --- a/src/info.c +++ b/src/info.c @@ -614,6 +614,7 @@ char sprnames[NUMSPRITES + 1][5] = "EXPC", + "TWBB", "TWOK", "TW_L", @@ -2225,6 +2226,7 @@ state_t states[NUMSTATES] = {SPR_AMPD, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPAURA {SPR_AMPB, FF_FULLBRIGHT|FF_ADD|FF_PAPERSPRITE|2, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBURST + {SPR_TWBB, FF_ADD|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBOOM {SPR_TWOK, FF_FULLBRIGHT|FF_ANIMATE|0, 56, {NULL}, 55, 1, S_NULL}, // S_TRIPWIREOK {SPR_TW_L, FF_FULLBRIGHT|FF_ANIMATE|0, 56, {NULL}, 55, 1, S_NULL}, // S_TRIPWIRELOCKOUT @@ -13998,6 +14000,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SONICBOOM + -1, // doomednum + S_SONICBOOM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 67*FRACUNIT, // radius + 67*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_TRIPWIREOK -1, // doomednum S_TRIPWIREOK, // spawnstate diff --git a/src/info.h b/src/info.h index 70391a3f8..796a07b3b 100644 --- a/src/info.h +++ b/src/info.h @@ -1155,6 +1155,7 @@ typedef enum sprite SPR_EXPC, + SPR_TWBB, // Sonic Boom SPR_TWOK, // Tripwire OK SPR_TW_L, // Tripwire Lockout @@ -2681,6 +2682,7 @@ typedef enum state S_AMPAURA, S_AMPBURST, + S_SONICBOOM, S_TRIPWIREOK, S_TRIPWIRELOCKOUT, @@ -4706,6 +4708,7 @@ typedef enum mobj_type MT_AMPAURA, MT_AMPBURST, + MT_SONICBOOM, MT_TRIPWIREOK, MT_TRIPWIRELOCKOUT, diff --git a/src/k_kart.c b/src/k_kart.c index bd9cf3686..ff919d3e3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3171,6 +3171,7 @@ boolean K_SlopeResistance(const player_t *player) fixed_t K_PlayerTripwireSpeedThreshold(const player_t *player) { + fixed_t required_speed = 2 * K_GetKartSpeed(player, false, false); // 200% if (K_LegacyRingboost(player)) @@ -3182,15 +3183,48 @@ fixed_t K_PlayerTripwireSpeedThreshold(const player_t *player) if (modeattacking && !(gametyperules & GTR_CATCHER)) required_speed = 4 * K_GetKartSpeed(player, false, false); - if ((gametyperules & GTR_CIRCUIT) && !K_Cooperative() && M_NotFreePlay() && !modeattacking) + if ((gametyperules & GTR_CIRCUIT) && !K_Cooperative() && M_NotFreePlay() && !modeattacking) { - required_speed += FixedMul(required_speed, K_PlayerScamPercentage(player, 2)); // Proration: Players near 1st need more speed! - } + /* + All of this will be for making Sonic Boom easier when you're drowning in the back, like a "reverse" proration + */ - if (player->offroad && K_ApplyOffroad(player)) - { - // Increase to 300% if you're lawnmowering. - required_speed = (required_speed * 3) / 2; + #define REVERSED_SONICBOOM_PRORATION (30000) + #define MAX_SONICBOOM_REDUCTION (7*FRACUNIT/8) + + UINT32 dist = K_GetItemRouletteDistance(player, D_NumPlayersInRace()); + + if (dist > REVERSED_SONICBOOM_PRORATION) + { + dist = REVERSED_SONICBOOM_PRORATION; + } + + fixed_t distfactor = FixedDiv(dist, REVERSED_SONICBOOM_PRORATION); // + fixed_t sonicboom_aid = Easing_InCubic(distfactor, FRACUNIT, MAX_SONICBOOM_REDUCTION); + + required_speed = FixedMul(sonicboom_aid, required_speed); + + /* + And then all of this will be for making it harder when you're in scam range, actual proration + */ + + required_speed += FixedMul(required_speed, K_PlayerScamPercentage(player, 3/2)); + + if(player->position == 1) + { + required_speed = 9 * K_GetKartSpeed(player, false, false); // Seek employment + } + + /* + if (!K_PlayerUsesBotMovement(player)) // Sonic Boom debug + { + //CONS_Printf("Sonic Boom threshold: %d percent, IN FRACUNIT: %d \n", ((required_speed *100) / K_GetKartSpeed(player, false, false)), required_speed); + CONS_Printf("D=%d DF=%d SBA=%d RS=%d RRS=%d\n", dist, distfactor, sonicboom_aid, required_speed, required_speed * 100 / K_GetKartSpeed(player, false, false)); + } + */ + + #undef REVERSED_SONICBOOM_PRORATION + #undef MAX_SONICBOOM_REDUCTION } if (player->botvars.rubberband > FRACUNIT && K_PlayerUsesBotMovement(player) == true) @@ -9688,7 +9722,7 @@ static void K_UpdateTripwire(player_t *player) tripwirepass_t triplevel = K_TripwirePassConditions(player); boolean mightplaysound = false; - if (triplevel != TRIPWIRE_NONE) + if (triplevel != TRIPWIRE_NONE) // Sonic Boom, able to pass tripwire { if (!boostExists) { @@ -9894,7 +9928,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { mobj_t *ghost; ghost = P_SpawnGhostMobj(player->mo); - ghost->extravalue1 = player->numboosts+1; + ghost->extravalue1 = player->numboosts; ghost->extravalue2 = (leveltime % ghost->extravalue1); ghost->fuse = ghost->extravalue1; ghost->renderflags |= RF_FULLBRIGHT; diff --git a/src/k_kart.h b/src/k_kart.h index ad084d6fa..e45792a3a 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -76,7 +76,7 @@ Make sure this matches the actual number of states #define EARLY_ITEM_FLICKER (NUMTRANSMAPS) -#define TRIPWIRE_OK_SOUND (sfx_s3k40) +#define TRIPWIRE_OK_SOUND (sfx_sonbo2) #define TRIPWIRE_NG_SOUND (sfx_gshaf) // 2023-08-26 +ang20 to Sal's OG values to make them friendlier - Tyron diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 231ed07e0..9602d6da6 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -375,6 +375,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->tripwirePass); else if (fastcmp(field,"fakeboost")) lua_pushinteger(L, plr->fakeBoost); + else if (fastcmp(field,"subsonicleniency")) + lua_pushinteger(L, plr->subsonicleniency); else if (fastcmp(field,"tripwireleniency")) lua_pushinteger(L, plr->tripwireLeniency); else if (fastcmp(field,"tripwireairleniency")) @@ -1040,6 +1042,8 @@ static int player_set(lua_State *L) plr->tripwirePass = luaL_checkinteger(L, 3); else if (fastcmp(field,"fakeboost")) plr->fakeBoost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"subsonicleniency")) + plr->subsonicleniency = luaL_checkinteger(L, 3); else if (fastcmp(field,"tripwireleniency")) plr->tripwireLeniency = luaL_checkinteger(L, 3); else if (fastcmp(field,"tripwireairleniency")) diff --git a/src/p_mobj.c b/src/p_mobj.c index 493bf2a89..f872cf9fc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7997,7 +7997,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } } break; - case MT_TRIPWIREAPPROACH: { + case MT_TRIPWIREAPPROACH: { // Subsonic Visuals if (!mobj->target || !mobj->target->health || !mobj->target->player) { P_RemoveMobj(mobj); @@ -8007,17 +8007,53 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj_t *target = mobj->target; player_t *player = target->player; fixed_t myspeed = (player->speed); - + boolean In_A_Race = ((gametyperules & GTR_CIRCUIT) && !K_Cooperative() && M_NotFreePlay() && !modeattacking); // If you're in a real race. + boolean prorated_sonicboom_alert = (K_PlayerTripwireSpeedThreshold(player) > 2 * K_GetKartSpeed(player, false, false)) ; // If you're being prorated. fixed_t maxspeed = K_PlayerTripwireSpeedThreshold(player); // Centered at this speed. - fixed_t minspeed = max(2 * maxspeed / 4, 16 * K_GetKartSpeed(player, false, false) / 10); // Starts appearing at this speed. + fixed_t minspeed = max(2 * maxspeed / 4, 7 * K_GetKartSpeed(player, false, false) / 5); // Starts appearing at this speed. fixed_t alertspeed = 9 * maxspeed / 10; // When to flash? fixed_t frontoffset = 5*target->scale; // How far in front? - + fixed_t percentvisible = 0; + if (myspeed > minspeed) + { percentvisible = min(FRACUNIT, FixedDiv(myspeed - minspeed, maxspeed - minspeed)); + } + if (myspeed >= maxspeed || player->tripwireLeniency) - percentvisible = 0; + { + player->subsonicleniency++; // Subsonic visual stays for a bit during tripwire leniency + + if(player->subsonicleniency == 1 && player->tripwireLeniency && myspeed >= maxspeed && !S_SoundPlaying(player->mo, sfx_gsha7)) // Don't play during superring too + { + mobj_t *boost = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height/2, MT_SONICBOOM); + boost->momx = player->mo->momx/2; + boost->momy = player->mo->momy/2; + boost->momz = player->mo->momz/2; + boost->angle = player->mo->angle + ANGLE_90; + boost->scalespeed = boost->scale; + boost->destscale = boost->scale*8; + //sonicboom->color = SKINCOLOR_WHITE; + boost->fuse = 8; + } + } + else + { + player->subsonicleniency = 0; // Goes back down otherwise + } + + if (player->subsonicleniency >= (3*TICRATE)) + { + percentvisible = 0; // Once it stays long enough, no longer visible + } + +#if 0 + if (!K_PlayerUsesBotMovement(player)) + { + CONS_Printf("SSL=%d, PV=%d\n", player->subsonicleniency, percentvisible); + } +#endif #if 0 fixed_t hang = 85*FRACUNIT/100; // Dampen inward movement past a certain point @@ -8045,8 +8081,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_InstaScale(mobj, FixedMul(target->scale, easedscale)); K_MatchGenericExtraFlagsNoInterp(mobj, target); - UINT8 maxtranslevel = NUMTRANSMAPS - 2; + UINT8 maxtranslevel = NUMTRANSMAPS; UINT8 trans = FixedInt(FixedMul(percentvisible, FRACUNIT*(maxtranslevel+1))); + //UINT8 trans = FixedInt(FixedMul(percentvisible - player->subsonicleniency * FRACUNIT/100, FRACUNIT*(maxtranslevel+1))); + if (trans > maxtranslevel) trans = maxtranslevel; trans = NUMTRANSMAPS - trans; @@ -8060,13 +8098,52 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->renderflags |= RF_PAPERSPRITE; mobj->colorized = true; - if (myspeed > alertspeed) - mobj->color = (leveltime & 1) ? SKINCOLOR_LILAC : SKINCOLOR_JAWZ; - else - mobj->color = SKINCOLOR_WHITE; + +/* + if (!K_PlayerUsesBotMovement(player)) + { + CONS_Printf("In_A_Race=%d, Prorated_SonicBoom_Alert=%d\n", In_A_Race, prorated_sonicboom_alert); + } +*/ + if (In_A_Race == true && prorated_sonicboom_alert == true) + { + mobj->color = (leveltime & 1) ? SKINCOLOR_KETCHUP : SKINCOLOR_RED; // If you're being prorated we flash red + trans = trans*2; + } + else if (myspeed > alertspeed) + mobj->color = (leveltime & 1) ? SKINCOLOR_LILAC : SKINCOLOR_JAWZ; // If the Subsonic lines meet we flash tripwire colors + else + mobj->color = SKINCOLOR_WHITE; // Default mobj->renderflags |= (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(player)); + // Alright, let's just handle all the sfx down here + + if (P_IsDisplayPlayer(player)) + { + UINT8 MIN_VOLUME = 25; + UINT8 MAX_VOLUME = 75; + UINT8 volume = FixedRescale(myspeed, minspeed, maxspeed, Easing_Linear, MIN_VOLUME, MAX_VOLUME); + + if (myspeed >= minspeed && myspeed < maxspeed) + { + S_StopSoundByID(mobj, sfx_sonbo1); + if(!S_SoundPlaying(mobj, sfx_sonbo3)) + S_StartSoundAtVolume(mobj, sfx_sonbo3, volume); // Subsonic SFX + } + else if (myspeed >= maxspeed || player->tripwireLeniency) + { + S_StopSoundByID(mobj, sfx_sonbo3); + if(!S_SoundPlaying(mobj, sfx_sonbo1)) + S_StartSoundAtVolume(mobj, sfx_sonbo1, MAX_VOLUME); // SonicBoom lingering SFX + } + else + { + S_StopSoundByID(mobj, sfx_sonbo1); + S_StopSoundByID(mobj, sfx_sonbo3); + } + } + break; } case MT_TRIPWIREBOOST: { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 8072a905f..aadf50aa8 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -533,6 +533,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].tripwireLeniency); WRITEUINT8(save->p, players[i].tripwireAirLeniency); WRITEUINT8(save->p, players[i].fakeBoost); + WRITEUINT16(save->p, players[i].subsonicleniency); WRITESINT8(save->p, players[i].itemtype); WRITEUINT8(save->p, players[i].itemamount); @@ -1212,6 +1213,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].tripwireLeniency = READUINT16(save->p); players[i].tripwireAirLeniency = READUINT8(save->p); players[i].fakeBoost = READUINT8(save->p); + players[i].subsonicleniency = READUINT16(save->p); players[i].itemtype = READSINT8(save->p); players[i].itemamount = READUINT8(save->p); diff --git a/src/sounds.c b/src/sounds.c index 483d7d11e..8b9642606 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1164,12 +1164,18 @@ sfxinfo_t S_sfx[NUMSFX] = {"gate04", false, 32, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"gate05", false, 32, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // Wavedash {"waved1", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"waved2", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"waved3", false, 32, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"waved4", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"waved5", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // Sonic Boom & Subsonic + {"sonbo1", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"sonbo2", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"sonbo3", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + // Passing sounds {"pass01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"pass02", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index cc9de28f0..8d43fb997 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1239,6 +1239,11 @@ typedef enum sfx_waved3, sfx_waved4, sfx_waved5, + + // Sonic Boom & Subsonic + sfx_sonbo1, + sfx_sonbo2, + sfx_sonbo3, // Passing sounds sfx_pass01,