summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Cox <garrettjcox@gmail.com>2025-11-08 15:51:09 -0600
committerGitHub <noreply@github.com>2025-11-08 15:51:09 -0600
commit8073f9685611222c180e1407c0bd9612981e4150 (patch)
tree03a327c5ded705dc34013f14456e428ed71ab34a
parent66a9c7a218e5ec8ba94c48a3c89282b8780f1efc (diff)
Various hooks to support anchor (#5929)
-rw-r--r--soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h11
-rw-r--r--soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp36
-rw-r--r--soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h9
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h17
-rw-r--r--soh/soh/Enhancements/randomizer/item_location.cpp2
-rw-r--r--soh/soh/Enhancements/randomizer/randomizer_entrance.c3
-rw-r--r--soh/soh/SaveManager.cpp2
-rw-r--r--soh/soh/util.cpp1
-rw-r--r--soh/src/code/z_actor.c34
-rw-r--r--soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c7
-rw-r--r--soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c4
-rw-r--r--soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c2
-rw-r--r--soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c1
-rw-r--r--soh/src/overlays/actors/ovl_En_Door/z_en_door.c1
14 files changed, 114 insertions, 16 deletions
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h
index 0f694660c..30aa16a2a 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h
@@ -23,11 +23,15 @@ DEFINE_HOOK(OnFlagUnset, (int16_t flagType, int16_t flag));
DEFINE_HOOK(OnSceneSpawnActors, ());
DEFINE_HOOK(OnPlayerUpdate, ());
DEFINE_HOOK(OnSetDoAction, (uint16_t action));
+DEFINE_HOOK(OnPlayerSfx, (u16 sfxId));
DEFINE_HOOK(OnOcarinaSongAction, ());
DEFINE_HOOK(OnCuccoOrChickenHatch, ());
DEFINE_HOOK(OnShopSlotChange, (uint8_t cursorIndex, int16_t price));
+DEFINE_HOOK(OnDungeonKeyUsed, (uint16_t mapIndex));
+DEFINE_HOOK(ShouldActorInit, (void* actor, bool* result));
DEFINE_HOOK(OnActorInit, (void* actor));
DEFINE_HOOK(OnActorSpawn, (void* actor));
+DEFINE_HOOK(ShouldActorUpdate, (void* actor, bool* result));
DEFINE_HOOK(OnActorUpdate, (void* actor));
DEFINE_HOOK(OnActorKill, (void* actor));
DEFINE_HOOK(OnActorDestroy, (void* actor));
@@ -45,7 +49,7 @@ DEFINE_HOOK(OnPlayDestroy, ());
DEFINE_HOOK(OnPlayDrawBegin, ());
DEFINE_HOOK(OnPlayDrawEnd, ());
DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs));
-DEFINE_HOOK(OnSaveFile, (int32_t fileNum));
+DEFINE_HOOK(OnSaveFile, (int32_t fileNum, int32_t sectionID));
DEFINE_HOOK(OnLoadFile, (int32_t fileNum));
DEFINE_HOOK(OnDeleteFile, (int32_t fileNum));
@@ -77,3 +81,8 @@ DEFINE_HOOK(OnKaleidoUpdate, ());
// Audio
DEFINE_HOOK(OnSeqPlayerInit, (int32_t playerIdx, int32_t seqId));
+
+// Rando
+DEFINE_HOOK(OnRandoSetCheckStatus, (RandomizerCheck rc, RandomizerCheckStatus status));
+DEFINE_HOOK(OnRandoSetIsSkipped, (RandomizerCheck rc, bool isSkipped));
+DEFINE_HOOK(OnRandoEntranceDiscovered, (u16 entranceIndex, u8 isReversedEntrance));
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
index 7d5a243d2..fda2e4709 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
@@ -89,6 +89,10 @@ void GameInteractor_ExecuteOnSetDoAction(uint16_t action) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetDoAction>(action);
}
+void GameInteractor_ExecuteOnPlayerSfx(u16 sfxId) {
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerSfx>(sfxId);
+}
+
void GameInteractor_ExecuteOnOcarinaSongAction() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnOcarinaSongAction>();
}
@@ -101,6 +105,19 @@ void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t pr
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnShopSlotChange>(cursorIndex, price);
}
+void GameInteractor_ExecuteOnDungeonKeyUsedHooks(uint16_t mapIndex) {
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnDungeonKeyUsed>(mapIndex);
+}
+
+bool GameInteractor_ShouldActorInit(void* actor) {
+ bool result = true;
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::ShouldActorInit>(actor, &result);
+ GameInteractor::Instance->ExecuteHooksForID<GameInteractor::ShouldActorInit>(((Actor*)actor)->id, actor, &result);
+ GameInteractor::Instance->ExecuteHooksForPtr<GameInteractor::ShouldActorInit>((uintptr_t)actor, actor, &result);
+ GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::ShouldActorInit>(actor, &result);
+ return result;
+}
+
void GameInteractor_ExecuteOnActorInit(void* actor) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorInit>(actor);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorInit>(((Actor*)actor)->id, actor);
@@ -115,6 +132,15 @@ void GameInteractor_ExecuteOnActorSpawn(void* actor) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorSpawn>(actor);
}
+bool GameInteractor_ShouldActorUpdate(void* actor) {
+ bool result = true;
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::ShouldActorUpdate>(actor, &result);
+ GameInteractor::Instance->ExecuteHooksForID<GameInteractor::ShouldActorUpdate>(((Actor*)actor)->id, actor, &result);
+ GameInteractor::Instance->ExecuteHooksForPtr<GameInteractor::ShouldActorUpdate>((uintptr_t)actor, actor, &result);
+ GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::ShouldActorUpdate>(actor, &result);
+ return result;
+}
+
void GameInteractor_ExecuteOnActorUpdate(void* actor) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnActorUpdate>(actor);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnActorUpdate>(((Actor*)actor)->id, actor);
@@ -217,8 +243,8 @@ bool GameInteractor_Should(GIVanillaBehavior flag, u32 result, ...) {
// MARK: - Save Files
-void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {
- GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
+void GameInteractor_ExecuteOnSaveFile(int32_t fileNum, int32_t sectionID) {
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum, sectionID);
}
void GameInteractor_ExecuteOnLoadFile(int32_t fileNum) {
@@ -332,3 +358,9 @@ void GameInteractor_ExecuteOnKaleidoUpdate() {
void GameInteractor_ExecuteOnSeqPlayerInit(int32_t playerIdx, int32_t seqId) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSeqPlayerInit>(playerIdx, seqId);
}
+
+// MARK: - Rando
+void GameInteractor_ExecuteOnRandoEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) {
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnRandoEntranceDiscovered>(entranceIndex,
+ isReversedEntrance);
+}
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
index 4c3a600e7..b39513195 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
@@ -26,10 +26,13 @@ void GameInteractor_ExecuteOnFlagUnset(int16_t flagType, int16_t flag);
void GameInteractor_ExecuteOnSceneSpawnActors();
void GameInteractor_ExecuteOnPlayerUpdate();
void GameInteractor_ExecuteOnSetDoAction(uint16_t action);
+void GameInteractor_ExecuteOnPlayerSfx(u16 sfxId);
void GameInteractor_ExecuteOnOcarinaSongAction();
void GameInteractor_ExecuteOnCuccoOrChickenHatch();
+bool GameInteractor_ShouldActorInit(void* actor);
void GameInteractor_ExecuteOnActorInit(void* actor);
void GameInteractor_ExecuteOnActorSpawn(void* actor);
+bool GameInteractor_ShouldActorUpdate(void* actor);
void GameInteractor_ExecuteOnActorUpdate(void* actor);
void GameInteractor_ExecuteOnActorKill(void* actor);
void GameInteractor_ExecuteOnActorDestroy(void* actor);
@@ -44,13 +47,14 @@ void GameInteractor_ExecuteOnPlayerFirstPersonControl(Player* player);
void GameInteractor_ExecuteOnPlayerShieldControl(float_t* sp50, float_t* sp54);
void GameInteractor_ExecuteOnPlayerProcessStick();
void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price);
+void GameInteractor_ExecuteOnDungeonKeyUsedHooks(uint16_t mapIndex);
void GameInteractor_ExecuteOnPlayDestroy();
void GameInteractor_ExecuteOnPlayDrawBegin();
void GameInteractor_ExecuteOnPlayDrawEnd();
bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...);
// MARK: - Save Files
-void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);
+void GameInteractor_ExecuteOnSaveFile(int32_t fileNum, int32_t sectionID);
void GameInteractor_ExecuteOnLoadFile(int32_t fileNum);
void GameInteractor_ExecuteOnDeleteFile(int32_t fileNum);
@@ -89,6 +93,9 @@ void GameInteractor_ExecuteOnKaleidoUpdate();
// Mark: - Audio
void GameInteractor_ExecuteOnSeqPlayerInit(int32_t playerIdx, int32_t seqId);
+// MARK: - Rando
+void GameInteractor_ExecuteOnRandoEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance);
+
#ifdef __cplusplus
}
#endif
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index 08d663c7e..fe437907a 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -2318,6 +2318,23 @@ typedef enum {
// - `*Player`
VB_SET_STATIC_FLOOR_TYPE,
+ // #### `result`
+ // ```c
+ // (this->collider.base.acFlags & AC_HIT) && !Player_InCsMode(play) &&
+ // (player->meleeWeaponAnimation == 22 || player->meleeWeaponAnimation == 23)
+ // ```
+ // #### `args`
+ // - `*BgHidanDalm`
+ VB_HAMMER_TOTEM_BREAK,
+
+ // #### `result`
+ // ```c
+ // Actor_GetCollidedExplosive(play, &this->collider.base) != NULL
+ // ```
+ // #### `args`
+ // - `*BgHidanKowarerukabe`
+ VB_FIRE_TEMPLE_BOMBABLE_WALL_BREAK,
+
} GIVanillaBehavior;
#endif
diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp
index f7587ec5e..b5325c604 100644
--- a/soh/soh/Enhancements/randomizer/item_location.cpp
+++ b/soh/soh/Enhancements/randomizer/item_location.cpp
@@ -134,6 +134,7 @@ bool ItemLocation::HasObtained() const {
void ItemLocation::SetCheckStatus(RandomizerCheckStatus status_) {
status = status_;
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnRandoSetCheckStatus>(rc, status);
}
RandomizerCheckStatus ItemLocation::GetCheckStatus() {
@@ -142,6 +143,7 @@ RandomizerCheckStatus ItemLocation::GetCheckStatus() {
void ItemLocation::SetIsSkipped(bool isSkipped_) {
isSkipped = isSkipped_;
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnRandoSetIsSkipped>(rc, isSkipped);
}
bool ItemLocation::GetIsSkipped() {
diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c
index 36e5dd983..82082a9d0 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c
+++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c
@@ -16,6 +16,7 @@
#include "global.h"
#include "entrance.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
extern PlayState* gPlayState;
@@ -812,6 +813,8 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) {
return;
}
+ GameInteractor_ExecuteOnRandoEntranceDiscovered(entranceIndex, isReversedEntrance);
+
u16 bitsPerIndex = sizeof(u32) * 8;
u32 idx = entranceIndex / bitsPerIndex;
if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) {
diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp
index d15c01086..c17ab0a54 100644
--- a/soh/soh/SaveManager.cpp
+++ b/soh/soh/SaveManager.cpp
@@ -1069,7 +1069,7 @@ void SaveManager::SaveFileThreaded(int fileNum, SaveContext* saveContext, int se
delete saveContext;
InitMeta(fileNum);
- GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum);
+ GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveFile>(fileNum, sectionID);
SPDLOG_INFO("Save File Finish - fileNum: {}", fileNum);
saveMtx.unlock();
}
diff --git a/soh/soh/util.cpp b/soh/soh/util.cpp
index c05f03f0c..159ccfbe2 100644
--- a/soh/soh/util.cpp
+++ b/soh/soh/util.cpp
@@ -120,6 +120,7 @@ std::vector<std::string> sceneNames = {
"Castle Hedge Maze (Early)",
"Sasa Test",
"Treasure Chest Room",
+ "Unknown",
};
std::vector<std::string> itemNamesEng = {
diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c
index d8263f5de..d1386a48a 100644
--- a/soh/src/code/z_actor.c
+++ b/soh/src/code/z_actor.c
@@ -1256,10 +1256,16 @@ void Actor_Init(Actor* actor, PlayState* play) {
ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f);
if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
Actor_SetObjectDependency(play, actor);
- actor->init(actor, play);
- actor->init = NULL;
- GameInteractor_ExecuteOnActorInit(actor);
+ if (GameInteractor_ShouldActorInit(actor)) {
+ actor->init(actor, play);
+ actor->init = NULL;
+
+ GameInteractor_ExecuteOnActorInit(actor);
+ } else {
+ actor->init = NULL;
+ Actor_Kill(actor);
+ }
}
}
@@ -2244,6 +2250,10 @@ void Player_PlaySfx(Actor* actor, u16 sfxId) {
Audio_PlaySoundGeneral(sfxId, &actor->projectedPos, 4, &freqMultiplier, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultReverb);
}
+
+ if (actor->id == ACTOR_PLAYER) {
+ GameInteractor_ExecuteOnPlayerSfx(sfxId);
+ }
}
void Audio_PlayActorSound2(Actor* actor, u16 sfxId) {
@@ -2624,10 +2634,16 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
if (actor->init != NULL) {
if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
Actor_SetObjectDependency(play, actor);
- actor->init(actor, play);
- actor->init = NULL;
- GameInteractor_ExecuteOnActorInit(actor);
+ if (GameInteractor_ShouldActorInit(actor)) {
+ actor->init(actor, play);
+ actor->init = NULL;
+
+ GameInteractor_ExecuteOnActorInit(actor);
+ } else {
+ actor->init = NULL;
+ Actor_Kill(actor);
+ }
}
actor = actor->next;
} else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
@@ -2670,8 +2686,10 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
if (actor->colorFilterTimer != 0) {
actor->colorFilterTimer--;
}
- actor->update(actor, play);
- GameInteractor_ExecuteOnActorUpdate(actor);
+ if (GameInteractor_ShouldActorUpdate(actor)) {
+ actor->update(actor, play);
+ GameInteractor_ExecuteOnActorUpdate(actor);
+ }
func_8003F8EC(play, &play->colCtx.dyna, actor);
}
diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c
index 725bfacd6..b4e3ca3c3 100644
--- a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c
+++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c
@@ -6,6 +6,7 @@
#include "z_bg_hidan_dalm.h"
#include "objects/object_hidan_objects/object_hidan_objects.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0
@@ -126,8 +127,10 @@ void BgHidanDalm_Destroy(Actor* thisx, PlayState* play) {
void BgHidanDalm_Wait(BgHidanDalm* this, PlayState* play) {
Player* player = GET_PLAYER(play);
- if ((this->collider.base.acFlags & AC_HIT) && !Player_InCsMode(play) &&
- (player->meleeWeaponAnimation == 22 || player->meleeWeaponAnimation == 23)) {
+ if (GameInteractor_Should(VB_HAMMER_TOTEM_BREAK,
+ (this->collider.base.acFlags & AC_HIT) && !Player_InCsMode(play) &&
+ (player->meleeWeaponAnimation == 22 || player->meleeWeaponAnimation == 23),
+ this)) {
this->collider.base.acFlags &= ~AC_HIT;
if ((this->collider.elements[0].info.bumperFlags & BUMP_HIT) ||
(this->collider.elements[1].info.bumperFlags & BUMP_HIT)) {
diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c
index 328d1f4c0..0625c6ab8 100644
--- a/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c
+++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Kowarerukabe/z_bg_hidan_kowarerukabe.c
@@ -8,6 +8,7 @@
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
#include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h"
#include "objects/object_hidan_objects/object_hidan_objects.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0
@@ -303,7 +304,8 @@ void BgHidanKowarerukabe_Update(Actor* thisx, PlayState* play) {
BgHidanKowarerukabe* this = (BgHidanKowarerukabe*)thisx;
s32 pad;
- if (Actor_GetCollidedExplosive(play, &this->collider.base) != NULL) {
+ if (GameInteractor_Should(VB_FIRE_TEMPLE_BOMBABLE_WALL_BREAK,
+ Actor_GetCollidedExplosive(play, &this->collider.base) != NULL, this)) {
BgHidanKowarerukabe_Break(this, play);
Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
diff --git a/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c b/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c
index 34796f980..29eccfdd7 100644
--- a/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c
+++ b/soh/src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.c
@@ -6,6 +6,7 @@
#include "z_door_gerudo.h"
#include "objects/object_door_gerudo/object_door_gerudo.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS 0
@@ -103,6 +104,7 @@ void func_8099485C(DoorGerudo* this, PlayState* play) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] -= 1;
Flags_SetSwitch(play, this->dyna.actor.params & 0x3F);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK);
+ GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex);
} else {
s32 direction = func_80994750(this, play);
diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
index ea983771f..307aee785 100644
--- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
+++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
@@ -391,6 +391,7 @@ void func_80996B0C(DoorShutter* this, PlayState* play) {
if (this->doorType != SHUTTER_BOSS) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--;
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK);
+ GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex);
} else {
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK_B);
}
diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
index e714cb211..268355094 100644
--- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
+++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
@@ -209,6 +209,7 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) {
Flags_SetSwitch(play, this->actor.params & 0x3F);
}
Audio_PlayActorSound2(&this->actor, NA_SE_EV_CHAIN_KEY_UNLOCK);
+ GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex);
}
} else if (!Player_InCsMode(play)) {
if (fabsf(playerPosRelToDoor.y) < 20.0f && fabsf(playerPosRelToDoor.x) < 20.0f &&