From f89d8d15c2ac8b3ee32610700a10ed0cf0d5662c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 23 Sep 2022 03:35:18 -0400 Subject: [PATCH] Properly separate SPB & Shrink cooldowns Also refactors some of the result -> type & amount code --- src/doomstat.h | 2 +- src/g_game.c | 2 +- src/k_hud.c | 23 +---- src/k_kart.c | 226 ++++++++++++++++++++++++------------------- src/k_kart.h | 5 + src/k_menudraw.c | 44 +-------- src/lua_script.c | 5 - src/objects/shrink.c | 2 + src/objects/spb.c | 2 +- src/p_mobj.c | 2 +- src/p_saveg.c | 6 +- src/p_setup.c | 7 +- src/p_tick.c | 3 +- src/p_user.c | 2 +- 14 files changed, 155 insertions(+), 176 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 95baf7ce4..30578d3e6 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -707,7 +707,7 @@ extern boolean comeback; extern SINT8 battlewanted[4]; extern tic_t wantedcalcdelay; -extern tic_t indirectitemcooldown; +extern tic_t itemCooldowns[NUMKARTITEMS - 1]; extern tic_t mapreset; extern boolean thwompsactive; extern UINT8 lastLowestLap; diff --git a/src/g_game.c b/src/g_game.c index 4d98256f1..790d04941 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -317,7 +317,7 @@ SINT8 pickedvote; // What vote the host rolls // Server-sided, synched variables SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points 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 itemCooldowns[NUMKARTITEMS - 1]; // Cooldowns to prevent item spawning 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_hud.c b/src/k_hud.c index 609ddaaf8..161795fef 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -4607,6 +4607,7 @@ static void K_drawDistributionDebugger(void) 0, stplyr->bot, (stplyr->bot && stplyr->botvars.rival) ); + INT32 amount = 1; if (itemodds <= 0) continue; @@ -4615,27 +4616,9 @@ static void K_drawDistributionDebugger(void) V_DrawThinString(x+11, y+31, V_SNAPTOTOP, va("%d", itemodds)); // Display amount for multi-items - if (i >= NUMKARTITEMS) + amount = K_ItemResultToAmount(i); + if (amount > 1) { - INT32 amount; - switch (i) - { - case KRITEM_TENFOLDBANANA: - amount = 10; - break; - case KRITEM_QUADORBINAUT: - amount = 4; - break; - case KRITEM_DUALJAWZ: - amount = 2; - break; - case KRITEM_DUALSNEAKER: - amount = 2; - break; - default: - amount = 3; - break; - } V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("x%d", amount)); } diff --git a/src/k_kart.c b/src/k_kart.c index ee7b0b62b..91015d886 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -47,7 +47,6 @@ // encoremode is Encore Mode (duh), bool // comeback is Battle Mode's karma comeback, also bool // battlewanted is an array of the WANTED player nums, -1 for no player in that slot -// indirectitemcooldown is timer before anyone's allowed another Shrink/SPB // mapreset is set when enough players fill an empty server void K_TimerReset(void) @@ -448,6 +447,111 @@ INT32 K_GetShieldFromItem(INT32 item) } } +SINT8 K_ItemResultToType(SINT8 getitem) +{ + if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback) + { + if (getitem != 0) + { + CONS_Printf("ERROR: K_GetItemResultToItemType - Item roulette gave bad item (%d) :(\n", getitem); + } + + return KITEM_SAD; + } + + if (getitem >= NUMKARTITEMS) + { + switch (getitem) + { + case KRITEM_DUALSNEAKER: + case KRITEM_TRIPLESNEAKER: + return KITEM_SNEAKER; + + case KRITEM_TRIPLEBANANA: + case KRITEM_TENFOLDBANANA: + return KITEM_BANANA; + + case KRITEM_TRIPLEORBINAUT: + case KRITEM_QUADORBINAUT: + return KITEM_ORBINAUT; + + case KRITEM_DUALJAWZ: + return KITEM_JAWZ; + + default: + I_Error("Bad item cooldown redirect for result %d\n", getitem); + break; + } + } + + return getitem; +} + +UINT8 K_ItemResultToAmount(SINT8 getitem) +{ + switch (getitem) + { + case KRITEM_DUALSNEAKER: + case KRITEM_DUALJAWZ: + return 2; + + case KRITEM_TRIPLESNEAKER: + case KRITEM_TRIPLEBANANA: + case KRITEM_TRIPLEORBINAUT: + return 3; + + case KRITEM_QUADORBINAUT: + return 4; + + case KITEM_BALLHOG: // Not a special result, but has a special amount + return 5; + + case KRITEM_TENFOLDBANANA: + return 10; + + default: + return 1; + } +} + +tic_t K_GetItemCooldown(SINT8 itemResult) +{ + SINT8 itemType = K_ItemResultToType(itemResult); + + if (itemType < 1 || itemType >= NUMKARTITEMS) + { + return 0; + } + + return itemCooldowns[itemType - 1]; +} + +void K_SetItemCooldown(SINT8 itemResult, tic_t time) +{ + SINT8 itemType = K_ItemResultToType(itemResult); + + if (itemType < 1 || itemType >= NUMKARTITEMS) + { + return; + } + + itemCooldowns[itemType - 1] = max(itemCooldowns[itemType - 1], time); +} + +void K_RunItemCooldowns(void) +{ + size_t i; + + for (i = 0; i < NUMKARTITEMS-1; i++) + { + if (itemCooldowns[i] > 0) + { + itemCooldowns[i]--; + } + } +} + + /** \brief Item Roulette for Kart \param player player @@ -457,61 +561,16 @@ INT32 K_GetShieldFromItem(INT32 item) */ static void K_KartGetItemResult(player_t *player, SINT8 getitem) { - if (getitem == KITEM_SPB) // Indirect items + if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) { - indirectitemcooldown = 20*TICRATE; + K_SetItemCooldown(getitem, 20*TICRATE); } player->botvars.itemdelay = TICRATE; player->botvars.itemconfirm = 0; - switch (getitem) - { - // Special roulettes first, then the generic ones are handled by default - case KRITEM_DUALSNEAKER: // Sneaker x2 - player->itemtype = KITEM_SNEAKER; - player->itemamount = 2; - break; - case KRITEM_TRIPLESNEAKER: // Sneaker x3 - player->itemtype = KITEM_SNEAKER; - player->itemamount = 3; - break; - case KRITEM_TRIPLEBANANA: // Banana x3 - player->itemtype = KITEM_BANANA; - player->itemamount = 3; - break; - case KRITEM_TENFOLDBANANA: // Banana x10 - player->itemtype = KITEM_BANANA; - player->itemamount = 10; - break; - case KRITEM_TRIPLEORBINAUT: // Orbinaut x3 - player->itemtype = KITEM_ORBINAUT; - player->itemamount = 3; - break; - case KRITEM_QUADORBINAUT: // Orbinaut x4 - player->itemtype = KITEM_ORBINAUT; - player->itemamount = 4; - break; - case KRITEM_DUALJAWZ: // Jawz x2 - player->itemtype = KITEM_JAWZ; - player->itemamount = 2; - break; - case KITEM_BALLHOG: // Ballhog x5 - player->itemtype = KITEM_BALLHOG; - player->itemamount = 5; - break; - default: - if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback) - { - if (getitem != 0) - CONS_Printf("ERROR: P_KartGetItemResult - Item roulette gave bad item (%d) :(\n", getitem); - player->itemtype = KITEM_SAD; - } - else - player->itemtype = getitem; - player->itemamount = 1; - break; - } + player->itemtype = K_ItemResultToType(getitem); + player->itemamount = K_ItemResultToAmount(getitem); } fixed_t K_ItemOddsScale(UINT8 playerCount) @@ -591,7 +650,6 @@ INT32 K_KartGetItemOdds( boolean powerItem = false; boolean cooldownOnStart = false; - boolean indirectItem = false; boolean notNearEnd = false; INT32 shieldtype = KSHIELD_NONE; @@ -600,7 +658,15 @@ INT32 K_KartGetItemOdds( I_Assert(KartItemCVars[NUMKARTRESULTS-2] != NULL); // Make sure this exists if (!KartItemCVars[item-1]->value && !modeattacking) + { return 0; + } + + if (K_GetItemCooldown(item) > 0) + { + // Cooldown is still running, don't give another. + return 0; + } /* if (bot) @@ -719,7 +785,6 @@ INT32 K_KartGetItemOdds( case KITEM_SPB: cooldownOnStart = true; - indirectItem = true; notNearEnd = true; if (firstDist < ENDDIST*2 // No SPB when 1st is almost done @@ -775,12 +840,8 @@ INT32 K_KartGetItemOdds( return newodds; } - if ((indirectItem == true) && (indirectitemcooldown > 0)) - { - // Too many items that act indirectly in a match can feel kind of bad. - newodds = 0; - } - else if ((cooldownOnStart == true) && (leveltime < (30*TICRATE)+starttime)) + + if ((cooldownOnStart == true) && (leveltime < (30*TICRATE)+starttime)) { // This item should not appear at the beginning of a race. (Usually really powerful crowd-breaking items) newodds = 0; @@ -946,7 +1007,7 @@ boolean K_ForcedSPB(player_t *player) return false; } - if (indirectitemcooldown > 0) + if (itemCooldowns[KITEM_SPB - 1] > 0) { return false; } @@ -6436,46 +6497,8 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 // K_KartGetItemResult requires a player // but item roulette will need rewritten to change this - switch (i) - { - // Special roulettes first, then the generic ones are handled by default - case KRITEM_DUALSNEAKER: // Sneaker x2 - newType = KITEM_SNEAKER; - newAmount = 2; - break; - case KRITEM_TRIPLESNEAKER: // Sneaker x3 - newType = KITEM_SNEAKER; - newAmount = 3; - break; - case KRITEM_TRIPLEBANANA: // Banana x3 - newType = KITEM_BANANA; - newAmount = 3; - break; - case KRITEM_TENFOLDBANANA: // Banana x10 - newType = KITEM_BANANA; - newAmount = 10; - break; - case KRITEM_TRIPLEORBINAUT: // Orbinaut x3 - newType = KITEM_ORBINAUT; - newAmount = 3; - break; - case KRITEM_QUADORBINAUT: // Orbinaut x4 - newType = KITEM_ORBINAUT; - newAmount = 4; - break; - case KRITEM_DUALJAWZ: // Jawz x2 - newType = KITEM_JAWZ; - newAmount = 2; - break; - case KITEM_BALLHOG: // Ballhog x5 - newType = KITEM_BALLHOG; - newAmount = 5; - break; - default: - newType = i; - newAmount = 1; - break; - } + newType = K_ItemResultToType(i); + newAmount = K_ItemResultToAmount(i); if (newAmount > 1) { @@ -10701,9 +10724,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (spbplace == -1 || player->position != spbplace) player->pflags &= ~PF_RINGLOCK; // reset ring lock - if (player->itemtype == KITEM_SPB) + if (player->itemtype == KITEM_SPB + || player->itemtype == KITEM_SHRINK) { - indirectitemcooldown = 20*TICRATE; + K_SetItemCooldown(player->itemtype, 20*TICRATE); } if (player->hyudorotimer > 0) diff --git a/src/k_kart.h b/src/k_kart.h index 6655ec034..eda49b4c3 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -50,6 +50,11 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers); INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, fixed_t mashed, boolean bot, boolean rival); boolean K_ForcedSPB(player_t *player); INT32 K_GetShieldFromItem(INT32 item); +SINT8 K_ItemResultToType(SINT8 getitem); +UINT8 K_ItemResultToAmount(SINT8 getitem); +tic_t K_GetItemCooldown(SINT8 itemResult); +void K_SetItemCooldown(SINT8 itemResult, tic_t time); +void K_RunItemCooldowns(void); fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against); boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2); boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 76a001544..2785f83ac 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3366,34 +3366,14 @@ void M_DrawItemToggles(void) cv = KartItemCVars[currentMenu->menuitems[thisitem].mvar1-1]; translucent = (cv->value ? 0 : V_TRANSLUCENT); - switch (currentMenu->menuitems[thisitem].mvar1) - { - case KRITEM_DUALSNEAKER: - case KRITEM_DUALJAWZ: - drawnum = 2; - break; - case KRITEM_TRIPLESNEAKER: - case KRITEM_TRIPLEBANANA: - case KRITEM_TRIPLEORBINAUT: - drawnum = 3; - break; - case KRITEM_QUADORBINAUT: - drawnum = 4; - break; - case KRITEM_TENFOLDBANANA: - drawnum = 10; - break; - default: - drawnum = 0; - break; - } + drawnum = K_ItemResultToAmount(currentMenu->menuitems[thisitem].mvar1); if (cv->value) V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE)); else V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBGD", PU_CACHE)); - if (drawnum != 0) + if (drawnum > 1) { V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISMUL", PU_CACHE)); V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].mvar1, true), PU_CACHE)); @@ -3433,30 +3413,14 @@ void M_DrawItemToggles(void) cv = KartItemCVars[currentMenu->menuitems[itemOn].mvar1-1]; translucent = (cv->value ? 0 : V_TRANSLUCENT); - switch (currentMenu->menuitems[itemOn].mvar1) - { - case KRITEM_DUALSNEAKER: - case KRITEM_DUALJAWZ: - drawnum = 2; - break; - case KRITEM_TRIPLESNEAKER: - case KRITEM_TRIPLEBANANA: - drawnum = 3; - break; - case KRITEM_TENFOLDBANANA: - drawnum = 10; - break; - default: - drawnum = 0; - break; - } + drawnum = K_ItemResultToAmount(currentMenu->menuitems[itemOn].mvar1); if (cv->value) V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE)); else V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBGD", PU_CACHE)); - if (drawnum != 0) + if (drawnum > 1) { V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE)); V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].mvar1, false), PU_CACHE)); diff --git a/src/lua_script.c b/src/lua_script.c index 8a1e307bb..051739976 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -375,9 +375,6 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"wantedcalcdelay")) { lua_pushinteger(L, wantedcalcdelay); return 1; - } else if (fastcmp(word,"indirectitemcooldown")) { - lua_pushinteger(L, indirectitemcooldown); - return 1; } else if (fastcmp(word,"thwompsactive")) { lua_pushboolean(L, thwompsactive); return 1; @@ -463,8 +460,6 @@ int LUA_WriteGlobals(lua_State *L, const char *word) racecountdown = (tic_t)luaL_checkinteger(L, 2); else if (fastcmp(word,"exitcountdown")) exitcountdown = (tic_t)luaL_checkinteger(L, 2); - else if (fastcmp(word,"indirectitemcooldown")) - indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2); else return 0; diff --git a/src/objects/shrink.c b/src/objects/shrink.c index 241164aa7..9a520171b 100644 --- a/src/objects/shrink.c +++ b/src/objects/shrink.c @@ -439,6 +439,8 @@ void Obj_PohbeeThinker(mobj_t *pohbee) { mobj_t *gun = NULL; + K_SetItemCooldown(KITEM_SHRINK, 20*TICRATE); + pohbee->momx = pohbee->momy = pohbee->momz = 0; pohbee->spritexscale = pohbee->spriteyscale = 2*FRACUNIT; diff --git a/src/objects/spb.c b/src/objects/spb.c index d22dbe49c..ca3c5813a 100644 --- a/src/objects/spb.c +++ b/src/objects/spb.c @@ -766,7 +766,7 @@ void Obj_SPBThink(mobj_t *spb) return; } - indirectitemcooldown = 20*TICRATE; + K_SetItemCooldown(KITEM_SPB, 20*TICRATE); ghost = P_SpawnGhostMobj(spb); ghost->fuse = 3; diff --git a/src/p_mobj.c b/src/p_mobj.c index ab37b2e7c..01c6b649a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6743,7 +6743,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; case KITEM_SPB: case KITEM_SHRINK: - indirectitemcooldown = 20*TICRATE; + K_SetItemCooldown(mobj->threshold, 20*TICRATE); /* FALLTHRU */ default: mobj->sprite = SPR_ITEM; diff --git a/src/p_saveg.c b/src/p_saveg.c index fe11f0ee9..e04b4a3f4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4560,7 +4560,8 @@ static void P_NetArchiveMisc(boolean resending) WRITEFIXED(save_p, battleovertime.z); WRITEUINT32(save_p, wantedcalcdelay); - WRITEUINT32(save_p, indirectitemcooldown); + for (i = 0; i < NUMKARTITEMS-1; i++) + WRITEUINT32(save_p, itemCooldowns[i]); WRITEUINT32(save_p, mapreset); WRITEUINT8(save_p, spectateGriefed); @@ -4723,7 +4724,8 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) battleovertime.z = READFIXED(save_p); wantedcalcdelay = READUINT32(save_p); - indirectitemcooldown = READUINT32(save_p); + for (i = 0; i < NUMKARTITEMS-1; i++) + itemCooldowns[i] = READUINT32(save_p); mapreset = READUINT32(save_p); spectateGriefed = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index 6815d1496..a75d830ec 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4022,6 +4022,8 @@ static void P_InitPlayers(void) static void P_InitGametype(void) { + size_t i; + spectateGriefed = 0; K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped @@ -4046,7 +4048,10 @@ static void P_InitGametype(void) } wantedcalcdelay = wantedfrequency*2; - indirectitemcooldown = 0; + + for (i = 0; i < NUMKARTITEMS-1; i++) + itemCooldowns[i] = 0; + mapreset = 0; thwompsactive = false; diff --git a/src/p_tick.c b/src/p_tick.c index 58b11406f..9da702289 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -683,8 +683,7 @@ void P_Ticker(boolean run) if (exitcountdown > 1) exitcountdown--; - if (indirectitemcooldown > 0) - indirectitemcooldown--; + K_RunItemCooldowns(); K_BossInfoTicker(); diff --git a/src/p_user.c b/src/p_user.c index f733bad28..c3b602195 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2592,7 +2592,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) if (mo->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown. { spbplace = -1; - indirectitemcooldown = 0; + itemCooldowns[KITEM_SPB - 1] = 0; } if (mo->flags & MF_BOSS) //don't OHKO bosses nor players!