From a697f924c81281c27884a4eb39b25a5f11344464 Mon Sep 17 00:00:00 2001 From: Anonimus Date: Wed, 15 Oct 2025 07:30:50 -0400 Subject: [PATCH 1/5] Introduce the goner table I'm Wing Gaster, the royal scientist! --- src/doomstat.h | 2 +- src/g_game.c | 3 +- src/k_odds.c | 90 +++++++++++++++++++++++++++++++++++++++++++---- src/k_odds.h | 15 ++++++++ src/lua_baselib.c | 44 ++++++++++++++++++++++- src/lua_script.c | 7 ++-- src/p_saveg.c | 10 +++++- src/p_setup.c | 9 ++++- src/p_tick.c | 11 ++++-- 9 files changed, 176 insertions(+), 15 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 484e773a7..e869975c6 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -677,7 +677,7 @@ extern SINT8 mostwanted; extern SINT8 battlewanted[4]; extern tic_t wantedcalcdelay; extern tic_t indirectitemcooldown; -extern tic_t hyubgone; +//extern tic_t hyubgone; extern tic_t mapreset; extern boolean thwompsactive; extern UINT8 lastLowestLap; diff --git a/src/g_game.c b/src/g_game.c index 51849d6af..c9224d710 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -60,6 +60,7 @@ #include "k_grandprix.h" #include "k_boss.h" #include "k_bot.h" +#include "k_odds.h" #include "doomstat.h" #include "acs/interface.h" #include "k_director.h" @@ -299,7 +300,7 @@ SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points SINT8 mostwanted; // The "most wanted" (first in line) player. tic_t wantedcalcdelay; // Time before it recalculates WANTED tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded -tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled +// hyubgone was taken out back. See k_odds.c tic_t mapreset; // Map reset delay when enough players have joined an empty game boolean thwompsactive; // Thwomps activate on lap 2 UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors diff --git a/src/k_odds.c b/src/k_odds.c index c557cbc9b..877c510d8 100644 --- a/src/k_odds.c +++ b/src/k_odds.c @@ -152,6 +152,80 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] = { 5, 1 } // Jawz x2 }; +// Cooldown time table; contains both base (index 0) and current (index 1) +// times. Base times are in seconds, current times are in tics. +tic_t ItemBGone[NUMKARTRESULTS][2] = +{ + //BASE CURR + { 0, 0 }, // Null/Sad Face + { 0, 0 }, // Sneaker + { 0, 0 }, // Rocket Sneaker + { 0, 0 }, // Invincibility + { 0, 0 }, // Banana + { 10, 0 }, // Eggman Monitor + { 0, 0 }, // Orbinaut + { 5, 0 }, // Jawz + { 0, 0 }, // Mine + { 10, 0 }, // Ballhog + { 20, 0 }, // Self-Propelled Bomb + { 10, 0 }, // Grow + { 20, 0 }, // Shrink + { 0, 0 }, // Thunder Shield + { 0, 0 }, // Hyudoro + { 0, 0 }, // Pogo Spring + { 0, 0 }, // Kitchen Sink + { 0, 0 }, // Super Ring + { 0, 0 }, // Land Mine + { 5, 0 }, // Bubble Shield + { 10, 0 }, // Flame Shield + { 0, 0 }, // Sneaker x2 + { 0, 0 }, // Sneaker x3 + { 0, 0 }, // Banana x3 + { 30, 0 }, // Banana x10 + { 10, 0 }, // Orbinaut x3 + { 20, 0 }, // Orbinaut x4 + { 10, 0 } // Jawz x2 +}; + +// TODO: Vectorize all item tables and shove them into gamemode-uniqe pools (k_oddstable.cpp?). +// Basically necessary for any hopes of easy SOC support in the near future. + +/** \brief Sets the cooldown timer for an item. When active, the item is removed + * from all players' item pools for some time. + + \param item (SINT8) item to assign cooldown for + \param time (tic_t) cooldown time + + \return void +*/ +void K_SetBGone(SINT8 item, tic_t time) +{ + ItemBGone[item][GONER_CURRCOOLDOWN] = time; +} + +/** \brief Sets the cooldown timer for an item to its "base" (intended) time. + + \param item (SINT8) item to assign base cooldown for + + \return void +*/ +void K_SetBGoneToBase(SINT8 item) +{ + ItemBGone[item][GONER_CURRCOOLDOWN] = (ItemBGone[item][GONER_BASECOOLDOWN] * TICRATE); +} + +/** \brief Gets the cooldown timer for an item. + + \param item (SINT8) item to retrieve cooldown for + \param base (bool) if true, returns the "base" (intended) cooldown instead + + \return (tic_t) cooldown time +*/ +tic_t K_GetBGone(SINT8 item, boolean base) +{ + return ItemBGone[item][base ? GONER_BASECOOLDOWN : GONER_CURRCOOLDOWN] * (base ? TICRATE : 1); +} + // Magic number distance for use with item roulette tiers #define ACTIVEDISTVAR (K_UsingLegacyCheckpoints() ? DISTVAR_LEGACY : DISTVAR) @@ -288,8 +362,10 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items indirectitemcooldown = 20*TICRATE; - if (getitem == KITEM_HYUDORO) // Hyudoro cooldown - hyubgone = 20*TICRATE; + if (K_GetBGone(getitem, true) > 0) // Item cooldowns + { + K_SetBGoneToBase(getitem); + } K_BotResetItemConfirm(player, true); @@ -674,9 +750,6 @@ INT32 K_KartGetItemOdds( break; case KITEM_HYUDORO: cooldownOnStart = true; - - if (hyubgone > 0) - newodds = 0; break; default: break; @@ -688,7 +761,12 @@ INT32 K_KartGetItemOdds( return newodds; } - if ((indirectItem == true) && (indirectitemcooldown > 0)) + if (K_GetBGone(item, false) > 0) + { + // (Replaces hyubgone) This item is on cooldown; don't let it get rolled. + newodds = 0; + } + else if ((indirectItem == true) && (indirectitemcooldown > 0)) { // Too many items that act indirectly in a match can feel kind of bad. newodds = 0; diff --git a/src/k_odds.h b/src/k_odds.h index cf57d2c50..42860b19e 100644 --- a/src/k_odds.h +++ b/src/k_odds.h @@ -36,6 +36,21 @@ extern "C" { extern consvar_t *KartItemCVars[NUMKARTRESULTS-1]; +// Goner; tracks how long an item should be "gone" for. +// AKA a time-based cooldown so Hyudoro and whatever else piss off to prevent +// spamming. + +typedef enum goner_sect_e { + GONER_BASECOOLDOWN = 0, + GONER_CURRCOOLDOWN = 1, +} goner_sect_t; + +extern tic_t ItemBGone[NUMKARTRESULTS][2]; + +void K_SetBGone(SINT8 item, tic_t time); +void K_SetBGoneToBase(SINT8 item); +tic_t K_GetBGone(SINT8 item, boolean base); + UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame); UINT32 K_CalculatePDIS(const player_t *player, UINT8 numPlayers, boolean *spbrush); UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9a3735d35..9762c280e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -33,6 +33,7 @@ #include "k_color.h" #include "k_hud.h" #include "k_waypoint.h" +#include "k_odds.h" #include "d_netcmd.h" // IsPlayerAdmin #include "m_menu.h" // Player Setup menu color stuff #include "p_spec.h" // P_StartQuake @@ -4110,10 +4111,48 @@ static int lib_kSetHyuCountdown(lua_State *L) { tic_t c = (tic_t)luaL_checkinteger(L, 1); NOHUD - hyubgone = c; + K_SetBGone(KITEM_HYUDORO, c); return 0; } +static int lib_kSetBGone(lua_State *L) +{ + SINT8 item = (SINT8)luaL_checkinteger(L, 1); + tic_t c = (tic_t)luaL_checkinteger(L, 2); + NOHUD + if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1)) + { + luaL_error(L, "given item ID is outside bgone range"); + } + K_SetBGone(item, c); + return 0; +} + +static int lib_kSetBGoneToBase(lua_State *L) +{ + SINT8 item = (SINT8)luaL_checkinteger(L, 1); + NOHUD + if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1)) + { + luaL_error(L, "given item ID is outside bgone range"); + } + K_SetBGoneToBase(item); + return 0; +} + +static int lib_kGetBGone(lua_State *L) +{ + SINT8 item = (SINT8)luaL_checkinteger(L, 1); + boolean base = lua_isnoneornil(L, 2) ? false : luaL_checkboolean(L, 2); + NOHUD + if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1)) + { + luaL_error(L, "given item ID is outside bgone range"); + } + lua_pushinteger(L, K_GetBGone(item, base)); + return 1; +} + // Checks if the floor closet floor under an object would be safe to respawn/land on. static int lib_kSafeRespawnPosition(lua_State *L) { @@ -5302,6 +5341,9 @@ static luaL_Reg lib[] = { {"K_SetExitCountdown",lib_kSetExitCountdown}, {"K_SetIndirectItemCooldown",lib_kSetIndirectItemCountdown}, {"K_SetHyudoroCooldown",lib_kSetHyuCountdown}, + {"K_SetBGone", lib_kSetBGone}, + {"K_SetBGoneToBase", lib_kSetBGoneToBase}, + {"K_GetBGone", lib_kGetBGone}, {"K_SafeRespawnPosition",lib_kSafeRespawnPosition}, {"K_GetCollideAngle",lib_kGetCollideAngle}, diff --git a/src/lua_script.c b/src/lua_script.c index 36b911f37..b3ffc781f 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -27,6 +27,7 @@ #include "p_slopes.h" // for P_SlopeById and slopelist #include "p_polyobj.h" // polyobj_t, PolyObjects #include "k_battle.h" +#include "k_odds.h" #ifdef LUA_ALLOW_BYTECODE #include "d_netfil.h" // for LUA_DumpFile #endif @@ -416,7 +417,7 @@ int LUA_PushGlobals(lua_State *L, const char *word) lua_pushinteger(L, invintype); return 1; } else if (fastcmp(word,"hyubgone")) { - lua_pushinteger(L, hyubgone); + lua_pushinteger(L, K_GetBGone(KITEM_HYUDORO, false)); return 1; } else if (fastcmp(word,"encoremode")) { lua_pushboolean(L, encoremode); @@ -559,7 +560,9 @@ int LUA_WriteGlobals(lua_State *L, const char *word) else if (fastcmp(word,"indirectitemcooldown")) indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2); else if (fastcmp(word,"hyubgone")) - hyubgone = (tic_t)luaL_checkinteger(L, 2); + { + K_SetBGone(KITEM_HYUDORO, (tic_t)luaL_checkinteger(L, 2)); + } else if (fastcmp(word,"starttime")) starttime = (tic_t)luaL_checkinteger(L, 2); else if (fastcmp(word,"introtime")) diff --git a/src/p_saveg.c b/src/p_saveg.c index b1d5820e3..8270810cb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -41,6 +41,7 @@ #include "k_battle.h" #include "k_pwrlv.h" #include "k_terrain.h" +#include "k_odds.h" #include "acs/interface.h" #include "g_party.h" @@ -4260,7 +4261,14 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNC(wantedcalcdelay); SYNC(indirectitemcooldown); - SYNC(hyubgone); + + for (i = 0; i < NUMKARTRESULTS; i++) + { + // hyubgone + //SYNC(ItemBGone[i][GONER_BASECOOLDOWN]); + SYNC(ItemBGone[i][GONER_CURRCOOLDOWN]); + } + SYNC(mapreset); SYNC(spectateGriefed); diff --git a/src/p_setup.c b/src/p_setup.c index cdf461ebc..63ba164f8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -103,6 +103,7 @@ #include "k_terrain.h" // TRF_TRIPWIRE #include "k_brightmap.h" #include "k_director.h" // K_InitDirector +#include "k_odds.h" // ItemBGone #include "acs/interface.h" #include "doomstat.h" // MAXMUSNAMES #include "k_mapuser.h" @@ -8467,7 +8468,13 @@ static void P_InitGametype(void) wantedcalcdelay = wantedfrequency*2; indirectitemcooldown = 0; - hyubgone = 0; + + for (i = 0; i < NUMKARTRESULTS; i++) + { + // hyubgone + ItemBGone[i][GONER_CURRCOOLDOWN] = 0; + } + mapreset = 0; thwompsactive = false; diff --git a/src/p_tick.c b/src/p_tick.c index 6d3407e1e..8672a10b8 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -41,6 +41,7 @@ #include "k_director.h" #include "acs/interface.h" #include "k_bot.h" // K_BotTicker +#include "k_odds.h" // ItemBGone #ifdef PARANOIA #include "deh_tables.h" // MOBJTYPE_LIST @@ -925,8 +926,14 @@ void P_Ticker(boolean run) if (indirectitemcooldown > 0) indirectitemcooldown--; - if (hyubgone > 0) - hyubgone--; + for (i = 0; i < NUMKARTRESULTS; i++) + { + // hyubgone + if (K_GetBGone(i, false) > 0) + { + ItemBGone[i][GONER_CURRCOOLDOWN]--; + } + } K_BossInfoTicker(); From 98fd13adf70ee3faafaf6ea44941cd192e0891ec Mon Sep 17 00:00:00 2001 From: Anonimus Date: Wed, 15 Oct 2025 09:21:01 -0400 Subject: [PATCH 2/5] More goner system stuff * Adjust item cooldowns * Re-add Hyuu cooldown (I forgot) * Force-set shield cooldowns for as long as one is being held --- src/k_odds.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/k_odds.h | 1 + src/p_tick.c | 8 ++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/k_odds.c b/src/k_odds.c index 877c510d8..5e6c2ab7b 100644 --- a/src/k_odds.c +++ b/src/k_odds.c @@ -168,16 +168,16 @@ tic_t ItemBGone[NUMKARTRESULTS][2] = { 0, 0 }, // Mine { 10, 0 }, // Ballhog { 20, 0 }, // Self-Propelled Bomb - { 10, 0 }, // Grow + { 3, 0 }, // Grow { 20, 0 }, // Shrink { 0, 0 }, // Thunder Shield - { 0, 0 }, // Hyudoro + { 20, 0 }, // Hyudoro { 0, 0 }, // Pogo Spring { 0, 0 }, // Kitchen Sink { 0, 0 }, // Super Ring { 0, 0 }, // Land Mine { 5, 0 }, // Bubble Shield - { 10, 0 }, // Flame Shield + { 8, 0 }, // Flame Shield { 0, 0 }, // Sneaker x2 { 0, 0 }, // Sneaker x3 { 0, 0 }, // Banana x3 @@ -487,6 +487,69 @@ static INT32 K_KartGetInvincibilityOdds(UINT32 dist) return min(MAXINVODDS, finodds); } +#ifdef PARANOIA +static const char* K_GetShieldName(kartshields_t s) +{ + switch (s) + { + case KSHIELD_THUNDER: + return "KSHIELD_THUNDER"; + break; + case KSHIELD_BUBBLE: + return "KSHIELD_BUBBLE"; + break; + case KSHIELD_FLAME: + return "KSHIELD_FLAME"; + break; + case KSHIELD_NONE: + default: + return "KSHIELD_NONE"; + break; + } +} +#endif + +// Assigns general cooldowns to shield items. +void K_KartHandleShieldCooldown(SINT8 item) +{ + INT32 i; + + UINT8 pingame = 0, pexiting = 0; + + INT32 shieldtype = KSHIELD_NONE; + shieldtype = K_GetShieldFromItem(item); + + if (shieldtype == KSHIELD_NONE) + { + // Not a shield! + return; + } + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!(gametyperules & GTR_BUMPERS) || players[i].bumper) + pingame++; + + if (players[i].exiting) + pexiting++; + + if (((shieldtype == K_GetShieldFromItem(players[i].itemtype)) + || (shieldtype == K_GetShieldFromPlayer(&players[i])))) + { + // If this shield has a cooldown, force-apply the cooldown preeemptively for + // the entire time the shield is being held by a player. + if (K_GetBGone(item, true) > 0) + { + K_SetBGoneToBase(item); + break; + } + } + } +} + /** \brief Item Roulette for Kart \param player player object passed from P_KartPlayerThink diff --git a/src/k_odds.h b/src/k_odds.h index 42860b19e..c5ad73f59 100644 --- a/src/k_odds.h +++ b/src/k_odds.h @@ -50,6 +50,7 @@ extern tic_t ItemBGone[NUMKARTRESULTS][2]; void K_SetBGone(SINT8 item, tic_t time); void K_SetBGoneToBase(SINT8 item); tic_t K_GetBGone(SINT8 item, boolean base); +void K_KartHandleShieldCooldown(SINT8 item); UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame); UINT32 K_CalculatePDIS(const player_t *player, UINT8 numPlayers, boolean *spbrush); diff --git a/src/p_tick.c b/src/p_tick.c index 8672a10b8..e48ac83e2 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -935,6 +935,14 @@ void P_Ticker(boolean run) } } + if (gametyperules & GTR_RACEODDS) + { + // Shield cooldowns + K_KartHandleShieldCooldown(KITEM_THUNDERSHIELD); + K_KartHandleShieldCooldown(KITEM_BUBBLESHIELD); + K_KartHandleShieldCooldown(KITEM_FLAMESHIELD); + } + K_BossInfoTicker(); if (gametyperules & GTR_WANTED) From e3fa439f27e119206dc5704d21efd3aac2a80694 Mon Sep 17 00:00:00 2001 From: Anonimus Date: Wed, 15 Oct 2025 09:21:27 -0400 Subject: [PATCH 3/5] Add Doomguy to indev notice --- src/f_finale.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 69ced6bf7..bea8e14e1 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -439,8 +439,14 @@ void F_IntroTicker(void) } if (finalecount == 80) { - char chars[5][10] = {"tails", "chao", "aiai", "sakura"}; - SINT8 random = M_RandomRange(0, 3); + // I'm assuming these are all representative of a "dev character". + // Tails: NepDisk + // Chao: Alug + // Aiai: GHG + // Sakura: Anon + // Doomguy: Minenice + char chars[6][10] = {"tails", "chao", "aiai", "sakura", "doomguy"}; + SINT8 random = M_RandomRange(0, 4); sfxenum_t rsound = skins[R_SkinAvailable(chars[random])].soundsid[SKSKWIN]; S_StartSound(NULL, sfx_flgcap); S_StartSound(NULL, rsound); From fd5da2dd73faf34ea50daa1fec3c5c1e5a7e9d75 Mon Sep 17 00:00:00 2001 From: Anonimus Date: Wed, 15 Oct 2025 09:23:20 -0400 Subject: [PATCH 4/5] Adjust INVFORCEODDS It's now half of INVFORCEODDS instead of 75% --- src/k_odds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_odds.c b/src/k_odds.c index 5e6c2ab7b..62266395d 100644 --- a/src/k_odds.c +++ b/src/k_odds.c @@ -454,7 +454,7 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush) #define MAXINVODDS ((MAXPROBABILITY * 2) * INVINDESPERATION) // Odds value for Alt. Invin. to force itself on trailing players. -#define INVFORCEODDS (3 * MAXINVODDS / 4) +#define INVFORCEODDS (MAXINVODDS / 2) static INT32 K_KartGetInvincibilityOdds(UINT32 dist) { From 33022483266e16b55900456955f0f2cc84f7052d Mon Sep 17 00:00:00 2001 From: Anonimus Date: Wed, 15 Oct 2025 09:24:42 -0400 Subject: [PATCH 5/5] Get rid of debug shield namer --- src/k_odds.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/k_odds.c b/src/k_odds.c index 62266395d..0c72f18af 100644 --- a/src/k_odds.c +++ b/src/k_odds.c @@ -487,28 +487,6 @@ static INT32 K_KartGetInvincibilityOdds(UINT32 dist) return min(MAXINVODDS, finodds); } -#ifdef PARANOIA -static const char* K_GetShieldName(kartshields_t s) -{ - switch (s) - { - case KSHIELD_THUNDER: - return "KSHIELD_THUNDER"; - break; - case KSHIELD_BUBBLE: - return "KSHIELD_BUBBLE"; - break; - case KSHIELD_FLAME: - return "KSHIELD_FLAME"; - break; - case KSHIELD_NONE: - default: - return "KSHIELD_NONE"; - break; - } -} -#endif - // Assigns general cooldowns to shield items. void K_KartHandleShieldCooldown(SINT8 item) {