Item refactor, part 2

Clean up alt item stuff, replace the billion parameters with kartroulette_t
This commit is contained in:
GenericHeroGuy 2025-11-07 17:58:19 +01:00
parent 540978570a
commit a2396fbdac
11 changed files with 429 additions and 429 deletions

View file

@ -140,7 +140,7 @@ typedef enum
typedef enum {
KROULETTE_DISABLED,
KROULETTE_ACTIVE,
} kartroulette_t;
} kartroulettestate_t;
typedef enum {
KROULETTETYPE_NORMAL,

View file

@ -1519,7 +1519,7 @@ struct int_const_s const INT_CONST[] = {
{"KSHIELD_FLAME",KSHIELD_FLAME},
{"NUMKARTSHIELDS",NUMKARTSHIELDS},
// kartroulette_t
// kartroulettestate_t
{"KROULETTE_DISABLED",KROULETTE_DISABLED},
{"KROULETTE_ACTIVE",KROULETTE_ACTIVE},

View file

@ -1155,7 +1155,7 @@ static void K_BotItemRouletteMash(botdata_t *bd, const player_t *player)
}
}
if (player->rings < 0 && K_ItemResultEnabled("superring") && K_RingsActive())
if (player->rings < 0 && K_ItemResultEnabled(K_GetKartResult("superring")))
{
// Uh oh, we need a loan!
// It'll be better in the long run for bots to lose an item set for 5-15 free rings.

View file

@ -657,7 +657,7 @@ patch_t *K_GetCachedItemPatch(SINT8 type, boolean tiny, UINT8 amount)
kartitem_t *item = &kartitems[type];
kartitemgraphics_t *graphics = &item->graphics[tiny ? 1 : 0];
if ((item->hudflags & KPF_ANIMATED))
if (item->flags & KIF_ANIMATED)
return graphics->patches[(leveltime % (graphics->numpatches*3)) / 3];
else
return graphics->patches[CLAMP(amount - 1, 0, graphics->numpatches - 1)];
@ -1299,8 +1299,8 @@ static void K_drawKartItem(void)
if (stplyr->itemtype > 0 && stplyr->itemtype < numkartitems)
{
kartitem_t *item = &kartitems[stplyr->itemtype];
numberdisplaymin = (item->hudflags & KPF_ANIMATED) ? 2 : item->graphics[tiny ? 1 : 0].numpatches + 1;
dark = (item->hudflags & KPF_DARKBG);
numberdisplaymin = item->flags & KIF_ANIMATED ? 2 : item->graphics[tiny ? 1 : 0].numpatches + 1;
dark = item->flags & KIF_DARKBG;
}
if ((stplyr->itemflags & IF_ITEMOUT) && !(leveltime & 1))
@ -1337,7 +1337,7 @@ static void K_drawKartItem(void)
{
colmap = R_GetTranslationColormap(colormode, localcolor, GTC_CACHE);
}
else if ((kartitems[stplyr->itemtype]).hudflags & KPF_COLPATCH2PLAYER)
else if (kartitems[stplyr->itemtype].flags & KIF_COLPATCH2PLAYER)
{
colmap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, GTC_CACHE);
}
@ -5591,7 +5591,7 @@ static void K_drawDistributionDebugger(void)
if (pingame == 1)
{
if (stplyr->itemroulette && stplyr->cmd.buttons & BT_ATTACK && K_ItemResultEnabled("superring") && K_RingsActive())
if (stplyr->itemroulette && stplyr->cmd.buttons & BT_ATTACK && K_ItemResultEnabled(K_GetKartResult("superring")))
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetCachedItemPatch(KITEM_SUPERRING, true, 0));
else
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetCachedItemPatch(KITEM_SNEAKER, true, 0));
@ -5599,30 +5599,35 @@ static void K_drawDistributionDebugger(void)
}
else
{
INT32 itemodds[MAXKARTRESULTS];
kartroulette_t roulette = {
.pdis = pdis,
.playerpos = stplyr->position,
.pos = useodds,
.ourDist = stplyr->distancetofinish,
.clusterDist = stplyr->distancefromcluster,
.mashed = 0,
.spbrush = spbrush,
.bot = stplyr->bot,
.rival = stplyr->bot && stplyr->botvars.rival,
.inBottom = K_IsPlayerLosing(stplyr),
};
K_KartGetItemOdds(&roulette, itemodds);
for (i = 0; i < numkartresults; i++)
{
kartresult_t *result = &kartresults[i];
INT32 itemodds = K_KartGetItemOdds(
pdis, stplyr->position, useodds, result,
stplyr->distancetofinish,
stplyr->distancefromcluster,
0,
spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival),
K_IsPlayerLosing(stplyr)
);
if ((itemodds <= 0) && (!result->forceme)) // At the very least display forced items; that info's also important.
if (itemodds[i] <= 0 && !result->forceme) // At the very least display forced items; that info's also important.
continue;
V_DrawScaledPatch(x, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, K_GetCachedItemPatch(result->type, true, 0));
V_DrawThinString(x+11, y+31, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, result->forceme ? va("\x85" "FRC(%d)" "\x80 ", result->forceme) : va("%d", itemodds));
// Display amount for multi-items
if (result->isalt)
V_DrawScaledPatch(x+2, y, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, W_CachePatchName("K_ALTITS", PU_CACHE));
V_DrawThinString(x+11, y+31, V_SPLITSCREEN|V_HUDTRANS|V_SNAPTOTOP, result->forceme ? va("\x85" "FRC(%d)" "\x80 ", result->forceme) : va("%d", itemodds[i]));
if (result->amount > 1)
{
V_DrawString(x+24, y+31, V_SPLITSCREEN|V_ALLOWLOWERCASE|V_HUDTRANS|V_SNAPTOTOP, va("x%d", result->amount));
}
x += 32;
if (x >= 297)

File diff suppressed because it is too large Load diff

View file

@ -60,13 +60,6 @@ typedef enum
MAXKARTITEMS
} ATTRPACK kartitemtype_e;
typedef enum
{
KIFRMT_STANDARD = 0,
KIFRMT_ALTERN,
NUMKARTITEMFORMATS
} ATTRPACK kartitemformat_e;
#define MAXKARTRESULTS 255
typedef enum
@ -77,6 +70,27 @@ typedef enum
MAXODDSTABLES
} ATTRPACK kartoddstable_e;
// item flags for HUD and usage
typedef enum
{
KIF_ANIMATED = 1<<0, // animate patches instead of using diffrent patches for different amounts (inversion of xItemLib's XIF_ICONFORAMT)
KIF_DARKBG = 1<<1, // use dark item roulette BG
KIF_COLPATCH2PLAYER = 1<<2, // colourize patch to player
} ATTRPACK kartitemflags_e;
// flags relevant to item rolls and usage
typedef enum
{
KRF_INDIRECTITEM = 1<<0, // This item affects others indirectly. A 20 second cooldown is applied to all other items with this flag when an indirect item is rolled.
KRF_POWERITEM = 1<<1, // This item is a "power item". This activates "frantic item" toggle related functionality.
KRF_COOLDOWNONSTART = 1<<2, // This item should not appear at the beginning of a race. (Usually really powerful crowd-breaking items)
KRF_NOTNEAREND = 1<<3, // This item should not appear at the end of a race. (Usually trap items that lose their effectiveness)
KRF_NOTFORBOTTOM = 1<<4, // After the first 30 seconds, this item stops appearing for losing players. (Usually items that feel less effective at these positions)
KRF_UNIQUE = 1<<5, // Only one player can use this item at a time
KRF_RUNNERAUGMENT = 1<<6, // This item's odds are affected by the severity of 1st place's frontrun. (Very likely only for SPBs, but who knows?)
// free: 1<<7
} ATTRPACK kartresultflags_e;
struct kartitemgraphics_t
{
UINT8 numpatches;
@ -87,73 +101,70 @@ struct kartitemgraphics_t
struct kartitem_t
{
const char *name;
consvar_t *altcvar;
kartitemgraphics_t graphics[2];
UINT8 hudflags;
kartitemflags_e flags;
consvar_t *altcvar; // if not NULL, an altitem exists
boolean altenabled;
// note: could be how we do this?
// int (*oddsOverrideFunc)(player_t *p, int pos, int mashed, boolean spbrush, fixed_t seconddist, int pingame, int pexiting);
// int (*resultOverrideFunc)(player_t *p);
};
// item flags relevant to item rolls and usage
enum
{
KRF_INDIRECTITEM = 1<<0, // This item affects others indirectly. A 20 second cooldown is applied to all other items with this flag when an indirect item is rolled.
KRF_POWERITEM = 1<<1, // This item is a "power item". This activates "frantic item" toggle related functionality.
KRF_COOLDOWNONSTART = 1<<2, // This item should not appear at the beginning of a race. (Usually really powerful crowd-breaking items)
KRF_NOTNEAREND = 1<<3, // This item should not appear at the end of a race. (Usually trap items that lose their effectiveness)
KRF_NOTFORBOTTOM = 1<<4, // After the first 30 seconds, this item stops appearing for losing players. (Usually items that feel less effective at these positions)
KRF_UNIQUE = 1<<5,
KRF_RUNNERAUGMENT = 1<<6, // This item's odds are affected by the severity of 1st place's frontrun. (Very likely only for SPBs, but who knows?)
// free: 1<<7
};
// item flags relevant to patch rendering in the HUD
enum
{
KPF_ANIMATED = 1<<0, // animate patches instead of using diffrent patches for different amounts (inversion of xItemLib's XIF_ICONFORAMT)
KPF_DARKBG = 1<<1, // use dark item roulette BG
KPF_COLPATCH2PLAYER = 1<<2, // colourize patch to player
};
// Unique useodds function:
// uoddsfunc(result, playerpos, pdis, newodds, pos, pingame, pexiting, firstDist, ourDist, clusterDist, mashed, spbrush, bot, rival, inBottom)
// FIXME: This is fucking gross; is there not a better way to do this?
typedef INT32(*useoddsfunc_t)(kartresult_t *, SINT8, UINT32, INT32, UINT8, UINT8, UINT8, UINT32, UINT32, UINT32, fixed_t, boolean, boolean, boolean, boolean);
typedef INT32 (useoddsfunc_f)(INT32 odds, const kartroulette_t *roulette, kartresult_t *result);
struct kartresult_t
{
const char *name;
consvar_t *cvar;
// this block is shared by all item variants
consvar_t *cvar; // contains name
kartitemtype_e type;
UINT8 amount;
kartitemformat_e format; // An item's format. Different formats have different odds
boolean isalt; // is alt (i salt)
kartresultflags_e flags;
UINT8 forceme; // This item is being forced into a player's item slot for one reason or another. Higher value = higher priority.
// 3D array determining item odds, selected by table, then format.
UINT8 odds[MAXODDSTABLES][NUMKARTITEMFORMATS][MAXODDS];
UINT8 odds[MAXODDSTABLES][MAXODDS];
// Functions that tell the game to use unique means of rolling these items.
// If NULL, the functions never execute.
useoddsfunc_t unique_odds[MAXODDSTABLES][NUMKARTITEMFORMATS];
useoddsfunc_f *unique_odds[MAXODDSTABLES];
UINT8 flags[NUMKARTITEMFORMATS];
tic_t basebgone, bgone;
};
// contains all data for a call to K_KartGetItemOdds
struct kartroulette_t
{
UINT32 pdis; // the player's PDIS value
SINT8 playerpos; // the player's position
UINT8 pos; // position in the odds table (why is this just "pos"???)
UINT32 ourDist; // the player's finish line distance
UINT32 clusterDist; // distance to cluster
fixed_t mashed;
boolean spbrush;
boolean bot;
boolean rival;
boolean inBottom;
// extras for useodds functions
UINT8 pingame;
UINT8 pexiting;
UINT32 firstDist;
};
extern kartitem_t kartitems[MAXKARTITEMS];
extern UINT8 numkartitems;
extern kartresult_t kartresults[MAXKARTRESULTS];
extern UINT8 numkartresults;
boolean K_IsKartResultAlternate(const char *name);
kartresult_t *K_GetKartResult(const char *name);
void K_InitializeItems(void);
boolean K_ItemResultEnabled(const char *name);
boolean K_ItemResultEnabled(const kartresult_t *result);
boolean K_IsKartItemAlternate(kartitemtype_e itemtype);
void K_SetupItemOdds(void);
void K_KartHandleShieldCooldown(kartitemtype_e item);
@ -164,7 +175,6 @@ 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);
UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush);
INT32 K_KartGetItemOdds(UINT32 pdis, SINT8 playerpos, UINT8 pos, kartresult_t *result, UINT32 ourDist, UINT32 clusterDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival, boolean inBottom);
INT32 K_GetRollingRouletteItem(player_t *player);
void K_KartItemRoulette(player_t *player, ticcmd_t *cmd);
@ -184,4 +194,8 @@ void K_AltShrinkPityIncrease(player_t *player);
} // extern "C"
#endif
#ifndef __cplusplus
void K_KartGetItemOdds(kartroulette_t *roulette, INT32 outodds[static MAXKARTRESULTS]);
#endif
#endif // __K_ITEMS__

