Migrate okarina_tag changes

This commit is contained in:
Garrett Cox 2024-02-21 14:01:49 -06:00
parent 37e89c0c7c
commit 7bebe7a573
7 changed files with 117 additions and 66 deletions

View File

@ -206,6 +206,9 @@ typedef enum {
// Opt: *EnSyatekiMan // Opt: *EnSyatekiMan
// Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)
GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD,
// Opt: *EnOkarinaTag
// Vanilla condition: !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME)
GI_VB_BE_ELIGIBLE_TO_OPEN_DOT,
/*** Play Cutscenes ***/ /*** Play Cutscenes ***/
@ -235,6 +238,16 @@ typedef enum {
GI_VB_PLAY_BOLERO_OF_FIRE_CS, GI_VB_PLAY_BOLERO_OF_FIRE_CS,
GI_VB_PLAY_SERENADE_OF_WATER_CS, GI_VB_PLAY_SERENADE_OF_WATER_CS,
GI_VB_PLAY_EYEDROPS_CS, GI_VB_PLAY_EYEDROPS_CS,
// Opt: *EnOkarinaTag
GI_VB_PLAY_DRAIN_WELL_CS,
// Opt: *EnOkarinaTag
// Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SUN)
GI_VB_PLAY_SUNS_SONG_CS,
// Opt: *EnOkarinaTag
GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS,
GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE,
// Opt: *EnOkarinaTag
GI_VB_PLAY_DOOR_OF_TIME_CS,
/*** Give Items ***/ /*** Give Items ***/

View File

@ -796,6 +796,16 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void
} }
break; break;
} }
case GI_VB_BE_ELIGIBLE_TO_OPEN_DOT: {
bool eligible = RAND_GET_OPTION(RSK_DOOR_OF_TIME) != RO_DOOROFTIME_CLOSED || (
INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_TIME &&
CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) &&
CHECK_QUEST_ITEM(QUEST_GORON_RUBY) &&
CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)
);
*should = eligible;
break;
}
case GI_VB_TRADE_CLAIM_CHECK: case GI_VB_TRADE_CLAIM_CHECK:
case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_ODD_MUSHROOM:
case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_EYEDROPS:

View File

@ -1314,7 +1314,7 @@ void Rando::StaticData::InitLocationTable() { //
locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_SONG_FROM_IMPA] = Location::Delayed(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x26, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x59), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true);
locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); locationTable[RC_SONG_FROM_MALON] = Location::Delayed(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x27, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, { Category::cSong }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true);
locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); locationTable[RC_SONG_FROM_SARIA] = Location::Delayed(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x28, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true);
locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x00), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Delayed(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x29, "Song from Composers Grave", "Song from Composers Grave", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true);
locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Delayed(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2A, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xA9), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true);
locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_SONG_FROM_WINDMILL] = Location::Delayed(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x2B, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true);

View File

