mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-22 17:32:19 -05:00
Adds Quick Boss Death checkbox and implements Phantom Ganon's quick death (#119)
* Adds Quick Boss Death checkbox and implements Phantom Ganon's quick death. * Clarifies relocation comment.
This commit is contained in:
parent
7e7445ebcc
commit
baaa00569d
@ -376,6 +376,10 @@ typedef enum {
|
||||
/*** Fixes ***/
|
||||
// Vanilla condition: false
|
||||
GI_VB_FIX_SAW_SOFTLOCK,
|
||||
|
||||
/*** Quick Boss Deaths ***/
|
||||
// Vanilla condition: true
|
||||
GI_VB_PHANTOM_GANON_DEATH_SCENE,
|
||||
} GIVanillaBehavior;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -24,6 +24,8 @@ extern "C" {
|
||||
#include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
|
||||
#include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h"
|
||||
#include "src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h"
|
||||
#include <overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h>
|
||||
#include <objects/object_gnd/object_gnd.h>
|
||||
extern SaveContext gSaveContext;
|
||||
extern PlayState* gPlayState;
|
||||
extern int32_t D_8011D3AC;
|
||||
@ -719,6 +721,31 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void*
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GI_VB_PHANTOM_GANON_DEATH_SCENE: {
|
||||
if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO || IS_BOSS_RUSH)) {
|
||||
*should = false;
|
||||
BossGanondrof* pg = static_cast<BossGanondrof*>(opt);
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (pg != nullptr && pg->work[GND_ACTION_STATE] == DEATH_SPASM) {
|
||||
// Skip to death scream animation and move ganondrof to middle
|
||||
pg->deathState = DEATH_SCREAM;
|
||||
pg->timers[0] = 50;
|
||||
AnimationHeader* screamAnim = (AnimationHeader*)gPhantomGanonScreamAnim;
|
||||
Animation_MorphToLoop(&pg->skelAnime, screamAnim, -10.0f);
|
||||
pg->actor.world.pos.x = GND_BOSSROOM_CENTER_X;
|
||||
pg->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f;
|
||||
pg->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
|
||||
pg->actor.shape.rot.y = 0;
|
||||
pg->work[GND_BODY_DECAY_INDEX] = 0;
|
||||
Audio_PlayActorSound2(&pg->actor, NA_SE_EN_FANTOM_LAST);
|
||||
|
||||
// Move Player out of the center of the room
|
||||
player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
|
||||
player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -581,6 +581,7 @@ void DrawEnhancementsMenu() {
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) &&
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) &&
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) &&
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) &&
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) &&
|
||||
CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) &&
|
||||
CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) &&
|
||||
@ -592,6 +593,7 @@ void DrawEnhancementsMenu() {
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) ||
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) ||
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO) ||
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO) ||
|
||||
CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO) ||
|
||||
CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO) ||
|
||||
CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) ||
|
||||
@ -608,6 +610,7 @@ void DrawEnhancementsMenu() {
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 1);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1);
|
||||
CVarSetInteger("gTimeSavers.NoForcedDialog", 1);
|
||||
CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1);
|
||||
@ -619,6 +622,7 @@ void DrawEnhancementsMenu() {
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", 0);
|
||||
CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0);
|
||||
CVarSetInteger("gTimeSavers.NoForcedDialog", 0);
|
||||
CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0);
|
||||
@ -633,6 +637,7 @@ void DrawEnhancementsMenu() {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Quick Boss Deaths", "gTimeSavers.SkipCutscene.QuickBossDeaths", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
|
||||
UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
|
||||
UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO);
|
||||
UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs");
|
||||
|
@ -12,19 +12,10 @@
|
||||
#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
|
||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||
#include "soh/Enhancements/boss-rush/BossRush.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ NOT_DEAD,
|
||||
/* 1 */ DEATH_START,
|
||||
/* 2 */ DEATH_THROES,
|
||||
/* 3 */ DEATH_WARP,
|
||||
/* 4 */ DEATH_SCREAM,
|
||||
/* 5 */ DEATH_DISINTEGRATE,
|
||||
/* 6 */ DEATH_FINISH
|
||||
} BossGanondrofDeathState;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ THROW_NORMAL,
|
||||
/* 1 */ THROW_SLOW
|
||||
@ -42,12 +33,6 @@ typedef enum {
|
||||
/* 3 */ CHARGE_FINISH
|
||||
} BossGanondrofChargeAction;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ DEATH_SPASM,
|
||||
/* 1 */ DEATH_LIMP,
|
||||
/* 2 */ DEATH_HUNCHED
|
||||
} BossGanondrofDeathAction;
|
||||
|
||||
void BossGanondrof_Init(Actor* thisx, PlayState* play);
|
||||
void BossGanondrof_Destroy(Actor* thisx, PlayState* play);
|
||||
void BossGanondrof_Update(Actor* thisx, PlayState* play);
|
||||
@ -959,26 +944,13 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
|
||||
case DEATH_THROES:
|
||||
switch (this->work[GND_ACTION_STATE]) {
|
||||
case DEATH_SPASM:
|
||||
if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME]) && !IS_RANDO && !IS_BOSS_RUSH) {
|
||||
this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim);
|
||||
Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f,
|
||||
this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f);
|
||||
this->work[GND_ACTION_STATE] = DEATH_LIMP;
|
||||
} else if (IS_RANDO || IS_BOSS_RUSH) {
|
||||
// Skip to death scream animation and move ganondrof to middle
|
||||
this->deathState = DEATH_SCREAM;
|
||||
this->timers[0] = 50;
|
||||
Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonScreamAnim, -10.0f);
|
||||
this->actor.world.pos.x = GND_BOSSROOM_CENTER_X;
|
||||
this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f;
|
||||
this->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
|
||||
this->actor.shape.rot.y = 0;
|
||||
this->work[GND_BODY_DECAY_INDEX] = 0;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAST);
|
||||
|
||||
// Move Player out of the center of the room
|
||||
player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
|
||||
player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
|
||||
if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, this)) {
|
||||
if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
|
||||
this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim);
|
||||
Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f,
|
||||
this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f);
|
||||
this->work[GND_ACTION_STATE] = DEATH_LIMP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEATH_LIMP:
|
||||
@ -991,26 +963,25 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
|
||||
bodyDecayLevel = 1;
|
||||
break;
|
||||
}
|
||||
if (IS_RANDO || IS_BOSS_RUSH) {
|
||||
break;
|
||||
}
|
||||
Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8);
|
||||
Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f);
|
||||
Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f);
|
||||
this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
|
||||
this->cameraNextAt.x = this->targetPos.x;
|
||||
this->cameraNextAt.y = this->targetPos.y - 10.0f;
|
||||
this->cameraNextAt.z = this->targetPos.z;
|
||||
if (this->timers[0] == 0) {
|
||||
this->deathState = DEATH_WARP;
|
||||
this->timers[0] = 350;
|
||||
this->timers[1] = 50;
|
||||
this->fwork[GND_CAMERA_ZOOM] = 300.0f;
|
||||
this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f;
|
||||
player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
|
||||
player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
|
||||
holdCamera = true;
|
||||
bodyDecayLevel = 1;
|
||||
if (GameInteractor_Should(GI_VB_PHANTOM_GANON_DEATH_SCENE, true, NULL)) {
|
||||
Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8);
|
||||
Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f);
|
||||
Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f);
|
||||
this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
|
||||
this->cameraNextAt.x = this->targetPos.x;
|
||||
this->cameraNextAt.y = this->targetPos.y - 10.0f;
|
||||
this->cameraNextAt.z = this->targetPos.z;
|
||||
if (this->timers[0] == 0) {
|
||||
this->deathState = DEATH_WARP;
|
||||
this->timers[0] = 350;
|
||||
this->timers[1] = 50;
|
||||
this->fwork[GND_CAMERA_ZOOM] = 300.0f;
|
||||
this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f;
|
||||
player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
|
||||
player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
|
||||
holdCamera = true;
|
||||
bodyDecayLevel = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEATH_WARP:
|
||||
|
@ -61,6 +61,23 @@ typedef enum {
|
||||
/* 13 */ GND_FLOAT_COUNT = 13
|
||||
} BossGanondrofF32Var;
|
||||
|
||||
// SOH [Enhancements] Relocated from z_boss_ganondrof.c to use in time saver.
|
||||
typedef enum {
|
||||
/* 0 */ NOT_DEAD,
|
||||
/* 1 */ DEATH_START,
|
||||
/* 2 */ DEATH_THROES,
|
||||
/* 3 */ DEATH_WARP,
|
||||
/* 4 */ DEATH_SCREAM,
|
||||
/* 5 */ DEATH_DISINTEGRATE,
|
||||
/* 6 */ DEATH_FINISH
|
||||
} BossGanondrofDeathState;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ DEATH_SPASM,
|
||||
/* 1 */ DEATH_LIMP,
|
||||
/* 2 */ DEATH_HUNCHED
|
||||
} BossGanondrofDeathAction;
|
||||
|
||||
typedef struct BossGanondrof {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ SkelAnime skelAnime;
|
||||
|
Loading…
Reference in New Issue
Block a user