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();