@ -19,6 +19,7 @@ extern "C" {
#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h" #include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h"
#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h"
#include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h"
#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h"
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
extern PlayState* gPlayState; extern PlayState* gPlayState;
} }
@ -471,6 +472,44 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void*
} }
break; break;
} }
case GI_VB_PLAY_DRAIN_WELL_CS: {
if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
*should = false;
Flags_SetSwitch(gPlayState, 0x2);
Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL);
Flags_SetEventChkInf(EVENTCHKINF_DRAINED_WELL_IN_KAKARIKO);
}
break;
}
case GI_VB_PLAY_SUNS_SONG_CS:
if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) {
*should = false;
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG);
// SoH [Randomizer] TODO: Increment time X amount (find out X)
// When time is 0, it's changed to 0x46A7
// When it's 0x8000, it's changed to 0xC090
}
break;
case GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS: {
if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) {
*should = false;
}
break;
}
case GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: {
if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) {
*should = Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB);
}
break;
}
case GI_VB_PLAY_DOOR_OF_TIME_CS: {
if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) {
*should = false;
Flags_SetEnv(gPlayState, 2);
func_80078884(NA_SE_SY_CORRECT_CHIME);
}
break;
}
case GI_VB_GIVE_ITEM_MINUET_OF_FOREST: case GI_VB_GIVE_ITEM_MINUET_OF_FOREST:
case GI_VB_GIVE_ITEM_BOLERO_OF_FIRE: case GI_VB_GIVE_ITEM_BOLERO_OF_FIRE:
case GI_VB_GIVE_ITEM_SERENADE_OF_WATER: case GI_VB_GIVE_ITEM_SERENADE_OF_WATER:
@ -534,6 +573,8 @@ static uint32_t enMa1UpdateHook = 0;
static uint32_t enMa1KillHook = 0; static uint32_t enMa1KillHook = 0;
static uint32_t enFuUpdateHook = 0; static uint32_t enFuUpdateHook = 0;
static uint32_t enFuKillHook = 0; static uint32_t enFuKillHook = 0;
static uint32_t bgSpot02UpdateHook = 0;
static uint32_t bgSpot02KillHook = 0;
void TimeSaverOnActorInitHandler(void* actorRef) { void TimeSaverOnActorInitHandler(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef); Actor* actor = static_cast<Actor*>(actorRef);
@ -610,7 +651,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) {
} }
if (actor->id == ACTOR_EN_FU) { if (actor->id == ACTOR_EN_FU) {
enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable { enFuUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable {
Actor* innerActor = static_cast<Actor*>(innerActorRef); Actor* innerActor = static_cast<Actor*>(innerActorRef);
if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) { if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) {
EnFu* enFu = static_cast<EnFu*>(innerActorRef); EnFu* enFu = static_cast<EnFu*>(innerActorRef);
@ -623,11 +664,36 @@ void TimeSaverOnActorInitHandler(void* actorRef) {
} }
} }
}); });
enMa1KillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable { enFuKillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enMa1UpdateHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enFuUpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enMa1KillHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enFuKillHook);
enMa1UpdateHook = 0; enFuUpdateHook = 0;
enMa1KillHook = 0; enFuKillHook = 0;
});
}
if (actor->id == ACTOR_BG_SPOT02_OBJECTS && actor->params == 2) {
SPDLOG_INFO("Registering BG_SPOT02 hook");
bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable {
Actor* innerActor = static_cast<Actor*>(innerActorRef);
if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0))) {
SPDLOG_INFO("on update BG_SPOT02 hook");
BgSpot02Objects* bgSpot02 = static_cast<BgSpot02Objects*>(innerActorRef);
if (bgSpot02->actionFunc == func_808ACC34) {
SPDLOG_INFO("BGspot02 OVERRIDDEN");
bgSpot02->actionFunc = func_808AC908;
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(bgSpot02UpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(bgSpot02KillHook);
bgSpot02UpdateHook = 0;
bgSpot02KillHook = 0;
}
}
});
bgSpot02KillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(bgSpot02UpdateHook);
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(bgSpot02KillHook);
bgSpot02UpdateHook = 0;
bgSpot02KillHook = 0;
}); });
} }
@ -781,6 +847,9 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
case EVENTCHKINF_LEARNED_SONG_OF_STORMS: case EVENTCHKINF_LEARNED_SONG_OF_STORMS:
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy(); vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy();
break; break;
case EVENTCHKINF_LEARNED_SUNS_SONG:
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SUNS_SONG).GetGIEntry_Copy();
break;
} }
break; break;
case FLAG_RANDOMIZER_INF: case FLAG_RANDOMIZER_INF:

View File

