add visualization for pause menu item cycling (#3118)

This commit is contained in:
Adam Bird 2023-08-20 14:00:43 -04:00 committed by GitHub
parent 155f5e165a
commit 0ce2d30605
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,8 +1,10 @@
#include "z_kaleido_scope.h" #include "z_kaleido_scope.h"
#include "textures/parameter_static/parameter_static.h" #include "textures/parameter_static/parameter_static.h"
#include "textures/icon_item_static/icon_item_static.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
u8 gAmmoItems[] = { u8 gAmmoItems[] = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE, ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
@ -85,6 +87,139 @@ void KaleidoScope_SetItemCursorVtx(PauseContext* pauseCtx) {
KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_ITEM] * 4, pauseCtx->itemVtx); KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_ITEM] * 4, pauseCtx->itemVtx);
} }
// Vertices for the extra items
static Vtx sCycleExtraItemVtx[] = {
// Left Item
VTX(-48, 16, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-16, 16, 0, 32 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-48, -16, 0, 0 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-16, -16, 0, 32 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
// Right Item
VTX(16, 16, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(48, 16, 0, 32 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(16, -16, 0, 0 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(48, -16, 0, 32 << 5, 32 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
};
// Vertices for the circle behind the items
static Vtx sCycleCircleVtx[] = {
// Left Item
VTX(-56, 24, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-8, 24, 0, 48 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-56, -24, 0, 0 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-8, -24, 0, 48 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
// Right Item
VTX(8, 24, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(56, 24, 0, 48 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(8, -24, 0, 0 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(56, -24, 0, 48 << 5, 48 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
};
// Vertices for A button indicator (coordinates 1.5x larger than texture size)
static Vtx sCycleAButtonVtx[] = {
VTX(-18, 12, 0, 0 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(18, 12, 0, 24 << 5, 0 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(-18, -12, 0, 0 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(18, -12, 0, 24 << 5, 16 << 5, 0xFF, 0xFF, 0xFF, 0xFF),
};
// Track animation timers for each inventory slot
static sSlotCycleActiveAnimTimer[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Renders a left and/or right item for any item slot that can support cycling
void KaleidoScope_DrawItemCycleExtras(PlayState* play, u8 slot, u8 isCycling, u8 canCycle, u8 leftItem, u8 rightItem) {
PauseContext* pauseCtx = &play->pauseCtx;
OPEN_DISPS(play->state.gfxCtx);
// Update active cycling animation timer
if (isCycling) {
if (sSlotCycleActiveAnimTimer[slot] < 5) {
sSlotCycleActiveAnimTimer[slot]++;
}
} else {
if (sSlotCycleActiveAnimTimer[slot] > 0) {
sSlotCycleActiveAnimTimer[slot]--;
}
}
u8 slotItem = gSaveContext.inventory.items[slot];
u8 showLeftItem = leftItem != ITEM_NONE && slotItem != leftItem;
u8 showRightItem = rightItem != ITEM_NONE && slotItem != rightItem && leftItem != rightItem;
// Render the extra cycle items if at least the left or right item are valid
if (canCycle && slotItem != ITEM_NONE && (showLeftItem || showRightItem)) {
Matrix_Push();
Vtx* itemTopLeft = &pauseCtx->itemVtx[slot * 4];
Vtx* itemBottomRight = &itemTopLeft[3];
s16 halfX = (itemBottomRight->v.ob[0] - itemTopLeft->v.ob[0]) / 2;
s16 halfY = (itemBottomRight->v.ob[1] - itemTopLeft->v.ob[1]) / 2;
Matrix_Translate(itemTopLeft->v.ob[0] + halfX, itemTopLeft->v.ob[1] + halfY, 0, MTXMODE_APPLY);
f32 animScale = (f32)(5 - sSlotCycleActiveAnimTimer[slot]) / 5;
// When not cycling or actively animating, shrink and move the items under the main slot item
if (!isCycling || sSlotCycleActiveAnimTimer[slot] < 5) {
f32 finalScale = 1.0f - (0.675f * animScale);
Matrix_Translate(0, -15.0f * animScale, 0, MTXMODE_APPLY);
Matrix_Scale(finalScale, finalScale, 1.0f, MTXMODE_APPLY);
}
gSPMatrix(POLY_KAL_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
// Render A button indicator when hovered and not cycling
if (!isCycling && sSlotCycleActiveAnimTimer[slot] == 0 && pauseCtx->cursorSlot[PAUSE_ITEM] == slot &&
pauseCtx->cursorSpecialPos == 0) {
Color_RGB8 aButtonColor = { 0, 100, 255 };
if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) {
aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor);
} else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = (Color_RGB8){ 0, 255, 100 };
}
gSPVertex(POLY_KAL_DISP++, sCycleAButtonVtx, 4, 0);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, aButtonColor.r, aButtonColor.g, aButtonColor.b, pauseCtx->alpha);
gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD);
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
}
// Render a dark circle behind the extra items when cycling
if (isCycling) {
gSPVertex(POLY_KAL_DISP++, sCycleCircleVtx, 8, 0);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 0, 0, 0, pauseCtx->alpha * (1.0f - animScale));
gDPLoadTextureBlock_4b(POLY_KAL_DISP++, gPausePromptCursorTex, G_IM_FMT_I, 48, 48, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
if (showLeftItem) {
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
}
if (showRightItem) {
gSP1Quadrangle(POLY_KAL_DISP++, 4, 6, 7, 5, 0);
}
}
// Render left and right items
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha);
gSPVertex(POLY_KAL_DISP++, sCycleExtraItemVtx, 8, 0);
if (showLeftItem) {
KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gItemIcons[leftItem], 32, 32, 0);
}
if (showRightItem) {
KaleidoScope_DrawQuadTextureRGBA32(play->state.gfxCtx, gItemIcons[rightItem], 32, 32, 4);
}
Matrix_Pop();
}
CLOSE_DISPS(play->state.gfxCtx);
}
void KaleidoScope_DrawItemSelect(PlayState* play) { void KaleidoScope_DrawItemSelect(PlayState* play) {
static s16 magicArrowEffectsR[] = { 255, 100, 255 }; static s16 magicArrowEffectsR[] = { 255, 100, 255 };
static s16 magicArrowEffectsG[] = { 0, 100, 255 }; static s16 magicArrowEffectsG[] = { 0, 100, 255 };
@ -105,6 +240,16 @@ void KaleidoScope_DrawItemSelect(PlayState* play) {
bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && gSaveContext.n64ddFlag) || bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && gSaveContext.n64ddFlag) ||
(CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON);
// only allow mask select when:
// the shop is open:
// * zelda's letter check: Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)
// * kak gate check: Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD)
// and the mask quest is complete: Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE)
bool canMaskSelect = CVarGetInteger("gMaskSelect", 0) &&
Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE) &&
Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) &&
Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD);
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_42Opa(play->state.gfxCtx); Gfx_SetupDL_42Opa(play->state.gfxCtx);
@ -354,16 +499,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) {
KaleidoScope_SetCursorVtx(pauseCtx, index, pauseCtx->itemVtx); KaleidoScope_SetCursorVtx(pauseCtx, index, pauseCtx->itemVtx);
if ((pauseCtx->debugState == 0) && (pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0)) { if ((pauseCtx->debugState == 0) && (pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0)) {
// only allow mask select when: if (canMaskSelect && cursorSlot == SLOT_TRADE_CHILD && CHECK_BTN_ALL(input->press.button, BTN_A)) {
// the shop is open:
// * zelda's letter check: Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)
// * kak gate check: Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD)
// and the mask quest is complete: Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE)
if (CVarGetInteger("gMaskSelect", 0) &&
(Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE)) &&
cursorSlot == SLOT_TRADE_CHILD && CHECK_BTN_ALL(input->press.button, BTN_A) &&
(Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) &&
(Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD))) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSelectingMask = !gSelectingMask; gSelectingMask = !gSelectingMask;
} }
@ -542,6 +678,16 @@ void KaleidoScope_DrawItemSelect(PlayState* play) {
} }
} }
// Adult trade item cycle
KaleidoScope_DrawItemCycleExtras(play, SLOT_TRADE_ADULT, gSelectingAdultTrade,
gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE),
Randomizer_GetPrevAdultTradeItem(), Randomizer_GetNextAdultTradeItem());
// Child mask item cycle (mimics the left/right item behavior from the cycling logic above)
u8 childTradeItem = INV_CONTENT(ITEM_TRADE_CHILD);
KaleidoScope_DrawItemCycleExtras(play, SLOT_TRADE_CHILD, gSelectingMask, canMaskSelect,
childTradeItem <= ITEM_MASK_KEATON ? ITEM_MASK_TRUTH : childTradeItem - 1,
childTradeItem >= ITEM_MASK_TRUTH ? ITEM_MASK_KEATON : childTradeItem + 1);
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }