mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-04-28 13:17:58 +03:00
Merge 03df49004b
into fbbfc07ff1
This commit is contained in:
commit
b3f24b458f
14 changed files with 326 additions and 384 deletions
|
@ -1,7 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
|
@ -12,48 +10,47 @@ extern PlayState* gPlayState;
|
|||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
#define CVAR_BLOCKLIFT_NAME CVAR_ENHANCEMENT("FasterHeavyBlockLift")
|
||||
#define CVAR_BLOCKLIFT_VALUE CVarGetInteger(CVAR_BLOCKLIFT_NAME, 0)
|
||||
|
||||
#define CVAR_SKIP_CUTSCENE_NAME CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint")
|
||||
#define CVAR_SKIP_CUTSCENE_VALUE CVarGetInteger(CVAR_SKIP_CUTSCENE_NAME, IS_RANDO)
|
||||
|
||||
/**
|
||||
* This primarily handles speeding up the heavy block lifts (OGC and in the Fire Trial) but also handles skipping
|
||||
* the one point cutscene since the two options are so similar in what they do.
|
||||
*/
|
||||
void FasterHeavyBlockLift_Register() {
|
||||
REGISTER_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, {
|
||||
void RegisterFasterHeavyBlockLift() {
|
||||
COND_VB_SHOULD(VB_PLAY_ONEPOINT_ACTOR_CS, CVAR_BLOCKLIFT_VALUE || CVAR_SKIP_CUTSCENE_VALUE, {
|
||||
Actor* actor = va_arg(args, Actor*);
|
||||
|
||||
if (actor->id == ACTOR_BG_HEAVY_BLOCK &&
|
||||
(CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO))) {
|
||||
if (actor->id == ACTOR_BG_HEAVY_BLOCK) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
REGISTER_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) ||
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
COND_VB_SHOULD(VB_FREEZE_LINK_FOR_BLOCK_THROW, CVAR_BLOCKLIFT_VALUE || CVAR_SKIP_CUTSCENE_VALUE,
|
||||
{ *should = false; });
|
||||
|
||||
REGISTER_VB_SHOULD(VB_PLAY_THROW_ANIMATION, {
|
||||
COND_VB_SHOULD(VB_PLAY_THROW_ANIMATION, CVAR_BLOCKLIFT_VALUE, {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Actor* interactRangeActor = player->interactRangeActor;
|
||||
s32 interactActorId = interactRangeActor->id;
|
||||
LinkAnimationHeader* anim = va_arg(args, LinkAnimationHeader*);
|
||||
|
||||
// Same actor is used for small and large silver rocks, use actor params to identify large ones
|
||||
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && interactRangeActor->params & 1 == 1;
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0) &&
|
||||
(isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK)) {
|
||||
bool isLargeSilverRock = interactActorId == ACTOR_EN_ISHI && (interactRangeActor->params & 1) == 1;
|
||||
if (isLargeSilverRock || interactActorId == ACTOR_BG_HEAVY_BLOCK) {
|
||||
*should = false;
|
||||
LinkAnimation_PlayOnceSetSpeed(gPlayState, &player->skelAnime, anim, 5.0f);
|
||||
}
|
||||
});
|
||||
|
||||
REGISTER_VB_SHOULD(VB_MOVE_THROWN_ACTOR, {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FasterHeavyBlockLift"), 0)) {
|
||||
Actor* heldActor = va_arg(args, Actor*);
|
||||
COND_VB_SHOULD(VB_MOVE_THROWN_ACTOR, CVAR_BLOCKLIFT_VALUE, {
|
||||
Actor* heldActor = va_arg(args, Actor*);
|
||||
|
||||
heldActor->shape.rot.x -= 3510;
|
||||
}
|
||||
heldActor->shape.rot.x -= 3510;
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterFasterHeavyBlockLift, { CVAR_BLOCKLIFT_NAME, CVAR_SKIP_CUTSCENE_NAME });
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
|
@ -12,11 +10,8 @@ extern PlayState* gPlayState;
|
|||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
void FasterRupeeAccumulator_Register() {
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnInterfaceUpdate>([]() {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0))
|
||||
return;
|
||||
|
||||
void RegisterFasterRupeeAccumulator() {
|
||||
COND_HOOK(OnInterfaceUpdate, CVarGetInteger(CVAR_ENHANCEMENT("FasterRupeeAccumulator"), 0), []() {
|
||||
if (gSaveContext.rupeeAccumulator == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -46,3 +41,5 @@ void FasterRupeeAccumulator_Register() {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterFasterRupeeAccumulator, { CVAR_ENHANCEMENT("FasterRupeeAccumulator") });
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/randomizer/context.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
|
@ -10,12 +10,12 @@ extern PlayState* gPlayState;
|
|||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
void SkipIntro_Register() {
|
||||
void RegisterSkipIntro() {
|
||||
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
|
||||
// If we're playing rando and if starting age is adult and/or overworld spawns are shuffled we need to skip
|
||||
// the cutscene regardless of the enhancement being on.
|
||||
bool adultStart = gSaveContext.linkAge == LINK_AGE_ADULT;
|
||||
bool shuffleEntrances = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_ENTRANCES).Is(true);
|
||||
bool shuffleEntrances = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_ENTRANCES).Is(true);
|
||||
if ((CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), IS_RANDO) ||
|
||||
(IS_RANDO && (adultStart || shuffleEntrances))) &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
|
@ -45,3 +45,5 @@ void SkipIntro_Register() {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipIntro);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/Enhancements/randomizer/context.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "macros.h"
|
||||
|
@ -14,120 +15,6 @@ extern "C" {
|
|||
|
||||
static bool sEnteredBlueWarp = false;
|
||||
|
||||
/**
|
||||
* This will override the transitions into the blue warp cutscenes, set any appropriate flags, and
|
||||
* set the entrance index to where you would normally end up after the blue warp cutscene. This
|
||||
* should also account for the difference between your first and following visits to the blue warp.
|
||||
*/
|
||||
void SkipBlueWarp_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
|
||||
// Do nothing when in a boss rush
|
||||
if (IS_BOSS_RUSH) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool overrideBlueWarpDestinations =
|
||||
IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
|
||||
RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
|
||||
|
||||
// Force blue warp skip on when ER needs to place Link somewhere else.
|
||||
// This is preferred over having story cutscenes play in the overworld and then reloading Link somewhere else after.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) || overrideBlueWarpDestinations) {
|
||||
bool isBlueWarpCutscene = false;
|
||||
// Deku Tree Blue warp
|
||||
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Dodongo's Cavern Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Jabu Jabu's Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF0) {
|
||||
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Forest Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
|
||||
// Normally set in the blue warp cutscene
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
|
||||
|
||||
if (IS_RANDO) {
|
||||
gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP;
|
||||
} else {
|
||||
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12;
|
||||
}
|
||||
|
||||
isBlueWarpCutscene = true;
|
||||
// Fire Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF3) {
|
||||
// Normally set in the blue warp cutscene
|
||||
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
|
||||
|
||||
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Water Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
|
||||
// Normally set in the blue warp cutscene
|
||||
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800;
|
||||
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
|
||||
|
||||
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Spirit Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
|
||||
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Shadow Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
|
||||
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
}
|
||||
|
||||
if (isBlueWarpCutscene) {
|
||||
if (gSaveContext.entranceIndex != ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP) {
|
||||
// Normally set in the blue warp cutscene
|
||||
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000;
|
||||
}
|
||||
|
||||
*should = false;
|
||||
gSaveContext.cutsceneIndex = 0;
|
||||
}
|
||||
|
||||
// This is outside the above condition because we want to handle both first and following visits to the blue
|
||||
// warp
|
||||
if (sEnteredBlueWarp && overrideBlueWarpDestinations) {
|
||||
Entrance_OverrideBlueWarp();
|
||||
}
|
||||
}
|
||||
|
||||
sEnteredBlueWarp = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using this hook to simply observe that Link has entered a bluewarp
|
||||
* This way we know to allow entrance rando overrides to be processed on the next tranisition hook
|
||||
*/
|
||||
void SkipBlueWarp_ShouldPlayBlueWarpCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
|
||||
sEnteredBlueWarp = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* While we could rely on the Item_Give that's normally called, it's not very clear to the player that they
|
||||
* received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given
|
||||
* to the player instead.
|
||||
*/
|
||||
void SkipBlueWarp_ShouldGiveItem(GIVanillaBehavior _, bool* should, va_list originalArgs) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
*should = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Todo: Move item queueing here
|
||||
|
||||
/**
|
||||
|
@ -150,35 +37,143 @@ void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
|
|||
void SkipBlueWarp_OnActorUpdate(void* actorPtr) {
|
||||
EnKo* enKo = static_cast<EnKo*>(actorPtr);
|
||||
|
||||
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3 && enKo->actionFunc == func_80A995CC) {
|
||||
enKo->actionFunc = EnKo_MoveWhenReady;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp cutscene.
|
||||
* Typically this checks for if you have the medallion, and when skipping the cutscene at this point you don't have it
|
||||
* yet.
|
||||
*/
|
||||
void SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished(GIVanillaBehavior _, bool* should, va_list originalArgs) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
|
||||
}
|
||||
}
|
||||
void RegisterSkipBlueWarp() {
|
||||
COND_ID_HOOK(OnActorUpdate, ACTOR_EN_KO,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO),
|
||||
SkipBlueWarp_OnActorUpdate);
|
||||
|
||||
/**
|
||||
* This will ensure that the Deku Tree Sprout considers the Forest Temple finished when you skip the blue warp
|
||||
* cutscene. Typically this checks for if you have the medallion, and when skipping the cutscene at this point you
|
||||
* don't have it yet.
|
||||
*/
|
||||
COND_VB_SHOULD(VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
|
||||
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* While we could rely on the Item_Give that's normally called, it's not very clear to the player that they
|
||||
* received the item when skipping the blue warp cutscene, so we'll prevent that and queue it up to be given
|
||||
* to the player instead.
|
||||
*/
|
||||
COND_VB_SHOULD(VB_GIVE_ITEM_FROM_BLUE_WARP,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), { *should = false; });
|
||||
}
|
||||
|
||||
void SkipBlueWarp_Register() {
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(ACTOR_EN_KO,
|
||||
SkipBlueWarp_OnActorUpdate);
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
|
||||
VB_PLAY_TRANSITION_CS, SkipBlueWarp_ShouldPlayTransitionCS);
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
|
||||
VB_PLAY_BLUE_WARP_CS, SkipBlueWarp_ShouldPlayBlueWarpCS);
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
|
||||
VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, SkipBlueWarp_ShouldDekuJrConsiderForestTempleFinished);
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(VB_GIVE_ITEM_FROM_BLUE_WARP,
|
||||
SkipBlueWarp_ShouldGiveItem);
|
||||
void RegisterShouldPlayBlueWarp() {
|
||||
/**
|
||||
* This will override the transitions into the blue warp cutscenes, set any appropriate flags, and
|
||||
* set the entrance index to where you would normally end up after the blue warp cutscene. This
|
||||
* should also account for the difference between your first and following visits to the blue warp.
|
||||
*/
|
||||
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
|
||||
// Do nothing when in a boss rush
|
||||
if (IS_BOSS_RUSH) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool overrideBlueWarpDestinations =
|
||||
IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
|
||||
RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
|
||||
|
||||
// Force blue warp skip on when ER needs to place Link somewhere else.
|
||||
// This is preferred over having story cutscenes play in the overworld and then reloading Link somewhere else
|
||||
// after.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO) ||
|
||||
overrideBlueWarpDestinations) {
|
||||
bool isBlueWarpCutscene = false;
|
||||
// Deku Tree Blue warp
|
||||
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Dodongo's Cavern Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Jabu Jabu's Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF0) {
|
||||
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Forest Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
|
||||
// Normally set in the blue warp cutscene
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
|
||||
|
||||
if (IS_RANDO) {
|
||||
gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP;
|
||||
} else {
|
||||
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12;
|
||||
}
|
||||
|
||||
isBlueWarpCutscene = true;
|
||||
// Fire Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_FRONT_GATE &&
|
||||
gSaveContext.cutsceneIndex == 0xFFF3) {
|
||||
// Normally set in the blue warp cutscene
|
||||
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
|
||||
|
||||
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Water Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
|
||||
// Normally set in the blue warp cutscene
|
||||
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4800;
|
||||
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
|
||||
|
||||
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Spirit Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
|
||||
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
// Shadow Temple Blue warp
|
||||
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 &&
|
||||
gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
|
||||
gSaveContext.entranceIndex = ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP;
|
||||
isBlueWarpCutscene = true;
|
||||
}
|
||||
|
||||
if (isBlueWarpCutscene) {
|
||||
if (gSaveContext.entranceIndex != ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP) {
|
||||
// Normally set in the blue warp cutscene
|
||||
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000;
|
||||
}
|
||||
|
||||
*should = false;
|
||||
gSaveContext.cutsceneIndex = 0;
|
||||
}
|
||||
|
||||
// This is outside the above condition because we want to handle both first and following visits to the blue
|
||||
// warp
|
||||
if (sEnteredBlueWarp && overrideBlueWarpDestinations) {
|
||||
Entrance_OverrideBlueWarp();
|
||||
}
|
||||
}
|
||||
|
||||
sEnteredBlueWarp = false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Using this hook to simply observe that Link has entered a bluewarp
|
||||
* This way we know to allow entrance rando overrides to be processed on the next tranisition hook
|
||||
*/
|
||||
REGISTER_VB_SHOULD(VB_PLAY_BLUE_WARP_CS, { sEnteredBlueWarp = true; });
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipBlueWarp,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });
|
||||
static RegisterShipInitFunc initFunc2(RegisterShouldPlayBlueWarp);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
|
||||
|
@ -9,15 +8,17 @@ extern "C" {
|
|||
/**
|
||||
* This will skip the Deku Tree intro, and simply open the mouth as you approach it.
|
||||
*/
|
||||
void SkipDekuTreeIntro_Register() {
|
||||
REGISTER_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS, {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
|
||||
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||
BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
void RegisterSkipDekuTreeIntro() {
|
||||
COND_VB_SHOULD(VB_PLAY_DEKU_TREE_INTRO_CS,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
|
||||
BgTreemouth* treeMouth = va_arg(args, BgTreemouth*);
|
||||
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
|
||||
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
|
||||
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
|
||||
BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
|
||||
*should = false;
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipDekuTreeIntro,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
|
@ -9,21 +9,19 @@ extern PlayState* gPlayState;
|
|||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
void SkipLostWoodsBridge_Register() {
|
||||
void RegisterSkipLostWoodsBridge() {
|
||||
/**
|
||||
* This skips the cutscene where you speak to Saria on the bridge in Lost Woods, where she gives you the Fairy
|
||||
* Ocarina.
|
||||
*/
|
||||
REGISTER_VB_SHOULD(VB_PLAY_TRANSITION_CS, {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) &&
|
||||
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
|
||||
if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) {
|
||||
Item_Give(gPlayState, ITEM_OCARINA_FAIRY);
|
||||
}
|
||||
*should = false;
|
||||
COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
|
||||
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_BRIDGE_EAST_EXIT) &&
|
||||
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
|
||||
if (GameInteractor_Should(VB_GIVE_ITEM_FAIRY_OCARINA, true)) {
|
||||
Item_Give(gPlayState, ITEM_OCARINA_FAIRY);
|
||||
}
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -32,11 +30,11 @@ void SkipLostWoodsBridge_Register() {
|
|||
* player that they received the item when skipping the cutscene, so we'll prevent it, and queue it up to be given
|
||||
* instead.
|
||||
*/
|
||||
REGISTER_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA, {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
COND_VB_SHOULD(VB_GIVE_ITEM_FAIRY_OCARINA,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), { *should = false; });
|
||||
|
||||
// Todo: Move item queueing here
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipLostWoodsBridge,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
|
||||
|
@ -33,16 +32,17 @@ void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
|
|||
}
|
||||
|
||||
void SkipToGivingZeldasLetter_OnActorInit(void* actorPtr) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr);
|
||||
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0)
|
||||
return;
|
||||
EnZl4* enZl4 = static_cast<EnZl4*>(actorPtr);
|
||||
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0)
|
||||
return;
|
||||
|
||||
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
|
||||
}
|
||||
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
|
||||
}
|
||||
|
||||
void SkipToGivingZeldasLetter_Register() {
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_ZL4,
|
||||
SkipToGivingZeldasLetter_OnActorInit);
|
||||
void RegisterSkipToGivingZeldasLetter() {
|
||||
COND_ID_HOOK(OnActorInit, ACTOR_EN_ZL4, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO),
|
||||
SkipToGivingZeldasLetter_OnActorInit);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipToGivingZeldasLetter,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
|
@ -8,18 +7,6 @@ extern "C" {
|
|||
extern SaveContext gSaveContext;
|
||||
}
|
||||
|
||||
void SkipZeldaFleeingCastle_ShouldPlayTransitionCS(GIVanillaBehavior _, bool* should, va_list originalArgs) {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_PAST_BRIDGE_SPAWN && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
// Normally set in the cutscene
|
||||
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA;
|
||||
|
||||
gSaveContext.cutsceneIndex = 0;
|
||||
*should = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When this cutscene is skipped, walking up to the bridge to castle town triggers a quick fade in/out
|
||||
* which can be confusing to beginners, because they need to then fetch the Ocarina of Time from the water.
|
||||
|
@ -46,7 +33,7 @@ void SkipZeldaFleeingCastle_OnActorUpdate(void* actorPtr) {
|
|||
void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
|
||||
Actor* actor = static_cast<Actor*>(actorPtr);
|
||||
|
||||
if (actor->params == 3 && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
if (actor->params == 3) {
|
||||
framesSinceSpawn = 0;
|
||||
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr<GameInteractor::OnActorUpdate>(
|
||||
(uintptr_t)actorPtr, SkipZeldaFleeingCastle_OnActorUpdate);
|
||||
|
@ -59,9 +46,20 @@ void SkipZeldaFleeingCastle_OnActorInit(void* actorPtr) {
|
|||
}
|
||||
}
|
||||
|
||||
void SkipZeldaFleeingCastle_Register() {
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_ITEM_OCARINA,
|
||||
SkipZeldaFleeingCastle_OnActorInit);
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnVanillaBehavior>(
|
||||
VB_PLAY_TRANSITION_CS, SkipZeldaFleeingCastle_ShouldPlayTransitionCS);
|
||||
void RegisterSkipZeldaFleeingCastle() {
|
||||
COND_ID_HOOK(OnActorInit, ACTOR_ITEM_OCARINA,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO),
|
||||
SkipZeldaFleeingCastle_OnActorInit);
|
||||
COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO), {
|
||||
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_PAST_BRIDGE_SPAWN && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||
// Normally set in the cutscene
|
||||
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA;
|
||||
|
||||
gSaveContext.cutsceneIndex = 0;
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipZeldaFleeingCastle,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), "IS_RANDO" });
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "src/overlays/actors/ovl_Bg_Bdan_Objects/z_bg_bdan_objects.h"
|
||||
}
|
||||
|
||||
void BdanInit(void* actorRef) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);
|
||||
|
||||
if (bgBdanObjects->dyna.actor.params == 1) {
|
||||
if (player->actor.world.pos.y < -500.0f) {
|
||||
bgBdanObjects->timer = 220;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom
|
||||
*/
|
||||
void MoveJabuJabuElevator_Register() {
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(
|
||||
ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef);
|
||||
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bgBdanObjects->dyna.actor.params == 1) {
|
||||
if (player->actor.world.pos.y < -500.0f) {
|
||||
bgBdanObjects->timer = 220;
|
||||
}
|
||||
}
|
||||
});
|
||||
void RegisterMoveJabuJabuElevator() {
|
||||
COND_ID_HOOK(OnActorInit, ACTOR_BG_BDAN_OBJECTS,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), BdanInit);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterMoveJabuJabuElevator,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "z64save.h"
|
||||
|
@ -15,14 +14,17 @@ extern SaveContext gSaveContext;
|
|||
* This simply skips the Mido interaction in Kokiri Forest, once you equip the Kokiri
|
||||
* Sword and Deku Shield he will move out of the way without you needing to talk to him.
|
||||
*/
|
||||
void MoveMidoInKokiriForest_Register() {
|
||||
REGISTER_VB_SHOULD(VB_MOVE_MIDO_IN_KOKIRI_FOREST, {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
|
||||
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
||||
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
|
||||
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
||||
*should = true;
|
||||
}
|
||||
});
|
||||
void RegisterMoveMidoInKokiriForest() {
|
||||
COND_VB_SHOULD(
|
||||
VB_MOVE_MIDO_IN_KOKIRI_FOREST, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
|
||||
if (!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
||||
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
|
||||
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
||||
*should = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterMoveMidoInKokiriForest,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "overlays/actors/ovl_En_Ru1/z_en_ru1.h"
|
||||
|
@ -9,93 +8,87 @@ extern "C" {
|
|||
Actor* func_80AEB124(PlayState* play);
|
||||
}
|
||||
|
||||
void SkipChildRutoInteractions_Register() {
|
||||
// Skips the Child Ruto introduction cutscene, where she drops down into the hole in Jabu-Jabu's Belly
|
||||
REGISTER_VB_SHOULD(VB_PLAY_CHILD_RUTO_INTRO, {
|
||||
EnRu1* enRu1 = va_arg(args, EnRu1*);
|
||||
void Ru1Init(void* actorRef) {
|
||||
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
|
||||
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME);
|
||||
Flags_SetInfTable(INFTABLE_143);
|
||||
if (enRu1->action == 22) {
|
||||
enRu1->action = 27;
|
||||
enRu1->drawConfig = 1;
|
||||
enRu1->actor.world.pos.x = 127.0f;
|
||||
enRu1->actor.world.pos.y = -340.0f;
|
||||
enRu1->actor.world.pos.z = -3041.0f;
|
||||
enRu1->actor.shape.rot.y = enRu1->actor.world.rot.y = -5098;
|
||||
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
|
||||
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
|
||||
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (*should) {
|
||||
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildTurnAroundAnim, 1.0f, 0,
|
||||
Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f);
|
||||
enRu1->action = 10;
|
||||
}
|
||||
void RegisterSkipChildRutoInteractions() {
|
||||
// Skips the Child Ruto introduction cutscene, where she drops down into the hole in Jabu-Jabu's Belly
|
||||
COND_VB_SHOULD(
|
||||
VB_PLAY_CHILD_RUTO_INTRO, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
|
||||
EnRu1* enRu1 = va_arg(args, EnRu1*);
|
||||
|
||||
*should = false;
|
||||
});
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME);
|
||||
Flags_SetInfTable(INFTABLE_143);
|
||||
enRu1->drawConfig = 1;
|
||||
enRu1->actor.world.pos.x = 127.0f;
|
||||
enRu1->actor.world.pos.y = -340.0f;
|
||||
enRu1->actor.world.pos.z = -3041.0f;
|
||||
enRu1->actor.shape.rot.y = enRu1->actor.world.rot.y = -5098;
|
||||
|
||||
if (*should) {
|
||||
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildTurnAroundAnim, 1.0f, 0,
|
||||
Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f);
|
||||
enRu1->action = 10;
|
||||
}
|
||||
|
||||
*should = false;
|
||||
});
|
||||
|
||||
// Skips a short dialogue sequence where Ruto tells you to throw her to the Sapphire
|
||||
REGISTER_VB_SHOULD(VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE, {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*should) {
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE);
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
COND_VB_SHOULD(VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
|
||||
if (*should) {
|
||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE);
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and
|
||||
// waits for link to get closer
|
||||
REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, {
|
||||
EnRu1* enRu1 = va_arg(args, EnRu1*);
|
||||
DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*);
|
||||
COND_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
|
||||
EnRu1* enRu1 = va_arg(args, EnRu1*);
|
||||
DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*);
|
||||
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (*should) {
|
||||
enRu1->unk_28C = (BgBdanObjects*)dynaPolyActor;
|
||||
Flags_SetInfTable(INFTABLE_145);
|
||||
Flags_SetSwitch(gPlayState, 0x02);
|
||||
Flags_SetSwitch(gPlayState, 0x1F);
|
||||
enRu1->action = 42;
|
||||
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0,
|
||||
Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f);
|
||||
// If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting
|
||||
// to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point
|
||||
// Cutscene of Ruto getting lifted up from getting queued up twice.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) ||
|
||||
enRu1->unk_28C->cameraSetting != 2) {
|
||||
enRu1->unk_28C->cameraSetting = 1;
|
||||
}
|
||||
Actor* sapphire = func_80AEB124(gPlayState);
|
||||
if (sapphire != NULL) {
|
||||
Actor_Kill(sapphire);
|
||||
}
|
||||
enRu1->actor.room = gPlayState->roomCtx.curRoom.num;
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
if (*should) {
|
||||
enRu1->unk_28C = (BgBdanObjects*)dynaPolyActor;
|
||||
Flags_SetInfTable(INFTABLE_145);
|
||||
Flags_SetSwitch(gPlayState, 0x02);
|
||||
Flags_SetSwitch(gPlayState, 0x1F);
|
||||
enRu1->action = 42;
|
||||
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0,
|
||||
Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f);
|
||||
// If we aren't skipping one point cutscenes and BgBdan objects has set the camera setting
|
||||
// to CAM_SET_NORMAL1 (2), don't reset the camera setting to 1. This prevents the One Point
|
||||
// Cutscene of Ruto getting lifted up from getting queued up twice.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO) ||
|
||||
enRu1->unk_28C->cameraSetting != 2) {
|
||||
enRu1->unk_28C->cameraSetting = 1;
|
||||
}
|
||||
Actor* sapphire = func_80AEB124(gPlayState);
|
||||
if (sapphire != NULL) {
|
||||
Actor_Kill(sapphire);
|
||||
}
|
||||
enRu1->actor.room = gPlayState->roomCtx.curRoom.num;
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
// This overrides the behavior that causes Ruto to get upset at you before sitting back down again when
|
||||
// INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set
|
||||
GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) {
|
||||
EnRu1* enRu1 = static_cast<EnRu1*>(actorRef);
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enRu1->action == 22) {
|
||||
enRu1->action = 27;
|
||||
enRu1->drawConfig = 1;
|
||||
enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
|
||||
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
|
||||
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
|
||||
}
|
||||
});
|
||||
COND_ID_HOOK(OnActorInit, ACTOR_EN_RU1,
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), Ru1Init);
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterSkipChildRutoInteractions,
|
||||
{ CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" });
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#include "TimeSavers.h"
|
||||
|
||||
void TimeSavers_Register() {
|
||||
// SkipCutscene
|
||||
// Story
|
||||
SkipBlueWarp_Register();
|
||||
SkipDekuTreeIntro_Register();
|
||||
SkipLostWoodsBridge_Register();
|
||||
SkipToGivingZeldasLetter_Register();
|
||||
SkipZeldaFleeingCastle_Register();
|
||||
SkipIntro_Register();
|
||||
// SkipMiscInteractions
|
||||
MoveJabuJabuElevator_Register();
|
||||
MoveMidoInKokiriForest_Register();
|
||||
SkipChildRutoInteractions_Register();
|
||||
FasterHeavyBlockLift_Register();
|
||||
FasterRupeeAccumulator_Register();
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef TIME_SAVERS_H
|
||||
#define TIME_SAVERS_H
|
||||
|
||||
void TimeSavers_Register();
|
||||
|
||||
// SkipCutscene
|
||||
// Story
|
||||
void SkipBlueWarp_Register();
|
||||
void SkipDekuTreeIntro_Register();
|
||||
void SkipLostWoodsBridge_Register();
|
||||
void SkipToGivingZeldasLetter_Register();
|
||||
void SkipZeldaFleeingCastle_Register();
|
||||
void SkipIntro_Register();
|
||||
// SkipMiscInteractions
|
||||
void MoveJabuJabuElevator_Register();
|
||||
void MoveMidoInKokiriForest_Register();
|
||||
void SkipChildRutoInteractions_Register();
|
||||
void FasterHeavyBlockLift_Register();
|
||||
void FasterRupeeAccumulator_Register();
|
||||
|
||||
#endif // TIME_SAVERS_H
|
|
@ -14,7 +14,6 @@
|
|||
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
||||
#include "soh/Enhancements/nametag.h"
|
||||
#include "soh/Enhancements/timesaver_hook_handlers.h"
|
||||
#include "soh/Enhancements/TimeSavers/TimeSavers.h"
|
||||
#include "soh/Enhancements/randomizer/hook_handlers.h"
|
||||
|
||||
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
|
||||
|
@ -1071,7 +1070,6 @@ void InitMods() {
|
|||
BossRush_RegisterHooks();
|
||||
RandomizerRegisterHooks();
|
||||
TimeSaverRegisterHooks();
|
||||
TimeSavers_Register();
|
||||
RegisterTTS();
|
||||
RegisterOcarinaTimeTravel();
|
||||
RegisterDaytimeGoldSkultullas();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue