From aab661cad86045b998792fe89166b023c5325d08 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 3 Jan 2023 04:11:42 -0800 Subject: [PATCH 1/2] Split shields and SPB special conditions from K_KartGetItemOdds --- src/k_roulette.c | 149 ++++++++++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 53 deletions(-) diff --git a/src/k_roulette.c b/src/k_roulette.c index da12d5209..7ffb57461 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -417,6 +417,99 @@ static UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers return pdis; } +/*-------------------------------------------------- + static boolean K_DenyShieldOdds(kartitems_t item) + + Checks if this type of shield already exists in + another player's inventory. + + Input Arguments:- + item - The item type of the shield. + + Return:- + Whether this item is a shield and may not be awarded + at this time. +--------------------------------------------------*/ +static boolean K_DenyShieldOdds(kartitems_t item) +{ + INT32 shieldType = K_GetShieldFromItem(item); + + switch (shieldType) + { + case KSHIELD_NONE: + /* Marble Garden Top is not REALLY + a Sonic 3 shield */ + case KSHIELD_TOP: + { + break; + } + + default: + { + size_t i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] == false || players[i].spectator == true) + { + continue; + } + + if (shieldType == K_GetShieldFromItem(players[i].itemtype)) + { + // Don't allow more than one of each shield type at a time + return true; + } + } + } + } + + return false; +} + +/*-------------------------------------------------- + static fixed_t K_AdjustSPBOdds(const itemroulette_t *roulette, UINT8 position) + + Adjust odds of SPB according to distances of first and + second place players. + + Input Arguments:- + roulette - The roulette data that we intend to + insert this item into. + position - Position of player to consider for these + odds. + + Return:- + New item odds. +--------------------------------------------------*/ +static fixed_t K_AdjustSPBOdds(const itemroulette_t *roulette, UINT8 position) +{ + if (roulette->firstDist < ENDDIST*2 // No SPB when 1st is almost done + || position == 1) // No SPB for 1st ever + { + return 0; + } + else + { + const UINT32 dist = max(0, ((signed)roulette->secondToFirst) - SPBSTARTDIST); + const UINT32 distRange = SPBFORCEDIST - SPBSTARTDIST; + const fixed_t maxOdds = 20 << FRACBITS; + fixed_t multiplier = FixedDiv(dist, distRange); + + if (multiplier < 0) + { + multiplier = 0; + } + + if (multiplier > FRACUNIT) + { + multiplier = FRACUNIT; + } + + return FixedMul(maxOdds, multiplier); + } +} + /*-------------------------------------------------- INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, UINT8 pos, kartitems_t item) @@ -428,14 +521,11 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, boolean rival = false; UINT8 position = 0; - INT32 shieldType = KSHIELD_NONE; - boolean powerItem = false; boolean cooldownOnStart = false; boolean notNearEnd = false; fixed_t newOdds = 0; - size_t i; I_Assert(roulette != NULL); @@ -478,33 +568,9 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, */ (void)bot; - shieldType = K_GetShieldFromItem(item); - switch (shieldType) + if (K_DenyShieldOdds(item)) { - case KSHIELD_NONE: - /* Marble Garden Top is not REALLY - a Sonic 3 shield */ - case KSHIELD_TOP: - { - break; - } - - default: - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] == false || players[i].spectator == true) - { - continue; - } - - if (shieldType == K_GetShieldFromItem(players[i].itemtype)) - { - // Don't allow more than one of each shield type at a time - return 0; - } - } - } + return 0; } if (gametype == GT_BATTLE) @@ -581,30 +647,7 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, if (specialstageinfo.valid == false) { - if (roulette->firstDist < ENDDIST*2 // No SPB when 1st is almost done - || position == 1) // No SPB for 1st ever - { - return 0; - } - else - { - const UINT32 dist = max(0, ((signed)roulette->secondToFirst) - SPBSTARTDIST); - const UINT32 distRange = SPBFORCEDIST - SPBSTARTDIST; - const fixed_t maxOdds = 20 << FRACBITS; - fixed_t multiplier = FixedDiv(dist, distRange); - - if (multiplier < 0) - { - multiplier = 0; - } - - if (multiplier > FRACUNIT) - { - multiplier = FRACUNIT; - } - - newOdds = FixedMul(maxOdds, multiplier); - } + newOdds = K_AdjustSPBOdds(roulette, position); } break; } From a37eccd7080fa1b715bdeb0917ee53a15167584b Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 3 Jan 2023 04:32:21 -0800 Subject: [PATCH 2/2] Split powerItem etc conditions from K_KartGetItemOdds --- src/k_roulette.c | 124 +++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 47 deletions(-) diff --git a/src/k_roulette.c b/src/k_roulette.c index 7ffb57461..d2a0066cb 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -510,6 +510,62 @@ static fixed_t K_AdjustSPBOdds(const itemroulette_t *roulette, UINT8 position) } } +typedef struct { + boolean powerItem; + boolean cooldownOnStart; + boolean notNearEnd; + + // gameplay state + boolean rival; // player is a bot Rival +} itemconditions_t; + +/*-------------------------------------------------- + static fixed_t K_AdjustItemOddsToConditions(fixed_t newOdds, const itemconditions_t *conditions, const itemroulette_t *roulette) + + Adjust item odds to certain group conditions. + + Input Arguments:- + newOdds - The item odds to adjust. + conditions - The conditions state. + roulette - The roulette data that we intend to + insert this item into. + + Return:- + New item odds. +--------------------------------------------------*/ +static fixed_t K_AdjustItemOddsToConditions(fixed_t newOdds, const itemconditions_t *conditions, const itemroulette_t *roulette) +{ + if ((conditions->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; + } + else if ((conditions->notNearEnd == true) && (roulette->baseDist < ENDDIST)) + { + // This item should not appear at the end of a race. (Usually trap items that lose their effectiveness) + newOdds = 0; + } + else if (conditions->powerItem == true) + { + // This item is a "power item". This activates "frantic item" toggle related functionality. + if (franticitems == true) + { + // First, power items multiply their odds by 2 if frantic items are on; easy-peasy. + newOdds *= 2; + } + + if (conditions->rival == true) + { + // The Rival bot gets frantic-like items, also :p + newOdds *= 2; + } + + newOdds = FixedMul(newOdds, FRACUNIT + K_ItemOddsScale(roulette->playing)); + } + + return newOdds; +} + /*-------------------------------------------------- INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, UINT8 pos, kartitems_t item) @@ -518,12 +574,14 @@ static fixed_t K_AdjustSPBOdds(const itemroulette_t *roulette, UINT8 position) INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, UINT8 pos, kartitems_t item) { boolean bot = false; - boolean rival = false; UINT8 position = 0; - boolean powerItem = false; - boolean cooldownOnStart = false; - boolean notNearEnd = false; + itemconditions_t conditions = { + .powerItem = false, + .cooldownOnStart = false, + .notNearEnd = false, + .rival = false, + }; fixed_t newOdds = 0; @@ -535,7 +593,7 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, if (player != NULL) { bot = player->bot; - rival = (bot == true && player->botvars.rival == true); + conditions.rival = (bot == true && player->botvars.rival == true); position = player->position; } @@ -597,7 +655,7 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, case KITEM_EGGMAN: case KITEM_SUPERRING: { - notNearEnd = true; + conditions.notNearEnd = true; break; } @@ -611,15 +669,15 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, case KRITEM_QUADORBINAUT: case KRITEM_DUALJAWZ: { - powerItem = true; + conditions.powerItem = true; break; } case KITEM_HYUDORO: case KRITEM_TRIPLEBANANA: { - powerItem = true; - notNearEnd = true; + conditions.powerItem = true; + conditions.notNearEnd = true; break; } @@ -629,15 +687,15 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, case KITEM_BUBBLESHIELD: case KITEM_FLAMESHIELD: { - cooldownOnStart = true; - powerItem = true; + conditions.cooldownOnStart = true; + conditions.powerItem = true; break; } case KITEM_SPB: { - cooldownOnStart = true; - notNearEnd = true; + conditions.cooldownOnStart = true; + conditions.notNearEnd = true; if ((gametyperules & GTR_CIRCUIT) == 0) { @@ -654,9 +712,9 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, case KITEM_SHRINK: { - cooldownOnStart = true; - powerItem = true; - notNearEnd = true; + conditions.cooldownOnStart = true; + conditions.powerItem = true; + conditions.notNearEnd = true; if (roulette->playing - 1 <= roulette->exiting) { @@ -667,8 +725,8 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, case KITEM_LIGHTNINGSHIELD: { - cooldownOnStart = true; - powerItem = true; + conditions.cooldownOnStart = true; + conditions.powerItem = true; if (spbplace != -1) { @@ -689,35 +747,7 @@ INT32 K_KartGetItemOdds(const player_t *player, itemroulette_t *const roulette, return newOdds; } - 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; - } - else if ((notNearEnd == true) && (roulette->baseDist < ENDDIST)) - { - // This item should not appear at the end of a race. (Usually trap items that lose their effectiveness) - newOdds = 0; - } - else if (powerItem == true) - { - // This item is a "power item". This activates "frantic item" toggle related functionality. - if (franticitems == true) - { - // First, power items multiply their odds by 2 if frantic items are on; easy-peasy. - newOdds *= 2; - } - - if (rival == true) - { - // The Rival bot gets frantic-like items, also :p - newOdds *= 2; - } - - newOdds = FixedMul(newOdds, FRACUNIT + K_ItemOddsScale(roulette->playing)); - } - - newOdds = FixedInt(FixedRound(newOdds)); + newOdds = FixedInt(FixedRound(K_AdjustItemOddsToConditions(newOdds, &conditions, roulette))); return newOdds; }