Implement roulette visuals

This commit is contained in:
Sally Coolatta 2022-12-12 02:18:18 -05:00
parent 534026764c
commit 202c505664
5 changed files with 97 additions and 43 deletions

View file

@ -225,6 +225,7 @@ typedef enum
// Item box // Item box
khud_itemblink, // Item flashing after roulette, serves as a mashing indicator khud_itemblink, // Item flashing after roulette, serves as a mashing indicator
khud_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) khud_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items)
khud_rouletteoffset,// Roulette stop height
// Rings // Rings
khud_ringframe, // Ring spin frame khud_ringframe, // Ring spin frame

View file

@ -1023,7 +1023,7 @@ static void K_drawKartItem(void)
// Why write V_DrawScaledPatch calls over and over when they're all the same? // Why write V_DrawScaledPatch calls over and over when they're all the same?
// Set to 'no item' just in case. // Set to 'no item' just in case.
const UINT8 offset = ((r_splitscreen > 1) ? 1 : 0); const UINT8 offset = ((r_splitscreen > 1) ? 1 : 0);
patch_t *localpatch = kp_nodraw; patch_t *localpatch[3] = {kp_nodraw};
patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]); patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]);
patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]); patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]);
INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags... INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags...
@ -1036,28 +1036,42 @@ static void K_drawKartItem(void)
UINT8 *colmap = NULL; UINT8 *colmap = NULL;
boolean flipamount = false; // Used for 3P/4P splitscreen to flip item amount stuff boolean flipamount = false; // Used for 3P/4P splitscreen to flip item amount stuff
fixed_t rouletteOffset = 0;
const INT32 rouletteBox = 36;
INT32 i;
if (stplyr->itemRoulette.active == true) if (stplyr->itemRoulette.active == true)
{ {
const SINT8 item = K_ItemResultToType(stplyr->itemRoulette.itemList[ stplyr->itemRoulette.index ]); rouletteOffset = K_GetRouletteOffset(&stplyr->itemRoulette, rendertimefrac);
if (stplyr->skincolor) if (stplyr->skincolor)
{ {
localcolor = stplyr->skincolor; localcolor = stplyr->skincolor;
} }
switch (item) for (i = 0; i < 3; i++)
{ {
case KITEM_INVINCIBILITY: const SINT8 indexOfs = i-1;
localpatch = localinv; const size_t index = (stplyr->itemRoulette.index + indexOfs) % stplyr->itemRoulette.itemListLen;
break;
case KITEM_ORBINAUT: const SINT8 result = stplyr->itemRoulette.itemList[index];
localpatch = kp_orbinaut[3 + offset]; const SINT8 item = K_ItemResultToType(result);
break; const UINT8 amt = K_ItemResultToAmount(result);
default: switch (item)
localpatch = K_GetCachedItemPatch(item, offset); {
break; case KITEM_INVINCIBILITY:
localpatch[i] = localinv;
break;
case KITEM_ORBINAUT:
localpatch[i] = kp_orbinaut[(offset ? 4 : min(amt-1, 3))];
break;
default:
localpatch[i] = K_GetCachedItemPatch(item, offset);
break;
}
} }
} }
else else
@ -1066,23 +1080,26 @@ static void K_drawKartItem(void)
// The only actual reason is to make sneakers line up this way in the code below // The only actual reason is to make sneakers line up this way in the code below
// This shouldn't have any actual baring over how it functions // This shouldn't have any actual baring over how it functions
// Hyudoro is first, because we're drawing it on top of the player's current item // Hyudoro is first, because we're drawing it on top of the player's current item
rouletteOffset = stplyr->karthud[khud_rouletteoffset];
if (stplyr->stealingtimer < 0) if (stplyr->stealingtimer < 0)
{ {
if (leveltime & 2) if (leveltime & 2)
localpatch = kp_hyudoro[offset]; localpatch[0] = kp_hyudoro[offset];
else else
localpatch = kp_nodraw; localpatch[0] = kp_nodraw;
} }
else if ((stplyr->stealingtimer > 0) && (leveltime & 2)) else if ((stplyr->stealingtimer > 0) && (leveltime & 2))
{ {
localpatch = kp_hyudoro[offset]; localpatch[0] = kp_hyudoro[offset];
} }
else if (stplyr->eggmanexplode > 1) else if (stplyr->eggmanexplode > 1)
{ {
if (leveltime & 1) if (leveltime & 1)
localpatch = kp_eggman[offset]; localpatch[0] = kp_eggman[offset];
else else
localpatch = kp_nodraw; localpatch[0] = kp_nodraw;
} }
else if (stplyr->ballhogcharge > 0) else if (stplyr->ballhogcharge > 0)
{ {
@ -1090,9 +1107,9 @@ static void K_drawKartItem(void)
maxl = (((stplyr->itemamount-1) * BALLHOGINCREMENT) + 1); maxl = (((stplyr->itemamount-1) * BALLHOGINCREMENT) + 1);
if (leveltime & 1) if (leveltime & 1)
localpatch = kp_ballhog[offset]; localpatch[0] = kp_ballhog[offset];
else else
localpatch = kp_nodraw; localpatch[0] = kp_nodraw;
} }
else if (stplyr->rocketsneakertimer > 1) else if (stplyr->rocketsneakertimer > 1)
{ {
@ -1100,16 +1117,16 @@ static void K_drawKartItem(void)
maxl = (itemtime*3) - barlength; maxl = (itemtime*3) - barlength;
if (leveltime & 1) if (leveltime & 1)
localpatch = kp_rocketsneaker[offset]; localpatch[0] = kp_rocketsneaker[offset];
else else
localpatch = kp_nodraw; localpatch[0] = kp_nodraw;
} }
else if (stplyr->sadtimer > 0) else if (stplyr->sadtimer > 0)
{ {
if (leveltime & 2) if (leveltime & 2)
localpatch = kp_sadface[offset]; localpatch[0] = kp_sadface[offset];
else else
localpatch = kp_nodraw; localpatch[0] = kp_nodraw;
} }
else else
{ {
@ -1119,12 +1136,12 @@ static void K_drawKartItem(void)
switch (stplyr->itemtype) switch (stplyr->itemtype)
{ {
case KITEM_INVINCIBILITY: case KITEM_INVINCIBILITY:
localpatch = localinv; localpatch[0] = localinv;
localbg = kp_itembg[offset+1]; localbg = kp_itembg[offset+1];
break; break;
case KITEM_ORBINAUT: case KITEM_ORBINAUT:
localpatch = kp_orbinaut[(offset ? 4 : min(stplyr->itemamount-1, 3))]; localpatch[0] = kp_orbinaut[(offset ? 4 : min(stplyr->itemamount-1, 3))];
break; break;
case KITEM_SPB: case KITEM_SPB:
@ -1135,15 +1152,15 @@ static void K_drawKartItem(void)
/*FALLTHRU*/ /*FALLTHRU*/
default: default:
localpatch = K_GetCachedItemPatch(stplyr->itemtype, offset); localpatch[0] = K_GetCachedItemPatch(stplyr->itemtype, offset);
if (localpatch == NULL) if (localpatch[0] == NULL)
localpatch = kp_nodraw; // diagnose underflows localpatch[0] = kp_nodraw; // diagnose underflows
break; break;
} }
if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1)) if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1))
localpatch = kp_nodraw; localpatch[0] = kp_nodraw;
} }
if (stplyr->karthud[khud_itemblink] && (leveltime & 1)) if (stplyr->karthud[khud_itemblink] && (leveltime & 1))
@ -1194,18 +1211,31 @@ static void K_drawKartItem(void)
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg); V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|fflags, localbg);
//V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); if (stplyr->itemRoulette.active == true)
// Then, the numbers:
if (stplyr->itemamount >= numberdisplaymin && stplyr->itemRoulette.active == false)
{ {
V_SetClipRect((fx + 7) << FRACBITS, (fy + 7) << FRACBITS, rouletteBox << FRACBITS, rouletteBox << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags);
// Need to draw these in a particular order, for sorting.
V_DrawFixedPatch(fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset + ROULETTE_SPACING, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch[0], colmap);
V_DrawFixedPatch(fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset - ROULETTE_SPACING, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch[2], colmap);
V_DrawFixedPatch(fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch[1], NULL);
V_ClearClipRect();
}
else if (stplyr->itemamount >= numberdisplaymin && stplyr->itemRoulette.active == false)
{
// Then, the numbers:
V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|V_SLIDEIN|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it. V_DrawScaledPatch(fx + (flipamount ? 48 : 0), fy, V_HUDTRANS|V_SLIDEIN|fflags|(flipamount ? V_FLIP : 0), kp_itemmulsticker[offset]); // flip this graphic for p2 and p4 in split and shift it.
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch, colmap);
V_DrawFixedPatch(fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch[0], colmap);
if (offset) if (offset)
{
if (flipamount) // reminder that this is for 3/4p's right end of the screen. if (flipamount) // reminder that this is for 3/4p's right end of the screen.
V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount)); V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount));
else else
V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount)); V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount));
}
else else
{ {
V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx); V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx);
@ -1213,9 +1243,9 @@ static void K_drawKartItem(void)
} }
} }
else else
V_DrawFixedPatch(fx<<FRACBITS, fy<<FRACBITS, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch, colmap); {
V_DrawFixedPatch(fx<<FRACBITS, (fy<<FRACBITS) + rouletteOffset, FRACUNIT, V_HUDTRANS|V_SLIDEIN|fflags, localpatch[0], colmap);
//V_ClearClipRect(); }
// Extensible meter, currently only used for rocket sneaker... // Extensible meter, currently only used for rocket sneaker...
if (itembar) if (itembar)

View file

@ -6940,6 +6940,11 @@ void K_KartPlayerHUDUpdate(player_t *player)
player->karthud[khud_itemblink] = 0; player->karthud[khud_itemblink] = 0;
} }
if (player->karthud[khud_rouletteoffset] != 0)
{
player->karthud[khud_rouletteoffset] = FixedMul(player->karthud[khud_rouletteoffset], FRACUNIT*3/4);
}
if (!(gametyperules & GTR_SPHERES)) if (!(gametyperules & GTR_SPHERES))
{ {
if (player->mo && player->mo->hitlag <= 0) if (player->mo && player->mo->hitlag <= 0)

View file

@ -146,14 +146,12 @@ static kartitems_t K_KartItemReelBreakTheCapsules[] =
KITEM_NONE KITEM_NONE
}; };
#if 0
static kartitems_t K_KartItemReelBoss[] = static kartitems_t K_KartItemReelBoss[] =
{ {
KITEM_ORBINAUT, KITEM_ORBINAUT,
KITEM_BANANA, KITEM_BANANA,
KITEM_NONE KITEM_NONE
}; };
#endif
boolean K_ItemEnabled(SINT8 item) boolean K_ItemEnabled(SINT8 item)
{ {
@ -809,7 +807,16 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette)
// SPECIAL CASE No. 2: // SPECIAL CASE No. 2:
// Use a special, pre-determined item reel for Time Attack / Free Play // Use a special, pre-determined item reel for Time Attack / Free Play
if (modeattacking || playing <= 1) if (bossinfo.boss == true)
{
for (i = 0; K_KartItemReelBoss[i] != KITEM_NONE; i++)
{
K_PushToRouletteItemList(roulette, K_KartItemReelBoss[i]);
}
return;
}
else if (modeattacking || playing <= 1)
{ {
switch (gametype) switch (gametype)
{ {
@ -819,7 +826,6 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette)
for (i = 0; K_KartItemReelTimeAttack[i] != KITEM_NONE; i++) for (i = 0; K_KartItemReelTimeAttack[i] != KITEM_NONE; i++)
{ {
K_PushToRouletteItemList(roulette, K_KartItemReelTimeAttack[i]); K_PushToRouletteItemList(roulette, K_KartItemReelTimeAttack[i]);
CONS_Printf("Added %d\n", K_KartItemReelTimeAttack[i]);
} }
break; break;
} }
@ -828,7 +834,6 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette)
for (i = 0; K_KartItemReelBreakTheCapsules[i] != KITEM_NONE; i++) for (i = 0; K_KartItemReelBreakTheCapsules[i] != KITEM_NONE; i++)
{ {
K_PushToRouletteItemList(roulette, K_KartItemReelBreakTheCapsules[i]); K_PushToRouletteItemList(roulette, K_KartItemReelBreakTheCapsules[i]);
CONS_Printf("Added %d\n", K_KartItemReelBreakTheCapsules[i]);
} }
break; break;
} }
@ -875,7 +880,7 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette)
{ {
rngRoll = P_RandomKey(PR_ITEM_ROULETTE, totalSpawnChance); rngRoll = P_RandomKey(PR_ITEM_ROULETTE, totalSpawnChance);
for (i = 0; i < NUMKARTRESULTS && spawnChance[i] <= rngRoll; i++) for (i = 1; i < NUMKARTRESULTS && spawnChance[i] <= rngRoll; i++)
{ {
continue; continue;
} }
@ -924,6 +929,14 @@ static void K_KartGetItemResult(player_t *const player, kartitems_t getitem)
player->itemamount = K_ItemResultToAmount(getitem); player->itemamount = K_ItemResultToAmount(getitem);
} }
fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta)
{
const fixed_t curTic = (roulette->tics << FRACBITS) - renderDelta;
const fixed_t midTic = roulette->speed * (FRACUNIT >> 1);
return FixedMul(FixedDiv(midTic - curTic, ((roulette->speed + 1) << FRACBITS)), ROULETTE_SPACING);
}
void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd) void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
{ {
itemroulette_t *const roulette = &player->itemRoulette; itemroulette_t *const roulette = &player->itemRoulette;
@ -970,6 +983,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
//player->karthud[khud_itemblink] = TICRATE; //player->karthud[khud_itemblink] = TICRATE;
//player->karthud[khud_itemblinkmode] = 1; //player->karthud[khud_itemblinkmode] = 1;
//player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT);
if (P_IsDisplayPlayer(player) && !demo.freecam) if (P_IsDisplayPlayer(player) && !demo.freecam)
{ {
@ -984,6 +998,7 @@ void K_KartItemRoulette(player_t *const player, ticcmd_t *const cmd)
player->karthud[khud_itemblink] = TICRATE; player->karthud[khud_itemblink] = TICRATE;
player->karthud[khud_itemblinkmode] = 0; player->karthud[khud_itemblinkmode] = 0;
player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT);
if (P_IsDisplayPlayer(player) && !demo.freecam) if (P_IsDisplayPlayer(player) && !demo.freecam)
{ {

View file

@ -30,6 +30,9 @@ boolean K_ForcedSPB(player_t *const player);
void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette); void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette);
void K_StartEggmanRoulette(player_t *const player); void K_StartEggmanRoulette(player_t *const player);
#define ROULETTE_SPACING (36 << FRACBITS)
fixed_t K_GetRouletteOffset(itemroulette_t *const roulette, fixed_t renderDelta);
void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd); void K_KartItemRoulette(player_t *const player, ticcmd_t *cmd);
#endif // __K_ROULETTE_H__ #endif // __K_ROULETTE_H__