diff --git a/mods/randomizer/src/hooks.cpp b/mods/randomizer/src/hooks.cpp index 3c1725e60f..68f74ff70a 100644 --- a/mods/randomizer/src/hooks.cpp +++ b/mods/randomizer/src/hooks.cpp @@ -54,15 +54,20 @@ #include "d/d_item.h" #include "f_op/f_op_overlap_mng.h" #include "m_Do/m_Do_Reset.h" +#include "Z2AudioLib/Z2SceneMgr.h" DEFINE_HOOK(&dFile_select_c::selectDataNameMove, dFile_select_c__selectDataNameMove); DEFINE_HOOK(&dFile_select_c::dataSelect, dFile_select_c__dataSelect); DEFINE_HOOK(&dFile_info_c::setSaveData, dFile_info_c__setSaveData); +DEFINE_HOOK(&Z2SceneMgr::setSceneName, Z2SceneMgr__setSceneName); + DEFINE_HOOK(&dSv_event_c::isEventBit, dSv_event_c__isEventBit); DEFINE_HOOK(&dSv_event_c::onEventBit, dSv_event_c__onEventBit); +DEFINE_HOOK(&dComIfGs_isStageSwitch, isStageSwitch); + DEFINE_HOOK(&dSv_memBit_c::isSwitch, dSv_memBit_c__isSwitch); DEFINE_HOOK(&dSv_memBit_c::onSwitch, dSv_memBit_c__onSwitch); DEFINE_HOOK(&dSv_memBit_c::onDungeonItem, dSv_memBit_c__onDungeonItem); @@ -276,10 +281,37 @@ void hookPostSetSaveData(ModContext* ctx, void* args, void* retval, void* userda } } +bool isInZ2SceneMgrSetSceneName = false; +HookAction hookPreZ2SceneMgrSetSceneName(ModContext*, void* args, void* retval, void* userdata) { + isInZ2SceneMgrSetSceneName = true; + return HOOK_CONTINUE; +} + +void hookPostZ2SceneMgrSetSceneName(ModContext*, void* args, void* retval, void* userdata) { + isInZ2SceneMgrSetSceneName = false; +} + HookAction hookPreIsEventBit(ModContext*, void* args, void* retval, void*) { const u16 i_no = mods::arg(args, 1); auto& out = *static_cast(retval); + // Special checks when the game is setting up boss room audio in Z2SceneMgr::setSceneName + if (isInZ2SceneMgrSetSceneName) { + switch (i_no) { + case FOREST_TEMPLE_CLEARED: + case LAKEBED_TEMPLE_CLEARED: + case ARBITERS_GROUNDS_CLEARED: + case TEMPLE_OF_TIME_CLEARED: + // If we're setting up audio, return whether the boss is defeated rather than if we've + // completed the temple. Otherwise, we won't get the boss music depending on some + // randomizer settings. + out = dComIfGs_isStageBossEnemy(); + return HOOK_SKIP_ORIGINAL; + default: + break; + } + } + switch (i_no) { case BO_TALKED_TO_YOU_AFTER_OPENING_IRON_BOOTS_CHEST: { if (daAlink_c::checkStageName(allStages[Ordon_Village_Interiors])) { @@ -449,6 +481,24 @@ HookAction hookPreOnEventBit(ModContext*, void* args, void*, void*) { return HOOK_CONTINUE; } +HookAction hookPreIsStageSwitch(ModContext*, void* args, void* retval, void*) { + auto i_stageNo = mods::arg(args, 0); + auto i_no = mods::arg(args, 1); + auto& out = *static_cast(retval); + + // Special checks when the game is setting up boss room audio in Z2SceneMgr::setSceneName + if (isInZ2SceneMgrSetSceneName && + ((i_stageNo == 4 && i_no == 0xE) || // Lakebed Temple Boss + (i_stageNo == 0xA && i_no == 0xA) || // Arbiters Grounds Boss + (i_stageNo == 7 && i_no == 0x18))) // Temple of Time Boss + { + out = dComIfGs_isStageBossEnemy(); + return HOOK_SKIP_ORIGINAL; + } + + return HOOK_CONTINUE; +} + HookAction hookPreMembitIsSwitch(ModContext*, void* args, void* retval, void*) { if (getStageID() == Hidden_Village_Interiors) { if (mods::arg(args, 1) == 0x61) { // Is Impaz in her house @@ -3051,9 +3101,14 @@ ModResult initialize() { ADD_HOOK_POST(dFile_info_c__setSaveData, hookPostSetSaveData); + ADD_HOOK_PRE(Z2SceneMgr__setSceneName, hookPreZ2SceneMgrSetSceneName); + ADD_HOOK_POST(Z2SceneMgr__setSceneName, hookPostZ2SceneMgrSetSceneName); + ADD_HOOK_PRE(dSv_event_c__isEventBit, hookPreIsEventBit); ADD_HOOK_PRE(dSv_event_c__onEventBit, hookPreOnEventBit); + ADD_HOOK_PRE(isStageSwitch, hookPreIsStageSwitch); + ADD_HOOK_PRE(dSv_memBit_c__isSwitch, hookPreMembitIsSwitch); ADD_HOOK_PRE(dSv_memBit_c__onSwitch, hookPreMembitOnSwitch); ADD_HOOK_PRE(dSv_memBit_c__onDungeonItem, hookPreOnDungeonItem); @@ -3194,9 +3249,13 @@ ModResult uninstall() { mods::hook::uninstall(svc_hook); + mods::hook::uninstall(svc_hook); + mods::hook::uninstall(svc_hook); mods::hook::uninstall(svc_hook); + mods::hook::uninstall(svc_hook); + mods::hook::uninstall(svc_hook); mods::hook::uninstall(svc_hook); mods::hook::uninstall(svc_hook);