diff --git a/mm/2s2h/BenGui/BenMenu.cpp b/mm/2s2h/BenGui/BenMenu.cpp index 6c083b3986..f0eb465eca 100644 --- a/mm/2s2h/BenGui/BenMenu.cpp +++ b/mm/2s2h/BenGui/BenMenu.cpp @@ -1149,6 +1149,9 @@ void BenMenu::AddEnhancements() { .CVar("gEnhancements.Cutscenes.SkipMiscInteractions") .Options(CheckboxOptions().Tooltip( "Disclaimer: This doesn't do much yet, we will be progressively adding more skips over time.")); + AddWidget(path, "Skip Enemy Cutscenes", WIDGET_CVAR_CHECKBOX) + .CVar("gEnhancements.Cutscenes.SkipEnemyCutscenes") + .Options(CheckboxOptions().Tooltip("Skips cutscenes specific to enemies and boss battles.")); AddWidget(path, "Skip Item Get Cutscene", WIDGET_CVAR_COMBOBOX) .CVar("gEnhancements.Cutscenes.SkipGetItemCutscenes") .Options(ComboboxOptions() diff --git a/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipBossCutscenes.cpp b/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipBossCutscenes.cpp deleted file mode 100644 index a66cecb128..0000000000 --- a/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipBossCutscenes.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include "2s2h/GameInteractor/GameInteractor.h" -#include "2s2h/ShipInit.hpp" - -extern "C" { -#include "variables.h" -#include "functions.h" -} - -#define CVAR_NAME "gEnhancements.Cutscenes.SkipStoryCutscenes" -#define CVAR CVarGetInteger(CVAR_NAME, 0) - -// TODO: Handle other bosses like Majora -void RegisterSkipBossCutscenes() { - // Odolwa intro - COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_01, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_54); }); - - // Goht intro - COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_HAKUGIN, CVAR, [](Actor* actor, bool* should) { - /* - * EVENTINF_62 gets set after seeing the boss lair intro cutscene. - * EVENTINF_53 gets set after melting the ice (not skipped here, as that would skip the ice melting - * requirement). - */ - SET_EVENTINF(EVENTINF_62); - }); - - // Gyorg intro - COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_03, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_56); }); - - // Twinmold intro - COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_02, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_55); }); - - // Igos du Ikana (and lackeys) intro - COND_ID_HOOK(ShouldActorInit, ACTOR_EN_KNIGHT, CVAR, [](Actor* actor, bool* should) { - // In the credits, this sceneLayer will 1. Do not set this flag in that case, or things will break. - if (gSaveContext.sceneLayer == 0) { - SET_EVENTINF(EVENTINF_57); - } - }); - - COND_VB_SHOULD(VB_START_CUTSCENE, CVAR, { - s16* csId = va_arg(args, s16*); - switch (gPlayState->sceneId) { - case SCENE_MITURIN_BS: // Odolwa's Lair - if (*csId == 9) { // Warping out - *should = false; - } - break; - case SCENE_MITURIN: // Woodfall Temple - if (*csId == 34) { // Cleared vines to room Deku Princess is in - *should = false; - } - break; - case SCENE_HAKUGIN_BS: // Goht's Lair - if (*csId == 10) { // Warping out - *should = false; - } - break; - case SCENE_10YUKIYAMANOMURA2: // Mountain Village (Spring) - if (*csId == 13) { // Warping from Goht's Lair - *should = false; - } - break; - case SCENE_SEA_BS: // Gyorg's Lair - if (*csId == 9) { // Warping out - *should = false; - } - break; - case SCENE_31MISAKI: // Zora Cape - if (*csId == 18) { // Warping from Gyorg's Lair - *should = false; - } - break; - case SCENE_INISIE_BS: // Twinmold's Lair - if (*csId == 9) { // Warping out - *should = false; - } - break; - case SCENE_IKANA: // Ikana Canyon - if (*csId == 31) { // Warping from Twinmold's Lair - *should = false; - } - break; - default: - break; - } - }); -} - -static RegisterShipInitFunc initFunc(RegisterSkipBossCutscenes, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipEnemyCutscenes.cpp b/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipEnemyCutscenes.cpp new file mode 100644 index 0000000000..6d3e6fd62e --- /dev/null +++ b/mm/2s2h/Enhancements/Cutscenes/StoryCutscenes/SkipEnemyCutscenes.cpp @@ -0,0 +1,290 @@ +#include +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { +#include "variables.h" +#include "functions.h" +#include "overlays/actors/ovl_Boss_06/z_boss_06.h" +#include "overlays/actors/ovl_En_Bigpo/z_en_bigpo.h" +#include "overlays/actors/ovl_En_Bigslime/z_en_bigslime.h" +#include "overlays/actors/ovl_En_Death/z_en_death.h" +#include "overlays/actors/ovl_En_Jso2/z_en_jso2.h" +#include "overlays/actors/ovl_En_Kaizoku/z_en_kaizoku.h" +#include "overlays/actors/ovl_En_Knight/z_en_knight.h" +#include "overlays/actors/ovl_En_Wiz/z_en_wiz.h" +void EnDeath_DeathCutscenePart1(EnDeath* enDeath, PlayState* play); +void EnDeath_SetupDeathCutscenePart2(EnDeath* enDeath, PlayState* play); +void func_809F2EE8(Boss06* boss06, PlayState* play); +void func_809B3E9C(EnKnight* enKnight, PlayState* play); +void EnWiz_SetupDisappear(EnWiz* enWiz); +void EnBigpo_SetupIdleFlying(EnBigpo* enBigpo); +void EnBigpo_DrawMainBigpo(Actor* actor, PlayState* play); +void EnBigslime_CallMinislime(EnBigslime* enBigslime, PlayState* play); +void EnBigslime_GekkoSfxOutsideBigslime(EnBigslime* enBigslime, u16 sfxId); +void func_80B872A4(EnKaizoku* enKaizoku); +void EnKaizoku_Draw(Actor* actor, PlayState* play); +} + +#define CVAR_NAME "gEnhancements.Cutscenes.SkipEnemyCutscenes" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void RegisterSkipEnemyIntros() { + // Odolwa + COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_01, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_54); }); + + // Goht + COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_HAKUGIN, CVAR, [](Actor* actor, bool* should) { + /* + * EVENTINF_62 gets set after seeing the boss lair intro cutscene. + * EVENTINF_53 gets set after melting the ice (not skipped here, as that would skip the ice melting + * requirement). + */ + SET_EVENTINF(EVENTINF_62); + }); + + // Gyorg + COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_03, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_56); }); + + // Twinmold + COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_02, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_55); }); + + // Majora + COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_07, CVAR, + [](Actor* actor, bool* should) { gSaveContext.eventInf[6] |= 2; }); + + // Igos du Ikana (and lackeys) + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_KNIGHT, CVAR, [](Actor* actor, bool* should) { + // In the credits, this sceneLayer will be 1. Do not set this flag in that case, or things will break. + if (gSaveContext.sceneLayer == 0) { + SET_EVENTINF(EVENTINF_57); + } + }); + + // Gomess + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_DEATH, CVAR, + [](Actor* actor, bool* should) { gSaveContext.eventInf[6] |= 8; }); + + // Stone Tower Temple Garo Master + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_JSO2, CVAR, [](Actor* actor, bool* should) { + /* + * Two of the three Garo Masters have no cutscenes, but the one in Stone Tower Temple is special. Its intro and + * death cutscenes can be skipped by simply changing its type to that of a normal Garo Master. + */ + actor->params = EN_JSO2_TYPE_NORMAL; + }); + + // Dinolfos + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_DINOFOS, CVAR, [](Actor* actor, bool* should) { + /* + * The Woodfall Temple and Secret Shrine Dinolfos have intro and death cutscenes, while the two Snowhead Temple + * Dinolfos do not. Simply setting the csId to CS_ID_NONE circumvents the cutscenes entirely, putting the + * Dinolfos into an attack-ready state. + */ + if (actor->csId != CS_ID_NONE) { + actor->csId = CS_ID_NONE; + Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS); + } + }); + + // Wart + COND_ID_HOOK(ShouldActorInit, ACTOR_BOSS_04, CVAR, [](Actor* actor, bool* should) { SET_EVENTINF(EVENTINF_60); }); + + // Big Poe (Beneath the Well) + COND_ID_HOOK(OnActorInit, ACTOR_EN_BIGPO, CVAR, [](Actor* actor) { + // Only do for the well Big Poe. The Dampe one has a brief cutscene where Dampe flees. + if (actor->params == BIG_POE_TYPE_REGULAR) { + EnBigpo* enBigpo = (EnBigpo*)actor; + actor->draw = EnBigpo_DrawMainBigpo; + enBigpo->mainColor.a = 255; + EnBigpo_SetupIdleFlying(enBigpo); + } + }); + + // Gekko + Mad Jelly + COND_ID_HOOK(OnActorInit, ACTOR_EN_BIGSLIME, CVAR, [](Actor* actor) { + EnBigslime* enBigslime = (EnBigslime*)actor; + Animation_MorphToPlayOnce(&enBigslime->skelAnime, (AnimationHeader*)&gGekkoCallAnim, 5.0f); + EnBigslime_GekkoSfxOutsideBigslime(enBigslime, NA_SE_EN_FROG_GREET); + enBigslime->callTimer = 0; + enBigslime->actionFunc = EnBigslime_CallMinislime; + }); + + // Gerudo Pirate + COND_ID_HOOK(OnActorInit, ACTOR_EN_KAIZOKU, CVAR, [](Actor* actor) { + EnKaizoku* enKaizoku = (EnKaizoku*)actor; + enKaizoku->unk_59C = 0; + enKaizoku->picto.actor.flags &= ~ACTOR_FLAG_100000; + enKaizoku->picto.actor.flags &= ~ACTOR_FLAG_CANT_LOCK_ON; + enKaizoku->picto.actor.flags |= ACTOR_FLAG_TARGETABLE; + enKaizoku->picto.actor.draw = EnKaizoku_Draw; + enKaizoku->picto.actor.gravity = -2.0f; + // Swords + enKaizoku->unk_2F8.y = 1.0f; + enKaizoku->unk_2F8.z = 1.0f; + enKaizoku->unk_304.x = 1.0f; + enKaizoku->unk_304.y = 1.0f; + enKaizoku->unk_304.z = 1.0f; + enKaizoku->unk_2D8 = 0; // Flag for updating animation + Audio_SetMainBgmVolume(0x7F, 0); + Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS); + func_80B872A4(enKaizoku); + }); + + // Wizrobe + COND_ID_HOOK(OnActorInit, ACTOR_EN_WIZ, CVAR, [](Actor* actor) { + EnWiz* enWiz = (EnWiz*)actor; + enWiz->introCutsceneState = 6; // EN_WIZ_INTRO_CS_DISAPPEAR + EnWiz_SetupDisappear(enWiz); + if (enWiz->type != EN_WIZ_TYPE_FIRE_NO_BGM) { + Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS); + } + }); +} + +void RegisterSkipBossWarpCutscenes() { + COND_VB_SHOULD(VB_START_CUTSCENE, CVAR, { + s16* csId = va_arg(args, s16*); + switch (gPlayState->sceneId) { + case SCENE_MITURIN_BS: // Odolwa's Lair + if (*csId == 9) { // Warping out + *should = false; + } + break; + case SCENE_MITURIN: // Woodfall Temple + if (*csId == 34) { // Cleared vines to room Deku Princess is in + *should = false; + } + break; + case SCENE_HAKUGIN_BS: // Goht's Lair + if (*csId == 10) { // Warping out + *should = false; + } + break; + case SCENE_10YUKIYAMANOMURA2: // Mountain Village (Spring) + if (*csId == 13) { // Warping from Goht's Lair + *should = false; + } + break; + case SCENE_SEA_BS: // Gyorg's Lair + if (*csId == 9) { // Warping out + *should = false; + } + break; + case SCENE_31MISAKI: // Zora Cape + if (*csId == 18) { // Warping from Gyorg's Lair + *should = false; + } + break; + case SCENE_INISIE_BS: // Twinmold's Lair + if (*csId == 9) { // Warping out + *should = false; + } + break; + case SCENE_IKANA: // Ikana Canyon + if (*csId == 31) { // Warping from Twinmold's Lair + *should = false; + } + break; + default: + break; + } + }); +} + +void RegisterSkipEnemyCutscenes() { + // Enemy actor cutscene starts + COND_VB_SHOULD(VB_START_CUTSCENE, CVAR, { + s16* csId = va_arg(args, s16*); + Actor* actor = va_arg(args, Actor*); + + if (actor == NULL) { + return; + } + + switch (actor->id) { + case ACTOR_EN_BIGSLIME: + case ACTOR_EN_DEATH: + case ACTOR_EN_EGOL: + case ACTOR_EN_GB2: + case ACTOR_EN_IK: + case ACTOR_EN_KAIZOKU: + case ACTOR_EN_PAMETFROG: + *should = false; + break; + default: + break; + } + }); + + // Enemy cutscene actions (camera control, phase changes, etc.) + COND_VB_SHOULD(VB_ENEMY_CUTSCENE_ACTION, CVAR, { + Actor* actor = va_arg(args, Actor*); + switch (actor->id) { + case ACTOR_BOSS_06: { + // Igos du Ikana curtain burning. Just instantly snap to the post-burned state + Boss06* boss06 = (Boss06*)actor; + boss06->unk_1C9 = 2; + boss06->unk_1CA = 0; + boss06->unk_1B4 = 0.0f; + boss06->unk_1B0 = 0.0f; + boss06->unk_144 = 2; + boss06->unk_1A4 = 0.0f; + boss06->unk_1A0 = 0.0f; + boss06->unk_1DC = 18.0f; + boss06->unk_1E0 = 255.0f; + boss06->unk_19C = 1.0f; + Actor_SpawnAsChild(&gPlayState->actorCtx, actor, gPlayState, ACTOR_MIR_RAY2, actor->world.pos.x, + actor->world.pos.y - 200.0f, actor->world.pos.z - 170.0f, 15, 0, 0, 1); + boss06->actionFunc = func_809F2EE8; + *should = false; + } break; + case ACTOR_EN_KNIGHT: { + // Igos du Ikana standing up. Skip the camera locking and just immediately ready him for battle + EnKnight* enKnight = (EnKnight*)actor; + enKnight->unk46C = enKnight->unk470 = 1.0f; // Show sword and shield + enKnight->unk688 = 0; + func_809B3E9C(enKnight, gPlayState); + enKnight->unk14A[2] = 0x12C; + enKnight->unk152 = 1; + enKnight->actor.flags |= 1; + enKnight->actor.gravity = -1.5f; + *should = false; + } break; + case ACTOR_EN_DEATH: { + EnDeath* enDeath = (EnDeath*)actor; + if (enDeath->actionFunc == EnDeath_DeathCutscenePart1) { + // Gomess death. Manually advance the timer, as camera movement is skipped. + if (--enDeath->actionTimer == 0) { + EnDeath_SetupDeathCutscenePart2(enDeath, gPlayState); + } + } + *should = false; + } break; + case ACTOR_EN_WIZ: { + // Start of second phase + EnWiz* enWiz = (EnWiz*)actor; + enWiz->action = 2; // EN_WIZ_ACTION_RUN_BETWEEN_PLATFORMS + enWiz->nextPlatformIndex = 0; + enWiz->platformCount = 0; + enWiz->fightState = 2; // EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE + enWiz->timer = 0; + EnWiz_SetupDisappear(enWiz); + *should = false; + } break; + case ACTOR_EN_BIGSLIME: + case ACTOR_EN_EGOL: + case ACTOR_EN_IK: + case ACTOR_EN_KAIZOKU: + case ACTOR_EN_PAMETFROG: + *should = false; + break; + default: + break; + } + }); +} + +static RegisterShipInitFunc introsInitFunc(RegisterSkipEnemyIntros, { CVAR_NAME }); +static RegisterShipInitFunc bossWarpInitFunc(RegisterSkipBossWarpCutscenes, { CVAR_NAME }); +static RegisterShipInitFunc enemyCsInitFunc(RegisterSkipEnemyCutscenes, { CVAR_NAME }); diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h index d857dee280..74a2432322 100644 --- a/mm/2s2h/GameInteractor/GameInteractor.h +++ b/mm/2s2h/GameInteractor/GameInteractor.h @@ -233,6 +233,7 @@ typedef enum { VB_BUY_GORMAN_MILK, VB_PLAY_LOW_HP_ALARM, VB_PLAY_GORON_CHILD_CRY, + VB_ENEMY_CUTSCENE_ACTION, } GIVanillaBehavior; typedef enum { diff --git a/mm/src/overlays/actors/ovl_Boss_06/z_boss_06.c b/mm/src/overlays/actors/ovl_Boss_06/z_boss_06.c index 1730278a1b..d7994edd3c 100644 --- a/mm/src/overlays/actors/ovl_Boss_06/z_boss_06.c +++ b/mm/src/overlays/actors/ovl_Boss_06/z_boss_06.c @@ -13,6 +13,7 @@ #include "2s2h/BenPort.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20) @@ -182,6 +183,10 @@ void func_809F23CC(Boss06* this) { } void func_809F24A8(Boss06* this) { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + this->actionFunc = func_809F24C8; this->unk_A28 = 0.0f; this->unk_1AC = 0.0f; diff --git a/mm/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c b/mm/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c index 7996b4e430..dbd8c0cf7c 100644 --- a/mm/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c +++ b/mm/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c @@ -12,6 +12,7 @@ #include "objects/object_bigslime/object_bigslime.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/GameInteractor/GameInteractor.h" #include "BenPort.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_200) @@ -819,6 +820,10 @@ void EnBigslime_JerkCameraPlayerHit(EnBigslime* this, PlayState* play) { * then zooms into the Gekko until the Gekko calls the minislimes down from the ceiling */ void EnBigslime_UpdateCameraIntroCs(EnBigslime* this, PlayState* play, s32 noticeTimer) { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + Camera* subCam = Play_GetCamera(play, this->subCamId); Vec3f subCamEye; f32 zoom = (noticeTimer * 19.0f) + 67.0f; @@ -836,6 +841,10 @@ void EnBigslime_UpdateCameraIntroCs(EnBigslime* this, PlayState* play, s32 notic * center of the roof. This is used when the minislimes merges into bigslime. */ void EnBigslime_UpdateCameraFormingBigslime(EnBigslime* this, PlayState* play) { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + Play_SetCameraAtEye(play, this->subCamId, &this->actor.focus.pos, &Play_GetCamera(play, this->subCamId)->eye); } @@ -1009,7 +1018,9 @@ void EnBigslime_CallMinislime(EnBigslime* this, PlayState* play) { EnBigslime_InitFallMinislime(this); play->envCtx.lightSettingOverride = LIGHT_SETTING_OVERRIDE_NONE; this->callTimer = 35; - Player_SetCsActionWithHaltedActors(play, &this->actor, PLAYER_CSACTION_4); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Player_SetCsActionWithHaltedActors(play, &this->actor, PLAYER_CSACTION_4); + } } } @@ -2345,7 +2356,9 @@ void EnBigslime_SetupCutsceneDefeat(EnBigslime* this, PlayState* play) { subCamEye.x = (Math_SinS(yawOffset) * 250.0f) + subCamAt.x; subCamEye.y = subCamAt.y + 60.0f; subCamEye.z = (Math_CosS(yawOffset) * 250.0f) + subCamAt.z; - Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); + } for (i = 0; i < MINISLIME_NUM_SPAWN; i++) { this->minislime[i]->actor.params = MINISLIME_DEFEAT_IDLE; @@ -2368,6 +2381,10 @@ void EnBigslime_CutsceneDefeat(EnBigslime* this, PlayState* play) { EnBigslime_SetupGekkoDespawn(this, play); } else { // Continue for the camera to follow Gekko as it spins in defeat + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + subCam = Play_GetCamera(play, this->subCamId); subCamAt.x = this->actor.world.pos.x; subCamAt.y = this->actor.world.pos.y + 40.0f; @@ -2407,6 +2424,10 @@ void EnBigslime_GekkoDespawn(EnBigslime* this, PlayState* play) { if (this->despawnTimer == 0) { EnBigslime_SetupFrogSpawn(this, play); } else { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + subCam = Play_GetCamera(play, this->subCamId); Math_Vec3f_Copy(&subCamAt, &subCam->at); Math_Vec3f_Diff(&subCam->eye, &this->subCamDistToFrog, &subCamEye); @@ -2469,7 +2490,9 @@ void EnBigslime_FrogSpawn(EnBigslime* this, PlayState* play) { subCamEye.x = subCam->at.x + (this->subCamDistToFrog.x * subCamZoom); subCamEye.z = subCam->at.z + (this->subCamDistToFrog.z * subCamZoom); subCamEye.y = subCam->at.y + (this->subCamDistToFrog.y * subCamZoom); - Play_SetCameraAtEye(play, this->subCamId, &subCam->at, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Play_SetCameraAtEye(play, this->subCamId, &subCam->at, &subCamEye); + } if (this->spawnFrogTimer == 0) { EnBigslime_EndCutscene(this, play); @@ -2544,7 +2567,7 @@ void EnBigslime_PlayCutscene(EnBigslime* this, PlayState* play) { CutsceneManager_Queue(this->csId); } else if (CutsceneManager_IsNext(this->csId)) { CutsceneManager_Start(this->csId, &this->actor); - if (this->actionFuncStored != EnBigslime_SquishFlat) { + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, this->actionFuncStored != EnBigslime_SquishFlat, this)) { Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_WAIT); } diff --git a/mm/src/overlays/actors/ovl_En_Death/z_en_death.c b/mm/src/overlays/actors/ovl_En_Death/z_en_death.c index 3d54872d7a..b1407cc49c 100644 --- a/mm/src/overlays/actors/ovl_En_Death/z_en_death.c +++ b/mm/src/overlays/actors/ovl_En_Death/z_en_death.c @@ -9,6 +9,7 @@ #include "overlays/actors/ovl_Arrow_Light/z_arrow_light.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_IGNORE_QUAKE) @@ -818,10 +819,12 @@ void EnDeath_SetupDeathCutscenePart1(EnDeath* this, PlayState* play) { eye.x = Math_SinS(this->actor.shape.rot.y + 0x900) * 179.0f + this->actor.world.pos.x; eye.z = Math_CosS(this->actor.shape.rot.y + 0x900) * 179.0f + this->actor.world.pos.z; eye.y = this->actor.home.pos.y + 30.0f; - Play_SetCameraAtEye(play, this->camId, &at, &eye); - this->camEyeSpeed = Math_Vec3f_DistXYZ(&eye, &this->camEyeTarget) * 0.05f; - this->actor.shape.rot.y += 0x2000; - Player_SetCsAction(play, &this->actor, 7); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Play_SetCameraAtEye(play, this->camId, &at, &eye); + this->camEyeSpeed = Math_Vec3f_DistXYZ(&eye, &this->camEyeTarget) * 0.05f; + this->actor.shape.rot.y += 0x2000; + Player_SetCsAction(play, &this->actor, 7); + } Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_DEAD); this->actionFunc = EnDeath_DeathCutscenePart1; } @@ -830,7 +833,9 @@ void EnDeath_DeathCutscenePart1(EnDeath* this, PlayState* play) { Camera* camera = Play_GetCamera(play, this->camId); f32 distToTarget = Math_Vec3f_StepTo(&camera->eye, &this->camEyeTarget, this->camEyeSpeed); - Play_SetCameraAtEye(play, this->camId, &camera->at, &camera->eye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Play_SetCameraAtEye(play, this->camId, &camera->at, &camera->eye); + } if (SkelAnime_Update(&this->skelAnime)) { this->actor.shape.rot.y += 0x2000; @@ -874,18 +879,20 @@ void EnDeath_SetupDeathCutscenePart2(EnDeath* this, PlayState* play) { this->actionTimer = 30; player->actor.shape.rot.y = Actor_WorldYawTowardPoint(&player->actor, &this->actor.home.pos) + 0x1000; this->actor.shape.rot.y = player->actor.shape.rot.y + 0x6000; - sinRotY = Math_SinS(player->actor.shape.rot.y); - cosRotY = Math_CosS(player->actor.shape.rot.y); - this->actor.world.pos.x = player->actor.world.pos.x + (260.0f * sinRotY); - this->actor.world.pos.z = player->actor.world.pos.z + (260.0f * cosRotY); - this->actor.world.pos.y = this->actor.home.pos.y + 15.0f; - eye.x = (Math_SinS((s16)(player->actor.shape.rot.y - 0x2500)) * 182.0f) + this->actor.world.pos.x; - eye.z = (Math_CosS((s16)(player->actor.shape.rot.y - 0x2500)) * 182.0f) + this->actor.world.pos.z; - eye.y = this->actor.world.pos.y - 13.0f; - at.x = player->actor.world.pos.x + (120.0f * sinRotY); - at.y = player->actor.world.pos.y + 90.0f; - at.z = player->actor.world.pos.z + (120.0f * cosRotY); - Play_SetCameraAtEye(play, this->camId, &at, &eye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + sinRotY = Math_SinS(player->actor.shape.rot.y); + cosRotY = Math_CosS(player->actor.shape.rot.y); + this->actor.world.pos.x = player->actor.world.pos.x + (260.0f * sinRotY); + this->actor.world.pos.z = player->actor.world.pos.z + (260.0f * cosRotY); + this->actor.world.pos.y = this->actor.home.pos.y + 15.0f; + eye.x = (Math_SinS((s16)(player->actor.shape.rot.y - 0x2500)) * 182.0f) + this->actor.world.pos.x; + eye.z = (Math_CosS((s16)(player->actor.shape.rot.y - 0x2500)) * 182.0f) + this->actor.world.pos.z; + eye.y = this->actor.world.pos.y - 13.0f; + at.x = player->actor.world.pos.x + (120.0f * sinRotY); + at.y = player->actor.world.pos.y + 90.0f; + at.z = player->actor.world.pos.z + (120.0f * cosRotY); + Play_SetCameraAtEye(play, this->camId, &at, &eye); + } lightSettings1 = &play->envCtx.lightSettingsList[20]; lightSettings2 = &play->envCtx.lightSettingsList[21]; diff --git a/mm/src/overlays/actors/ovl_En_Egol/z_en_egol.c b/mm/src/overlays/actors/ovl_En_Egol/z_en_egol.c index ae8021d948..8c778a334a 100644 --- a/mm/src/overlays/actors/ovl_En_Egol/z_en_egol.c +++ b/mm/src/overlays/actors/ovl_En_Egol/z_en_egol.c @@ -13,6 +13,7 @@ #include "overlays/effects/ovl_Effect_Ss_Hitmark/z_eff_ss_hitmark.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_80000000) @@ -1095,8 +1096,10 @@ void EnEgol_Death(EnEgol* this, PlayState* play) { this->subCamEye.y = this->actor.world.pos.y + 70.0f; this->subCamEye.z = this->actor.world.pos.z; Math_ApproachF(&this->subCamFov, this->subCamFovTarget, 0.3f, 10.0f); - Play_SetCameraAtEye(play, this->subCamId, &this->subCamEye, &this->subCamAt); - Play_SetCameraFov(play, this->subCamId, this->subCamFov); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Play_SetCameraAtEye(play, this->subCamId, &this->subCamEye, &this->subCamAt); + Play_SetCameraFov(play, this->subCamId, this->subCamFov); + } if ((this->action == EYEGORE_ACTION_DEAD) && (this->waitTimer == 1)) { if (this->switchFlag > SWITCH_FLAG_NONE) { Flags_SetSwitch(play, this->switchFlag); diff --git a/mm/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/mm/src/overlays/actors/ovl_En_Ik/z_en_ik.c index 7d131273af..41a612ec2b 100644 --- a/mm/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/mm/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -7,6 +7,7 @@ #include "z_en_ik.h" #include "z64rumble.h" #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_400) @@ -646,7 +647,7 @@ void EnIk_SetupReactToAttack(EnIk* this, s32 arg1) { void EnIk_ReactToAttack(EnIk* this, PlayState* play) { Math_StepToF(&this->actor.speed, 0.0f, 1.0f); - if (this->subCamId != SUB_CAM_ID_DONE) { + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, this->subCamId != SUB_CAM_ID_DONE, this)) { Play_SetCameraAtEye(play, this->subCamId, &this->actor.focus.pos, &Play_GetCamera(play, this->subCamId)->eye); } if (SkelAnime_Update(&this->skelAnime)) { @@ -738,11 +739,13 @@ void EnIk_PlayCutscene(EnIk* this, PlayState* play) { if (CutsceneManager_IsNext(this->actor.csId)) { if (this->actor.csId != CS_ID_NONE) { CutsceneManager_StartWithPlayerCsAndSetFlag(this->actor.csId, &this->actor); - this->subCamId = CutsceneManager_GetCurrentSubCamId(this->actor.csId); - subCamEye.x = (Math_SinS((this->actor.shape.rot.y - 0x2000)) * 120.0f) + this->actor.focus.pos.x; - subCamEye.y = this->actor.focus.pos.y + 20.0f; - subCamEye.z = (Math_CosS((this->actor.shape.rot.y - 0x2000)) * 120.0f) + this->actor.focus.pos.z; - Play_SetCameraAtEye(play, this->subCamId, &this->actor.focus.pos, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + this->subCamId = CutsceneManager_GetCurrentSubCamId(this->actor.csId); + subCamEye.x = (Math_SinS((this->actor.shape.rot.y - 0x2000)) * 120.0f) + this->actor.focus.pos.x; + subCamEye.y = this->actor.focus.pos.y + 20.0f; + subCamEye.z = (Math_CosS((this->actor.shape.rot.y - 0x2000)) * 120.0f) + this->actor.focus.pos.z; + Play_SetCameraAtEye(play, this->subCamId, &this->actor.focus.pos, &subCamEye); + } } if (this->actor.colChkInfo.health != 0) { EnIk_SetupReactToAttack(this, false); diff --git a/mm/src/overlays/actors/ovl_En_Kaizoku/z_en_kaizoku.c b/mm/src/overlays/actors/ovl_En_Kaizoku/z_en_kaizoku.c index ebeb68ef1d..fd64ed1f21 100644 --- a/mm/src/overlays/actors/ovl_En_Kaizoku/z_en_kaizoku.c +++ b/mm/src/overlays/actors/ovl_En_Kaizoku/z_en_kaizoku.c @@ -6,6 +6,7 @@ #include "z_en_kaizoku.h" #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_100000) @@ -757,22 +758,24 @@ void func_80B86B74(EnKaizoku* this, PlayState* play) { s32 textId; f32 curFrame = this->skelAnime.curFrame; - if (this->unk_59C < 2) { - Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.yawTowardsPlayer, 1, 0xFA0, 1); - player->actor.world.pos.x = this->picto.actor.home.pos.x + 90.0f; - player->actor.world.pos.z = this->picto.actor.home.pos.z + 30.0f; - this->picto.actor.world.pos.x = this->picto.actor.home.pos.x; - this->picto.actor.world.pos.z = this->picto.actor.home.pos.z; - this->unk_5C8.x = player->actor.world.pos.x + 39.0f; - this->unk_5C8.y = player->actor.world.pos.y + 4.0f; - this->unk_5C8.z = player->actor.world.pos.z - 41.0f; - this->unk_5D4.x = player->actor.world.pos.x - 150.0f; - this->unk_5D4.y = player->actor.world.pos.y + 60.0f; - this->unk_5D4.z = player->actor.world.pos.z + 50.0f; - } - - player->actor.shape.rot.y = player->actor.world.rot.y = - Math_Vec3f_Yaw(&player->actor.world.pos, &this->picto.actor.world.pos); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + if (this->unk_59C < 2) { + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.yawTowardsPlayer, 1, 0xFA0, 1); + player->actor.world.pos.x = this->picto.actor.home.pos.x + 90.0f; + player->actor.world.pos.z = this->picto.actor.home.pos.z + 30.0f; + this->picto.actor.world.pos.x = this->picto.actor.home.pos.x; + this->picto.actor.world.pos.z = this->picto.actor.home.pos.z; + this->unk_5C8.x = player->actor.world.pos.x + 39.0f; + this->unk_5C8.y = player->actor.world.pos.y + 4.0f; + this->unk_5C8.z = player->actor.world.pos.z - 41.0f; + this->unk_5D4.x = player->actor.world.pos.x - 150.0f; + this->unk_5D4.y = player->actor.world.pos.y + 60.0f; + this->unk_5D4.z = player->actor.world.pos.z + 50.0f; + } + + player->actor.shape.rot.y = player->actor.world.rot.y = + Math_Vec3f_Yaw(&player->actor.world.pos, &this->picto.actor.world.pos); + } switch (this->unk_59C) { case 0: EnKaizoku_ChangeAnim(this, EN_KAIZOKU_ANIM_17); @@ -1725,27 +1728,29 @@ void func_80B8971C(EnKaizoku* this, PlayState* play) { } Math_Vec3f_Copy(&this->unk_3C4, &gZeroVec3f); - player->actor.world.pos.x = this->picto.actor.home.pos.x + 90.0f; - player->actor.world.pos.z = this->picto.actor.home.pos.z + 30.0f; - this->picto.actor.world.pos.x = this->picto.actor.home.pos.x; - this->picto.actor.world.pos.z = this->picto.actor.home.pos.z; + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + player->actor.world.pos.x = this->picto.actor.home.pos.x + 90.0f; + player->actor.world.pos.z = this->picto.actor.home.pos.z + 30.0f; + this->picto.actor.world.pos.x = this->picto.actor.home.pos.x; + this->picto.actor.world.pos.z = this->picto.actor.home.pos.z; - this->subCamEye.x = this->unk_5C8.x = player->actor.world.pos.x + 39.0f; - this->subCamEye.y = this->unk_5C8.y = player->actor.world.pos.y + 4.0f; - this->subCamEye.z = this->unk_5C8.z = player->actor.world.pos.z - 41.0f; + this->subCamEye.x = this->unk_5C8.x = player->actor.world.pos.x + 39.0f; + this->subCamEye.y = this->unk_5C8.y = player->actor.world.pos.y + 4.0f; + this->subCamEye.z = this->unk_5C8.z = player->actor.world.pos.z - 41.0f; - this->subCamAt.x = this->unk_5D4.x = player->actor.world.pos.x - 150.0f; - this->subCamAt.y = this->unk_5D4.y = player->actor.world.pos.y + 60.0f; - this->subCamAt.z = this->unk_5D4.z = player->actor.world.pos.z + 50.0f; + this->subCamAt.x = this->unk_5D4.x = player->actor.world.pos.x - 150.0f; + this->subCamAt.y = this->unk_5D4.y = player->actor.world.pos.y + 60.0f; + this->subCamAt.z = this->unk_5D4.z = player->actor.world.pos.z + 50.0f; - player->actor.shape.rot.y = player->actor.world.rot.y = - Math_Vec3f_Yaw(&player->actor.world.pos, &this->picto.actor.world.pos); + player->actor.shape.rot.y = player->actor.world.rot.y = + Math_Vec3f_Yaw(&player->actor.world.pos, &this->picto.actor.world.pos); - if (this->subCamId != SUB_CAM_ID_DONE) { - this->subCamUp.x = 0.0f; - this->subCamUp.y = 1.0f; - this->subCamUp.z = 0.0f; - Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &this->subCamEye, &this->subCamUp); + if (this->subCamId != SUB_CAM_ID_DONE) { + this->subCamUp.x = 0.0f; + this->subCamUp.y = 1.0f; + this->subCamUp.z = 0.0f; + Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &this->subCamEye, &this->subCamUp); + } } } diff --git a/mm/src/overlays/actors/ovl_En_Knight/z_en_knight.c b/mm/src/overlays/actors/ovl_En_Knight/z_en_knight.c index 62f4b3c641..9de7fc70b5 100644 --- a/mm/src/overlays/actors/ovl_En_Knight/z_en_knight.c +++ b/mm/src/overlays/actors/ovl_En_Knight/z_en_knight.c @@ -9,6 +9,7 @@ #include "overlays/actors/ovl_Mir_Ray3/z_mir_ray3.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_knight/object_knight.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20) @@ -1848,7 +1849,9 @@ void func_809B6764(EnKnight* this, PlayState* play) { } if (D_809BEFD4->actor.draw == NULL && D_809BEFD8->actor.draw == NULL) { - func_809B7190(this, play); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + func_809B7190(this, play); + } this->unk17A = this->unk178 = this->unk176 = this->unk174 = 0; } diff --git a/mm/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c b/mm/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c index 2ac779d271..63663a3345 100644 --- a/mm/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c +++ b/mm/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c @@ -11,6 +11,8 @@ #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" +#include "2s2h/GameInteractor/GameInteractor.h" + #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20) #define THIS ((EnPametfrog*)thisx) @@ -324,6 +326,10 @@ s32 func_8086A2CC(EnPametfrog* this, CollisionPoly* floorPoly) { } void EnPametfrog_ShakeCamera(EnPametfrog* this, PlayState* play, f32 magShakeXZ, f32 magShakeY) { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + Camera* subCam = Play_GetCamera(play, this->subCamId); s16 subCamYaw; Vec3f subCamEye; @@ -336,6 +342,10 @@ void EnPametfrog_ShakeCamera(EnPametfrog* this, PlayState* play, f32 magShakeXZ, } void EnPametfrog_StopCutscene(EnPametfrog* this, PlayState* play) { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + Camera* subCam; if (this->subCamId != SUB_CAM_ID_DONE) { @@ -506,10 +516,12 @@ void EnPametfrog_SetupFallOffSnapper(EnPametfrog* this, PlayState* play) { this->timer = 30; this->collider.base.ocFlags1 |= OC1_ON; yaw = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos); - subCamEye.x = (Math_SinS(yaw) * 300.0f) + this->actor.focus.pos.x; - subCamEye.y = this->actor.focus.pos.y + 100.0f; - subCamEye.z = (Math_CosS(yaw) * 300.0f) + this->actor.focus.pos.z; - Play_SetCameraAtEye(play, this->subCamId, &this->actor.focus.pos, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + subCamEye.x = (Math_SinS(yaw) * 300.0f) + this->actor.focus.pos.x; + subCamEye.y = this->actor.focus.pos.y + 100.0f; + subCamEye.z = (Math_CosS(yaw) * 300.0f) + this->actor.focus.pos.z; + Play_SetCameraAtEye(play, this->subCamId, &this->actor.focus.pos, &subCamEye); + } Actor_PlaySfx(&this->actor, NA_SE_EN_FROG_DAMAGE); this->actionFunc = EnPametfrog_FallOffSnapper; } @@ -525,6 +537,7 @@ void EnPametfrog_FallOffSnapper(EnPametfrog* this, PlayState* play) { } sin = Math_SinF(this->timer * (M_PI / 3)) * ((0.02f * (this->timer * (1.0f / 6.0f))) + 0.005f) + 1.0f; + EnPametfrog_ShakeCamera(this, play, 300.0f * sin, 100.0f * sin); if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { EnPametfrog_StopCutscene(this, play); @@ -899,15 +912,17 @@ void EnPametfrog_FallOnGround(EnPametfrog* this, PlayState* play) { } void EnPametfrog_SetupDefeatGekko(EnPametfrog* this, PlayState* play) { - Vec3f subCamEye; - s16 yaw = Actor_WorldYawTowardPoint(this->actor.child, &this->actor.home.pos); - s16 yawDiff = this->actor.yawTowardsPlayer - yaw; - - yaw = yawDiff > 0 ? yaw - 0x2000 : yaw + 0x2000; - subCamEye.x = this->actor.child->focus.pos.x + 150.0f * Math_SinS(yaw); - subCamEye.y = this->actor.child->focus.pos.y + 20.0f; - subCamEye.z = this->actor.child->focus.pos.z + 150.0f * Math_CosS(yaw); - Play_SetCameraAtEye(play, this->subCamId, &this->actor.child->focus.pos, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Vec3f subCamEye; + s16 yaw = Actor_WorldYawTowardPoint(this->actor.child, &this->actor.home.pos); + s16 yawDiff = this->actor.yawTowardsPlayer - yaw; + + yaw = yawDiff > 0 ? yaw - 0x2000 : yaw + 0x2000; + subCamEye.x = this->actor.child->focus.pos.x + 150.0f * Math_SinS(yaw); + subCamEye.y = this->actor.child->focus.pos.y + 20.0f; + subCamEye.z = this->actor.child->focus.pos.z + 150.0f * Math_CosS(yaw); + Play_SetCameraAtEye(play, this->subCamId, &this->actor.child->focus.pos, &subCamEye); + } this->actor.params = GEKKO_DEFEAT; this->timer = 38; this->actionFunc = EnPametfrog_DefeatGekko; @@ -924,15 +939,17 @@ void EnPametfrog_DefeatGekko(EnPametfrog* this, PlayState* play) { } void EnPametfrog_SetupDefeatSnapper(EnPametfrog* this, PlayState* play) { - Vec3f subCamEye; - s16 yaw = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos); - s16 yawDiff = this->actor.yawTowardsPlayer - yaw; - - yaw = yawDiff > 0 ? yaw - 0x2000 : yaw + 0x2000; - subCamEye.x = this->actor.world.pos.x + Math_SinS(yaw) * 150.0f; - subCamEye.y = this->actor.world.pos.y + 20.0f; - subCamEye.z = this->actor.world.pos.z + Math_CosS(yaw) * 150.0f; - Play_SetCameraAtEye(play, this->subCamId, &this->actor.world.pos, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + Vec3f subCamEye; + s16 yaw = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos); + s16 yawDiff = this->actor.yawTowardsPlayer - yaw; + + yaw = yawDiff > 0 ? yaw - 0x2000 : yaw + 0x2000; + subCamEye.x = this->actor.world.pos.x + Math_SinS(yaw) * 150.0f; + subCamEye.y = this->actor.world.pos.y + 20.0f; + subCamEye.z = this->actor.world.pos.z + Math_CosS(yaw) * 150.0f; + Play_SetCameraAtEye(play, this->subCamId, &this->actor.world.pos, &subCamEye); + } this->timer = 20; this->actionFunc = EnPametfrog_DefeatSnapper; } @@ -1006,8 +1023,10 @@ void EnPametfrog_SetupCutscene(EnPametfrog* this) { void EnPametfrog_PlayCutscene(EnPametfrog* this, PlayState* play) { if (CutsceneManager_IsNext(this->csId)) { CutsceneManager_Start(this->csId, &this->actor); - this->subCamId = CutsceneManager_GetCurrentSubCamId(this->csId); - Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_WAIT); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + this->subCamId = CutsceneManager_GetCurrentSubCamId(this->csId); + Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_WAIT); + } if (this->actor.colChkInfo.health == 0) { if (this->actor.params == GEKKO_PRE_SNAPPER) { EnPametfrog_SetupCallSnapper(this, play); @@ -1183,15 +1202,17 @@ void EnPametfrog_SetupCallSnapper(EnPametfrog* this, PlayState* play) { } this->actor.shape.rot.y = this->actor.world.rot.y; - subCamAt.x = this->actor.world.pos.x; - subCamAt.z = this->actor.world.pos.z; - subCamAt.y = this->actor.world.pos.y + 45.0f; - subCamEye.x = (Math_SinS(this->actor.shape.rot.y) * 90.0f) + subCamAt.x; - subCamEye.z = (Math_CosS(this->actor.shape.rot.y) * 90.0f) + subCamAt.z; - subCamEye.y = subCamAt.y + 4.0f; - - // Zooms in on Gekko - Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + subCamAt.x = this->actor.world.pos.x; + subCamAt.z = this->actor.world.pos.z; + subCamAt.y = this->actor.world.pos.y + 45.0f; + subCamEye.x = (Math_SinS(this->actor.shape.rot.y) * 90.0f) + subCamAt.x; + subCamEye.z = (Math_CosS(this->actor.shape.rot.y) * 90.0f) + subCamAt.z; + subCamEye.y = subCamAt.y + 4.0f; + + // Zooms in on Gekko + Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); + } this->timer = 0; this->actor.hintId = TATL_HINT_ID_GEKKO_GIANT_SLIME; this->actionFunc = EnPametfrog_CallSnapper; @@ -1218,12 +1239,14 @@ void EnPametfrog_SetupSnapperSpawn(EnPametfrog* this, PlayState* play) { yaw = this->actor.child->shape.rot.y + 0x1000; } - subCamEye.x = (Math_SinS(yaw) * 500.0f) + subCamAt.x; - subCamEye.y = subCamAt.y + 55.0f; - subCamEye.z = (Math_CosS(yaw) * 500.0f) + subCamAt.z; + if (GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + subCamEye.x = (Math_SinS(yaw) * 500.0f) + subCamAt.x; + subCamEye.y = subCamAt.y + 55.0f; + subCamEye.z = (Math_CosS(yaw) * 500.0f) + subCamAt.z; - // Zooms in on Snapper spawn point - Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); + // Zooms in on Snapper spawn point + Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); + } this->quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); Quake_SetSpeed(this->quakeIndex, 18000); diff --git a/mm/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c b/mm/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c index 94d8e79246..2bd9656d74 100644 --- a/mm/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c +++ b/mm/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c @@ -8,6 +8,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" #include "overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS \ (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_IGNORE_QUAKE | \ @@ -832,6 +833,10 @@ void EnWiz_Dance(EnWiz* this, PlayState* play) { } void EnWiz_SetupSecondPhaseCutscene(EnWiz* this, PlayState* play) { + if (!GameInteractor_Should(VB_ENEMY_CUTSCENE_ACTION, true, this)) { + return; + } + s16 secondPhaseCsId = CutsceneManager_GetAdditionalCsId(this->actor.csId); if (!CutsceneManager_IsNext(secondPhaseCsId)) {