From 202c5056648240cc61429dd831eea185d058129a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 12 Dec 2022 02:18:18 -0500 Subject: [PATCH] Implement roulette visuals --- src/d_player.h | 1 + src/k_hud.c | 104 ++++++++++++++++++++++++++++++----------------- src/k_kart.c | 5 +++ src/k_roulette.c | 27 +++++++++--- src/k_roulette.h | 3 ++ 5 files changed, 97 insertions(+), 43 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index a8b70f1a7..842edbc0e 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -225,6 +225,7 @@ typedef enum // Item box 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_rouletteoffset,// Roulette stop height // Rings khud_ringframe, // Ring spin frame diff --git a/src/k_hud.c b/src/k_hud.c index f92c94a6f..5ba874913 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1023,7 +1023,7 @@ static void K_drawKartItem(void) // Why write V_DrawScaledPatch calls over and over when they're all the same? // Set to 'no item' just in case. 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 *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... @@ -1036,28 +1036,42 @@ static void K_drawKartItem(void) UINT8 *colmap = NULL; 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) { - const SINT8 item = K_ItemResultToType(stplyr->itemRoulette.itemList[ stplyr->itemRoulette.index ]); + rouletteOffset = K_GetRouletteOffset(&stplyr->itemRoulette, rendertimefrac); if (stplyr->skincolor) { localcolor = stplyr->skincolor; } - switch (item) + for (i = 0; i < 3; i++) { - case KITEM_INVINCIBILITY: - localpatch = localinv; - break; + const SINT8 indexOfs = i-1; + const size_t index = (stplyr->itemRoulette.index + indexOfs) % stplyr->itemRoulette.itemListLen; - case KITEM_ORBINAUT: - localpatch = kp_orbinaut[3 + offset]; - break; + const SINT8 result = stplyr->itemRoulette.itemList[index]; + const SINT8 item = K_ItemResultToType(result); + const UINT8 amt = K_ItemResultToAmount(result); - default: - localpatch = K_GetCachedItemPatch(item, offset); - break; + switch (item) + { + 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 @@ -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 // 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 + + rouletteOffset = stplyr->karthud[khud_rouletteoffset]; + if (stplyr->stealingtimer < 0) { if (leveltime & 2) - localpatch = kp_hyudoro[offset]; + localpatch[0] = kp_hyudoro[offset]; else - localpatch = kp_nodraw; + localpatch[0] = kp_nodraw; } else if ((stplyr->stealingtimer > 0) && (leveltime & 2)) { - localpatch = kp_hyudoro[offset]; + localpatch[0] = kp_hyudoro[offset]; } else if (stplyr->eggmanexplode > 1) { if (leveltime & 1) - localpatch = kp_eggman[offset]; + localpatch[0] = kp_eggman[offset]; else - localpatch = kp_nodraw; + localpatch[0] = kp_nodraw; } else if (stplyr->ballhogcharge > 0) { @@ -1090,9 +1107,9 @@ static void K_drawKartItem(void) maxl = (((stplyr->itemamount-1) * BALLHOGINCREMENT) + 1); if (leveltime & 1) - localpatch = kp_ballhog[offset]; + localpatch[0] = kp_ballhog[offset]; else - localpatch = kp_nodraw; + localpatch[0] = kp_nodraw; } else if (stplyr->rocketsneakertimer > 1) { @@ -1100,16 +1117,16 @@ static void K_drawKartItem(void) maxl = (itemtime*3) - barlength; if (leveltime & 1) - localpatch = kp_rocketsneaker[offset]; + localpatch[0] = kp_rocketsneaker[offset]; else - localpatch = kp_nodraw; + localpatch[0] = kp_nodraw; } else if (stplyr->sadtimer > 0) { if (leveltime & 2) - localpatch = kp_sadface[offset]; + localpatch[0] = kp_sadface[offset]; else - localpatch = kp_nodraw; + localpatch[0] = kp_nodraw; } else { @@ -1119,12 +1136,12 @@ static void K_drawKartItem(void) switch (stplyr->itemtype) { case KITEM_INVINCIBILITY: - localpatch = localinv; + localpatch[0] = localinv; localbg = kp_itembg[offset+1]; break; 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; case KITEM_SPB: @@ -1135,15 +1152,15 @@ static void K_drawKartItem(void) /*FALLTHRU*/ default: - localpatch = K_GetCachedItemPatch(stplyr->itemtype, offset); + localpatch[0] = K_GetCachedItemPatch(stplyr->itemtype, offset); - if (localpatch == NULL) - localpatch = kp_nodraw; // diagnose underflows + if (localpatch[0] == NULL) + localpatch[0] = kp_nodraw; // diagnose underflows break; } if ((stplyr->pflags & PF_ITEMOUT) && !(leveltime & 1)) - localpatch = kp_nodraw; + localpatch[0] = kp_nodraw; } 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_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); - - // Then, the numbers: - if (stplyr->itemamount >= numberdisplaymin && stplyr->itemRoulette.active == false) + if (stplyr->itemRoulette.active == true) { + 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<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_DrawFixedPatch(fx<itemamount)); else V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|V_SLIDEIN|fflags, va("x%d", stplyr->itemamount)); + } else { V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|V_SLIDEIN|fflags, kp_itemx); @@ -1213,9 +1243,9 @@ static void K_drawKartItem(void) } } else - V_DrawFixedPatch(fx<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 (player->mo && player->mo->hitlag <= 0) diff --git a/src/k_roulette.c b/src/k_roulette.c index c5a493365..7e3d7a3b7 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -146,14 +146,12 @@ static kartitems_t K_KartItemReelBreakTheCapsules[] = KITEM_NONE }; -#if 0 static kartitems_t K_KartItemReelBoss[] = { KITEM_ORBINAUT, KITEM_BANANA, KITEM_NONE }; -#endif boolean K_ItemEnabled(SINT8 item) { @@ -809,7 +807,16 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette) // SPECIAL CASE No. 2: // 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) { @@ -819,7 +826,6 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette) for (i = 0; K_KartItemReelTimeAttack[i] != KITEM_NONE; i++) { K_PushToRouletteItemList(roulette, K_KartItemReelTimeAttack[i]); - CONS_Printf("Added %d\n", K_KartItemReelTimeAttack[i]); } 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++) { K_PushToRouletteItemList(roulette, K_KartItemReelBreakTheCapsules[i]); - CONS_Printf("Added %d\n", K_KartItemReelBreakTheCapsules[i]); } break; } @@ -875,7 +880,7 @@ void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette) { 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; } @@ -924,6 +929,14 @@ static void K_KartGetItemResult(player_t *const player, kartitems_t 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) { 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_itemblinkmode] = 1; + //player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT); 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_itemblinkmode] = 0; + player->karthud[khud_rouletteoffset] = K_GetRouletteOffset(roulette, FRACUNIT); if (P_IsDisplayPlayer(player) && !demo.freecam) { diff --git a/src/k_roulette.h b/src/k_roulette.h index 8fd302abf..81e12aae3 100644 --- a/src/k_roulette.h +++ b/src/k_roulette.h @@ -30,6 +30,9 @@ boolean K_ForcedSPB(player_t *const player); void K_StartItemRoulette(player_t *const player, itemroulette_t *const roulette); 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); #endif // __K_ROULETTE_H__