From 1b6508556d65392fdc84d7fb10770081fe8ccd87 Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Fri, 3 Jan 2025 02:16:03 -0500 Subject: [PATCH] Fix Broken Giant's Knife flag not resetting (#4608) * Fix Broken Giant's Knife flag not resetting * Force setting on in rando * Fix flag when checkbox is toggled --- soh/soh/Enhancements/mods.cpp | 37 +++++++++++++++++++++++++++++++++++ soh/soh/SohMenuBar.cpp | 19 ++++++++++++++++-- soh/src/code/z_parameter.c | 6 +----- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 0c11c79b2..0c42ebe1d 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -775,6 +775,42 @@ void RegisterResetNaviTimer() { }); } +void RegisterBrokenGiantsKnifeFix() { + GameInteractor::Instance->RegisterGameHook([](GetItemEntry itemEntry) { + if (itemEntry.itemId != ITEM_SWORD_BGS) { + return; + } + + int32_t bypassEquipmentChecks = 0; + + if (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("FixBrokenGiantsKnife"), 0)) { + // Flag wasn't reset because Kokiri or Master Sword was missing, so we need to + // bypass those checks + bypassEquipmentChecks |= (1 << EQUIP_INV_SWORD_KOKIRI) | (1 << EQUIP_INV_SWORD_MASTER); + } else { + // If enhancement is off, flag should be handled exclusively by vanilla behaviour + return; + } + + int32_t allSwordsInEquipment = bypassEquipmentChecks | ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD); + int32_t allSwordFlags = (1 << EQUIP_INV_SWORD_KOKIRI) | (1 << EQUIP_INV_SWORD_MASTER) | + (1 << EQUIP_INV_SWORD_BIGGORON) | (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE); + + if (allSwordsInEquipment != allSwordFlags) { + return; + } + + gSaveContext.inventory.equipment ^= OWNED_EQUIP_FLAG_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE); + + if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; + if (gPlayState != NULL) { + Interface_LoadItemIcon1(gPlayState, 0); + } + } + }); +} + //this map is used for enemies that can be uniquely identified by their id //and that are always counted //enemies that can't be uniquely identified by their id @@ -1429,6 +1465,7 @@ void InitMods() { RegisterMenuPathFix(); RegisterMirrorModeHandler(); RegisterResetNaviTimer(); + RegisterBrokenGiantsKnifeFix(); RegisterEnemyDefeatCounts(); RegisterBossDefeatTimestamps(); RegisterAltTrapTypes(); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c49895421..346838190 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -14,6 +14,8 @@ #include "z64.h" #include "cvar_prefixes.h" #include "macros.h" +#include "functions.h" +#include "variables.h" #include "Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/presets.h" #include "soh/Enhancements/mods.h" @@ -1523,10 +1525,23 @@ void DrawEnhancementsMenu() { "This will lower them, making activating them easier"); UIWidgets::PaddedEnhancementCheckbox("Fix Zora hint dialogue", CVAR_ENHANCEMENT("FixZoraHintDialogue"), true, false); UIWidgets::Tooltip("Fixes one Zora's dialogue giving a hint about bringing Ruto's Letter to King Zora to properly occur before moving King Zora rather than after"); - if (UIWidgets::PaddedEnhancementCheckbox("Fix hand holding Hammer", "gEnhancements.FixHammerHand", true, false)) { + if (UIWidgets::PaddedEnhancementCheckbox("Fix hand holding Hammer", CVAR_ENHANCEMENT("FixHammerHand"), true, false)) { UpdatePatchHand(); } - UIWidgets::Tooltip("Fixes Adult Link have a backwards left hand when holding the Megaton Hammer."); + UIWidgets::Tooltip("Fixes Adult Link having a backwards left hand when holding the Megaton Hammer."); + if (UIWidgets::PaddedEnhancementCheckbox( + "Fix Broken Giant's Knife bug", CVAR_ENHANCEMENT("FixBrokenGiantsKnife"), true, false, IS_RANDO, + "This setting is forcefully enabled when you are playing a randomizer.", + UIWidgets::CheckboxGraphics::Checkmark)) { + bool hasGiantsKnife = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON); + bool hasBrokenKnife = CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE); + bool knifeIsBroken = gSaveContext.swordHealth == 0.0f; + + if (hasGiantsKnife && (hasBrokenKnife != knifeIsBroken)) { + func_800849EC(gPlayState); + } + } + UIWidgets::Tooltip("Fixes the Broken Giant's Knife flag not being reset when Medigoron fixes it"); ImGui::EndMenu(); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index d2c3e1a26..396188b48 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1987,13 +1987,9 @@ u8 Item_Give(PlayState* play, u8 item) { if (item == ITEM_SWORD_BGS) { gSaveContext.swordHealth = 8; - // In rando, when buying Giant's Knife, also check - // without the Koriri Sword in case we don't have it if (ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == ((1 << EQUIP_INV_SWORD_KOKIRI) | (1 << EQUIP_INV_SWORD_MASTER) | (1 << EQUIP_INV_SWORD_BIGGORON) | - (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)) || - (IS_RANDO && ALL_EQUIP_VALUE(EQUIP_TYPE_SWORD) == - ((1 << EQUIP_INV_SWORD_MASTER) | (1 << EQUIP_INV_SWORD_BIGGORON) | (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE)))) { + (1 << EQUIP_INV_SWORD_BROKENGIANTKNIFE))) { gSaveContext.inventory.equipment ^= OWNED_EQUIP_FLAG_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE);