Refactor some item related things.

This commit is contained in:
NepDisk 2025-05-03 12:16:05 -04:00
parent c20a785119
commit ee92faabba
3 changed files with 257 additions and 161 deletions

View file

@ -4297,44 +4297,48 @@ K_drawMiniPing (void)
}
}
static patch_t *K_GetSmallStaticCachedItemPatch(kartitems_t item)
{
UINT8 offset;
item = K_ItemResultToType(item);
switch (item)
{
case KITEM_INVINCIBILITY:
offset = 7;
break;
case KITEM_BANANA:
offset = 4;
break;
case KITEM_ORBINAUT:
offset = 4;
break;
case KITEM_JAWZ:
offset = 2;
break;
case KITEM_SNEAKER:
offset = 3;
break;
default:
offset = 1;
}
return K_GetCachedItemPatch(item, offset);
}
static void K_drawDistributionDebugger(void)
{
patch_t *items[NUMKARTRESULTS] = {
kp_sadface[1],
kp_sneaker[3],
kp_rocketsneaker[1],
kp_invincibility[7],
kp_banana[4],
kp_eggman[1],
kp_orbinaut[4],
kp_jawz[2],
kp_mine[1],
kp_ballhog[1],
kp_selfpropelledbomb[1],
kp_grow[1],
kp_shrink[1],
kp_thundershield[1],
kp_hyudoro[1],
kp_pogospring[1],
kp_kitchensink[1],
kp_superring[1],
kp_landmine[1],
kp_bubbleshield[1],
kp_flameshield[1],
kp_droptarget[1],
kp_sneaker[3],
kp_sneaker[3],
kp_banana[4],
kp_banana[4],
kp_orbinaut[4],
kp_orbinaut[4],
kp_jawz[2]
};
UINT8 useodds = 0;
UINT8 pingame = 0, bestbumper = 0;
UINT32 pdis = 0;
INT32 i;
INT32 item;
INT32 x = -9, y = -9;
boolean dontforcespb = false;
boolean spbrush = false;
@ -4354,7 +4358,7 @@ static void K_drawDistributionDebugger(void)
bestbumper = players[i].bumper;
}
if (!(K_UsingLegacyCheckpoints()))
if (!K_UsingLegacyCheckpoints())
{
// lovely double loop......
for (i = 0; i < MAXPLAYERS; i++)
@ -4368,6 +4372,123 @@ static void K_drawDistributionDebugger(void)
}
}
}
else
{
// Pain and fucking suffering.
SINT8 sortedPlayers[MAXPLAYERS];
UINT8 sortLength = 0;
memset(sortedPlayers, -1, sizeof(sortedPlayers));
if (stplyr->mo != NULL && P_MobjWasRemoved(stplyr->mo) == false)
{
// Sort all of the players ahead of you.
// Then tally up their distances in a conga line.
// This will create a much more consistent item
// distance algorithm than the "spider web" thing
// that it was doing before.
// Add yourself to the list.
// You'll always be the end of the list,
// so we can also calculate the length here.
sortedPlayers[ stplyr->position - 1 ] = stplyr - players;
sortLength = stplyr->position;
// Will only need to do this if there's goint to be
// more than yourself in the list.
if (sortLength > 1)
{
SINT8 firstIndex = -1;
SINT8 secondIndex = -1;
INT32 startFrom = INT32_MAX;
// Add all of the other players.
for (i = 0; i < MAXPLAYERS; i++)
{
INT32 pos = INT32_MAX;
if (!playeringame[i] || players[i].spectator)
{
continue;
}
if (players[i].mo == NULL || P_MobjWasRemoved(players[i].mo) == true)
{
continue;
}
pos = players[i].position;
if (pos <= 0 || pos > MAXPLAYERS)
{
// Invalid position.
continue;
}
if (pos >= stplyr->position)
{
// Tied / behind us.
// Also handles ourselves, obviously.
continue;
}
// Ties are done with port priority, if there are any.
if (sortedPlayers[ pos - 1 ] == -1)
{
sortedPlayers[ pos - 1 ] = i;
}
}
// The chance of this list having gaps is improbable,
// but not impossible. So we need to spend some extra time
// to prevent the gaps from mattering.
for (i = 0; i < sortLength-1; i++)
{
if (sortedPlayers[i] >= 0 && sortedPlayers[i] < MAXPLAYERS)
{
// First valid index in the list found.
firstIndex = sortedPlayers[i];
// Start the next loop after this player.
startFrom = i + 1;
break;
}
}
if (firstIndex >= 0 && firstIndex < MAXPLAYERS
&& startFrom < sortLength)
{
// First index is valid, so we can
// start comparing the players.
player_t *firstPlayer = NULL;
player_t *secondPlayer = NULL;
for (i = startFrom; i < sortLength; i++)
{
if (sortedPlayers[i] >= 0 && sortedPlayers[i] < MAXPLAYERS)
{
secondIndex = sortedPlayers[i];
firstPlayer = &players[firstIndex];
secondPlayer = &players[secondIndex];
// Add the distance to the player behind you.
pdis += P_AproxDistance(P_AproxDistance(
firstPlayer->mo->x - secondPlayer->mo->x,
firstPlayer->mo->y - secondPlayer->mo->y),
firstPlayer->mo->z - secondPlayer->mo->z) / FRACUNIT;
// Advance to next index.
firstIndex = secondIndex;
}
}
}
}
}
}
if (spbplace != -1 && stplyr->position == spbplace+1)
{
@ -4377,17 +4498,12 @@ static void K_drawDistributionDebugger(void)
spbrush = true;
}
pdis = K_ScaleItemDistance(pdis, pingame, spbrush);
if (!(K_UsingLegacyCheckpoints()))
if (stplyr->bot && stplyr->botvars.rival)
{
pdis = K_ScaleItemDistance(pdis, pingame, spbrush);
if (stplyr->bot && stplyr->botvars.rival)
{
// Rival has better odds :)
pdis = (15 * pdis) / 14;
}
// Rival has better odds :)
pdis = (15 * pdis) / 14;
}
if (K_UsingLegacyCheckpoints())
@ -4398,31 +4514,30 @@ static void K_drawDistributionDebugger(void)
if (pingame == 1)
{
if (stplyr->itemroulette && (stplyr->cmd.buttons & BT_ATTACK) && cv_superring.value && (K_RingsActive() == true))
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, kp_superring[1]);
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetSmallStaticCachedItemPatch(KITEM_SUPERRING));
else
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, items[1]);
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetSmallStaticCachedItemPatch(KITEM_SNEAKER));
V_DrawThinString(x+11, y+31, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, va("%d", 200));
}
else if (useodds == 69)
{
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, items[11]);
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetSmallStaticCachedItemPatch(KITEM_SPB));
V_DrawThinString(x+11, y+31, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, va("%d", 200));
}
else
{
for (i = 1; i < NUMKARTRESULTS; i++)
for (item = 1; item < NUMKARTRESULTS; item++)
{
INT32 itemodds;
INT32 amount;
if (K_UsingLegacyCheckpoints())
itemodds = K_KartGetLegacyItemOdds(useodds, i, 0, spbrush);
itemodds = K_KartGetLegacyItemOdds(useodds, item, 0, spbrush);
else
itemodds = K_KartGetItemOdds(
useodds, i,
useodds, item,
stplyr->distancetofinish,
0,
spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival)
@ -4431,34 +4546,17 @@ static void K_drawDistributionDebugger(void)
if (itemodds <= 0)
continue;
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, items[i]);
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetSmallStaticCachedItemPatch(item));
V_DrawThinString(x+11, y+31, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, va("%d", itemodds));
// Display amount for multi-items
if (i >= NUMKARTITEMS)
amount = K_ItemResultToAmount(item);
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_SPLITSCREEN|V_ALLOWLOWERCASE|V_HUDTRANS|V_SNAPTOTOP, va("x%d", amount));
}
x += 32;
if (x >= 297)
{
@ -4475,6 +4573,8 @@ static void K_drawDistributionDebugger(void)
else
V_DrawString(0, 0, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, va("USEODDS %d", useodds));
V_DrawString(150, 0, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, va("PDIS %d", pdis));
if (K_UsingLegacyCheckpoints())
V_DrawSmallString(70, 0, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, "Legacy Distance Mode");

View file

@ -523,6 +523,70 @@ 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 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 KRITEM_TENFOLDBANANA:
return 10;
default:
return 1;
}
}
/** \brief Item Roulette for Kart
\param player player
@ -541,49 +605,11 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
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;
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);
UINT8 itemamount = K_ItemResultToAmount(getitem);
if (cv_kartdebugitem.value != KITEM_NONE && cv_kartdebugitem.value == player->itemtype && cv_kartdebugamount.value > 1)
itemamount = cv_kartdebugamount.value;
player->itemamount = itemamount;
}
fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush)
@ -1356,6 +1382,12 @@ INT32 K_FindLegacyUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32
pdis = K_ScaleItemDistance(pdis, pingame, spbrush);
if (player->bot && player->botvars.rival)
{
// Rival has better odds :)
pdis = (15 * pdis) / 14;
}
if (pingame == 1 && oddsvalid[0])
{
// Record Attack / FREE PLAY
@ -1531,13 +1563,13 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
}
}
if (spbplace != -1 && player->position == spbplace+1)
{
// SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell
if (!(K_UsingLegacyCheckpoints()))
pdis = (3 * pdis) / 2;
spbrush = true;
}
if (spbplace != -1 && player->position == spbplace+1)
{
// SPB Rush Mode: It's 2nd place's job to catch-up items and make 1st place's job hell
if (!(K_UsingLegacyCheckpoints()))
pdis = (3 * pdis) / 2;
spbrush = true;
}
if (!(K_UsingLegacyCheckpoints()))
{
@ -1568,7 +1600,6 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
if (cv_kartdebugitem.value != 0 && !modeattacking)
{
K_KartGetItemResult(player, cv_kartdebugitem.value);
player->itemamount = cv_kartdebugamount.value;
player->itemblink = TICRATE;
player->itemblinkmode = 2;
player->itemroulette = 0;
@ -6050,9 +6081,6 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
if (totalspawnchance > 0)
{
UINT8 newType;
UINT8 newAmount;
totalspawnchance = P_RandomKey(totalspawnchance);
for (i = 0; i < NUMKARTRESULTS && spawnchance[i] <= totalspawnchance; i++);
@ -6060,42 +6088,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;
default:
newType = i;
newAmount = 1;
break;
}
const UINT8 newType = K_ItemResultToType(i);
const UINT8 newAmount = K_ItemResultToAmount(i);
if (newAmount > 1)
{

View file

@ -128,6 +128,8 @@ INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spb
INT32 K_GetRollingRouletteItem(player_t *player);
INT32 K_GetShieldFromPlayer(player_t *player);
INT32 K_GetShieldFromItem(INT32 item);
SINT8 K_ItemResultToType(SINT8 getitem);
UINT8 K_ItemResultToAmount(SINT8 getitem);
fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against);
boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
void K_KartPainEnergyFling(player_t *player);