Various hooks to support anchor (#5929)

This commit is contained in:
Garrett Cox
2025-11-08 15:51:09 -06:00
committed by GitHub
parent 66a9c7a218
commit 8073f96856
14 changed files with 114 additions and 16 deletions

View File

@@ -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));

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -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();
}

View File

@@ -120,6 +120,7 @@ std::vector<std::string> sceneNames = {
"Castle Hedge Maze (Early)",
"Sasa Test",
"Treasure Chest Room",
"Unknown",
};
std::vector<std::string> itemNamesEng = {

View File

@@ -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);
}

View File

@@ -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)) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 &&