From 21ca074bf7489e615c382dd553b43ed075104a40 Mon Sep 17 00:00:00 2001 From: LittleCube Date: Sun, 13 Oct 2024 00:02:08 -0400 Subject: [PATCH] Add exports for fd anywhere and epona fix patches (#494) * add exports for fd anywhere and epona fix patches * use better logic for restoreHudVisibility * cleanup * fix a couple edge cases (being sent the bow while riding Epona) --- patches/input.c | 95 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/patches/input.c b/patches/input.c index 53f7eb3..f65d2cc 100644 --- a/patches/input.c +++ b/patches/input.c @@ -534,6 +534,13 @@ RECOMP_PATCH void Player_Action_86(Player *this, PlayState *play) { func_808550D0(play, this, this->unk_B10[4], this->unk_B10[5], (this->transformation == PLAYER_FORM_HUMAN) ? 0 : 1); } +bool no_bow_epona_fix = false; + +// @recomp_export void recomp_set_no_bow_epona_fix(bool new_val): Set whether to enable the fix for getting on Epona without a bow. +RECOMP_EXPORT void recomp_set_no_bow_epona_fix(bool new_val) { + no_bow_epona_fix = new_val; +} + extern s16 sPictoState; extern s16 sPictoPhotoBeingTaken; extern void* gWorkBuffer; @@ -603,24 +610,46 @@ RECOMP_PATCH void Interface_UpdateButtonsPart1(PlayState* play) { BUTTON_STATUS(EQUIP_SLOT_C_RIGHT) = BTN_DISABLED; set_extra_item_slot_status(BTN_DISABLED); } else { - BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_BOW; + // @recomp_use_export_var no_bow_epona_fix: Part of the no bow Epona fix. + if (no_bow_epona_fix) { + if (gSaveContext.save.saveInfo.inventory.items[SLOT_BOW] == ITEM_BOW) { + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_BOW; + BUTTON_STATUS(EQUIP_SLOT_B) = BTN_ENABLED; + } + } else { + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_BOW; + } if (play->unk_1887C >= 2) { Interface_LoadItemIconImpl(play, EQUIP_SLOT_B); } else if (gSaveContext.save.saveInfo.inventory.items[SLOT_BOW] == ITEM_NONE) { - BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_NONE; + // @recomp_use_export_var no_bow_epona_fix: Part of the no bow Epona fix. + if (no_bow_epona_fix) { + gSaveContext.buttonStatus[EQUIP_SLOT_B] = BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B); + BUTTON_STATUS(EQUIP_SLOT_B) = BTN_DISABLED; + } else { + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_NONE; + } } else { Interface_LoadItemIconImpl(play, EQUIP_SLOT_B); } - BUTTON_STATUS(EQUIP_SLOT_C_LEFT) = BTN_DISABLED; - BUTTON_STATUS(EQUIP_SLOT_C_DOWN) = BTN_DISABLED; - BUTTON_STATUS(EQUIP_SLOT_C_RIGHT) = BTN_DISABLED; - set_extra_item_slot_status(BTN_DISABLED); - Interface_SetHudVisibility(HUD_VISIBILITY_A_HEARTS_MAGIC_MINIMAP_WITH_OVERWRITE); + // @recomp_use_export_var no_bow_epona_fix: If the B button does not contain a sword, don't disable the UI. + if (!no_bow_epona_fix || BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) < ITEM_SWORD_KOKIRI || + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) > ITEM_SWORD_GILDED) { + BUTTON_STATUS(EQUIP_SLOT_C_LEFT) = BTN_DISABLED; + BUTTON_STATUS(EQUIP_SLOT_C_DOWN) = BTN_DISABLED; + BUTTON_STATUS(EQUIP_SLOT_C_RIGHT) = BTN_DISABLED; + set_extra_item_slot_status(BTN_DISABLED); + Interface_SetHudVisibility(HUD_VISIBILITY_A_HEARTS_MAGIC_MINIMAP_WITH_OVERWRITE); + } } } + if (BUTTON_STATUS(EQUIP_SLOT_B) == BTN_DISABLED && BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) == ITEM_BOW) { + BUTTON_STATUS(EQUIP_SLOT_B) = BTN_ENABLED; + } + if (play->transitionMode != TRANS_MODE_OFF) { Interface_SetHudVisibility(HUD_VISIBILITY_NONE); } else if ((gSaveContext.minigameStatus == MINIGAME_STATUS_ACTIVE) && @@ -662,27 +691,51 @@ RECOMP_PATCH void Interface_UpdateButtonsPart1(PlayState* play) { BUTTON_STATUS(EQUIP_SLOT_C_RIGHT) = BTN_DISABLED; set_extra_item_slot_status(BTN_DISABLED); } else { - BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_BOW; + // @recomp_use_export_var no_bow_epona_fix: Part of the no bow Epona fix. + if (no_bow_epona_fix) { + if (gSaveContext.save.saveInfo.inventory.items[SLOT_BOW] == ITEM_BOW) { + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_BOW; + BUTTON_STATUS(EQUIP_SLOT_B) = BTN_ENABLED; + } + } else { + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_BOW; + } } if (play->unk_1887C >= 2) { Interface_LoadItemIconImpl(play, EQUIP_SLOT_B); } else if (gSaveContext.save.saveInfo.inventory.items[SLOT_BOW] == ITEM_NONE) { - BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_NONE; + // @recomp_use_export_var no_bow_epona_fix: Part of the no bow Epona fix. + if (no_bow_epona_fix) { + gSaveContext.buttonStatus[EQUIP_SLOT_B] = BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B); + BUTTON_STATUS(EQUIP_SLOT_B) = BTN_DISABLED; + } else { + BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_NONE; + } } else { Interface_LoadItemIconImpl(play, EQUIP_SLOT_B); } if (BUTTON_STATUS(EQUIP_SLOT_B) == BTN_DISABLED) { - BUTTON_STATUS(EQUIP_SLOT_B) = BTN_ENABLED; - restoreHudVisibility = true; + // @recomp_use_export_var no_bow_epona_fix: Don't enable the B button unless it is being used for the bow. + if (!no_bow_epona_fix || BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) == ITEM_BOW) { + BUTTON_STATUS(EQUIP_SLOT_B) = BTN_ENABLED; + } + + // @recomp_use_export_var no_bow_epona_fix: Don't restore hud visibility from Epona without a sword. + if (!no_bow_epona_fix || (player->stateFlags1 & PLAYER_STATE1_800000) == 0) { + restoreHudVisibility = true; + } } - BUTTON_STATUS(EQUIP_SLOT_C_LEFT) = BTN_DISABLED; - BUTTON_STATUS(EQUIP_SLOT_C_DOWN) = BTN_DISABLED; - BUTTON_STATUS(EQUIP_SLOT_C_RIGHT) = BTN_DISABLED; - set_extra_item_slot_status(BTN_DISABLED); - Interface_SetHudVisibility(HUD_VISIBILITY_A_HEARTS_MAGIC_MINIMAP_WITH_OVERWRITE); + // @recomp_use_export_var no_bow_epona_fix: If the B button does not contain the bow, don't disable the UI. + if (!no_bow_epona_fix || BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) == ITEM_BOW) { + BUTTON_STATUS(EQUIP_SLOT_C_LEFT) = BTN_DISABLED; + BUTTON_STATUS(EQUIP_SLOT_C_DOWN) = BTN_DISABLED; + BUTTON_STATUS(EQUIP_SLOT_C_RIGHT) = BTN_DISABLED; + set_extra_item_slot_status(BTN_DISABLED); + Interface_SetHudVisibility(HUD_VISIBILITY_A_HEARTS_MAGIC_MINIMAP_WITH_OVERWRITE); + } if (play->transitionMode != TRANS_MODE_OFF) { Interface_SetHudVisibility(HUD_VISIBILITY_NONE); @@ -802,6 +855,13 @@ RECOMP_PATCH void Interface_UpdateButtonsPart1(PlayState* play) { } } +bool fd_anywhere = false; + +// @recomp_export void recomp_set_fd_anywhere(bool new_val): Set whether the Fierce Deity's Mask has scene restrictions. +RECOMP_EXPORT void recomp_set_fd_anywhere(bool new_val) { + fd_anywhere = new_val; +} + /** * A continuation of the if-else chain from Interface_UpdateButtonsPart1 * Also used directly when opening the pause menu i.e. skips part 1 @@ -1181,7 +1241,8 @@ RECOMP_PATCH void Interface_UpdateButtonsPart2(PlayState* play) { } } else if (GET_CUR_FORM_BTN_ITEM(i) == ITEM_MASK_FIERCE_DEITY) { // Fierce Deity's Mask is equipped - if ((play->sceneId != SCENE_MITURIN_BS) && (play->sceneId != SCENE_HAKUGIN_BS) && + // @recomp_use_export_var fd_anywhere: Allow the player to use the Fierce Deity's Mask anywhere if mods enable it. + if (!fd_anywhere && (play->sceneId != SCENE_MITURIN_BS) && (play->sceneId != SCENE_HAKUGIN_BS) && (play->sceneId != SCENE_SEA_BS) && (play->sceneId != SCENE_INISIE_BS) && (play->sceneId != SCENE_LAST_BS)) { if (BUTTON_STATUS(i) != BTN_DISABLED) {