@ -6,6 +6,7 @@
#include "z_bg_spot02_objects.h" #include "z_bg_spot02_objects.h"
#include "objects/object_spot02_objects/object_spot02_objects.h" #include "objects/object_spot02_objects/object_spot02_objects.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
@ -129,20 +130,7 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) {
static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
Vec3f pos; Vec3f pos;
// We want to do most of the same things in rando, but we're not in a cutscene and the flag for if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, play->csCtx.state != 0 && play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2, this)) {
// destroying the royal tombstone is already set.
if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) {
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION);
this->timer = 25;
pos.x = (Math_SinS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.x;
pos.y = this->dyna.actor.world.pos.y + 30.0f;
pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z;
EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30);
this->actionFunc = func_808ACA08;
}
if (play->csCtx.state != 0) {
if (play->csCtx.npcActions[3] != NULL && play->csCtx.npcActions[3]->action == 2) {
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION);
Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB);
this->timer = 25; this->timer = 25;
@ -151,7 +139,6 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) {
pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z; pos.z = (Math_CosS(this->dyna.actor.shape.rot.y) * 50.0f) + this->dyna.actor.world.pos.z;
EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30); EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30);
this->actionFunc = func_808ACA08; this->actionFunc = func_808ACA08;
}
} }
} }
@ -174,7 +161,7 @@ void func_808ACA08(BgSpot02Objects* this, PlayState* play) {
// This shouldn't execute in rando even without the check since we never // This shouldn't execute in rando even without the check since we never
// enter the cutscene context. // enter the cutscene context.
if (play->csCtx.frames == 402 && !(IS_RANDO)) { if (play->csCtx.frames == 402) {
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
Player_PlaySfx(&player->actor, NA_SE_VO_LI_DEMO_DAMAGE_KID); Player_PlaySfx(&player->actor, NA_SE_VO_LI_DEMO_DAMAGE_KID);
} else { } else {
@ -217,13 +204,6 @@ void BgSpot02Objects_Draw(Actor* thisx, PlayState* play) {
} }
void func_808ACC34(BgSpot02Objects* this, PlayState* play) { void func_808ACC34(BgSpot02Objects* this, PlayState* play) {
// This is the actionFunc that the game settles on when you load the Graveyard
// When we're in rando and the flag for the gravestone being destroyed gets set,
// set the actionFunc to the function where the gravestone explodes.
if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) {
this->actionFunc = func_808AC908;
}
if (play->csCtx.state != 0 && play->csCtx.npcActions[0] != NULL && if (play->csCtx.state != 0 && play->csCtx.npcActions[0] != NULL &&
play->csCtx.npcActions[0]->action == 2) { play->csCtx.npcActions[0]->action == 2) {
this->unk_16A++; this->unk_16A++;

View File

@ -19,4 +19,7 @@ typedef struct BgSpot02Objects {
/* 0x0172 */ u16 unk_172; /* 0x0172 */ u16 unk_172;
} BgSpot02Objects; // size = 0x0174 } BgSpot02Objects; // size = 0x0174
void func_808ACC34(BgSpot02Objects* bgSpot02Objects, PlayState* play);
void func_808AC908(BgSpot02Objects* bgSpot02Objects, PlayState* play);
#endif #endif

View File

@ -8,6 +8,7 @@
#include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" #include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h"
#include "scenes/overworld/spot02/spot02_scene.h" #include "scenes/overworld/spot02/spot02_scene.h"
#include "vt.h" #include "vt.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
@ -192,7 +193,7 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) {
if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) {
if ((this->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) { if ((this->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) {
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
} else if (((this->type != 4) || !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME)) && } else if (((this->type != 4) || GameInteractor_Should(GI_VB_BE_ELIGIBLE_TO_OPEN_DOT, !Flags_GetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME), this)) &&
((this->type != 6) || !Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) && ((this->type != 6) || !Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB)) &&
(this->actor.xzDistToPlayer < (90.0f + this->interactRange)) && (this->actor.xzDistToPlayer < (90.0f + this->interactRange)) &&
(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 80.0f)) { (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < 80.0f)) {
@ -234,47 +235,30 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) {
if (play->msgCtx.ocarinaMode == OCARINA_MODE_04) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_04) {
this->actionFunc = func_80ABF28C; this->actionFunc = func_80ABF28C;
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
if (!IS_RANDO || (IS_RANDO && Randomizer_GetSettingValue(RSK_DOOR_OF_TIME) != RO_DOOROFTIME_CLOSED)) { func_80078884(NA_SE_SY_CORRECT_CHIME);
func_80078884(NA_SE_SY_CORRECT_CHIME);
}
if (this->switchFlag >= 0) { if (this->switchFlag >= 0) {
Flags_SetSwitch(play, this->switchFlag); Flags_SetSwitch(play, this->switchFlag);
} }
switch (this->type) { switch (this->type) {
case 1: case 1: // Zora's River Waterfall
Flags_SetSwitch(play, this->switchFlag); Flags_SetSwitch(play, this->switchFlag);
Flags_SetEventChkInf(EVENTCHKINF_OPENED_ZORAS_DOMAIN); Flags_SetEventChkInf(EVENTCHKINF_OPENED_ZORAS_DOMAIN);
break; break;
case 2: case 2: // Kakariko Windmill
if (!IS_RANDO) { if (GameInteractor_Should(GI_VB_PLAY_DRAIN_WELL_CS, true, this)) {
play->csCtx.segment = D_80ABF9D0; play->csCtx.segment = D_80ABF9D0;
gSaveContext.cutsceneTrigger = 1; gSaveContext.cutsceneTrigger = 1;
} else {
Flags_SetEventChkInf(EVENTCHKINF_DRAINED_WELL_IN_KAKARIKO);
Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL);
} }
func_800F574C(1.18921f, 0x5A); func_800F574C(1.18921f, 0x5A);
break; break;
case 4: case 4: // Door of Time
if (IS_RANDO) { if (GameInteractor_Should(GI_VB_PLAY_DOOR_OF_TIME_CS, true, this)) {
if (Randomizer_GetSettingValue(RSK_DOOR_OF_TIME) == RO_DOOROFTIME_CLOSED &&
(INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_OCARINA_TIME ||
!CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || !CHECK_QUEST_ITEM(QUEST_GORON_RUBY) ||
!CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE))) {
func_80078884(NA_SE_SY_OCARINA_ERROR);
break;
} else {
Flags_SetEnv(play, 2);
func_80078884(NA_SE_SY_CORRECT_CHIME);
}
} else {
play->csCtx.segment = D_80ABFB40; play->csCtx.segment = D_80ABFB40;
gSaveContext.cutsceneTrigger = 1; gSaveContext.cutsceneTrigger = 1;
} }
break; break;
case 6: case 6: // Royal Family Tomb
// Don't start the cutscene in a rando save. if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS, true, this)) {
if (!(IS_RANDO)) {
play->csCtx.segment = LINK_IS_ADULT ? SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_003C80) play->csCtx.segment = LINK_IS_ADULT ? SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_003C80)
: SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_005020); : SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_005020);
gSaveContext.cutsceneTrigger = 1; gSaveContext.cutsceneTrigger = 1;
@ -311,7 +295,7 @@ void func_80ABF708(EnOkarinaTag* this, PlayState* play) {
yawDiff = this->actor.yawTowardsPlayer - this->actor.world.rot.y; yawDiff = this->actor.yawTowardsPlayer - this->actor.world.rot.y;
this->unk_15A++; this->unk_15A++;
if (!(this->actor.xzDistToPlayer > 120.0f)) { if (!(this->actor.xzDistToPlayer > 120.0f)) {
if (CHECK_QUEST_ITEM(QUEST_SONG_SUN) || IS_RANDO) { if (CHECK_QUEST_ITEM(QUEST_SONG_SUN)) {
this->actor.textId = 0x5021; this->actor.textId = 0x5021;
} }
yawDiffNew = ABS(yawDiff); yawDiffNew = ABS(yawDiff);
@ -323,23 +307,15 @@ void func_80ABF708(EnOkarinaTag* this, PlayState* play) {
} }
} }
void GivePlayerRandoRewardSunSong(EnOkarinaTag* song, PlayState* play, RandomizerCheck check) {
Flags_SetTreasure(play, 0x1F);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, GI_LETTER_ZELDA);
GiveItemEntryFromActor(&song->actor, play, getItemEntry, 10000.0f, 100.0f);
}
void func_80ABF7CC(EnOkarinaTag* this, PlayState* play) { void func_80ABF7CC(EnOkarinaTag* this, PlayState* play) {
// "Open sesame sesame!" // "Open sesame sesame!"
osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 開けゴマゴマゴマ! ☆☆☆☆☆ %d\n" VT_RST, Message_GetState(&play->msgCtx)); osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 開けゴマゴマゴマ! ☆☆☆☆☆ %d\n" VT_RST, Message_GetState(&play->msgCtx));
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
if (!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_SONG_SUN)) { if (GameInteractor_Should(GI_VB_PLAY_SUNS_SONG_CS, !CHECK_QUEST_ITEM(QUEST_SONG_SUN), this)) {
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gSunSongGraveSunSongTeachCs); play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gSunSongGraveSunSongTeachCs);
gSaveContext.cutsceneTrigger = 1; gSaveContext.cutsceneTrigger = 1;
} else if (IS_RANDO && !Flags_GetTreasure(play, 0x1F)) {
GivePlayerRandoRewardSunSong(this, play, RC_SONG_FROM_ROYAL_FAMILYS_TOMB);
} }
this->actionFunc = func_80ABF708; this->actionFunc = func_80ABF708;
} }