From 53faf37dc1d1472b372af27370d61e318f4351d7 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 18 Aug 2024 10:41:17 -0500 Subject: [PATCH] Add persistent bunny mask enhancement (#537) --- mm/2s2h/BenGui/BenMenuBar.cpp | 5 + mm/2s2h/Enhancements/Enhancements.cpp | 1 + mm/2s2h/Enhancements/Enhancements.h | 1 + .../GameInteractor/GameInteractor.cpp | 17 ++ .../GameInteractor/GameInteractor.h | 13 +- .../Enhancements/Masks/PersistentMasks.cpp | 206 ++++++++++++++++++ mm/2s2h/Enhancements/Masks/PersistentMasks.h | 7 + mm/include/gfxprint.h | 8 + mm/include/z64.h | 2 - mm/src/code/z_player_lib.c | 3 + .../actors/ovl_player_actor/z_player.c | 33 +-- .../ovl_kaleido_scope/z_kaleido_mask.c | 29 ++- .../ovl_kaleido_scope/z_kaleido_scope_NES.c | 8 + 13 files changed, 305 insertions(+), 28 deletions(-) create mode 100644 mm/2s2h/Enhancements/Masks/PersistentMasks.cpp create mode 100644 mm/2s2h/Enhancements/Masks/PersistentMasks.h diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index cadc3bbe8..4a1dd56e9 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -593,6 +593,11 @@ void DrawEnhancementsMenu() { UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere", { .tooltip = "Allow using Fierce Deity's mask outside of boss rooms." }); UIWidgets::CVarCheckbox("No Blast Mask Cooldown", "gEnhancements.Masks.NoBlastMaskCooldown", {}); + if (UIWidgets::CVarCheckbox("Persistent Bunny Hood", "gEnhancements.Masks.PersistentBunnyHood.Enabled", + { .tooltip = "Permanantly toggle a speed boost from the bunny hood by pressing " + "'A' on it in the mask menu." })) { + UpdatePersistentMasksState(); + } ImGui::EndMenu(); } diff --git a/mm/2s2h/Enhancements/Enhancements.cpp b/mm/2s2h/Enhancements/Enhancements.cpp index 1590e8a67..ae30f2361 100644 --- a/mm/2s2h/Enhancements/Enhancements.cpp +++ b/mm/2s2h/Enhancements/Enhancements.cpp @@ -37,6 +37,7 @@ void InitEnhancements() { RegisterFierceDeityAnywhere(); RegisterBlastMaskKeg(); RegisterNoBlastMaskCooldown(); + RegisterPersistentMasks(); // Minigames RegisterAlwaysWinDoggyRace(); diff --git a/mm/2s2h/Enhancements/Enhancements.h b/mm/2s2h/Enhancements/Enhancements.h index da9a3a2bb..7aa780c7f 100644 --- a/mm/2s2h/Enhancements/Enhancements.h +++ b/mm/2s2h/Enhancements/Enhancements.h @@ -18,6 +18,7 @@ #include "Masks/FierceDeityAnywhere.h" #include "Masks/NoBlastMaskCooldown.h" #include "Masks/FastTransformation.h" +#include "Masks/PersistentMasks.h" #include "Minigames/AlwaysWinDoggyRace.h" #include "Cutscenes/Cutscenes.h" #include "Restorations/FlipHopVariable.h" diff --git a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp index f27becaa0..15f96126b 100644 --- a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp +++ b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp @@ -27,6 +27,17 @@ void GameInteractor_ExecuteOnKaleidoUpdate(PauseContext* pauseCtx) { GameInteractor::Instance->ExecuteHooks(pauseCtx); } +void GameInteractor_ExecuteBeforeKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex) { + GameInteractor::Instance->ExecuteHooks(pauseCtx, pauseIndex); + GameInteractor::Instance->ExecuteHooksForID(pauseIndex, pauseCtx, + pauseIndex); +} + +void GameInteractor_ExecuteAfterKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex) { + GameInteractor::Instance->ExecuteHooks(pauseCtx, pauseIndex); + GameInteractor::Instance->ExecuteHooksForID(pauseIndex, pauseCtx, pauseIndex); +} + void GameInteractor_ExecuteOnSaveInit(s16 fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } @@ -123,6 +134,12 @@ void GameInteractor_ExecuteOnActorKill(Actor* actor) { GameInteractor::Instance->ExecuteHooksForFilter(actor); } +void GameInteractor_ExecuteOnPlayerPostLimbDraw(Player* player, s32 limbIndex) { + GameInteractor::Instance->ExecuteHooks(player, limbIndex); + GameInteractor::Instance->ExecuteHooksForID(limbIndex, player, limbIndex); + GameInteractor::Instance->ExecuteHooksForFilter(player, limbIndex); +} + void GameInteractor_ExecuteOnSceneFlagSet(s16 sceneId, FlagType flagType, u32 flag) { SPDLOG_DEBUG("OnSceneFlagSet: sceneId: {}, flagType: {}, flag: {}", sceneId, (u32)flagType, flag); GameInteractor::Instance->ExecuteHooks(sceneId, flagType, flag); diff --git a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h index 41d5f99ab..2ef0b487f 100644 --- a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h +++ b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h @@ -5,8 +5,6 @@ #include extern "C" { #endif -#include "z64actor.h" -#include "z64camera.h" #include "z64.h" #ifdef __cplusplus } @@ -48,6 +46,11 @@ typedef enum { GI_VB_SONG_AVAILABLE_TO_PLAY, GI_VB_USE_CUSTOM_CAMERA, GI_VB_DELETE_OWL_SAVE, + GI_VB_CONSIDER_BUNNY_HOOD_EQUIPPED, + GI_VB_USE_ITEM_EQUIP_MASK, + GI_VB_KALEIDO_DISPLAY_ITEM_TEXT, + GI_VB_USE_ITEM_CONSIDER_LINK_HUMAN, + GI_VB_DRAW_ITEM_EQUIPPED_OUTLINE, GI_VB_PLAY_TRANSITION_CS, GI_VB_TATL_INTERUPT_MSG3, GI_VB_TATL_INTERUPT_MSG6, @@ -260,6 +263,8 @@ class GameInteractor { DEFINE_HOOK(OnGameStateUpdate, ()); DEFINE_HOOK(OnConsoleLogoUpdate, ()); DEFINE_HOOK(OnKaleidoUpdate, (PauseContext * pauseCtx)); + DEFINE_HOOK(BeforeKaleidoDrawPage, (PauseContext * pauseCtx, u16 pauseIndex)); + DEFINE_HOOK(AfterKaleidoDrawPage, (PauseContext * pauseCtx, u16 pauseIndex)); DEFINE_HOOK(OnSaveInit, (s16 fileNum)); DEFINE_HOOK(BeforeEndOfCycleSave, ()); DEFINE_HOOK(AfterEndOfCycleSave, ()); @@ -277,6 +282,7 @@ class GameInteractor { DEFINE_HOOK(ShouldActorDraw, (Actor * actor, bool* should)); DEFINE_HOOK(OnActorDraw, (Actor * actor)); DEFINE_HOOK(OnActorKill, (Actor * actor)); + DEFINE_HOOK(OnPlayerPostLimbDraw, (Player * player, s32 limbIndex)); DEFINE_HOOK(OnSceneFlagSet, (s16 sceneId, FlagType flagType, u32 flag)); DEFINE_HOOK(OnSceneFlagUnset, (s16 sceneId, FlagType flagType, u32 flag)); @@ -305,6 +311,8 @@ void GameInteractor_ExecuteOnGameStateDrawFinish(); void GameInteractor_ExecuteOnGameStateUpdate(); void GameInteractor_ExecuteOnConsoleLogoUpdate(); void GameInteractor_ExecuteOnKaleidoUpdate(PauseContext* pauseCtx); +void GameInteractor_ExecuteBeforeKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex); +void GameInteractor_ExecuteAfterKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex); void GameInteractor_ExecuteOnSaveInit(s16 fileNum); void GameInteractor_ExecuteBeforeEndOfCycleSave(); void GameInteractor_ExecuteAfterEndOfCycleSave(); @@ -322,6 +330,7 @@ void GameInteractor_ExecuteOnActorUpdate(Actor* actor); bool GameInteractor_ShouldActorDraw(Actor* actor); void GameInteractor_ExecuteOnActorDraw(Actor* actor); void GameInteractor_ExecuteOnActorKill(Actor* actor); +void GameInteractor_ExecuteOnPlayerPostLimbDraw(Player* player, s32 limbIndex); void GameInteractor_ExecuteOnSceneFlagSet(s16 sceneId, FlagType flagType, u32 flag); void GameInteractor_ExecuteOnSceneFlagUnset(s16 sceneId, FlagType flagType, u32 flag); diff --git a/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp b/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp new file mode 100644 index 000000000..92177f9be --- /dev/null +++ b/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp @@ -0,0 +1,206 @@ +#include +#include +#include "Enhancements/GameInteractor/GameInteractor.h" +#include "Enhancements/FrameInterpolation/FrameInterpolation.h" + +extern "C" { +#include "z64.h" +#include "z64player.h" +#include "functions.h" +#include "macros.h" +#include "gfx.h" +#include "src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" +#include "assets/interface/parameter_static/parameter_static.h" + +void func_8082E1F0(Player* player, u16 sfxId); +void Player_DrawBunnyHood(PlayState* play); +extern PlayState* gPlayState; +extern const char* D_801C0B20[28]; +extern SaveContext gSaveContext; +} + +void UpdatePersistentMasksState() { + static Vtx* persistentMasksVtx; + static HOOK_ID beforePageDrawHook = 0; + static HOOK_ID onPlayerPostLimbDrawHook = 0; + GameInteractor::Instance->UnregisterGameHook(beforePageDrawHook); + GameInteractor::Instance->UnregisterGameHookForID(onPlayerPostLimbDrawHook); + + if (!CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) { + CVarClear("gEnhancements.Masks.PersistentBunnyHood.State"); + return; + } + + // If the mask is equipped, unequip it + if (gSaveContext.save.equippedMask == PLAYER_MASK_BUNNY) { + gSaveContext.save.equippedMask = PLAYER_MASK_NONE; + CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 1); + + if (gPlayState != NULL) { + Player* player = GET_PLAYER(gPlayState); + player->prevMask = player->currentMask; + player->currentMask = PLAYER_MASK_NONE; + } + } + + // If they don't have the mask, clear the state + if (INV_CONTENT(ITEM_MASK_BUNNY) != ITEM_MASK_BUNNY) { + CVarClear("gEnhancements.Masks.PersistentBunnyHood.State"); + } + + // This hook draws the mask on the players head when it's active and they aren't in first person + onPlayerPostLimbDrawHook = GameInteractor::Instance->RegisterGameHookForID( + PLAYER_LIMB_HEAD, [](Player* player, s32 limbIndex) { + // Ensure they aren't in first person + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0) && + !(player->stateFlags1 & PLAYER_STATE1_100000)) { + OPEN_DISPS(gPlayState->state.gfxCtx); + Matrix_Push(); + Player_DrawBunnyHood(gPlayState); + gSPDisplayList(POLY_OPA_DISP++, + (Gfx*)D_801C0B20[PLAYER_MASK_BUNNY - 1]); // D_801C0B20 is an array of mask DLs + Matrix_Pop(); + CLOSE_DISPS(gPlayState->state.gfxCtx); + } + }); + + // This hook sets up the quad and draws the "active" blue border around the mask in the pause menu + beforePageDrawHook = GameInteractor::Instance->RegisterGameHookForID( + PAUSE_MASK, [](PauseContext* _, u16 __) { + GraphicsContext* gfxCtx = gPlayState->state.gfxCtx; + PauseContext* pauseCtx = &gPlayState->pauseCtx; + s16 i = 0; + s16 j = 0; + s16 k; + + OPEN_DISPS(gfxCtx); + + persistentMasksVtx = (Vtx*)GRAPH_ALLOC(gfxCtx, (4 * 4) * sizeof(Vtx)); + + if ((pauseCtx->state == PAUSE_STATE_MAIN)) { + s16 slot = SLOT_MASK_BUNNY - ITEM_NUM_SLOTS; + s16 slotX = slot % MASK_GRID_COLS; + s16 slotY = slot / MASK_GRID_COLS; + s16 initialX = 0 - (MASK_GRID_COLS * MASK_GRID_CELL_WIDTH) / 2; + s16 initialY = (MASK_GRID_ROWS * MASK_GRID_CELL_HEIGHT) / 2 - 6; + s16 vtxX = (initialX + (slotX * MASK_GRID_CELL_WIDTH)) + MASK_GRID_QUAD_MARGIN; + s16 vtxY = (initialY - (slotY * MASK_GRID_CELL_HEIGHT)) + pauseCtx->offsetY - MASK_GRID_QUAD_MARGIN; + persistentMasksVtx[i + 0].v.ob[0] = persistentMasksVtx[i + 2].v.ob[0] = + vtxX + MASK_GRID_SELECTED_QUAD_MARGIN; + persistentMasksVtx[i + 1].v.ob[0] = persistentMasksVtx[i + 3].v.ob[0] = + persistentMasksVtx[i + 0].v.ob[0] + MASK_GRID_SELECTED_QUAD_WIDTH; + persistentMasksVtx[i + 0].v.ob[1] = persistentMasksVtx[i + 1].v.ob[1] = + vtxY - MASK_GRID_SELECTED_QUAD_MARGIN; + + persistentMasksVtx[i + 2].v.ob[1] = persistentMasksVtx[i + 3].v.ob[1] = + persistentMasksVtx[i + 0].v.ob[1] - MASK_GRID_SELECTED_QUAD_HEIGHT; + + persistentMasksVtx[i + 0].v.ob[2] = persistentMasksVtx[i + 1].v.ob[2] = + persistentMasksVtx[i + 2].v.ob[2] = persistentMasksVtx[i + 3].v.ob[2] = 0; + + persistentMasksVtx[i + 0].v.flag = persistentMasksVtx[i + 1].v.flag = persistentMasksVtx[i + 2].v.flag = + persistentMasksVtx[i + 3].v.flag = 0; + + persistentMasksVtx[i + 0].v.tc[0] = persistentMasksVtx[i + 0].v.tc[1] = + persistentMasksVtx[i + 1].v.tc[1] = persistentMasksVtx[i + 2].v.tc[0] = 0; + + persistentMasksVtx[i + 1].v.tc[0] = persistentMasksVtx[i + 2].v.tc[1] = + persistentMasksVtx[i + 3].v.tc[0] = persistentMasksVtx[i + 3].v.tc[1] = + MASK_GRID_SELECTED_QUAD_TEX_SIZE * (1 << 5); + + persistentMasksVtx[i + 0].v.cn[0] = persistentMasksVtx[i + 1].v.cn[0] = + persistentMasksVtx[i + 2].v.cn[0] = persistentMasksVtx[i + 3].v.cn[0] = + persistentMasksVtx[i + 0].v.cn[1] = persistentMasksVtx[i + 1].v.cn[1] = + persistentMasksVtx[i + 2].v.cn[1] = persistentMasksVtx[i + 3].v.cn[1] = + persistentMasksVtx[i + 0].v.cn[2] = persistentMasksVtx[i + 1].v.cn[2] = + persistentMasksVtx[i + 2].v.cn[2] = persistentMasksVtx[i + 3].v.cn[2] = 255; + + persistentMasksVtx[i + 0].v.cn[3] = persistentMasksVtx[i + 1].v.cn[3] = + persistentMasksVtx[i + 2].v.cn[3] = persistentMasksVtx[i + 3].v.cn[3] = pauseCtx->alpha; + + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 200, 255, 255); + gSPVertex(POLY_OPA_DISP++, (uintptr_t)persistentMasksVtx, 4, 0); + POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, (TexturePtr)gEquippedItemOutlineTex, 32, 32, 0); + } + } + + CLOSE_DISPS(gfxCtx); + }); +} + +void RegisterPersistentMasks() { + UpdatePersistentMasksState(); + + // Easiest way to handle things like loading into a different file, debug warping, etc. + GameInteractor::Instance->RegisterGameHook( + [](s8 sceneId, s8 spawnNum) { UpdatePersistentMasksState(); }); + + // Speed the player up when the bunny hood state is active + REGISTER_VB_SHOULD(GI_VB_CONSIDER_BUNNY_HOOD_EQUIPPED, { + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + *should = true; + } + }); + + // Overrides allowing them to equip a mask while transformed + REGISTER_VB_SHOULD(GI_VB_USE_ITEM_CONSIDER_LINK_HUMAN, { + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0) && + *(PlayerItemAction*)opt == PLAYER_IA_MASK_BUNNY) { + *should = true; + } + }); + + // When they do equip the mask, prevent it and instead set our state + REGISTER_VB_SHOULD(GI_VB_USE_ITEM_EQUIP_MASK, { + PlayerMask* maskId = (PlayerMask*)opt; + Player* player = GET_PLAYER(gPlayState); + + if (*maskId == PLAYER_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) { + *should = false; + + CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", + !CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)); + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + func_8082E1F0(player, NA_SE_PL_CHANGE_ARMS); + } else { + func_8082E1F0(player, NA_SE_PL_TAKE_OUT_SHIELD); + } + } + }); + + // Prevent the "equipped" white border from being drawn so ours shows instead (ours was drawn before it, so it's + // underneath) + REGISTER_VB_SHOULD(GI_VB_DRAW_ITEM_EQUIPPED_OUTLINE, { + if (*(ItemId*)opt == ITEM_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + *should = false; + } + }); + + // Typically when you are in a transformation all masks are dimmed on the C-Buttons + REGISTER_VB_SHOULD(GI_VB_ITEM_BE_RESTRICTED, { + if (*(ItemId*)opt == ITEM_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) { + *should = false; + } + }); + + // Override "A" press behavior on kaleido scope to toggle the mask state + REGISTER_VB_SHOULD(GI_VB_KALEIDO_DISPLAY_ITEM_TEXT, { + ItemId* itemId = (ItemId*)opt; + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0) && *itemId == ITEM_MASK_BUNNY) { + *should = false; + CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", + !CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)); + if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_DOWN); + } else { + Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_UP); + } + } else if (CVarGetInteger("gEnhancements.Masks.PersistentGreatFairyMask.Enabled", 0) && + *itemId == ITEM_MASK_GREAT_FAIRY) { + *should = false; + CVarSetInteger("gEnhancements.Masks.PersistentGreatFairyMask.State", + !CVarGetInteger("gEnhancements.Masks.PersistentGreatFairyMask.State", 0)); + } + }); +} diff --git a/mm/2s2h/Enhancements/Masks/PersistentMasks.h b/mm/2s2h/Enhancements/Masks/PersistentMasks.h new file mode 100644 index 000000000..db441e7b8 --- /dev/null +++ b/mm/2s2h/Enhancements/Masks/PersistentMasks.h @@ -0,0 +1,7 @@ +#ifndef MASKS_PERSISTENT_MASKS_H +#define MASKS_PERSISTENT_MASKS_H + +void RegisterPersistentMasks(); +void UpdatePersistentMasksState(); + +#endif // MASKS_PERSISTENT_MASKS_H diff --git a/mm/include/gfxprint.h b/mm/include/gfxprint.h index f6c896c01..6fb8c0e30 100644 --- a/mm/include/gfxprint.h +++ b/mm/include/gfxprint.h @@ -1,6 +1,10 @@ #ifndef GFXPRINT_H #define GFXPRINT_H +#ifdef __cplusplus +#define this thisx +#endif + #include "color.h" #include "PR/gbi.h" #include "PR/ultratypes.h" @@ -61,4 +65,8 @@ s32 GfxPrint_Printf(GfxPrint* this, const char* fmt, ...); (void)0 // #endregion +#ifdef __cplusplus +#undef this +#endif + #endif diff --git a/mm/include/z64.h b/mm/include/z64.h index 64a8888c1..703edba0a 100644 --- a/mm/include/z64.h +++ b/mm/include/z64.h @@ -2,7 +2,6 @@ #define Z64_H #ifdef __cplusplus extern "C" { -#define this thisx #endif #include "libc/math.h" #include "libc/stdarg.h" @@ -308,6 +307,5 @@ typedef enum { // #ifdef __cplusplus } -#undef this #endif #endif diff --git a/mm/src/code/z_player_lib.c b/mm/src/code/z_player_lib.c index 01556acc8..2dca51ea7 100644 --- a/mm/src/code/z_player_lib.c +++ b/mm/src/code/z_player_lib.c @@ -43,6 +43,7 @@ // Assets for other actors #include "overlays/actors/ovl_En_Arrow/z_en_arrow.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" void PlayerCall_Init(Actor* thisx, PlayState* play); void PlayerCall_Destroy(Actor* thisx, PlayState* play); @@ -4020,5 +4021,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList1, G Player_SetFeetPos(play, player, limbIndex); } + GameInteractor_ExecuteOnPlayerPostLimbDraw(player, limbIndex); + func_8012536C(); } diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index f3a173303..16e9c9ca7 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -4471,7 +4471,9 @@ void Player_UseItem(PlayState* play, Player* this, ItemId item) { (itemAction == PLAYER_IA_MASK_ZORA) || ((this->currentBoots >= PLAYER_BOOTS_ZORA_UNDERWATER) && (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND)))) { s32 var_v1 = ((itemAction >= PLAYER_IA_MASK_MIN) && (itemAction <= PLAYER_IA_MASK_MAX) && - ((this->transformation != PLAYER_FORM_HUMAN) || (itemAction >= PLAYER_IA_MASK_GIANT))); + (!GameInteractor_Should(GI_VB_USE_ITEM_CONSIDER_LINK_HUMAN, + this->transformation == PLAYER_FORM_HUMAN, &itemAction) || + (itemAction >= PLAYER_IA_MASK_GIANT))); CollisionPoly* sp5C; s32 sp58; f32 sp54; @@ -4531,20 +4533,23 @@ void Player_UseItem(PlayState* play, Player* this, ItemId item) { } else { Audio_PlaySfx(NA_SE_SY_ERROR); } - } else if ((this->transformation == PLAYER_FORM_HUMAN) && (itemAction >= PLAYER_IA_MASK_MIN) && - (itemAction < PLAYER_IA_MASK_GIANT)) { + } else if (GameInteractor_Should(GI_VB_USE_ITEM_CONSIDER_LINK_HUMAN, this->transformation == PLAYER_FORM_HUMAN, + &itemAction) && + (itemAction >= PLAYER_IA_MASK_MIN) && (itemAction < PLAYER_IA_MASK_GIANT)) { PlayerMask maskId = GET_MASK_FROM_IA(itemAction); - // Handle wearable masks - this->prevMask = this->currentMask; - if (maskId == this->currentMask) { - this->currentMask = PLAYER_MASK_NONE; - func_8082E1F0(this, NA_SE_PL_TAKE_OUT_SHIELD); - } else { - this->currentMask = maskId; - func_8082E1F0(this, NA_SE_PL_CHANGE_ARMS); + if (GameInteractor_Should(GI_VB_USE_ITEM_EQUIP_MASK, true, &maskId)) { + // Handle wearable masks + this->prevMask = this->currentMask; + if (maskId == this->currentMask) { + this->currentMask = PLAYER_MASK_NONE; + func_8082E1F0(this, NA_SE_PL_TAKE_OUT_SHIELD); + } else { + this->currentMask = maskId; + func_8082E1F0(this, NA_SE_PL_CHANGE_ARMS); + } + gSaveContext.save.equippedMask = this->currentMask; } - gSaveContext.save.equippedMask = this->currentMask; } else if ((itemAction != this->heldItemAction) || ((this->heldActor == NULL) && (Player_ExplosiveFromIA(this, itemAction) > PLAYER_EXPLOSIVE_NONE))) { u8 nextAnimType; @@ -12193,7 +12198,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { this->actor.shape.face = ((play->gameplayFrames & 0x20) ? 0 : 3) + this->blinkInfo.eyeTexIndex; - if (this->currentMask == PLAYER_MASK_BUNNY) { + if (GameInteractor_Should(GI_VB_CONSIDER_BUNNY_HOOD_EQUIPPED, this->currentMask == PLAYER_MASK_BUNNY, this)) { Player_UpdateBunnyEars(this); } @@ -14458,7 +14463,7 @@ void Player_Action_13(Player* this, PlayState* play) { Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play); - if (this->currentMask == PLAYER_MASK_BUNNY) { + if (GameInteractor_Should(GI_VB_CONSIDER_BUNNY_HOOD_EQUIPPED, this->currentMask == PLAYER_MASK_BUNNY, this)) { speedTarget *= 1.5f; } diff --git a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c index 13583678c..7d6da43c4 100644 --- a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c +++ b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c @@ -210,8 +210,11 @@ void KaleidoScope_DrawMaskSelect(PlayState* play) { for (i = 0, j = MASK_NUM_SLOTS * 4; i < 3; i++, j += 4) { if (GET_CUR_FORM_BTN_ITEM(i + 1) != ITEM_NONE) { if (GET_CUR_FORM_BTN_SLOT(i + 1) >= ITEM_NUM_SLOTS) { - gSPVertex(POLY_OPA_DISP++, &pauseCtx->maskVtx[j], 4, 0); - POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, gEquippedItemOutlineTex, 32, 32, 0); + ItemId item = GET_CUR_FORM_BTN_ITEM(i + 1); + if (GameInteractor_Should(GI_VB_DRAW_ITEM_EQUIPPED_OUTLINE, true, &item)) { + gSPVertex(POLY_OPA_DISP++, &pauseCtx->maskVtx[j], 4, 0); + POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, gEquippedItemOutlineTex, 32, 32, 0); + } } } } @@ -220,8 +223,11 @@ void KaleidoScope_DrawMaskSelect(PlayState* play) { for (i = EQUIP_SLOT_D_RIGHT; i <= EQUIP_SLOT_D_UP; i++, j += 4) { if (DPAD_GET_CUR_FORM_BTN_ITEM(i) != ITEM_NONE) { if (DPAD_GET_CUR_FORM_BTN_SLOT(i) >= ITEM_NUM_SLOTS) { - gSPVertex(POLY_OPA_DISP++, &pauseCtx->maskVtx[j], 4, 0); - POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, gEquippedItemOutlineTex, 32, 32, 0); + ItemId item = DPAD_GET_CUR_FORM_BTN_ITEM(i); + if (GameInteractor_Should(GI_VB_DRAW_ITEM_EQUIPPED_OUTLINE, true, &item)) { + gSPVertex(POLY_OPA_DISP++, &pauseCtx->maskVtx[j], 4, 0); + POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, gEquippedItemOutlineTex, 32, 32, 0); + } } } } @@ -669,12 +675,15 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { } else if ((pauseCtx->debugEditor == DEBUG_EDITOR_NONE) && (pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) && CHECK_BTN_ALL(input->press.button, BTN_A) && (msgCtx->msgLength == 0)) { - // Give description on item through a message box - pauseCtx->itemDescriptionOn = true; - if (pauseCtx->cursorYIndex[PAUSE_MASK] < 2) { - func_801514B0(play, 0x1700 + pauseCtx->cursorItem[PAUSE_MASK], 3); - } else { - func_801514B0(play, 0x1700 + pauseCtx->cursorItem[PAUSE_MASK], 1); + if (GameInteractor_Should(GI_VB_KALEIDO_DISPLAY_ITEM_TEXT, true, + &pauseCtx->cursorItem[PAUSE_MASK])) { + // Give description on item through a message box + pauseCtx->itemDescriptionOn = true; + if (pauseCtx->cursorYIndex[PAUSE_MASK] < 2) { + func_801514B0(play, 0x1700 + pauseCtx->cursorItem[PAUSE_MASK], 3); + } else { + func_801514B0(play, 0x1700 + pauseCtx->cursorItem[PAUSE_MASK], 1); + } } } } diff --git a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index 79a7d2ef6..f060ed01e 100644 --- a/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/mm/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -834,7 +834,9 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->itemPageVtx, sItemPageBgTextures); + GameInteractor_ExecuteBeforeKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); KaleidoScope_DrawItemSelect(play); + GameInteractor_ExecuteAfterKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); } break; @@ -855,6 +857,7 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures); + GameInteractor_ExecuteBeforeKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); if (sInDungeonScene) { KaleidoScope_DrawDungeonMap(play); Gfx_SetupDL42_Opa(gfxCtx); @@ -884,6 +887,7 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { KaleidoScope_DrawWorldMap(play); } + GameInteractor_ExecuteAfterKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); break; case PAUSE_QUEST: @@ -906,7 +910,9 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->questPageVtx, sQuestPageBgTextures); + GameInteractor_ExecuteBeforeKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); KaleidoScope_DrawQuestStatus(play); + GameInteractor_ExecuteAfterKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); break; case PAUSE_MASK: @@ -927,7 +933,9 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->maskPageVtx, sMaskPageBgTextures); + GameInteractor_ExecuteBeforeKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); KaleidoScope_DrawMaskSelect(play); + GameInteractor_ExecuteAfterKaleidoDrawPage(pauseCtx, pauseCtx->pageIndex); break; } }