View file

@ -4706,7 +4706,7 @@ static void K_DoHyudoroSteal(player_t *player)
prandom = P_RandomFixed();
S_StartSound(player->mo, sfx_s3k92);
if (sink && numplayers > 0 && K_ItemResultEnabled("kitchensink")) // BEHOLD THE KITCHEN SINK
if (sink && numplayers > 0 && K_ItemResultEnabled(K_GetKartResult("kitchensink"))) // BEHOLD THE KITCHEN SINK
{
player->hyudorotimer = hyu;
player->stealingtimer = stealtime;
@ -5510,16 +5510,25 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
useodds = amount;
kartroulette_t roulette = {
.pdis = 0,
.playerpos = 0,
.pos = useodds,
.ourDist = UINT32_MAX,
.clusterDist = 0,
.mashed = 0,
.spbrush = false,
.bot = false,
.rival = false,
.inBottom = false
};
K_KartGetItemOdds(&roulette, spawnchance);
for (i = 0; i < numkartresults; i++)
{
spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(
0, 0, useodds, &kartresults[i],
UINT32_MAX,
0,
0,
false, false, false, false
)
);
totalspawnchance += spawnchance[i];
spawnchance[i] = totalspawnchance;
}
if (totalspawnchance > 0)
@ -11470,12 +11479,6 @@ boolean K_ItemPushingActive(void)
return itempushing;
}
boolean K_IsKartItemAlternate(UINT8 itemtype)
{
return itemtype >= 0 && itemtype < numkartitems
&& kartitems[itemtype].altcvar != NULL && kartitems[itemtype].altcvar->value == 1;
}
boolean K_UsingLegacyCheckpoints(void)
{
if (K_UsingPatchedMap() && waypointcap != NULL)

View file

@ -349,7 +349,6 @@ boolean K_DraftingActive(void);
boolean K_AirDropActive(void);
boolean K_ItemLitterActive(void);
boolean K_ItemPushingActive(void);
boolean K_IsKartItemAlternate(UINT8 itemtype);
INT32 K_GetBumpSpark(void);
boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound);
INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement, boolean chainsound);

View file

@ -8385,9 +8385,9 @@ void MD_DrawMonitorToggles(void)
kartresult_t *result = &kartresults[arg - 1];
kartitem_t *item = &kartitems[result->type];
boolean enabled = K_ItemResultEnabled(result->name);
boolean enabled = K_ItemResultEnabled(result);
translucent = enabled ? 0 : V_TRANSLUCENT;
drawnum = (item->hudflags & KPF_ANIMATED) ? 0 : CLAMP(result->amount, 0, item->graphics[1].numpatches - 1);
drawnum = item->flags & KIF_ANIMATED ? 0 : CLAMP(result->amount, 0, item->graphics[1].numpatches - 1);
if (enabled)
V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE));
@ -8432,9 +8432,9 @@ void MD_DrawMonitorToggles(void)
{
kartresult_t *result = &kartresults[arg - 1];
kartitem_t *item = &kartitems[result->type];
boolean enabled = K_ItemResultEnabled(result->name);
boolean enabled = K_ItemResultEnabled(result);
translucent = enabled ? 0 : V_TRANSLUCENT;
drawnum = (item->hudflags & KPF_ANIMATED) ? 0 : CLAMP(result->amount, 0, item->graphics[0].numpatches - 1);
drawnum = item->flags & KIF_ANIMATED ? 0 : CLAMP(result->amount, 0, item->graphics[0].numpatches - 1);
if (enabled)
V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE));
@ -8534,7 +8534,7 @@ INT32 MR_HandleMonitorToggles(INT32 choice)
}
else if (choice == 0)
{
INT32 v = K_ItemResultEnabled("sneaker") ? 1 : 0;
INT32 v = K_ItemResultEnabled(K_GetKartResult("sneaker")) ? 1 : 0;
S_StartSound(NULL, sfx_s1b4);
for (UINT8 i = 0; i < numkartresults; i++)
{

View file

@ -8077,29 +8077,6 @@ static void P_InitLevelSettings(boolean reloadinggamestate)
if (!reloadinggamestate)
K_SetupItemOdds();
for (i = 0; i < numkartitems; i++)
{
const kartitem_t *kitm = &kartitems[i];
char *findname = malloc(strlen(kitm->name)+1);
sprintf(findname, "%s", kitm->name);
strlwr(findname);
kartresult_t *kres = K_GetKartResult(findname);
if ((kres) && (kitm->altcvar))
{
// Update the result's format based on the cvar's value.
if (kres->format != kitm->altcvar->value)
{
CONS_Printf("%s: updating format to %s\n", kres->name, kitm->altcvar->string);
kres->format = kitm->altcvar->value;
}
}
free(findname); // Don't need this anymore
}
// emerald hunt
hunt1 = hunt2 = hunt3 = NULL;

View file

@ -212,6 +212,7 @@ TYPEDEF (mapUserProperties_t);
TYPEDEF (kartitem_t);
TYPEDEF (kartresult_t);
TYPEDEF (kartitemgraphics_t);
TYPEDEF (kartroulette_t);
// lua_hudlib_drawlist.h
typedef struct huddrawlist_s *huddrawlist_h;