mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-25 19:43:22 +00:00
Merge branch 'refactor-get-item-odds' into 'master'
Refactor K_KartGetItemOdds See merge request KartKrew/Kart!851
This commit is contained in:
commit
6e6a799b1e
1 changed files with 173 additions and 100 deletions
273
src/k_roulette.c
273
src/k_roulette.c
|
|
@ -417,6 +417,155 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -425,17 +574,16 @@ static UINT32 K_GetItemRouletteDistance(const player_t *player, UINT8 numPlayers
|
|||
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;
|
||||
|
||||
INT32 shieldType = KSHIELD_NONE;
|
||||
|
||||
boolean powerItem = false;
|
||||
boolean cooldownOnStart = false;
|
||||
boolean notNearEnd = false;
|
||||
itemconditions_t conditions = {
|
||||
.powerItem = false,
|
||||
.cooldownOnStart = false,
|
||||
.notNearEnd = false,
|
||||
.rival = false,
|
||||
};
|
||||
|
||||
fixed_t newOdds = 0;
|
||||
size_t i;
|
||||
|
||||
I_Assert(roulette != NULL);
|
||||
|
||||
|
|
@ -445,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;
|
||||
}
|
||||
|
||||
|
|
@ -478,33 +626,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)
|
||||
|
|
@ -531,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;
|
||||
}
|
||||
|
||||
|
|
@ -545,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;
|
||||
}
|
||||
|
||||
|
|
@ -563,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)
|
||||
{
|
||||
|
|
@ -581,39 +705,16 @@ 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;
|
||||
}
|
||||
|
||||
case KITEM_SHRINK:
|
||||
{
|
||||
cooldownOnStart = true;
|
||||
powerItem = true;
|
||||
notNearEnd = true;
|
||||
conditions.cooldownOnStart = true;
|
||||
conditions.powerItem = true;
|
||||
conditions.notNearEnd = true;
|
||||
|
||||
if (roulette->playing - 1 <= roulette->exiting)
|
||||
{
|
||||
|
|
@ -624,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)
|
||||
{
|
||||
|
|
@ -646,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue