diff --git a/soh/soh/Enhancements/TimeSavers/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/TimeSavers/timesaver_hook_handlers.cpp index 4a1fcfa851..624becd8a8 100644 --- a/soh/soh/Enhancements/TimeSavers/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/TimeSavers/timesaver_hook_handlers.cpp @@ -31,6 +31,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h" #include "src/overlays/actors/ovl_Obj_Lightswitch/z_obj_lightswitch.h" #include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.h" +#include "src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.h" #include #include #include @@ -919,6 +920,8 @@ static uint32_t bgSpot03UpdateHook = 0; static uint32_t bgSpot03KillHook = 0; static uint32_t enPoSistersUpdateHook = 0; static uint32_t enPoSistersKillHook = 0; +static uint32_t enBigokutaUpdateHook = 0; +static uint32_t enBigokutaKillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); @@ -1145,6 +1148,38 @@ void TimeSaverOnActorInitHandler(void* actorRef) { Actor_Kill(actor); } } + + // Prevent softlock from pre-battle early hit on Bigocto (possible by cutscene skip) + if (actor->id == ACTOR_EN_BIGOKUTA) { + enBigokutaUpdateHook = + GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_BIGOKUTA && + (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) { + EnBigokuta* enBigokuta = static_cast(innerActorRef); + if (enBigokuta->actor.params == 2) { // Platform already active + GameInteractor::Instance->UnregisterGameHook( + enBigokutaUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enBigokutaKillHook); + enBigokutaUpdateHook = 0; + enBigokutaKillHook = 0; + // Possible action functions after taken damage + } else if (enBigokuta->actionFunc == func_809BE058 || enBigokuta->actionFunc == func_809BDF34 || + enBigokuta->actionFunc == func_809BE180) { + enBigokuta->actor.home.pos.y = enBigokuta->actor.world.pos.y = -1025.0f; + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, &enBigokuta->actor, ACTORCAT_ENEMY); + enBigokuta->actor.params = 2; // Activate platform + } + } + }); + enBigokutaKillHook = + GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enBigokutaUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enBigokutaKillHook); + enBigokutaUpdateHook = 0; + enBigokutaKillHook = 0; + }); + } } void TimeSaverOnSceneInitHandler(int16_t sceneNum) { diff --git a/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.h b/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.h index 83e0d12e9f..4748a8ea72 100644 --- a/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.h +++ b/soh/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.h @@ -24,4 +24,8 @@ typedef struct EnBigokuta { /* 0x02EC */ ColliderCylinder cylinder[2]; } EnBigokuta; // size = 0x0384 +void func_809BE058(EnBigokuta*, PlayState*); +void func_809BDF34(EnBigokuta*, PlayState*); +void func_809BE180(EnBigokuta*, PlayState*); + #endif