diff --git a/libultraship b/libultraship index b135db823..493639d5d 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit b135db823aaabf6e848fcbd2796933b0771f9968 +Subproject commit 493639d5daf75c8fa5d374f96fc95b652714299f diff --git a/soh/include/functions.h b/soh/include/functions.h index 850ddb8d8..8ee00ed8d 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -183,6 +183,8 @@ void __osSetWatchLo(u32); EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params); EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params); void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry); +void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc); +void func_8001E5C8(EnItem00* this, PlayState* play); void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnPos, s16 params); void EffectBlure_ChangeType(EffectBlure* this, int type); void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2); @@ -415,6 +417,7 @@ f32 Actor_WorldDistXZToPoint(Actor* actor, Vec3f* refPoint); void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2); f32 Actor_HeightDiff(Actor* actorA, Actor* actorB); f32 Player_GetHeight(Player* player); +s32 Player_ActionChange_2(Player* player, PlayState* play); f32 func_8002DCE4(Player* player); s32 func_8002DD6C(Player* player); s32 func_8002DD78(Player* player); @@ -426,7 +429,7 @@ void Actor_MountHorse(PlayState* play, Player* player, Actor* horse); s32 func_8002DEEC(Player* player); void func_8002DF18(PlayState* play, Player* player); s32 func_8002DF38(PlayState* play, Actor* actor, u8 csMode); -s32 func_8002DF54(PlayState* play, Actor* actor, u8 arg2); +s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 arg2); void func_8002DF90(DynaPolyActor* dynaActor); void func_8002DFA4(DynaPolyActor* dynaActor, f32 arg1, s16 arg2); s32 Player_IsFacingActor(Actor* actor, s16 angle, PlayState* play); @@ -454,11 +457,11 @@ u32 Actor_TextboxIsClosing(Actor* actor, PlayState* play); s8 func_8002F368(PlayState* play); void Actor_GetScreenPos(PlayState* play, Actor* actor, s16* x, s16* y); u32 Actor_HasParent(Actor* actor, PlayState* play); -// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename func_8002F434 and func_8002F554. +// TODO: Rename the follwing 3 functions using whatever scheme we use when we rename Actor_OfferGetItem and func_8002F554. s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry); s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEntry, f32 xzRange, f32 yRange); s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemEntry getItemEntry); -s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange); +s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange); void func_8002F554(Actor* actor, PlayState* play, s32 getItemId); void func_8002F580(Actor* actor, PlayState* play); u32 Actor_HasNoParent(Actor* actor, PlayState* play); @@ -572,8 +575,6 @@ void Flags_UnsetRandomizerInf(RandomizerInf flag); u16 func_80037C30(PlayState* play, s16 arg1); s32 func_80037D98(PlayState* play, Actor* actor, s16 arg2, s32* arg3); s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f arg4); -GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, PlayState* play); -s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play); // ? func_80038600(?); u16 DynaSSNodeList_GetNextNodeIdx(DynaSSNodeList*); @@ -1106,6 +1107,7 @@ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input); u8 PlayerGrounded(Player* player); void Player_SetBootData(PlayState* play, Player* player); s32 Player_InBlockingCsMode(PlayState* play, Player* player); +s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction); s32 Player_InCsMode(PlayState* play); s32 func_8008E9C4(Player* player); s32 Player_IsChildWithHylianShield(Player* player); diff --git a/soh/include/z64actor.h b/soh/include/z64actor.h index 0a8ac9297..156f1d679 100644 --- a/soh/include/z64actor.h +++ b/soh/include/z64actor.h @@ -266,7 +266,12 @@ typedef enum { /* 0x17 */ ITEM00_TUNIC_ZORA, /* 0x18 */ ITEM00_TUNIC_GORON, /* 0x19 */ ITEM00_BOMBS_SPECIAL, - /* 0x20 */ ITEM00_BOMBCHU, + /* 0x1A */ ITEM00_BOMBCHU, + /* 0x1B */ ITEM00_SOH_DUMMY, + /* 0x1C */ ITEM00_SOH_GIVE_ITEM_ENTRY, + /* 0x1D */ ITEM00_SOH_GIVE_ITEM_ENTRY_GI, + /* 0x1E */ ITEM00_MAX, + /* 0xFF */ ITEM00_NONE = 0xFF } Item00Type; struct EnItem00; @@ -284,10 +289,13 @@ typedef struct EnItem00 { /* 0x15A */ s16 unk_15A; /* 0x15C */ f32 scale; /* 0x160 */ ColliderCylinder collider; - s16 ogParams; + // #region SOH [Randomizer] GetItemEntry randoGiEntry; RandomizerCheck randoCheck; RandomizerInf randoInf; + /* */ s16 ogParams; + /* */ GetItemEntry itemEntry; + // #endregion } EnItem00; // size = 0x1AC // Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files. diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 0f527925d..617c2acf5 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -283,7 +283,7 @@ typedef struct { // #endregion // #region SOH [Randomizer] // Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer - /* */ u16 randomizerInf[16]; + /* */ u16 randomizerInf[17]; /* */ u8 mqDungeonCount; /* */ u16 adultTradeItems; /* */ u8 triforcePiecesCollected; diff --git a/soh/soh/Enhancements/boss-rush/BossRush.cpp b/soh/soh/Enhancements/boss-rush/BossRush.cpp index 63414f88c..9dbbad527 100644 --- a/soh/soh/Enhancements/boss-rush/BossRush.cpp +++ b/soh/soh/Enhancements/boss-rush/BossRush.cpp @@ -129,15 +129,15 @@ void BossRush_SpawnBlueWarps(PlayState* play) { // Spawn blue warps in Chamber of Sages based on what bosses have been defeated. if (gSaveContext.linkAge == LINK_AGE_CHILD) { // Forest Medallion (Gohma) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false); } // Fire Medallion (King Dodongo) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false); } // Water Medallion (Barinade) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false); } } else { @@ -146,15 +146,15 @@ void BossRush_SpawnBlueWarps(PlayState* play) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -199, 6, 0, 0, 0, 0, -1, false); } // Forest Medallion (Phantom Ganondorf) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, -100, 6, -170, 0, 0, 0, -1, false); } // Fire Medallion (Volvagia) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 100, 6, -170, 0, 0, 0, -1, false); } // Water Medallion (Morpha) - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_DOOR_WARP1, 199, 6, 0, 0, 0, 0, -1, false); } // Spirit Medallion (Twinrova) @@ -242,22 +242,22 @@ void BossRush_HandleCompleteBoss(PlayState* play) { gSaveContext.isBossRushPaused = 1; switch (play->sceneNum) { case SCENE_DEKU_TREE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); + Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); break; case SCENE_DODONGOS_CAVERN_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); + Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); break; case SCENE_JABU_JABU_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); + Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); break; case SCENE_FOREST_TEMPLE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); break; case SCENE_FIRE_TEMPLE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); break; case SCENE_WATER_TEMPLE_BOSS: - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); break; case SCENE_SPIRIT_TEMPLE_BOSS: Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); @@ -432,13 +432,13 @@ void BossRush_InitSave() { // Set flags and Link's age based on chosen settings. if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ADULT || gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) { - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); + Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) { - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); + Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); + Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); } diff --git a/soh/soh/Enhancements/cheat_hook_handlers.cpp b/soh/soh/Enhancements/cheat_hook_handlers.cpp new file mode 100644 index 000000000..cdc8333ce --- /dev/null +++ b/soh/soh/Enhancements/cheat_hook_handlers.cpp @@ -0,0 +1,56 @@ +#include +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/enhancementTypes.h" + +extern "C" { +#include "macros.h" +#include "variables.h" + +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +} + +void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { + switch (id) { + case GI_VB_DEKU_STICK_BREAK: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + *should = false; + } + break; + } + case GI_VB_DEKU_STICK_BE_ON_FIRE: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { + Player* player = GET_PLAYER(gPlayState); + player->unk_860 = 200; // Keeps the stick's flame lit + player->unk_85C = 1.0f; // Ensures the stick is the proper length + *should = true; + } + break; + } + case GI_VB_DEKU_STICK_BURN_OUT: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + *should = false; + } + break; + } + case GI_VB_DEKU_STICK_BURN_DOWN: { + if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) { + *should = false; + } + break; + } + } +} + +static uint32_t onVanillaBehaviorHook = 0; +void CheatsRegisterHooks() { + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) mutable { + + GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); + onVanillaBehaviorHook = 0; + onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(CheatsOnVanillaBehaviorHandler); + + }); +} diff --git a/soh/soh/Enhancements/cheat_hook_handlers.h b/soh/soh/Enhancements/cheat_hook_handlers.h new file mode 100644 index 000000000..88a79f285 --- /dev/null +++ b/soh/soh/Enhancements/cheat_hook_handlers.h @@ -0,0 +1,6 @@ +#ifndef CHEAT_HOOK_HANDLERS_H +#define CHEAT_HOOK_HANDLERS_H + +void CheatsRegisterHooks(); + +#endif // CHEAT_HOOK_HANDLERS_H diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index b0650bfa0..53cd4b7ae 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -349,22 +349,9 @@ const std::vector flagTables = { { 0x30, "Entered the Market" }, } }, { "Randomizer Inf Flags", RANDOMIZER_INF, 16, { - { RAND_INF_DUNGEONS_DONE_DEKU_TREE, "DUNGEONS_DONE_DEKU_TREE" }, - { RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN, "DUNGEONS_DONE_DODONGOS_CAVERN" }, - { RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY, "DUNGEONS_DONE_JABU_JABUS_BELLY" }, - { RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE, "DUNGEONS_DONE_FOREST_TEMPLE" }, - { RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE, "DUNGEONS_DONE_FIRE_TEMPLE" }, - { RAND_INF_DUNGEONS_DONE_WATER_TEMPLE, "DUNGEONS_DONE_WATER_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, "DUNGEONS_DONE_SPIRIT_TEMPLE" }, { RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, "DUNGEONS_DONE_SHADOW_TEMPLE" }, - { RAND_INF_TRIALS_DONE_LIGHT_TRIAL, "TRIALS_DONE_LIGHT_TRIAL" }, - { RAND_INF_TRIALS_DONE_FOREST_TRIAL, "TRIALS_DONE_FOREST_TRIAL" }, - { RAND_INF_TRIALS_DONE_FIRE_TRIAL, "TRIALS_DONE_FIRE_TRIAL" }, - { RAND_INF_TRIALS_DONE_WATER_TRIAL, "TRIALS_DONE_WATER_TRIAL" }, - { RAND_INF_TRIALS_DONE_SPIRIT_TRIAL, "TRIALS_DONE_SPIRIT_TRIAL" }, - { RAND_INF_TRIALS_DONE_SHADOW_TRIAL, "TRIALS_DONE_SHADOW_TRIAL" }, - { RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, "COWS_MILKED_KF_LINKS_HOUSE_COW" }, { RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, "COWS_MILKED_HF_COW_GROTTO_COW" }, { RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, "COWS_MILKED_LLR_STABLES_LEFT_COW" }, @@ -505,6 +492,7 @@ const std::vector flagTables = { { RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" }, { RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" }, { RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" }, + { RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" }, { RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" }, { RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" }, @@ -515,7 +503,6 @@ const std::vector flagTables = { { RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" }, { RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" }, { RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" }, - { RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" }, { RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"}, { RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" }, @@ -607,7 +594,19 @@ const std::vector flagTables = { { RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" }, { RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" }, { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" }, - { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" } + { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }, + + { RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" }, + { RAND_INF_LEARNED_EPONA_SONG, "RAND_INF_LEARNED_EPONA_SONG" }, + { RAND_INF_DARUNIAS_JOY, "RAND_INF_DARUNIAS_JOY" }, + { RAND_INF_KING_ZORA_THAWED, "RAND_INF_KING_ZORA_THAWED" }, + + { RAND_INF_HC_GREAT_FAIRY_REWARD, "RAND_INF_HC_GREAT_FAIRY_REWARD" }, + { RAND_INF_DMT_GREAT_FAIRY_REWARD, "RAND_INF_DMT_GREAT_FAIRY_REWARD" }, + { RAND_INF_DMC_GREAT_FAIRY_REWARD, "RAND_INF_DMC_GREAT_FAIRY_REWARD" }, + { RAND_INF_ZF_GREAT_FAIRY_REWARD, "RAND_INF_ZF_GREAT_FAIRY_REWARD" }, + { RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD, "RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD" }, + { RAND_INF_OGC_GREAT_FAIRY_REWARD, "RAND_INF_OGC_GREAT_FAIRY_REWARD" }, } }, }; diff --git a/soh/soh/Enhancements/debugger/valueViewer.cpp b/soh/soh/Enhancements/debugger/valueViewer.cpp index 14a571dac..213c81cfa 100644 --- a/soh/soh/Enhancements/debugger/valueViewer.cpp +++ b/soh/soh/Enhancements/debugger/valueViewer.cpp @@ -34,6 +34,8 @@ std::vector valueTable = { { "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE }, { "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE }, { "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE }, + { "getItemID", "Player->getItemId", "ITEM:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemId; }, WHITE }, + { "getItemEntry", "Player->getItemEntry", "IE:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemEntry.itemId; }, WHITE }, /* TODO: Find these (from GZ) "XZ Units Traveled (Camera based speed variable)" f32 0x801C9018 "Movement Angle" x16 0x801DBB1C diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h index 56160567a..3dce64b12 100644 --- a/soh/soh/Enhancements/enhancementTypes.h +++ b/soh/soh/Enhancements/enhancementTypes.h @@ -14,6 +14,13 @@ typedef enum { CSMC_SIZE } ChestStyleMatchesContentsType; +typedef enum { + SGIA_DISABLED, + SGIA_JUNK, + SGIA_ALL, + SGIA_SIZE +} SkipGetItemAnimationType; + typedef enum { BUNNY_HOOD_VANILLA, BUNNY_HOOD_FAST_AND_JUMP, diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 7503dbd78..84126099f 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -3,6 +3,7 @@ #ifndef GameInteractor_h #define GameInteractor_h +#include "libultraship/libultraship.h" #include "GameInteractionEffect.h" #include "soh/Enhancements/item-tables/ItemTableTypes.h" #include @@ -67,6 +68,328 @@ typedef enum { /* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7, } GITeleportDestinations; +typedef enum { + // Vanilla condition: gSaveContext.showTitleCard + GI_VB_SHOW_TITLE_CARD, + // Opt: *EnWonderTalk2 + GI_VB_WONDER_TALK, + // Opt: *ElfMsg + GI_VB_NAVI_TALK, + // Vanilla condition: INFTABLE_GREETED_BY_SARIA + GI_VB_NOT_BE_GREETED_BY_SARIA, + // Opt: *EnMd + // Vanilla condition: EnMd->interactInfo.talkState == NPC_TALK_STATE_ACTION + GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, + // Opt: *EnMd + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) + GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, + // Opt: *ObjDekujr + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) + GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, + // Opt: *EnKo + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) + GI_VB_OPEN_KOKIRI_FOREST, + // Opt: *EnOwl + // Vanilla condition: EnOwl->actor.xzDistToPlayer < targetDist + GI_VB_OWL_INTERACTION, + // Vanilla condition: EVENTCHKINF_TALON_RETURNED_FROM_CASTLE + GI_VB_MALON_RETURN_FROM_CASTLE, + // Vanilla condition: CUR_UPG_VALUE(UPG_STRENGTH) <= 0 + GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, + /* Vanilla condition: + ``` + LINK_IS_ADULT && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + ``` + */ + GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, + // Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SARIA) + GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_SONG_EPONA) + GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, + // Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) + GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, + // Vanilla condition: (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT + GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, + // Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP + GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, + GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, + /* Vanilla Condition: + ``` + LINK_IS_ADULT && + gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && + Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + ``` + */ + GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, + // Opt: *EnGo2 + // Vanilla condition: CUR_CAPACITY(UPG_BOMB_BAG) >= 20 && this->waypoint > 7 && this->waypoint < 12 + GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, + // Vanilla condition: !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) + GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, + // Opt: *EnMs + // Vanilla condition: gSaveContext.rupees >= sPrices[BEANS_BOUGHT] + GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, + // Opt: *EnItem00 + // Vanilla condition: Flags_GetCollectible(play, this->collectibleFlag) + GI_VB_ITEM00_DESPAWN, + // Opt: *EnTk + // Vanilla condition: gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD + GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, + // Opt: *EnTk + // Vanilla condition: this->validDigHere == 1 + GI_VB_BE_VALID_GRAVEDIGGING_SPOT, + // Opt: *EnTk + // Vanilla condition: this->currentReward == 3 + GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, + // Opt: *EnTk + // Vanilla condition: !Flags_GetItemGetInf(ITEMGETINF_1C) + GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, + // Opt: *EnShopnuts + /* Vanilla Condition: + ``` + ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || + ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) || + ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))) + ``` + */ + GI_VB_BUSINESS_SCRUB_DESPAWN, + // Opt: *EnCow + // Vanilla condition: play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) + GI_VB_DESPAWN_HORSE_RACE_COW, + // Opt: *EnHs + // Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30) + GI_VB_DESPAWN_GROG, + // Opt: *EnKo + // Vanilla condition: (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false; + GI_VB_SPAWN_LW_FADO, + // Opt: *EnMk + GI_VB_PLAY_EYEDROP_CREATION_ANIM, + // Opt: *EnDs + GI_VB_PLAY_ODD_POTION_ANIM, + // Opt: *EnMk + // Vanilla condition: INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS + GI_VB_USE_EYEDROP_DIALOGUE, + // Opt: *EnMk + // Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30) + GI_VB_OFFER_BLUE_POTION, + // Vanilla condition: Inventory_HasEmptyBottle() == 0 + GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, + // Opt: *EnNiwLady + GI_VB_SET_CUCCO_COUNT, + // Opt: *EnKz + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) + GI_VB_KING_ZORA_THANK_CHILD, + // Opt: *EnKz + // Vanilla condition: this->actor.textId == 0x401A + GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, + // Opt: *EnKz + // Vanilla condition: Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) + GI_VB_KING_ZORA_BE_MOVED, + // Vanilla condition: gSaveState.bgsFlag + GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, + // Vanilla condition: gSaveState.bgsFlag + GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, + // Vanilla condition: Environment_GetBgsDayCount() >= 3 + GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) + GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, + // Vanilla condition: CHECK_QUEST_ITEM(QUEST_GORON_RUBY) + GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, + // Opt: *uint16_t + // Vanilla condition: false + GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, + // Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON) + GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, + // Opt: *EnSyatekiMan + // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) + 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, + // Opt: *BgDyYoseizo + // Vanilla condition: see soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c + GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, + // Vanilla condition: see CheckCarpentersFreed in z_en_ge1 and z_en_ge2 + GI_VB_GERUDOS_BE_FRIENDLY, + // Vanilla condition: switch + GI_VB_GTG_GATE_BE_OPEN, + + /*** Play Cutscenes ***/ + + GI_VB_PLAY_TRANSITION_CS, + // Opt: *EventChkInf flag + GI_VB_PLAY_ENTRANCE_CS, + // Opt: *cutsceneId + GI_VB_PLAY_ONEPOINT_CS, + // Opt: *actor + GI_VB_PLAY_ONEPOINT_ACTOR_CS, + // Opt: *BgTreemouth + GI_VB_PLAY_DEKU_TREE_INTRO_CS, + // Vanilla condition: !EventChkInf except for spirit & shadow temple which are !medallion, and Jabu which always is true + GI_VB_PLAY_BLUE_WARP_CS, + GI_VB_PLAY_DARUNIAS_JOY_CS, + GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, + // Vanilla condition: !EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL + GI_VB_PLAY_PULL_MASTER_SWORD_CS, + GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, + // Vanilla condition: player->getItemId == GI_GAUNTLETS_SILVER + GI_VB_PLAY_NABOORU_CAPTURED_CS, + GI_VB_PLAY_ZELDAS_LULLABY_CS, + // Opt: *EnSa + GI_VB_PLAY_SARIAS_SONG_CS, + GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, + GI_VB_PLAY_MINUET_OF_FOREST_CS, + GI_VB_PLAY_BOLERO_OF_FIRE_CS, + GI_VB_PLAY_SERENADE_OF_WATER_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, + GI_VB_PLAY_RAINBOW_BRIDGE_CS, + + /*** Give Items ***/ + + // Opt: *EnBox + GI_VB_GIVE_ITEM_FROM_CHEST, + GI_VB_GIVE_ITEM_FROM_BLUE_WARP, + // Opt: *EnItem00 + GI_VB_GIVE_ITEM_FROM_ITEM_00, + // Opt: *EnSi + GI_VB_GIVE_ITEM_SKULL_TOKEN, + // Opt: *EnCow + GI_VB_GIVE_ITEM_FROM_COW, + // Opt: *EnDns + GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, + // Opt: *EnMk + GI_VB_GIVE_ITEM_FROM_LAB_DIVE, + // Opt: *EnDs + GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, + // Opt: *EnNiwLady + GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, + // Opt: *EnNiwLady + GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, + // Opt: *EnKz + // Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) + GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, + // Opt: *EnGo2 + GI_VB_GIVE_ITEM_FROM_GORON, + // Opt: *EnJs + GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, + // Opt: *EnGm + GI_VB_GIVE_ITEM_FROM_MEDIGORON, + // Opt: *EnMs + GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, + // Opt: *EnFr + GI_VB_GIVE_ITEM_FROM_FROGS, + // Opt: *EnSkj + GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, + // Opt: *EnSkj + GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, + GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, + // Opt: *EnSyatekiMan + GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, + // Opt: *EnExItem + GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, + // Opt: *EnTa + GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, + // Opt: *EnDivingGame + GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, + // Opt: *EnGe1 + GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, + // Opt: *EnSth + GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, + // Opt: *EnHy + GI_VB_GIVE_ITEM_FROM_LOST_DOG, + // Opt: *EnBomBowlPit + GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, + + GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, + + GI_VB_GIVE_ITEM_FAIRY_OCARINA, + GI_VB_GIVE_ITEM_WEIRD_EGG, + GI_VB_GIVE_ITEM_LIGHT_ARROW, + GI_VB_GIVE_ITEM_STRENGTH_1, + GI_VB_GIVE_ITEM_ZELDAS_LETTER, + GI_VB_GIVE_ITEM_MASTER_SWORD, + GI_VB_GIVE_ITEM_OCARINA_OF_TIME, + GI_VB_GIVE_ITEM_KOKIRI_EMERALD, + GI_VB_GIVE_ITEM_GORON_RUBY, + GI_VB_GIVE_ITEM_ZORA_SAPPHIRE, + GI_VB_GIVE_ITEM_LIGHT_MEDALLION, + GI_VB_GIVE_ITEM_FOREST_MEDALLION, + GI_VB_GIVE_ITEM_FIRE_MEDALLION, + GI_VB_GIVE_ITEM_WATER_MEDALLION, + GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, + GI_VB_GIVE_ITEM_SHADOW_MEDALLION, + + /*** Give Songs ***/ + + GI_VB_GIVE_ITEM_ZELDAS_LULLABY, + GI_VB_GIVE_ITEM_SARIAS_SONG, + GI_VB_GIVE_ITEM_EPONAS_SONG, + GI_VB_GIVE_ITEM_SUNS_SONG, + GI_VB_GIVE_ITEM_SONG_OF_TIME, + GI_VB_GIVE_ITEM_SONG_OF_STORMS, + GI_VB_GIVE_ITEM_MINUET_OF_FOREST, + GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, + GI_VB_GIVE_ITEM_SERENADE_OF_WATER, + GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, + GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, + GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, + + /*** Adult Trade ***/ + // Opt: *EnNiwLady + GI_VB_TRADE_POCKET_CUCCO, + // Opt: *EnHs + GI_VB_TRADE_COJIRO, + // Opt: *EnDs + GI_VB_TRADE_ODD_MUSHROOM, + // Opt: *EnKo + GI_VB_TRADE_ODD_POTION, + // Opt: *EnToryo + GI_VB_TRADE_SAW, + // Opt: *EnKz, + GI_VB_TRADE_PRESCRIPTION, + // Opt: *EnMk + GI_VB_TRADE_FROG, + + GI_VB_TRADE_TIMER_ODD_MUSHROOM, + GI_VB_TRADE_TIMER_EYEDROPS, + GI_VB_TRADE_TIMER_FROG, + // Opt: *EnNiwLady + GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, + + /*** Fixes ***/ + // Vanilla condition: false + GI_VB_FIX_SAW_SOFTLOCK, + + /*** Cheats? ***/ + GI_VB_DEKU_STICK_BE_ON_FIRE, + GI_VB_DEKU_STICK_BREAK, + GI_VB_DEKU_STICK_BURN_DOWN, + GI_VB_DEKU_STICK_BURN_OUT, + GI_VB_DEKU_UPDATE_BURNING_DEKU_STICK, + + /*** Quick Boss Deaths ***/ + // Vanilla condition: true + GI_VB_PHANTOM_GANON_DEATH_SCENE, + GI_VB_NABOORU_KNUCKLE_DEATH_SCENE, +} GIVanillaBehavior; + #ifdef __cplusplus extern "C" { #endif @@ -98,6 +421,7 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state); #ifdef __cplusplus #include +#include #include #include #include @@ -213,6 +537,8 @@ public: DEFINE_HOOK(OnPlayDestroy, void()); DEFINE_HOOK(OnPlayDrawEnd, void()); + DEFINE_HOOK(OnVanillaBehavior, void(GIVanillaBehavior flag, bool* result, void* opt)); + DEFINE_HOOK(OnSaveFile, void(int32_t fileNum)); DEFINE_HOOK(OnLoadFile, void(int32_t fileNum)); DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 911c47a71..b0c119798 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -90,6 +90,11 @@ void GameInteractor_ExecuteOnPlayDrawEnd() { GameInteractor::Instance->ExecuteHooks(); } +bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt) { + GameInteractor::Instance->ExecuteHooks(flag, &result, opt); + return result; +} + // MARK: - Save Files void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) { diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 5c86cb39b..82deeaf80 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -27,6 +27,7 @@ void GameInteractor_ExecuteOnOcarinaSongAction(); void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price); void GameInteractor_ExecuteOnPlayDestroy(); void GameInteractor_ExecuteOnPlayDrawEnd(); +bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt); // MARK: - Save Files void GameInteractor_ExecuteOnSaveFile(int32_t fileNum); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index e129048c8..6e93bf94b 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -10,6 +10,9 @@ #include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include #include "soh/Enhancements/nametag.h" +#include "soh/Enhancements/timesaver_hook_handlers.h" +#include "soh/Enhancements/cheat_hook_handlers.h" +#include "soh/Enhancements/randomizer/hook_handlers.h" #include "objects/object_gi_compass/object_gi_compass.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" @@ -1709,6 +1712,9 @@ void RegisterRandomizerCompasses() { } void InitMods() { + RandomizerRegisterHooks(); + TimeSaverRegisterHooks(); + CheatsRegisterHooks(); RegisterTTS(); RegisterInfiniteMoney(); RegisterInfiniteHealth(); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 7bc941afb..d9f55bc59 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -280,6 +280,20 @@ const std::vector enhancementsCvars = { "gPermanentHeartLoss", "gRemoveExplosiveLimit", "gToggleStrength", + "gTimeSavers.SkipCutscene.Intro", + "gTimeSavers.SkipCutscene.Entrances", + "gTimeSavers.SkipCutscene.Story", + "gTimeSavers.SkipCutscene.LearnSong", + "gTimeSavers.SkipCutscene.BossIntro", + "gTimeSavers.SkipCutscene.GlitchAiding", + "gTimeSavers.SkipCutscene.OnePoint", + "gTimeSavers.NoForcedDialog", + "gTimeSavers.SkipOwlInteractions", + "gTimeSavers.SkipMiscInteractions", + "gTimeSavers.DisableTitleCard", + "gTimeSavers.SkipGetItemAnimation", + "gTimeSavers.SkipChildStealth", + "gTimeSavers.SkipTowerEscape", }; const std::vector cheatCvars = { diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index bf9b9ef19..6b23c6f2d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -1121,7 +1121,19 @@ int Fill() { std::vector remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; }); FastFill(remainingPool, GetAllEmptyLocations(), false); - //Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile. + //Add default prices to scrubs + for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { + if (Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_GROTTO_FRONT) { + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(40); + } else if (Rando::StaticData::scrubLocations[i] == RC_HF_DEKU_SCRUB_GROTTO) { + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10); + } else { + auto loc = Rando::StaticData::GetLocation(Rando::StaticData::scrubLocations[i]); + auto item = Rando::StaticData::RetrieveItem(loc->GetVanillaItem()); + ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(item.GetPrice()); + } + } + if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) { for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) { ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 33f6c64d0..22ef9f962 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -389,6 +389,76 @@ void StaticData::HintTable_Init() { /*french*/ "Selon moi, le #neuvième ou dixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); // /*spanish*/#el noveno o décimo cofre del azar# revela #[[1]]#. + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_1] = HintText(CustomMessage("They say that the #first locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #première salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la primera sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling once# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier une fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar solo una vez# revelará #[[1]]#. + CustomMessage("They say that the #first or second game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #premier ou deuxième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el primer o segundo cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_2] = HintText(CustomMessage("They say that the #second locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #deuxième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la segunda sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling twice# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier deux fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar dos veces# revelará #[[1]]#. + CustomMessage("They say that the #third or fourth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #troisième ou quatrième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el tercer o cuarto cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_3] = HintText(CustomMessage("They say that the #third locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #troisième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la tercera sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling 3 times# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier trois fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar tres veces# revelará #[[1]]#. + CustomMessage("They say that the #fifth or sixth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #cinquième ou sixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el quinto o sexto cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_4] = HintText(CustomMessage("They say that the #fourth locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #quatrième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la cuarta sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling 4 times# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier quatre fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar cuatro veces# revelará #[[1]]#. + CustomMessage("They say that the #seventh or eighth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #septième ou huitième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el séptimo u octavo cofre del azar# revela #[[1]]#. + + hintTextTable[RHT_MARKET_TREASURE_CHEST_GAME_KEY_5] = HintText(CustomMessage("They say that the #fifth locked room# in the chest game contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, la #cinquième salle# de la Chasse-aux-Trésors contient #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#en la quinta sala del Cofre del Tesoro# aguarda #[[1]]#. + {}, + {CustomMessage("They say that #gambling 5 times# grants #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, #parier cinq fois# donne #[[1]]#.", {QM_RED, QM_GREEN}), + // /*spanish*/#apostar cinco veces# revelará #[[1]]#. + CustomMessage("They say that the #ninth or tenth game chest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, le #neuvième ou dixième coffre à jeu# contient #[[1]]#.", {QM_RED, QM_GREEN})}); + // /*spanish*/#el noveno o décimo cofre del azar# revela #[[1]]#. + hintTextTable[RHT_GF_HBA_1500_POINTS] = HintText(CustomMessage("They say that scoring 1500 in #horseback archery# grants #[[1]]#.", /*german*/ "", /*french*/ "Selon moi, obtenir 1500 points dans l'#archerie équestre# donne #[[1]]#.", {QM_RED, QM_GREEN}), diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index f1119123c..9c1459cef 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -904,11 +904,16 @@ void GenerateItemPool() { } else if (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK)) { AddItemToMainPool(RG_TREASURE_GAME_SMALL_KEY); // 1 key which will behave as a pack of 6 } else { - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, false, true); - ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, false, true); + ctx->PlaceItemInLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, false, true); }; if (ctx->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp index dacd8127e..fbff295ad 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp @@ -65,6 +65,7 @@ void AreaTable_Init_CastleTown() { }, { //Locations LocationAccess(RC_TOT_MASTER_SWORD, {[]{return logic->IsAdult;}}), + LocationAccess(RC_GIFT_FROM_SAGES, {[]{return logic->IsAdult;}}), LocationAccess(RC_SHEIK_AT_TEMPLE, {[]{return logic->ForestMedallion && logic->IsAdult;}}), }, { //Exits @@ -234,10 +235,15 @@ void AreaTable_Init_CastleTown() { //Locations LocationAccess(RC_GREG_HINT, {[]{return true;}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return logic->ChildsWallet && ((logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), + LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return logic->ChildsWallet && ((randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !randoCtx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)));}}), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp index 51fc51941..89b9d36bc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp @@ -18,16 +18,11 @@ typedef enum { SPOILER_CHK_ITEM_GET_INF, SPOILER_CHK_EVENT_CHK_INF, SPOILER_CHK_INF_TABLE, - SPOILER_CHK_COW, SPOILER_CHK_FISH, SPOILER_CHK_MINIGAME, - SPOILER_CHK_SCRUB, - SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, SPOILER_CHK_POE_POINTS, SPOILER_CHK_SHOP_ITEM, - SPOILER_CHK_MAGIC_BEANS, SPOILER_CHK_MASTER_SWORD, - SPOILER_CHK_MERCHANT, SPOILER_CHK_GRAVEDIGGER, SPOILER_CHK_RANDOMIZER_INF, } SpoilerCollectionCheckType; diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp new file mode 100644 index 000000000..bd71f7e0c --- /dev/null +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -0,0 +1,1440 @@ +#include +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/enhancementTypes.h" +#include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "src/overlays/actors/ovl_En_Si/z_en_si.h" +#include "src/overlays/actors/ovl_En_Cow/z_en_cow.h" +#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" +#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" +#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h" +#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" +#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h" +#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h" +#include "src/overlays/actors/ovl_En_Kz/z_en_kz.h" +#include "src/overlays/actors/ovl_En_Go2/z_en_go2.h" +#include "src/overlays/actors/ovl_En_Ms/z_en_ms.h" +#include "src/overlays/actors/ovl_En_Fr/z_en_fr.h" +#include "src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" +#include "src/overlays/actors/ovl_En_Sth/z_en_sth.h" +#include "src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h" +#include "src/overlays/actors/ovl_En_Box/z_en_box.h" +#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h" +#include "src/overlays/actors/ovl_En_Hy/z_en_hy.h" +#include "src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h" +#include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" +#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h" +#include "adult_trade_shuffle.h" +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +} + +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() + +RandomizerCheck GetRandomizerCheckFromFlag(int16_t flagType, int16_t flag) { + for (auto& loc : Rando::StaticData::GetLocationTable()) { + if (loc.GetCollectionCheck().flag == flag && ( + (flagType == FLAG_INF_TABLE && loc.GetCollectionCheck().type == SPOILER_CHK_INF_TABLE) || + (flagType == FLAG_EVENT_CHECK_INF && loc.GetCollectionCheck().type == SPOILER_CHK_EVENT_CHK_INF) || + (flagType == FLAG_ITEM_GET_INF && loc.GetCollectionCheck().type == SPOILER_CHK_ITEM_GET_INF) || + (flagType == FLAG_RANDOMIZER_INF && loc.GetCollectionCheck().type == SPOILER_CHK_RANDOMIZER_INF) + ) || + (loc.GetActorParams() == flag && flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA) + ) { + return loc.GetRandomizerCheck(); + } + } + + return RC_UNKNOWN_CHECK; +} + +RandomizerCheck GetRandomizerCheckFromSceneFlag(int16_t sceneNum, int16_t flagType, int16_t flag) { + for (auto& loc : Rando::StaticData::GetLocationTable()) { + if (loc.GetCollectionCheck().scene == sceneNum && loc.GetCollectionCheck().flag == flag && ( + (flagType == FLAG_SCENE_TREASURE && loc.GetCollectionCheck().type == SPOILER_CHK_CHEST) || + (flagType == FLAG_SCENE_COLLECTIBLE && loc.GetCollectionCheck().type == SPOILER_CHK_COLLECTABLE) || + (flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA) + )) { + return loc.GetRandomizerCheck(); + } + } + + return RC_UNKNOWN_CHECK; +} + +bool MeetsLACSRequirements() { + switch (RAND_GET_OPTION(RSK_GANONS_BOSS_KEY)) { + case RO_GANON_BOSS_KEY_LACS_STONES: + if ((CheckStoneCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_STONE_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_MEDALLIONS: + if ((CheckMedallionCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_MEDALLION_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_REWARDS: + if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_REWARD_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_DUNGEONS: + if ((CheckDungeonCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_DUNGEON_COUNT)) { + return true; + } + break; + case RO_GANON_BOSS_KEY_LACS_TOKENS: + if (gSaveContext.inventory.gsTokens >= RAND_GET_OPTION(RSK_LACS_TOKEN_COUNT)) { + return true; + } + break; + default: + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { + return true; + } + break; + } + + return false; +} + +bool CompletedAllTrials() { + return Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_WATER_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_LIGHT_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FIRE_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SHADOW_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SPIRIT_TRIAL) && + Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL); +} + +bool MeetsRainbowBridgeRequirements() { + switch (RAND_GET_OPTION(RSK_RAINBOW_BRIDGE)) { + case RO_BRIDGE_VANILLA: { + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { + return true; + } + break; + } + case RO_BRIDGE_STONES: { + if ((CheckStoneCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_STONE_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_MEDALLIONS: { + if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_DUNGEON_REWARDS: { + if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_REWARD_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_DUNGEONS: { + if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_TOKENS: { + if (gSaveContext.inventory.gsTokens >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_TOKEN_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_GREG: { + if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) { + return true; + } + break; + } + case RO_BRIDGE_ALWAYS_OPEN: { + return true; + } + } + + return false; +} + +// Todo Move this to randomizer context, clear it out on save load etc +static std::queue randomizerQueuedChecks; +static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK; +static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE; + +void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { + // Consume adult trade items + if (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && flagType == FLAG_RANDOMIZER_INF) { + switch (flag) { + case RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD: + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SWORD_BROKEN); + break; + case RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS: + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_EYEDROPS); + break; + } + } + + RandomizerCheck rc = GetRandomizerCheckFromFlag(flagType, flag); + if (rc == RC_UNKNOWN_CHECK) return; + + auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); + if (loc == nullptr || loc->HasObtained()) return; + + SPDLOG_INFO("Queuing RC: {}", rc); + randomizerQueuedChecks.push(rc); +} + +void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) { + if (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && + sceneNum == SCENE_GERUDOS_FORTRESS && + flagType == FLAG_SCENE_SWITCH && + flag == 0x3A) { + Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); + } + + RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag); + if (rc == RC_UNKNOWN_CHECK) return; + + auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); + if (loc == nullptr || loc->HasObtained()) return; + + SPDLOG_INFO("Queuing RC: {}", rc); + randomizerQueuedChecks.push(rc); +} + +static Vec3f spawnPos = { 0.0f, -999.0f, 0.0f }; + +void RandomizerOnPlayerUpdateForRCQueueHandler() { + // If we're already queued, don't queue again + if (randomizerQueuedCheck != RC_UNKNOWN_CHECK) return; + + // If there's nothing to queue, don't queue + if (randomizerQueuedChecks.size() < 1) return; + + // If we're in a cutscene, don't queue + Player* player = GET_PLAYER(gPlayState); + if (Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + RandomizerCheck rc = randomizerQueuedChecks.front(); + auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); + GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + + if (loc->HasObtained()) { + SPDLOG_INFO("RC {} already obtained, skipping", rc); + } else { + randomizerQueuedCheck = rc; + randomizerQueuedItemEntry = getItemEntry; + SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, rc); + if ( + // Skipping ItemGet animation incompatible with checks that require closing a text box to finish + rc != RC_HF_OCARINA_OF_TIME_ITEM && + rc != RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && + rc != RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE && + rc != RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE && + rc != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS && + // Always show ItemGet animation for ice traps + !(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId == RG_ICE_TRAP) && + ( + CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_ALL || + ( + CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_JUNK && + ( + getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK || + getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN || + getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER + ) + ) + ) + ) { + Item_DropCollectible(gPlayState, &spawnPos, ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000); + } + } + + randomizerQueuedChecks.pop(); +} + +void RandomizerOnPlayerUpdateForItemQueueHandler() { + if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return; + + Player* player = GET_PLAYER(gPlayState); + if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + SPDLOG_INFO("Attempting to give Item mod {} item {} from RC {}", randomizerQueuedItemEntry.modIndex, randomizerQueuedItemEntry.itemId, randomizerQueuedCheck); + GiveItemEntryWithoutActor(gPlayState, randomizerQueuedItemEntry); + if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { + // Allow the player to receive the item while swimming + player->stateFlags2 |= PLAYER_STATE2_UNDERWATER; + Player_ActionChange_2(player, gPlayState); + } +} + +void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) { + if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return; + + auto loc = Rando::Context::GetInstance()->GetItemLocation(randomizerQueuedCheck); + if (randomizerQueuedItemEntry.modIndex == receivedItemEntry.modIndex && randomizerQueuedItemEntry.itemId == receivedItemEntry.itemId) { + SPDLOG_INFO("Item received mod {} item {} from RC {}", receivedItemEntry.modIndex, receivedItemEntry.itemId, randomizerQueuedCheck); + loc->MarkAsObtained(); + randomizerQueuedCheck = RC_UNKNOWN_CHECK; + randomizerQueuedItemEntry = GET_ITEM_NONE; + } + + if ( + receivedItemEntry.modIndex == MOD_NONE && ( + receivedItemEntry.itemId == ITEM_HEART_PIECE || + receivedItemEntry.itemId == ITEM_HEART_PIECE_2 || + receivedItemEntry.itemId == ITEM_HEART_CONTAINER + ) + ) { + gSaveContext.healthAccumulator = 0x140; // Refill 20 hearts + if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) { + gSaveContext.inventory.questItems ^= 0x40000000; + gSaveContext.healthCapacity += 0x10; + gSaveContext.health += 0x10; + } + } + + if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + static uint32_t updateHook; + updateHook = GameInteractor::Instance->RegisterGameHook([]() { + Player* player = GET_PLAYER(gPlayState); + if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + gPlayState->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.nextCutsceneIndex = 0xFFF1; + gPlayState->transitionType = TRANS_TYPE_SANDSTORM_END; + GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; + Player_TryCsAction(gPlayState, NULL, 8); + GameInteractor::Instance->UnregisterGameHook(updateHook); + }); + } +} + +void EnExItem_DrawRandomizedItem(EnExItem* enExItem, PlayState* play) { + func_8002ED80(&enExItem->actor, play, 0); + EnItem00_CustomItemsParticles(&enExItem->actor, play, enExItem->sohItemEntry); + GetItemEntry_Draw(play, enExItem->sohItemEntry); +} + +void EnExItem_WaitForObjectRandomized(EnExItem* enExItem, PlayState* play) { + EnExItem_WaitForObject(enExItem, play); + if (Object_IsLoaded(&play->objectCtx, enExItem->objectIdx)) { + enExItem->actor.draw = (ActorFunc)EnExItem_DrawRandomizedItem; + Actor_SetScale(&enExItem->actor, enExItem->scale); + + // for now we're just using this to not have items float + // below the bowling counter, but it would be nice to use + // this to not draw gigantic skull tokens etc. + switch (enExItem->type) { + case EXITEM_BOMB_BAG_COUNTER: { + enExItem->actor.shape.yOffset = -10.0f; + break; + } + } + } +} + +void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) { + f32 mtxScale = CVarGetFloat("gTimeSavers.SkipGetItemAnimationScale", 10.0f); + Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); + EnItem00_CustomItemsParticles(&enItem00->actor, play, enItem00->itemEntry); + GetItemEntry_Draw(play, enItem00->itemEntry); +} + +void ItemBHeart_DrawRandomizedItem(ItemBHeart* itemBHeart, PlayState* play) { + EnItem00_CustomItemsParticles(&itemBHeart->actor, play, itemBHeart->sohItemEntry); + GetItemEntry_Draw(play, itemBHeart->sohItemEntry); +} + +void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) { + ItemBHeart* itemBHeart = (ItemBHeart*)actor; + + func_80B85264(itemBHeart, play); + Actor_UpdateBgCheckInfo(play, &itemBHeart->actor, 0.0f, 0.0f, 0.0f, 4); + if ((itemBHeart->actor.xzDistToPlayer < 30.0f) && (fabsf(itemBHeart->actor.yDistToPlayer) < 40.0f)) { + Flags_SetCollectible(play, 0x1F); + Actor_Kill(&itemBHeart->actor); + } +} + +void ItemEtcetera_DrawRandomizedItem(ItemEtcetera* itemEtcetera, PlayState* play) { + EnItem00_CustomItemsParticles(&itemEtcetera->actor, play, itemEtcetera->sohItemEntry); + func_8002EBCC(&itemEtcetera->actor, play, 0); + func_8002ED80(&itemEtcetera->actor, play, 0); + GetItemEntry_Draw(play, itemEtcetera->sohItemEntry); +} + +void ItemEtcetera_DrawRandomizedItemThroughLens(ItemEtcetera* itemEtcetera, PlayState* play) { + if (play->actorCtx.lensActive) { + ItemEtcetera_DrawRandomizedItem(itemEtcetera, play); + } +} + +void ItemEtcetera_func_80B858B4_Randomized(ItemEtcetera* itemEtcetera, PlayState* play) { + if (itemEtcetera->actor.xzDistToPlayer < 30.0f && + fabsf(itemEtcetera->actor.yDistToPlayer) < 50.0f) { + if ((itemEtcetera->actor.params & 0xFF) == 1) { + Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); + Flags_SetSwitch(play, 0xB); + } + + Actor_Kill(&itemEtcetera->actor); + } else { + if ((play->gameplayFrames & 0xD) == 0) { + EffectSsBubble_Spawn(play, &itemEtcetera->actor.world.pos, 0.0f, 0.0f, 10.0f, 0.13f); + } + } +} + +void ItemEtcetera_func_80B85824_Randomized(ItemEtcetera* itemEtcetera, PlayState* play) { + if ((itemEtcetera->actor.params & 0xFF) != 7) { + return; + } + + if (itemEtcetera->actor.xzDistToPlayer < 30.0f && + fabsf(itemEtcetera->actor.yDistToPlayer) < 50.0f) { + + Flags_SetTreasure(play, 0x1F); + Actor_Kill(&itemEtcetera->actor); + } +} + +void ItemEtcetera_MoveRandomizedFireArrowDown(ItemEtcetera* itemEtcetera, PlayState* play) { + Actor_UpdateBgCheckInfo(play, &itemEtcetera->actor, 10.0f, 10.0f, 0.0f, 5); + Actor_MoveForward(&itemEtcetera->actor); + if (!(itemEtcetera->actor.bgCheckFlags & 1)) { + ItemEtcetera_SpawnSparkles(itemEtcetera, play); + } + itemEtcetera->actor.shape.rot.y += 0x400; + ItemEtcetera_func_80B85824_Randomized(itemEtcetera, play); +} + +void ItemEtcetera_UpdateRandomizedFireArrow(ItemEtcetera* itemEtcetera, PlayState* play) { + if ((play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.npcActions[0] != NULL)) { + if (play->csCtx.npcActions[0]->action == 2) { + itemEtcetera->actor.draw = (ActorFunc)ItemEtcetera_DrawRandomizedItem; + itemEtcetera->actor.gravity = -0.1f; + itemEtcetera->actor.minVelocityY = -4.0f; + itemEtcetera->actionFunc = ItemEtcetera_MoveRandomizedFireArrowDown; + } + } else { + itemEtcetera->actor.gravity = -0.1f; + itemEtcetera->actor.minVelocityY = -4.0f; + itemEtcetera->actionFunc = ItemEtcetera_MoveRandomizedFireArrowDown; + } +} + +void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) { + bool moved = false; + + // Don't reposition the tail + if (enCow->actor.params != 0) { + return; + } + + // Move left cow in lon lon tower + if (play->sceneNum == SCENE_LON_LON_BUILDINGS && enCow->actor.world.pos.x == -108 && + enCow->actor.world.pos.z == -65) { + enCow->actor.world.pos.x = -229.0f; + enCow->actor.world.pos.z = 157.0f; + enCow->actor.shape.rot.y = 15783.0f; + moved = true; + // Move right cow in lon lon stable + } else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) { + enCow->actor.world.pos.x += 119.0f; + moved = true; + } + + if (moved) { + // Reposition collider + func_809DEE9C(enCow); + } +} + +u8 EnDs_RandoCanGetGrannyItem() { + return RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && + // Traded odd mushroom when adult trade is on + ((RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && Flags_GetItemGetInf(ITEMGETINF_30)) || + // Found claim check when adult trade is off + (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && + INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)); +} + +RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) { + switch (songIndex) { + case FROG_ZL: + return RC_ZR_FROGS_ZELDAS_LULLABY; + case FROG_EPONA: + return RC_ZR_FROGS_EPONAS_SONG; + case FROG_SARIA: + return RC_ZR_FROGS_SARIAS_SONG; + case FROG_SUNS: + return RC_ZR_FROGS_SUNS_SONG; + case FROG_SOT: + return RC_ZR_FROGS_SONG_OF_TIME; + case FROG_STORMS: + return RC_ZR_FROGS_IN_THE_RAIN; + case FROG_CHOIR_SONG: + return RC_ZR_FROGS_OCARINA_GAME; + default: + return RC_UNKNOWN_CHECK; + } +} + +void RandomizerSetChestGameRandomizerInf(RandomizerCheck rc) { + switch (rc) { + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_1: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_2: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_3: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_4: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4); + break; + case RC_MARKET_TREASURE_CHEST_GAME_ITEM_5: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_1: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_2: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_3: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_4: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4); + break; + case RC_MARKET_TREASURE_CHEST_GAME_KEY_5: + Flags_SetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5); + break; + } +} + +void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) { + switch (id) { + case GI_VB_GIVE_ITEM_FROM_CHEST: { + EnBox* chest = static_cast(optionalArg); + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(chest->dyna.actor.id, gPlayState->sceneNum, chest->dyna.actor.params); + + // if this is a treasure chest game chest then set the appropriate rando inf + RandomizerSetChestGameRandomizerInf(rc); + + Player* player = GET_PLAYER(gPlayState); + player->av2.actionVar2 = 1; + player->getItemId = GI_NONE; + player->getItemEntry = GetItemEntry(GET_ITEM_NONE); + *should = false; + break; + } + case GI_VB_PLAY_NABOORU_CAPTURED_CS: + // This behavior is replicated for randomizer in RandomizerOnItemReceiveHandler + *should = false; + break; + case GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER: { + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !Flags_GetTreasure(gPlayState, 0x2); + break; + } + case GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER: + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && Flags_GetTreasure(gPlayState, 0x2); + break; + case GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT: + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST); + break; + case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: + if (RAND_GET_OPTION(RSK_FOREST) == RO_FOREST_OPEN) { + *should = true; + } + break; + case GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD: + *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); + break; + case GI_VB_OPEN_KOKIRI_FOREST: + *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_FOREST_CLOSED; + break; + case GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD: + *should = !Flags_GetRandomizerInf(RAND_INF_DARUNIAS_JOY); + break; + case GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS: + *should = !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements(); + break; + case GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW: + *should = + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) && + LINK_IS_ADULT && + gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KAKARIKO_VILLAGE && + CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER); + break; + case GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: { + // Don't require a bomb bag to get prize in rando + *should = true; + break; + } + case GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE: { + if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) { + *should = gSaveContext.rupees >= 60; + } + break; + } + case GI_VB_GIVE_ITEM_MASTER_SWORD: + if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD)) { + *should = false; + } else { + *should = true; + Rando::Context::GetInstance()->GetItemLocation(RC_TOT_MASTER_SWORD)->MarkAsObtained(); + } + break; + case GI_VB_ITEM00_DESPAWN: { + EnItem00* item00 = static_cast(optionalArg); + if (item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY) { + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(item00->actor.id, gPlayState->sceneNum, item00->ogParams); + if (rc != RC_UNKNOWN_CHECK) { + item00->actor.params = ITEM00_SOH_DUMMY; + item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + *should = Rando::Context::GetInstance()->GetItemLocation(rc)->HasObtained(); + } + } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY || item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) { + GetItemEntry itemEntry = randomizerQueuedItemEntry; + item00->itemEntry = itemEntry; + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + } + break; + } + case GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG: { + *should = Flags_GetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); + break; + } + case GI_VB_SET_CUCCO_COUNT: { + EnNiwLady* enNiwLady = static_cast(optionalArg); + // Override starting Cucco count using setting value + enNiwLady->cuccosInPen = 7 - RAND_GET_OPTION(RSK_CUCCO_COUNT); + *should = false; + break; + } + case GI_VB_KING_ZORA_THANK_CHILD: { + // Allow turning in Ruto's letter even if you have already rescued her + if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + GET_PLAYER(gPlayState)->exchangeItemId = EXCH_ITEM_LETTER_RUTO; + } + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); + break; + } + case GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER: { + *should = LINK_IS_CHILD; + break; + } + case GI_VB_KING_ZORA_BE_MOVED: { + *should = false; + switch (RAND_GET_OPTION(RSK_ZORAS_FOUNTAIN)) { + case RO_ZF_CLOSED: + if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + *should = true; + } + break; + case RO_ZF_CLOSED_CHILD: + if (LINK_IS_ADULT) { + *should = true; + } else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + *should = true; + } + break; + case RO_ZF_OPEN: + *should = true; + break; + } + break; + } + case GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED: { + *should = Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); + break; + } + case GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE: { + // This being true will prevent other biggoron trades, there are already safegaurds in place to prevent + // claim check from being traded multiple times, so we don't really need the quest to ever be considered "complete" + *should = false; + break; + } + case GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); + break; + } + case GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED: { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); + break; + } + case GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED: { + *should = Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); + break; + } + case GI_VB_GIVE_ITEM_FROM_ITEM_00: { + EnItem00* item00 = static_cast(optionalArg); + if (item00->actor.params == ITEM00_SOH_DUMMY) { + if (item00->randoInf != RAND_INF_MAX) { + Flags_SetRandomizerInf(item00->randoInf); + } else { + Flags_SetCollectible(gPlayState, item00->collectibleFlag); + } + Actor_Kill(&item00->actor); + *should = false; + } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY) { + Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + if (item00->itemEntry.modIndex == MOD_NONE) { + if (item00->itemEntry.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } + Item_Give(gPlayState, item00->itemEntry.itemId); + } else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) { + if (item00->itemEntry.getItemId == RG_ICE_TRAP) { + gSaveContext.pendingIceTrapCount++; + } else { + Randomizer_Item_Give(gPlayState, item00->itemEntry); + } + } + // EnItem00_SetupAction(item00, func_8001E5C8); + // *should = false; + } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) { + if (!Actor_HasParent(&item00->actor, gPlayState)) { + GiveItemEntryFromActorWithFixedRange(&item00->actor, gPlayState, item00->itemEntry); + } + EnItem00_SetupAction(item00, func_8001E5C8); + *should = false; + } + break; + } + case GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG: { + *should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG); + break; + } + case GI_VB_GIVE_ITEM_FROM_COW: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { + break; + } + EnCow* enCow = static_cast(optionalArg); + CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z); + // Has this cow already rewarded an item? + if (Flags_GetRandomizerInf(cowIdentity.randomizerInf)) { + break; + } + Flags_SetRandomizerInf(cowIdentity.randomizerInf); + // setting the ocarina mode here prevents intermittent issues + // with the item get not triggering until walking away + gPlayState->msgCtx.ocarinaMode = OCARINA_MODE_00; + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP: { + if (!EnDs_RandoCanGetGrannyItem()) { + break; + } + // Only setting the inf if we've actually gotten the rando item and not the vanilla blue potion + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP); + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA: { + EnKz* enKz = static_cast(optionalArg); + // If we aren't setting up the item offer, then we're just checking if it should be possible. + if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) { + // Always give the reward in rando + *should = true; + break; + } + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD: { + Flags_SetItemGetInf(ITEMGETINF_0C); + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT: { + Flags_SetItemGetInf(ITEMGETINF_2C); + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN: { + *should = RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_OFF || + // If the rando check has already been awarded, use vanilla behavior. + Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); + break; + } + case GI_VB_GIVE_ITEM_FROM_MEDIGORON: { + // fallthrough + case GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE: + if (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { + if (id == GI_VB_GIVE_ITEM_FROM_MEDIGORON) { + Flags_SetInfTable(INFTABLE_B1); + *should = false; + } else { + // Resets "Talked to Medigoron" flag in infTable to restore initial conversation state + Flags_UnsetInfTable(INFTABLE_B1); + *should = true; + } + } + break; + } + case GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN: { + EnMs* enMs = static_cast(optionalArg); + if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) { + Rupees_ChangeBy(-60); + BEANS_BOUGHT = 10; + // Only set inf for buying rando check + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN); + enMs->actionFunc = (EnMsActionFunc)EnMs_Wait; + *should = false; + } + break; + } + case GI_VB_GIVE_ITEM_FROM_FROGS: { + EnFr* enFr = static_cast(optionalArg); + + // Skip GiveReward+SetIdle action func if the reward is an ice trap + if (enFr->actionFunc == (EnFrActionFunc)EnFr_GiveReward) { + RandomizerCheck rc = EnFr_RandomizerCheckFromSongIndex(enFr->songIndex); + GetItemEntry gi = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + if (gi.getItemId == RG_ICE_TRAP) { + enFr->actionFunc = (EnFrActionFunc)EnFr_Idle; + } + } + + *should = false; + break; + } + case GI_VB_TRADE_POCKET_CUCCO: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_POCKET_CUCCO); + // Trigger the reward now + Flags_SetItemGetInf(ITEMGETINF_2E); + *should = false; + break; + } + case GI_VB_TRADE_COJIRO: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_COJIRO); + *should = false; + break; + } + case GI_VB_TRADE_ODD_MUSHROOM: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_MUSHROOM); + // Trigger the reward now + Flags_SetItemGetInf(ITEMGETINF_30); + *should = false; + break; + } + case GI_VB_TRADE_ODD_POTION: { + EnKo* enKo = static_cast(optionalArg); + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_POTION); + // Trigger the reward now + Flags_SetItemGetInf(ITEMGETINF_31); + *should = false; + break; + } + case GI_VB_TRADE_SAW: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SAW); + *should = false; + break; + } + case GI_VB_TRADE_PRESCRIPTION: { + EnKz* enKz = static_cast(optionalArg); + // If we aren't setting up the item offer, then we're just checking if it should be possible. + if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) { + *should = !Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION); + break; + } + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_PRESCRIPTION); + *should = false; + break; + } + case GI_VB_TRADE_FROG: { + Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_FROG); + *should = false; + break; + } + case GI_VB_DESPAWN_HORSE_RACE_COW: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) { + break; + } + EnCow* enCow = static_cast(optionalArg); + // If this is a cow we have to move, then move it now. + EnCow_MoveForRandomizer(enCow, gPlayState); + break; + } + case GI_VB_BUSINESS_SCRUB_DESPAWN: { + EnShopnuts* enShopnuts = static_cast(optionalArg); + s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); + ScrubIdentity scrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enShopnuts->actor.params, respawnData); + + if (scrubIdentity.isShuffled) { + *should = Flags_GetRandomizerInf(scrubIdentity.randomizerInf); + } + break; + } + case GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB: { + EnDns* enDns = static_cast(optionalArg); + *should = !enDns->sohScrubIdentity.isShuffled; + break; + } + // To explain the logic because Fado and Grog are linked: + // - If you have Cojiro, then spawn Grog and not Fado. + // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. + // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. + // - If you don't have either but have traded the mushroom, don't spawn either. + case GI_VB_DESPAWN_GROG: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) { + break; + } + if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { + *should = false; + } else if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION)) { + *should = true; + } else { + *should = Flags_GetItemGetInf(ITEMGETINF_30); // Traded odd mushroom + } + break; + } + case GI_VB_SPAWN_LW_FADO: { + if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) { + break; + } + + if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { + *should = false; + } else { + *should = PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION); + } + + break; + } + case GI_VB_USE_EYEDROP_DIALOGUE: { + // Skip eye drop text on rando if Link went in the water, so you can still receive the dive check + EnMk* enMk = static_cast(optionalArg); + *should &= enMk->swimFlag == 0; + break; + } + case GI_VB_OFFER_BLUE_POTION: { + // Always offer blue potion when adult trade is off + *should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF; + break; + } + case GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM: { + // Allow buying the rando item regardless of having a bottle + *should &= !EnDs_RandoCanGetGrannyItem(); + break; + } + case GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY: { + EnSyatekiMan* enSyatekiMan = static_cast(optionalArg); + enSyatekiMan->getItemId = GI_RUPEE_PURPLE; + if (LINK_IS_ADULT) { + // Give purple rupee if we've already obtained the reward OR we don't have a bow + *should = Flags_GetItemGetInf(ITEMGETINF_0E) || CUR_UPG_VALUE(UPG_QUIVER) == 0; + } else { + // Give purple rupee if we've already obtained the reward + *should = Flags_GetItemGetInf(ITEMGETINF_0D); + } + break; + } + case GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD: { + *should = CUR_UPG_VALUE(UPG_QUIVER) > 0; + if (!*should) { + // In Rando without a quiver, display a message reminding the player to come back with a bow + Message_StartTextbox(gPlayState, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL); + } + 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_GIVE_ITEM_FROM_HORSEBACK_ARCHERY: { + // give both rewards at the same time + if (gSaveContext.minigameScore >= 1500) { + Flags_SetItemGetInf(ITEMGETINF_0F); + } + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD: { + // In z_en_sth.c the rewards are stored in sGetItemIds, the first entry + // in that array is GI_RUPEE_GOLD, and the reward is picked in EnSth_GivePlayerItem + // via sGetItemIds[this->actor.params]. This means if actor.params == 0 we're looking + // at the 100 GS reward + EnSth* enSth = static_cast(optionalArg); + if (enSth->actor.params == 0) { + // if nothing is shuffled onto 100 GS, + // or we already got the 100 GS reward, + // let the player farm + if (!RAND_GET_OPTION(RSK_SHUFFLE_100_GS_REWARD) || + Flags_GetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD)) { + *should = true; + break; + } + + // we're giving the 100 GS rando reward! set the rando inf + Flags_SetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD); + + // also set the actionfunc so this doesn't immediately get + // called again (and lead to a vanilla+rando item give + // because the flag check will pass next time) + enSth->actionFunc = (EnSthActionFunc)EnSth_RewardObtainedTalk; + } + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME: { + EnSkj* enSkj = static_cast(optionalArg); + Flags_SetItemGetInf(ITEMGETINF_17); + enSkj->actionFunc = (EnSkjActionFunc)EnSkj_CleanupOcarinaGame; + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_LOST_DOG: { + EnHy* enHy = static_cast(optionalArg); + Flags_SetInfTable(INFTABLE_191); + gSaveContext.dogParams = 0; + gSaveContext.dogIsLost = false; + enHy->actionFunc = func_80A7127C; + *should = false; + break; + } + case GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING: { + EnBomBowlPit* enBomBowlPit = static_cast(optionalArg); + if (enBomBowlPit->prizeIndex == EXITEM_BOMB_BAG_BOWLING || enBomBowlPit->prizeIndex == EXITEM_HEART_PIECE_BOWLING) { + *should = false; + } + break; + } + case GI_VB_GERUDOS_BE_FRIENDLY: { + *should = CHECK_QUEST_ITEM(QUEST_GERUDO_CARD); + break; + } + case GI_VB_GTG_GATE_BE_OPEN: { + if (Flags_GetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)) { + *should = true; + } + break; + } + case GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD: { + Flags_SetRandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS); + *should = false; + break; + } + case GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE: { + *should = MeetsRainbowBridgeRequirements(); + break; + } + case GI_VB_PLAY_BLUE_WARP_CS: { + // We need to override just these two temples because they check medallions instead of flags + if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { + *should = !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); + } else if (gPlayState->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { + *should = !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); + } + break; + } + case GI_VB_TRADE_TIMER_ODD_MUSHROOM: + case GI_VB_TRADE_TIMER_EYEDROPS: + case GI_VB_TRADE_TIMER_FROG: + case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM: + case GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: + case GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS: + case GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME: + case GI_VB_GIVE_ITEM_FROM_GORON: + case GI_VB_GIVE_ITEM_FROM_LAB_DIVE: + case GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: + case GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF: + case GI_VB_GIVE_ITEM_SKULL_TOKEN: + case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: + case GI_VB_GIVE_ITEM_FAIRY_OCARINA: + case GI_VB_GIVE_ITEM_WEIRD_EGG: + case GI_VB_GIVE_ITEM_LIGHT_ARROW: + case GI_VB_GIVE_ITEM_STRENGTH_1: + case GI_VB_GIVE_ITEM_ZELDAS_LETTER: + case GI_VB_GIVE_ITEM_OCARINA_OF_TIME: + case GI_VB_GIVE_ITEM_KOKIRI_EMERALD: + case GI_VB_GIVE_ITEM_GORON_RUBY: + case GI_VB_GIVE_ITEM_ZORA_SAPPHIRE: + case GI_VB_GIVE_ITEM_LIGHT_MEDALLION: + case GI_VB_GIVE_ITEM_FOREST_MEDALLION: + case GI_VB_GIVE_ITEM_FIRE_MEDALLION: + case GI_VB_GIVE_ITEM_WATER_MEDALLION: + case GI_VB_GIVE_ITEM_SPIRIT_MEDALLION: + case GI_VB_GIVE_ITEM_SHADOW_MEDALLION: + *should = false; + break; + } +} + +void RandomizerOnSceneInitHandler(int16_t sceneNum) { + // Treasure Chest Game + // todo: for now we're just unsetting all of them, we will + // probably need to do something different when we implement shuffle + if (sceneNum == SCENE_TREASURE_BOX_SHOP) { + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_1)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_2)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_3)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_4)->MarkAsNotObtained(); + Flags_UnsetRandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5); + Rando::Context::GetInstance()->GetItemLocation(RC_MARKET_TREASURE_CHEST_GAME_KEY_5)->MarkAsNotObtained(); + } + + // LACs & Prelude checks + static uint32_t updateHook = 0; + + if (updateHook) { + GameInteractor::Instance->UnregisterGameHook(updateHook); + updateHook = 0; + } + + if ( + sceneNum != SCENE_TEMPLE_OF_TIME || + ( + Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && + Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) + ) + ) return; + + updateHook = GameInteractor::Instance->RegisterGameHook([]() { + if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && gPlayState->roomCtx.curRoom.num == 0) { + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); + } + + if (!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements()) { + Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + } + + if ( + Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && + Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) + ) { + GameInteractor::Instance->UnregisterGameHook(updateHook); + } + }); +} + +void EnSi_DrawRandomizedItem(EnSi* enSi, PlayState* play) { + func_8002ED80(&enSi->actor, play, 0); + func_8002EBCC(&enSi->actor, play, 0); + EnItem00_CustomItemsParticles(&enSi->actor, play, enSi->sohGetItemEntry); + GetItemEntry_Draw(play, enSi->sohGetItemEntry); +} + +u32 EnDns_RandomizerPurchaseableCheck(EnDns* enDns) { + if (Flags_GetRandomizerInf(enDns->sohScrubIdentity.randomizerInf)) { + return 3; // Can't get this now + } + if (gSaveContext.rupees < enDns->dnsItemEntry->itemPrice) { + return 0; // Not enough rupees + } + return 4; +} + +void EnDns_RandomizerPurchase(EnDns* enDns) { + Rupees_ChangeBy(-enDns->dnsItemEntry->itemPrice); + Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf); +} + +void ObjComb_RandomizerChooseItemDrop(ObjComb* objComb, PlayState* play) { + s16 params = objComb->actor.params & 0x1F; + + if ( + RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && + !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf) + ) { + EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &objComb->actor.world.pos, ITEM00_SOH_DUMMY); + item00->randoInf = objComb->beehiveIdentity.randomizerInf; + item00->itemEntry = OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(objComb->beehiveIdentity.randomizerCheck, GI_NONE); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + return; + } + + if ((params > 0) || (params < 0x1A)) { + if (params == 6) { + if (Flags_GetCollectible(play, (objComb->actor.params >> 8) & 0x3F)) { + params = -1; + } else { + params = (params | (((objComb->actor.params >> 8) & 0x3F) << 8)); + } + } else if (Rand_ZeroOne() < 0.5f) { + params = -1; + } + if (params >= 0 && !CVarGetInteger("gNoRandomDrops", 0)) { + Item_DropCollectible(play, &objComb->actor.world.pos, params); + } + } +} + +void ObjComb_RandomizerWait(ObjComb* objComb, PlayState* play) { + s32 dmgFlags; + + objComb->unk_1B0 -= 50; + if ( + RAND_GET_OPTION(RSK_SHUFFLE_BEEHIVES) && + !Flags_GetRandomizerInf(objComb->beehiveIdentity.randomizerInf) + ) { + if (objComb->unk_1B0 <= -5000) { + objComb->unk_1B0 = 1500; + } + } else if (objComb->unk_1B0 < 0) { + objComb->unk_1B0 = 0; + } + + if ((objComb->collider.base.acFlags & AC_HIT) != 0) { + objComb->collider.base.acFlags &= ~AC_HIT; + dmgFlags = objComb->collider.elements[0].info.acHitInfo->toucher.dmgFlags; + if (dmgFlags & 0x4001F866) { + objComb->unk_1B0 = 1500; + } else { + ObjComb_Break(objComb, play); + ObjComb_RandomizerChooseItemDrop(objComb, play); + Actor_Kill(&objComb->actor); + } + } else { + CollisionCheck_SetAC(play, &play->colChkCtx, &objComb->collider.base); + } + + if (objComb->actor.update != NULL) { + CollisionCheck_SetOC(play, &play->colChkCtx, &objComb->collider.base); + } +} + +void RandomizerOnActorInitHandler(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id == ACTOR_EN_SI) { + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params); + if (rc != RC_UNKNOWN_CHECK) { + EnSi* enSi = static_cast(actorRef); + enSi->sohGetItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + actor->draw = (ActorFunc)EnSi_DrawRandomizedItem; + } + } + + if (actor->id == ACTOR_ITEM_B_HEART) { + ItemBHeart* itemBHeart = static_cast(actorRef); + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(itemBHeart->actor.id, gPlayState->sceneNum, itemBHeart->actor.params); + if (rc != RC_UNKNOWN_CHECK) { + itemBHeart->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + itemBHeart->actor.draw = (ActorFunc)ItemBHeart_DrawRandomizedItem; + itemBHeart->actor.update = (ActorFunc)ItemBHeart_UpdateRandomizedItem; + } + } + + if (actor->id == ACTOR_EN_DNS) { + EnDns* enDns = static_cast(actorRef); + s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); + enDns->sohScrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enDns->actor.params, respawnData); + + if (enDns->sohScrubIdentity.isShuffled) { + // DNS uses pointers so we're creating our own entry instead of modifying the original + enDns->sohDnsItemEntry = { + enDns->dnsItemEntry->itemPrice, + 1, + enDns->sohScrubIdentity.getItemId, + EnDns_RandomizerPurchaseableCheck, + EnDns_RandomizerPurchase, + }; + enDns->dnsItemEntry = &enDns->sohDnsItemEntry; + + if (enDns->sohScrubIdentity.itemPrice != -1) { + enDns->dnsItemEntry->itemPrice = enDns->sohScrubIdentity.itemPrice; + } + + enDns->actor.textId = TEXT_SCRUB_RANDOM; + + static uint32_t enDnsUpdateHook = 0; + static uint32_t enDnsKillHook = 0; + if (!enDnsUpdateHook) { + enDnsUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_DNS) { + EnDns* innerEnDns = static_cast(innerActorRef); + if (innerEnDns->sohScrubIdentity.isShuffled) { + innerActor->textId = TEXT_SCRUB_RANDOM; + } + } + }); + enDnsKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) { + GameInteractor::Instance->UnregisterGameHook(enDnsUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enDnsKillHook); + enDnsUpdateHook = 0; + enDnsKillHook = 0; + }); + } + } + } + + if (actor->id == ACTOR_ITEM_ETCETERA) { + ItemEtcetera* itemEtcetera = static_cast(actorRef); + RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(itemEtcetera->actor.id, gPlayState->sceneNum, itemEtcetera->actor.params); + if (rc != RC_UNKNOWN_CHECK) { + itemEtcetera->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + itemEtcetera->drawFunc = (ActorFunc)ItemEtcetera_DrawRandomizedItem; + } + + int32_t type = itemEtcetera->actor.params & 0xFF; + switch (type) { + case ITEM_ETC_LETTER: { + itemEtcetera->futureActionFunc = (ItemEtceteraActionFunc)ItemEtcetera_func_80B858B4_Randomized; + break; + } + case ITEM_ETC_ARROW_FIRE: { + itemEtcetera->futureActionFunc = (ItemEtceteraActionFunc)ItemEtcetera_UpdateRandomizedFireArrow; + break; + } + case ITEM_ETC_RUPEE_GREEN_CHEST_GAME: + case ITEM_ETC_RUPEE_BLUE_CHEST_GAME: + case ITEM_ETC_RUPEE_RED_CHEST_GAME: + case ITEM_ETC_RUPEE_PURPLE_CHEST_GAME: + case ITEM_ETC_HEART_PIECE_CHEST_GAME: + case ITEM_ETC_KEY_SMALL_CHEST_GAME: { + if (rc != RC_UNKNOWN_CHECK) { + itemEtcetera->drawFunc = (ActorFunc)ItemEtcetera_DrawRandomizedItemThroughLens; + } + break; + } + } + } + + if (actor->id == ACTOR_OBJ_COMB) { + ObjComb* objComb = static_cast(actorRef); + s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); + objComb->beehiveIdentity = OTRGlobals::Instance->gRandomizer->IdentifyBeehive(gPlayState->sceneNum, (s16)actor->world.pos.x, respawnData); + objComb->actionFunc = (ObjCombActionFunc)ObjComb_RandomizerWait; + } + + if (actor->id == ACTOR_EN_EX_ITEM) { + EnExItem* enExItem = static_cast(actorRef); + + RandomizerCheck rc = RC_UNKNOWN_CHECK; + switch (enExItem->type) { + case EXITEM_BOMB_BAG_COUNTER: + case EXITEM_BOMB_BAG_BOWLING: + rc = RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE; + break; + case EXITEM_HEART_PIECE_COUNTER: + case EXITEM_HEART_PIECE_BOWLING: + rc = RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE; + break; + case EXITEM_BOMBCHUS_COUNTER: + case EXITEM_BOMBCHUS_BOWLING: + rc = RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS; + break; + case EXITEM_BULLET_BAG: + rc = RC_LW_TARGET_IN_WOODS; + break; + } + if (rc != RC_UNKNOWN_CHECK) { + enExItem->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem()); + enExItem->actionFunc = (EnExItemActionFunc)EnExItem_WaitForObjectRandomized; + } + } + + if (actor->id == ACTOR_EN_GE1) { + EnGe1* enGe1 = static_cast(actorRef); + auto ge1Type = enGe1->actor.params & 0xFF; + if (ge1Type == GE1_TYPE_TRAINING_GROUNDS_GUARD && + Flags_GetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)) { + enGe1->actionFunc = (EnGe1ActionFunc)EnGe1_SetNormalText; + } + } + + if (actor->id == ACTOR_DEMO_KEKKAI && actor->params == 0) { // 0 == KEKKAI_TOWER + if (CompletedAllTrials()) { + Actor_Kill(actor); + } + } +} + +void RandomizerRegisterHooks() { + static uint32_t onFlagSetHook = 0; + static uint32_t onSceneFlagSetHook = 0; + static uint32_t onPlayerUpdateForRCQueueHook = 0; + static uint32_t onPlayerUpdateForItemQueueHook = 0; + static uint32_t onItemReceiveHook = 0; + static uint32_t onVanillaBehaviorHook = 0; + static uint32_t onSceneInitHook = 0; + static uint32_t onActorInitHook = 0; + + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) { + randomizerQueuedChecks = std::queue(); + randomizerQueuedCheck = RC_UNKNOWN_CHECK; + randomizerQueuedItemEntry = GET_ITEM_NONE; + + GameInteractor::Instance->UnregisterGameHook(onFlagSetHook); + GameInteractor::Instance->UnregisterGameHook(onSceneFlagSetHook); + GameInteractor::Instance->UnregisterGameHook(onPlayerUpdateForRCQueueHook); + GameInteractor::Instance->UnregisterGameHook(onPlayerUpdateForItemQueueHook); + GameInteractor::Instance->UnregisterGameHook(onItemReceiveHook); + GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); + GameInteractor::Instance->UnregisterGameHook(onSceneInitHook); + GameInteractor::Instance->UnregisterGameHook(onActorInitHook); + + onFlagSetHook = 0; + onSceneFlagSetHook = 0; + onPlayerUpdateForRCQueueHook = 0; + onPlayerUpdateForItemQueueHook = 0; + onItemReceiveHook = 0; + onVanillaBehaviorHook = 0; + onSceneInitHook = 0; + onActorInitHook = 0; + + if (!IS_RANDO) return; + + onFlagSetHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnFlagSetHandler); + onSceneFlagSetHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnSceneFlagSetHandler); + onPlayerUpdateForRCQueueHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnPlayerUpdateForRCQueueHandler); + onPlayerUpdateForItemQueueHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnPlayerUpdateForItemQueueHandler); + onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnItemReceiveHandler); + onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnVanillaBehaviorHandler); + onSceneInitHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnSceneInitHandler); + onActorInitHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnActorInitHandler); + }); +} diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.h b/soh/soh/Enhancements/randomizer/hook_handlers.h new file mode 100644 index 000000000..46abb30b7 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/hook_handlers.h @@ -0,0 +1,6 @@ +#ifndef RANDOMIZER_HOOK_HANDLERS_H +#define RANDOMIZER_HOOK_HANDLERS_H + +void RandomizerRegisterHooks(); + +#endif // RANDOMIZER_HOOK_HANDLERS_H \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp index 59bceb8d5..032619a62 100644 --- a/soh/soh/Enhancements/randomizer/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/item_location.cpp @@ -101,6 +101,18 @@ void ItemLocation::SetCustomPrice(const uint16_t price_) { hasCustomPrice = true; } +bool ItemLocation::HasObtained() const { + return obtained; +} + +void ItemLocation::MarkAsObtained() { + obtained = true; +} + +void ItemLocation::MarkAsNotObtained() { + obtained = false; +} + bool ItemLocation::IsHintable() const { return isHintable; } @@ -201,5 +213,6 @@ void ItemLocation::ResetVariables() { wothCandidate = false; barrenCandidate = false; area = RA_NONE; + obtained = false; } } \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/item_location.h b/soh/soh/Enhancements/randomizer/item_location.h index dd5ec8a00..082fd4493 100644 --- a/soh/soh/Enhancements/randomizer/item_location.h +++ b/soh/soh/Enhancements/randomizer/item_location.h @@ -31,6 +31,9 @@ class ItemLocation { void SetPrice(uint16_t price_); bool HasCustomPrice() const; void SetCustomPrice(uint16_t price_); + bool HasObtained() const; + void MarkAsObtained(); + void MarkAsNotObtained(); bool IsHintable() const; void SetAsHintable(); bool IsAHintAccessible() const; @@ -67,5 +70,6 @@ class ItemLocation { bool visibleInImGui = false; bool wothCandidate = false; bool barrenCandidate = false; + bool obtained = false; }; } // namespace Rando \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index 993e8c184..1731067cf 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -16,10 +16,10 @@ class SpoilerCollectionCheck { public: SpoilerCollectionCheckType type = SPOILER_CHK_NONE; uint8_t scene = 0; - uint8_t flag = 0; + uint16_t flag = 0; SpoilerCollectionCheck() = default; - SpoilerCollectionCheck(const SpoilerCollectionCheckType type_, const uint8_t scene_, const uint8_t flag_) + SpoilerCollectionCheck(const SpoilerCollectionCheckType type_, const uint8_t scene_, const uint16_t flag_) : type(type_), scene(scene_), flag(flag_) { } @@ -39,8 +39,8 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag); } - static auto InfTable(const uint8_t offset, const uint8_t bit) { - return SpoilerCollectionCheck(SPOILER_CHK_INF_TABLE, offset, bit); + static auto InfTable(const uint16_t flag) { + return SpoilerCollectionCheck(SPOILER_CHK_INF_TABLE, 0xFF, flag); } static auto Collectable(const uint8_t scene, const uint8_t flag) { @@ -51,10 +51,6 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene, flag); } - static auto Cow(const uint8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_COW, scene, flag); - } - static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) { return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag); } @@ -63,14 +59,6 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit); } - static auto Scrub(const uint8_t scene, const uint8_t bit) { - return SpoilerCollectionCheck(SPOILER_CHK_SCRUB, scene, bit); - } - - static auto GerudoToken() { - return SpoilerCollectionCheck(SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00); - } - static auto BigPoePoints() { return SpoilerCollectionCheck(SPOILER_CHK_POE_POINTS, 0x00, 0x00); } @@ -83,20 +71,12 @@ class SpoilerCollectionCheck { return SpoilerCollectionCheck(SPOILER_CHK_SHOP_ITEM, scene, itemSlot); } - static auto MagicBeans(const uint8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_MAGIC_BEANS, scene, flag); - } - static auto MasterSword() { return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00); } - static auto Merchant(const int8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_MERCHANT, scene, flag); - } - - static auto RandomizerInf(const int8_t scene, const uint8_t flag) { - return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, scene, flag); + static auto RandomizerInf(const uint16_t flag) { + return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, 0x00, flag); } }; diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index f990bb1fb..92a91f32a 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -1,4 +1,5 @@ #include "static_data.h" +#include "z64save.h" #define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) @@ -208,6 +209,11 @@ std::vector Rando::StaticData::overworldLocations = { RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RC_MARKET_TREASURE_CHEST_GAME_KEY_1, + RC_MARKET_TREASURE_CHEST_GAME_KEY_2, + RC_MARKET_TREASURE_CHEST_GAME_KEY_3, + RC_MARKET_TREASURE_CHEST_GAME_KEY_4, + RC_MARKET_TREASURE_CHEST_GAME_KEY_5, // Market Shops RC_MARKET_BOMBCHU_SHOP_ITEM_1, @@ -246,6 +252,7 @@ std::vector Rando::StaticData::overworldLocations = { RC_TOT_MASTER_SWORD, RC_SHEIK_AT_TEMPLE, RC_TOT_LIGHT_ARROWS_CUTSCENE, + RC_GIFT_FROM_SAGES, // Kakariko RC_SHEIK_IN_KAKARIKO, @@ -596,786 +603,778 @@ typedef enum { using namespace Rando; -void Rando::StaticData::InitLocationTable() { +void Rando::StaticData::InitLocationTable() { // Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // clang-format off - locationTable[RC_UNKNOWN_CHECK] = Location::Base(RC_UNKNOWN_CHECK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Invalid Location", "Invalid Location", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None()); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression + locationTable[RC_UNKNOWN_CHECK] = Location::Base(RC_UNKNOWN_CHECK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Invalid Location", "Invalid Location", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None()); // Kokiri Forest - locationTable[RC_KF_KOKIRI_SWORD_CHEST] = Location::Chest(RC_KF_KOKIRI_SWORD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, 0x00, "Kokiri Sword Chest", "KF Kokiri Sword Chest", RHT_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_KF_MIDOS_TOP_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, 0x00, "Mido Top Left Chest", "KF Mido Top Left Chest", RHT_KF_MIDOS_TOP_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_TOP_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, 0x01, "Mido Top Right Chest", "KF Mido Top Right Chest", RHT_KF_MIDOS_TOP_RIGHT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_BOTTOM_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22914, 0x02, "Mido Bottom Left Chest", "KF Mido Bottom Left Chest", RHT_KF_MIDOS_BOTTOM_LEFT_CHEST, RG_GREG_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_MIDOS_BOTTOM_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22787, 0x03, "Mido Bottom Right Chest", "KF Mido Bottom Right Chest", RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_STORMS_GROTTO_CHEST] = Location::Chest(RC_KF_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_GROTTOS, 22988, 0x0C, "Storms Grotto Chest", "KF Storms Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_KOKIRI_SWORD_CHEST] = Location::Chest(RC_KF_KOKIRI_SWORD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, 0x00, "Kokiri Sword Chest", "KF Kokiri Sword Chest", RHT_KF_KOKIRI_SWORD_CHEST, RG_KOKIRI_SWORD, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); + locationTable[RC_KF_MIDOS_TOP_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, 0x00, "Mido Top Left Chest", "KF Mido Top Left Chest", RHT_KF_MIDOS_TOP_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_TOP_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, 0x01, "Mido Top Right Chest", "KF Mido Top Right Chest", RHT_KF_MIDOS_TOP_RIGHT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_BOTTOM_LEFT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22914, 0x02, "Mido Bottom Left Chest", "KF Mido Bottom Left Chest", RHT_KF_MIDOS_BOTTOM_LEFT_CHEST, RG_GREG_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_MIDOS_BOTTOM_RIGHT_CHEST] = Location::Chest(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22787, 0x03, "Mido Bottom Right Chest", "KF Mido Bottom Right Chest", RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_STORMS_GROTTO_CHEST] = Location::Chest(RC_KF_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_GROTTOS, 22988, 0x0C, "Storms Grotto Chest", "KF Storms Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Lost Woods - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = Location::Chest(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_GROTTOS, 22964, 0x14, "Near Shortcuts Grotto Chest", "LW Near Shortcuts Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_SKULL_KID] = Location::Base(RC_LW_SKULL_KID, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x3E, "Skull Kid", "LW Skull Kid", RHT_LW_SKULL_KID, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(30), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TRADE_COJIRO] = Location::Base(RC_LW_TRADE_COJIRO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x1F, "Trade Cojiro", "LW Trade Cojiro", RHT_LW_TRADE_COJIRO, RG_ODD_MUSHROOM, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x5B, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TRADE_ODD_POTION] = Location::Base(RC_LW_TRADE_ODD_POTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Trade Odd Potion", "LW Trade Odd Potion", RHT_LW_TRADE_COJIRO, RG_POACHERS_SAW, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_OCARINA_MEMORY_GAME] = Location::Base(RC_LW_OCARINA_MEMORY_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Ocarina Memory Game", "LW Ocarina Memory Game", RHT_LW_OCARINA_MEMORY_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(31), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_TARGET_IN_WOODS] = Location::Base(RC_LW_TARGET_IN_WOODS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x60, "Target in Woods", "LW Target in Woods", RHT_LW_TARGET_IN_WOODS, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x00, 0x30, "Deku Scrub Near Deku Theater Right","LW Deku Scrub Near Deku Theater Right",RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x5B, 0x01), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, 0x31, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x5B, 0x02), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE,{ Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::Scrub(0x5B, 0x0A), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x1F, 0x04), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::Scrub(0x1F, 0x0B), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE,{}, SpoilerCollectionCheck::Chest(0x3E, 0x1F), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::Chest(0x3E, 0x1E), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = Location::Chest(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_EN_BOX, SCENE_GROTTOS, 22964, 0x14, "Near Shortcuts Grotto Chest", "LW Near Shortcuts Grotto Chest", RHT_KF_STORMS_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_SKULL_KID] = Location::Base(RC_LW_SKULL_KID, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x3E, "Skull Kid", "LW Skull Kid", RHT_LW_SKULL_KID, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(22), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TRADE_COJIRO] = Location::Base(RC_LW_TRADE_COJIRO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x1F, "Trade Cojiro", "LW Trade Cojiro", RHT_LW_TRADE_COJIRO, RG_ODD_MUSHROOM, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TRADE_ODD_POTION] = Location::Base(RC_LW_TRADE_ODD_POTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Trade Odd Potion", "LW Trade Odd Potion", RHT_LW_TRADE_COJIRO, RG_POACHERS_SAW, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(49), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_OCARINA_MEMORY_GAME] = Location::Base(RC_LW_OCARINA_MEMORY_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x21, "Ocarina Memory Game", "LW Ocarina Memory Game", RHT_LW_OCARINA_MEMORY_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(23), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_TARGET_IN_WOODS] = Location::Base(RC_LW_TARGET_IN_WOODS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x60, "Target in Woods", "LW Target in Woods", RHT_LW_TARGET_IN_WOODS, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x00, 0x30, "Deku Scrub Near Deku Theater Right", "LW Deku Scrub Near Deku Theater Right", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, 0x31, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", RHT_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_NEAR_BRIDGE] = Location::Base(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, 0x77, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", RHT_LW_DEKU_SCRUB_NEAR_BRIDGE, RG_PROGRESSIVE_STICK_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF5), 0x33, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", RHT_LW_DEKU_SCRUB_GROTTO_REAR, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A, 0xF5), 0x79, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", RHT_LW_DEKU_SCRUB_GROTTO_FRONT, RG_PROGRESSIVE_NUT_UPGRADE, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_DEKU_THEATER_SKULL_MASK] = Location::Base(RC_DEKU_THEATER_SKULL_MASK, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x77, "Deku Theater Skull Mask", "Deku Theater Skull Mask", RHT_DEKU_THEATER_SKULL_MASK, RG_PROGRESSIVE_STICK_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_DEKU_THEATER_MASK_OF_TRUTH] = Location::Base(RC_DEKU_THEATER_MASK_OF_TRUTH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, 0x7A, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", RHT_DEKU_THEATER_MASK_OF_TRUTH, RG_PROGRESSIVE_NUT_UPGRADE, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); // Sacred Forest Meadow - locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x18, 0x08), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEE), 0x3A, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front", RHT_SFM_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x18, 0x09), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_WOLFOS_GROTTO_CHEST] = Location::Chest(RC_SFM_WOLFOS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_BOX, SCENE_GROTTOS, 31409, 0x11, "Wolfos Grotto Chest", "SFM Wolfos Grotto Chest", RHT_SFM_WOLFOS_GROTTO_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEE), 0x39, "Deku Scrub Grotto Rear", "SFM Deku Scrub Grotto Rear", RHT_SFM_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_SACRED_FOREST_MEADOW, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEE), 0x3A, "Deku Scrub Grotto Front", "SFM Deku Scrub Grotto Front", RHT_SFM_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); // Hyrule Field - locationTable[RC_HF_SOUTHEAST_GROTTO_CHEST] = Location::Chest(RC_HF_SOUTHEAST_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22978, 0x02, "Southeast Grotto Chest", "HF Southeast Grotto Chest", RHT_HF_SOUTHEAST_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_CHEST] = Location::Chest(RC_HF_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22947, 0x03, "Open Grotto Chest", "HF Open Grotto Chest", RHT_HF_OPEN_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_CHEST] = Location::Chest(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22944, 0x00, "Near Market Grotto Chest", "HF Near Market Grotto Chest", RHT_HF_NEAR_MARKET_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OCARINA_OF_TIME_ITEM] = Location::Base(RC_HF_OCARINA_OF_TIME_ITEM, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, 0x0C, "Ocarina of Time Item", "HF Ocarina of Time Item", RHT_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0x43), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_TEKTITE_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_GROTTOS, 262, 0x01, "Tektite Grotto Freestanding PoH", "HF Tektite Grotto Freestanding PoH", RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); - locationTable[RC_HF_DEKU_SCRUB_GROTTO] = Location::GrottoScrub(RC_HF_DEKU_SCRUB_GROTTO, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x02, 0xE6), 0x3E, "Deku Scrub Grotto", "HF Deku Scrub Grotto", RHT_HF_DEKU_SCRUB_GROTTO, RG_PIECE_OF_HEART, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::Scrub(0x10, 0x03), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_HF_SOUTHEAST_GROTTO_CHEST] = Location::Chest(RC_HF_SOUTHEAST_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22978, 0x02, "Southeast Grotto Chest", "HF Southeast Grotto Chest", RHT_HF_SOUTHEAST_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_CHEST] = Location::Chest(RC_HF_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22947, 0x03, "Open Grotto Chest", "HF Open Grotto Chest", RHT_HF_OPEN_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_CHEST] = Location::Chest(RC_HF_NEAR_MARKET_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_BOX, SCENE_GROTTOS, 22944, 0x00, "Near Market Grotto Chest", "HF Near Market Grotto Chest", RHT_HF_NEAR_MARKET_GROTTO_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OCARINA_OF_TIME_ITEM] = Location::Base(RC_HF_OCARINA_OF_TIME_ITEM, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_HYRULE_FIELD, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, 0x0C, "Ocarina of Time Item", "HF Ocarina of Time Item", RHT_HF_OCARINA_OF_TIME_ITEM, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0x43), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_TEKTITE_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_FIELD, ACTOR_EN_ITEM00, SCENE_GROTTOS, 262, 0x01, "Tektite Grotto Freestanding PoH", "HF Tektite Grotto Freestanding PoH", RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); + locationTable[RC_HF_DEKU_SCRUB_GROTTO] = Location::GrottoScrub(RC_HF_DEKU_SCRUB_GROTTO, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_HYRULE_FIELD, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x02, 0xE6), 0x3E, "Deku Scrub Grotto", "HF Deku Scrub Grotto", RHT_HF_DEKU_SCRUB_GROTTO, RG_PIECE_OF_HEART, { Category::cDekuScrub, Category::cDekuScrubUpgrades }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, true); // Lake Hylia - locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", "LH Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_FISHING_POND, RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", "LH Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_FISHING_POND, RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", "LH Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(24), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x38, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", "LH Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_SUN] = Location::Base(RC_LH_SUN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x58, "Sun", "LH Sun", RHT_LH_SUN, RG_FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_FREESTANDING_POH] = Location::Collectable(RC_LH_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_LAKE_HYLIA, 7686, 0x1E, "Freestanding PoH", "LH Freestanding PoH", RHT_LH_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xEF), 0x30, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left", RHT_LH_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x19, 0x01), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xEF), 0x37, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right", RHT_LH_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x19, 0x06), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xEF), 0x33, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center", RHT_LH_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x19, 0x04), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISHING] = Location::Base(RC_LH_CHILD_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x3E, "Child Fishing", "LH Child Fishing", RHT_LH_CHILD_FISHING, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_CHILD_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_ADULT_FISHING] = Location::Base(RC_LH_ADULT_FISHING, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_FISHING_POND, 0x00, 0x38, "Adult Fishing", "LH Adult Fishing", RHT_LH_ADULT_FISHING, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_FISHING), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_LAB_DIVE] = Location::Base(RC_LH_LAB_DIVE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x3E, "Lab Dive", "LH Lab Dive", RHT_LH_LAB_DIVE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(16), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_TRADE_FROG] = Location::Base(RC_LH_TRADE_FROG, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKESIDE_LABORATORY, 0x00, 0x25, "Lab Trade Eyeball Frog", "LH Lab Trade Eyeball Frog", RHT_LH_TRADE_FROG, RG_EYEDROPS, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_UNDERWATER_ITEM] = Location::Base(RC_LH_UNDERWATER_ITEM, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x15, "Underwater Item", "LH Underwater Item", RHT_LH_UNDERWATER_ITEM, RG_RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_SUN] = Location::Base(RC_LH_SUN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_ID_MAX, SCENE_LAKE_HYLIA, 0x00, 0x58, "Sun", "LH Sun", RHT_LH_SUN, RG_FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_FREESTANDING_POH] = Location::Collectable(RC_LH_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LAKE_HYLIA, ACTOR_EN_ITEM00, SCENE_LAKE_HYLIA, 7686, 0x1E, "Freestanding PoH", "LH Freestanding PoH", RHT_LH_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, true); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xEF), 0x30, "Deku Scrub Grotto Left", "LH Deku Scrub Grotto Left", RHT_LH_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xEF), 0x37, "Deku Scrub Grotto Right", "LH Deku Scrub Grotto Right", RHT_LH_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LH_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LAKE_HYLIA, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xEF), 0x33, "Deku Scrub Grotto Center", "LH Deku Scrub Grotto Center", RHT_LH_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Gerudo Valley - locationTable[RC_GV_CHEST] = Location::Chest(RC_GV_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_GERUDO_VALLEY, 23200, 0x00, "Chest", "GV Chest", RHT_GV_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_TRADE_SAW] = Location::Base(RC_GV_TRADE_SAW, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_GERUDO_VALLEY, 0x00, 0x22, "Trade Saw", "GV Trade Saw", RHT_GV_TRADE_SAW, RG_BROKEN_SWORD, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x5A, 0x1F), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_WATERFALL_FREESTANDING_POH] = Location::Collectable(RC_GV_WATERFALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 262, 0x01, "Waterfall Freestanding PoH", "GV Waterfall Freestanding PoH", RHT_GV_WATERFALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_CRATE_FREESTANDING_POH] = Location::Collectable(RC_GV_CRATE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 518, 0x02, "Crate Freestanding PoH", "GV Crate Freestanding PoH", RHT_GV_CRATE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xF0), 0x39, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x1A, 0x09), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x1A, 0x09), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_CHEST] = Location::Chest(RC_GV_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_BOX, SCENE_GERUDO_VALLEY, 23200, 0x00, "Chest", "GV Chest", RHT_GV_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_TRADE_SAW] = Location::Base(RC_GV_TRADE_SAW, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_GERUDO_VALLEY, ACTOR_ID_MAX, SCENE_GERUDO_VALLEY, 0x00, 0x22, "Trade Saw", "GV Trade Saw", RHT_GV_TRADE_SAW, RG_BROKEN_SWORD, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_WATERFALL_FREESTANDING_POH] = Location::Collectable(RC_GV_WATERFALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 262, 0x01, "Waterfall Freestanding PoH", "GV Waterfall Freestanding PoH", RHT_GV_WATERFALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_CRATE_FREESTANDING_POH] = Location::Collectable(RC_GV_CRATE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_VALLEY, ACTOR_EN_ITEM00, SCENE_GERUDO_VALLEY, 518, 0x02, "Crate Freestanding PoH", "GV Crate Freestanding PoH", RHT_GV_CRATE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xF0), 0x39, "Deku Scrub Grotto Rear", "GV Deku Scrub Grotto Rear", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_GV_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GERUDO_VALLEY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xF0), 0x3A, "Deku Scrub Grotto Front", "GV Deku Scrub Grotto Front", RHT_GV_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress - locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", "GF Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(7), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_CHEST] = Location::Chest(RC_GF_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_EN_BOX, SCENE_GERUDOS_FORTRESS, 1984, 0x00, "Chest", "GF Chest", RHT_GF_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1000_POINTS] = Location::Base(RC_GF_HBA_1000_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x3E, "GF HBA 1000 Points", "GF HBA 1000 Points", RHT_GF_HBA_1000_POINTS, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_190), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_HBA_1500_POINTS] = Location::Base(RC_GF_HBA_1500_POINTS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_GERUDOS_FORTRESS, 0x00, 0x30, "GF HBA 1500 Points", "GF HBA 1500 Points", RHT_GF_HBA_1500_POINTS, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // RandoTodo: Do we replace these with the RC_HIDEOUT keys or keep these? - locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_GF_SOUTH_F2_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3857, 0x0F, "GF South F2 Carpenter", "GF South F2 Carpenter", RHT_GF_SOUTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY,{ Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_GERUDO_MEMBERSHIP_CARD] = Location::Base(RC_GF_GERUDO_MEMBERSHIP_CARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GERUDO_FORTRESS, ACTOR_ID_MAX, SCENE_THIEVES_HIDEOUT, 0x00, 0x3A, "GF Gerudo Membership Card", "GF Gerudo Membership Card", RHT_GF_GERUDO_MEMBERSHIP_CARD, RG_GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_NORTH_F1_CARPENTER] = Location::Collectable(RC_GF_NORTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3089, 0x0C, "GF North F1 Carpenter", "GF North F1 Carpenter", RHT_GF_NORTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_NORTH_F2_CARPENTER] = Location::Collectable(RC_GF_NORTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 2577, 0x0A, "GF North F2 Carpenter", "GF North F2 Carpenter", RHT_GF_NORTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_SOUTH_F1_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F1_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3601, 0x0E, "GF South F1 Carpenter", "GF South F1 Carpenter", RHT_GF_SOUTH_F1_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_GF_SOUTH_F2_CARPENTER] = Location::Collectable(RC_GF_SOUTH_F2_CARPENTER, RCQUEST_BOTH, RCTYPE_GF_KEY, RCAREA_GERUDO_FORTRESS, ACTOR_EN_ITEM00, SCENE_THIEVES_HIDEOUT, 3857, 0x0F, "GF South F2 Carpenter", "GF South F2 Carpenter", RHT_GF_SOUTH_F2_CARPENTER, RG_GERUDO_FORTRESS_SMALL_KEY, { Category::cVanillaGFSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); // Haunted Wasteland - locationTable[RC_WASTELAND_CHEST] = Location::Chest(RC_WASTELAND_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_HAUNTED_WASTELAND, -30048, 0x00, "Chest", "Wasteland Chest", RHT_WASTELAND_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_WASTELAND_BOMBCHU_SALESMAN] = Location::Base(RC_WASTELAND_BOMBCHU_SALESMAN, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_HAUNTED_WASTELAND, 0x00, 0x03, "Carpet Salesman", "Wasteland Carpet Salesman", RHT_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, { Category::cMerchant }, SpoilerCollectionCheck::Merchant(0x5E, 0x86), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_CHEST] = Location::Chest(RC_WASTELAND_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_WASTELAND, ACTOR_EN_BOX, SCENE_HAUNTED_WASTELAND, -30048, 0x00, "Chest", "Wasteland Chest", RHT_WASTELAND_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_BOMBCHU_SALESMAN] = Location::Base(RC_WASTELAND_BOMBCHU_SALESMAN, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_WASTELAND, ACTOR_ID_MAX, SCENE_HAUNTED_WASTELAND, 0x00, 0x03, "Carpet Salesman", "Wasteland Carpet Salesman", RHT_WASTELAND_BOMBCHU_SALESMAN, RG_BOMBCHU_10, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Desert Colossus - locationTable[RC_COLOSSUS_FREESTANDING_POH] = Location::Collectable(RC_COLOSSUS_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_DESERT_COLOSSUS, 3334, 0x0D, "Freestanding PoH", "Colossus Freestanding PoH", RHT_COLOSSUS_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xFD), 0x39, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x27, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xFD), 0x3A, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x27, 0x09), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_FREESTANDING_POH] = Location::Collectable(RC_COLOSSUS_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_EN_ITEM00, SCENE_DESERT_COLOSSUS, 3334, 0x0D, "Freestanding PoH", "Colossus Freestanding PoH", RHT_COLOSSUS_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xFD), 0x39, "Deku Scrub Grotto Rear", "Colossus Deku Scrub Grotto Rear", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DESERT_COLOSSUS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xFD), 0x3A, "Deku Scrub Grotto Front", "Colossus Deku Scrub Grotto Front", RHT_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Market - locationTable[RC_MARKET_TREASURE_CHEST_GAME_REWARD] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x0A, "Treasure Chest Game Reward", "MK Treasure Chest Game Reward", RHT_MARKET_TREASURE_CHEST_GAME_REWARD, RG_TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(19), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", "MK Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(25), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(26), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_MARKET_GUARD_HOUSE, RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x03, "Chest Game Second Room Chest", "MK Chest Game Second Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x05, "Chest Game Third Room Chest", "MK Chest Game Third Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x07, "Chest Game Fourth Room Chest", "MK Chest Game Fourth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x09, "Chest Game Fifth Room Chest", "MK Chest Game Fifth Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_REWARD] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x0A, "Treasure Chest Game Reward", "MK Treasure Chest Game Reward", RHT_MARKET_TREASURE_CHEST_GAME_REWARD, RG_TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(27), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x33, "Bombchu Bowling First Prize", "MK Bombchu Bowling First Prize", RHT_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(17), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(INFTABLE_191), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Item", "MK Chest Game First Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Item", "MK Chest Game Second Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_GREEN_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Item", "MK Chest Game Third Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Item", "MK Chest Game Fourth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RG_BLUE_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Item", "MK Chest Game Fifth Room Item", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, RG_RED_RUPEE, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game First Room Key", "MK Chest Game First Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Second Room Key", "MK Chest Game Second Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_3] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Third Room Key", "MK Chest Game Third Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_3, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_4] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fourth Room Key", "MK Chest Game Fourth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_4, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_TREASURE_CHEST_GAME_KEY_5] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0xFF, "Chest Game Fifth Room Key", "MK Chest Game Fifth Room Key", RHT_MARKET_TREASURE_CHEST_GAME_KEY_5, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Hyrule Castle - locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", "HC Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", "HC Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_HC_MALON_EGG] = Location::Base(RC_HC_MALON_EGG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_HYRULE_CASTLE, 0x00, 0x47, "Malon Egg", "HC Malon Egg", RHT_HC_MALON_EGG, RG_WEIRD_EGG, {}, SpoilerCollectionCheck::EventChkInf(0x12), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_HC_ZELDAS_LETTER] = Location::Base(RC_HC_ZELDAS_LETTER, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_CASTLE_COURTYARD_ZELDA, 0x00, 0x0B, "Zeldas Letter", "HC Zeldas Letter", RHT_HC_ZELDAS_LETTER, RG_ZELDAS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x40), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); // Kakariko - locationTable[RC_KAK_REDEAD_GROTTO_CHEST] = Location::Chest(RC_KAK_REDEAD_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 31434, 0x0A, "Redead Grotto Chest", "Kak Redead Grotto Chest", RHT_KAK_REDEAD_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_OPEN_GROTTO_CHEST] = Location::Chest(RC_KAK_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 22984, 0x08, "Open Grotto Chest", "Kak Open Grotto Chest", RHT_KAK_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_10_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_10_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x45, "10 Gold Skulltula Reward", "Kak 10 Gold Skulltula Reward", RHT_KAK_10_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_20_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_20_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x39, "20 Gold Skulltula Reward", "Kak 20 Gold Skulltula Reward", RHT_KAK_20_GOLD_SKULLTULA_REWARD, RG_STONE_OF_AGONY, {}, SpoilerCollectionCheck::EventChkInf(0xDB), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_30_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x46, "30 Gold Skulltula Reward", "Kak 30 Gold Skulltula Reward", RHT_KAK_30_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_40_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x03, "40 Gold Skulltula Reward", "Kak 40 Gold Skulltula Reward", RHT_KAK_40_GOLD_SKULLTULA_REWARD, RG_BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_HOUSE_OF_SKULLTULA, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(56), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(SCENE_POTION_SHOP_GRANNY, RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(36), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_ANJU_AS_CHILD] = Location::Base(RC_KAK_ANJU_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0F, "Anju as Child", "Kak Anju as Child", RHT_KAK_ANJU_AS_CHILD, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_TRADE_POCKET_CUCCO] = Location::Base(RC_KAK_TRADE_POCKET_CUCCO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0E, "Trade Pocket Cucco", "Kak Trade Pocket Cucco", RHT_KAK_TRADE_POCKET_CUCCO, RG_COJIRO, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(38), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_IMPAS_HOUSE_FREESTANDING_POH] = Location::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_IMPAS_HOUSE, 262, 0x01, "Impas House Freestanding PoH", "Kak Impas House Freestanding PoH", RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_WINDMILL_FREESTANDING_POH] = Location::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 262, 0x01, "Windmill Freestanding PoH", "Kak Windmill Freestanding PoH", RHT_KAK_WINDMILL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_REDEAD_GROTTO_CHEST] = Location::Chest(RC_KAK_REDEAD_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 31434, 0x0A, "Redead Grotto Chest", "Kak Redead Grotto Chest", RHT_KAK_REDEAD_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_OPEN_GROTTO_CHEST] = Location::Chest(RC_KAK_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_BOX, SCENE_GROTTOS, 22984, 0x08, "Open Grotto Chest", "Kak Open Grotto Chest", RHT_KAK_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_10_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_10_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x45, "10 Gold Skulltula Reward", "Kak 10 Gold Skulltula Reward", RHT_KAK_10_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_20_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_20_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x39, "20 Gold Skulltula Reward", "Kak 20 Gold Skulltula Reward", RHT_KAK_20_GOLD_SKULLTULA_REWARD, RG_STONE_OF_AGONY, {}, SpoilerCollectionCheck::EventChkInf(0xDB), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_30_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_30_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x46, "30 Gold Skulltula Reward", "Kak 30 Gold Skulltula Reward", RHT_KAK_30_GOLD_SKULLTULA_REWARD, RG_PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_40_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_40_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x03, "40 Gold Skulltula Reward", "Kak 40 Gold Skulltula Reward", RHT_KAK_40_GOLD_SKULLTULA_REWARD, RG_BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0E), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_ANJU_AS_CHILD] = Location::Base(RC_KAK_ANJU_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0F, "Anju as Child", "Kak Anju as Child", RHT_KAK_ANJU_AS_CHILD, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(12), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_TRADE_POCKET_CUCCO] = Location::Base(RC_KAK_TRADE_POCKET_CUCCO, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x0E, "Trade Pocket Cucco", "Kak Trade Pocket Cucco", RHT_KAK_TRADE_POCKET_CUCCO, RG_COJIRO, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(46), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_IMPAS_HOUSE_FREESTANDING_POH] = Location::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_IMPAS_HOUSE, 262, 0x01, "Impas House Freestanding PoH", "Kak Impas House Freestanding PoH", RHT_KAK_IMPAS_HOUSE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_WINDMILL_FREESTANDING_POH] = Location::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 262, 0x01, "Windmill Freestanding PoH", "Kak Windmill Freestanding PoH", RHT_KAK_WINDMILL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); // Graveyard - locationTable[RC_GRAVEYARD_SHIELD_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN,21824, 0x00, "Shield Grave Chest", "GY Shield Grave Chest", RHT_GRAVEYARD_SHIELD_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_REDEAD_GRAVE, -22592, 0x00, "Heart Piece Grave Chest", "GY Heart Piece Grave Chest", RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = Location::Chest(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_ROYAL_FAMILYS_TOMB, -32736, 0x00, "Composers Grave Chest", "GY Composers Grave Chest", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_HOOKSHOT_CHEST] = Location::Chest(RC_GRAVEYARD_HOOKSHOT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, 0x00, "Hookshot Chest", "GY Hookshot Chest", RHT_GRAVEYARD_HOOKSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, 0x04, "Freestanding PoH", "GY Freestanding PoH", RHT_GRAVEYARD_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] =Location::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH,RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, 0x07, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH,RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = Location::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, 0x08, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::Gravedigger(0x53, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_SHIELD_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, 21824, 0x00, "Shield Grave Chest", "GY Shield Grave Chest", RHT_GRAVEYARD_SHIELD_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST] = Location::Chest(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_REDEAD_GRAVE, -22592, 0x00, "Heart Piece Grave Chest", "GY Heart Piece Grave Chest", RHT_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST] = Location::Chest(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_ROYAL_FAMILYS_TOMB, -32736, 0x00, "Composers Grave Chest", "GY Composers Grave Chest", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_HOOKSHOT_CHEST] = Location::Chest(RC_GRAVEYARD_HOOKSHOT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, 0x00, "Hookshot Chest", "GY Hookshot Chest", RHT_GRAVEYARD_HOOKSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, 0x04, "Freestanding PoH", "GY Freestanding PoH", RHT_GRAVEYARD_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = Location::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, 0x07, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", RHT_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = Location::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, 0x19, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", RHT_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); // Death Mountain - locationTable[RC_DMT_CHEST] = Location::Chest(RC_DMT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_DEATH_MOUNTAIN_TRAIL, 23201, 0x01, "Chest", "DMT Chest", RHT_DMT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_STORMS_GROTTO_CHEST] = Location::Chest(RC_DMT_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_GROTTOS, 23255, 0x17, "Storms Grotto Chest", "DMT Storms Grotto Chest", RHT_DMT_STORMS_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_TRADE_BROKEN_SWORD] = Location::Base(RC_DMT_TRADE_BROKEN_SWORD, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x23, "Trade Broken Sword", "DMT Trade Broken Sword", RHT_DMT_TRADE_BROKEN_SWORD, RG_PRESCRIPTION, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x60, 0x1D), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_TRADE_EYEDROPS] = Location::Base(RC_DMT_TRADE_EYEDROPS, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x26, "Trade Eyedrops", "DMT Trade Eyedrops", RHT_DMT_TRADE_EYEDROPS, RG_CLAIM_CHECK, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(0x60, 0x1E), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_TRADE_CLAIM_CHECK] = Location::Base(RC_DMT_TRADE_CLAIM_CHECK, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x57, "Trade Claim Check", "DMT Trade Claim Check", RHT_DMT_TRADE_CLAIM_CHECK, RG_BIGGORON_SWORD, {}, SpoilerCollectionCheck::Chest(0x60, 0x1F), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMT_FREESTANDING_POH] = Location::Collectable(RC_DMT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_TRAIL, 7686, 0x1E, "Freestanding PoH", "DMT Freestanding PoH", RHT_DMT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_CHEST] = Location::Chest(RC_DMT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_DEATH_MOUNTAIN_TRAIL, 23201, 0x01, "Chest", "DMT Chest", RHT_DMT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_CHEST] = Location::Chest(RC_DMT_STORMS_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_BOX, SCENE_GROTTOS, 23255, 0x17, "Storms Grotto Chest", "DMT Storms Grotto Chest", RHT_DMT_STORMS_GROTTO_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_TRADE_BROKEN_SWORD] = Location::Base(RC_DMT_TRADE_BROKEN_SWORD, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x23, "Trade Broken Sword", "DMT Trade Broken Sword", RHT_DMT_TRADE_BROKEN_SWORD, RG_PRESCRIPTION, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_TRADE_EYEDROPS] = Location::Base(RC_DMT_TRADE_EYEDROPS, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x26, "Trade Eyedrops", "DMT Trade Eyedrops", RHT_DMT_TRADE_EYEDROPS, RG_CLAIM_CHECK, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_TRADE_CLAIM_CHECK] = Location::Base(RC_DMT_TRADE_CLAIM_CHECK, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_TRAIL, 0x00, 0x57, "Trade Claim Check", "DMT Trade Claim Check", RHT_DMT_TRADE_CLAIM_CHECK, RG_BIGGORON_SWORD, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMT_FREESTANDING_POH] = Location::Collectable(RC_DMT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_TRAIL, 7686, 0x1E, "Freestanding PoH", "DMT Freestanding PoH", RHT_DMT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); // Goron City - locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", "GC Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", "GC Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", "GC Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::InfTable(0x11, 0x06), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::InfTable(0x10, 0x01), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", "GC Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::Chest(0x62, 0x1E), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", "GC Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x25, 0x01), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFB), 0x37, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right", RHT_GC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x25, 0x06), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFB), 0x33, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center", RHT_GC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x25, 0x04), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_MEDIGORON] = Location::Base(RC_GC_MEDIGORON, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x51, "Medigoron", "GC Medigoron", RHT_GC_MEDIGORON, RG_GIANTS_KNIFE, { Category::cMerchant }, SpoilerCollectionCheck::Merchant(0x62, 0x87), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_LEFT_CHEST] = Location::Chest(RC_GC_MAZE_LEFT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23232, 0x00, "Maze Left Chest", "GC Maze Left Chest", RHT_GC_MAZE_LEFT_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_RIGHT_CHEST] = Location::Chest(RC_GC_MAZE_RIGHT_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23201, 0x01, "Maze Right Chest", "GC Maze Right Chest", RHT_GC_MAZE_RIGHT_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MAZE_CENTER_CHEST] = Location::Chest(RC_GC_MAZE_CENTER_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_BOX, SCENE_GORON_CITY, 23202, 0x02, "Maze Center Chest", "GC Maze Center Chest", RHT_GC_MAZE_CENTER_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_ROLLING_GORON_AS_CHILD] = Location::Base(RC_GC_ROLLING_GORON_AS_CHILD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x34, "Rolling Goron as Child", "GC Rolling Goron as Child", RHT_GC_ROLLING_GORON_AS_CHILD, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::InfTable(INFTABLE_11E), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_ROLLING_GORON_AS_ADULT] = Location::Base(RC_GC_ROLLING_GORON_AS_ADULT, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x2C, "Rolling Goron as Adult", "GC Rolling Goron as Adult", RHT_GC_ROLLING_GORON_AS_ADULT, RG_GORON_TUNIC, {}, SpoilerCollectionCheck::InfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_DARUNIAS_JOY] = Location::Base(RC_GC_DARUNIAS_JOY, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x54, "Darunias Joy", "GC Darunias Joy", RHT_GC_DARUNIAS_JOY, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DARUNIAS_JOY), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_POT_FREESTANDING_POH] = Location::Collectable(RC_GC_POT_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_GORON_CITY, ACTOR_EN_ITEM00, SCENE_GORON_CITY, 7942, 0x1F, "Pot Freestanding PoH", "GC Pot Freestanding PoH", RHT_GC_POT_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GORON_CITY, true); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFB), 0x30, "Deku Scrub Grotto Left", "GC Deku Scrub Grotto Left", RHT_GC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFB), 0x37, "Deku Scrub Grotto Right", "GC Deku Scrub Grotto Right", RHT_GC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_GC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_GORON_CITY, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFB), 0x33, "Deku Scrub Grotto Center", "GC Deku Scrub Grotto Center", RHT_GC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_MEDIGORON] = Location::Base(RC_GC_MEDIGORON, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_GORON_CITY, ACTOR_ID_MAX, SCENE_GORON_CITY, 0x00, 0x51, "Medigoron", "GC Medigoron", RHT_GC_MEDIGORON, RG_GIANTS_KNIFE, { Category::cMerchant }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MEDIGORON), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); // Death Mountain Crater - locationTable[RC_DMC_UPPER_GROTTO_CHEST] = Location::Chest(RC_DMC_UPPER_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_GROTTOS, 23802, 0x1A, "Upper Grotto Chest", "DMC Upper Grotto Chest", RHT_DMC_UPPER_GROTTO_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_WALL_FREESTANDING_POH] = Location::Collectable(RC_DMC_WALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 518, 0x02, "Wall Freestanding PoH", "DMC Wall Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_VOLCANO_FREESTANDING_POH] = Location::Collectable(RC_DMC_VOLCANO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 2054, 0x08, "Volcano Freestanding PoH", "DMC Volcano Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_DEKU_SCRUB] = Location::Base(RC_DMC_DEKU_SCRUB, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_DEATH_MOUNTAIN_CRATER, 0x05, 0x37, "Deku Scrub", "DMC Deku Scrub", RHT_DMC_DEKU_SCRUB, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x61, 0x06), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xF9), 0x30, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left", RHT_DMC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x23, 0x01), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xF9), 0x37, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right", RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x23, 0x06), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF9), 0x33, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center", RHT_DMC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x23, 0x04), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_CHEST] = Location::Chest(RC_DMC_UPPER_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_BOX, SCENE_GROTTOS, 23802, 0x1A, "Upper Grotto Chest", "DMC Upper Grotto Chest", RHT_DMC_UPPER_GROTTO_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_WALL_FREESTANDING_POH] = Location::Collectable(RC_DMC_WALL_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 518, 0x02, "Wall Freestanding PoH", "DMC Wall Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_VOLCANO_FREESTANDING_POH] = Location::Collectable(RC_DMC_VOLCANO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_ITEM00, SCENE_DEATH_MOUNTAIN_CRATER, 2054, 0x08, "Volcano Freestanding PoH", "DMC Volcano Freestanding PoH", RHT_DMC_WALL_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_DEKU_SCRUB] = Location::Base(RC_DMC_DEKU_SCRUB, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_DEATH_MOUNTAIN_CRATER, 0x05, 0x37, "Deku Scrub", "DMC Deku Scrub", RHT_DMC_DEKU_SCRUB, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xF9), 0x30, "Deku Scrub Grotto Left", "DMC Deku Scrub Grotto Left", RHT_DMC_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xF9), 0x37, "Deku Scrub Grotto Right", "DMC Deku Scrub Grotto Right", RHT_DMC_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xF9), 0x33, "Deku Scrub Grotto Center", "DMC Deku Scrub Grotto Center", RHT_DMC_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); // Zoras River - locationTable[RC_ZR_OPEN_GROTTO_CHEST] = Location::Chest(RC_ZR_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_GROTTOS, 22985, 0x09, "Open Grotto Chest", "ZR Open Grotto Chest", RHT_ZR_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_MAGIC_BEAN_SALESMAN] = Location::Base(RC_ZR_MAGIC_BEAN_SALESMAN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_ZORAS_RIVER, 0x00, 0x16, "Magic Bean Salesman", "ZR Magic Bean Salesman", RHT_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, {}, SpoilerCollectionCheck::MagicBeans(0x54, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_FROGS_ZELDAS_LULLABY] = Location::Base(RC_ZR_FROGS_ZELDAS_LULLABY, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby", RHT_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD1), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_EPONAS_SONG] = Location::Base(RC_ZR_FROGS_EPONAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Epona's Song", "ZR Frogs Epona's Song", RHT_ZR_FROGS_EPONAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD2), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SARIAS_SONG] = Location::Base(RC_ZR_FROGS_SARIAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Saria's Song", "ZR Frogs Saria's Song", RHT_ZR_FROGS_SARIAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD4), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SUNS_SONG] = Location::Base(RC_ZR_FROGS_SUNS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Sun's Song", "ZR Frogs Sun's Song", RHT_ZR_FROGS_SUNS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD3), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_SONG_OF_TIME] = Location::Base(RC_ZR_FROGS_SONG_OF_TIME, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Song of Time", "ZR Frogs Song of Time", RHT_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD5), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_FROGS_IN_THE_RAIN] = Location::Base(RC_ZR_FROGS_IN_THE_RAIN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs in the Rain", "ZR Frogs in the Rain", RHT_ZR_FROGS_IN_THE_RAIN, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_FROGS_OCARINA_GAME] = Location::Base(RC_ZR_FROGS_OCARINA_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x76, "Frogs Ocarina Game", "ZR Frogs Ocarina Game", RHT_ZR_FROGS_OCARINA_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 1030, 0x04, "Near Open Grotto Freestanding PoH", "ZR Near Open Grotto Freestanding PoH", RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_NEAR_DOMAIN_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 2822, 0x0B, "Near Domain Freestanding PoH", "ZR Near Domain Freestanding PoH", RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); - locationTable[RC_ZR_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEB), 0x39, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear", RHT_ZR_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x15, 0x08), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEB), 0x3A, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front", RHT_ZR_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x15, 0x09), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_OPEN_GROTTO_CHEST] = Location::Chest(RC_ZR_OPEN_GROTTO_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_BOX, SCENE_GROTTOS, 22985, 0x09, "Open Grotto Chest", "ZR Open Grotto Chest", RHT_ZR_OPEN_GROTTO_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_MAGIC_BEAN_SALESMAN] = Location::Base(RC_ZR_MAGIC_BEAN_SALESMAN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_ID_MAX, SCENE_ZORAS_RIVER, 0x00, 0x16, "Magic Bean Salesman", "ZR Magic Bean Salesman", RHT_ZR_MAGIC_BEAN_SALESMAN, RG_MAGIC_BEAN, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_FROGS_ZELDAS_LULLABY] = Location::Base(RC_ZR_FROGS_ZELDAS_LULLABY, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Zelda's Lullaby", "ZR Frogs Zelda's Lullaby", RHT_ZR_FROGS_ZELDAS_LULLABY, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD1), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_EPONAS_SONG] = Location::Base(RC_ZR_FROGS_EPONAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Epona's Song", "ZR Frogs Epona's Song", RHT_ZR_FROGS_EPONAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD2), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SARIAS_SONG] = Location::Base(RC_ZR_FROGS_SARIAS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Saria's Song", "ZR Frogs Saria's Song", RHT_ZR_FROGS_SARIAS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD4), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SUNS_SONG] = Location::Base(RC_ZR_FROGS_SUNS_SONG, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Sun's Song", "ZR Frogs Sun's Song", RHT_ZR_FROGS_SUNS_SONG, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD3), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_SONG_OF_TIME] = Location::Base(RC_ZR_FROGS_SONG_OF_TIME, RCQUEST_BOTH, RCTYPE_FROG_SONG, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs Song of Time", "ZR Frogs Song of Time", RHT_ZR_FROGS_SONG_OF_TIME, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xD5), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_FROGS_IN_THE_RAIN] = Location::Base(RC_ZR_FROGS_IN_THE_RAIN, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x3E, "Frogs in the Rain", "ZR Frogs in the Rain", RHT_ZR_FROGS_IN_THE_RAIN, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_FROGS_OCARINA_GAME] = Location::Base(RC_ZR_FROGS_OCARINA_GAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_FR, SCENE_ZORAS_RIVER, 0x00, 0x76, "Frogs Ocarina Game", "ZR Frogs Ocarina Game", RHT_ZR_FROGS_OCARINA_GAME, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 1030, 0x04, "Near Open Grotto Freestanding PoH", "ZR Near Open Grotto Freestanding PoH", RHT_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_NEAR_DOMAIN_FREESTANDING_POH] = Location::Collectable(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_RIVER, ACTOR_EN_ITEM00, SCENE_ZORAS_RIVER, 2822, 0x0B, "Near Domain Freestanding PoH", "ZR Near Domain Freestanding PoH", RHT_ZR_NEAR_DOMAIN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, true); + locationTable[RC_ZR_DEKU_SCRUB_GROTTO_REAR] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_REAR, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x07, 0xEB), 0x39, "Deku Scrub Grotto Rear", "ZR Deku Scrub Grotto Rear", RHT_ZR_DEKU_SCRUB_GROTTO_REAR, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_DEKU_SCRUB_GROTTO_FRONT] = Location::GrottoScrub(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_ZORAS_RIVER, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x08, 0xEB), 0x3A, "Deku Scrub Grotto Front", "ZR Deku Scrub Grotto Front", RHT_ZR_DEKU_SCRUB_GROTTO_FRONT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); // Zoras Domain - locationTable[RC_ZD_CHEST] = Location::Chest(RC_ZD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_ZORAS_DOMAIN, -18496, 0x00, "Chest", "ZD Chest", RHT_ZD_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_DIVING_MINIGAME] = Location::Base(RC_ZD_DIVING_MINIGAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x37, "Diving Minigame", "ZD Diving Minigame", RHT_ZD_DIVING_MINIGAME, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::EventChkInf(0x38), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_KING_ZORA_THAWED] = Location::Base(RC_ZD_KING_ZORA_THAWED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x2D, "King Zora Thawed", "ZD King Zora Thawed", RHT_ZD_KING_ZORA_THAWED, RG_ZORA_TUNIC, {}, SpoilerCollectionCheck::InfTable(0x13, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZD_TRADE_PRESCRIPTION] = Location::Base(RC_ZD_TRADE_PRESCRIPTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x24, "Trade Prescription", "ZD Trade Prescription", RHT_ZD_TRADE_PRESCRIPTION, RG_EYEBALL_FROG, { Category::cAdultTrade }, SpoilerCollectionCheck::Chest(0x58, 0x1F), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_CHEST] = Location::Chest(RC_ZD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_EN_BOX, SCENE_ZORAS_DOMAIN, -18496, 0x00, "Chest", "ZD Chest", RHT_ZD_CHEST, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_DIVING_MINIGAME] = Location::Base(RC_ZD_DIVING_MINIGAME, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x37, "Diving Minigame", "ZD Diving Minigame", RHT_ZD_DIVING_MINIGAME, RG_PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::EventChkInf(0x38), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_KING_ZORA_THAWED] = Location::Base(RC_ZD_KING_ZORA_THAWED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x2D, "King Zora Thawed", "ZD King Zora Thawed", RHT_ZD_KING_ZORA_THAWED, RG_ZORA_TUNIC, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KING_ZORA_THAWED), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZD_TRADE_PRESCRIPTION] = Location::Base(RC_ZD_TRADE_PRESCRIPTION, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_ZORAS_DOMAIN, ACTOR_ID_MAX, SCENE_ZORAS_DOMAIN, 0x00, 0x24, "Trade Prescription", "ZD Trade Prescription", RHT_ZD_TRADE_PRESCRIPTION, RG_EYEBALL_FROG, { Category::cAdultTrade }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); // Zora's Fountain - locationTable[RC_ZF_ICEBERC_FREESTANDING_POH] = Location::Collectable(RC_ZF_ICEBERC_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 262, 0x01, "Iceberg Freestanding PoH", "ZF Iceberg Freestanding PoH", RHT_ZF_ICEBERG_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_ZF_BOTTOM_FREESTANDING_POH] = Location::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 5126, 0x14, "Bottom Freestanding PoH", "ZF Bottom Freestanding PoH", RHT_ZF_BOTTOM_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZF_ICEBERC_FREESTANDING_POH] = Location::Collectable(RC_ZF_ICEBERC_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 262, 0x01, "Iceberg Freestanding PoH", "ZF Iceberg Freestanding PoH", RHT_ZF_ICEBERG_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_ZF_BOTTOM_FREESTANDING_POH] = Location::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_EN_ITEM00, SCENE_ZORAS_FOUNTAIN, 5126, 0x14, "Bottom Freestanding PoH", "ZF Bottom Freestanding PoH", RHT_ZF_BOTTOM_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); // Lon Lon Ranch - locationTable[RC_LLR_TALONS_CHICKENS] = Location::Base(RC_LLR_TALONS_CHICKENS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_LON_LON_BUILDINGS, 0x00, 0x14, "Talons Chickens", "LLR Talons Chickens", RHT_LLR_TALONS_CHICKENS, RG_BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(10), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_LLR_FREESTANDING_POH] = Location::Collectable(RC_LLR_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_LON_LON_BUILDINGS, 262, 0x01, "Freestanding PoH", "LLR Freestanding PoH", RHT_LLR_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFC), 0x30, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left", RHT_LLR_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x26, 0x01), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFC), 0x37, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right", RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x26, 0x06), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFC), 0x33, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center", RHT_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x26, 0x04), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TALONS_CHICKENS] = Location::Base(RC_LLR_TALONS_CHICKENS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_ID_MAX, SCENE_LON_LON_BUILDINGS, 0x00, 0x14, "Talons Chickens", "LLR Talons Chickens", RHT_LLR_TALONS_CHICKENS, RG_BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(2), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_LLR_FREESTANDING_POH] = Location::Collectable(RC_LLR_FREESTANDING_POH, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_LON_LON_RANCH, ACTOR_EN_ITEM00, SCENE_LON_LON_BUILDINGS, 262, 0x01, "Freestanding PoH", "LLR Freestanding PoH", RHT_LLR_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, true); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_LEFT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x00, 0xFC), 0x30, "Deku Scrub Grotto Left", "LLR Deku Scrub Grotto Left", RHT_LLR_DEKU_SCRUB_GROTTO_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_RIGHT] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x05, 0xFC), 0x37, "Deku Scrub Grotto Right", "LLR Deku Scrub Grotto Right", RHT_LLR_DEKU_SCRUB_GROTTO_RIGHT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_DEKU_SCRUB_GROTTO_CENTER] = Location::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, RCQUEST_BOTH, RCTYPE_SCRUB, RCAREA_LON_LON_RANCH, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03, 0xFC), 0x33, "Deku Scrub Grotto Center", "LLR Deku Scrub Grotto Center", RHT_LLR_DEKU_SCRUB_GROTTO_CENTER, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); // Dungeons - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Deku Tree Vanilla - locationTable[RC_DEKU_TREE_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "Map Chest", "Deku Tree Map Chest", RHT_DEKU_TREE_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2050, 0x02, "Compass Chest", "Deku Tree Compass Chest", RHT_DEKU_TREE_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22790, 0x06, "Compass Room Side Chest", "Deku Tree Compass Room Side Chest", RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22788, 0x04, "Basement Chest", "Deku Tree Basement Chest", RHT_DEKU_TREE_BASEMENT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 161, 0x01, "Slingshot Chest", "Deku Tree Slingshot Chest", RHT_DEKU_TREE_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "Slingshot Room Side Chest", "Deku Tree Slingshot Room Side Chest", RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "Map Chest", "Deku Tree Map Chest", RHT_DEKU_TREE_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2050, 0x02, "Compass Chest", "Deku Tree Compass Chest", RHT_DEKU_TREE_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22790, 0x06, "Compass Room Side Chest", "Deku Tree Compass Room Side Chest", RHT_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22788, 0x04, "Basement Chest", "Deku Tree Basement Chest", RHT_DEKU_TREE_BASEMENT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 161, 0x01, "Slingshot Chest", "Deku Tree Slingshot Chest", RHT_DEKU_TREE_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST] = Location::Chest(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "Slingshot Room Side Chest", "Deku Tree Slingshot Room Side Chest", RHT_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Deku Tree MQ - locationTable[RC_DEKU_TREE_MQ_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "MQ Map Chest", "Deku Tree MQ Map Chest", RHT_DEKU_TREE_MQ_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2049, 0x01, "MQ Compass Chest", "Deku Tree MQ Compass Chest", RHT_DEKU_TREE_MQ_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 4262, 0x06, "MQ Slingshot Chest", "Deku Tree MQ Slingshot Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31454, 0x02, "MQ Slingshot Room Back Chest", "Deku Tree MQ Slingshot Room Back Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31452, 0x04, "MQ Basement Chest", "Deku Tree MQ Basement Chest", RHT_DEKU_TREE_MQ_BASEMENT_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "MQ Before Spinning Log Chest", "Deku Tree MQ Before Spinning Log Chest", RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 23200, 0x00, "MQ After Spinning Log Chest", "Deku Tree MQ After Spinning Log Chest", RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_DEKU_SCRUB] = Location::Base(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_DEKU_TREE, 0x04, 0x34, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub", RHT_DEKU_TREE_MQ_DEKU_SCRUB, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x00, 0x05), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_MAP_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2083, 0x03, "MQ Map Chest", "Deku Tree MQ Map Chest", RHT_DEKU_TREE_MQ_MAP_CHEST, RG_DEKU_TREE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_COMPASS_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 2049, 0x01, "MQ Compass Chest", "Deku Tree MQ Compass Chest", RHT_DEKU_TREE_MQ_COMPASS_CHEST, RG_DEKU_TREE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 4262, 0x06, "MQ Slingshot Chest", "Deku Tree MQ Slingshot Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_CHEST, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31454, 0x02, "MQ Slingshot Room Back Chest", "Deku Tree MQ Slingshot Room Back Chest", RHT_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_BASEMENT_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, -31452, 0x04, "MQ Basement Chest", "Deku Tree MQ Basement Chest", RHT_DEKU_TREE_MQ_BASEMENT_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 22789, 0x05, "MQ Before Spinning Log Chest", "Deku Tree MQ Before Spinning Log Chest", RHT_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST] = Location::Chest(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DEKU_TREE, ACTOR_EN_BOX, SCENE_DEKU_TREE, 23200, 0x00, "MQ After Spinning Log Chest", "Deku Tree MQ After Spinning Log Chest", RHT_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_DEKU_SCRUB] = Location::Base(RC_DEKU_TREE_MQ_DEKU_SCRUB, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DEKU_TREE, ACTOR_EN_DNS, SCENE_DEKU_TREE, 0x04, 0x34, "MQ Deku Scrub", "Deku Tree MQ Deku Scrub", RHT_DEKU_TREE_MQ_DEKU_SCRUB, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DEKU_TREE_MQ_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Dodongo's Cavern Shared - locationTable[RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN_BOSS, 20512, 0x00, "Boss Room Chest", "Dodongos Cavern Boss Room Chest", RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN_BOSS, 20512, 0x00, "Boss Room Chest", "Dodongos Cavern Boss Room Chest", RHT_DODONGOS_CAVERN_BOSS_ROOM_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Dodongo's Cavern Vanilla - locationTable[RC_DODONGOS_CAVERN_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2088, 0x08, "Map Chest", "Dodongos Cavern Map Chest", RHT_DODONGOS_CAVERN_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2053, 0x05, "Compass Chest", "Dodongos Cavern Compass Chest", RHT_DODONGOS_CAVERN_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22982, 0x06, "Bomb Flower Platform Chest", "Dodongos Cavern Bomb Flower Platform Chest", RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "Bomb Bag Chest", "Dodongos Cavern Bomb Bag Chest", RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21802, 0x0A, "End Of Bridge Chest", "Dodongos Cavern End Of Bridge Chest", RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x00, 0x30, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x01), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos", RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x02), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby", RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x05), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2088, 0x08, "Map Chest", "Dodongos Cavern Map Chest", RHT_DODONGOS_CAVERN_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2053, 0x05, "Compass Chest", "Dodongos Cavern Compass Chest", RHT_DODONGOS_CAVERN_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22982, 0x06, "Bomb Flower Platform Chest", "Dodongos Cavern Bomb Flower Platform Chest", RHT_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "Bomb Bag Chest", "Dodongos Cavern Bomb Bag Chest", RHT_DODONGOS_CAVERN_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21802, 0x0A, "End Of Bridge Chest", "Dodongos Cavern End Of Bridge Chest", RHT_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x00, 0x30, "Deku Scrub Near Bomb Bag Left", "Dodongos Cavern Deku Scrub Near Bomb Bag Left", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "Deku Scrub Side Room Near Dodongos", "Dodongos Cavern Deku Scrub Side Room Near Dodongos", RHT_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "Deku Scrub Near Bomb Bag Right", "Dodongos Cavern Deku Scrub Near Bomb Bag Right", RHT_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY] = Location::Base(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "Deku Scrub Lobby", "Dodongos Cavern Deku Scrub Lobby", RHT_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); // Dodongo's Cavern MQ - locationTable[RC_DODONGOS_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2080, 0x00, "MQ Map Chest", "Dodongos Cavern MQ Map Chest", RHT_DODONGOS_CAVERN_MQ_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "MQ Bomb Bag Chest", "Dodongos Cavern MQ Bomb Bag Chest", RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 6149, 0x05, "MQ Compass Chest", "Dodongos Cavern MQ Compass Chest", RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 29986, 0x02, "MQ Larvae Room Chest", "Dodongos Cavern MQ Larvae Room Chest", RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22947, 0x03, "MQ Torch Puzzle Room Chest", "Dodongos Cavern MQ Torch Puzzle Room Chest", RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21825, 0x01, "MQ Under Grave Chest", "Dodongos Cavern MQ Under Grave Chest", RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "MQ Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x02), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "MQ Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "MQ Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x05), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x07, 0x39, "MQ Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x01, 0x08), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 2080, 0x00, "MQ Map Chest", "Dodongos Cavern MQ Map Chest", RHT_DODONGOS_CAVERN_MQ_MAP_CHEST, RG_DODONGOS_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 1604, 0x04, "MQ Bomb Bag Chest", "Dodongos Cavern MQ Bomb Bag Chest", RHT_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, RG_PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 6149, 0x05, "MQ Compass Chest", "Dodongos Cavern MQ Compass Chest", RHT_DODONGOS_CAVERN_MQ_COMPASS_CHEST, RG_DODONGOS_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 29986, 0x02, "MQ Larvae Room Chest", "Dodongos Cavern MQ Larvae Room Chest", RHT_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 22947, 0x03, "MQ Torch Puzzle Room Chest", "Dodongos Cavern MQ Torch Puzzle Room Chest", RHT_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST] = Location::Chest(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_DODONGOS_CAVERN, ACTOR_EN_BOX, SCENE_DODONGOS_CAVERN, 21825, 0x01, "MQ Under Grave Chest", "Dodongos Cavern MQ Under Grave Chest", RHT_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x01, 0x31, "MQ Deku Scrub Lobby Rear", "Dodongos Cavern Deku Scrub Lobby Rear", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, RG_BUY_DEKU_STICK_1, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x03, 0x33, "MQ Deku Scrub Lobby Front", "Dodongos Cavern Deku Scrub Lobby Front", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, RG_BUY_DEKU_SEEDS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x04, 0x34, "MQ Deku Scrub Staircase", "Dodongos Cavern Deku Scrub Staircase", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, RG_BUY_DEKU_SHIELD, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::Base(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_DODONGOS_CAVERN, ACTOR_EN_DNS, SCENE_DODONGOS_CAVERN, 0x07, 0x39, "MQ Deku Scrub Side Room Near Lower Lizalfos", "Dodongos Cavern Deku Scrub Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Jabu-Jabu's Belly Vanilla - locationTable[RC_JABU_JABUS_BELLY_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 6178, 0x02, "Map Chest", "Jabu Jabus Belly Map Chest", RHT_JABU_JABUS_BELLY_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18428, 0x04, "Compass Chest", "Jabu Jabus Belly Compass Chest", RHT_JABU_JABUS_BELLY_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4289, 0x01, "Boomerang Chest", "Jabu Jabus Belly Boomerang Chest", RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_DEKU_SCRUB] = Location::Base(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_JABU_JABU, 0x00, 0x30, "Deku Scrub", "Jabu Jabus Belly Deku Scrub", RHT_JABU_JABUS_BELLY_DEKU_SCRUB, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x02, 0x01), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 6178, 0x02, "Map Chest", "Jabu Jabus Belly Map Chest", RHT_JABU_JABUS_BELLY_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18428, 0x04, "Compass Chest", "Jabu Jabus Belly Compass Chest", RHT_JABU_JABUS_BELLY_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4289, 0x01, "Boomerang Chest", "Jabu Jabus Belly Boomerang Chest", RHT_JABU_JABUS_BELLY_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_DEKU_SCRUB] = Location::Base(RC_JABU_JABUS_BELLY_DEKU_SCRUB, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_DNS, SCENE_JABU_JABU, 0x00, 0x30, "Deku Scrub", "Jabu Jabus Belly Deku Scrub", RHT_JABU_JABUS_BELLY_DEKU_SCRUB, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); // Jabu-Jabu's Belly MQ - locationTable[RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32699, 0x05, "MQ First Room Side Chest", "Jabu Jabus Belly MQ First Room Side Chest", RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18397, 0x03, "MQ Map Chest", "Jabu Jabus Belly MQ Map Chest", RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20546, 0x02, "MQ Second Room Lower Chest", "Jabu Jabus Belly MQ Second Room Lower Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18432, 0x00, "MQ Compass Chest", "Jabu Jabus Belly MQ Compass Chest", RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -30457, 0x07, "MQ Second Room Upper Chest", "Jabu Jabus Belly MQ Second Room Upper Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32696, 0x08, "MQ Basement Near Switches Chest", "Jabu Jabus Belly MQ Basement Near Switches Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32668, 0x04, "MQ Basement Near Vines Chest", "Jabu Jabus Belly MQ Basement Near Vines Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -31446, 0x0A, "MQ Near Boss Chest", "Jabu Jabus Belly MQ Near Boss Chest", RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 28905, 0x09, "MQ Falling Like Like Room Chest", "Jabu Jabus Belly MQ Falling Like Like Room Chest", RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RG_DEKU_STICK_1, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20545, 0x01, "MQ Boomerang Room Small Chest", "Jabu Jabus Belly MQ Boomerang Room Small Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4294, 0x06, "MQ Boomerang Chest", "Jabu Jabus Belly MQ Boomerang Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32699, 0x05, "MQ First Room Side Chest", "Jabu Jabus Belly MQ First Room Side Chest", RHT_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_MAP_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18397, 0x03, "MQ Map Chest", "Jabu Jabus Belly MQ Map Chest", RHT_JABU_JABUS_BELLY_MQ_MAP_CHEST, RG_JABU_JABUS_BELLY_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20546, 0x02, "MQ Second Room Lower Chest", "Jabu Jabus Belly MQ Second Room Lower Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -18432, 0x00, "MQ Compass Chest", "Jabu Jabus Belly MQ Compass Chest", RHT_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, RG_JABU_JABUS_BELLY_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -30457, 0x07, "MQ Second Room Upper Chest", "Jabu Jabus Belly MQ Second Room Upper Chest", RHT_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32696, 0x08, "MQ Basement Near Switches Chest", "Jabu Jabus Belly MQ Basement Near Switches Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -32668, 0x04, "MQ Basement Near Vines Chest", "Jabu Jabus Belly MQ Basement Near Vines Chest", RHT_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, -31446, 0x0A, "MQ Near Boss Chest", "Jabu Jabus Belly MQ Near Boss Chest", RHT_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 28905, 0x09, "MQ Falling Like Like Room Chest", "Jabu Jabus Belly MQ Falling Like Like Room Chest", RHT_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, RG_DEKU_STICK_1, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 20545, 0x01, "MQ Boomerang Room Small Chest", "Jabu Jabus Belly MQ Boomerang Room Small Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST] = Location::Chest(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_BOX, SCENE_JABU_JABU, 4294, 0x06, "MQ Boomerang Chest", "Jabu Jabus Belly MQ Boomerang Chest", RHT_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, RG_BOOMERANG, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Forest Temple Vanilla - locationTable[RC_FOREST_TEMPLE_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22595, 0x03, "First Room Chest", "Forest Temple First Room Chest", RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "First Stalfos Chest", "Forest Temple First Stalfos Chest", RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22789, 0x05, "Raised Island Courtyard Chest", "Forest Temple Raised Island Courtyard Chest", RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6177, 0x01, "Map Chest", "Forest Temple Map Chest", RHT_FOREST_TEMPLE_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_WELL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "Well Chest", "Forest Temple Well Chest", RHT_FOREST_TEMPLE_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22855, 0x07, "Falling Ceiling Room Chest", "Forest Temple Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_EYE_SWITCH_CHEST] = Location::Chest(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30364, 0x04, "Eye Switch Chest", "Forest Temple Eye Switch Chest", RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "Boss Key Chest", "Forest Temple Boss Key Chest", RHT_FOREST_TEMPLE_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_FLOORMASTER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "Floormaster Chest", "Forest Temple Floormaster Chest", RHT_FOREST_TEMPLE_FLOORMASTER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "Bow Chest", "Forest Temple Bow Chest", RHT_FOREST_TEMPLE_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_RED_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RED_POE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30797, 0x0D, "Red Poe Chest", "Forest Temple Red Poe Chest", RHT_FOREST_TEMPLE_RED_POE_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BLUE_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BLUE_POE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "Blue Poe Chest", "Forest Temple Blue Poe Chest", RHT_FOREST_TEMPLE_BLUE_POE_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "Basement Chest", "Forest Temple Basement Chest", RHT_FOREST_TEMPLE_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22595, 0x03, "First Room Chest", "Forest Temple First Room Chest", RHT_FOREST_TEMPLE_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "First Stalfos Chest", "Forest Temple First Stalfos Chest", RHT_FOREST_TEMPLE_FIRST_STALFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22789, 0x05, "Raised Island Courtyard Chest", "Forest Temple Raised Island Courtyard Chest", RHT_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6177, 0x01, "Map Chest", "Forest Temple Map Chest", RHT_FOREST_TEMPLE_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_WELL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "Well Chest", "Forest Temple Well Chest", RHT_FOREST_TEMPLE_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22855, 0x07, "Falling Ceiling Room Chest", "Forest Temple Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_EYE_SWITCH_CHEST] = Location::Chest(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30364, 0x04, "Eye Switch Chest", "Forest Temple Eye Switch Chest", RHT_FOREST_TEMPLE_EYE_SWITCH_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "Boss Key Chest", "Forest Temple Boss Key Chest", RHT_FOREST_TEMPLE_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_FLOORMASTER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "Floormaster Chest", "Forest Temple Floormaster Chest", RHT_FOREST_TEMPLE_FLOORMASTER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BOW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "Bow Chest", "Forest Temple Bow Chest", RHT_FOREST_TEMPLE_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_RED_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_RED_POE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30797, 0x0D, "Red Poe Chest", "Forest Temple Red Poe Chest", RHT_FOREST_TEMPLE_RED_POE_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BLUE_POE_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BLUE_POE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "Blue Poe Chest", "Forest Temple Blue Poe Chest", RHT_FOREST_TEMPLE_BLUE_POE_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_BASEMENT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "Basement Chest", "Forest Temple Basement Chest", RHT_FOREST_TEMPLE_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); // Forest Temple MQ - locationTable[RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30653, 0x03, "MQ First Room Chest", "Forest Temple MQ First Room Chest", RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "MQ Wolfos Chest", "Forest Temple MQ Wolfos Chest", RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOW_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "MQ Bow Chest", "Forest Temple MQ Bow Chest", RHT_FOREST_TEMPLE_MQ_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22593, 0x01, "MQ Raised Island Courtyard Lower Chest", "Forest Temple MQ Raised Island Courtyard Lower Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22597, 0x05, "MQ Raised Island Courtyard Upper Chest", "Forest Temple MQ Raised Island Courtyard Upper Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WELL_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "MQ Well Chest", "Forest Temple MQ Well Chest", RHT_FOREST_TEMPLE_MQ_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6189, 0x0D, "MQ Map Chest", "Forest Temple MQ Map Chest", RHT_FOREST_TEMPLE_MQ_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "MQ Compass Chest", "Forest Temple MQ Compass Chest", RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30426, 0x06, "MQ Falling Ceiling Room Chest", "Forest Temple MQ Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "MQ Basement Chest", "Forest Temple MQ Basement Chest", RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_REDEAD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "MQ Redead Chest", "Forest Temple MQ Redead Chest", RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "MQ Boss Key Chest", "Forest Temple MQ Boss Key Chest", RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30653, 0x03, "MQ First Room Chest", "Forest Temple MQ First Room Chest", RHT_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30784, 0x00, "MQ Wolfos Chest", "Forest Temple MQ Wolfos Chest", RHT_FOREST_TEMPLE_MQ_WOLFOS_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_BOW_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOW_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -20340, 0x0C, "MQ Bow Chest", "Forest Temple MQ Bow Chest", RHT_FOREST_TEMPLE_MQ_BOW_CHEST, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22593, 0x01, "MQ Raised Island Courtyard Lower Chest", "Forest Temple MQ Raised Island Courtyard Lower Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22597, 0x05, "MQ Raised Island Courtyard Upper Chest", "Forest Temple MQ Raised Island Courtyard Upper Chest", RHT_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_WELL_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_WELL_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22601, 0x09, "MQ Well Chest", "Forest Temple MQ Well Chest", RHT_FOREST_TEMPLE_MQ_WELL_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6189, 0x0D, "MQ Map Chest", "Forest Temple MQ Map Chest", RHT_FOREST_TEMPLE_MQ_MAP_CHEST, RG_FOREST_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 6159, 0x0F, "MQ Compass Chest", "Forest Temple MQ Compass Chest", RHT_FOREST_TEMPLE_MQ_COMPASS_CHEST, RG_FOREST_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, -30426, 0x06, "MQ Falling Ceiling Room Chest", "Forest Temple MQ Falling Ceiling Room Chest", RHT_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 22827, 0x0B, "MQ Basement Chest", "Forest Temple MQ Basement Chest", RHT_FOREST_TEMPLE_MQ_BASEMENT_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_REDEAD_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 30786, 0x02, "MQ Redead Chest", "Forest Temple MQ Redead Chest", RHT_FOREST_TEMPLE_MQ_REDEAD_CHEST, RG_FOREST_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FOREST_TEMPLE, ACTOR_EN_BOX, SCENE_FOREST_TEMPLE, 10222, 0x0E, "MQ Boss Key Chest", "Forest Temple MQ Boss Key Chest", RHT_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FOREST_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Fire Temple Vanilla - locationTable[RC_FIRE_TEMPLE_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "Near Boss Chest", "Fire Temple Near Boss Chest", RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_FLARE_DANCER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 31936, 0x00, "Flare Dancer Chest", "Fire Temple Flare Dancer Chest", RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10220, 0x0C, "Boss Key Chest", "Fire Temple Boss Key Chest", RHT_FIRE_TEMPLE_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22594, 0x02, "Big Lava Room Blocked Door Chest", "Fire Temple Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22596, 0x04, "Big Lava Room Lower Open Door Chest", "Fire Temple Big Lava Room Lower Open Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22595, 0x03, "Boulder Maze Lower Chest", "Fire Temple Boulder Maze Lower Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22598, 0x06, "Boulder Maze Upper Chest", "Fire Temple Boulder Maze Upper Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "Boulder Maze Side Room Chest", "Fire Temple Boulder Maze Side Room Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22603, 0x0B, "Boulder Maze Shortcut Chest", "Fire Temple Boulder Maze Shortcut Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_SCARECROW_CHEST] = Location::Chest(RC_FIRE_TEMPLE_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23245, 0x0D, "Scarecrow Chest", "Fire Temple Scarecrow Chest", RHT_FIRE_TEMPLE_SCARECROW_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2090, 0x0A, "Map Chest", "Fire Temple Map Chest", RHT_FIRE_TEMPLE_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2055, 0x07, "Compass Chest", "Fire Temple Compass Chest", RHT_FIRE_TEMPLE_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = Location::Chest(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22601, 0x09, "Highest Goron Chest", "Fire Temple Highest Goron Chest", RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 421, 0x05, "Megaton Hammer Chest", "Fire Temple Megaton Hammer Chest", RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "Near Boss Chest", "Fire Temple Near Boss Chest", RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_FLARE_DANCER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 31936, 0x00, "Flare Dancer Chest", "Fire Temple Flare Dancer Chest", RHT_FIRE_TEMPLE_FLARE_DANCER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10220, 0x0C, "Boss Key Chest", "Fire Temple Boss Key Chest", RHT_FIRE_TEMPLE_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22594, 0x02, "Big Lava Room Blocked Door Chest", "Fire Temple Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22596, 0x04, "Big Lava Room Lower Open Door Chest", "Fire Temple Big Lava Room Lower Open Door Chest", RHT_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22595, 0x03, "Boulder Maze Lower Chest", "Fire Temple Boulder Maze Lower Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22598, 0x06, "Boulder Maze Upper Chest", "Fire Temple Boulder Maze Upper Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "Boulder Maze Side Room Chest", "Fire Temple Boulder Maze Side Room Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST] = Location::Chest(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22603, 0x0B, "Boulder Maze Shortcut Chest", "Fire Temple Boulder Maze Shortcut Chest", RHT_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_SCARECROW_CHEST] = Location::Chest(RC_FIRE_TEMPLE_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23245, 0x0D, "Scarecrow Chest", "Fire Temple Scarecrow Chest", RHT_FIRE_TEMPLE_SCARECROW_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2090, 0x0A, "Map Chest", "Fire Temple Map Chest", RHT_FIRE_TEMPLE_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2055, 0x07, "Compass Chest", "Fire Temple Compass Chest", RHT_FIRE_TEMPLE_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST] = Location::Chest(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22601, 0x09, "Highest Goron Chest", "Fire Temple Highest Goron Chest", RHT_FIRE_TEMPLE_HIGHEST_GORON_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 421, 0x05, "Megaton Hammer Chest", "Fire Temple Megaton Hammer Chest", RHT_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); // Fire Temple MQ - locationTable[RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22599, 0x07, "MQ Near Boss Chest", "Fire Temple MQ Near Boss Chest", RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 4512, 0x00, "MQ Megaton Hammer Chest", "Fire Temple MQ Megaton Hammer Chest", RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2059, 0x0B, "MQ Compass Chest", "Fire Temple MQ Compass Chest", RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23747, 0x03, "MQ Lizalfos Maze Lower Chest", "Fire Temple MQ Lizalfos Maze Lower Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23782, 0x06, "MQ Lizalfos Maze Upper Chest", "Fire Temple MQ Lizalfos Maze Upper Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = Location::Chest(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22597, 0x05, "MQ Chest on Fire", "Fire Temple MQ Chest on Fire", RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 30018, 0x02, "MQ Map Room Side Chest", "Fire Temple MQ Map Room Side Chest", RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2092, 0x0C, "MQ Map Chest", "Fire Temple MQ Map Chest", RHT_FIRE_TEMPLE_MQ_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10212, 0x04, "MQ Boss Key Chest", "Fire Temple MQ Boss Key Chest", RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "MQ Big Lava Room Blocked Door Chest", "Fire Temple MQ Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "MQ Lizalfos Maze Side Room Chest", "Fire Temple MQ Lizalfos Maze Side Room Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_ITEM00, SCENE_FIRE_TEMPLE, 7185, 0x1C, "MQ Freestanding Key", "Fire Temple MQ Freestanding Key", RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22599, 0x07, "MQ Near Boss Chest", "Fire Temple MQ Near Boss Chest", RHT_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 4512, 0x00, "MQ Megaton Hammer Chest", "Fire Temple MQ Megaton Hammer Chest", RHT_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, RG_MEGATON_HAMMER, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2059, 0x0B, "MQ Compass Chest", "Fire Temple MQ Compass Chest", RHT_FIRE_TEMPLE_MQ_COMPASS_CHEST, RG_FIRE_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23747, 0x03, "MQ Lizalfos Maze Lower Chest", "Fire Temple MQ Lizalfos Maze Lower Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 23782, 0x06, "MQ Lizalfos Maze Upper Chest", "Fire Temple MQ Lizalfos Maze Upper Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE] = Location::Chest(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22597, 0x05, "MQ Chest on Fire", "Fire Temple MQ Chest on Fire", RHT_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 30018, 0x02, "MQ Map Room Side Chest", "Fire Temple MQ Map Room Side Chest", RHT_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 2092, 0x0C, "MQ Map Chest", "Fire Temple MQ Map Chest", RHT_FIRE_TEMPLE_MQ_MAP_CHEST, RG_FIRE_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 10212, 0x04, "MQ Boss Key Chest", "Fire Temple MQ Boss Key Chest", RHT_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, RG_FIRE_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22593, 0x01, "MQ Big Lava Room Blocked Door Chest", "Fire Temple MQ Big Lava Room Blocked Door Chest", RHT_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST] = Location::Chest(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_BOX, SCENE_FIRE_TEMPLE, 22600, 0x08, "MQ Lizalfos Maze Side Room Chest", "Fire Temple MQ Lizalfos Maze Side Room Chest", RHT_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_FIRE_TEMPLE, ACTOR_EN_ITEM00, SCENE_FIRE_TEMPLE, 7185, 0x1C, "MQ Freestanding Key", "Fire Temple MQ Freestanding Key", RHT_FIRE_TEMPLE_MQ_FREESTANDING_KEY, RG_FIRE_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Randomizer Get Categories Collection Check Group Vanilla Progression // Water Temple Vanilla - locationTable[RC_WATER_TEMPLE_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6178, 0x02, "Map Chest", "Water Temple Map Chest", RHT_WATER_TEMPLE_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 2057, 0x09, "Compass Chest", "Water Temple Compass Chest", RHT_WATER_TEMPLE_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_TORCHES_CHEST] = Location::Chest(RC_WATER_TEMPLE_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 30785, 0x01, "Torches Chest", "Water Temple Torches Chest", RHT_WATER_TEMPLE_TORCHES_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_DRAGON_CHEST] = Location::Chest(RC_WATER_TEMPLE_DRAGON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22602, 0x0A, "Dragon Chest", "Water Temple Dragon Chest", RHT_WATER_TEMPLE_DRAGON_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22600, 0x08, "Central Bow Target Chest", "Water Temple Central Bow Target Chest", RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22598, 0x06, "Central Pillar Chest", "Water Temple Central Pillar Chest", RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_CRACKED_WALL_CHEST] = Location::Chest(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22592, 0x00, "Cracked Wall Chest", "Water Temple Cracked Wall Chest", RHT_WATER_TEMPLE_CRACKED_WALL_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "Boss Key Chest", "Water Temple Boss Key Chest", RHT_WATER_TEMPLE_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_LONGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 295, 0x07, "Longshot Chest", "Water Temple Longshot Chest", RHT_WATER_TEMPLE_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_RIVER_CHEST] = Location::Chest(RC_WATER_TEMPLE_RIVER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22595, 0x03, "River Chest", "Water Temple River Chest", RHT_WATER_TEMPLE_RIVER_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6178, 0x02, "Map Chest", "Water Temple Map Chest", RHT_WATER_TEMPLE_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 2057, 0x09, "Compass Chest", "Water Temple Compass Chest", RHT_WATER_TEMPLE_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_TORCHES_CHEST] = Location::Chest(RC_WATER_TEMPLE_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 30785, 0x01, "Torches Chest", "Water Temple Torches Chest", RHT_WATER_TEMPLE_TORCHES_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_DRAGON_CHEST] = Location::Chest(RC_WATER_TEMPLE_DRAGON_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22602, 0x0A, "Dragon Chest", "Water Temple Dragon Chest", RHT_WATER_TEMPLE_DRAGON_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22600, 0x08, "Central Bow Target Chest", "Water Temple Central Bow Target Chest", RHT_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22598, 0x06, "Central Pillar Chest", "Water Temple Central Pillar Chest", RHT_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_CRACKED_WALL_CHEST] = Location::Chest(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22592, 0x00, "Cracked Wall Chest", "Water Temple Cracked Wall Chest", RHT_WATER_TEMPLE_CRACKED_WALL_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "Boss Key Chest", "Water Temple Boss Key Chest", RHT_WATER_TEMPLE_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_LONGSHOT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 295, 0x07, "Longshot Chest", "Water Temple Longshot Chest", RHT_WATER_TEMPLE_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_RIVER_CHEST] = Location::Chest(RC_WATER_TEMPLE_RIVER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 22595, 0x03, "River Chest", "Water Temple River Chest", RHT_WATER_TEMPLE_RIVER_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); // Water Temple MQ - locationTable[RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -30650, 0x06, "MQ Central Pillar Chest", "Water Temple MQ Central Pillar Chest", RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Water Temple MQ Boss Key Chest", RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -20192, 0x00, "MQ Longshot Chest", "Water Temple MQ Longshot Chest", RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Water Temple MQ Compass Chest", RHT_WATER_TEMPLE_MQ_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -18398, 0x02, "MQ Map Chest", "Water Temple MQ Map Chest", RHT_WATER_TEMPLE_MQ_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_ITEM00, SCENE_WATER_TEMPLE, 273, 0x01, "MQ Freestanding Key", "Water Temple MQ Freestanding Key", RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -30650, 0x06, "MQ Central Pillar Chest", "Water Temple MQ Central Pillar Chest", RHT_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Water Temple MQ Boss Key Chest", RHT_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, RG_WATER_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -20192, 0x00, "MQ Longshot Chest", "Water Temple MQ Longshot Chest", RHT_WATER_TEMPLE_MQ_LONGSHOT_CHEST, RG_PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Water Temple MQ Compass Chest", RHT_WATER_TEMPLE_MQ_COMPASS_CHEST, RG_WATER_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_WATER_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_WATER_TEMPLE, ACTOR_EN_BOX, SCENE_WATER_TEMPLE, -18398, 0x02, "MQ Map Chest", "Water Temple MQ Map Chest", RHT_WATER_TEMPLE_MQ_MAP_CHEST, RG_WATER_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_WATER_TEMPLE, ACTOR_EN_ITEM00, SCENE_WATER_TEMPLE, 273, 0x01, "MQ Freestanding Key", "Water Temple MQ Freestanding Key", RHT_WATER_TEMPLE_MQ_FREESTANDING_KEY, RG_WATER_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Spirit Temple Shared - locationTable[RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 1707, 0x0B, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest", RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 13673, 0x09, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest", RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RG_MIRROR_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 1707, 0x0B, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest", RHT_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_DESERT_COLOSSUS, 13673, 0x09, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest", RHT_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RG_MIRROR_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Spirit Temple Vanilla - locationTable[RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 21800, 0x08, "Child Bridge Chest", "Spirit Temple Child Bridge Chest", RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30656, 0x00, "Child Early Torches Chest", "Spirit Temple Child Early Torches Chest", RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 14340, 0x04, "Compass Chest", "Spirit Temple Compass Chest", RHT_SPIRIT_TEMPLE_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22599, 0x07, "Early Adult Right Chest", "Spirit Temple Early Adult Right Chest", RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30451, 0x0D, "First Mirror Left Chest", "Spirit Temple First Mirror Left Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -28786, 0x0E, "First Mirror Right Chest", "Spirit Temple First Mirror Right Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18397, 0x03, "Map Chest", "Spirit Temple Map Chest", RHT_SPIRIT_TEMPLE_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32666, 0x06, "Child Climb North Chest", "Spirit Temple Child Climb North Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -31444, 0x0C, "Child Climb East Chest", "Spirit Temple Child Climb East Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30655, 0x01, "Sun Block Room Chest", "Spirit Temple Sun Block Room Chest", RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30654, 0x02, "Statue Room Hand Chest", "Spirit Temple Statue Room Hand Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "Statue Room Northeast Chest", "Spirit Temple Statue Room Northeast Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22597, 0x05, "Near Four Armos Chest", "Spirit Temple Near Four Armos Chest", RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26900, 0x14, "Hallway Right Invisible Chest", "Spirit Temple Hallway Right Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26901, 0x15, "Hallway Left Invisible Chest", "Spirit Temple Hallway Left Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10218, 0x0A, "Boss Key Chest", "Spirit Temple Boss Key Chest", RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_TOPMOST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -29454, 0x12, "Topmost Chest", "Spirit Temple Topmost Chest", RHT_SPIRIT_TEMPLE_TOPMOST_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 21800, 0x08, "Child Bridge Chest", "Spirit Temple Child Bridge Chest", RHT_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30656, 0x00, "Child Early Torches Chest", "Spirit Temple Child Early Torches Chest", RHT_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 14340, 0x04, "Compass Chest", "Spirit Temple Compass Chest", RHT_SPIRIT_TEMPLE_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22599, 0x07, "Early Adult Right Chest", "Spirit Temple Early Adult Right Chest", RHT_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30451, 0x0D, "First Mirror Left Chest", "Spirit Temple First Mirror Left Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -28786, 0x0E, "First Mirror Right Chest", "Spirit Temple First Mirror Right Chest", RHT_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18397, 0x03, "Map Chest", "Spirit Temple Map Chest", RHT_SPIRIT_TEMPLE_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32666, 0x06, "Child Climb North Chest", "Spirit Temple Child Climb North Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -31444, 0x0C, "Child Climb East Chest", "Spirit Temple Child Climb East Chest", RHT_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30655, 0x01, "Sun Block Room Chest", "Spirit Temple Sun Block Room Chest", RHT_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30654, 0x02, "Statue Room Hand Chest", "Spirit Temple Statue Room Hand Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "Statue Room Northeast Chest", "Spirit Temple Statue Room Northeast Chest", RHT_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 22597, 0x05, "Near Four Armos Chest", "Spirit Temple Near Four Armos Chest", RHT_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26900, 0x14, "Hallway Right Invisible Chest", "Spirit Temple Hallway Right Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26901, 0x15, "Hallway Left Invisible Chest", "Spirit Temple Hallway Left Invisible Chest", RHT_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10218, 0x0A, "Boss Key Chest", "Spirit Temple Boss Key Chest", RHT_SPIRIT_TEMPLE_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_TOPMOST_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -29454, 0x12, "Topmost Chest", "Spirit Temple Topmost Chest", RHT_SPIRIT_TEMPLE_TOPMOST_CHEST, RG_BOMBS_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); // Spirit Temple MQ - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 20602, 0x1A, "MQ Entrance Front Left Chest", "Spirit Temple MQ Entrance Front Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32641, 0x1F, "MQ Entrance Back Right Chest", "Spirit Temple MQ Entrance Back Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30629, 0x1B, "MQ Entrance Front Right Chest", "Spirit Temple MQ Entrance Front Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30626, 0x1E, "MQ Entrance Back Left Chest", "Spirit Temple MQ Entrance Back Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30627, 0x1D, "MQ Child Hammer Switch Chest", "Spirit Temple MQ Child Hammer Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 2080, 0x00, "MQ Map Chest", "Spirit Temple MQ Map Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 30792, 0x08, "MQ Map Room Enemy Chest", "Spirit Temple MQ Map Room Enemy Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 28774, 0x06, "MQ Child Climb North Chest", "Spirit Temple MQ Child Climb North Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30644, 0x0C, "MQ Child Climb South Chest", "Spirit Temple MQ Child Climb South Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18429, 0x03, "MQ Compass Chest", "Spirit Temple MQ Compass Chest", RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "MQ Statue Room Lullaby Chest", "Spirit Temple MQ Statue Room Lullaby Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26882, 0x02, "MQ Statue Room Invisible Chest", "Spirit Temple MQ Statue Room Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30628, 0x1C, "MQ Silver Block Hallway Chest", "Spirit Temple MQ Silver Block Hallway Chest", RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30463, 0x01, "MQ Sun Block Room Chest", "Spirit Temple MQ Sun Block Room Chest", RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 23207, 0x07, "MQ Symphony Room Chest", "Spirit Temple MQ Symphony Room Chest", RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31396, 0x04, "MQ Leever Room Chest", "Spirit Temple MQ Leever Room Chest", RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 24472, 0x19, "MQ Beamos Room Chest", "Spirit Temple MQ Beamos Room Chest", RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31097, 0x18, "MQ Chest Switch Chest", "Spirit Temple MQ Chest Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Spirit Temple MQ Boss Key Chest", RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26706, 0x12, "MQ Mirror Puzzle Invisible Chest", "Spirit Temple MQ Mirror Puzzle Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 20602, 0x1A, "MQ Entrance Front Left Chest", "Spirit Temple MQ Entrance Front Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -32641, 0x1F, "MQ Entrance Back Right Chest", "Spirit Temple MQ Entrance Back Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30629, 0x1B, "MQ Entrance Front Right Chest", "Spirit Temple MQ Entrance Front Right Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30626, 0x1E, "MQ Entrance Back Left Chest", "Spirit Temple MQ Entrance Back Left Chest", RHT_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30627, 0x1D, "MQ Child Hammer Switch Chest", "Spirit Temple MQ Child Hammer Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 2080, 0x00, "MQ Map Chest", "Spirit Temple MQ Map Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_CHEST, RG_SPIRIT_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 30792, 0x08, "MQ Map Room Enemy Chest", "Spirit Temple MQ Map Room Enemy Chest", RHT_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 28774, 0x06, "MQ Child Climb North Chest", "Spirit Temple MQ Child Climb North Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30644, 0x0C, "MQ Child Climb South Chest", "Spirit Temple MQ Child Climb South Chest", RHT_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -18429, 0x03, "MQ Compass Chest", "Spirit Temple MQ Compass Chest", RHT_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, RG_SPIRIT_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30577, 0x0F, "MQ Statue Room Lullaby Chest", "Spirit Temple MQ Statue Room Lullaby Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26882, 0x02, "MQ Statue Room Invisible Chest", "Spirit Temple MQ Statue Room Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30628, 0x1C, "MQ Silver Block Hallway Chest", "Spirit Temple MQ Silver Block Hallway Chest", RHT_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, -30463, 0x01, "MQ Sun Block Room Chest", "Spirit Temple MQ Sun Block Room Chest", RHT_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 23207, 0x07, "MQ Symphony Room Chest", "Spirit Temple MQ Symphony Room Chest", RHT_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31396, 0x04, "MQ Leever Room Chest", "Spirit Temple MQ Leever Room Chest", RHT_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 24472, 0x19, "MQ Beamos Room Chest", "Spirit Temple MQ Beamos Room Chest", RHT_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 31097, 0x18, "MQ Chest Switch Chest", "Spirit Temple MQ Chest Switch Chest", RHT_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 10213, 0x05, "MQ Boss Key Chest", "Spirit Temple MQ Boss Key Chest", RHT_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SPIRIT_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST] = Location::Chest(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPIRIT_TEMPLE, 26706, 0x12, "MQ Mirror Puzzle Invisible Chest", "Spirit Temple MQ Mirror Puzzle Invisible Chest", RHT_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, RG_SPIRIT_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Shadow Temple Vanilla - locationTable[RC_SHADOW_TEMPLE_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6177, 0x01, "Map Chest", "Shadow Temple Map Chest", RHT_SHADOW_TEMPLE_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "Hover Boots Chest", "Shadow Temple Hover Boots Chest", RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6147, 0x03, "Compass Chest", "Shadow Temple Compass Chest", RHT_SHADOW_TEMPLE_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22594, 0x02, "Early Silver Rupee Chest", "Shadow Temple Early Silver Rupee Chest", RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "Invisible Blades Visible Chest", "Shadow Temple Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26998, 0x16, "Invisible Blades Invisible Chest", "Shadow Temple Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "Falling Spikes Lower Chest", "Shadow Temple Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x06, "Falling Spikes Upper Chest", "Shadow Temple Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x04, "Falling Spikes Switch Chest", "Shadow Temple Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "Invisible Spikes Chest", "Shadow Temple Invisible Spikes Chest", RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26965, 0x15, "Wind Hint Chest", "Shadow Temple Wind Hint Chest", RHT_SHADOW_TEMPLE_WIND_HINT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "After Wind Enemy Chest", "Shadow Temple After Wind Enemy Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26708, 0x14, "After Wind Hidden Chest", "Shadow Temple After Wind Hidden Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "Spike Walls Left Chest", "Shadow Temple Spike Walls Left Chest", RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "Boss Key Chest", "Shadow Temple Boss Key Chest", RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30797, 0x0D, "Invisible Floormaster Chest", "Shadow Temple Invisible Floormaster Chest", RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 273, 0x01, "Freestanding Key", "Shadow Temple Freestanding Key", RHT_SHADOW_TEMPLE_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6177, 0x01, "Map Chest", "Shadow Temple Map Chest", RHT_SHADOW_TEMPLE_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "Hover Boots Chest", "Shadow Temple Hover Boots Chest", RHT_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6147, 0x03, "Compass Chest", "Shadow Temple Compass Chest", RHT_SHADOW_TEMPLE_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22594, 0x02, "Early Silver Rupee Chest", "Shadow Temple Early Silver Rupee Chest", RHT_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "Invisible Blades Visible Chest", "Shadow Temple Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26998, 0x16, "Invisible Blades Invisible Chest", "Shadow Temple Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "Falling Spikes Lower Chest", "Shadow Temple Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x06, "Falling Spikes Upper Chest", "Shadow Temple Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x04, "Falling Spikes Switch Chest", "Shadow Temple Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "Invisible Spikes Chest", "Shadow Temple Invisible Spikes Chest", RHT_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26965, 0x15, "Wind Hint Chest", "Shadow Temple Wind Hint Chest", RHT_SHADOW_TEMPLE_WIND_HINT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "After Wind Enemy Chest", "Shadow Temple After Wind Enemy Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26708, 0x14, "After Wind Hidden Chest", "Shadow Temple After Wind Hidden Chest", RHT_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "Spike Walls Left Chest", "Shadow Temple Spike Walls Left Chest", RHT_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "Boss Key Chest", "Shadow Temple Boss Key Chest", RHT_SHADOW_TEMPLE_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30797, 0x0D, "Invisible Floormaster Chest", "Shadow Temple Invisible Floormaster Chest", RHT_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 273, 0x01, "Freestanding Key", "Shadow Temple Freestanding Key", RHT_SHADOW_TEMPLE_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); // Shadow Temple MQ - locationTable[RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Shadow Temple MQ Compass Chest", RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "MQ Hover Boots Chest", "Shadow Temple MQ Hover Boots Chest", RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30787, 0x03, "MQ Early Gibdos Chest", "Shadow Temple MQ Early Gibdos Chest", RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 2082, 0x02, "MQ Map Chest", "Shadow Temple MQ Map Chest", RHT_SHADOW_TEMPLE_MQ_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30417, 0x0F, "MQ Beamos Silver Rupees Chest", "Shadow Temple MQ Beamos Silver Rupees Chest", RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x04, "MQ Falling Spikes Switch Chest", "Shadow Temple MQ Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "MQ Falling Spikes Lower Chest", "Shadow Temple MQ Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x06, "MQ Falling Spikes Upper Chest", "Shadow Temple MQ Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "MQ Invisible Spikes Chest", "Shadow Temple MQ Invisible Spikes Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "MQ Boss Key Chest", "Shadow Temple MQ Boss Key Chest", RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "MQ Spike Walls Left Chest", "Shadow Temple MQ Spike Walls Left Chest", RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31184, 0x10, "MQ Stalfos Room Chest", "Shadow Temple MQ Stalfos Room Chest", RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26710, 0x16, "MQ Invisible Blades Invisible Chest", "Shadow Temple MQ Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "MQ Invisible Blades Visible Chest", "Shadow Temple MQ Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31053, 0x0D, "MQ Bomb Flower Chest", "Shadow Temple MQ Bomb Flower Chest", RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26709, 0x15, "MQ Wind Hint Chest", "Shadow Temple MQ Wind Hint Chest", RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26932, 0x14, "MQ After Wind Hidden Chest", "Shadow Temple MQ After Wind Hidden Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "MQ After Wind Enemy Chest", "Shadow Temple MQ After Wind Enemy Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26702, 0x0E, "MQ Near Ship Invisible Chest", "Shadow Temple MQ Near Ship Invisible Chest", RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 1553, 0x06, "MQ Freestanding Key", "Shadow Temple MQ Freestanding Key", RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 6145, 0x01, "MQ Compass Chest", "Shadow Temple MQ Compass Chest", RHT_SHADOW_TEMPLE_MQ_COMPASS_CHEST, RG_SHADOW_TEMPLE_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 5607, 0x07, "MQ Hover Boots Chest", "Shadow Temple MQ Hover Boots Chest", RHT_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, RG_HOVER_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30787, 0x03, "MQ Early Gibdos Chest", "Shadow Temple MQ Early Gibdos Chest", RHT_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_MAP_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 2082, 0x02, "MQ Map Chest", "Shadow Temple MQ Map Chest", RHT_SHADOW_TEMPLE_MQ_MAP_CHEST, RG_SHADOW_TEMPLE_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30417, 0x0F, "MQ Beamos Silver Rupees Chest", "Shadow Temple MQ Beamos Silver Rupees Chest", RHT_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22662, 0x04, "MQ Falling Spikes Switch Chest", "Shadow Temple MQ Falling Spikes Switch Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22853, 0x05, "MQ Falling Spikes Lower Chest", "Shadow Temple MQ Falling Spikes Lower Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, -30652, 0x06, "MQ Falling Spikes Upper Chest", "Shadow Temple MQ Falling Spikes Upper Chest", RHT_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30857, 0x09, "MQ Invisible Spikes Chest", "Shadow Temple MQ Invisible Spikes Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RCQUEST_MQ, RCTYPE_BOSS_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 10219, 0x0B, "MQ Boss Key Chest", "Shadow Temple MQ Boss Key Chest", RHT_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, RG_SHADOW_TEMPLE_BOSS_KEY, { Category::cVanillaBossKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22666, 0x0A, "MQ Spike Walls Left Chest", "Shadow Temple MQ Spike Walls Left Chest", RHT_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31184, 0x10, "MQ Stalfos Room Chest", "Shadow Temple MQ Stalfos Room Chest", RHT_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26710, 0x16, "MQ Invisible Blades Invisible Chest", "Shadow Temple MQ Invisible Blades Invisible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 22668, 0x0C, "MQ Invisible Blades Visible Chest", "Shadow Temple MQ Invisible Blades Visible Chest", RHT_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 31053, 0x0D, "MQ Bomb Flower Chest", "Shadow Temple MQ Bomb Flower Chest", RHT_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26709, 0x15, "MQ Wind Hint Chest", "Shadow Temple MQ Wind Hint Chest", RHT_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26932, 0x14, "MQ After Wind Hidden Chest", "Shadow Temple MQ After Wind Hidden Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, RG_ARROWS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 30856, 0x08, "MQ After Wind Enemy Chest", "Shadow Temple MQ After Wind Enemy Chest", RHT_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST] = Location::Chest(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_BOX, SCENE_SHADOW_TEMPLE, 26702, 0x0E, "MQ Near Ship Invisible Chest", "Shadow Temple MQ Near Ship Invisible Chest", RHT_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY] = Location::Collectable(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_SHADOW_TEMPLE, ACTOR_EN_ITEM00, SCENE_SHADOW_TEMPLE, 1553, 0x06, "MQ Freestanding Key", "Shadow Temple MQ Freestanding Key", RHT_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Bottom of the Well Vanilla - locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22600, 0x08, "Front Left Fake Wall Chest", "Bottom of the Well Front Left Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20578, 0x02, "Front Center Bombable Chest", "Bottom of the Well Front Center Bombable Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22597, 0x05, "Right Bottom Fake Wall Chest", "Bottom of the Well Right Bottom Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2049, 0x01, "Compass Chest", "Bottom of the Well Compass Chest", RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20558, 0x0E, "Center Skulltula Chest", "Bottom of the Well Center Skulltula Chest", RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23684, 0x04, "Back Left Bombable Chest", "Bottom of the Well Back Left Bombable Chest", RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RG_DEKU_NUTS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 4419, 0x03, "Lens of Truth Chest", "Bottom of the Well Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 27348, 0x14, "Invisible Chest", "Bottom of the Well Invisible Chest", RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23760, 0x10, "Underwater Front Chest", "Bottom of the Well Underwater Front Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22793, 0x09, "Underwater Left Chest", "Bottom of the Well Underwater Left Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MAP_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2087, 0x07, "Map Chest", "Bottom of the Well Map Chest", RHT_BOTTOM_OF_THE_WELL_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21802, 0x0A, "Fire Keese Chest", "Bottom of the Well Fire Keese Chest", RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21836, 0x0C, "Like Like Chest", "Bottom of the Well Like Like Chest", RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = Location::Chest( RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "Freestanding Key", "Bottom of the Well Freestanding Key", RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22600, 0x08, "Front Left Fake Wall Chest", "Bottom of the Well Front Left Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20578, 0x02, "Front Center Bombable Chest", "Bottom of the Well Front Center Bombable Chest", RHT_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22597, 0x05, "Right Bottom Fake Wall Chest", "Bottom of the Well Right Bottom Fake Wall Chest", RHT_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2049, 0x01, "Compass Chest", "Bottom of the Well Compass Chest", RHT_BOTTOM_OF_THE_WELL_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 20558, 0x0E, "Center Skulltula Chest", "Bottom of the Well Center Skulltula Chest", RHT_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, RG_DEKU_NUTS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23684, 0x04, "Back Left Bombable Chest", "Bottom of the Well Back Left Bombable Chest", RHT_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, RG_DEKU_NUTS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 4419, 0x03, "Lens of Truth Chest", "Bottom of the Well Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 27348, 0x14, "Invisible Chest", "Bottom of the Well Invisible Chest", RHT_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 23760, 0x10, "Underwater Front Chest", "Bottom of the Well Underwater Front Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, RG_BOMBS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 22793, 0x09, "Underwater Left Chest", "Bottom of the Well Underwater Left Chest", RHT_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2087, 0x07, "Map Chest", "Bottom of the Well Map Chest", RHT_BOTTOM_OF_THE_WELL_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21802, 0x0A, "Fire Keese Chest", "Bottom of the Well Fire Keese Chest", RHT_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, RG_DEKU_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 21836, 0x0C, "Like Like Chest", "Bottom of the Well Like Like Chest", RHT_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, RG_HYLIAN_SHIELD, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "Freestanding Key", "Bottom of the Well Freestanding Key", RHT_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); // Bottom of the Well Master Quest - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2083, 0x03, "MQ Map Chest", "Bottom of the Well MQ Map Chest", RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, -20159, 0x01, "MQ Lens of Truth Chest", "Bottom of the Well MQ Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = Location::Chest( RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 6146, 0x02, "MQ Compass Chest", "Bottom of the Well MQ Compass Chest", RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 529, 0x02, "MQ Dead Hand Freestanding Key", "Bottom of the Well MQ Dead Hand Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "MQ East Inner Room Freestanding Key", "Bottom of the Well MQ East Inner Room Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 2083, 0x03, "MQ Map Chest", "Bottom of the Well MQ Map Chest", RHT_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, RG_BOTTOM_OF_THE_WELL_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, -20159, 0x01, "MQ Lens of Truth Chest", "Bottom of the Well MQ Lens of Truth Chest", RHT_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, RG_LENS_OF_TRUTH, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST] = Location::Chest(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_BOX, SCENE_BOTTOM_OF_THE_WELL, 6146, 0x02, "MQ Compass Chest", "Bottom of the Well MQ Compass Chest", RHT_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, RG_BOTTOM_OF_THE_WELL_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 529, 0x02, "MQ Dead Hand Freestanding Key", "Bottom of the Well MQ Dead Hand Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_BOTTOM_OF_THE_WELL, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, 273, 0x01, "MQ East Inner Room Freestanding Key", "Bottom of the Well MQ East Inner Room Freestanding Key", RHT_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flag Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Ice Cavern Vanilla - locationTable[RC_ICE_CAVERN_MAP_CHEST] = Location::Chest( RC_ICE_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2080, 0x00, "Map Chest", "Ice Cavern Map Chest", RHT_ICE_CAVERN_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_COMPASS_CHEST] = Location::Chest( RC_ICE_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2049, 0x01, "Compass Chest", "Ice Cavern Compass Chest", RHT_ICE_CAVERN_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_IRON_BOOTS_CHEST] = Location::Chest( RC_ICE_CAVERN_IRON_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "Iron Boots Chest", "Ice Cavern Iron Boots Chest", RHT_ICE_CAVERN_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_FREESTANDING_POH, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "Freestanding PoH", "Ice Cavern Freestanding PoH", RHT_ICE_CAVERN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MAP_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2080, 0x00, "Map Chest", "Ice Cavern Map Chest", RHT_ICE_CAVERN_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_COMPASS_CHEST, RCQUEST_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2049, 0x01, "Compass Chest", "Ice Cavern Compass Chest", RHT_ICE_CAVERN_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_IRON_BOOTS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "Iron Boots Chest", "Ice Cavern Iron Boots Chest", RHT_ICE_CAVERN_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_FREESTANDING_POH, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "Freestanding PoH", "Ice Cavern Freestanding PoH", RHT_ICE_CAVERN_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); // Ice Cavern Master Quest - locationTable[RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = Location::Chest( RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "MQ Iron Boots Chest", "Ice Cavern MQ Iron Boots Chest", RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_COMPASS_CHEST] = Location::Chest( RC_ICE_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2048, 0x00, "MQ Compass Chest", "Ice Cavern MQ Compass Chest", RHT_ICE_CAVERN_MQ_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_MAP_CHEST] = Location::Chest( RC_ICE_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, -18399, 0x01, "MQ Map Chest", "Ice Cavern MQ Map Chest", RHT_ICE_CAVERN_MQ_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_ICE_CAVERN_MQ_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_MQ_FREESTANDING_POH, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "MQ Freestanding PoH", "Ice Cavern MQ Freestanding PoH", RHT_ICE_CAVERN_MQ_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 5570, 0x02, "MQ Iron Boots Chest", "Ice Cavern MQ Iron Boots Chest", RHT_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, RG_IRON_BOOTS, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_COMPASS_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_COMPASS_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, 2048, 0x00, "MQ Compass Chest", "Ice Cavern MQ Compass Chest", RHT_ICE_CAVERN_MQ_COMPASS_CHEST, RG_ICE_CAVERN_COMPASS, { Category::cVanillaCompass }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_MAP_CHEST] = Location::Chest(RC_ICE_CAVERN_MQ_MAP_CHEST, RCQUEST_MQ, RCTYPE_MAP_COMPASS, RCAREA_ICE_CAVERN, ACTOR_EN_BOX, SCENE_ICE_CAVERN, -18399, 0x01, "MQ Map Chest", "Ice Cavern MQ Map Chest", RHT_ICE_CAVERN_MQ_MAP_CHEST, RG_ICE_CAVERN_MAP, { Category::cVanillaMap }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_ICE_CAVERN_MQ_FREESTANDING_POH] = Location::Collectable(RC_ICE_CAVERN_MQ_FREESTANDING_POH, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_ICE_CAVERN, ACTOR_EN_ITEM00, SCENE_ICE_CAVERN, 262, 0x01, "MQ Freestanding PoH", "Ice Cavern MQ Freestanding PoH", RHT_ICE_CAVERN_MQ_FREESTANDING_POH, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flag Short Name Spoiler Name Hint Text Key Vanilla Item Categories Collection Check Group Vanilla Progression // Gerudo Training Grounds Vanilla - locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30573, 0x13, "Lobby Left Chest", "Gerudo Training Grounds Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30393, 0x07, "Lobby Right Chest", "Gerudo Training Grounds Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30656, 0x00, "Stalfos Chest", "Gerudo Training Grounds Stalfos Chest", RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "Beamos Chest", "Gerudo Training Grounds Beamos Chest", RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22603, 0x0B, "Hidden Ceiling Chest", "Gerudo Training Grounds Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23206, 0x06, "Maze Path First Chest", "Gerudo Training Grounds Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "Maze Path Second Chest", "Gerudo Training Grounds Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22889, 0x09, "Maze Path Third Chest", "Gerudo Training Grounds Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 2860, 0x0C, "Maze Path Final Chest", "Gerudo Training Grounds Maze Path Final Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23877, 0x05, "Maze Right Central Chest", "Gerudo Training Grounds Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22888, 0x08, "Maze Right Side Chest", "Gerudo Training Grounds Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "Underwater Silver Rupee Chest", "Gerudo Training Grounds Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "Hammer Room Clear Chest", "Gerudo Training Grounds Hammer Room Clear Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22608, 0x10, "Hammer Room Switch Chest", "Gerudo Training Grounds Hammer Room Switch Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30653, 0x03, "Eye Statue Chest", "Gerudo Training Grounds Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22596, 0x04, "Near Scarecrow Chest", "Gerudo Training Grounds Near Scarecrow Chest", RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31089, 0x11, "Before Heavy Block Chest", "Gerudo Training Grounds Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31439, 0x0F, "Heavy Block First Chest", "Gerudo Training Grounds Heavy Block First Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 30862, 0x0E, "Heavy Block Second Chest", "Gerudo Training Grounds Heavy Block Second Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 26708, 0x14, "Heavy Block Third Chest", "Gerudo Training Grounds Heavy Block Third Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24450, 0x02, "Heavy Block Fourth Chest", "Gerudo Training Grounds Heavy Block Fourth Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = Location::Collectable(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_ITEM00, SCENE_GERUDO_TRAINING_GROUND, 273, 0x01, "Freestanding Key", "Gerudo Training Grounds Freestanding Key", RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30573, 0x13, "Lobby Left Chest", "Gerudo Training Grounds Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30393, 0x07, "Lobby Right Chest", "Gerudo Training Grounds Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30656, 0x00, "Stalfos Chest", "Gerudo Training Grounds Stalfos Chest", RHT_GERUDO_TRAINING_GROUND_STALFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "Beamos Chest", "Gerudo Training Grounds Beamos Chest", RHT_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22603, 0x0B, "Hidden Ceiling Chest", "Gerudo Training Grounds Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23206, 0x06, "Maze Path First Chest", "Gerudo Training Grounds Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "Maze Path Second Chest", "Gerudo Training Grounds Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22889, 0x09, "Maze Path Third Chest", "Gerudo Training Grounds Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RCQUEST_VANILLA, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 2860, 0x0C, "Maze Path Final Chest", "Gerudo Training Grounds Maze Path Final Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23877, 0x05, "Maze Right Central Chest", "Gerudo Training Grounds Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22888, 0x08, "Maze Right Side Chest", "Gerudo Training Grounds Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "Underwater Silver Rupee Chest", "Gerudo Training Grounds Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "Hammer Room Clear Chest", "Gerudo Training Grounds Hammer Room Clear Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22608, 0x10, "Hammer Room Switch Chest", "Gerudo Training Grounds Hammer Room Switch Chest", RHT_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30653, 0x03, "Eye Statue Chest", "Gerudo Training Grounds Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22596, 0x04, "Near Scarecrow Chest", "Gerudo Training Grounds Near Scarecrow Chest", RHT_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31089, 0x11, "Before Heavy Block Chest", "Gerudo Training Grounds Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31439, 0x0F, "Heavy Block First Chest", "Gerudo Training Grounds Heavy Block First Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, RG_HUGE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 30862, 0x0E, "Heavy Block Second Chest", "Gerudo Training Grounds Heavy Block Second Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 26708, 0x14, "Heavy Block Third Chest", "Gerudo Training Grounds Heavy Block Third Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24450, 0x02, "Heavy Block Fourth Chest", "Gerudo Training Grounds Heavy Block Fourth Chest", RHT_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY] = Location::Collectable(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_ITEM00, SCENE_GERUDO_TRAINING_GROUND, 273, 0x01, "Freestanding Key", "Gerudo Training Grounds Freestanding Key", RHT_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); // Gerudo Training Grounds Master Quest - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23879, 0x07, "MQ Lobby Right Chest", "Gerudo Training Grounds MQ Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22867, 0x13, "MQ Lobby Left Chest", "Gerudo Training Grounds MQ Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30304, 0x00, "MQ First Iron Knuckle Chest", "Gerudo Training Grounds MQ First Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31057, 0x11, "MQ Before Heavy Block Chest", "Gerudo Training Grounds MQ Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -32669, 0x03, "MQ Eye Statue Chest", "Gerudo Training Grounds MQ Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30642, 0x0E, "MQ Flame Circle Chest", "Gerudo Training Grounds MQ Flame Circle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "MQ Second Iron Knuckle Chest", "Gerudo Training Grounds MQ Second Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "MQ Dinolfos Chest", "Gerudo Training Grounds MQ Dinolfos Chest", RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -17628, 0x04, "MQ Ice Arrows Chest", "Gerudo Training Grounds MQ Ice Arrows Chest", RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22661, 0x05, "MQ Maze Right Central Chest", "Gerudo Training Grounds MQ Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22918, 0x06, "MQ Maze Path First Chest", "Gerudo Training Grounds MQ Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RG_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24136, 0x08, "MQ Maze Right Side Chest", "Gerudo Training Grounds MQ Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = Location::Chest( RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24137, 0x09, "MQ Maze Path Third Chest", "Gerudo Training Grounds MQ Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "MQ Maze Path Second Chest", "Gerudo Training Grounds MQ Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23211, 0x0B, "MQ Hidden Ceiling Chest", "Gerudo Training Grounds MQ Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "MQ Underwater Silver Rupee Chest", "Gerudo Training Grounds MQ Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); - locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31394, 0x02, "MQ Heavy Block Chest", "Gerudo Training Grounds MQ Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23879, 0x07, "MQ Lobby Right Chest", "Gerudo Training Grounds MQ Lobby Right Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, RG_BOMBCHU_5, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22867, 0x13, "MQ Lobby Left Chest", "Gerudo Training Grounds MQ Lobby Left Chest", RHT_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30304, 0x00, "MQ First Iron Knuckle Chest", "Gerudo Training Grounds MQ First Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31057, 0x11, "MQ Before Heavy Block Chest", "Gerudo Training Grounds MQ Before Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -32669, 0x03, "MQ Eye Statue Chest", "Gerudo Training Grounds MQ Eye Statue Chest", RHT_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30642, 0x0E, "MQ Flame Circle Chest", "Gerudo Training Grounds MQ Flame Circle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31058, 0x12, "MQ Second Iron Knuckle Chest", "Gerudo Training Grounds MQ Second Iron Knuckle Chest", RHT_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30655, 0x01, "MQ Dinolfos Chest", "Gerudo Training Grounds MQ Dinolfos Chest", RHT_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RCQUEST_MQ, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -17628, 0x04, "MQ Ice Arrows Chest", "Gerudo Training Grounds MQ Ice Arrows Chest", RHT_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, RG_ICE_ARROWS, { Category::cSongDungeonReward }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22661, 0x05, "MQ Maze Right Central Chest", "Gerudo Training Grounds MQ Maze Right Central Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22918, 0x06, "MQ Maze Path First Chest", "Gerudo Training Grounds MQ Maze Path First Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, RG_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24136, 0x08, "MQ Maze Right Side Chest", "Gerudo Training Grounds MQ Maze Right Side Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 24137, 0x09, "MQ Maze Path Third Chest", "Gerudo Training Grounds MQ Maze Path Third Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 22986, 0x0A, "MQ Maze Path Second Chest", "Gerudo Training Grounds MQ Maze Path Second Chest", RHT_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 23211, 0x0B, "MQ Hidden Ceiling Chest", "Gerudo Training Grounds MQ Hidden Ceiling Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, -30643, 0x0D, "MQ Underwater Silver Rupee Chest", "Gerudo Training Grounds MQ Underwater Silver Rupee Chest", RHT_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, RG_TREASURE_GAME_GREEN_RUPEE, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND, true); + locationTable[RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST] = Location::Chest(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_GERUDO_TRAINING_GROUND, 31394, 0x02, "MQ Heavy Block Chest", "Gerudo Training Grounds MQ Heavy Block Chest", RHT_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RG_PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_TRAINING_GROUND); - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flag Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression // Ganon's Castle Shared - locationTable[RC_GANONS_TOWER_BOSS_KEY_CHEST] = Location::Chest(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCQUEST_BOTH, RCTYPE_GANON_BOSS_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONS_TOWER, 10219, 0x0B, "Boss Key Chest", "Ganon's Tower Boss Key Chest", RHT_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_TOWER_BOSS_KEY_CHEST] = Location::Chest(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCQUEST_BOTH, RCTYPE_GANON_BOSS_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONS_TOWER, 10219, 0x0B, "Boss Key Chest", "Ganon's Tower Boss Key Chest", RHT_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); // Ganon's Castle Vanilla - locationTable[RC_GANONS_CASTLE_FOREST_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30857, 0x09, "Forest Trial Chest", "Ganon's Castle Forest Trial Chest", RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24455, 0x07, "Water Trial Left Chest", "Ganon's Castle Water Trial Left Chest", RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22790, 0x06, "Water Trial Right Chest", "Ganon's Castle Water Trial Right Chest", RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22664, 0x08, "Shadow Trial Front Chest", "Ganon's Castle Shadow Trial Front Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 14021, 0x05, "Shadow Trial Golden Gauntlets Chest", "Ganon's Castle Shadow Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -29326, 0x12, "Spirit Trial Crystal Switch Chest", "Ganon's Castle Spirit Trial Crystal Switch Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RG_BOMBCHU_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "Spirit Trial Invisible Chest", "Ganon's Castle Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22668, 0x0C, "Light Trial First Left Chest", "Ganon's Castle Light Trial First Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24459, 0x0B, "Light Trial Second Left Chest", "Ganon's Castle Light Trial Second Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22797, 0x0D, "Light Trial Third Left Chest", "Ganon's Castle Light Trial Third Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24462, 0x0E, "Light Trial First Right Chest", "Ganon's Castle Light Trial First Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22890, 0x0A, "Light Trial Second Right Chest", "Ganon's Castle Light Trial Second Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24463, 0x0F, "Light Trial Third Right Chest", "Ganon's Castle Light Trial Third Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30800, 0x10, "Light Trial Invisible Enemies Chest", "Ganon's Castle Light Trial Invisible Enemies Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30639, 0x11, "Light Trial Lullaby Chest", "Ganon's Castle Light Trial Lullaby Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x06), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right", RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x08), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left", RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x09), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_FOREST_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30857, 0x09, "Forest Trial Chest", "Ganon's Castle Forest Trial Chest", RHT_GANONS_CASTLE_FOREST_TRIAL_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24455, 0x07, "Water Trial Left Chest", "Ganon's Castle Water Trial Left Chest", RHT_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22790, 0x06, "Water Trial Right Chest", "Ganon's Castle Water Trial Right Chest", RHT_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22664, 0x08, "Shadow Trial Front Chest", "Ganon's Castle Shadow Trial Front Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 14021, 0x05, "Shadow Trial Golden Gauntlets Chest", "Ganon's Castle Shadow Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -29326, 0x12, "Spirit Trial Crystal Switch Chest", "Ganon's Castle Spirit Trial Crystal Switch Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, RG_BOMBCHU_20, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "Spirit Trial Invisible Chest", "Ganon's Castle Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22668, 0x0C, "Light Trial First Left Chest", "Ganon's Castle Light Trial First Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, RG_BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24459, 0x0B, "Light Trial Second Left Chest", "Ganon's Castle Light Trial Second Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22797, 0x0D, "Light Trial Third Left Chest", "Ganon's Castle Light Trial Third Left Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24462, 0x0E, "Light Trial First Right Chest", "Ganon's Castle Light Trial First Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22890, 0x0A, "Light Trial Second Right Chest", "Ganon's Castle Light Trial Second Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, RG_ARROWS_30, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RCQUEST_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 24463, 0x0F, "Light Trial Third Right Chest", "Ganon's Castle Light Trial Third Right Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, RG_ICE_TRAP, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 30800, 0x10, "Light Trial Invisible Enemies Chest", "Ganon's Castle Light Trial Invisible Enemies Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_VANILLA, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30639, 0x11, "Light Trial Lullaby Chest", "Ganon's Castle Light Trial Lullaby Chest", RHT_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "Deku Scrub Center-Left", "Ganon's Castle Deku Scrub Center-Left", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "Deku Scrub Center-Right", "Ganon's Castle Deku Scrub Center-Right", RHT_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "Deku Scrub Right", "Ganon's Castle Deku Scrub Right", RHT_GANONS_CASTLE_DEKU_SCRUB_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, RCQUEST_VANILLA, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "Deku Scrub Left", "Ganon's Castle Deku Scrub Left", RHT_GANONS_CASTLE_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); // Ganon's Castle MQ - locationTable[RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22977, 0x01, "MQ Water Trial Chest", "Ganon's Castle MQ Water Trial Chest", RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30398, 0x02, "MQ Forest Trial Eye Switch Chest", "Ganon's Castle MQ Forest Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -32733, 0x03, "MQ Forest Trial Frozen Eye Switch Chest", "Ganon's Castle MQ Forest Trial Frozen Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30460, 0x04, "MQ Light Trial Lullaby Chest", "Ganon's Castle MQ Light Trial Lullaby Chest", RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30400, 0x00, "MQ Shadow Trial Bomb Flower Chest", "Ganon's Castle MQ Shadow Trial Bomb Flower Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30651, 0x05, "MQ Shadow Trial Eye Switch Chest", "Ganon's Castle MQ Shadow Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -18746, 0x06, "MQ Spirit Trial Golden Gauntlets Chest", "Ganon's Castle MQ Spirit Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30457, 0x07, "MQ Spirit Trial Sun Back Right Chest", "Ganon's Castle MQ Spirit Trial Sun Back Right Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30648, 0x08, "MQ Spirit Trial Sun Back Left Chest", "Ganon's Castle MQ Spirit Trial Sun Back Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30455, 0x09, "MQ Spirit Trial Sun Front Left Chest", "Ganon's Castle MQ Spirit Trial Sun Front Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 20586, 0x0A, "MQ Spirit Trial First Chest", "Ganon's Castle MQ Spirit Trial First Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "MQ Spirit Trial Invisible Chest", "Ganon's Castle MQ Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = Location::Collectable(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_INSIDE_GANONS_CASTLE, 273, 0x01, "MQ Forest Trial Freestanding Key", "Ganon's Castle MQ Forest Trial Freestanding Key", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x00, 0x30, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x01), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x06), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x04), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x08), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::Scrub(0x0D, 0x09), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 22977, 0x01, "MQ Water Trial Chest", "Ganon's Castle MQ Water Trial Chest", RHT_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, RG_RED_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30398, 0x02, "MQ Forest Trial Eye Switch Chest", "Ganon's Castle MQ Forest Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -32733, 0x03, "MQ Forest Trial Frozen Eye Switch Chest", "Ganon's Castle MQ Forest Trial Frozen Eye Switch Chest", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, RG_BOMBS_5, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30460, 0x04, "MQ Light Trial Lullaby Chest", "Ganon's Castle MQ Light Trial Lullaby Chest", RHT_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30400, 0x00, "MQ Shadow Trial Bomb Flower Chest", "Ganon's Castle MQ Shadow Trial Bomb Flower Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30651, 0x05, "MQ Shadow Trial Eye Switch Chest", "Ganon's Castle MQ Shadow Trial Eye Switch Chest", RHT_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -18746, 0x06, "MQ Spirit Trial Golden Gauntlets Chest", "Ganon's Castle MQ Spirit Trial Golden Gauntlets Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, RG_PROGRESSIVE_STRENGTH, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30457, 0x07, "MQ Spirit Trial Sun Back Right Chest", "Ganon's Castle MQ Spirit Trial Sun Back Right Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30648, 0x08, "MQ Spirit Trial Sun Back Left Chest", "Ganon's Castle MQ Spirit Trial Sun Back Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, -30455, 0x09, "MQ Spirit Trial Sun Front Left Chest", "Ganon's Castle MQ Spirit Trial Sun Front Left Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, RG_RECOVERY_HEART, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 20586, 0x0A, "MQ Spirit Trial First Chest", "Ganon's Castle MQ Spirit Trial First Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, RG_BOMBCHU_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST] = Location::Chest(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RCQUEST_MQ, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_INSIDE_GANONS_CASTLE, 26964, 0x14, "MQ Spirit Trial Invisible Chest", "Ganon's Castle MQ Spirit Trial Invisible Chest", RHT_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, RG_ARROWS_10, {}, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY] = Location::Collectable(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RCQUEST_MQ, RCTYPE_SMALL_KEY, RCAREA_GANONS_CASTLE, ACTOR_EN_ITEM00, SCENE_INSIDE_GANONS_CASTLE, 273, 0x01, "MQ Forest Trial Freestanding Key", "Ganon's Castle MQ Forest Trial Freestanding Key", RHT_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, RG_GANONS_CASTLE_SMALL_KEY, { Category::cVanillaSmallKey }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x00, 0x30, "MQ Deku Scrub Right", "Ganon's Castle MQ Deku Scrub Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, RG_BUY_DEKU_NUTS_5, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x05, 0x37, "MQ Deku Scrub Center-Left", "Ganon's Castle MQ Deku Scrub Center-Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, RG_BUY_BOMBS_535, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x03, 0x33, "MQ Deku Scrub Center", "Ganon's Castle MQ Deku Scrub Center", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, RG_BUY_ARROWS_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x07, 0x39, "MQ Deku Scrub Center-Right", "Ganon's Castle MQ Deku Scrub Center-Right", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, RG_BUY_RED_POTION_30, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT] = Location::Base(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RCQUEST_MQ, RCTYPE_SCRUB, RCAREA_GANONS_CASTLE, ACTOR_EN_DNS, SCENE_INSIDE_GANONS_CASTLE, 0x08, 0x3A, "MQ Deku Scrub Left", "Ganon's Castle MQ Deku Scrub Left", RHT_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, RG_BUY_GREEN_POTION, { Category::cDekuScrub }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); // Gold Skulltula Tokens // Dungeons - // Deku Tree RandomizerCheck RandomizerCheck Quest Area Scene ID params Flag Short Name Spoiler Name Hint Text Key Categories Collection Check Group - locationTable[RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "GS Basement Back Room", "Deku Tree GS Basement Back Room", RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_BASEMENT_GATE] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_GATE, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "GS Basement Gate", "Deku Tree GS Basement Gate", RHT_DEKU_TREE_GS_BASEMENT_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_BASEMENT_VINES] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_VINES, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "GS Basement Vines", "Deku Tree GS Basement Vines", RHT_DEKU_TREE_GS_BASEMENT_VINES, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_COMPASS_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "GS Compass Room", "Deku Tree GS Compass Room", RHT_DEKU_TREE_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_LOBBY] = Location::GSToken(RC_DEKU_TREE_MQ_GS_LOBBY, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "MQ GS Lobby", "Deku Tree MQ GS Lobby", RHT_DEKU_TREE_MQ_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "MQ GS Compass Room", "Deku Tree MQ GS Compass Room", RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "MQ GS Basement Graves Room", "Deku Tree MQ GS Basement Graves Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); - locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "MQ GS Basement Back Room", "Deku Tree MQ GS Basement Back Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + // Deku Tree + locationTable[RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "GS Basement Back Room", "Deku Tree GS Basement Back Room", RHT_DEKU_TREE_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_GATE] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_GATE, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "GS Basement Gate", "Deku Tree GS Basement Gate", RHT_DEKU_TREE_GS_BASEMENT_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_BASEMENT_VINES] = Location::GSToken(RC_DEKU_TREE_GS_BASEMENT_VINES, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "GS Basement Vines", "Deku Tree GS Basement Vines", RHT_DEKU_TREE_GS_BASEMENT_VINES, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_GS_COMPASS_ROOM, RCQUEST_VANILLA, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "GS Compass Room", "Deku Tree GS Compass Room", RHT_DEKU_TREE_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_LOBBY] = Location::GSToken(RC_DEKU_TREE_MQ_GS_LOBBY, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8194, 0x02, "MQ GS Lobby", "Deku Tree MQ GS Lobby", RHT_DEKU_TREE_MQ_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_COMPASS_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8200, 0x08, "MQ GS Compass Room", "Deku Tree MQ GS Compass Room", RHT_DEKU_TREE_MQ_GS_COMPASS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8196, 0x04, "MQ GS Basement Graves Room", "Deku Tree MQ GS Basement Graves Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); + locationTable[RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM] = Location::GSToken(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, RCQUEST_MQ, RCAREA_DEKU_TREE, SCENE_DEKU_TREE, 8193, 0x01, "MQ GS Basement Back Room", "Deku Tree MQ GS Basement Back Room", RHT_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE); // Dodongo's Cavern - locationTable[RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "GS Vines Above Stairs", "Dodongos Cavern GS Vines Above Stairs", RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_SCARECROW] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SCARECROW, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "GS Scarecrow", "Dodongos Cavern GS Scarecrow", RHT_DODONGOS_CAVERN_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "GS Alcove Above Stairs", "Dodongos Cavern GS Alcove Above Stairs", RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_BACK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_GS_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "GS Back Room", "Dodongos Cavern GS Back Room", RHT_DODONGOS_CAVERN_GS_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "GS Side Room Near Lower Lizalfos", "Dodongos Cavern GS Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "MQ GS Scrub Room", "Dodongos Cavern MQ GS Scrub Room", RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "MQ GS Song of Time Block Room", "Dodongos Cavern MQ GS Song of Time Block Room", RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "MQ GS Lizalfos Room", "Dodongos Cavern MQ GS Lizalfos Room", RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "MQ GS Larvae Room", "Dodongos Cavern MQ GS Larvae Room", RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "MQ GS Back Room", "Dodongos Cavern MQ GS Back Room", RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); - locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "GS Lobby Basement Lower", "Jabu Jabus Belly GS Lobby Basement Lower", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "GS Lobby Basement Upper", "Jabu Jabus Belly GS Lobby Basement Upper", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "GS Near Boss", "Jabu Jabus Belly GS Near Boss", RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "GS Water Switch Room", "Jabu Jabus Belly GS Water Switch Room", RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "MQ GS Tail Parasan Room", "Jabu Jabus Belly MQ GS Tail Parasan Room", RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "MQ GS Invisible Enemies Room", "Jabu Jabus Belly MQ GS Invisible Enemies Room", RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "MQ GS Boomerang Chest Room", "Jabu Jabus Belly MQ GS Boomerang Chest Room", RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "MQ GS Near Boss", "Jabu Jabus Belly MQ GS Near Boss", RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); - locationTable[RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "GS Raised Island Courtyard", "Forest Temple GS Raised Island Courtyard", RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_FIRST_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_GS_FIRST_ROOM, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "GS First Room", "Forest Temple GS First Room", RHT_FOREST_TEMPLE_GS_FIRST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "GS Level Island Courtyard", "Forest Temple GS Level Island Courtyard", RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_LOBBY] = Location::GSToken(RC_FOREST_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "GS Lobby", "Forest Temple GS Lobby", RHT_FOREST_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_GS_BASEMENT] = Location::GSToken(RC_FOREST_TEMPLE_GS_BASEMENT, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "GS Basement", "Forest Temple GS Basement", RHT_FOREST_TEMPLE_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "MQ GS First Hallway", "Forest Temple MQ GS First Hallway", RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "MQ GS Block Push Room", "Forest Temple MQ GS Block Push Room", RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "MQ GS Raised Island Courtyard", "Forest Temple MQ GS Raised Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "MQ GS Level Island Courtyard", "Forest Temple MQ GS Level Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); - locationTable[RC_FOREST_TEMPLE_MQ_GS_WELL] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_WELL, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "MQ GS Well", "Forest Temple MQ GS Well", RHT_FOREST_TEMPLE_MQ_GS_WELL, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "GS Vines Above Stairs", "Dodongos Cavern GS Vines Above Stairs", RHT_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_SCARECROW] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SCARECROW, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "GS Scarecrow", "Dodongos Cavern GS Scarecrow", RHT_DODONGOS_CAVERN_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "GS Alcove Above Stairs", "Dodongos Cavern GS Alcove Above Stairs", RHT_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_BACK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_GS_BACK_ROOM, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "GS Back Room", "Dodongos Cavern GS Back Room", RHT_DODONGOS_CAVERN_GS_BACK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS] = Location::GSToken(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "GS Side Room Near Lower Lizalfos", "Dodongos Cavern GS Side Room Near Lower Lizalfos", RHT_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8450, 0x02, "MQ GS Scrub Room", "Dodongos Cavern MQ GS Scrub Room", RHT_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8456, 0x08, "MQ GS Song of Time Block Room", "Dodongos Cavern MQ GS Song of Time Block Room", RHT_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8452, 0x04, "MQ GS Lizalfos Room", "Dodongos Cavern MQ GS Lizalfos Room", RHT_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8464, 0x10, "MQ GS Larvae Room", "Dodongos Cavern MQ GS Larvae Room", RHT_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA] = Location::GSToken(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, RCQUEST_MQ, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 8449, 0x01, "MQ GS Back Room", "Dodongos Cavern MQ GS Back Room", RHT_DODONGOS_CAVERN_MQ_GS_BACK_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN); + locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "GS Lobby Basement Lower", "Jabu Jabus Belly GS Lobby Basement Lower", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "GS Lobby Basement Upper", "Jabu Jabus Belly GS Lobby Basement Upper", RHT_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "GS Near Boss", "Jabu Jabus Belly GS Near Boss", RHT_JABU_JABUS_BELLY_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, RCQUEST_VANILLA, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "GS Water Switch Room", "Jabu Jabus Belly GS Water Switch Room", RHT_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8708, 0x04, "MQ GS Tail Parasan Room", "Jabu Jabus Belly MQ GS Tail Parasan Room", RHT_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8712, 0x08, "MQ GS Invisible Enemies Room", "Jabu Jabus Belly MQ GS Invisible Enemies Room", RHT_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8705, 0x01, "MQ GS Boomerang Chest Room", "Jabu Jabus Belly MQ GS Boomerang Chest Room", RHT_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, 8706, 0x02, "MQ GS Near Boss", "Jabu Jabus Belly MQ GS Near Boss", RHT_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + locationTable[RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "GS Raised Island Courtyard", "Forest Temple GS Raised Island Courtyard", RHT_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_FIRST_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_GS_FIRST_ROOM, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "GS First Room", "Forest Temple GS First Room", RHT_FOREST_TEMPLE_GS_FIRST_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "GS Level Island Courtyard", "Forest Temple GS Level Island Courtyard", RHT_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_LOBBY] = Location::GSToken(RC_FOREST_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "GS Lobby", "Forest Temple GS Lobby", RHT_FOREST_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_GS_BASEMENT] = Location::GSToken(RC_FOREST_TEMPLE_GS_BASEMENT, RCQUEST_VANILLA, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "GS Basement", "Forest Temple GS Basement", RHT_FOREST_TEMPLE_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8962, 0x02, "MQ GS First Hallway", "Forest Temple MQ GS First Hallway", RHT_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8976, 0x10, "MQ GS Block Push Room", "Forest Temple MQ GS Block Push Room", RHT_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8961, 0x01, "MQ GS Raised Island Courtyard", "Forest Temple MQ GS Raised Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8964, 0x04, "MQ GS Level Island Courtyard", "Forest Temple MQ GS Level Island Courtyard", RHT_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); + locationTable[RC_FOREST_TEMPLE_MQ_GS_WELL] = Location::GSToken(RC_FOREST_TEMPLE_MQ_GS_WELL, RCQUEST_MQ, RCAREA_FOREST_TEMPLE, SCENE_FOREST_TEMPLE, 8968, 0x08, "MQ GS Well", "Forest Temple MQ GS Well", RHT_FOREST_TEMPLE_MQ_GS_WELL, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE); // Fire Temple - locationTable[RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "GS Song of Time Room", "Fire Temple GS Song of Time Room", RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "GS Boss Key Loop", "Fire Temple GS Boss Key Loop", RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", "Fire Temple GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", "Fire Temple GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", "Fire Temple GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", "Fire Temple MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", "Fire Temple MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", "Fire Temple MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", "Fire Temple MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); - locationTable[RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "MQ GS Skull on Fire", "Fire Temple MQ GS Skull on Fire", RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "GS Song of Time Room", "Fire Temple GS Song of Time Room", RHT_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "GS Boss Key Loop", "Fire Temple GS Boss Key Loop", RHT_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_BOULDER_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "GS Boulder Maze", "Fire Temple GS Boulder Maze", RHT_FIRE_TEMPLE_GS_BOULDER_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_TOP] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "GS Scarecrow Top", "Fire Temple GS Scarecrow Top", RHT_FIRE_TEMPLE_GS_SCARECROW_TOP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB] = Location::GSToken(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, RCQUEST_VANILLA, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "GS Scarecrow Climb", "Fire Temple GS Scarecrow Climb", RHT_FIRE_TEMPLE_GS_SCARECROW_CLIMB, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9218, 0x02, "MQ GS Above Fire Wall Maze", "Fire Temple MQ GS Above Fire Wall Maze", RHT_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9224, 0x08, "MQ GS Fire Wall Maze Center", "Fire Temple MQ GS Fire Wall Maze Center", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9217, 0x01, "MQ GS Big Lava Room Open Door", "Fire Temple MQ GS Big Lava Room Open Door", RHT_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9232, 0x10, "MQ GS Fire Wall Maze Side Room", "Fire Temple MQ GS Fire Wall Maze Side Room", RHT_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); + locationTable[RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE] = Location::GSToken(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, RCQUEST_MQ, RCAREA_FIRE_TEMPLE, SCENE_FIRE_TEMPLE, 9220, 0x04, "MQ GS Skull on Fire", "Fire Temple MQ GS Skull on Fire", RHT_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE); // Water Temple - locationTable[RC_WATER_TEMPLE_GS_BEHIND_GATE] = Location::GSToken(RC_WATER_TEMPLE_GS_BEHIND_GATE, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "GS Behind Gate", "Water Temple GS Behind Gate", RHT_WATER_TEMPLE_GS_BEHIND_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = Location::GSToken(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "GS Falling Platform Room", "Water Temple GS Falling Platform Room", RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_CENTRAL_PILLAR] = Location::GSToken(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "GS Central Pillar", "Water Temple GS Central Pillar", RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = Location::GSToken(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "GS Near Boss Key Chest", "Water Temple GS Near Boss Key Chest", RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_GS_RIVER, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "GS River", "Water Temple GS River", RHT_WATER_TEMPLE_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "MQ GS Before Upper Water Switch", "Water Temple MQ GS Before Upper Water Switch", RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "MQ GS Freestanding Key Area", "Water Temple MQ GS Freestanding Key Area", RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "MQ GS Lizalfos Hallway", "Water Temple MQ GS Lizalfos Hallway", RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_RIVER, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "MQ GS River", "Water Temple MQ GS River", RHT_WATER_TEMPLE_MQ_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); - locationTable[RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "MQ GS Triple Wall Torch", "Water Temple MQ GS Triple Wall Torch", RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_BEHIND_GATE] = Location::GSToken(RC_WATER_TEMPLE_GS_BEHIND_GATE, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "GS Behind Gate", "Water Temple GS Behind Gate", RHT_WATER_TEMPLE_GS_BEHIND_GATE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM] = Location::GSToken(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "GS Falling Platform Room", "Water Temple GS Falling Platform Room", RHT_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_CENTRAL_PILLAR] = Location::GSToken(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "GS Central Pillar", "Water Temple GS Central Pillar", RHT_WATER_TEMPLE_GS_CENTRAL_PILLAR, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST] = Location::GSToken(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "GS Near Boss Key Chest", "Water Temple GS Near Boss Key Chest", RHT_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_GS_RIVER, RCQUEST_VANILLA, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "GS River", "Water Temple GS River", RHT_WATER_TEMPLE_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9476, 0x04, "MQ GS Before Upper Water Switch", "Water Temple MQ GS Before Upper Water Switch", RHT_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9480, 0x08, "MQ GS Freestanding Key Area", "Water Temple MQ GS Freestanding Key Area", RHT_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9473, 0x01, "MQ GS Lizalfos Hallway", "Water Temple MQ GS Lizalfos Hallway", RHT_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_RIVER] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_RIVER, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9474, 0x02, "MQ GS River", "Water Temple MQ GS River", RHT_WATER_TEMPLE_MQ_GS_RIVER, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); + locationTable[RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH] = Location::GSToken(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, RCQUEST_MQ, RCAREA_WATER_TEMPLE, SCENE_WATER_TEMPLE, 9488, 0x10, "MQ GS Triple Wall Torch", "Water Temple MQ GS Triple Wall Torch", RHT_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE); // Spirit Temple - locationTable[RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "GS Hall After Sun Block Room", "Spirit Temple GS Hall After Sun Block Room", RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "GS Boulder Room", "Spirit Temple GS Boulder Room", RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_LOBBY] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "GS Lobby", "Spirit Temple GS Lobby", RHT_SPIRIT_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "GS Sun on Floor Room", "Spirit Temple GS Sun on Floor Room", RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_GS_METAL_FENCE] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "GS Metal Fence", "Spirit Temple GS Metal Fence", RHT_SPIRIT_TEMPLE_GS_METAL_FENCE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "MQ GS Symphony Room", "Spirit Temple MQ GS Symphony Room", RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "MQ GS Leever Room", "Spirit Temple MQ GS Leever Room", RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "MQ GS Nine Thrones Room West", "Spirit Temple MQ GS Nine Thrones Room West", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "MQ GS Nine Thrones Room North", "Spirit Temple MQ GS Nine Thrones Room North", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); - locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "MQ GS Sun Block Room", "Spirit Temple MQ GS Sun Block Room", RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "GS Hall After Sun Block Room", "Spirit Temple GS Hall After Sun Block Room", RHT_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "GS Boulder Room", "Spirit Temple GS Boulder Room", RHT_SPIRIT_TEMPLE_GS_BOULDER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_LOBBY] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_LOBBY, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "GS Lobby", "Spirit Temple GS Lobby", RHT_SPIRIT_TEMPLE_GS_LOBBY, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "GS Sun on Floor Room", "Spirit Temple GS Sun on Floor Room", RHT_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_GS_METAL_FENCE] = Location::GSToken(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, RCQUEST_VANILLA, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "GS Metal Fence", "Spirit Temple GS Metal Fence", RHT_SPIRIT_TEMPLE_GS_METAL_FENCE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9736, 0x08, "MQ GS Symphony Room", "Spirit Temple MQ GS Symphony Room", RHT_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9730, 0x02, "MQ GS Leever Room", "Spirit Temple MQ GS Leever Room", RHT_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9732, 0x04, "MQ GS Nine Thrones Room West", "Spirit Temple MQ GS Nine Thrones Room West", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9744, 0x10, "MQ GS Nine Thrones Room North", "Spirit Temple MQ GS Nine Thrones Room North", RHT_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); + locationTable[RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM] = Location::GSToken(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, RCQUEST_MQ, RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, 9729, 0x01, "MQ GS Sun Block Room", "Spirit Temple MQ GS Sun Block Room", RHT_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE); // Shadow Temple - locationTable[RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "GS Single Giant Pot", "Shadow Temple GS Single Giant Pot", RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "GS Falling Spikes Room", "Shadow Temple GS Falling Spikes Room", RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "GS Triple Giant Pot", "Shadow Temple GS Triple Giant Pot", RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "GS Like Like Room", "Shadow Temple GS Like Like Room", RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_GS_NEAR_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "GS Near Ship", "Shadow Temple GS Near Ship", RHT_SHADOW_TEMPLE_GS_NEAR_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "MQ GS Falling Spikes Room", "Shadow Temple MQ GS Falling Spikes Room", RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "MQ GS Wind Hint Room", "Shadow Temple MQ GS Wind Hint Room", RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "MQ GS After Wind", "Shadow Temple MQ GS After Wind", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "MQ GS After Ship", "Shadow Temple MQ GS After Ship", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); - locationTable[RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "MQ GS Near Boss", "Shadow Temple MQ GS Near Boss", RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "GS Single Giant Pot", "Shadow Temple GS Single Giant Pot", RHT_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "GS Falling Spikes Room", "Shadow Temple GS Falling Spikes Room", RHT_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT] = Location::GSToken(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "GS Triple Giant Pot", "Shadow Temple GS Triple Giant Pot", RHT_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "GS Like Like Room", "Shadow Temple GS Like Like Room", RHT_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_GS_NEAR_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, RCQUEST_VANILLA, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "GS Near Ship", "Shadow Temple GS Near Ship", RHT_SHADOW_TEMPLE_GS_NEAR_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9986, 0x02, "MQ GS Falling Spikes Room", "Shadow Temple MQ GS Falling Spikes Room", RHT_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9985, 0x01, "MQ GS Wind Hint Room", "Shadow Temple MQ GS Wind Hint Room", RHT_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9992, 0x08, "MQ GS After Wind", "Shadow Temple MQ GS After Wind", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 10000, 0x10, "MQ GS After Ship", "Shadow Temple MQ GS After Ship", RHT_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); + locationTable[RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS] = Location::GSToken(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, RCQUEST_MQ, RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, 9988, 0x04, "MQ GS Near Boss", "Shadow Temple MQ GS Near Boss", RHT_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE); // Bottom of the Well - locationTable[RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "GS Like Like Cage", "Bottom of the Well GS Like Like Cage", RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "GS East Inner Room", "Bottom of the Well GS East Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "GS West Inner Room", "Bottom of the Well GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "MQ GS Basement", "Bottom of the Well MQ GS Basement", RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "MQ GS Coffin Room", "Bottom of the Well MQ GS Coffin Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); - locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "MQ GS West Inner Room", "Bottom of the Well MQ GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "GS Like Like Cage", "Bottom of the Well GS Like Like Cage", RHT_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "GS East Inner Room", "Bottom of the Well GS East Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "GS West Inner Room", "Bottom of the Well GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10241, 0x01, "MQ GS Basement", "Bottom of the Well MQ GS Basement", RHT_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10244, 0x04, "MQ GS Coffin Room", "Bottom of the Well MQ GS Coffin Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); + locationTable[RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM] = Location::GSToken(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, RCQUEST_MQ, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, 10242, 0x02, "MQ GS West Inner Room", "Bottom of the Well MQ GS West Inner Room", RHT_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_BOTTOM_OF_THE_WELL); // Ice Cavern - locationTable[RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "GS Push Block Room", "Ice Cavern GS Push Block Room", RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "GS Spinning Scythe Room", "Ice Cavern GS Spinning Scythe Room", RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_GS_HEART_PIECE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "GS Heart Piece Room", "Ice Cavern GS Heart Piece Room", RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_SCARECROW] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_SCARECROW, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "MQ GS Scarecrow", "Ice Cavern MQ GS Scarecrow", RHT_ICE_CAVERN_MQ_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_ICE_BLOCK] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "MQ GS Ice Block", "Ice Cavern MQ GS Ice Block", RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); - locationTable[RC_ICE_CAVERN_MQ_GS_RED_ICE] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_RED_ICE, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "MQ GS Red Ice", "Ice Cavern MQ GS Red Ice", RHT_ICE_CAVERN_MQ_GS_RED_ICE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "GS Push Block Room", "Ice Cavern GS Push Block Room", RHT_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "GS Spinning Scythe Room", "Ice Cavern GS Spinning Scythe Room", RHT_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_GS_HEART_PIECE_ROOM] = Location::GSToken(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, RCQUEST_VANILLA, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "GS Heart Piece Room", "Ice Cavern GS Heart Piece Room", RHT_ICE_CAVERN_GS_HEART_PIECE_ROOM, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_SCARECROW] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_SCARECROW, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10497, 0x01, "MQ GS Scarecrow", "Ice Cavern MQ GS Scarecrow", RHT_ICE_CAVERN_MQ_GS_SCARECROW, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_ICE_BLOCK] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10500, 0x04, "MQ GS Ice Block", "Ice Cavern MQ GS Ice Block", RHT_ICE_CAVERN_MQ_GS_ICE_BLOCK, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); + locationTable[RC_ICE_CAVERN_MQ_GS_RED_ICE] = Location::GSToken(RC_ICE_CAVERN_MQ_GS_RED_ICE, RCQUEST_MQ, RCAREA_ICE_CAVERN, SCENE_ICE_CAVERN, 10498, 0x02, "MQ GS Red Ice", "Ice Cavern MQ GS Red Ice", RHT_ICE_CAVERN_MQ_GS_RED_ICE, { Category::cSkulltula }, SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN); // Overworld - // Kokiri Forest RandomizerCheck RandomizerCheck Quest Area Scene ID params Flag Short Name Spoiler Name Hint Text Key Categories Map Index Collection Check Group - locationTable[RC_KF_GS_BEAN_PATCH] = Location::GSToken(RC_KF_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 27649, 0x01, "GS Bean Patch", "KF GS Bean Patch", RHT_KF_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_GS_KNOW_IT_ALL_HOUSE] = Location::GSToken(RC_KF_GS_KNOW_IT_ALL_HOUSE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19458, 0x02, "GS Know It All House", "KF GS Know It All House", RHT_KF_GS_KNOW_IT_ALL_HOUSE, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_GS_HOUSE_OF_TWINS] = Location::GSToken(RC_KF_GS_HOUSE_OF_TWINS, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19460, 0x04, "GS House of Twins", "KF GS House of Twins", RHT_KF_GS_HOUSE_OF_TWINS, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + // Kokiri Forest + locationTable[RC_KF_GS_BEAN_PATCH] = Location::GSToken(RC_KF_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 27649, 0x01, "GS Bean Patch", "KF GS Bean Patch", RHT_KF_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_KNOW_IT_ALL_HOUSE] = Location::GSToken(RC_KF_GS_KNOW_IT_ALL_HOUSE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19458, 0x02, "GS Know It All House", "KF GS Know It All House", RHT_KF_GS_KNOW_IT_ALL_HOUSE, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_GS_HOUSE_OF_TWINS] = Location::GSToken(RC_KF_GS_HOUSE_OF_TWINS, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 19460, 0x04, "GS House of Twins", "KF GS House of Twins", RHT_KF_GS_HOUSE_OF_TWINS, { Category::cSkulltula }, 0x0C, SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Lost Woods - locationTable[RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27905, 0x01, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_GS_BEAN_PATCH_NEAR_THEATER] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27906, 0x02, "GS Bean Patch Near Theater", "LW GS Bean Patch Near Theater", RHT_LW_GS_BEAN_PATCH_NEAR_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_LW_GS_ABOVE_THEATER] = Location::GSToken(RC_LW_GS_ABOVE_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 19716, 0x04, "GS Above Theater", "LW GS Above Theater", RHT_LW_GS_ABOVE_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_SFM_GS] = Location::GSToken(RC_SFM_GS, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 19720, 0x08, "GS", "SFM GS", RHT_SFM_GS, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27905, 0x01, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", RHT_LW_GS_BEAN_PATCH_NEAR_BRIDGE, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_BEAN_PATCH_NEAR_THEATER] = Location::GSToken(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 27906, 0x02, "GS Bean Patch Near Theater", "LW GS Bean Patch Near Theater", RHT_LW_GS_BEAN_PATCH_NEAR_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_GS_ABOVE_THEATER] = Location::GSToken(RC_LW_GS_ABOVE_THEATER, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 19716, 0x04, "GS Above Theater", "LW GS Above Theater", RHT_LW_GS_ABOVE_THEATER, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_GS] = Location::GSToken(RC_SFM_GS, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 19720, 0x08, "GS", "SFM GS", RHT_SFM_GS, { Category::cSkulltula }, 0x0D, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); // Hyrule Field - locationTable[RC_HF_GS_COW_GROTTO] = Location::GSToken(RC_HF_GS_COW_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10753, 0x01, "GS Cow Grotto", "HF GS Cow Grotto", RHT_HF_GS_COW_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_GS_NEAR_KAK_GROTTO] = Location::GSToken(RC_HF_GS_NEAR_KAK_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10754, 0x02, "GS Near Kak Grotto", "HF GS Near Kak Grotto", RHT_HF_GS_NEAR_KAK_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_GS_COW_GROTTO] = Location::GSToken(RC_HF_GS_COW_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10753, 0x01, "GS Cow Grotto", "HF GS Cow Grotto", RHT_HF_GS_COW_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_GS_NEAR_KAK_GROTTO] = Location::GSToken(RC_HF_GS_NEAR_KAK_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 10754, 0x02, "GS Near Kak Grotto", "HF GS Near Kak Grotto", RHT_HF_GS_NEAR_KAK_GROTTO, { Category::cSkulltula }, 0x0A, SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); // Lake Hylia - locationTable[RC_LH_GS_BEAN_PATCH] = Location::GSToken(RC_LH_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 29185, 0x01, "GS Bean Patch", "LH GS Bean Patch", RHT_LH_GS_BEAN_PATCH, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_SMALL_ISLAND] = Location::GSToken(RC_LH_GS_SMALL_ISLAND, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20994, 0x02, "GS Small Island", "LH GS Small Island", RHT_LH_GS_SMALL_ISLAND, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_LAB_WALL] = Location::GSToken(RC_LH_GS_LAB_WALL, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20996, 0x04, "GS Lab Wall", "LH GS Lab Wall", RHT_LH_GS_LAB_WALL, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_LAB_CRATE] = Location::GSToken(RC_LH_GS_LAB_CRATE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKESIDE_LABORATORY, -28152, 0x08, "GS Lab Crate", "LH GS Lab Crate", RHT_LH_GS_LAB_CRATE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_GS_TREE] = Location::GSToken(RC_LH_GS_TREE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 21008, 0x10, "GS Tree", "LH GS Tree", RHT_LH_GS_TREE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_BEAN_PATCH] = Location::GSToken(RC_LH_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 29185, 0x01, "GS Bean Patch", "LH GS Bean Patch", RHT_LH_GS_BEAN_PATCH, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_SMALL_ISLAND] = Location::GSToken(RC_LH_GS_SMALL_ISLAND, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20994, 0x02, "GS Small Island", "LH GS Small Island", RHT_LH_GS_SMALL_ISLAND, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_LAB_WALL] = Location::GSToken(RC_LH_GS_LAB_WALL, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 20996, 0x04, "GS Lab Wall", "LH GS Lab Wall", RHT_LH_GS_LAB_WALL, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_LAB_CRATE] = Location::GSToken(RC_LH_GS_LAB_CRATE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKESIDE_LABORATORY, -28152, 0x08, "GS Lab Crate", "LH GS Lab Crate", RHT_LH_GS_LAB_CRATE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_GS_TREE] = Location::GSToken(RC_LH_GS_TREE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 21008, 0x10, "GS Tree", "LH GS Tree", RHT_LH_GS_TREE, { Category::cSkulltula }, 0x12, SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Gerudo Valley - locationTable[RC_GV_GS_BEAN_PATCH] = Location::GSToken(RC_GV_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 29441, 0x01, "GS Bean Patch", "GV GS Bean Patch", RHT_GV_GS_BEAN_PATCH, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_SMALL_BRIDGE] = Location::GSToken(RC_GV_GS_SMALL_BRIDGE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21250, 0x02, "GS Small Bridge", "GV GS Small Bridge", RHT_GV_GS_SMALL_BRIDGE, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_PILLAR] = Location::GSToken(RC_GV_GS_PILLAR, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21252, 0x04, "GS Pillar", "GV GS Pillar", RHT_GV_GS_PILLAR, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GV_GS_BEHIND_TENT] = Location::GSToken(RC_GV_GS_BEHIND_TENT, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21256, 0x08, "GS Behind Tent", "GV GS Behind Tent", RHT_GV_GS_BEHIND_TENT, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_BEAN_PATCH] = Location::GSToken(RC_GV_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 29441, 0x01, "GS Bean Patch", "GV GS Bean Patch", RHT_GV_GS_BEAN_PATCH, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_SMALL_BRIDGE] = Location::GSToken(RC_GV_GS_SMALL_BRIDGE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21250, 0x02, "GS Small Bridge", "GV GS Small Bridge", RHT_GV_GS_SMALL_BRIDGE, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_PILLAR] = Location::GSToken(RC_GV_GS_PILLAR, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21252, 0x04, "GS Pillar", "GV GS Pillar", RHT_GV_GS_PILLAR, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GV_GS_BEHIND_TENT] = Location::GSToken(RC_GV_GS_BEHIND_TENT, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 21256, 0x08, "GS Behind Tent", "GV GS Behind Tent", RHT_GV_GS_BEHIND_TENT, { Category::cSkulltula }, 0x13, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Gerudo Fortress - locationTable[RC_GF_GS_ARCHERY_RANGE] = Location::GSToken(RC_GF_GS_ARCHERY_RANGE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21505, 0x01, "GS Archery Range", "GF GS Archery Range", RHT_GF_GS_ARCHERY_RANGE, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_GF_GS_TOP_FLOOR] = Location::GSToken(RC_GF_GS_TOP_FLOOR, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21506, 0x02, "GS Top Floor", "GF GS Top Floor", RHT_GF_GS_TOP_FLOOR, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GF_GS_ARCHERY_RANGE] = Location::GSToken(RC_GF_GS_ARCHERY_RANGE, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21505, 0x01, "GS Archery Range", "GF GS Archery Range", RHT_GF_GS_ARCHERY_RANGE, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_GF_GS_TOP_FLOOR] = Location::GSToken(RC_GF_GS_TOP_FLOOR, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_GERUDOS_FORTRESS, 21506, 0x02, "GS Top Floor", "GF GS Top Floor", RHT_GF_GS_TOP_FLOOR, { Category::cSkulltula }, 0x14, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Wasteland & Desert Colossus - locationTable[RC_WASTELAND_GS] = Location::GSToken(RC_WASTELAND_GS, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, 13570, 0x02, "GS", "Wasteland GS", RHT_WASTELAND_GS, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_BEAN_PATCH] = Location::GSToken(RC_COLOSSUS_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 29953, 0x01, "GS Bean Patch", "Colossus GS Bean Patch", RHT_COLOSSUS_GS_BEAN_PATCH, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_HILL] = Location::GSToken(RC_COLOSSUS_GS_HILL, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21764, 0x04, "GS Hill", "Colossus GS Hill", RHT_COLOSSUS_GS_HILL, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_COLOSSUS_GS_TREE] = Location::GSToken(RC_COLOSSUS_GS_TREE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21768, 0x08, "GS Tree", "Colossus GS Tree", RHT_COLOSSUS_GS_TREE, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_WASTELAND_GS] = Location::GSToken(RC_WASTELAND_GS, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, 13570, 0x02, "GS", "Wasteland GS", RHT_WASTELAND_GS, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_BEAN_PATCH] = Location::GSToken(RC_COLOSSUS_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 29953, 0x01, "GS Bean Patch", "Colossus GS Bean Patch", RHT_COLOSSUS_GS_BEAN_PATCH, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_HILL] = Location::GSToken(RC_COLOSSUS_GS_HILL, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21764, 0x04, "GS Hill", "Colossus GS Hill", RHT_COLOSSUS_GS_HILL, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GS_TREE] = Location::GSToken(RC_COLOSSUS_GS_TREE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 21768, 0x08, "GS Tree", "Colossus GS Tree", RHT_COLOSSUS_GS_TREE, { Category::cSkulltula }, 0x15, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); // Hyrule Castle, Market, and Outside Ganon's Castle - locationTable[RC_OGC_GS] = Location::GSToken(RC_OGC_GS, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE,11777, 0x01, "OGC GS", "OGC GS", RHT_OGC_GS, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_HC_GS_STORMS_GROTTO] = Location::GSToken(RC_HC_GS_STORMS_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 11778, 0x02, "GS Storms Grotto", "HC GS Storms Grotto", RHT_HC_GS_STORMS_GROTTO, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_HC_GS_TREE] = Location::GSToken(RC_HC_GS_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, -29180, 0x04, "GS Tree", "HC GS Tree", RHT_HC_GS_TREE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_GS_GUARD_HOUSE] = Location::GSToken(RC_MARKET_GS_GUARD_HOUSE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, -29176, 0x08, "Market GS Guard House", "Market GS Guard House", RHT_MARKET_GS_GUARD_HOUSE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_OGC_GS] = Location::GSToken(RC_OGC_GS, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, 11777, 0x01, "OGC GS", "OGC GS", RHT_OGC_GS, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_HC_GS_STORMS_GROTTO] = Location::GSToken(RC_HC_GS_STORMS_GROTTO, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 11778, 0x02, "GS Storms Grotto", "HC GS Storms Grotto", RHT_HC_GS_STORMS_GROTTO, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_HC_GS_TREE] = Location::GSToken(RC_HC_GS_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, -29180, 0x04, "GS Tree", "HC GS Tree", RHT_HC_GS_TREE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_GS_GUARD_HOUSE] = Location::GSToken(RC_MARKET_GS_GUARD_HOUSE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, -29176, 0x08, "Market GS Guard House", "Market GS Guard House", RHT_MARKET_GS_GUARD_HOUSE, { Category::cSkulltula }, 0x0E, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Kakariko - locationTable[RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = Location::GSToken(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20488, 0x08, "GS House Under Construction", "Kak GS House Under Construction", RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_SKULLTULA_HOUSE] = Location::GSToken(RC_KAK_GS_SKULLTULA_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20496, 0x10, "GS Skulltula House", "Kak GS Skulltula House", RHT_KAK_GS_SKULLTULA_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_GUARDS_HOUSE] = Location::GSToken(RC_KAK_GS_GUARDS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20482, 0x02, "GS Guards House", "Kak GS Guards House", RHT_KAK_GS_GUARDS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_TREE] = Location::GSToken(RC_KAK_GS_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, -28640, 0x20, "GS Tree", "Kak GS Tree", RHT_KAK_GS_TREE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_WATCHTOWER] = Location::GSToken(RC_KAK_GS_WATCHTOWER, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20484, 0x04, "GS Watchtower", "Kak GS Watchtower", RHT_KAK_GS_WATCHTOWER, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_GS_ABOVE_IMPAS_HOUSE] = Location::GSToken(RC_KAK_GS_ABOVE_IMPAS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20544, 0x40, "GS Above Impas House", "Kak GS Above Impas House", RHT_KAK_GS_ABOVE_IMPAS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION] = Location::GSToken(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20488, 0x08, "GS House Under Construction", "Kak GS House Under Construction", RHT_KAK_GS_HOUSE_UNDER_CONSTRUCTION, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_SKULLTULA_HOUSE] = Location::GSToken(RC_KAK_GS_SKULLTULA_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20496, 0x10, "GS Skulltula House", "Kak GS Skulltula House", RHT_KAK_GS_SKULLTULA_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_GUARDS_HOUSE] = Location::GSToken(RC_KAK_GS_GUARDS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20482, 0x02, "GS Guards House", "Kak GS Guards House", RHT_KAK_GS_GUARDS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_TREE] = Location::GSToken(RC_KAK_GS_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, -28640, 0x20, "GS Tree", "Kak GS Tree", RHT_KAK_GS_TREE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_WATCHTOWER] = Location::GSToken(RC_KAK_GS_WATCHTOWER, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20484, 0x04, "GS Watchtower", "Kak GS Watchtower", RHT_KAK_GS_WATCHTOWER, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_GS_ABOVE_IMPAS_HOUSE] = Location::GSToken(RC_KAK_GS_ABOVE_IMPAS_HOUSE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, 20544, 0x40, "GS Above Impas House", "Kak GS Above Impas House", RHT_KAK_GS_ABOVE_IMPAS_HOUSE, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Graveyard - locationTable[RC_GRAVEYARD_GS_WALL] = Location::GSToken(RC_GRAVEYARD_GS_WALL, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 20608, 0x80, "GS Wall", "Graveyard GS Wall", RHT_GRAVEYARD_GS_WALL, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_GRAVEYARD_GS_BEAN_PATCH] = Location::GSToken(RC_GRAVEYARD_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 28673, 0x01, "GS Bean Patch", "Graveyard GS Bean Patch", RHT_GRAVEYARD_GS_BEAN_PATCH, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_GS_WALL] = Location::GSToken(RC_GRAVEYARD_GS_WALL, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 20608, 0x80, "GS Wall", "Graveyard GS Wall", RHT_GRAVEYARD_GS_WALL, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_GRAVEYARD_GS_BEAN_PATCH] = Location::GSToken(RC_GRAVEYARD_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 28673, 0x01, "GS Bean Patch", "Graveyard GS Bean Patch", RHT_GRAVEYARD_GS_BEAN_PATCH, { Category::cSkulltula }, 0x10, SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Death Mountain - locationTable[RC_DMC_GS_BEAN_PATCH] = Location::GSToken(RC_DMC_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER,28417, 0x01, "GS Bean Patch", "DMC GS Bean Patch", RHT_DMC_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_GS_CRATE] = Location::GSToken(RC_DMC_GS_CRATE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER,-28800, 0x80, "GS Crate", "DMC GS Crate", RHT_DMC_GS_CRATE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_BEAN_PATCH] = Location::GSToken(RC_DMT_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 28418, 0x02, "GS Bean Patch", "DMT GS Bean Patch", RHT_DMT_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_NEAR_KAK] = Location::GSToken(RC_DMT_GS_NEAR_KAK, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 12036, 0x04, "GS Near Kak", "DMT GS Near Kak", RHT_DMT_GS_NEAR_KAK, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_ABOVE_DODONGOS_CAVERN] = Location::GSToken(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20232, 0x08, "GS Above Dodongos Cavern", "DMT GS Above Dodongos Cavern", RHT_DMT_GS_ABOVE_DODONGOS_CAVERN, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMT_GS_FALLING_ROCKS_PATH] = Location::GSToken(RC_DMT_GS_FALLING_ROCKS_PATH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20240, 0x10, "GS Falling Rocks Path", "DMT GS Falling Rocks Path", RHT_DMT_GS_FALLING_ROCKS_PATH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GC_GS_CENTER_PLATFORM] = Location::GSToken(RC_GC_GS_CENTER_PLATFORM, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 12064, 0x20, "GS Center Platform", "GC GS Center Platform", RHT_GC_GS_CENTER_PLATFORM, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_GS_BOULDER_MAZE] = Location::GSToken(RC_GC_GS_BOULDER_MAZE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, -28864, 0x40, "GS Boulder Maze", "GC GS Boulder Maze", RHT_GC_GS_BOULDER_MAZE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_DMC_GS_BEAN_PATCH] = Location::GSToken(RC_DMC_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 28417, 0x01, "GS Bean Patch", "DMC GS Bean Patch", RHT_DMC_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_GS_CRATE] = Location::GSToken(RC_DMC_GS_CRATE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, -28800, 0x80, "GS Crate", "DMC GS Crate", RHT_DMC_GS_CRATE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_BEAN_PATCH] = Location::GSToken(RC_DMT_GS_BEAN_PATCH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 28418, 0x02, "GS Bean Patch", "DMT GS Bean Patch", RHT_DMT_GS_BEAN_PATCH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_NEAR_KAK] = Location::GSToken(RC_DMT_GS_NEAR_KAK, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 12036, 0x04, "GS Near Kak", "DMT GS Near Kak", RHT_DMT_GS_NEAR_KAK, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_ABOVE_DODONGOS_CAVERN] = Location::GSToken(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20232, 0x08, "GS Above Dodongos Cavern", "DMT GS Above Dodongos Cavern", RHT_DMT_GS_ABOVE_DODONGOS_CAVERN, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_GS_FALLING_ROCKS_PATH] = Location::GSToken(RC_DMT_GS_FALLING_ROCKS_PATH, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 20240, 0x10, "GS Falling Rocks Path", "DMT GS Falling Rocks Path", RHT_DMT_GS_FALLING_ROCKS_PATH, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GC_GS_CENTER_PLATFORM] = Location::GSToken(RC_GC_GS_CENTER_PLATFORM, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 12064, 0x20, "GS Center Platform", "GC GS Center Platform", RHT_GC_GS_CENTER_PLATFORM, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_GS_BOULDER_MAZE] = Location::GSToken(RC_GC_GS_BOULDER_MAZE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, -28864, 0x40, "GS Boulder Maze", "GC GS Boulder Maze", RHT_GC_GS_BOULDER_MAZE, { Category::cSkulltula }, 0x0F, SpoilerCollectionCheckGroup::GROUP_GORON_CITY); // Zora's River, Domain, and Fountain - locationTable[RC_ZR_GS_LADDER] = Location::GSToken(RC_ZR_GS_LADDER, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20737, 0x01, "GS Ladder", "ZR GS Ladder", RHT_ZR_GS_LADDER, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_TREE] = Location::GSToken(RC_ZR_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, -28414, 0x02, "GS Tree", "ZR GS Tree", RHT_ZR_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_ABOVE_BRIDGE] = Location::GSToken(RC_ZR_GS_ABOVE_BRIDGE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20744, 0x08, "GS Above Bridge", "ZR GS Above Bridge", RHT_ZR_GS_ABOVE_BRIDGE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZR_GS_NEAR_RAISED_GROTTOS] = Location::GSToken(RC_ZR_GS_NEAR_RAISED_GROTTOS, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20752, 0x10, "GS Near Raised Grottos", "ZR GS Near Raised Grottos", RHT_ZR_GS_NEAR_RAISED_GROTTOS, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); - locationTable[RC_ZD_GS_FROZEN_WATERFALL] = Location::GSToken(RC_ZD_GS_FROZEN_WATERFALL, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 20800, 0x40, "GS Frozen Waterfall", "ZD GS Frozen Waterfall", RHT_ZD_GS_FROZEN_WATERFALL, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_ABOVE_THE_LOG] = Location::GSToken(RC_ZF_GS_ABOVE_THE_LOG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20740, 0x04, "GS Above The Log", "ZF GS Above The Log", RHT_ZF_GS_ABOVE_THE_LOG, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_HIDDEN_CAVE] = Location::GSToken(RC_ZF_GS_HIDDEN_CAVE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20768, 0x20, "GS Hidden Cave", "ZF GS Hidden Cave", RHT_ZF_GS_HIDDEN_CAVE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZF_GS_TREE] = Location::GSToken(RC_ZF_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, -28288, 0x80, "GS Tree", "ZF GS Tree", RHT_ZF_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZR_GS_LADDER] = Location::GSToken(RC_ZR_GS_LADDER, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20737, 0x01, "GS Ladder", "ZR GS Ladder", RHT_ZR_GS_LADDER, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_TREE] = Location::GSToken(RC_ZR_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, -28414, 0x02, "GS Tree", "ZR GS Tree", RHT_ZR_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_ABOVE_BRIDGE] = Location::GSToken(RC_ZR_GS_ABOVE_BRIDGE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20744, 0x08, "GS Above Bridge", "ZR GS Above Bridge", RHT_ZR_GS_ABOVE_BRIDGE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_GS_NEAR_RAISED_GROTTOS] = Location::GSToken(RC_ZR_GS_NEAR_RAISED_GROTTOS, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 20752, 0x10, "GS Near Raised Grottos", "ZR GS Near Raised Grottos", RHT_ZR_GS_NEAR_RAISED_GROTTOS, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZD_GS_FROZEN_WATERFALL] = Location::GSToken(RC_ZD_GS_FROZEN_WATERFALL, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 20800, 0x40, "GS Frozen Waterfall", "ZD GS Frozen Waterfall", RHT_ZD_GS_FROZEN_WATERFALL, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_ABOVE_THE_LOG] = Location::GSToken(RC_ZF_GS_ABOVE_THE_LOG, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20740, 0x04, "GS Above The Log", "ZF GS Above The Log", RHT_ZF_GS_ABOVE_THE_LOG, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_HIDDEN_CAVE] = Location::GSToken(RC_ZF_GS_HIDDEN_CAVE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 20768, 0x20, "GS Hidden Cave", "ZF GS Hidden Cave", RHT_ZF_GS_HIDDEN_CAVE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZF_GS_TREE] = Location::GSToken(RC_ZF_GS_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, -28288, 0x80, "GS Tree", "ZF GS Tree", RHT_ZF_GS_TREE, { Category::cSkulltula }, 0x11, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Lon Lon Ranch - locationTable[RC_LLR_GS_BACK_WALL] = Location::GSToken(RC_LLR_GS_BACK_WALL, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11009, 0x01, "GS Back Wall", "LLR GS Back Wall", RHT_LLR_GS_BACK_WALL, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_RAIN_SHED] = Location::GSToken(RC_LLR_GS_RAIN_SHED, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11010, 0x02, "GS Rain Shed", "LLR GS Rain Shed", RHT_LLR_GS_RAIN_SHED, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_HOUSE_WINDOW] = Location::GSToken(RC_LLR_GS_HOUSE_WINDOW, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11012, 0x04, "GS House Window", "LLR GS House Window", RHT_LLR_GS_HOUSE_WINDOW, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_GS_TREE] = Location::GSToken(RC_LLR_GS_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, -29944, 0x08, "GS Tree", "LLR GS Tree", RHT_LLR_GS_TREE, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_BACK_WALL] = Location::GSToken(RC_LLR_GS_BACK_WALL, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11009, 0x01, "GS Back Wall", "LLR GS Back Wall", RHT_LLR_GS_BACK_WALL, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_RAIN_SHED] = Location::GSToken(RC_LLR_GS_RAIN_SHED, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11010, 0x02, "GS Rain Shed", "LLR GS Rain Shed", RHT_LLR_GS_RAIN_SHED, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_HOUSE_WINDOW] = Location::GSToken(RC_LLR_GS_HOUSE_WINDOW, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, 11012, 0x04, "GS House Window", "LLR GS House Window", RHT_LLR_GS_HOUSE_WINDOW, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_GS_TREE] = Location::GSToken(RC_LLR_GS_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, -29944, 0x08, "GS Tree", "LLR GS Tree", RHT_LLR_GS_TREE, { Category::cSkulltula }, 0x0B, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - // Bosses Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::AlwaysCollected(), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); - locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::Chest(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::Chest(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::Chest(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::Chest(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); - locationTable[RC_GIFT_FROM_SAGES] = Location::Reward(RC_GIFT_FROM_SAGES, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Gift from Raoru", "Gift from Raoru", RHT_NONE, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true); + // Bosses + locationTable[RC_LINKS_POCKET] = Location::Reward(RC_LINKS_POCKET, RCQUEST_BOTH, RCTYPE_LINKS_POCKET, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Link's Pocket", "Link's Pocket", RHT_LINKS_POCKET, RG_NONE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LINKS_POCKET), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, true); + locationTable[RC_QUEEN_GOHMA] = Location::Reward(RC_QUEEN_GOHMA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DEKU_TREE, ACTOR_DOOR_WARP1, SCENE_DEKU_TREE_BOSS, 0x00, DungeonId::DUNGEON_DEKU_TREE, "Queen Gohma", "Queen Gohma", RHT_QUEEN_GOHMA, RG_KOKIRI_EMERALD, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_KING_DODONGO] = Location::Reward(RC_KING_DODONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_DOOR_WARP1, SCENE_DODONGOS_CAVERN_BOSS, 0x00, DungeonId::DUNGEON_DODONGOS_CAVERN, "King Dodongo", "King Dodongo", RHT_KING_DODONGO, RG_GORON_RUBY, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_BARINADE] = Location::Reward(RC_BARINADE, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_DOOR_WARP1, SCENE_JABU_JABU_BOSS, 0x00, DungeonId::DUNGEON_JABUJABUS_BELLY, "Barinade", "Barinade", RHT_BARINADE, RG_ZORA_SAPPHIRE, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_PHANTOM_GANON] = Location::Reward(RC_PHANTOM_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FOREST_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FOREST_TEMPLE, "Phantom Ganon", "Phantom Ganon", RHT_PHANTOM_GANON, RG_FOREST_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_VOLVAGIA] = Location::Reward(RC_VOLVAGIA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_DOOR_WARP1, SCENE_FIRE_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_FIRE_TEMPLE, "Volvagia", "Volvagia", RHT_VOLVAGIA, RG_FIRE_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_MORPHA] = Location::Reward(RC_MORPHA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_WATER_TEMPLE, ACTOR_DOOR_WARP1, SCENE_WATER_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_WATER_TEMPLE, "Morpha", "Morpha", RHT_MORPHA, RG_WATER_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_TWINROVA] = Location::Reward(RC_TWINROVA, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SPIRIT_TEMPLE, "Twinrova", "Twinrova", RHT_TWINROVA, RG_SPIRIT_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_BONGO_BONGO] = Location::Reward(RC_BONGO_BONGO, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_DOOR_WARP1, SCENE_SHADOW_TEMPLE_BOSS, 0x00, DungeonId::DUNGEON_SHADOW_TEMPLE, "Bongo Bongo", "Bongo Bongo", RHT_BONGO_BONGO, RG_SHADOW_MEDALLION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + locationTable[RC_GANON] = Location::Reward(RC_GANON, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_GANONS_CASTLE, ACTOR_DOOR_WARP1, SCENE_GANON_BOSS, 0x00, DungeonId::DUNGEON_GANONS_CASTLE_CRUMBLING, "Ganon", "Ganon", RHT_NONE, RG_TRIFORCE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE); + locationTable[RC_GIFT_FROM_SAGES] = Location::Reward(RC_GIFT_FROM_SAGES, RCQUEST_BOTH, RCTYPE_DUNGEON_REWARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Gift from Raoru", "Gift from Raoru", RHT_NONE, RG_LIGHT_MEDALLION, {}, SpoilerCollectionCheck::EventChkInf(0xC9), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true); - // Heart Containers Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_DEKU_TREE_QUEEN_GOHMA_HEART] = Location::Base(RC_DEKU_TREE_QUEEN_GOHMA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DEKU_TREE, ACTOR_ITEM_B_HEART, SCENE_DEKU_TREE_BOSS, 0x00, 0x4F, "Queen Gohma Heart Container", "Deku Tree Queen Gohma Heart Container", RHT_DEKU_TREE_QUEEN_GOHMA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); - locationTable[RC_DODONGOS_CAVERN_KING_DODONGO_HEART] = Location::Base(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_ITEM_B_HEART, SCENE_DODONGOS_CAVERN_BOSS, 0x00, 0x4F, "King Dodongo Heart Container", "Dodongos Cavern King Dodongo Heart Container", RHT_DODONGOS_CAVERN_KING_DODONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); - locationTable[RC_JABU_JABUS_BELLY_BARINADE_HEART] = Location::Base(RC_JABU_JABUS_BELLY_BARINADE_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_ITEM_B_HEART, SCENE_JABU_JABU_BOSS, 0x00, 0x4F, "Barinade Heart Container", "Jabu Jabus Belly Barinade Heart Container", RHT_JABU_JABUS_BELLY_BARINADE_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); - locationTable[RC_FOREST_TEMPLE_PHANTOM_GANON_HEART] = Location::Base(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FOREST_TEMPLE_BOSS, 0x00, 0x4F, "Phantom Ganon Heart Container", "Forest Temple Phantom Ganon Heart Container", RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); - locationTable[RC_FIRE_TEMPLE_VOLVAGIA_HEART] = Location::Base(RC_FIRE_TEMPLE_VOLVAGIA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FIRE_TEMPLE_BOSS, 0x00, 0x4F, "Volvagia Heart Container", "Fire Temple Volvagia Heart Container", RHT_FIRE_TEMPLE_VOLVAGIA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); - locationTable[RC_WATER_TEMPLE_MORPHA_HEART] = Location::Base(RC_WATER_TEMPLE_MORPHA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_WATER_TEMPLE_BOSS, 0x00, 0x4F, "Morpha Heart Container", "Water Temple Morpha Heart Container", RHT_WATER_TEMPLE_MORPHA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); - locationTable[RC_SPIRIT_TEMPLE_TWINROVA_HEART] = Location::Base(RC_SPIRIT_TEMPLE_TWINROVA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, 0x4F, "Twinrova Heart Container", "Spirit Temple Twinrova Heart Container", RHT_SPIRIT_TEMPLE_TWINROVA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); - locationTable[RC_SHADOW_TEMPLE_BONGO_BONGO_HEART] = Location::Base(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SHADOW_TEMPLE_BOSS, 0x00, 0x4F, "Bongo Bongo Heart Container", "Shadow Temple Bongo Bongo Heart Container", RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); + // Heart Containers + locationTable[RC_DEKU_TREE_QUEEN_GOHMA_HEART] = Location::Base(RC_DEKU_TREE_QUEEN_GOHMA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DEKU_TREE, ACTOR_ITEM_B_HEART, SCENE_DEKU_TREE_BOSS, 0x00, 0x4F, "Queen Gohma Heart Container", "Deku Tree Queen Gohma Heart Container", RHT_DEKU_TREE_QUEEN_GOHMA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x11, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DEKU_TREE, true); + locationTable[RC_DODONGOS_CAVERN_KING_DODONGO_HEART] = Location::Base(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_DODONGOS_CAVERN, ACTOR_ITEM_B_HEART, SCENE_DODONGOS_CAVERN_BOSS, 0x00, 0x4F, "King Dodongo Heart Container", "Dodongos Cavern King Dodongo Heart Container", RHT_DODONGOS_CAVERN_KING_DODONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x12, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_DODONGOS_CAVERN, true); + locationTable[RC_JABU_JABUS_BELLY_BARINADE_HEART] = Location::Base(RC_JABU_JABUS_BELLY_BARINADE_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_JABU_JABUS_BELLY, ACTOR_ITEM_B_HEART, SCENE_JABU_JABU_BOSS, 0x00, 0x4F, "Barinade Heart Container", "Jabu Jabus Belly Barinade Heart Container", RHT_JABU_JABUS_BELLY_BARINADE_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x13, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY, true); + locationTable[RC_FOREST_TEMPLE_PHANTOM_GANON_HEART] = Location::Base(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FOREST_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FOREST_TEMPLE_BOSS, 0x00, 0x4F, "Phantom Ganon Heart Container", "Forest Temple Phantom Ganon Heart Container", RHT_FOREST_TEMPLE_PHANTOM_GANON_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x14, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FOREST_TEMPLE, true); + locationTable[RC_FIRE_TEMPLE_VOLVAGIA_HEART] = Location::Base(RC_FIRE_TEMPLE_VOLVAGIA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_FIRE_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_FIRE_TEMPLE_BOSS, 0x00, 0x4F, "Volvagia Heart Container", "Fire Temple Volvagia Heart Container", RHT_FIRE_TEMPLE_VOLVAGIA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x15, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_FIRE_TEMPLE, true); + locationTable[RC_WATER_TEMPLE_MORPHA_HEART] = Location::Base(RC_WATER_TEMPLE_MORPHA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_WATER_TEMPLE_BOSS, 0x00, 0x4F, "Morpha Heart Container", "Water Temple Morpha Heart Container", RHT_WATER_TEMPLE_MORPHA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x16, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WATER_TEMPLE, true); + locationTable[RC_SPIRIT_TEMPLE_TWINROVA_HEART] = Location::Base(RC_SPIRIT_TEMPLE_TWINROVA_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SPIRIT_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SPIRIT_TEMPLE_BOSS, 0x00, 0x4F, "Twinrova Heart Container", "Spirit Temple Twinrova Heart Container", RHT_SPIRIT_TEMPLE_TWINROVA_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x17, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SPIRIT_TEMPLE, true); + locationTable[RC_SHADOW_TEMPLE_BONGO_BONGO_HEART] = Location::Base(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, RCQUEST_BOTH, RCTYPE_BOSS_HEART_OR_OTHER_REWARD, RCAREA_SHADOW_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_SHADOW_TEMPLE_BOSS, 0x00, 0x4F, "Bongo Bongo Heart Container", "Shadow Temple Bongo Bongo Heart Container", RHT_SHADOW_TEMPLE_BONGO_BONGO_HEART, RG_HEART_CONTAINER, { Category::cSongDungeonReward }, SpoilerCollectionCheck::Collectable(0x18, 0x1F), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SHADOW_TEMPLE, true); - // Cutscenes Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::MasterSword(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::Chest(0x43, 0x1E), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", "LW Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::Chest(0x3D, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); - locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x02), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::Chest(0x3D, 0x03), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x01), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::Chest(0x3B, 0x02), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::Chest(0x3B, 0x03), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); + // Cutscenes + locationTable[RC_TOT_MASTER_SWORD] = Location::Delayed(RC_TOT_MASTER_SWORD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "ToT Master Sword", "ToT Master Sword", RHT_TOT_MASTER_SWORD, RG_MASTER_SWORD, {}, SpoilerCollectionCheck::EventChkInf(0x45), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_TOT_LIGHT_ARROWS_CUTSCENE] = Location::Delayed(RC_TOT_LIGHT_ARROWS_CUTSCENE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x01, "ToT Light Arrow Cutscene", "ToT Light Arrow Cutscene", RHT_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS, {}, SpoilerCollectionCheck::EventChkInf(0xC4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_LW_GIFT_FROM_SARIA] = Location::Delayed(RC_LW_GIFT_FROM_SARIA, RCQUEST_BOTH, RCTYPE_OCARINA, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_LOST_WOODS, 0x00, 0x02, "Gift From Saria", "LW Gift From Saria", RHT_LW_GIFT_FROM_SARIA, RG_PROGRESSIVE_OCARINA, {}, SpoilerCollectionCheck::EventChkInf(0xC1), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_ZF_GREAT_FAIRY_REWARD] = Location::Delayed(RC_ZF_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_ZORAS_FOUNTAIN, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 1, 0x10, "Great Fairy Reward", "ZF Great Fairy Reward", RHT_ZF_GREAT_FAIRY_REWARD, RG_FARORES_WIND, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, true); + locationTable[RC_HC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_HC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 2, 0x11, "Great Fairy Reward", "HC Great Fairy Reward", RHT_HC_GREAT_FAIRY_REWARD, RG_DINS_FIRE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_COLOSSUS_GREAT_FAIRY_REWARD] = Location::Delayed(RC_COLOSSUS_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DESERT_COLOSSUS, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 3, 0x12, "Great Fairy Reward", "Colossus Great Fairy Reward", RHT_COLOSSUS_GREAT_FAIRY_REWARD, RG_NAYRUS_LOVE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_DMT_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMT_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 1, 0x13, "Great Fairy Reward", "DMT Great Fairy Reward", RHT_DMT_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_DMC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_DMC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 2, 0x14, "Great Fairy Reward", "DMC Great Fairy Reward", RHT_DMC_GREAT_FAIRY_REWARD, RG_PROGRESSIVE_MAGIC_METER, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_OGC_GREAT_FAIRY_REWARD] = Location::Delayed(RC_OGC_GREAT_FAIRY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_HYRULE_CASTLE, ACTOR_BG_DY_YOSEIZO, SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 3, 0x15, "OGC Great Fairy Reward", "OGC Great Fairy Reward", RHT_OGC_GREAT_FAIRY_REWARD, RG_DOUBLE_DEFENSE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_OGC_GREAT_FAIRY_REWARD), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GANONS_CASTLE, true); - // Songs Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); - locationTable[RC_SHEIK_IN_CRATER] = Location::Delayed(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x21, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x51), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); - locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Delayed(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_ICE_CAVERN, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, 0x22, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x52), SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); - locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Delayed(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DESERT_COLOSSUS, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, 0x23, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAC), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); - locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Delayed(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x24, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_SHEIK_AT_TEMPLE] = Location::Delayed(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x25, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, { Category::cSong }, SpoilerCollectionCheck::Chest(0x43, 0x1F), 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::Chest(0x63, 0x1F), 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::Chest(0x56, 0x1F), 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::Chest(0x41, 0x1F), 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::Chest(0x51, 0x1F), 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(0x5B), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + // Songs + locationTable[RC_SHEIK_IN_FOREST] = Location::Delayed(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_SACRED_FOREST_MEADOW, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, 0x20, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x50), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, true); + locationTable[RC_SHEIK_IN_CRATER] = Location::Delayed(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x21, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x51), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, true); + locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Delayed(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_ICE_CAVERN, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, 0x22, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, { Category::cSong, Category::cSongDungeonReward }, SpoilerCollectionCheck::EventChkInf(0x52), SpoilerCollectionCheckGroup::GROUP_DUNGEON_ICE_CAVERN, true); + locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Delayed(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_DESERT_COLOSSUS, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, 0x23, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAC), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, true); + locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Delayed(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x24, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0xAA), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_SHEIK_AT_TEMPLE] = Location::Delayed(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x25, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, { Category::cSong }, SpoilerCollectionCheck::EventChkInf(0x55), 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_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(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_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); - //Beehives Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group Vanilla Progression - locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", "KF Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, false); - locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), 0x00, "Storms Grotto Beehive Right", "KF Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST, false); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), 0x00, "Near Shortcuts Grotto Beehive Left", "LW Near Shortcuts Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), 0x00, "Near Shortcuts Grotto Beehive Right", "LW Near Shortcuts Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), 0x00, "Deku Scrub Grotto Beehive", "LW Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), 0x00, "Storms Grotto Beehive", "SFM Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS, false); - locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), 0x00, "Near Market Grotto Beehive Left", "HF Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), 0x00, "Near Market Grotto Beehive Right", "HF Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), 0x00, "Open Grotto Beehive Left", "HF Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), 0x00, "Open Grotto Beehive Right", "HF Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), 0x00, "Southeast Grotto Beehive Left", "HF Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), 0x00, "Southeast Grotto Beehive Right", "HF Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), 0x00, "Inside Fence Grotto Beehive", "HF Inside Fence Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD, false); - locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), 0x00, "Grotto Beehive", "LLR Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH, false); - locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), 0x00, "Open Grotto Beehive Left", "Kak Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, false); - locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), 0x00, "Open Grotto Beehive Right", "Kak Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, false); - locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), 0x00, "Cow Grotto Beehive", "DMT Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), 0x00, "Storms Grotto Beehive Left", "DMT Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), 0x00, "Storms Grotto Beehive Right", "DMT Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), 0x00, "Grotto Beehive", "GC Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY, false); - locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), 0x00, "Upper Grotto Beehive Left", "DMC Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), 0x00, "Upper Grotto Beehive Right", "DMC Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), 0x00, "Hammer Grotto Beehive", "DMC Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN, false); - locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), 0x00, "Open Grotto Beehive Left", "ZR Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, false); - locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), 0x00, "Open Grotto Beehive Right", "ZR Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, false); - locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), 0x00, "Storms Grotto Beehive", "ZR Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER, false); - locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), 0x00, "In Front of King Zora Beehive Left", "ZD In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, false); - locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), 0x00, "In Front of King Zora Beehive Right", "ZD In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, false); - locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), 0x00, "Behind King Zora Beehive", "ZD Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN, false); - locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), 0x00, "Grotto Beehive", "LH Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA, false); - locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), 0x00, "Deku Scrub Grotto Beehive", "GV Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, false); - locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), 0x00, "Grotto Beehive", "Colossus Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, {Category::cBeehive}, SpoilerCollectionCheck::RandomizerInf(0, 0), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY, false); + //Beehives + locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x2C), 0x00, "Storms Grotto Beehive Left", "KF Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KF_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KOKIRI_FOREST, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x2C), 0x00, "Storms Grotto Beehive Right", "KF Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x14), 0x00, "Near Shortcuts Grotto Beehive Left", "LW Near Shortcuts Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x14), 0x00, "Near Shortcuts Grotto Beehive Right", "LW Near Shortcuts Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LOST_WOODS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(747, 0xF5), 0x00, "Deku Scrub Grotto Beehive", "LW Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LW_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_SFM_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_SFM_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_SACRED_FOREST_MEADOW, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEE), 0x00, "Storms Grotto Beehive", "SFM Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_SFM_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x00), 0x00, "Near Market Grotto Beehive Left", "HF Near Market Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x00), 0x00, "Near Market Grotto Beehive Right", "HF Near Market Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_NEAR_MARKET_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x03), 0x00, "Open Grotto Beehive Left", "HF Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x03), 0x00, "Open Grotto Beehive Right", "HF Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x22), 0x00, "Southeast Grotto Beehive Left", "HF Southeast Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_HF_SOUTHEAST_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x22), 0x00, "Southeast Grotto Beehive Right", "HF Southeast Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_SOUTHEAST_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE] = Location::Base(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_HYRULE_FIELD, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1410, 0xE6), 0x00, "Inside Fence Grotto Beehive", "HF Inside Fence Grotto Beehive", RHT_BEEHIVE_LONELY_SCRUB_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_HF_INSIDE_FENCE_GROTTO), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_LLR_GROTTO_BEEHIVE] = Location::Base(RC_LLR_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LON_LON_RANCH, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFC), 0x00, "Grotto Beehive", "LLR Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LLR_GROTTO), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x28), 0x00, "Open Grotto Beehive Left", "Kak Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_KAK_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_KAKARIKO_VILLAGE, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x28), 0x00, "Open Grotto Beehive Right", "Kak Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_KAK_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_COW_GROTTO_BEEHIVE] = Location::Base(RC_DMT_COW_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2617, 0xF8), 0x00, "Cow Grotto Beehive", "DMT Cow Grotto Beehive", RHT_BEEHIVE_COW_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_COW_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x57), 0x00, "Storms Grotto Beehive Left", "DMT Storms Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMT_STORMS_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x57), 0x00, "Storms Grotto Beehive Right", "DMT Storms Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMT_STORMS_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GC_GROTTO_BEEHIVE] = Location::Base(RC_GC_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GORON_CITY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xFB), 0x00, "Grotto Beehive", "GC Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GC_GROTTO), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x7A), 0x00, "Upper Grotto Beehive Left", "DMC Upper Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_DMC_UPPER_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x7A), 0x00, "Upper Grotto Beehive Right", "DMC Upper Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_UPPER_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_HAMMER_GROTTO_BEEHIVE] = Location::Base(RC_DMC_HAMMER_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xF9), 0x00, "Hammer Grotto Beehive", "DMC Hammer Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_DMC_HAMMER_GROTTO), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(-144, 0x29), 0x00, "Open Grotto Beehive Left", "ZR Open Grotto Beehive Left", RHT_BEEHIVE_CHEST_GROTTO, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT] = Location::Base(RC_ZR_OPEN_GROTTO_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(121, 0x29), 0x00, "Open Grotto Beehive Right", "ZR Open Grotto Beehive Right", RHT_BEEHIVE_CHEST_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_OPEN_GROTTO_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZR_STORMS_GROTTO_BEEHIVE] = Location::Base(RC_ZR_STORMS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_RIVER, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xEB), 0x00, "Storms Grotto Beehive", "ZR Storms Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZR_STORMS_GROTTO), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_LEFT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(382, 0x00), 0x00, "In Front of King Zora Beehive Left", "ZD In Front of King Zora Beehive Left", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_BLUE_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_LEFT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT] = Location::Base(RC_ZD_IN_FRONT_OF_KING_ZORA_BEEHIVE_RIGHT, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(948, 0x00), 0x00, "In Front of King Zora Beehive Right", "ZD In Front of King Zora Beehive Right", RHT_BEEHIVE_IN_FRONT_OF_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_IN_FRONT_OF_KING_ZORA_RIGHT), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_BEHIND_KING_ZORA_BEEHIVE] = Location::Base(RC_ZD_BEHIND_KING_ZORA_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_ZORAS_DOMAIN, ACTOR_OBJ_COMB, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(701, 0x00), 0x00, "Behind King Zora Beehive", "ZD Behind King Zora Beehive", RHT_BEEHIVE_BEHIND_KING_ZORA, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_ZD_BEHIND_KING_ZORA), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_LH_GROTTO_BEEHIVE] = Location::Base(RC_LH_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_LAKE_HYLIA, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(5144, 0xEF), 0x00, "Grotto Beehive", "LH Grotto Beehive", RHT_BEEHIVE_SCRUB_TRIO_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_LH_GROTTO), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE] = Location::Base(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_GERUDO_VALLEY, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xF0), 0x00, "Deku Scrub Grotto Beehive", "GV Deku Scrub Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_GV_DEKU_SCRUB_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_COLOSSUS_GROTTO_BEEHIVE] = Location::Base(RC_COLOSSUS_GROTTO_BEEHIVE, RCQUEST_BOTH, RCTYPE_BEEHIVE, RCAREA_DESERT_COLOSSUS, ACTOR_OBJ_COMB, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2262, 0xFD), 0x00, "Grotto Beehive", "Colossus Grotto Beehive", RHT_BEEHIVE_SCRUB_PAIR_GROTTO, RG_RED_RUPEE, { Category::cBeehive }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BEEHIVE_COLOSSUS_GROTTO), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - // Cows Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group - locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KOKIRI_FOREST, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, 0x15, "Links House Cow", "KF Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x34, 0x15), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_HF_COW_GROTTO_COW] = Location::Base(RC_HF_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_HYRULE_FIELD, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3485, -291), 0x16, "Cow Grotto Cow", "HF Cow Grotto Cow", RHT_HF_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x3E, 0x16), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_LLR_STABLES_LEFT_COW] = Location::Base(RC_LLR_STABLES_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(-122, -254), 0x16, "Stables Left Cow", "LLR Stables Left Cow", RHT_LLR_STABLES_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x36, 0x16), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_STABLES_RIGHT_COW] = Location::Base(RC_LLR_STABLES_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(116, -254), 0x15, "Stables Right Cow", "LLR Stables Right Cow", RHT_LLR_STABLES_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x36, 0x15), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_TOWER_LEFT_COW] = Location::Base(RC_LLR_TOWER_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-229, 157), 0x15, "Tower Left Cow", "LLR Tower Left Cow", RHT_LLR_TOWER_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x4C, 0x16), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_LLR_TOWER_RIGHT_COW] = Location::Base(RC_LLR_TOWER_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-142, -140), 0x16, "Tower Right Cow", "LLR Tower Right Cow", RHT_LLR_TOWER_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x4C, 0x15), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); - locationTable[RC_KAK_IMPAS_HOUSE_COW] = Location::Base(RC_KAK_IMPAS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_COW, SCENE_IMPAS_HOUSE, 0x00, 0x15, "Impas House Cow", "Kak Impas House Cow", RHT_KAK_IMPAS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x37, 0x15), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), 0x15, "Cow Grotto Cow", "DMT Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x3E, 0x15), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", "GV Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x5A, 0x15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); - locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", "Jabu Jabus Belly MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::Cow(0x02, 0x15), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); + // Cows + locationTable[RC_KF_LINKS_HOUSE_COW] = Location::Base(RC_KF_LINKS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KOKIRI_FOREST, ACTOR_EN_COW, SCENE_LINKS_HOUSE, 0x00, 0x15, "Links House Cow", "KF Links House Cow", RHT_KF_LINKS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_HF_COW_GROTTO_COW] = Location::Base(RC_HF_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_HYRULE_FIELD, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3485, -291), 0x16, "Cow Grotto Cow", "HF Cow Grotto Cow", RHT_HF_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_LLR_STABLES_LEFT_COW] = Location::Base(RC_LLR_STABLES_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(-122, -254), 0x16, "Stables Left Cow", "LLR Stables Left Cow", RHT_LLR_STABLES_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_STABLES_RIGHT_COW] = Location::Base(RC_LLR_STABLES_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_STABLE, TWO_ACTOR_PARAMS(116, -254), 0x15, "Stables Right Cow", "LLR Stables Right Cow", RHT_LLR_STABLES_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TOWER_LEFT_COW] = Location::Base(RC_LLR_TOWER_LEFT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-229, 157), 0x15, "Tower Left Cow", "LLR Tower Left Cow", RHT_LLR_TOWER_LEFT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_LLR_TOWER_RIGHT_COW] = Location::Base(RC_LLR_TOWER_RIGHT_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_LON_LON_RANCH, ACTOR_EN_COW, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(-142, -140), 0x16, "Tower Right Cow", "LLR Tower Right Cow", RHT_LLR_TOWER_RIGHT_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH); + locationTable[RC_KAK_IMPAS_HOUSE_COW] = Location::Base(RC_KAK_IMPAS_HOUSE_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_COW, SCENE_IMPAS_HOUSE, 0x00, 0x15, "Impas House Cow", "Kak Impas House Cow", RHT_KAK_IMPAS_HOUSE_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_COW_GROTTO_COW] = Location::Base(RC_DMT_COW_GROTTO_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_COW, SCENE_GROTTOS, TWO_ACTOR_PARAMS(2444, -471), 0x15, "Cow Grotto Cow", "DMT Cow Grotto Cow", RHT_DMT_COW_GROTTO_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_GV_COW] = Location::Base(RC_GV_COW, RCQUEST_BOTH, RCTYPE_COW, RCAREA_GERUDO_VALLEY, ACTOR_EN_COW, SCENE_GERUDO_VALLEY, 0x00, 0x15, "Cow", "GV Cow", RHT_GV_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_GV_COW), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY); + locationTable[RC_JABU_JABUS_BELLY_MQ_COW] = Location::Base(RC_JABU_JABUS_BELLY_MQ_COW, RCQUEST_MQ, RCTYPE_COW, RCAREA_JABU_JABUS_BELLY, ACTOR_EN_COW, SCENE_JABU_JABU, 0x00, 0x15, "MQ Cow", "Jabu Jabus Belly MQ Cow", RHT_JABU_JABUS_BELLY_MQ_COW, RG_MILK, { Category::cCow }, SpoilerCollectionCheck::RandomizerInf(RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW), SpoilerCollectionCheckGroup::GROUP_DUNGEON_JABUJABUS_BELLY); /*------------------------------- --- SHOPS --- @@ -1383,192 +1382,190 @@ void Rando::StaticData::InitLocationTable() { 7 5 1 3 -------------------------------*/ - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Spoiler Collection Check Group // Kokiri Forest - locationTable[RC_KF_SHOP_ITEM_1] = Location::Base(RC_KF_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x00, 0x00, "Shop Item 1", "KF Shop Item 1", RHT_KF_SHOP_ITEM_1, RG_BUY_DEKU_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_2] = Location::Base(RC_KF_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x01, 0x01, "Shop Item 2", "KF Shop Item 2", RHT_KF_SHOP_ITEM_2, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 1), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_3] = Location::Base(RC_KF_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x02, 0x02, "Shop Item 3", "KF Shop Item 3", RHT_KF_SHOP_ITEM_3, RG_BUY_DEKU_NUTS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 2), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_4] = Location::Base(RC_KF_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x03, 0x03, "Shop Item 4", "KF Shop Item 4", RHT_KF_SHOP_ITEM_4, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 3), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_5] = Location::Base(RC_KF_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x04, 0x04, "Shop Item 5", "KF Shop Item 5", RHT_KF_SHOP_ITEM_5, RG_BUY_DEKU_SEEDS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 4), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_6] = Location::Base(RC_KF_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x05, 0x05, "Shop Item 6", "KF Shop Item 6", RHT_KF_SHOP_ITEM_6, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 5), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_7] = Location::Base(RC_KF_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x06, 0x06, "Shop Item 7", "KF Shop Item 7", RHT_KF_SHOP_ITEM_7, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 6), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_KF_SHOP_ITEM_8] = Location::Base(RC_KF_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x07, 0x07, "Shop Item 8", "KF Shop Item 8", RHT_KF_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 7), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_1] = Location::Base(RC_KF_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x00, 0x00, "Shop Item 1", "KF Shop Item 1", RHT_KF_SHOP_ITEM_1, RG_BUY_DEKU_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 0), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_2] = Location::Base(RC_KF_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x01, 0x01, "Shop Item 2", "KF Shop Item 2", RHT_KF_SHOP_ITEM_2, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 1), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_3] = Location::Base(RC_KF_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x02, 0x02, "Shop Item 3", "KF Shop Item 3", RHT_KF_SHOP_ITEM_3, RG_BUY_DEKU_NUTS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 2), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_4] = Location::Base(RC_KF_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x03, 0x03, "Shop Item 4", "KF Shop Item 4", RHT_KF_SHOP_ITEM_4, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 3), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_5] = Location::Base(RC_KF_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x04, 0x04, "Shop Item 5", "KF Shop Item 5", RHT_KF_SHOP_ITEM_5, RG_BUY_DEKU_SEEDS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 4), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_6] = Location::Base(RC_KF_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x05, 0x05, "Shop Item 6", "KF Shop Item 6", RHT_KF_SHOP_ITEM_6, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 5), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_7] = Location::Base(RC_KF_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x06, 0x06, "Shop Item 7", "KF Shop Item 7", RHT_KF_SHOP_ITEM_7, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 6), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_KF_SHOP_ITEM_8] = Location::Base(RC_KF_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KOKIRI_FOREST, ACTOR_EN_GIRLA, SCENE_KOKIRI_SHOP, 0x07, 0x07, "Shop Item 8", "KF Shop Item 8", RHT_KF_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2D, 7), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); // Kakariko Village - locationTable[RC_KAK_POTION_SHOP_ITEM_1] = Location::Base(RC_KAK_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x00, 0x30, "Potion Shop Item 1", "Kak Potion Shop Item 1", RHT_KAK_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_2] = Location::Base(RC_KAK_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x01, 0x31, "Potion Shop Item 2", "Kak Potion Shop Item 2", RHT_KAK_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_3] = Location::Base(RC_KAK_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x02, 0x32, "Potion Shop Item 3", "Kak Potion Shop Item 3", RHT_KAK_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_4] = Location::Base(RC_KAK_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x03, 0x33, "Potion Shop Item 4", "Kak Potion Shop Item 4", RHT_KAK_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_5] = Location::Base(RC_KAK_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x04, 0x34, "Potion Shop Item 5", "Kak Potion Shop Item 5", RHT_KAK_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_6] = Location::Base(RC_KAK_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x05, 0x35, "Potion Shop Item 6", "Kak Potion Shop Item 6", RHT_KAK_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_7] = Location::Base(RC_KAK_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x06, 0x36, "Potion Shop Item 7", "Kak Potion Shop Item 7", RHT_KAK_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_POTION_SHOP_ITEM_8] = Location::Base(RC_KAK_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x07, 0x37, "Potion Shop Item 8", "Kak Potion Shop Item 8", RHT_KAK_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_1] = Location::Base(RC_KAK_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x00, 0x38, "Bazaar Item 1", "Kak Bazaar Item 1", RHT_KAK_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_2] = Location::Base(RC_KAK_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x01, 0x39, "Bazaar Item 2", "Kak Bazaar Item 2", RHT_KAK_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_3] = Location::Base(RC_KAK_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x02, 0x3A, "Bazaar Item 3", "Kak Bazaar Item 3", RHT_KAK_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_4] = Location::Base(RC_KAK_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x03, 0x3B, "Bazaar Item 4", "Kak Bazaar Item 4", RHT_KAK_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_5] = Location::Base(RC_KAK_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x04, 0x3C, "Bazaar Item 5", "Kak Bazaar Item 5", RHT_KAK_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_6] = Location::Base(RC_KAK_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x05, 0x3D, "Bazaar Item 6", "Kak Bazaar Item 6", RHT_KAK_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_7] = Location::Base(RC_KAK_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x06, 0x3E, "Bazaar Item 7", "Kak Bazaar Item 7", RHT_KAK_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_KAK_BAZAAR_ITEM_8] = Location::Base(RC_KAK_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x07, 0x3F, "Bazaar Item 8", "Kak Bazaar Item 8", RHT_KAK_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_1] = Location::Base(RC_KAK_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x00, 0x30, "Potion Shop Item 1", "Kak Potion Shop Item 1", RHT_KAK_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_2] = Location::Base(RC_KAK_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x01, 0x31, "Potion Shop Item 2", "Kak Potion Shop Item 2", RHT_KAK_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_3] = Location::Base(RC_KAK_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x02, 0x32, "Potion Shop Item 3", "Kak Potion Shop Item 3", RHT_KAK_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_4] = Location::Base(RC_KAK_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x03, 0x33, "Potion Shop Item 4", "Kak Potion Shop Item 4", RHT_KAK_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_5] = Location::Base(RC_KAK_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x04, 0x34, "Potion Shop Item 5", "Kak Potion Shop Item 5", RHT_KAK_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_6] = Location::Base(RC_KAK_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x05, 0x35, "Potion Shop Item 6", "Kak Potion Shop Item 6", RHT_KAK_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_7] = Location::Base(RC_KAK_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x06, 0x36, "Potion Shop Item 7", "Kak Potion Shop Item 7", RHT_KAK_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_POTION_SHOP_ITEM_8] = Location::Base(RC_KAK_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_KAKARIKO, 0x07, 0x37, "Potion Shop Item 8", "Kak Potion Shop Item 8", RHT_KAK_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x30, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_1] = Location::Base(RC_KAK_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x00, 0x38, "Bazaar Item 1", "Kak Bazaar Item 1", RHT_KAK_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 0), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_2] = Location::Base(RC_KAK_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x01, 0x39, "Bazaar Item 2", "Kak Bazaar Item 2", RHT_KAK_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 1), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_3] = Location::Base(RC_KAK_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x02, 0x3A, "Bazaar Item 3", "Kak Bazaar Item 3", RHT_KAK_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 2), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_4] = Location::Base(RC_KAK_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x03, 0x3B, "Bazaar Item 4", "Kak Bazaar Item 4", RHT_KAK_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 3), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_5] = Location::Base(RC_KAK_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x04, 0x3C, "Bazaar Item 5", "Kak Bazaar Item 5", RHT_KAK_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_6] = Location::Base(RC_KAK_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x05, 0x3D, "Bazaar Item 6", "Kak Bazaar Item 6", RHT_KAK_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 5), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_7] = Location::Base(RC_KAK_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x06, 0x3E, "Bazaar Item 7", "Kak Bazaar Item 7", RHT_KAK_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 6), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_KAK_BAZAAR_ITEM_8] = Location::Base(RC_KAK_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_GIRLA, SCENE_TEST01, 0x07, 0x3F, "Bazaar Item 8", "Kak Bazaar Item 8", RHT_KAK_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x33, 7), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); // Market - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_1] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x00, 0x30, "Bombchu Shop Item 1", "MK Bombchu Shop Item 1", RHT_MARKET_BOMBCHU_SHOP_ITEM_1, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_2] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x01, 0x31, "Bombchu Shop Item 2", "MK Bombchu Shop Item 2", RHT_MARKET_BOMBCHU_SHOP_ITEM_2, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_3] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x02, 0x32, "Bombchu Shop Item 3", "MK Bombchu Shop Item 3", RHT_MARKET_BOMBCHU_SHOP_ITEM_3, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_4] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x03, 0x33, "Bombchu Shop Item 4", "MK Bombchu Shop Item 4", RHT_MARKET_BOMBCHU_SHOP_ITEM_4, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_5] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x04, 0x34, "Bombchu Shop Item 5", "MK Bombchu Shop Item 5", RHT_MARKET_BOMBCHU_SHOP_ITEM_5, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_6] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x05, 0x35, "Bombchu Shop Item 6", "MK Bombchu Shop Item 6", RHT_MARKET_BOMBCHU_SHOP_ITEM_6, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_7] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x06, 0x36, "Bombchu Shop Item 7", "MK Bombchu Shop Item 7", RHT_MARKET_BOMBCHU_SHOP_ITEM_7, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_8] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x07, 0x37, "Bombchu Shop Item 8", "MK Bombchu Shop Item 8", RHT_MARKET_BOMBCHU_SHOP_ITEM_8, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_1] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x00, 0x30, "Potion Shop Item 1", "MK Potion Shop Item 1", RHT_MARKET_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_2] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x01, 0x31, "Potion Shop Item 2", "MK Potion Shop Item 2", RHT_MARKET_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_3] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x02, 0x32, "Potion Shop Item 3", "MK Potion Shop Item 3", RHT_MARKET_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_4] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x03, 0x33, "Potion Shop Item 4", "MK Potion Shop Item 4", RHT_MARKET_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_5] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x04, 0x34, "Potion Shop Item 5", "MK Potion Shop Item 5", RHT_MARKET_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_6] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x05, 0x35, "Potion Shop Item 6", "MK Potion Shop Item 6", RHT_MARKET_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_7] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x06, 0x36, "Potion Shop Item 7", "MK Potion Shop Item 7", RHT_MARKET_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_POTION_SHOP_ITEM_8] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x07, 0x37, "Potion Shop Item 8", "MK Potion Shop Item 8", RHT_MARKET_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_1] = Location::Base(RC_MARKET_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x00, 0x30, "Bazaar Item 1", "MK Bazaar Item 1", RHT_MARKET_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_2] = Location::Base(RC_MARKET_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x01, 0x31, "Bazaar Item 2", "MK Bazaar Item 2", RHT_MARKET_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_3] = Location::Base(RC_MARKET_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x02, 0x32, "Bazaar Item 3", "MK Bazaar Item 3", RHT_MARKET_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_4] = Location::Base(RC_MARKET_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x03, 0x33, "Bazaar Item 4", "MK Bazaar Item 4", RHT_MARKET_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_5] = Location::Base(RC_MARKET_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x04, 0x34, "Bazaar Item 5", "MK Bazaar Item 5", RHT_MARKET_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_6] = Location::Base(RC_MARKET_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x05, 0x35, "Bazaar Item 6", "MK Bazaar Item 6", RHT_MARKET_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_7] = Location::Base(RC_MARKET_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x06, 0x36, "Bazaar Item 7", "MK Bazaar Item 7", RHT_MARKET_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); - locationTable[RC_MARKET_BAZAAR_ITEM_8] = Location::Base(RC_MARKET_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x07, 0x37, "Bazaar Item 8", "MK Bazaar Item 8", RHT_MARKET_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_1] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x00, 0x30, "Bombchu Shop Item 1", "MK Bombchu Shop Item 1", RHT_MARKET_BOMBCHU_SHOP_ITEM_1, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_2] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x01, 0x31, "Bombchu Shop Item 2", "MK Bombchu Shop Item 2", RHT_MARKET_BOMBCHU_SHOP_ITEM_2, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_3] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x02, 0x32, "Bombchu Shop Item 3", "MK Bombchu Shop Item 3", RHT_MARKET_BOMBCHU_SHOP_ITEM_3, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_4] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x03, 0x33, "Bombchu Shop Item 4", "MK Bombchu Shop Item 4", RHT_MARKET_BOMBCHU_SHOP_ITEM_4, RG_BUY_BOMBCHU_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_5] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x04, 0x34, "Bombchu Shop Item 5", "MK Bombchu Shop Item 5", RHT_MARKET_BOMBCHU_SHOP_ITEM_5, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_6] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x05, 0x35, "Bombchu Shop Item 6", "MK Bombchu Shop Item 6", RHT_MARKET_BOMBCHU_SHOP_ITEM_6, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_7] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x06, 0x36, "Bombchu Shop Item 7", "MK Bombchu Shop Item 7", RHT_MARKET_BOMBCHU_SHOP_ITEM_7, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BOMBCHU_SHOP_ITEM_8] = Location::Base(RC_MARKET_BOMBCHU_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BOMBCHU_SHOP, 0x07, 0x37, "Bombchu Shop Item 8", "MK Bombchu Shop Item 8", RHT_MARKET_BOMBCHU_SHOP_ITEM_8, RG_BUY_BOMBCHU_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x32, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_1] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x00, 0x30, "Potion Shop Item 1", "MK Potion Shop Item 1", RHT_MARKET_POTION_SHOP_ITEM_1, RG_BUY_GREEN_POTION, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_2] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x01, 0x31, "Potion Shop Item 2", "MK Potion Shop Item 2", RHT_MARKET_POTION_SHOP_ITEM_2, RG_BUY_BLUE_FIRE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_3] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x02, 0x32, "Potion Shop Item 3", "MK Potion Shop Item 3", RHT_MARKET_POTION_SHOP_ITEM_3, RG_BUY_RED_POTION_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_4] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x03, 0x33, "Potion Shop Item 4", "MK Potion Shop Item 4", RHT_MARKET_POTION_SHOP_ITEM_4, RG_BUY_FAIRYS_SPIRIT, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_5] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x04, 0x34, "Potion Shop Item 5", "MK Potion Shop Item 5", RHT_MARKET_POTION_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_6] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x05, 0x35, "Potion Shop Item 6", "MK Potion Shop Item 6", RHT_MARKET_POTION_SHOP_ITEM_6, RG_BUY_BOTTLE_BUG, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_7] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x06, 0x36, "Potion Shop Item 7", "MK Potion Shop Item 7", RHT_MARKET_POTION_SHOP_ITEM_7, RG_BUY_POE, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_POTION_SHOP_ITEM_8] = Location::Base(RC_MARKET_POTION_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_POTION_SHOP_MARKET, 0x07, 0x37, "Potion Shop Item 8", "MK Potion Shop Item 8", RHT_MARKET_POTION_SHOP_ITEM_8, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x31, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_1] = Location::Base(RC_MARKET_BAZAAR_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x00, 0x30, "Bazaar Item 1", "MK Bazaar Item 1", RHT_MARKET_BAZAAR_ITEM_1, RG_BUY_HYLIAN_SHIELD, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 0), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_2] = Location::Base(RC_MARKET_BAZAAR_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x01, 0x31, "Bazaar Item 2", "MK Bazaar Item 2", RHT_MARKET_BAZAAR_ITEM_2, RG_BUY_BOMBS_535, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 1), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_3] = Location::Base(RC_MARKET_BAZAAR_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x02, 0x32, "Bazaar Item 3", "MK Bazaar Item 3", RHT_MARKET_BAZAAR_ITEM_3, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 2), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_4] = Location::Base(RC_MARKET_BAZAAR_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x03, 0x33, "Bazaar Item 4", "MK Bazaar Item 4", RHT_MARKET_BAZAAR_ITEM_4, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 3), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_5] = Location::Base(RC_MARKET_BAZAAR_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x04, 0x34, "Bazaar Item 5", "MK Bazaar Item 5", RHT_MARKET_BAZAAR_ITEM_5, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 4), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_6] = Location::Base(RC_MARKET_BAZAAR_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x05, 0x35, "Bazaar Item 6", "MK Bazaar Item 6", RHT_MARKET_BAZAAR_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_7] = Location::Base(RC_MARKET_BAZAAR_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x06, 0x36, "Bazaar Item 7", "MK Bazaar Item 7", RHT_MARKET_BAZAAR_ITEM_7, RG_BUY_DEKU_STICK_1, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 6), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); + locationTable[RC_MARKET_BAZAAR_ITEM_8] = Location::Base(RC_MARKET_BAZAAR_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_MARKET, ACTOR_EN_GIRLA, SCENE_BAZAAR, 0x07, 0x37, "Bazaar Item 8", "MK Bazaar Item 8", RHT_MARKET_BAZAAR_ITEM_8, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2C, 7), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); // Zora's Domain - locationTable[RC_ZD_SHOP_ITEM_1] = Location::Base(RC_ZD_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x00, 0x30, "Shop Item 1", "ZD Shop Item 1", RHT_ZD_SHOP_ITEM_1, RG_BUY_ZORA_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_2] = Location::Base(RC_ZD_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x01, 0x31, "Shop Item 2", "ZD Shop Item 2", RHT_ZD_SHOP_ITEM_2, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 1), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_3] = Location::Base(RC_ZD_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x02, 0x32, "Shop Item 3", "ZD Shop Item 3", RHT_ZD_SHOP_ITEM_3, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 2), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_4] = Location::Base(RC_ZD_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x03, 0x33, "Shop Item 4", "ZD Shop Item 4", RHT_ZD_SHOP_ITEM_4, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 3), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_5] = Location::Base(RC_ZD_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x04, 0x34, "Shop Item 5", "ZD Shop Item 5", RHT_ZD_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 4), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_6] = Location::Base(RC_ZD_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x05, 0x35, "Shop Item 6", "ZD Shop Item 6", RHT_ZD_SHOP_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 5), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_7] = Location::Base(RC_ZD_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x06, 0x36, "Shop Item 7", "ZD Shop Item 7", RHT_ZD_SHOP_ITEM_7, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 6), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_SHOP_ITEM_8] = Location::Base(RC_ZD_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x07, 0x37, "Shop Item 8", "ZD Shop Item 8", RHT_ZD_SHOP_ITEM_8, RG_BUY_RED_POTION_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 7), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_1] = Location::Base(RC_ZD_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x00, 0x30, "Shop Item 1", "ZD Shop Item 1", RHT_ZD_SHOP_ITEM_1, RG_BUY_ZORA_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 0), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_2] = Location::Base(RC_ZD_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x01, 0x31, "Shop Item 2", "ZD Shop Item 2", RHT_ZD_SHOP_ITEM_2, RG_BUY_ARROWS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 1), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_3] = Location::Base(RC_ZD_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x02, 0x32, "Shop Item 3", "ZD Shop Item 3", RHT_ZD_SHOP_ITEM_3, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 2), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_4] = Location::Base(RC_ZD_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x03, 0x33, "Shop Item 4", "ZD Shop Item 4", RHT_ZD_SHOP_ITEM_4, RG_BUY_ARROWS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 3), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_5] = Location::Base(RC_ZD_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x04, 0x34, "Shop Item 5", "ZD Shop Item 5", RHT_ZD_SHOP_ITEM_5, RG_BUY_DEKU_NUTS_5, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 4), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_6] = Location::Base(RC_ZD_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x05, 0x35, "Shop Item 6", "ZD Shop Item 6", RHT_ZD_SHOP_ITEM_6, RG_BUY_ARROWS_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 5), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_7] = Location::Base(RC_ZD_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x06, 0x36, "Shop Item 7", "ZD Shop Item 7", RHT_ZD_SHOP_ITEM_7, RG_BUY_FISH, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 6), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_SHOP_ITEM_8] = Location::Base(RC_ZD_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_ZORAS_DOMAIN, ACTOR_EN_GIRLA, SCENE_ZORA_SHOP, 0x07, 0x37, "Shop Item 8", "ZD Shop Item 8", RHT_ZD_SHOP_ITEM_8, RG_BUY_RED_POTION_50, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2F, 7), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); // Goron City - locationTable[RC_GC_SHOP_ITEM_1] = Location::Base(RC_GC_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x00, 0x30, "Shop Item 1", "GC Shop Item 1", RHT_GC_SHOP_ITEM_1, RG_BUY_BOMBS_525, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_2] = Location::Base(RC_GC_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x01, 0x31, "Shop Item 2", "GC Shop Item 2", RHT_GC_SHOP_ITEM_2, RG_BUY_BOMBS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 1), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_3] = Location::Base(RC_GC_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x02, 0x32, "Shop Item 3", "GC Shop Item 3", RHT_GC_SHOP_ITEM_3, RG_BUY_BOMBS_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 2), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_4] = Location::Base(RC_GC_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x03, 0x33, "Shop Item 4", "GC Shop Item 4", RHT_GC_SHOP_ITEM_4, RG_BUY_BOMBS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 3), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_5] = Location::Base(RC_GC_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x04, 0x34, "Shop Item 5", "GC Shop Item 5", RHT_GC_SHOP_ITEM_5, RG_BUY_GORON_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 4), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_6] = Location::Base(RC_GC_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x05, 0x35, "Shop Item 6", "GC Shop Item 6", RHT_GC_SHOP_ITEM_6, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 5), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", "GC Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); - locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", "GC Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_1] = Location::Base(RC_GC_SHOP_ITEM_1, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x00, 0x30, "Shop Item 1", "GC Shop Item 1", RHT_GC_SHOP_ITEM_1, RG_BUY_BOMBS_525, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 0), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_2] = Location::Base(RC_GC_SHOP_ITEM_2, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x01, 0x31, "Shop Item 2", "GC Shop Item 2", RHT_GC_SHOP_ITEM_2, RG_BUY_BOMBS_10, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 1), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_3] = Location::Base(RC_GC_SHOP_ITEM_3, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x02, 0x32, "Shop Item 3", "GC Shop Item 3", RHT_GC_SHOP_ITEM_3, RG_BUY_BOMBS_20, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 2), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_4] = Location::Base(RC_GC_SHOP_ITEM_4, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x03, 0x33, "Shop Item 4", "GC Shop Item 4", RHT_GC_SHOP_ITEM_4, RG_BUY_BOMBS_30, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 3), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_5] = Location::Base(RC_GC_SHOP_ITEM_5, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x04, 0x34, "Shop Item 5", "GC Shop Item 5", RHT_GC_SHOP_ITEM_5, RG_BUY_GORON_TUNIC, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 4), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_6] = Location::Base(RC_GC_SHOP_ITEM_6, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x05, 0x35, "Shop Item 6", "GC Shop Item 6", RHT_GC_SHOP_ITEM_6, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 5), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", "GC Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); + locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", "GC Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY); /* +--------------+ | FISHSANITY | +--------------+ */ - // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group - locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", "LH Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", "LH Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", "LH Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", "LH Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", "LH Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", "LH Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", "LH Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", "LH Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", "LH Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", "LH Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", "LH Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", "LH Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", "LH Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", "LH Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", "LH Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", "LH Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", "LH Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", "LH Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", "LH Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", "LH Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", "LH Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", "LH Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", "LH Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", "LH Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", "LH Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", "LH Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", "LH Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", "LH Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", "LH Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", "LH Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", "LH Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", "LH Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); - locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", "LH Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + // Fishing Pond + locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", "LH Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", "LH Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", "LH Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", "LH Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", "LH Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", "LH Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", "LH Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", "LH Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", "LH Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", "LH Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", "LH Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", "LH Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", "LH Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", "LH Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", "LH Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", "LH Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", "LH Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", "LH Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", "LH Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", "LH Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", "LH Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", "LH Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", "LH Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", "LH Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", "LH Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", "LH Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", "LH Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", "LH Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", "LH Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", "LH Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", "LH Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", "LH Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); + locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", "LH Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA); // Grotto fish - locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "KF Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", "LW Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); - locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", "HF Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "HF Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", "HF Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); - locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "Kak Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); - locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "DMT Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER,ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", "DMC Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); - locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "ZR Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "KF Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", "LW Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS); + locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", "HF Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "HF Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", "HF Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD); + locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "Kak Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "DMT Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", "DMC Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN); + locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "ZR Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); // Zora's Domain fish - locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", "ZD Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", "ZD Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", "ZD Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", "ZD Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", "ZD Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", "ZD Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", "ZD Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", "ZD Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); + locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN); - // Gossip Stones RANDOTODO work towards removing and replacing with event access - // RandomizerCheck Randomizer Check Quest Area Scene Params Flag Short Name Spoiler name Categories - locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); - locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); - locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); - locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); - locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); - locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); - locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); - locationTable[RC_GRAVEYARD_GOSSIP_STONE] = Location::HintStone(RC_GRAVEYARD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); - locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); - locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); - locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); - locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); - locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); - locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); - locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); - locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); - locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); - locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); - locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); - locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); - locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); - locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); - locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); - locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); - locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); - locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); - locationTable[RC_ZF_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_ZF_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); - locationTable[RC_ZF_JABU_GOSSIP_STONE] = Location::HintStone(RC_ZF_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); - locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); - locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); - locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); - locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); - locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); - locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); - locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); - locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); - locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); - locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); - locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); + // Gossip Stones + locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {}); + locationTable[RC_DMT_GOSSIP_STONE] = Location::HintStone(RC_DMT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, 14340, 0x04, "Gossip Stone", "DMT Gossip Stone", {}); + locationTable[RC_COLOSSUS_GOSSIP_STONE] = Location::HintStone(RC_COLOSSUS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, 14362, 0x1A, "Gossip Stone", "Colossus Gossip Stone", {}); + locationTable[RC_DODONGOS_CAVERN_GOSSIP_STONE] = Location::HintStone(RC_DODONGOS_CAVERN_GOSSIP_STONE, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, 4372, 0x14, "Gossip Stone", "Dodongo's Cavern Gossip Stone", {}); + locationTable[RC_GV_GOSSIP_STONE] = Location::HintStone(RC_GV_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, 14353, 0x11, "Gossip Stone", "GV Gossip Stone", {}); + locationTable[RC_GC_MAZE_GOSSIP_STONE] = Location::HintStone(RC_GC_MAZE_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14357, 0x15, "Maze Gossip Stone", "GC Maze Gossip Stone", {}); + locationTable[RC_GC_MEDIGORON_GOSSIP_STONE] = Location::HintStone(RC_GC_MEDIGORON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, 14873, 0x19, "Medigoron Gossip Stone", "GC Medigoron Gossip Stone", {}); + locationTable[RC_GRAVEYARD_GOSSIP_STONE] = Location::HintStone(RC_GRAVEYARD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, 14346, 0x0A, "Gossip Stone", "GY Gossip Stone", {}); + locationTable[RC_HC_MALON_GOSSIP_STONE] = Location::HintStone(RC_HC_MALON_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14610, 0x12, "Malon Gossip Stone", "HC Malon Gossip Stone", {}); + locationTable[RC_HC_ROCK_WALL_GOSSIP_STONE] = Location::HintStone(RC_HC_ROCK_WALL_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, 14347, 0x0B, "Rock Wall Gossip Stone", "HC Rock Wall Gossip Stone", {}); + locationTable[RC_HC_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HC_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, 14355, 0x13, "Storms Grotto Gossip Stone", "HC Storms Grotto Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14623, 0x1F, "Deku Tree Left Gossip Stone", "KF Deku Tree Left Gossip Stone", {}); + locationTable[RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE] = Location::HintStone(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14880, 0x20, "Deku Tree Right Gossip Stone", "KF Deku Tree Right Gossip Stone", {}); + locationTable[RC_KF_GOSSIP_STONE] = Location::HintStone(RC_KF_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, 14366, 0x1E, "Gossip Stone", "KF Gossip Stone", {}); + locationTable[RC_KF_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KF_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_GROTTOS, -22988, 0x3C, "Storms Gossip Stone", "KF Storms Gossip Stone", {}); + locationTable[RC_LH_LAB_GOSSIP_STONE] = Location::HintStone(RC_LH_LAB_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14339, 0x03, "Lab Gossip Stone", "LH Lab Gossip Stone", {}); + locationTable[RC_LH_SOUTHEAST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHEAST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14863, 0x0F, "Southeast Gossip Stone", "LH Southeast Gossip Stone", {}); + locationTable[RC_LH_SOUTHWEST_GOSSIP_STONE] = Location::HintStone(RC_LH_SOUTHWEST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, 14600, 0x08, "Southwest Gossip Stone", "LH Southwest Gossip Stone", {}); + locationTable[RC_LW_GOSSIP_STONE] = Location::HintStone(RC_LW_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, 14365, 0x1D, "Gossip Stone", "LW Gossip Stone", {}); + locationTable[RC_SFM_MAZE_LOWER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_LOWER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14358, 0x16, "Maze Lower Gossip Stone", "SFM Maze Lower Gossip Stone", {}); + locationTable[RC_SFM_MAZE_UPPER_GOSSIP_STONE] = Location::HintStone(RC_SFM_MAZE_UPPER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14615, 0x17, "Maze Upper Gossip Stone", "SFM Maze Upper Gossip Stone", {}); + locationTable[RC_SFM_SARIA_GOSSIP_STONE] = Location::HintStone(RC_SFM_SARIA_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_SACRED_FOREST_MEADOW, SCENE_SACRED_FOREST_MEADOW, 14876, 0x1C, "Saria Gossip Stone", "SFM Saria Gossip Stone", {}); + locationTable[RC_TOT_LEFTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x06, "ToT Left Gossip Stone", "ToT Left Gossip Stone", {}); + locationTable[RC_TOT_RIGHTMOST_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHTMOST_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x07, "ToT Right Gossip Stone", "ToT Right Gossip Stone", {}); + locationTable[RC_TOT_RIGHT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x10, "ToT Right Center Gossip Stone", "ToT Right Center Gossip Stone", {}); + locationTable[RC_TOT_LEFT_CENTER_GOSSIP_STONE] = Location::HintStone(RC_TOT_LEFT_CENTER_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_ID_MAX, 0x00, 0x0E, "ToT Left Center Gossip Stone", "ToT Left Center Gossip Stone", {}); + locationTable[RC_ZD_GOSSIP_STONE] = Location::HintStone(RC_ZD_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, 14345, 0x09, "Gossip Stone", "ZD Gossip Stone", {}); + locationTable[RC_ZF_FAIRY_GOSSIP_STONE] = Location::HintStone(RC_ZF_FAIRY_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x01, "Fairy Gossip Stone", "Fairy Gossip Stone", {}); + locationTable[RC_ZF_JABU_GOSSIP_STONE] = Location::HintStone(RC_ZF_JABU_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, 0x00, 0x02, "Jabu Gossip Stone", "Jabu Gossip Stone", {}); + locationTable[RC_ZR_NEAR_GROTTOS_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14605, 0x0D, "Near Grottos Gossip Stone", "ZR Near Grottos Gossip Stone", {}); + locationTable[RC_ZR_NEAR_DOMAIN_GOSSIP_STONE] = Location::HintStone(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, 14860, 0x0C, "Near Domain Gossip Stone", "ZR Near Domain Gossip Stone", {}); + locationTable[RC_HF_COW_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_COW_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, 14363, 0x1B, "Cow Grotto Gossip Stone", "HF Cow Grotto Gossip Stone", {}); + locationTable[RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22944, 0x30, "Near Market Gossip Stone", "HF Near Market Gossip Stone", {}); + locationTable[RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22978, 0x32, "Southeast Gossip Stone", "HF Southeast Gossip Stone", {}); + locationTable[RC_HF_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_HF_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, -22947, 0x33, "Open Grotto Gossip Stone", "HF Open Grotto Gossip Stone", {}); + locationTable[RC_KAK_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_GROTTOS, -22984, 0x38, "Open Grotto Gossip Stone", "Kak Open Grotto Gossip Stone", {}); + locationTable[RC_ZR_OPEN_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_GROTTOS, -22985, 0x39, "Open Grotto Gossip Stone", "ZR Open Grotto Gossip Stone", {}); + locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, -22964, 0x34, "Near Shortcuts Gossip Stone", "LW Near Shortcuts Gossip Stone", {}); + locationTable[RC_DMT_STORMS_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, -23255, 0x37, "Storms Grotto Gossip Stone", "DMT Storms Grotto Gossip Stone", {}); + locationTable[RC_DMC_UPPER_GROTTO_GOSSIP_STONE] = Location::HintStone(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_GROTTOS, -23802, 0x3A, "Upper Grotto Gossip Stone", "DMC Upper Grotto Gossip Stone", {}); // Other Hints - locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint"); - locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in Ganons Castle"); - locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in MQ Ganons Castle"); - locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint", "Dampe's Diary Hint"); - locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint", "Greg Hint"); - locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song"); - locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text"); - locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text"); - locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT,RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint","Fishing Pole Hint"); + locationTable[RC_GANONDORF_HINT] = Location::OtherHint(RC_GANONDORF_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_GANON_MANT, SCENE_GANON_BOSS, "Ganondorf Hint", "Ganondorf Hint"); + locationTable[RC_SHEIK_HINT_GC] = Location::OtherHint(RC_SHEIK_HINT_GC, RCQUEST_VANILLA, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in Ganons Castle"); + locationTable[RC_SHEIK_HINT_MQ_GC] = Location::OtherHint(RC_SHEIK_HINT_MQ_GC, RCQUEST_MQ, RCTYPE_GOSSIP_STONE, RCAREA_GANONS_CASTLE, ACTOR_EN_XC, SCENE_INSIDE_GANONS_CASTLE, "Sheik Hint", "Sheik Hint in MQ Ganons Castle"); + locationTable[RC_DAMPE_HINT] = Location::OtherHint(RC_DAMPE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_GRAVEKEEPERS_HUT, "Diary Hint", "Dampe's Diary Hint"); + locationTable[RC_GREG_HINT] = Location::OtherHint(RC_GREG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_EN_TAKARA_MAN, SCENE_TREASURE_BOX_SHOP, "Greg Hint", "Greg Hint"); + locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song"); + locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text"); + locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text"); + locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint", "Fishing Pole Hint"); - locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); + locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP); // clang-format on // Init locationNameToEnum diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index d3f1fa8e4..b0160a6c6 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -438,8 +438,6 @@ void Settings::CreateOptionDescriptions() { "Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."; mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo."; - mOptionDescriptions[RSK_SKIP_TOWER_ESCAPE] = - "The tower escape sequence between Ganondorf and Ganon will be skipped."; mOptionDescriptions[RSK_COMPLETE_MASK_QUEST] = "Once the happy mask shop is opened, all masks will be available to be borrowed."; mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] = diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 868a9dea3..de0295b30 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -145,21 +145,6 @@ Randomizer::Randomizer() { Randomizer::~Randomizer() { } -std::unordered_map spoilerFileTrialToEnum = { - { "the Forest Trial", RAND_INF_TRIALS_DONE_FOREST_TRIAL }, - { "l'épreuve de la Forêt", RAND_INF_TRIALS_DONE_FOREST_TRIAL }, - { "the Fire Trial", RAND_INF_TRIALS_DONE_FIRE_TRIAL }, - { "l'épreuve du Feu", RAND_INF_TRIALS_DONE_FIRE_TRIAL }, - { "the Water Trial", RAND_INF_TRIALS_DONE_WATER_TRIAL }, - { "l'épreuve de l'Eau", RAND_INF_TRIALS_DONE_WATER_TRIAL }, - { "the Spirit Trial", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL }, - { "l'épreuve de l'Esprit", RAND_INF_TRIALS_DONE_SPIRIT_TRIAL }, - { "the Shadow Trial", RAND_INF_TRIALS_DONE_SHADOW_TRIAL }, - { "l'épreuve de l'Ombre", RAND_INF_TRIALS_DONE_SHADOW_TRIAL }, - { "the Light Trial", RAND_INF_TRIALS_DONE_LIGHT_TRIAL }, - { "l'épreuve de la Lumière", RAND_INF_TRIALS_DONE_LIGHT_TRIAL } -}; - std::unordered_map spoilerFileDungeonToScene = { { "Deku Tree", SCENE_DEKU_TREE }, { "Dodongo's Cavern", SCENE_DODONGOS_CAVERN }, @@ -344,8 +329,17 @@ void Randomizer::LoadMerchantMessages() { "Je te vends mon dernier %rHaricot&magique%w pour %r99 Rubis%w.\x1B&%gAcheter&Ne pas acheter%w")); } -bool Randomizer::IsTrialRequired(RandomizerInf trial) { - return Rando::Context::GetInstance()->GetTrial(trial - RAND_INF_TRIALS_DONE_LIGHT_TRIAL)->IsRequired(); +std::map trialFlagToTrialKey = { + { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, TK_LIGHT_TRIAL, }, + { EVENTCHKINF_COMPLETED_FOREST_TRIAL, TK_FOREST_TRIAL, }, + { EVENTCHKINF_COMPLETED_FIRE_TRIAL, TK_FIRE_TRIAL, }, + { EVENTCHKINF_COMPLETED_WATER_TRIAL, TK_WATER_TRIAL, }, + { EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, TK_SPIRIT_TRIAL, }, + { EVENTCHKINF_COMPLETED_SHADOW_TRIAL, TK_SHADOW_TRIAL, } +}; + +bool Randomizer::IsTrialRequired(s32 trialFlag) { + return Rando::Context::GetInstance()->GetTrial(trialFlagToTrialKey[trialFlag])->IsRequired(); } GetItemEntry Randomizer::GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, @@ -1417,21 +1411,28 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, RandomizerCheck specialRc = RC_UNKNOWN_CHECK; // TODO: Migrate these special cases into table, or at least document why they are special switch(sceneNum) { - case SCENE_TREASURE_BOX_SHOP: - if(actorParams == 20170) specialRc = RC_MARKET_TREASURE_CHEST_GAME_REWARD; + case SCENE_TREASURE_BOX_SHOP: { + if ((actorId == ACTOR_EN_BOX && actorParams == 20170) || (actorId == ACTOR_ITEM_ETCETERA && actorParams == 2572)) { + specialRc = RC_MARKET_TREASURE_CHEST_GAME_REWARD; + } - // RANDOTODO update logic to match 3ds rando when we implement keysanity - // keep keys og - if ((actorParams & 0x60) == 0x20) break; - - if (GetRandoSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - if((actorParams & 0xF) < 2) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_1; - if((actorParams & 0xF) < 4) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_2; - if((actorParams & 0xF) < 6) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_3; - if((actorParams & 0xF) < 8) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_4; - if((actorParams & 0xF) < 10) specialRc = RC_MARKET_TREASURE_CHEST_GAME_ITEM_5; + // todo: handle the itemetc part of this so drawing works when we implement shuffle + if (actorId == ACTOR_EN_BOX) { + bool isAKey = (actorParams & 0x60) == 0x20; + if ((actorParams & 0xF) < 2) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_1 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_1; + } else if ((actorParams & 0xF) < 4) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_2 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_2; + } else if ((actorParams & 0xF) < 6) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_3 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_3; + } else if ((actorParams & 0xF) < 8) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_4 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_4; + } else if ((actorParams & 0xF) < 10) { + specialRc = isAKey ? RC_MARKET_TREASURE_CHEST_GAME_KEY_5 : RC_MARKET_TREASURE_CHEST_GAME_ITEM_5; + } } break; + } case SCENE_SACRED_FOREST_MEADOW: if (actorId == ACTOR_EN_SA) { specialRc = RC_SONG_FROM_SARIA; diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 866f4cd7f..1e9fec263 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -43,7 +43,7 @@ class Randomizer { bool SpoilerFileExists(const char* spoilerFileName); void LoadMerchantMessages(); void LoadHintMessages(); - bool IsTrialRequired(RandomizerInf trial); + bool IsTrialRequired(s32 trialFlag); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 5e651e807..35d0b48ec 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -747,6 +747,11 @@ typedef enum { RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RC_MARKET_TREASURE_CHEST_GAME_KEY_1, + RC_MARKET_TREASURE_CHEST_GAME_KEY_2, + RC_MARKET_TREASURE_CHEST_GAME_KEY_3, + RC_MARKET_TREASURE_CHEST_GAME_KEY_4, + RC_MARKET_TREASURE_CHEST_GAME_KEY_5, RC_MARKET_GS_GUARD_HOUSE, RC_MARKET_BAZAAR_ITEM_1, RC_MARKET_BAZAAR_ITEM_2, @@ -2354,6 +2359,11 @@ typedef enum { RHT_MARKET_TREASURE_CHEST_GAME_ITEM_3, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_4, RHT_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_1, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_2, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_3, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_4, + RHT_MARKET_TREASURE_CHEST_GAME_KEY_5, RHT_MARKET_GS_GUARD_HOUSE, RHT_MARKET_BAZAAR_ITEM_1, RHT_MARKET_BAZAAR_ITEM_2, @@ -3620,7 +3630,6 @@ typedef enum { RSK_CUCCO_COUNT, RSK_BIG_POE_COUNT, RSK_SKIP_EPONA_RACE, - RSK_SKIP_TOWER_ESCAPE, RSK_COMPLETE_MASK_QUEST, RSK_SKIP_SCARECROWS_SONG, RSK_ENABLE_GLITCH_CUTSCENES, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index ae88171b5..1a78e8c5c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -440,26 +440,19 @@ bool HasItemBeenCollected(RandomizerCheck rc) { case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE: return (gPlayState->sceneNum == scene && gPlayState->actorCtx.flags.collect & (1 << flag)) || gSaveContext.sceneFlags[scene].collect & (1 << flag); - case SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT: case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM: - case SpoilerCollectionCheckType::SPOILER_CHK_COW: case SpoilerCollectionCheckType::SPOILER_CHK_FISH: - case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB: case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF: case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD: return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc)); case SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF: return gSaveContext.eventChkInf[flag / 16] & (0x01 << flag % 16); - case SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD: - return CHECK_FLAG_ALL(gSaveContext.eventChkInf[0x09], 0x0F); case SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA: return GET_GS_FLAGS(scene) & flag; case SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE: return gSaveContext.infTable[scene] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag); case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF: return gSaveContext.itemGetInf[flag / 16] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag); - case SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS: - return BEANS_BOUGHT >= 10; case SpoilerCollectionCheckType::SPOILER_CHK_NONE: return false; case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER: @@ -782,11 +775,8 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) { Rando::SpoilerCollectionCheck scCheck = loc.GetCollectionCheck(); SpoilerCollectionCheckType scCheckType = scCheck.type; if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF && - (scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT || - scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM || - scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_COW || + (scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH || - scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SCRUB || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD || scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) { if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(loc.GetRandomizerCheck())) { @@ -1372,6 +1362,11 @@ void DrawLocation(RandomizerCheck rc) { Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc); RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc]; RandomizerCheckStatus status = checkData.status; + + if (itemLoc->HasObtained()) { + status = RCSHOW_COLLECTED; + } + bool skipped = checkData.skipped; if (status == RCSHOW_COLLECTED) { if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) { @@ -1706,12 +1701,12 @@ void CheckTrackerWindow::InitElement() { GameInteractor::Instance->RegisterGameHook([](uint32_t fileNum) { Teardown(); }); - GameInteractor::Instance->RegisterGameHook(CheckTrackerItemReceive); + // GameInteractor::Instance->RegisterGameHook(CheckTrackerItemReceive); GameInteractor::Instance->RegisterGameHook(CheckTrackerFrame); GameInteractor::Instance->RegisterGameHook(CheckTrackerTransition); GameInteractor::Instance->RegisterGameHook(CheckTrackerShopSlotChange); - GameInteractor::Instance->RegisterGameHook(CheckTrackerSceneFlagSet); - GameInteractor::Instance->RegisterGameHook(CheckTrackerFlagSet); + // GameInteractor::Instance->RegisterGameHook(CheckTrackerSceneFlagSet); + // GameInteractor::Instance->RegisterGameHook(CheckTrackerFlagSet); hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1); alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0); diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index ba735fad3..5fd348343 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -448,34 +448,31 @@ void Entrance_SetWarpSongEntrance(void) { } void Entrance_OverrideBlueWarp(void) { - // Set nextEntranceIndex as a flag so that Grotto_CheckSpecialEntrance - // won't return index 0x7FFF, which can't work to override blue warps. - gPlayState->nextEntranceIndex = 0; + // Handles first time entering bluewarp (with item give) + switch (gSaveContext.entranceIndex) { + case ENTR_KOKIRI_FOREST_11: // Gohma blue warp + case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp + case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp + case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp + case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp + case ENTR_LAKE_HYLIA_9: // Morpha blue warp + case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp + case ENTR_GRAVEYARD_8: // Twinrova blue warp + gSaveContext.entranceIndex = Entrance_OverrideNextIndex(gSaveContext.entranceIndex); + return; + } - switch (gPlayState->sceneNum) { - case SCENE_DEKU_TREE_BOSS: // Ghoma boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_KOKIRI_FOREST_11); - return; - case SCENE_DODONGOS_CAVERN_BOSS: // King Dodongo boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_TRAIL_5); - return; - case SCENE_JABU_JABU_BOSS: // Barinade boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_ZORAS_FOUNTAIN_0); - return; - case SCENE_FOREST_TEMPLE_BOSS: // Phantom Ganon boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_SACRED_FOREST_MEADOW_3); - return; - case SCENE_FIRE_TEMPLE_BOSS: // Volvagia boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_CRATER_5); - return; - case SCENE_WATER_TEMPLE_BOSS: // Morpha boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_LAKE_HYLIA_9); - return; - case SCENE_SPIRIT_TEMPLE_BOSS: // Twinrova boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DESERT_COLOSSUS_8); - return; - case SCENE_SHADOW_TEMPLE_BOSS: // Bongo-Bongo boss room - gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_GRAVEYARD_8); + // Handles second+ times entering bluewarp + switch (gPlayState->nextEntranceIndex) { + case ENTR_KOKIRI_FOREST_11: // Gohma blue warp + case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp + case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp + case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp + case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp + case ENTR_LAKE_HYLIA_9: // Morpha blue warp + case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp + case ENTR_GRAVEYARD_8: // Twinrova blue warp + gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(gPlayState->nextEntranceIndex); return; } } diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index c61f933bf..f1ae83121 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1,22 +1,9 @@ #pragma once typedef enum { - RAND_INF_DUNGEONS_DONE_DEKU_TREE, - RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN, - RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY, - RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE, - RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE, - RAND_INF_DUNGEONS_DONE_WATER_TEMPLE, RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE, RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE, - RAND_INF_TRIALS_DONE_LIGHT_TRIAL, - RAND_INF_TRIALS_DONE_FOREST_TRIAL, - RAND_INF_TRIALS_DONE_FIRE_TRIAL, - RAND_INF_TRIALS_DONE_WATER_TRIAL, - RAND_INF_TRIALS_DONE_SPIRIT_TRIAL, - RAND_INF_TRIALS_DONE_SHADOW_TRIAL, - RAND_INF_COWS_MILKED_KF_LINKS_HOUSE_COW, RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW, RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW, @@ -143,12 +130,15 @@ typedef enum { RAND_INF_MERCHANTS_CARPET_SALESMAN, RAND_INF_MERCHANTS_MEDIGORON, RAND_INF_MERCHANTS_GRANNYS_SHOP, + RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN, RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, RAND_INF_ADULT_TRADES_GV_TRADE_SAW, RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD, + RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION, RAND_INF_ADULT_TRADES_LH_TRADE_FROG, RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS, + RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, @@ -267,6 +257,31 @@ typedef enum { RAND_INF_ZD_FISH_4, RAND_INF_ZD_FISH_5, + RAND_INF_LINKS_POCKET, + RAND_INF_LEARNED_EPONA_SONG, + RAND_INF_DARUNIAS_JOY, + RAND_INF_KING_ZORA_THAWED, + + RAND_INF_HC_GREAT_FAIRY_REWARD, + RAND_INF_DMT_GREAT_FAIRY_REWARD, + RAND_INF_DMC_GREAT_FAIRY_REWARD, + RAND_INF_ZF_GREAT_FAIRY_REWARD, + RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD, + RAND_INF_OGC_GREAT_FAIRY_REWARD, + + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_1, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_2, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_3, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_4, + RAND_INF_MARKET_TREASURE_CHEST_GAME_ITEM_5, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_1, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_2, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_3, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_4, + RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5, + + RAND_INF_GF_ITEM_FROM_LEADER_OF_FORTRESS, + RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN, // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index d3c2d535b..ffab46e49 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -97,6 +97,9 @@ void GiveLinksPocketItem() { if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE); StartingItemGive(getItemEntry); + Rando::Context::GetInstance()->GetItemLocation(RC_LINKS_POCKET)->MarkAsObtained(); + // If we re-add the above, we'll get the item on save creation, now it's given on first load + Flags_SetRandomizerInf(RAND_INF_LINKS_POCKET); } } @@ -202,99 +205,102 @@ void SetStartingItems() { } extern "C" void Randomizer_InitSaveFile() { - // Sets all rando flags to false - for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) { - gSaveContext.randomizerInf[i] = 0; - } + // Now handled by cutscene skips + // gSaveContext.cutsceneIndex = 0; // no intro cutscene + // Starts pending ice traps out at 0 before potentially incrementing them down the line. + gSaveContext.pendingIceTrapCount = 0; // Reset triforce pieces collected gSaveContext.triforcePiecesCollected = 0; - gSaveContext.cutsceneIndex = 0; // no intro cutscene - // Starts pending ice traps out at 0 before potentially incrementing them down the line. - gSaveContext.pendingIceTrapCount = 0; - // Set Cutscene flags and texts to skip them - Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); + // Now handled by cutscene skips + // Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO); - Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); - Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); + // Now handled by cutscene skips + // Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); + // Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); - Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); + // Now handled by cutscene skips + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); + // Now using this to grant master sword check + // Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); - Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + // Now used to give player LACS rewards + // Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO); Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET); Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE); - Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); - Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); - Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); - Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT); + // Now handled by cutscene skips + // Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); + // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); + // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS); + // Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); + // Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); + // Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); + // Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT); // Ruto already met in jabu and spawns down the hole immediately Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO); Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME); Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE); + // Now handled by cutscene skips // Skip cutscenes before Nabooru fight - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); + // Now handled by cutscene skips // Skip boss cutscenes - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); - Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); + // Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); - // Entered areas - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER); - Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR); - Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + // Now handled by cutscene skips + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER); + // Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR); + // Ensure Malon appears at castle first time you enter + // Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); // skip the z target talk instructions by the kokiri shop - gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F); + // Now handled by cutscene skips + // gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F); // Go away ruto (water temple first cutscene) gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10); + // Now handled by cutscene skips // no more kaepora - gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest - gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia - gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria - gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria - gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora - gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora - - if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) { - Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple - } + // gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest + // gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia + // gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria + // gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria + // gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora + // gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora if (Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A); @@ -341,10 +347,15 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.entranceIndex = -1; } - // If any trials aren't required, set them as completed - for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) { - if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired((RandomizerInf)i)) { - Flags_SetRandomizerInf((RandomizerInf)i); + for (auto trialFlag : { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, + EVENTCHKINF_COMPLETED_FOREST_TRIAL, + EVENTCHKINF_COMPLETED_FIRE_TRIAL, + EVENTCHKINF_COMPLETED_WATER_TRIAL, + EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, + EVENTCHKINF_COMPLETED_SHADOW_TRIAL } + ) { + if (!OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag)) { + Flags_SetEventChkInf(trialFlag); } } @@ -398,15 +409,16 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); } - int openForest = Randomizer_GetSettingValue(RSK_FOREST); - switch (openForest) { - case RO_FOREST_OPEN: - Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); - // Fallthrough - case RO_FOREST_CLOSED_DEKU: - Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); - break; - } + // Now handled on the fly + // int openForest = Randomizer_GetSettingValue(RSK_FOREST); + // switch (openForest) { + // case RO_FOREST_OPEN: + // Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); + // // Fallthrough + // case RO_FOREST_CLOSED_DEKU: + // Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); + // break; + // } int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); switch (doorOfTime) { diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index f00179ef7..76cda498a 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -147,7 +147,6 @@ void Settings::CreateOptions() { mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::Bool("Ganon's Castle", "gRandomizeShuffleKeyRingsGanonsCastle"); mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildStealth", mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipChildZelda", mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); - mOptions[RSK_SKIP_TOWER_ESCAPE] = Option::Bool("Skip Tower Escape", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipTowerEscape", mOptionDescriptions[RSK_SKIP_TOWER_ESCAPE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, "gRandomizeSkipEponaRace", mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", "gRandomizeSkipScarecrowsSong", mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, "gRandomizeBigPoeTargetCount", mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9); @@ -715,7 +714,6 @@ void Settings::CreateOptions() { &mOptions[RSK_SKIP_CHILD_STEALTH], &mOptions[RSK_SKIP_CHILD_ZELDA], &mOptions[RSK_SKIP_EPONA_RACE], - &mOptions[RSK_SKIP_TOWER_ESCAPE], &mOptions[RSK_COMPLETE_MASK_QUEST], &mOptions[RSK_SKIP_SCARECROWS_SONG] }, false, WidgetContainerType::COLUMN); @@ -1202,7 +1200,6 @@ void Settings::CreateOptions() { { "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT }, { "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH }, { "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE }, - { "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE }, { "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST }, { "Timesaver Settings:Skip Scarecrow's Song", RSK_SKIP_SCARECROWS_SONG }, { "Timesaver Settings:Enable Glitch-Useful Cutscenes", RSK_ENABLE_GLITCH_CUTSCENES }, @@ -2526,7 +2523,6 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SKIP_CHILD_ZELDA: case RSK_SKIP_CHILD_STEALTH: case RSK_SKIP_EPONA_RACE: - case RSK_SKIP_TOWER_ESCAPE: if (it.value() == "Don't Skip") { mOptions[index].SetSelectedIndex(RO_GENERIC_DONT_SKIP); } else if (it.value() == "Skip") { diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp new file mode 100644 index 000000000..642eae7cc --- /dev/null +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -0,0 +1,1212 @@ +#include +#include "soh/OTRGlobals.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + +extern "C" { +#include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h" +#include "src/overlays/actors/ovl_Elf_Msg/z_elf_msg.h" +#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h" +#include "src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h" +#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" +#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h" +#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" +#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h" +#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h" +#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h" +#include "src/overlays/actors/ovl_En_Sa/z_en_sa.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_Fu/z_en_fu.h" +#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" +#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" +#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 +#include +#include +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +extern int32_t D_8011D3AC; +} + +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() + +void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) { + func_80A995CC(enKo, play); + + if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) { + // Typically this doesn't get get live updated in vanilla, but we need to + // live update it if we're skipping a certain cutscene or in randomizer + if (GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) { + enKo->collider.dim.height -= 200; + Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos); + enKo->actionFunc = func_80A99384; + } + } +} + +void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { + if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) { + Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); + func_80078884(NA_SE_SY_CORRECT_CHIME); + enMa1->actor.flags &= ~ACTOR_FLAG_WILL_TALK; + play->msgCtx.ocarinaMode = OCARINA_MODE_04; + enMa1->actionFunc = func_80AA0D88; + enMa1->unk_1E0 = 1; + enMa1->interactInfo.talkState = NPC_TALK_STATE_IDLE; + return; + } +} + +void EnFu_EndTeachSong(EnFu* enFu, PlayState* play) { + if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) { + func_80078884(NA_SE_SY_CORRECT_CHIME); + enFu->actionFunc = EnFu_WaitAdult; + enFu->actor.flags &= ~ACTOR_FLAG_WILL_TALK; + + play->msgCtx.ocarinaMode = OCARINA_MODE_04; + Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS); + return; + } +} + +u16 EnZl4_GiveItemTextId(PlayState* play, Actor* actor) { + return 0x207D; +} + +void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) { + if (enZl4->csState == 0 && enZl4->actor.xzDistToPlayer < 600.0f && EnZl4_SetNextAnim(enZl4, 3)) { + Audio_PlayFanfare(NA_BGM_APPEAR); + enZl4->csState = 8; // ZL4_CS_PLAN + } else { + Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0); + func_80B5BB78(enZl4, play); + + if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) { + enZl4->talkState = 6; + enZl4->actionFunc = EnZl4_Cutscene; + } + } +} + +void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) { + // todo: figure out a better way to handle toggling so we don't + // need to double check cvars like this + if(!(IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + EnDntDemo_Judge(enDntDemo, play); + return; + } + + if (enDntDemo->actor.xzDistToPlayer > 30.0f) { + EnDntDemo_Judge(enDntDemo, play); + return; + } + + Player* player = GET_PLAYER(play); + switch (Player_GetMask(play)) { + case PLAYER_MASK_SKULL: { + Flags_SetItemGetInf(ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE); + return; + } + case PLAYER_MASK_TRUTH: { + Flags_SetItemGetInf(ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE); + return; + } + default: { + EnDntDemo_Judge(enDntDemo, play); + return; + } + } +} + +static int successChimeCooldown = 0; +void RateLimitedSuccessChime() { + if (successChimeCooldown == 0) { + // Currently disabled, need to find a better way to do this, while being consistent with vanilla + // func_80078884(NA_SE_SY_CORRECT_CHIME); + successChimeCooldown = 120; + } +} + +void TimeSaverOnGameFrameUpdateHandler() { + if (successChimeCooldown > 0) { + successChimeCooldown--; + } +} + +void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) { + switch (id) { + case GI_VB_PLAY_TRANSITION_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.cutsceneIndex = 0; + *should = false; + } + + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + // Song of Time + if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_0 && gSaveContext.cutsceneIndex == 0xFFF7) { + gSaveContext.entranceIndex = ENTR_HYRULE_FIELD_16; + gSaveContext.cutsceneIndex = 0; + gSaveContext.nextTransitionType = 3; + *should = false; + } + + // Requiem of Spirit + if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) { + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); + // Normally happens in the cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0xAC60; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { + Item_Give(gPlayState, ITEM_SONG_REQUIEM); + } + *should = false; + } + + u8 meetsBurningKakRequirements = + LINK_IS_ADULT && + gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && + Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, meetsBurningKakRequirements, NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + // Normally happens in the cutscene + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { + Item_Give(gPlayState, ITEM_SONG_NOCTURNE); + } + *should = false; + } + } + + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + uint8_t isBlueWarp = 0; + // Deku Tree Blue warp + if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_11; + isBlueWarp = 1; + // Dodongo's Cavern Blue warp + } else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; + isBlueWarp = 1; + // Jabu Jabu's Blue warp + } else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_0 && gSaveContext.cutsceneIndex == 0xFFF0) { + gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_0; + isBlueWarp = 1; + // 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_3; + } else { + gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_12; + } + + isBlueWarp = 1; + // Fire Temple Blue warp + } else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) { + gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; + isBlueWarp = 1; + // 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; + + gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9; + isBlueWarp = 1; + // 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_8; + isBlueWarp = 1; + // 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_8; + isBlueWarp = 1; + } + + if (isBlueWarp) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; + + *should = false; + gSaveContext.cutsceneIndex = 0; + + if (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)) { + Entrance_OverrideBlueWarp(); + } + } + + // Flee hyrule castle cutscene + if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_0 && gSaveContext.cutsceneIndex == 0xFFF1) { + // Normally set in the blue warp cutscene + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x4AAA; + + gSaveContext.cutsceneIndex = 0; + *should = false; + } + + // Lost Woods Bridge + if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { + Item_Give(gPlayState, ITEM_OCARINA_FAIRY); + } + *should = false; + } + + // LACS + u8 meetsLACSRequirements = + LINK_IS_ADULT && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, meetsLACSRequirements, NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { + Item_Give(gPlayState, ITEM_ARROW_LIGHT); + } + *should = false; + } + } + + if (gSaveContext.entranceIndex == ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0) { + if (CVarGetInteger("gTimeSavers.SkipTowerEscape", false) || IS_BOSS_RUSH) { + Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); + gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; + *should = false; + } + } + + if (gSaveContext.entranceIndex == ENTR_CASTLE_COURTYARD_GUARDS_DAY_0) { + if (CVarGetInteger("gTimeSavers.SkipChildStealth", false)) { + gSaveContext.entranceIndex = ENTR_CASTLE_COURTYARD_ZELDA_0; + *should = false; + } + } + break; + } + case GI_VB_PLAY_ENTRANCE_CS: { + s32* entranceFlag = static_cast(opt); + if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) { + *should = false; + } + break; + } + case GI_VB_PLAY_ONEPOINT_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { + s16* csId = static_cast(opt); + switch (*csId) { + case 4180: + case 4100: + *should = false; + RateLimitedSuccessChime(); + break; + default: + SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_CS {}", *csId); + break; + } + } + break; + } + case GI_VB_PLAY_ONEPOINT_ACTOR_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", IS_RANDO)) { + Actor* actor = static_cast(opt); + + // there are a few checks throughout the game (such as chest spawns) that rely on this + // the checks are for func_8005B198() == this->dyna.actor.category + // func_8005B198 just returns D_8011D3AC + // D_8011D3AC is set to camera->target->category in Camera_Demo5 + D_8011D3AC = actor->category; + + switch (actor->category) { + case ACTORCAT_BG: + if (actor->id == ACTOR_BG_DDAN_KD) { + BgDdanKd* ddanKd = static_cast(opt); + Flags_SetSwitch(gPlayState, ddanKd->dyna.actor.params); + } + if (actor->id == ACTOR_BG_MORI_HINERI) { + break; + } + + RateLimitedSuccessChime(); + *should = false; + break; + } + switch (actor->id) { + case ACTOR_OBJ_SWITCH: { + ObjSwitch *switchActor = static_cast(opt); + switchActor->cooldownTimer = 0; + *should = false; + RateLimitedSuccessChime(); + break; + } + case ACTOR_BG_BDAN_SWITCH: { + BgBdanSwitch* switchActor = static_cast(opt); + switchActor->unk_1D8 = 0; + switchActor->unk_1DA = 0; + *should = false; + RateLimitedSuccessChime(); + break; + } + case ACTOR_BG_HIDAN_KOUSI: { + BgHidanKousi* switchActor = static_cast(opt); + BgHidanKousi_SetupAction(switchActor, func_80889C18); + *should = false; + RateLimitedSuccessChime(); + break; + } + case ACTOR_BG_HIDAN_FWBIG: { + *should = false; + break; + } + case ACTOR_EN_EX_ITEM: { + *should = false; + break; + } + case ACTOR_EN_DNT_NOMAL: { + *should = false; + break; + } + case ACTOR_EN_DNT_DEMO: { + *should = false; + break; + } + case ACTOR_EN_TA: + case ACTOR_DOOR_SHUTTER: + case ACTOR_BG_ICE_SHUTTER: + case ACTOR_OBJ_LIGHTSWITCH: + case ACTOR_EN_BOX: + case ACTOR_OBJ_SYOKUDAI: + case ACTOR_OBJ_TIMEBLOCK: + case ACTOR_EN_PO_SISTERS: + case ACTOR_OBJ_ICE_POLY: + case ACTOR_BG_YDAN_MARUTA: + case ACTOR_BG_SPOT18_SHUTTER: + case ACTOR_BG_SPOT05_SOKO: + case ACTOR_BG_SPOT18_BASKET: + case ACTOR_BG_HIDAN_CURTAIN: + *should = false; + RateLimitedSuccessChime(); + break; + } + if (*should) { + SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_ACTOR_CS ID:{} Cat:{}", actor->id, actor->category); + } + } + break; + } + case GI_VB_SHOW_TITLE_CARD: + if (CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO)) { + *should = false; + } + break; + case GI_VB_WONDER_TALK: { + if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { + *should = false; + } + break; + } + case GI_VB_NAVI_TALK: { + if (CVarGetInteger("gTimeSavers.NoForcedDialog", IS_RANDO)) { + ElfMsg* naviTalk = static_cast(opt); + Flags_SetSwitch(gPlayState, (naviTalk->actor.params >> 8) & 0x3F); + Actor_Kill(&naviTalk->actor); + *should = false; + } + break; + } + case GI_VB_NOT_BE_GREETED_BY_SARIA: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { + Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA); + *should = true; + } + break; + case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST: + if ( + CVarGetInteger("gTimeSavers.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) + ) { + Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); + *should = true; + } + break; + case GI_VB_PLAY_DEKU_TREE_INTRO_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + BgTreemouth* treeMouth = static_cast(opt); + Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH); + Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + BgTreemouth_SetupAction(treeMouth, func_808BC6F8); + *should = false; + } + break; + } + case GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED: { + // We're overriding this so that the Deku JR doesn't despawn after skipping the forest temple blue warp cutscene. + // It typically relies on the forest medallion being obtained, but that isn't given yet until after scene init + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *should = Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); + } + break; + } + case GI_VB_GIVE_ITEM_FROM_BLUE_WARP: + case GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS: + case GI_VB_GIVE_ITEM_FAIRY_OCARINA: + case GI_VB_GIVE_ITEM_LIGHT_ARROW: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *should = false; + } + break; + case GI_VB_PLAY_NABOORU_CAPTURED_CS: + if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + Flags_SetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA); + *should = false; + } + break; + case GI_VB_PLAY_PULL_MASTER_SWORD_CS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { + // Normally, these would be done in the cutscene, but we're skipping it + Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); + Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); + Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); + Flags_SetEventChkInf(EVENTCHKINF_TIME_TRAVELED_TO_ADULT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { + Item_Give(gPlayState, ITEM_MEDALLION_LIGHT); + } + } + *should = false; + } + break; + case GI_VB_OWL_INTERACTION: { + if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", IS_RANDO) && *should) { + EnOwl* enOwl = static_cast(opt); + s32 owlType = (enOwl->actor.params & 0xFC0) >> 6; + + if (((enOwl->actor.params & 0xFC0) >> 6) == 1) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_KAEPORA_BY_LOST_WOODS); + } + + func_80ACA62C(enOwl, gPlayState); + *should = false; + } + break; + } + case GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + u16* textId = static_cast(opt); + // If the doors are not open yet, prioritize opening them + if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { + *textId = 0x3036; + *should = true; + } + } + break; + } + case GI_VB_PLAY_EYEDROP_CREATION_ANIM: + case GI_VB_PLAY_EYEDROPS_CS: + case GI_VB_PLAY_DROP_FISH_FOR_JABU_CS: + case GI_VB_PLAY_DARUNIAS_JOY_CS: + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + *should = false; + } + break; + case GI_VB_PLAY_ZELDAS_LULLABY_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + DemoIm* demoIm = static_cast(opt); + Player* player = GET_PLAYER(gPlayState); + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; + player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM; + func_80986794(demoIm); + + static uint32_t demoImUpdateHook = 0; + static uint32_t demoImKillHook = 0; + demoImUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* actorRef) mutable { + Actor* actor = static_cast(actorRef); + if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { + DemoIm* demoIm = static_cast(actorRef); + Player* player = GET_PLAYER(gPlayState); + player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; + player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM; + + if (Animation_OnFrame(&demoIm->skelAnime, 25.0f)) { + Audio_PlaySoundGeneral(NA_SE_IT_DEKU, &demoIm->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); + GameInteractor::Instance->UnregisterGameHook(demoImUpdateHook); + GameInteractor::Instance->UnregisterGameHook(demoImKillHook); + demoImUpdateHook = 0; + demoImKillHook = 0; + } else if (Animation_OnFrame(&demoIm->skelAnime, 15.0f)) { + Player* player = GET_PLAYER(gPlayState); + // SOH [Randomizer] In entrance rando have impa bring link back to the front of castle grounds + if (IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { + gPlayState->nextEntranceIndex = ENTR_HYRULE_CASTLE_0; + } else { + gPlayState->nextEntranceIndex = ENTR_HYRULE_FIELD_17; + } + gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000; + gPlayState->transitionType = TRANS_TYPE_FADE_WHITE; + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.nextTransitionType = 2; + Player_SetCsActionWithHaltedActors(gPlayState, &player->actor, 8); + } + } + }); + demoImKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(demoImUpdateHook); + GameInteractor::Instance->UnregisterGameHook(demoImKillHook); + demoImUpdateHook = 0; + demoImKillHook = 0; + }); + *should = false; + } + break; + } + case GI_VB_PLAY_SARIAS_SONG_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + EnSa* enSa = static_cast(opt); + enSa->actionFunc = func_80AF6B20; + *should = false; + } + break; + } + case GI_VB_DESPAWN_HORSE_RACE_COW: { + if (Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) && CVarGetInteger("gCowOfTime", 0)) { + *should = false; + } + break; + } + case GI_VB_PLAY_DRAIN_WELL_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *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", IS_RANDO) || 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", IS_RANDO)) { + *should = false; + } + break; + } + case GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + *should = Flags_GetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); + } + break; + } + case GI_VB_PLAY_DOOR_OF_TIME_CS: { + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO)) { + *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_BOLERO_OF_FIRE: + case GI_VB_GIVE_ITEM_SERENADE_OF_WATER: + case GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT: + case GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW: + case GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT: + case GI_VB_GIVE_ITEM_ZELDAS_LULLABY: + case GI_VB_GIVE_ITEM_EPONAS_SONG: + case GI_VB_GIVE_ITEM_SARIAS_SONG: + case GI_VB_GIVE_ITEM_SUNS_SONG: + case GI_VB_GIVE_ITEM_SONG_OF_TIME: + case GI_VB_GIVE_ITEM_SONG_OF_STORMS: + case GI_VB_PLAY_MINUET_OF_FOREST_CS: + case GI_VB_PLAY_BOLERO_OF_FIRE_CS: + case GI_VB_PLAY_SERENADE_OF_WATER_CS: + case GI_VB_PLAY_PRELUDE_OF_LIGHT_CS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO) { + *should = false; + } + break; + case GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN: + if (CVarGetInteger("gDampeAllNight", 0)) { + *should = LINK_IS_ADULT || gPlayState->sceneNum != SCENE_GRAVEYARD; + } + break; + case GI_VB_BE_VALID_GRAVEDIGGING_SPOT: + if (CVarGetInteger("gDampeWin", 0)) { + EnTk *enTk = static_cast(opt); + enTk->validDigHere = true; + *should = true; + } + break; + case GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE: + if (CVarGetInteger("gDampeWin", 0)) { + EnTk *enTk = static_cast(opt); + enTk->currentReward = 3; + *should = true; + } + break; + case GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE: + if (CVarGetInteger("gGravediggingTourFix", 0) || IS_RANDO) { + *should = !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE); + } + break; + case GI_VB_FIX_SAW_SOFTLOCK: + // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw + // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. + *should = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? gPlayState->animationCtx.animationCount > 1 : *should; + break; + case GI_VB_BIGGORON_CONSIDER_SWORD_FORGED: + *should = Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3); + break; + case GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD: { + BgDyYoseizo* bgDyYoseizo = static_cast(opt); + RandomizerInf flag = RAND_INF_MAX; + + if (gPlayState->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS) { + switch (bgDyYoseizo->fountainType) { + case 0: + flag = RAND_INF_ZF_GREAT_FAIRY_REWARD; + break; + case 1: + flag = RAND_INF_HC_GREAT_FAIRY_REWARD; + break; + case 2: + flag = RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD; + break; + } + } else { + switch (bgDyYoseizo->fountainType) { + case 0: + flag = RAND_INF_DMT_GREAT_FAIRY_REWARD; + break; + case 1: + flag = RAND_INF_DMC_GREAT_FAIRY_REWARD; + break; + case 2: + flag = RAND_INF_OGC_GREAT_FAIRY_REWARD; + break; + } + } + + if (flag != RAND_INF_MAX && (IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + if (IS_RANDO || *should) { + Flags_SetRandomizerInf(flag); + gSaveContext.healthAccumulator = 0x140; + Magic_Fill(gPlayState); + } + *should = false; + } + + break; + } + case GI_VB_PLAY_RAINBOW_BRIDGE_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *should = false; + func_800F595C(NA_BGM_BRIDGE_TO_GANONS); + } + break; + } + case GI_VB_PHANTOM_GANON_DEATH_SCENE: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO || IS_BOSS_RUSH)) { + *should = false; + BossGanondrof* pg = static_cast(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; + } + case GI_VB_NABOORU_KNUCKLE_DEATH_SCENE: { + EnIk* ik = static_cast(opt); + if (CVarGetInteger("gTimeSavers.SkipCutscene.QuickBossDeaths", IS_RANDO)) { + // Because no CS in rando, we hide the death of the knuckle by spawning flames and kill the actor + if ((ik->actor.colChkInfo.health <= 10)) { + s32 i; + Vec3f pos; + Vec3f sp7C = { 0.0f, 0.5f, 0.0f }; + int flameAmount = 100; + + for (i = flameAmount; i >= 0; i--) { + pos.x = ik->actor.world.pos.x + Rand_CenteredFloat(120.0f); + pos.z = ik->actor.world.pos.z + Rand_CenteredFloat(120.0f); + pos.y = ik->actor.world.pos.y + 20.0f + Rand_CenteredFloat(120.0f); + EffectSsDeadDb_Spawn(gPlayState, &pos, &sp7C, &sp7C, 100, 0, 255, 255, 255, 255, 0, 0, 255, 1, 9, + true); + } + Actor_Kill(&ik->actor); + } + *should = false; + } + break; + } + } +} + +static uint32_t enKoUpdateHook = 0; +static uint32_t enKoKillHook = 0; +static uint32_t itemOcarinaUpdateHook = 0; +static uint32_t itemOcarinaframesSinceSpawn = 0; +static uint32_t enMa1UpdateHook = 0; +static uint32_t enMa1KillHook = 0; +static uint32_t enFuUpdateHook = 0; +static uint32_t enFuKillHook = 0; +static uint32_t bgSpot02UpdateHook = 0; +static uint32_t bgSpot02KillHook = 0; +static uint32_t enPoSistersUpdateHook = 0; +static uint32_t enPoSistersKillHook = 0; +void TimeSaverOnActorInitHandler(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id == ACTOR_EN_KO && (actor->params & 0xFF) == ENKO_TYPE_CHILD_3) { + enKoUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO) || IS_RANDO)) { + EnKo* enKo = static_cast(innerActorRef); + // They haven't moved yet, wrap their update function so we check every frame + if (enKo->actionFunc == func_80A995CC) { + enKo->actionFunc = EnKo_MoveWhenReady; + GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enKoKillHook); + enKoUpdateHook = 0; + enKoKillHook = 0; + // They have already moved + } else if (enKo->actionFunc == func_80A99384) { + GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enKoKillHook); + enKoUpdateHook = 0; + enKoKillHook = 0; + } + } + }); + enKoKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enKoUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enKoKillHook); + enKoUpdateHook = 0; + enKoKillHook = 0; + }); + } + + if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + itemOcarinaframesSinceSpawn = 0; + itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id != ACTOR_ITEM_OCARINA || innerActor->params != 3) return; + itemOcarinaframesSinceSpawn++; + if (itemOcarinaframesSinceSpawn > 20) { + Audio_PlayActorSound2(innerActor, NA_SE_EV_BOMB_DROP_WATER); + + GameInteractor::Instance->UnregisterGameHook(itemOcarinaUpdateHook); + itemOcarinaUpdateHook = 0; + } + }); + } + + if (actor->id == ACTOR_EN_MA1 && gPlayState->sceneNum == SCENE_LON_LON_RANCH) { + enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { + EnMa1* enMa1 = static_cast(innerActorRef); + if (enMa1->actionFunc == func_80AA106C) { + enMa1->actionFunc = EnMa1_EndTeachSong; + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + // They've already learned the song + } else if (enMa1->actionFunc == func_80AA0D88) { + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + } + } + }); + enMa1KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enMa1UpdateHook); + GameInteractor::Instance->UnregisterGameHook(enMa1KillHook); + enMa1UpdateHook = 0; + enMa1KillHook = 0; + }); + } + + if (actor->id == ACTOR_EN_FU) { + enFuUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_FU && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", IS_RANDO) || IS_RANDO)) { + EnFu* enFu = static_cast(innerActorRef); + if (enFu->actionFunc == EnFu_TeachSong) { + enFu->actionFunc = EnFu_EndTeachSong; + GameInteractor::Instance->UnregisterGameHook(enFuUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enFuKillHook); + enFuUpdateHook = 0; + enFuKillHook = 0; + } + } + }); + enFuKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enFuUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enFuKillHook); + enFuUpdateHook = 0; + enFuKillHook = 0; + }); + } + + if (actor->id == ACTOR_BG_SPOT02_OBJECTS && actor->params == 2) { + bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_BG_SPOT02_OBJECTS && innerActor->params == 2 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + BgSpot02Objects* bgSpot02 = static_cast(innerActorRef); + if (bgSpot02->actionFunc == func_808ACC34) { + bgSpot02->actionFunc = func_808AC908; + GameInteractor::Instance->UnregisterGameHook(bgSpot02UpdateHook); + GameInteractor::Instance->UnregisterGameHook(bgSpot02KillHook); + bgSpot02UpdateHook = 0; + bgSpot02KillHook = 0; + } + } + }); + bgSpot02KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(bgSpot02UpdateHook); + GameInteractor::Instance->UnregisterGameHook(bgSpot02KillHook); + bgSpot02UpdateHook = 0; + bgSpot02KillHook = 0; + }); + } + + if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + EnZl4* enZl4 = static_cast(actorRef); + if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return; + + enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter; + } + + if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + EnDntDemo* enDntDemo = static_cast(actorRef); + enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; + } + + // Forest Temple entrance cutscene + // This is a bit of a hack, we can't effectively override the behavior of the torches + // or poes from which the cutscene is triggered until we can have a "BeforeActorInit" hook. + // So for now we're just going to set the flag before they get to the room the cutscene is in + if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && actor->id == ACTOR_EN_ST && !Flags_GetSwitch(gPlayState, 0x1B)) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { + Flags_SetSwitch(gPlayState, 0x1B); + } + } + + // Forest Temple purple poe fight speedup + if (actor->id == ACTOR_EN_PO_SISTERS && actor->params == 28) { + enPoSistersUpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_EN_PO_SISTERS && innerActor->params == 28 && (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO))) { + EnPoSisters* enPoSisters = static_cast(innerActorRef); + if (enPoSisters->actionFunc == func_80ADB338) { + enPoSisters->unk_19C = 0; + } + } + }); + enPoSistersKillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enPoSistersUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enPoSistersKillHook); + enPoSistersUpdateHook = 0; + enPoSistersKillHook = 0; + }); + } + + // Fire Temple Darunia cutscene + if (actor->id == ACTOR_EN_DU && gPlayState->sceneNum == SCENE_FIRE_TEMPLE) { + if (CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0)) { + Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); + Actor_Kill(actor); + } + } +} + +void TimeSaverOnSceneInitHandler(int16_t sceneNum) { + switch (sceneNum) { + case SCENE_HYRULE_CASTLE: + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); + } + break; + case SCENE_LON_LON_RANCH: + if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH); + Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); + Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); + } + break; + case SCENE_DEKU_TREE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE); + } + } + break; + case SCENE_DODONGOS_CAVERN_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE); + } + } + break; + case SCENE_JABU_JABU_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); + } + } + break; + case SCENE_FOREST_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE); + } + } + break; + case SCENE_FIRE_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); + } + } + break; + case SCENE_WATER_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE); + } + } + break; + case SCENE_SPIRIT_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE); + Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA); + } + } + break; + case SCENE_SHADOW_TEMPLE_BOSS: + if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", IS_RANDO)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE)) { + Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE); + } + } + break; + } +} + +static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE; + +void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) { + if (!CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) return; + + switch (flagType) { + case FLAG_EVENT_CHECK_INF: + switch (flag) { + case EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FAIRY_OCARINA).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_ZELDAS_LULLABY: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZELDAS_LULLABY).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_MINUET_OF_FOREST: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MINUET_OF_FOREST).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_BOLERO_OF_FIRE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_BOLERO_OF_FIRE).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SERENADE_OF_WATER: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SERENADE_OF_WATER).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_REQUIEM_OF_SPIRIT).GetGIEntry_Copy(); + break; + case EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NOCTURNE_OF_SHADOW).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_PRELUDE_OF_LIGHT).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SARIAS_SONG: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SARIAS_SONG).GetGIEntry_Copy(); + break; + case EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_GORON_RUBY).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZORA_SAPPHIRE).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FOREST_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FIRE_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_WATER_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_ARROWS).GetGIEntry_Copy(); + break; + case EVENTCHKINF_TIME_TRAVELED_TO_ADULT: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_MEDALLION).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SONG_OF_TIME: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_TIME).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SONG_OF_STORMS: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy(); + break; + case EVENTCHKINF_LEARNED_SUNS_SONG: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SUNS_SONG).GetGIEntry_Copy(); + break; + } + break; + case FLAG_RANDOMIZER_INF: + switch (flag) { + case RAND_INF_LEARNED_EPONA_SONG: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_EPONAS_SONG).GetGIEntry_Copy(); + break; + case RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SHADOW_MEDALLION).GetGIEntry_Copy(); + break; + case RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SPIRIT_MEDALLION).GetGIEntry_Copy(); + break; + case RAND_INF_ZF_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FARORES_WIND).GetGIEntry_Copy(); + break; + case RAND_INF_HC_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DINS_FIRE).GetGIEntry_Copy(); + break; + case RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NAYRUS_LOVE).GetGIEntry_Copy(); + break; + case RAND_INF_DMT_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_SINGLE).GetGIEntry_Copy(); + break; + case RAND_INF_DMC_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_DOUBLE).GetGIEntry_Copy(); + break; + case RAND_INF_OGC_GREAT_FAIRY_REWARD: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DOUBLE_DEFENSE).GetGIEntry_Copy(); + break; + } + break; + case FLAG_ITEM_GET_INF: + switch (flag) { + case ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DEKU_STICK_CAPACITY_30).GetGIEntry_Copy(); + break; + case ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE: + vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DEKU_NUT_CAPACITY_40).GetGIEntry_Copy(); + break; + } + break; + } +} + +void TimeSaverOnPlayerUpdateHandler() { + if (vanillaQueuedItemEntry.itemId == ITEM_NONE) return; + + Player* player = GET_PLAYER(gPlayState); + if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { + return; + } + + SPDLOG_INFO("Attempting to give Item: mod {} item {}", vanillaQueuedItemEntry.modIndex, vanillaQueuedItemEntry.itemId); + GiveItemEntryWithoutActor(gPlayState, vanillaQueuedItemEntry); + if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) { + // Allow the player to receive the item while swimming + player->stateFlags2 |= PLAYER_STATE2_UNDERWATER; + Player_ActionChange_2(player, gPlayState); + } +} + +void TimeSaverOnItemReceiveHandler(GetItemEntry receivedItemEntry) { + if (vanillaQueuedItemEntry.itemId == ITEM_NONE) return; + + if (vanillaQueuedItemEntry.modIndex == receivedItemEntry.modIndex && vanillaQueuedItemEntry.itemId == receivedItemEntry.itemId) { + SPDLOG_INFO("Item received: mod {} item {}", receivedItemEntry.modIndex, receivedItemEntry.itemId); + vanillaQueuedItemEntry = GET_ITEM_NONE; + } +} + +static uint32_t onSceneInitHook = 0; +static uint32_t onVanillaBehaviorHook = 0; +static uint32_t onActorInitHook = 0; +static uint32_t onGameFrameUpdate = 0; +static uint32_t onFlagSetHook = 0; +static uint32_t onPlayerUpdateHook = 0; +static uint32_t onItemReceiveHook = 0; +void TimeSaverRegisterHooks() { + GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) mutable { + vanillaQueuedItemEntry = GET_ITEM_NONE; + + GameInteractor::Instance->UnregisterGameHook(onSceneInitHook); + GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook); + GameInteractor::Instance->UnregisterGameHook(onActorInitHook); + GameInteractor::Instance->UnregisterGameHook(onGameFrameUpdate); + GameInteractor::Instance->UnregisterGameHook(onFlagSetHook); + GameInteractor::Instance->UnregisterGameHook(onPlayerUpdateHook); + GameInteractor::Instance->UnregisterGameHook(onItemReceiveHook); + + onSceneInitHook = 0; + onVanillaBehaviorHook = 0; + onActorInitHook = 0; + onGameFrameUpdate = 0; + onFlagSetHook = 0; + onPlayerUpdateHook = 0; + onItemReceiveHook = 0; + + onSceneInitHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnSceneInitHandler); + onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnVanillaBehaviorHandler); + onActorInitHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnActorInitHandler); + onGameFrameUpdate = GameInteractor::Instance->RegisterGameHook(TimeSaverOnGameFrameUpdateHandler); + + if (IS_RANDO) return; + + onFlagSetHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnFlagSetHandler); + onPlayerUpdateHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnPlayerUpdateHandler); + onItemReceiveHook = GameInteractor::Instance->RegisterGameHook(TimeSaverOnItemReceiveHandler); + }); +} diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.h b/soh/soh/Enhancements/timesaver_hook_handlers.h new file mode 100644 index 000000000..41bccd8d9 --- /dev/null +++ b/soh/soh/Enhancements/timesaver_hook_handlers.h @@ -0,0 +1,6 @@ +#ifndef TIMESAVER_HOOK_HANDLERS_H +#define TIMESAVER_HOOK_HANDLERS_H + +void TimeSaverRegisterHooks(); + +#endif // TIMESAVER_HOOK_HANDLERS_H \ No newline at end of file diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index f4b498815..3a375230f 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,7 +13,6 @@ #include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/resource/type/SohResourceType.h" -#include "soh/resource/type/RawJson.h" extern "C" { extern MapData* gMapData; @@ -1041,19 +1041,19 @@ void InitTTSBank() { auto initData = std::make_shared(); initData->Format = RESOURCE_FORMAT_BINARY; - initData->Type = static_cast(SOH::ResourceType::SOH_RawJson); + initData->Type = static_cast(LUS::ResourceType::Json); initData->ResourceVersion = 0; - sceneMap = std::static_pointer_cast( + sceneMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data; - miscMap = std::static_pointer_cast( + miscMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data; - kaleidoMap = std::static_pointer_cast( + kaleidoMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data; - fileChooseMap = std::static_pointer_cast( + fileChooseMap = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data; } diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index f8c292b59..2f166ada0 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -120,10 +120,13 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/importer/SkeletonLimbFactory.h" #include "soh/resource/importer/TextFactory.h" #include "soh/resource/importer/BackgroundFactory.h" -#include "soh/resource/importer/RawJsonFactory.h" #include "soh/config/ConfigUpdaters.h" +extern "C" { +#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" +} + void SoH_ProcessDroppedFiles(std::string filePath); OTRGlobals* OTRGlobals::Instance; @@ -345,7 +348,6 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast(SOH::ResourceType::SOH_AudioSoundFont), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast(SOH::ResourceType::SOH_AudioSequence), 2); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Background", static_cast(SOH::ResourceType::SOH_Background), 0); - loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast(SOH::ResourceType::SOH_RawJson), 0); gSaveStateMgr = std::make_shared(); gRandoContext->InitStaticData(); @@ -2348,8 +2350,8 @@ extern "C" void Randomizer_LoadMerchantMessages() { OTRGlobals::Instance->gRandomizer->LoadMerchantMessages(); } -extern "C" bool Randomizer_IsTrialRequired(RandomizerInf trial) { - return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trial); +extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) { + return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag); } extern "C" u32 SpoilerFileExists(const char* spoilerFileName) { @@ -2563,9 +2565,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); // textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT) - } else if (textId >= TEXT_SCRUB_RANDOM && textId <= TEXT_SCRUB_RANDOM + NUM_SCRUBS) { - RandomizerInf randoInf = (RandomizerInf)((textId - TEXT_SCRUB_RANDOM) + RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); + } else if (textId == TEXT_SCRUB_RANDOM) { + EnDns* enDns = (EnDns*)GET_PLAYER(play)->targetActor; + messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(enDns->sohScrubIdentity.randomizerInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index c90f07316..00b643bcb 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -159,7 +159,7 @@ FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams); void Randomizer_ParseSpoiler(const char* fileLoc); void Randomizer_LoadHintMessages(); void Randomizer_LoadMerchantMessages(); -bool Randomizer_IsTrialRequired(RandomizerInf trial); +bool Randomizer_IsTrialRequired(s32 trialFlag); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index a164c8a3d..c61c08100 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -403,6 +403,13 @@ void SaveManager::LoadRandomizerVersion3() { // all ItemLocations is 0 anyway. randoContext->GetItemLocation(i)->SetCustomPrice(price); } + uint16_t obtained = 0; + SaveManager::Instance->LoadData("obtained", obtained, (uint16_t)0); + if (obtained) { + randoContext->GetItemLocation(i)->MarkAsObtained(); + } else { + randoContext->GetItemLocation(i)->MarkAsNotObtained(); + } }); }); @@ -488,6 +495,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f if (randoContext->GetItemLocation(i)->HasCustomPrice()) { SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice()); } + SaveManager::Instance->SaveData("obtained", randoContext->GetItemLocation(i)->HasObtained()); }); }); @@ -817,6 +825,9 @@ void SaveManager::InitFileNormal() { for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.infTable); flag++) { gSaveContext.infTable[flag] = 0; } + for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.randomizerInf); flag++) { + gSaveContext.randomizerInf[flag] = 0; + } gSaveContext.worldMapAreaData = 0; gSaveContext.scarecrowLongSongSet = 0; for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f09de4e06..98de7a48c 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -72,6 +72,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large }; static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" }; + static const char* skipGetItemAnimationOptions[3] = { "Disabled", "Junk Items", "All Items" }; static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" }; static const char* mirroredWorldModes[9] = { "Disabled", "Always", "Random", "Random (Seeded)", "Dungeons", @@ -574,6 +575,88 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); ImGui::Text("Speed-ups:"); UIWidgets::PaddedSeparator(); + bool allChecked = + CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) && + CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) && + 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) && + CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) && + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); + bool someChecked = + CVarGetInteger("gTimeSavers.SkipCutscene.Intro", IS_RANDO) || + CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", IS_RANDO) || + 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) || + CVarGetInteger("gTimeSavers.SkipMiscInteractions", IS_RANDO) || + CVarGetInteger("gTimeSavers.DisableTitleCard", IS_RANDO); + + ImGuiContext* g = ImGui::GetCurrentContext(); + ImGuiItemFlags backup_item_flags = g->CurrentItemFlags; + if (!allChecked && someChecked) g->CurrentItemFlags |= ImGuiItemFlags_MixedValue; + if (ImGui::Checkbox("All", &allChecked)) { + if (allChecked) { + CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 1); + CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 1); + 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); + CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1); + CVarSetInteger("gTimeSavers.DisableTitleCard", 1); + } else { + CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0); + CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0); + 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); + CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0); + CVarSetInteger("gTimeSavers.DisableTitleCard", 0); + } + LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } + g->CurrentItemFlags = backup_item_flags; + UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + 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"); + UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); + UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); + UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); + UIWidgets::PaddedEnhancementCheckbox("Skip Child Stealth", "gTimeSavers.SkipChildStealth", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::Tooltip("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); + UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", "gTimeSavers.SkipTowerEscape", false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); + UIWidgets::Tooltip("Skip the tower escape sequence between Ganondorf and Ganon."); + + UIWidgets::PaddedText("Skip Get Item Animations", true, false); + UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED); + if (CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) != SGIA_DISABLED) { + UIWidgets::EnhancementSliderFloat("Item Scale: %f", "##ItemScale", "gTimeSavers.SkipGetItemAnimationScale", 5.0f, 15.0f, "", 10.0f, false); + UIWidgets::Tooltip("The size of the item when it is picked up"); + } UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true); @@ -605,7 +688,7 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); ImGui::Text("Changes:"); UIWidgets::PaddedSeparator(); - + UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true); UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false); @@ -1208,7 +1291,8 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); - UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false, SaveManager::Instance->IsRandoFile(), + "This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); diff --git a/soh/soh/resource/importer/RawJsonFactory.cpp b/soh/soh/resource/importer/RawJsonFactory.cpp deleted file mode 100644 index 4978f6f96..000000000 --- a/soh/soh/resource/importer/RawJsonFactory.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "soh/resource/importer/RawJsonFactory.h" -#include "soh/resource/type/RawJson.h" -#include "spdlog/spdlog.h" - -namespace SOH { -std::shared_ptr ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr file) { - if (!FileHasValidFormatAndReader(file)) { - return nullptr; - } - - auto rawJson = std::make_shared(file->InitData); - auto reader = std::get>(file->Reader); - - rawJson->DataSize = file->Buffer->size(); - rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true); - - return rawJson; -} -} // namespace SOH diff --git a/soh/soh/resource/importer/RawJsonFactory.h b/soh/soh/resource/importer/RawJsonFactory.h deleted file mode 100644 index d5fa656b6..000000000 --- a/soh/soh/resource/importer/RawJsonFactory.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "resource/Resource.h" -#include "resource/ResourceFactoryBinary.h" - -namespace SOH { -class ResourceFactoryBinaryRawJsonV0 : public LUS::ResourceFactoryBinary { - public: - std::shared_ptr ReadResource(std::shared_ptr file) override; -}; -}; // namespace SOH diff --git a/soh/soh/resource/type/RawJson.cpp b/soh/soh/resource/type/RawJson.cpp deleted file mode 100644 index 3022a67ef..000000000 --- a/soh/soh/resource/type/RawJson.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "RawJson.h" - -namespace SOH { -RawJson::RawJson() : Resource(std::shared_ptr()) { -} - -void* RawJson::GetPointer() { - return &Data; -} - -size_t RawJson::GetPointerSize() { - return DataSize * sizeof(char); -} -} // namespace SOH diff --git a/soh/soh/resource/type/RawJson.h b/soh/soh/resource/type/RawJson.h deleted file mode 100644 index 47e0323cc..000000000 --- a/soh/soh/resource/type/RawJson.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "resource/Resource.h" -#include - -namespace SOH { - -class RawJson : public LUS::Resource { - public: - using Resource::Resource; - - RawJson(); - - void* GetPointer() override; - size_t GetPointerSize() override; - - nlohmann::json Data; - size_t DataSize; -}; -}; // namespace SOH diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index 3ef4163fe..fdf39031e 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -17,6 +17,5 @@ enum class ResourceType { SOH_AudioSequence = 0x4F534551, // OSEQ SOH_Background = 0x4F424749, // OBGI SOH_SceneCommand = 0x4F52434D, // ORCM - SOH_RawJson = 0x4A534F4E, // JSON }; } // namespace SOH diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index c34ee9a9e..e1002d114 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1462,7 +1462,7 @@ s32 func_8002DF38(PlayState* play, Actor* actor, u8 csAction) { return true; } -s32 func_8002DF54(PlayState* play, Actor* actor, u8 csAction) { +s32 Player_SetCsActionWithHaltedActors(PlayState* play, Actor* actor, u8 csAction) { Player* player = GET_PLAYER(play); func_8002DF38(play, actor, csAction); @@ -2084,9 +2084,8 @@ s32 GiveItemEntryFromActorWithFixedRange(Actor* actor, PlayState* play, GetItemE return GiveItemEntryFromActor(actor, play, getItemEntry, 50.0f, 10.0f); } -// TODO: Rename to GiveItemIdFromActor or similar // If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActor -s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) { +s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 yRange) { Player* player = GET_PLAYER(play); if (!(player->stateFlags1 & @@ -2116,7 +2115,7 @@ s32 func_8002F434(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange, f32 // TODO: Rename to GiveItemIdFromActorWithFixedRange or similar // If you're doing something for randomizer, you're probably looking for GiveItemEntryFromActorWithFixedRange void func_8002F554(Actor* actor, PlayState* play, s32 getItemId) { - func_8002F434(actor, play, getItemId, 50.0f, 10.0f); + Actor_OfferGetItem(actor, play, getItemId, 50.0f, 10.0f); } void func_8002F580(Actor* actor, PlayState* play) { @@ -6283,58 +6282,3 @@ s32 func_80038290(PlayState* play, Actor* actor, Vec3s* arg2, Vec3s* arg3, Vec3f return true; } - -GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, PlayState* play) { - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - // RANDOTODO update this logic when we implement keysanity - // because 3drando replaces the keys not the rupees - if (ogDrawId == GID_RUPEE_GREEN || - ogDrawId == GID_RUPEE_BLUE || - ogDrawId == GID_RUPEE_RED) - { - switch(room) { - case 1: - if(!Flags_GetCollectible(play, 0x1B)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, GI_RUPEE_GREEN); - } - break; - case 2: - if(!Flags_GetCollectible(play, 0x1C)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, GI_RUPEE_GREEN); - } - break; - case 3: - if(!Flags_GetCollectible(play, 0x1D)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, GI_RUPEE_BLUE); - } - break; - case 4: - if(!Flags_GetCollectible(play, 0x1E)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, GI_RUPEE_BLUE); - } - break; - case 5: - if(!Flags_GetCollectible(play, 0x1F)) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, GI_RUPEE_RED); - } - break; - } - } - } - - if(ogDrawId == GID_HEART_PIECE) { - return Randomizer_GetItemFromKnownCheck(RC_MARKET_TREASURE_CHEST_GAME_REWARD, GI_HEART_PIECE); - } - - return (GetItemEntry)GET_ITEM_NONE; -} - -s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(room, ogDrawId, play); - - if (randoGetItem.itemId != ITEM_NONE) { - return randoGetItem.gid; - } - - return ogDrawId; -} diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 90634ea31..b5719d48c 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -6184,14 +6184,14 @@ s32 Camera_Demo5(Camera* camera) { pad = camera->play->state.frames - sDemo5PrevAction12Frame; if (player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) { // holding object over head. - func_8002DF54(camera->play, camera->target, 8); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 8); } else if (ABS(pad) > 3000) { - func_8002DF54(camera->play, camera->target, 12); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 12); } else { - func_8002DF54(camera->play, camera->target, 69); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 69); } } else { - func_8002DF54(camera->play, camera->target, 1); + Player_SetCsActionWithHaltedActors(camera->play, camera->target, 1); } } @@ -6250,7 +6250,7 @@ s32 Camera_Demo6(Camera* camera) { camera->animState++; case 1: if (stateTimers[camera->animState] < anim->animTimer) { - func_8002DF54(camera->play, &camera->player->actor, 8); + Player_SetCsActionWithHaltedActors(camera->play, &camera->player->actor, 8); Actor_GetWorld(&focusPosRot, camFocus); anim->atTarget.x = focusPosRot.pos.x; anim->atTarget.y = focusPosRot.pos.y - 20.0f; @@ -7735,7 +7735,7 @@ void Camera_Finish(Camera* camera) { player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; if (player->csAction != 0) { - func_8002DF54(camera->play, &player->actor, 7); + Player_SetCsActionWithHaltedActors(camera->play, &player->actor, 7); osSyncPrintf("camera: player demo end!!\n"); } diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index 9c0dd9b05..94b04580f 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -32,6 +32,7 @@ #include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" u16 D_8011E1C0 = 0; u16 D_8011E1C4 = 0; @@ -485,6 +486,7 @@ void func_80065134(PlayState* play, CutsceneContext* csCtx, CsCmdDayTime* cmd) { gSaveContext.dayTime = temp1 + temp2; gSaveContext.skyboxTime = temp1 + temp2; + LUSLOG_INFO("SET TIME %d", gSaveContext.dayTime); } } @@ -493,11 +495,16 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB Player* player = GET_PLAYER(play); s32 temp = 0; - // Automatically skip certain cutscenes when in rando - // cmd->base == 8: Traveling back/forward in time cutscene - // cmd->base == 24: Dropping a fish for Jabu Jabu - // cmd->base == 33: Zelda escaping with impa cutscene - bool randoCsSkip = (IS_RANDO && (cmd->base == 8 || cmd->base == 24 || cmd->base == 33)); + bool shouldSkipCommand = false; + + if (cmd->base == 8 && !GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, true, NULL)) { + shouldSkipCommand = true; + } + + if (cmd->base == 24 && !GameInteractor_Should(GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, true, NULL)) { + shouldSkipCommand = true; + } + bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) && (gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0)); @@ -558,7 +565,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB } } - if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (randoCsSkip || debugCsSkip))) { + if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (shouldSkipCommand || debugCsSkip))) { csCtx->state = CS_STATE_UNSKIPPABLE_EXEC; Audio_SetCutsceneFlag(0); @@ -624,7 +631,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB gSaveContext.fw.set = 0; gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0; } - if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) { + if (GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, !Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL), NULL)) { Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL); play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0; play->transitionTrigger = TRANS_TRIGGER_START; @@ -716,7 +723,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_FADE_WHITE; break; case 22: - Item_Give(play, ITEM_SONG_REQUIEM); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) { + Item_Give(play, ITEM_SONG_REQUIEM); + } play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; play->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.cutsceneIndex = 0xFFF0; @@ -768,7 +777,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_WHITE; - Item_Give(play, ITEM_MEDALLION_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FIRE); + } gSaveContext.chamberCutsceneNum = 1; break; case 31: @@ -848,7 +859,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->transitionType = TRANS_TYPE_FADE_BLACK_FAST; break; case 47: - Item_Give(play, ITEM_SONG_NOCTURNE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) { + Item_Give(play, ITEM_SONG_NOCTURNE); + } Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW); play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; play->transitionTrigger = TRANS_TRIGGER_START; @@ -1292,7 +1305,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB break; } - if (randoCsSkip) { + if (shouldSkipCommand && IS_RANDO) { Entrance_OverrideCutsceneEntrance(cmd->base); } } @@ -1561,7 +1574,49 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText } else if ((cmd->type == 4) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { Message_StartTextbox(play, cmd->textId1, NULL); } else { + GetItemEntry getItemEntry = GET_ITEM_NONE; + if (IS_RANDO) { + switch (cmd->base) { + case 0x80: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD); + break; + case 0x81: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY); + break; + case 0x82: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + break; + case 0x3E: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION); + break; + case 0x3C: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION); + break; + case 0x3D: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION); + break; + case 0x3F: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION); + break; + case 0x41: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION); + break; + case 0x40: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION); + break; + case 0x72: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS); + break; + } + if (getItemEntry.getItemId != GI_NONE) { + // cmd->base = getItemEntry.textId; + // GET_PLAYER(play)->getItemEntry = getItemEntry; + } + } Message_StartTextbox(play, cmd->base, NULL); + if (IS_RANDO && getItemEntry.getItemId != GI_NONE) { + // GET_PLAYER(play)->getItemEntry = (GetItemEntry)GET_ITEM_NONE; + } } return; } @@ -1584,12 +1639,14 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText if ((dialogState == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { if (play->msgCtx.choiceIndex == 0) { if (cmd->textId1 != 0xFFFF) { + // LUSLOG_INFO("Cutscene_Command_Textbox D: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2); Message_ContinueTextbox(play, cmd->textId1); } else { csCtx->frames++; } } else { if (cmd->textId2 != 0xFFFF) { + // LUSLOG_INFO("Cutscene_Command_Textbox E: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2); Message_ContinueTextbox(play, cmd->textId2); } else { csCtx->frames++; @@ -1599,6 +1656,7 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText if (dialogState == TEXT_STATE_9) { if (cmd->textId1 != 0xFFFF) { + // LUSLOG_INFO("Cutscene_Command_Textbox F: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2); Message_ContinueTextbox(play, cmd->textId1); } else { csCtx->frames++; @@ -2113,34 +2171,23 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) { u8 requiredAge; s16 i; - if (IS_RANDO && - // don't skip epona escape cutscenes - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_11 && - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_12 && - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_13 && - gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_15 && - // don't skip nabooru iron knuckle cs - gSaveContext.entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_0) { - gSaveContext.showTitleCard = false; - return; - } - for (i = 0; i < ARRAY_COUNT(sEntranceCutsceneTable); i++) { entranceCutscene = &sEntranceCutsceneTable[i]; - requiredAge = entranceCutscene->ageRestriction; if (requiredAge == 2) { requiredAge = gSaveContext.linkAge; } if ((gSaveContext.entranceIndex == entranceCutscene->entrance) && - (!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == 0x18)) && + (!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == EVENTCHKINF_EPONA_OBTAINED)) && (gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) && (gSaveContext.respawnFlag <= 0)) { Flags_SetEventChkInf(entranceCutscene->flag); - Cutscene_SetSegment(play, entranceCutscene->segAddr); - gSaveContext.cutsceneTrigger = 2; - gSaveContext.showTitleCard = false; + if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &entranceCutscene->flag)) { + Cutscene_SetSegment(play, entranceCutscene->segAddr); + gSaveContext.cutsceneTrigger = 2; + gSaveContext.showTitleCard = false; + } break; } } @@ -2148,48 +2195,48 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) { void Cutscene_HandleConditionalTriggers(PlayState* play) { osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag)); + LUSLOG_INFO("Cutscene_HandleConditionalTriggers - entranceIndex: %#x cutsceneIndex: %#x", gSaveContext.entranceIndex, gSaveContext.cutsceneIndex); + + if (!GameInteractor_Should(GI_VB_PLAY_TRANSITION_CS, true, NULL)) { + return; + } if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { - const bool bShouldTowerRandoSkip = - (IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE)); if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); - gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0; - gSaveContext.cutsceneIndex = 0xFFF0; - } - } else if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && LINK_IS_ADULT && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) && - (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) && (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) && - !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); - gSaveContext.cutsceneIndex = 0xFFF0; - } + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT); + gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0; + gSaveContext.cutsceneIndex = 0xFFF0; + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, ( + (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && + LINK_IS_ADULT && + Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) && + Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) && + !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) + ), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL); + gSaveContext.cutsceneIndex = 0xFFF0; } else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) { Item_Give(play, ITEM_OCARINA_FAIRY); - gSaveContext.entranceIndex = ENTR_LOST_WOODS_0; - gSaveContext.cutsceneIndex = 0xFFF0; } - } else if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); - gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0; - gSaveContext.cutsceneIndex = 0xFFF8; - } - } else if ((!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) && - gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS) || - (bShouldTowerRandoSkip && - gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR)) { + gSaveContext.entranceIndex = ENTR_LOST_WOODS_0; + gSaveContext.cutsceneIndex = 0xFFF0; + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, ( + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + LINK_IS_ADULT && + !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) + ), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); + gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0; + gSaveContext.cutsceneIndex = 0xFFF8; + } else if (!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) && + (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS)) { Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; - // In rando, skip the cutscene for the tower falling down after the escape. - if (IS_RANDO) { - return; - } gSaveContext.cutsceneIndex = 0xFFF0; } } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 77f42aebd..873a91ec9 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h" #include "textures/icon_item_static/icon_item_static.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -349,6 +350,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { s32 getItemId = GI_NONE; this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE; this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK; + this->itemEntry = (GetItemEntry)GET_ITEM_NONE; s16 spawnParam8000 = this->actor.params & 0x8000; s32 pad1; @@ -358,7 +360,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.params &= 0xFF; - if (Flags_GetCollectible(play, this->collectibleFlag)) { + if (GameInteractor_Should(GI_VB_ITEM00_DESPAWN, Flags_GetCollectible(play, this->collectibleFlag), this)) { Actor_Kill(&this->actor); return; } @@ -381,12 +383,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->unk_158 = 0; Actor_SetScale(&this->actor, 0.03f); this->scale = 0.03f; - // Offset keys in randomizer slightly higher for their GID replacement - if (!IS_RANDO) { - yOffset = 350.0f; - } else { - yOffset = 430.0f; - } + yOffset = 350.0f; break; case ITEM00_HEART_PIECE: this->unk_158 = 0; @@ -479,6 +476,14 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { Actor_SetScale(&this->actor, 0.03f); this->scale = 0.03f; break; + case ITEM00_SOH_GIVE_ITEM_ENTRY: + case ITEM00_SOH_GIVE_ITEM_ENTRY_GI: + case ITEM00_SOH_DUMMY: + this->unk_158 = 0; + Actor_SetScale(&this->actor, 0.03f); + this->scale = 0.03f; + yOffset = 430.0f; + break; } this->unk_156 = 0; @@ -507,6 +512,10 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { this->actor.velocity.y = 0.0f; this->actor.gravity = 0.0f; + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { + return; + } + switch (this->actor.params) { case ITEM00_RUPEE_GREEN: Item_Give(play, ITEM_RUPEE_GREEN); @@ -576,16 +585,8 @@ void EnItem00_Init(Actor* thisx, PlayState* play) { break; } - if (!Actor_HasParent(&this->actor, play)) { - if (getItemId != GI_NONE) { - if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) { - func_8002F554(&this->actor, play, getItemId); - } else { - if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(this->randoInf); - } - } - } + if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) { + func_8002F554(&this->actor, play, getItemId); } EnItem00_SetupAction(this, func_8001E5C8); @@ -603,8 +604,7 @@ void func_8001DFC8(EnItem00* this, PlayState* play) { (this->actor.params == ITEM00_HEART_PIECE)) { this->actor.shape.rot.y += 960; } else { - if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) && - (this->actor.params != ITEM00_BOMBCHU)) { + if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) { if (this->unk_15A == -1) { if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) == 0) { @@ -697,8 +697,7 @@ void func_8001E304(EnItem00* this, PlayState* play) { if (this->actor.params <= ITEM00_RUPEE_RED) { this->actor.shape.rot.y += 960; - } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) && - (this->actor.params != ITEM00_BOMBCHU)) { + } else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) { this->actor.world.rot.x -= 700; this->actor.shape.rot.y += 400; this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000; @@ -733,13 +732,7 @@ void func_8001E5C8(EnItem00* this, PlayState* play) { Player* player = GET_PLAYER(play); if (this->getItemId != GI_NONE) { if (!Actor_HasParent(&this->actor, play)) { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f); - } else { - if (GiveItemEntryFromActor(&this->actor, play, this->randoGiEntry, 50.0f, 80.0f) && this->randoInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(this->randoInf); - } - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 50.0f, 80.0f); this->unk_15A++; } else { this->getItemId = GI_NONE; @@ -781,13 +774,15 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { s32 pad; // Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect - if ((this->actor.params == ITEM00_HEART && this->unk_15A >= 0) || + if ( + (this->actor.params == ITEM00_HEART && this->unk_15A >= 0) || (this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) || - this->actor.params == ITEM00_BOMBS_A || this->actor.params == ITEM00_ARROWS_SINGLE || - this->actor.params == ITEM00_BOMBS_SPECIAL || this->actor.params == ITEM00_BOMBCHU) { - if (CVarGetInteger("gNewDrops", 0) || - // Keys in randomizer need to always rotate for their GID replacement - (IS_RANDO && this->actor.params == ITEM00_SMALL_KEY)) { + this->actor.params == ITEM00_BOMBS_A || + this->actor.params == ITEM00_ARROWS_SINGLE || + this->actor.params == ITEM00_BOMBS_SPECIAL || + (this->actor.params >= ITEM00_BOMBCHU && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI) + ) { + if (CVarGetInteger("gNewDrops", 0) || (this->actor.params >= ITEM00_SOH_DUMMY && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI)) { this->actor.shape.rot.y += 960; } else { this->actor.shape.rot.y = 0; @@ -871,6 +866,10 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { return; } + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) { + return; + } + switch (this->actor.params) { case ITEM00_RUPEE_GREEN: Item_Give(play, ITEM_RUPEE_GREEN); @@ -955,14 +954,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) { params = &this->actor.params; if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) { - if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) { - func_8002F554(&this->actor, play, getItemId); - } else { - getItemId = this->randoGiEntry.getItemId; - if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(this->randoInf); - } - } + func_8002F554(&this->actor, play, getItemId); } switch (*params) { @@ -1052,7 +1044,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { } break; case ITEM00_HEART_PIECE: - if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { + if (CVarGetInteger("gNewDrops", 0)) { mtxScale = 21.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_HEART_PIECE); @@ -1162,7 +1154,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) { break; } case ITEM00_SMALL_KEY: - if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) { + if (CVarGetInteger("gNewDrops", 0)) { mtxScale = 8.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItem_Draw(play, GID_KEY_SMALL); @@ -1368,17 +1360,7 @@ static const Vtx customDropVtx[] = { * Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...). */ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { - if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { - if (this->randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; - } - - f32 mtxScale = 10.67f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); - } else if (this->actor.params == ITEM00_BOMBCHU) { + if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); Matrix_ReplaceRotation(&play->billboardMtxF); @@ -1458,29 +1440,17 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) { * Draw Function used for the Piece of Heart type of En_Item00. */ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { - if (IS_RANDO) { - if (this->randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; - } + s32 pad; - f32 mtxScale = 16.0f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); - } else { - s32 pad; + OPEN_DISPS(play->state.gfxCtx); - OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + func_8002ED80(&this->actor, play, 0); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL); - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - func_8002ED80(&this->actor, play, 0); - gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL); - - CLOSE_DISPS(play->state.gfxCtx); - } + CLOSE_DISPS(play->state.gfxCtx); } /** diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 213ee018d..5ed13f810 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -395,7 +395,7 @@ void Map_InitData(PlayState* play, s16 room) { } else if (play->sceneNum == SCENE_LAKE_HYLIA) { if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)))) { + (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)))) { extendedMapIndex = 0x15; } } else if (play->sceneNum == SCENE_GERUDO_VALLEY) { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 7938bad01..a025a2c0d 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2607,8 +2607,23 @@ void Message_DrawMain(PlayState* play, Gfx** p) { msgCtx->lastPlayedSong = msgCtx->ocarinaStaff->state; msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_SUCCESS; - if (!IS_RANDO) { - Item_Give(play, ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]); + u8 songItemId = ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]; + + if ( + (songItemId == ITEM_SONG_MINUET && GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) || + (songItemId == ITEM_SONG_BOLERO && GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) || + (songItemId == ITEM_SONG_SERENADE && GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) || + (songItemId == ITEM_SONG_REQUIEM && GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) || + (songItemId == ITEM_SONG_NOCTURNE && GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) || + (songItemId == ITEM_SONG_PRELUDE && GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) || + (songItemId == ITEM_SONG_LULLABY && GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) || + (songItemId == ITEM_SONG_EPONA && GameInteractor_Should(GI_VB_GIVE_ITEM_EPONAS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_SARIA && GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_SUN && GameInteractor_Should(GI_VB_GIVE_ITEM_SUNS_SONG, true, NULL)) || + (songItemId == ITEM_SONG_TIME && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_TIME, true, NULL)) || + (songItemId == ITEM_SONG_STORMS && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_STORMS, true, NULL)) + ) { + Item_Give(play, songItemId); } osSyncPrintf(VT_FGCOL(YELLOW)); diff --git a/soh/src/code/z_onepointdemo.c b/soh/src/code/z_onepointdemo.c index 2ece7c2f1..24a8820af 100644 --- a/soh/src/code/z_onepointdemo.c +++ b/soh/src/code/z_onepointdemo.c @@ -1,6 +1,7 @@ #include "global.h" #include "vt.h" #include "overlays/actors/ovl_En_Sw/z_en_sw.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" static s16 sDisableAttention = false; static s16 sUnused = -1; @@ -267,7 +268,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor case 2290: { Actor* rideActor = player->rideActor; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (rideActor != NULL) { rideActor->freezeTimer = 180; } @@ -278,7 +279,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); } break; case 5120: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_80121314; csInfo->keyFrameCnt = 1; @@ -288,7 +289,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor case 4510: D_8012133C[0].eyeTargetInit = actor->world.pos; D_8012133C[0].eyeTargetInit.y = player->actor.world.pos.y + 40.0f; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_8012133C; csInfo->keyFrameCnt = 3; @@ -306,7 +307,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor OnePointCutscene_AddVecSphToVec3f(&spB4, &spC0, &spD0); Play_CameraChangeSetting(play, camIdx, CAM_SET_FREE2); Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csCam->roll = 0; csCam->fov = 50.0f; if (csCam->childCamIdx != SUBCAM_FREE) { @@ -320,7 +321,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor if (Rand_ZeroOne() < 0.0f) { D_801213B4[3].eyeTargetInit.x = -D_801213B4[3].eyeTargetInit.x; } - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_801213B4; csInfo->keyFrameCnt = 5; @@ -373,10 +374,10 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); csCam->roll = 6; csCam->fov = 75.0f; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3040: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_8012151C[0].timerInit = timer - 1; csInfo->keyFrames = D_8012151C; @@ -400,7 +401,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrameCnt = 2; func_800C0808(play, camIdx, player, CAM_SET_CS_C); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3010: D_801215BC[0].timerInit = timer; @@ -428,7 +429,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3090: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_80121814; csInfo->keyFrameCnt = 4; @@ -444,14 +445,14 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor Play_CameraSetAtEye(play, camIdx, &spC0, &spB4); csCam->roll = 0; csCam->fov = 70.0f; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3380: case 3065: csInfo->keyFrames = D_801218B4; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 1); @@ -463,12 +464,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121904; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3050: Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); - func_8002DF54(play, &player->actor, 5); + Player_SetCsActionWithHaltedActors(play, &player->actor, 5); OnePointCutscene_SetCsCamPoints(csCam, D_80120304 | 0x2000, D_80120300, D_8012013C, D_8012021C); func_80078884(NA_SE_SY_CORRECT_CHIME); OnePointCutscene_Vec3sToVec3f(&mainCam->at, &D_8012013C[D_801202FC - 2].pos); @@ -497,14 +498,14 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csCam->unk_14C |= 2; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3130: csInfo->keyFrames = D_80121A44; csInfo->keyFrameCnt = 12; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); csCam->unk_14C |= 2; break; @@ -635,7 +636,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csCam->roll = 0; csCam->fov = 75.0f; player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = spD0.yaw + 0x7FFF; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 3240: D_80121D3C[2].timerInit = timer - 5; @@ -643,12 +644,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121D3C; csInfo->keyFrameCnt = 3; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 6001: Play_CameraChangeSetting(play, camIdx, CAM_SET_CS_3); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Actor_GetWorld(&spA0, actor); if (spA0.pos.z > -750.0f) { OnePointCutscene_SetCsCamPoints(csCam, D_801208E8, D_801208E4, D_801206A0, D_80120820); @@ -679,12 +680,12 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121DB4; csInfo->keyFrameCnt = 9; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3310: Play_CameraChangeSetting(play, camIdx, CAM_SET_FIRE_STAIRCASE); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Play_CopyCamera(play, camIdx, MAIN_CAM); i = Quake_Add(csCam, 1); @@ -717,7 +718,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80121FBC; csInfo->keyFrameCnt = 4; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 3); @@ -744,7 +745,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor D_801220D4[1].eyeTargetInit.y = 80.0f; D_801220D4[1].eyeTargetInit.x = -D_801220D4[1].eyeTargetInit.x; } - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); csInfo->keyFrames = D_801220D4; csInfo->keyFrameCnt = 5; @@ -762,7 +763,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801222B4; csInfo->keyFrameCnt = 5; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 1); @@ -786,7 +787,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801223CC; csInfo->keyFrameCnt = 6; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; player->actor.freezeTimer = 90; @@ -800,7 +801,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801224BC; csInfo->keyFrameCnt = 7; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); i = Quake_Add(csCam, 1); @@ -810,16 +811,11 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor break; case 4100: csInfo->keyFrames = D_801225D4; - // RANDO: Waterfall opening cutscene skips to the end of the cutscene data earlier by doing this - if (!(IS_RANDO)) { - csInfo->keyFrameCnt = 5; - } else { - csInfo->keyFrameCnt = 2; - } + csInfo->keyFrameCnt = ARRAY_COUNT(D_801225D4); player->actor.shape.rot.y = player->actor.world.rot.y = player->yaw = 0x3FFC; func_800C0808(play, camIdx, player, CAM_SET_CS_C); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); break; case 4110: csInfo->keyFrames = D_8012269C; @@ -829,7 +825,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 4120: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_80122714[1].timerInit = 80; csInfo->keyFrames = D_80122714; csInfo->keyFrameCnt = 4; @@ -847,7 +843,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_801228A4; csInfo->keyFrameCnt = 5; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; @@ -855,7 +851,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_8012296C; csInfo->keyFrameCnt = 4; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; @@ -863,7 +859,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80122A0C; csInfo->keyFrameCnt = 2; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); Camera_ChangeMode(mainCam, CAM_MODE_NORMAL); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; @@ -912,11 +908,11 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor csInfo->keyFrames = D_80122C8C; csInfo->keyFrameCnt = 1; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3260: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_80122CB4[1].timerInit = timer - 5; csInfo->keyFrames = D_80122CB4; @@ -925,7 +921,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor func_800C0808(play, camIdx, player, CAM_SET_CS_C); break; case 3261: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); D_80122D04[1].timerInit = timer - 10; csInfo->keyFrames = D_80122D04; @@ -1176,6 +1172,16 @@ s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s1 s16 csCamIdx; Camera* csCam; + if (actor != NULL && actor->id != ACTOR_PLAYER) { + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) { + return SUBCAM_NONE; + } + } else { + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_CS, true, &csId)) { + return SUBCAM_NONE; + } + } + if (parentCamIdx == SUBCAM_ACTIVE) { parentCamIdx = play->activeCamera; } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index d22a65f8b..cb665999e 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2128,7 +2128,9 @@ u8 Item_Give(PlayState* play, u8 item) { AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); } } - item = ITEM_STICK; + // [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook + INV_CONTENT(ITEM_STICK) = ITEM_STICK; + return Return_Item(item, MOD_NONE, returnItem); } else if (item == ITEM_NUT) { if (gSaveContext.inventory.items[slot] == ITEM_NONE) { Inventory_ChangeUpgrade(UPG_NUTS, 1); @@ -2152,7 +2154,9 @@ u8 Item_Give(PlayState* play, u8 item) { AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); } } - item = ITEM_NUT; + // [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook + INV_CONTENT(ITEM_NUT) = ITEM_NUT; + return Return_Item(item, MOD_NONE, returnItem); } else if (item == ITEM_BOMB) { // "Bomb Bomb Bomb Bomb Bomb Bomb Bomb" osSyncPrintf(" 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 \n"); @@ -6155,7 +6159,7 @@ void Interface_Draw(PlayState* play) { gSaveContext.timer2State = 5; gSaveContext.cutsceneIndex = 0; Message_StartTextbox(play, 0x71B0, NULL); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); } else { D_8015FFE6 = 40; gSaveContext.timer2State = 6; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index f9b3e7cf4..4e27e6cb8 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -226,60 +226,6 @@ void Play_Destroy(GameState* thisx) { gPlayState = NULL; } -void GivePlayerRandoRewardSongOfTime(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_16 && player != NULL && !Player_InBlockingCsMode(play, player) && - !Flags_GetTreasure(play, 0x1F) && gSaveContext.nextTransitionType == TRANS_NEXT_TYPE_DEFAULT && !gSaveContext.pendingIceTrapCount) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0x1F; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } -} - -void GivePlayerRandoRewardNocturne(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 || - gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_1 || - gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_2) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && - CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) && player != NULL && - !Player_InBlockingCsMode(play, player) && !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_NOCTURNE_OF_SHADOW); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0xAA; - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - } -} - -void GivePlayerRandoRewardRequiem(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { - if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT) && player != NULL && - !Player_InBlockingCsMode(play, player)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0xAC; - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - } - } -} - -void GivePlayerRandoRewardMasterSword(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_2 && LINK_IS_ADULT && player != NULL && - !Player_InBlockingCsMode(play, player) && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - !Flags_GetRandomizerInf(RAND_INF_TOT_MASTER_SWORD)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_MASTER_SWORD); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = RAND_INF_TOT_MASTER_SWORD; - player->pendingFlag.flagType = FLAG_RANDOMIZER_INF; - } -} - u8 CheckStoneCount() { u8 stoneCount = 0; @@ -331,27 +277,27 @@ u8 CheckMedallionCount() { u8 CheckDungeonCount() { u8 dungeonCount = 0; - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { dungeonCount++; } - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { dungeonCount++; } @@ -402,69 +348,6 @@ u8 CheckLACSRewardCount() { return lacsRewardCount; } -void GivePlayerRandoRewardZeldaLightArrowsGift(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - - u8 meetsRequirements = 0; - - switch (Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY)) { - case RO_GANON_BOSS_KEY_LACS_STONES: - if ((CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_STONE_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_MEDALLIONS: - if ((CheckMedallionCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_MEDALLION_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_REWARDS: - if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_REWARD_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_DUNGEONS: - if ((CheckDungeonCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_DUNGEON_COUNT)) { - meetsRequirements = true; - } - break; - case RO_GANON_BOSS_KEY_LACS_TOKENS: - if (gSaveContext.inventory.gsTokens >= Randomizer_GetSettingValue(RSK_LACS_TOKEN_COUNT)) { - meetsRequirements = true; - } - break; - default: - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { - meetsRequirements = true; - } - break; - } - - if (meetsRequirements && LINK_IS_ADULT && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && - !Flags_GetTreasure(play, 0x1E) && player != NULL && !Player_InBlockingCsMode(play, player) && - play->transitionTrigger == TRANS_TRIGGER_OFF) { - GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(check, GI_ARROW_LIGHT); - if (GiveItemEntryWithoutActor(play, getItem)) { - player->pendingFlag.flagID = 0x1E; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - } -} - -void GivePlayerRandoRewardSariaGift(PlayState* play, RandomizerCheck check) { - Player* player = GET_PLAYER(play); - if (gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY); - - if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE) && player != NULL && !Player_InBlockingCsMode(play, player)) { - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - player->pendingFlag.flagID = 0xC1; - } - } -} - void Play_Init(GameState* thisx) { PlayState* play = (PlayState*)thisx; GraphicsContext* gfxCtx = play->state.gfxCtx; @@ -480,18 +363,6 @@ void Play_Init(GameState* thisx) { u8 tempSetupIndex; s32 pad[2]; - // Skip Child Stealth when option is enabled, Zelda's Letter isn't obtained and Impa's reward hasn't been received - // eventChkInf[4] & 1 = Got Zelda's Letter - // eventChkInf[5] & 0x200 = Got Impa's reward - // entranceIndex 0x7A, ENTR_CASTLE_COURTYARD_GUARDS_DAY_0, Castle Courtyard - Day from crawlspace - // entranceIndex 0x400, ENTR_CASTLE_COURTYARD_ZELDA_0, Zelda's Courtyard - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH) && - !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) { - if (gSaveContext.entranceIndex == ENTR_CASTLE_COURTYARD_GUARDS_DAY_0) { - gSaveContext.entranceIndex = ENTR_CASTLE_COURTYARD_ZELDA_0; - } - } - // Properly initialize the frame counter so it doesn't use garbage data if (!firstInit) { play->gameplayFrames = 0; @@ -1448,15 +1319,6 @@ skip: Environment_Update(play, &play->envCtx, &play->lightCtx, &play->pauseCtx, &play->msgCtx, &play->gameOverCtx, play->state.gfxCtx); - - if (IS_RANDO) { - GivePlayerRandoRewardSariaGift(play, RC_LW_GIFT_FROM_SARIA); - GivePlayerRandoRewardSongOfTime(play, RC_SONG_FROM_OCARINA_OF_TIME); - GivePlayerRandoRewardZeldaLightArrowsGift(play, RC_TOT_LIGHT_ARROWS_CUTSCENE); - GivePlayerRandoRewardNocturne(play, RC_SHEIK_IN_KAKARIKO); - GivePlayerRandoRewardRequiem(play, RC_SHEIK_AT_COLOSSUS); - GivePlayerRandoRewardMasterSword(play, RC_TOT_MASTER_SWORD); - } } void Play_DrawOverlayElements(PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c b/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c index 86d23c45b..e05c171f0 100644 --- a/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c +++ b/soh/src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.c @@ -6,6 +6,7 @@ #include "z_bg_bdan_switch.h" #include "objects/object_bdan_objects/object_bdan_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -224,10 +225,12 @@ void func_8086D4B4(BgBdanSwitch* this, PlayState* play) { if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { type = this->dyna.actor.params & 0xFF; Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); - if (type == BLUE || type == YELLOW_TALL_2) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); - } else { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (type == BLUE || type == YELLOW_TALL_2) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } else { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); + } } } } @@ -236,7 +239,9 @@ void func_8086D548(BgBdanSwitch* this, PlayState* play) { if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) { Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F); if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index 58f11a7f3..8b901339f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/soh/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -8,6 +8,7 @@ #include "scenes/dungeons/ddan/ddan_scene.h" #include "objects/object_bwall/object_bwall.h" #include "objects/object_kingdodongo/object_kingdodongo.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -300,10 +301,13 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) { if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) { Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN); - Cutscene_SetSegment(play, gDcOpeningCs); - gSaveContext.cutsceneTrigger = 1; + s32 flag = EVENTCHKINF_ENTERED_DODONGOS_CAVERN; + if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { + Cutscene_SetSegment(play, gDcOpeningCs); + gSaveContext.cutsceneTrigger = 1; + Player_SetCsActionWithHaltedActors(play, NULL, 0x31); + } Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - func_8002DF54(play, NULL, 0x31); } if (this->dyna.actor.params < 0) { diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index e8b2be4df..8e2139aed 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -11,6 +11,7 @@ #include "scenes/indoors/yousei_izumi_yoko/yousei_izumi_yoko_scene.h" #include "scenes/indoors/daiyousei_izumi/daiyousei_izumi_scene.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -68,19 +69,6 @@ const ActorInit Bg_Dy_Yoseizo_InitVars = { NULL, }; -void GivePlayerRandoRewardGreatFairy(BgDyYoseizo* this, PlayState* play) { - Player* player = GET_PLAYER(play); - GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->fountainType + 1, GI_NONE); - - if (this->actor.parent == GET_PLAYER(play) && !Flags_GetTreasure(play, this->fountainType + 1) && - !Player_InBlockingCsMode(play, GET_PLAYER(play))) { - Flags_SetTreasure(play, this->fountainType + 1); - Actor_Kill(&this->actor); - } else if (!Flags_GetTreasure(play, this->fountainType + 1)) { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f); - } -} - void BgDyYoseizo_Init(Actor* thisx, PlayState* play2) { PlayState* play = play2; BgDyYoseizo* this = (BgDyYoseizo*)thisx; @@ -196,32 +184,26 @@ void BgDyYoseizo_Bob(BgDyYoseizo* this, PlayState* play) { } void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { + u8 isEligible = true; if (Flags_GetSwitch(play, 0x38)) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; - if(IS_RANDO) { - gSaveContext.healthAccumulator = 0x140; - Magic_Fill(play); - if(Flags_GetTreasure(play, this->fountainType + 1)) { - Actor_Kill(&this->actor); - } else { - GivePlayerRandoRewardGreatFairy(this, play); - } - return; - } - if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { if (!gSaveContext.isMagicAcquired && (this->fountainType != FAIRY_UPGRADE_MAGIC)) { - Actor_Kill(&this->actor); - return; + isEligible = false; } } else { if (!gSaveContext.isMagicAcquired) { - Actor_Kill(&this->actor); - return; + isEligible = false; } } - func_8002DF54(play, &this->actor, 1); + + if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, isEligible, this)) { + Actor_Kill(&this->actor); + return; + } + + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = BgDyYoseizo_ChooseType; } } @@ -229,7 +211,7 @@ void BgDyYoseizo_CheckMagicAcquired(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_ChooseType(BgDyYoseizo* this, PlayState* play) { s32 givingReward; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); // "Mode" osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ もうど ☆☆☆☆☆ %d\n" VT_RST, play->msgCtx.ocarinaMode); givingReward = false; @@ -345,12 +327,12 @@ void BgDyYoseizo_SetupSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { } Audio_PlayActorSound2(&this->actor, NA_SE_VO_FR_LAUGH_0); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = BgDyYoseizo_SpinGrow_NoReward; } void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Math_ApproachF(&this->actor.world.pos.y, this->grownHeight, this->heightFraction, 100.0f); Math_ApproachF(&this->scale, 0.035f, this->scaleFraction, 0.005f); Math_ApproachF(&this->heightFraction, 0.8f, 0.1f, 0.02f); @@ -376,7 +358,7 @@ void BgDyYoseizo_SpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { f32 curFrame = this->skelAnime.curFrame; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if ((this->frameCount * 1273.0f) <= this->bobTimer) { this->bobTimer = 0.0f; @@ -390,7 +372,7 @@ void BgDyYoseizo_CompleteSpinGrow_NoReward(BgDyYoseizo* this, PlayState* play) { } void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { this->frameCount = Animation_GetLastFrame(&gGreatFairySittingAnim); @@ -410,7 +392,7 @@ void BgDyYoseizo_SetupGreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { } void BgDyYoseizo_GreetPlayer_NoReward(BgDyYoseizo* this, PlayState* play) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->bobTimer = this->skelAnime.curFrame * 1273.0f; if ((this->frameCount * 1273.0f) <= this->bobTimer) { @@ -578,7 +560,7 @@ void BgDyYoseizo_Vanish(BgDyYoseizo* this, PlayState* play) { Actor* findOcarinaSpot; if (this->vanishTimer == 0) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); play->envCtx.unk_BF = 0; findOcarinaSpot = play->actorCtx.actorLists[ACTORCAT_PROP].head; @@ -600,7 +582,7 @@ void BgDyYoseizo_SetupSpinGrow_Reward(BgDyYoseizo* this, PlayState* play) { if (play->csCtx.state != CS_STATE_IDLE) { if ((play->csCtx.npcActions[0] != NULL) && (play->csCtx.npcActions[0]->action == 2)) { this->actor.draw = BgDyYoseizo_Draw; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->finishedSpinGrow = false; if (play->sceneNum == SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC) { diff --git a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c index b592edcd5..543770505 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c +++ b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c @@ -7,6 +7,7 @@ #include "z_bg_gjyo_bridge.h" #include "objects/object_gjyo_objects/object_gjyo_objects.h" #include "scenes/dungeons/ganon_tou/ganon_tou_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -50,8 +51,7 @@ void BgGjyoBridge_Init(Actor* thisx, PlayState* play) { this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader); - int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); - if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT) || (IS_RANDO && bridge == RO_BRIDGE_ALWAYS_OPEN)) { + if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT)) { this->actionFunc = func_808787A4; } else { this->dyna.actor.draw = NULL; @@ -70,8 +70,10 @@ void func_808787A4(BgGjyoBridge* this, PlayState* play) { } void LaunchBridgeCutscene(BgGjyoBridge* this, PlayState* play) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); - gSaveContext.cutsceneTrigger = 1; + if (GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); + gSaveContext.cutsceneTrigger = 1; + } this->actionFunc = BgGjyoBridge_SpawnBridge; } @@ -84,70 +86,24 @@ u8 CheckPlayerPosition(Player* player, PlayState* play) { void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (!IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && CheckPlayerPosition(player, play)) { - LaunchBridgeCutscene(this, play); - } - } else { - int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); - int bridgeStoneCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT); - int bridgeMedallionCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT); - int bridgeRewardCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT); - int bridgeDungeonCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT); - int bridgeTokenCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT); + u8 vanillaBridgeCondition = + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && + CheckPlayerPosition(player, play); - switch (bridge) { - case RO_BRIDGE_VANILLA: - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_STONES: - if ((CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeStoneCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_MEDALLIONS: - if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= bridgeMedallionCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_DUNGEON_REWARDS: - if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeRewardCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_DUNGEONS: - if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= bridgeDungeonCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_TOKENS: - if (gSaveContext.inventory.gsTokens >= bridgeTokenCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_GREG: - if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - } + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, vanillaBridgeCondition, NULL)) { + LaunchBridgeCutscene(this, play); } } void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, PlayState* play) { - if (IS_RANDO || (play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.npcActions[2] != NULL) && - (play->csCtx.npcActions[2]->action == 2)) { + u8 vanillaBridgeCondition = + (play->csCtx.state != CS_STATE_IDLE) && + (play->csCtx.npcActions[2] != NULL) && + (play->csCtx.npcActions[2]->action == 2); + + if (!GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL) || vanillaBridgeCondition) { this->dyna.actor.draw = BgGjyoBridge_Draw; func_8003EC50(play, &play->colCtx.dyna, this->dyna.bgId); Flags_SetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT); diff --git a/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c b/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c index ae8f9cd05..37ff09efc 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c +++ b/soh/src/overlays/actors/ovl_Bg_Gnd_Iceblock/z_bg_gnd_iceblock.c @@ -241,7 +241,7 @@ void BgGndIceblock_Idle(BgGndIceblock* this, PlayState* play) { if (this->dyna.unk_150 > 0.0f) { BgGndIceblock_SetNextPosition(this); if (Actor_WorldDistXZToPoint(&this->dyna.actor, &this->targetPos) > 1.0f) { - func_8002DF54(play, &this->dyna.actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8); this->actionFunc = BgGndIceblock_Slide; } } @@ -282,7 +282,7 @@ void BgGndIceblock_Fall(BgGndIceblock* this, PlayState* play) { thisx->world.pos.y = thisx->home.pos.y - 100.0f; thisx->world.pos.z = thisx->home.pos.z; if (Player_InCsMode(play)) { - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); } this->actionFunc = BgGndIceblock_Reset; } @@ -295,7 +295,7 @@ void BgGndIceblock_Hole(BgGndIceblock* this, PlayState* play) { if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y - 100.0f, thisx->velocity.y)) { thisx->velocity.y = 0.0f; if (Player_InCsMode(play)) { - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); } this->actionFunc = BgGndIceblock_Idle; } @@ -319,7 +319,7 @@ void BgGndIceblock_Slide(BgGndIceblock* this, PlayState* play) { switch (BgGndIceblock_NextAction(this)) { case GNDICE_IDLE: this->actionFunc = BgGndIceblock_Idle; - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); break; case GNDICE_FALL: this->actionFunc = BgGndIceblock_Fall; diff --git a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c index 3b2524e79..97ed090a8 100644 --- a/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c +++ b/soh/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c @@ -370,7 +370,7 @@ void BgHeavyBlock_LiftedUp(BgHeavyBlock* this, PlayState* play) { this->timer++; if (!CVarGetInteger("gFasterHeavyBlockLift", 0)) { - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } // if parent is NULL, link threw it diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c index cae8037c6..3e1fd9d78 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Dalm/z_bg_hidan_dalm.c @@ -138,7 +138,7 @@ void BgHidanDalm_Wait(BgHidanDalm* this, PlayState* play) { this->dyna.actor.world.pos.x += 32.5f * Math_SinS(this->dyna.actor.world.rot.y); this->dyna.actor.world.pos.z += 32.5f * Math_CosS(this->dyna.actor.world.rot.y); - func_8002DF54(play, &this->dyna.actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8); this->dyna.actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; this->actionFunc = BgHidanDalm_Shrink; this->dyna.actor.bgCheckFlags &= ~2; @@ -159,7 +159,7 @@ void BgHidanDalm_Shrink(BgHidanDalm* this, PlayState* play) { Vec3f pos; if (Math_StepToF(&this->dyna.actor.scale.x, 0.0f, 0.004f)) { - func_8002DF54(play, &this->dyna.actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 7); Actor_Kill(&this->dyna.actor); } diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h b/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h index fff8c4c53..1f3eb4161 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h @@ -14,4 +14,7 @@ typedef struct BgHidanKousi { /* 0x0168 */ s16 unk_168; } BgHidanKousi; // size = 0x016C +void BgHidanKousi_SetupAction(BgHidanKousi* bgHidanKousi, BgHidanKousiActionFunc actionFunc); +void func_80889C18(BgHidanKousi* bgHidanKousi, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c b/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c index 1cd91d468..7193d3659 100644 --- a/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Ice_Objects/z_bg_ice_objects.c @@ -126,7 +126,7 @@ void BgIceObjects_CheckPits(BgIceObjects* this, PlayState* play) { thisx->world.pos.y = thisx->home.pos.y - 60.0f; thisx->world.pos.z = thisx->home.pos.z; if (thisx->params != 0) { - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); } this->actionFunc = BgIceObjects_Reset; } @@ -143,7 +143,7 @@ void BgIceObjects_Idle(BgIceObjects* this, PlayState* play) { BgIceObjects_SetNextTarget(this, play); if (Actor_WorldDistXZToPoint(thisx, &this->targetPos) > 1.0f) { thisx->flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; - func_8002DF54(play, thisx, 8); + Player_SetCsActionWithHaltedActors(play, thisx, 8); thisx->params = 1; this->actionFunc = BgIceObjects_Slide; } @@ -173,7 +173,7 @@ void BgIceObjects_Slide(BgIceObjects* this, PlayState* play) { thisx->flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; } thisx->params = 0; - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); Audio_PlayActorSound2(thisx, NA_SE_EV_BLOCK_BOUND); if ((fabsf(thisx->world.pos.x + 1387.0f) < 1.0f) && (fabsf(thisx->world.pos.z + 260.0f) < 1.0f)) { this->actionFunc = BgIceObjects_Stuck; diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c index eeecfabcb..51b7dc622 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Bigst/z_bg_mori_bigst.c @@ -6,6 +6,7 @@ #include "z_bg_mori_bigst.h" #include "objects/object_mori_objects/object_mori_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -149,7 +150,9 @@ void BgMoriBigst_StalfosFight(BgMoriBigst* this, PlayState* play) { if ((this->dyna.actor.home.rot.z == 0) && ((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) { BgMoriBigst_SetupFall(this, play); - OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM); + } } } @@ -163,8 +166,10 @@ void BgMoriBigst_Fall(BgMoriBigst* this, PlayState* play) { this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y; BgMoriBigst_SetupLanding(this, play); Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND); - OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM); - func_8002DF38(play, NULL, 0x3C); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM); + func_8002DF38(play, NULL, 0x3C); + } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c index 8392e7224..f020a462a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c +++ b/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c @@ -96,7 +96,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) { this->timer++; if ((this->timer > (28 - CVarGetInteger("gFasterBlockPush", 0) * 4)) && !Player_InCsMode(play)) { BgMoriKaitenkabe_SetupRotate(this); - func_8002DF54(play, &this->dyna.actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8); Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos); push.x = Math_SinS(this->dyna.unk_158); push.y = 0.0f; @@ -130,7 +130,7 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) { Math_StepToF(&this->rotSpeed, 0.6f, 0.02f); if (Math_StepToF(&this->rotYdeg, this->rotDirection * 45.0f, this->rotSpeed)) { BgMoriKaitenkabe_SetupWait(this); - func_8002DF54(play, thisx, 7); + Player_SetCsActionWithHaltedActors(play, thisx, 7); if (this->rotDirection > 0.0f) { thisx->home.rot.y += 0x2000; } else { diff --git a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c index a2fca0db7..08d4fc773 100644 --- a/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c +++ b/soh/src/overlays/actors/ovl_Bg_Po_Event/z_bg_po_event.c @@ -321,7 +321,7 @@ void BgPoEvent_BlockFall(BgPoEvent* this, PlayState* play) { if (firstFall == 0) { firstFall = 1; } else { - func_8002DF54(play, &GET_PLAYER(play)->actor, 7); + Player_SetCsActionWithHaltedActors(play, &GET_PLAYER(play)->actor, 7); } } this->direction = 0; @@ -358,7 +358,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, PlayState* play) { if (sBgPoEventPuzzleState == 0x10) { sBgPoEventPuzzleState = 0x40; Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_RISING); - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } } else if (this->dyna.unk_150 != 0.0f) { if (this->direction == 0) { diff --git a/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c b/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c index 0fb728661..675bbb3ed 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot00_Hanebasi/z_bg_spot00_hanebasi.c @@ -223,7 +223,7 @@ void BgSpot00Hanebasi_Update(Actor* thisx, PlayState* play) { Flags_SetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE); Flags_SetEventChkInf(EVENTCHKINF_DRAWBRIDGE_OPENED_AFTER_ZELDA_FLED); this->actionFunc = BgSpot00Hanebasi_DoNothing; - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); play->nextEntranceIndex = ENTR_HYRULE_FIELD_0; gSaveContext.nextCutsceneIndex = 0xFFF1; play->transitionTrigger = TRANS_TRIGGER_START; diff --git a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c index 2eb3faeda..cc7d4c854 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.c @@ -6,6 +6,7 @@ #include "z_bg_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) @@ -129,20 +130,7 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) { static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; Vec3f pos; - // We want to do most of the same things in rando, but we're not in a cutscene and the flag for - // 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) { + 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)) { Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_GRAVE_EXPLOSION); Flags_SetEventChkInf(EVENTCHKINF_DESTROYED_ROYAL_FAMILY_TOMB); 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; EffectSsBomb2_SpawnLayered(play, &pos, &zeroVec, &zeroVec, 70, 30); 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 // enter the cutscene context. - if (play->csCtx.frames == 402 && !(IS_RANDO)) { + if (play->csCtx.frames == 402) { if (!LINK_IS_ADULT) { Player_PlaySfx(&player->actor, NA_SE_VO_LI_DEMO_DAMAGE_KID); } else { @@ -217,13 +204,6 @@ void BgSpot02Objects_Draw(Actor* thisx, 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 && play->csCtx.npcActions[0]->action == 2) { this->unk_16A++; diff --git a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h index 0b54fa617..cf5152a7e 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h +++ b/soh/src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h @@ -19,4 +19,7 @@ typedef struct BgSpot02Objects { /* 0x0172 */ u16 unk_172; } BgSpot02Objects; // size = 0x0174 +void func_808ACC34(BgSpot02Objects* bgSpot02Objects, PlayState* play); +void func_808AC908(BgSpot02Objects* bgSpot02Objects, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c index 816f96aa4..0a4738092 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.c @@ -217,7 +217,7 @@ void BgSpot06Objects_Destroy(Actor* thisx, PlayState* play) { // Due to Ships resource caching, the water box collisions for the river have to be manually reset play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z; - if (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { // For randomizer when leaving lake hylia while the water level is lowered, // reset the "raise lake hylia water" flag back to on if the water temple is cleared Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); @@ -461,7 +461,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) { Object_Spawn(&play->objectCtx, OBJECT_GAMEPLAY_DANGEON_KEEP); s16 switchParams; - if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { // Toggle-able floor switch, // linked to temp_switch 0x1E (room temporary, cleared when room unloads) switchParams = 0x3E10; @@ -477,7 +477,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) { 0x0000 | (TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN & 0xFF), false); // Spawn a Navi check spot when Water Temple isn't cleared - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Actor_Spawn(&play->actorCtx, play, ACTOR_ELF_MSG2, -896.0f, -1243.0f, 6953.0f, 0, 0, 0, 0x3D00 | (TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI & 0xFF), false); } @@ -485,7 +485,7 @@ void BgSpot06Objects_Update(Actor* thisx, PlayState* play) { actionCounter++; return; } else if (actionCounter == 1) { - if (!Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) { + if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { // Remove the link to ice block so melting it doesn't set the flag lakeControlFloorSwitch->params = 0x3E01; } diff --git a/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c b/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c index 519767534..6d65c049f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot12_Saku/z_bg_spot12_saku.c @@ -6,6 +6,7 @@ #include "z_bg_spot12_saku.h" #include "objects/object_spot12_obj/object_spot12_obj.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -58,15 +59,9 @@ void func_808B3420(BgSpot12Saku* this, PlayState* play, CollisionHeader* collisi void BgSpot12Saku_Init(Actor* thisx, PlayState* play) { BgSpot12Saku* this = (BgSpot12Saku*)thisx; - // If ER is on, force the gate to always use its permanent flag - // (which it only uses in Child Gerudo Fortress in the vanilla game) - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) { - thisx->params = 0x0002; - } - func_808B3420(this, play, &gGerudoFortressGTGShutterCol, DPM_UNK); Actor_ProcessInitChain(&this->dyna.actor, sInitChain); - if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { func_808B3714(this); } else { func_808B3550(this); @@ -87,7 +82,7 @@ void func_808B3550(BgSpot12Saku* this) { } void func_808B357C(BgSpot12Saku* this, PlayState* play) { - if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { + if (GameInteractor_Should(GI_VB_GTG_GATE_BE_OPEN, Flags_GetSwitch(play, this->dyna.actor.params & 0x3F), NULL)) { func_808B35E4(this); this->timer = 20; OnePointCutscene_Init(play, 4170, -99, &this->dyna.actor, MAIN_CAM); @@ -131,12 +126,6 @@ void func_808B37AC(BgSpot12Saku* this, PlayState* play) { void BgSpot12Saku_Update(Actor* thisx, PlayState* play) { BgSpot12Saku* this = (BgSpot12Saku*)thisx; - // If ER is on, when the guard opens the GtG gate its permanent flag will be set. - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && - Flags_GetSwitch(play, 0x3A)) { - Flags_SetSwitch(play, 0x2); - } - if (this->timer > 0) { this->timer--; } diff --git a/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c b/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c index 26a02aa96..b6d5ed15a 100644 --- a/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c +++ b/soh/src/overlays/actors/ovl_Bg_Toki_Swd/z_bg_toki_swd.c @@ -6,6 +6,7 @@ #include "z_bg_toki_swd.h" #include "objects/object_toki_objects/object_toki_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -115,14 +116,17 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) { if (((Flags_GetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER)) == 0) && (gSaveContext.sceneSetupIndex < 4) && Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) { Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER); - play->csCtx.segment = D_808BBD90; - gSaveContext.cutsceneTrigger = 1; + s32 flag = EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER; + if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) { + play->csCtx.segment = D_808BBD90; + gSaveContext.cutsceneTrigger = 1; + } } if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) { if (Actor_HasParent(&this->actor, play)) { if (!LINK_IS_ADULT) { - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_MASTER_SWORD, true, NULL)) { Item_Give(play, ITEM_SWORD_MASTER); } play->csCtx.segment = D_808BB2F0; diff --git a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c index 75e920b29..04d1d6c72 100644 --- a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c +++ b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.c @@ -7,6 +7,7 @@ #include "z_bg_treemouth.h" #include "objects/object_spot04_objects/object_spot04_objects.h" #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -73,11 +74,7 @@ void BgTreemouth_Init(Actor* thisx, PlayState* play) { if ((gSaveContext.sceneSetupIndex < 4) && !LINK_IS_ADULT) { BgTreemouth_SetupAction(this, func_808BC8B8); - // If dungeon entrance randomizer is on, keep the tree mouth open - // when Link is adult and sword & shield have been shown to Mido - } else if ((LINK_IS_ADULT && (!IS_RANDO || - Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) || - !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) || (gSaveContext.sceneSetupIndex == 7)) { + } else if (LINK_IS_ADULT || (gSaveContext.sceneSetupIndex == 7)) { this->unk_168 = 0.0f; BgTreemouth_SetupAction(this, BgTreemouth_DoNothing); } else { @@ -157,9 +154,11 @@ void func_808BC8B8(BgTreemouth* this, PlayState* play) { } } else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) { Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE); - play->csCtx.segment = D_808BCE20; - gSaveContext.cutsceneTrigger = 1; - BgTreemouth_SetupAction(this, func_808BC9EC); + if (GameInteractor_Should(GI_VB_PLAY_DEKU_TREE_INTRO_CS, true, this)) { + play->csCtx.segment = D_808BCE20; + gSaveContext.cutsceneTrigger = 1; + BgTreemouth_SetupAction(this, func_808BC9EC); + } } } } else { diff --git a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h index 7fe96cfa1..daa33bfee 100644 --- a/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h +++ b/soh/src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h @@ -15,4 +15,7 @@ typedef struct BgTreemouth { /* 0x016C */ BgTreemouthActionFunc actionFunc; } BgTreemouth; // size = 0x0170 +void BgTreemouth_SetupAction(BgTreemouth* actor, BgTreemouthActionFunc actionFunc); +void func_808BC6F8(BgTreemouth* actor, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 30455e8e5..a825f67d7 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -443,7 +443,7 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) { break; case 1: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Play_ClearAllSubCameras(play); this->cutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, 1); @@ -470,11 +470,11 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) { } if (this->unk_198 == 110) { - func_8002DF54(play, &this->actor, 9); + Player_SetCsActionWithHaltedActors(play, &this->actor, 9); } if (this->unk_198 == 5) { - func_8002DF54(play, &this->actor, 12); + Player_SetCsActionWithHaltedActors(play, &this->actor, 12); } if (this->unk_198 < 6) { @@ -589,7 +589,7 @@ void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play) { func_800C08AC(play, this->cutsceneCamera, 0); this->cutsceneCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); BossDodongo_SetupWalk(this); this->unk_1DA = 50; this->unk_1BC = 0; @@ -1535,7 +1535,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) { case 0: this->csState = 5; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->cutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_UNK3); Play_ChangeCameraStatus(play, this->cutsceneCamera, CAM_STAT_ACTIVE); @@ -1850,7 +1850,7 @@ void BossDodongo_DeathCutscene(BossDodongo* this, PlayState* play) { this->csState = 100; Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); if (!IS_BOSS_RUSH) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD); } else { diff --git a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c index 0d33533ae..72908fd2f 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd/z_boss_fd.c @@ -323,7 +323,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { this->introState = BFD_CS_START; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->introCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->introCamera, CAM_STAT_ACTIVE); @@ -399,7 +399,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { Math_ApproachF(&this->camData.shake, 2.0f, 1.0f, 0.8 * 0.01f); } if (this->timers[0] == 40) { - func_8002DF54(play, &this->actor, 0x13); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x13); } if (this->timers[0] == 0) { this->introState = BFD_CS_LOOK_GROUND; @@ -428,7 +428,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { this->timers[0] = 170; this->camData.speedMod = 0.0f; this->camData.accel = 0.0f; - func_8002DF54(play, &this->actor, 0x14); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x14); } break; case BFD_CS_COLLAPSE: @@ -478,7 +478,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { if (this->timers[3] == 190) { this->camData.atMaxVel.x = this->camData.atMaxVel.y = this->camData.atMaxVel.z = 0.05f; this->platformSignal = VBSIMA_KILL; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } if (this->actor.world.pos.y > 120.0f) { this->camData.nextAt = this->actor.world.pos; @@ -546,7 +546,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { func_800C08AC(play, this->introCamera, 0); this->introState = this->introFlyState = this->introCamera = BFD_CS_NONE; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionFunc = BossFd_Wait; this->handoffSignal = FD2_SIGNAL_GROUND; Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE); @@ -854,7 +854,7 @@ void BossFd_Fly(BossFd* this, PlayState* play) { this->work[BFD_CAM_SHAKE_TIMER] = 20; Audio_PlaySoundGeneral(NA_SE_EN_VALVAISA_LAND2, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); for (i1 = 0; i1 < 15; i1++) { Vec3f sp144 = { 0.0f, 0.0f, 0.0f }; Vec3f sp138 = { 0.0f, 0.0f, 0.0f }; diff --git a/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c b/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c index fb14c5ebe..2a03f1839 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c @@ -661,7 +661,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) { case DEATH_START: this->deathState = DEATH_RETREAT; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->deathCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->deathCamera, CAM_STAT_ACTIVE); @@ -754,7 +754,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) { this->work[FD2_ACTION_STATE]++; this->camData.speedMod = 0.0f; this->camData.accel = 0.02f; - func_8002DF54(play, &bossFd->actor, 1); + Player_SetCsActionWithHaltedActors(play, &bossFd->actor, 1); } } if ((bossFd->work[BFD_ACTION_STATE] == BOSSFD_BONES_FALL) && (bossFd->timers[0] == 5)) { @@ -788,7 +788,7 @@ void BossFd2_Death(BossFd2* this, PlayState* play) { func_800C08AC(play, this->deathCamera, 0); this->deathCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); if (!IS_BOSS_RUSH) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 100.0f, 0.0f, 0, 0, 0, WARP_DUNGEON_ADULT); diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index 97551ca46..169794568 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -564,7 +564,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { this->actor.shape.rot.y = 0; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamIndex = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); @@ -609,7 +609,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { BossGanon_SetIntroCsCamera(this, 1); if (this->csTimer == 10) { - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); } if (this->csTimer == 13) { @@ -642,7 +642,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { break; } - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csState = 4; BossGanon_SetIntroCsCamera(this, 2); this->csTimer = 0; @@ -674,7 +674,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { } if (this->csTimer == 10) { - func_8002DF54(play, &this->actor, 0x4B); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4B); } if (this->csTimer == 70) { @@ -740,7 +740,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { this->csState = 9; this->csTimer = 0; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); sBossGanonZelda->unk_3C8 = 0; this->triforceType = GDF_TRIFORCE_ZELDA; this->fwork[GDF_TRIFORCE_SCALE] = 10.0f; @@ -794,7 +794,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { player->actor.world.pos.z = 20.0f; if (this->csTimer == 20) { - func_8002DF54(play, &this->actor, 0x17); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x17); Interface_ChangeAlpha(11); // show hearts only } @@ -1031,7 +1031,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { } if (this->csTimer == 30) { - func_8002DF54(play, &this->actor, 0x4A); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4A); } if (this->csTimer <= 50) { @@ -1154,7 +1154,7 @@ void BossGanon_IntroCutscene(BossGanon* this, PlayState* play) { func_800C08AC(play, this->csCamIndex, 0); this->csState = this->csCamIndex = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); BossGanon_SetupWait(this, play); } @@ -1267,7 +1267,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { switch (this->csState) { case 0: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamIndex = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); @@ -1510,7 +1510,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_BODY_SPARK - SFX_FLAG); if (this->csTimer == 2) { - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); } if (this->csTimer > 50) { @@ -1539,20 +1539,14 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { if (this->csTimer == 180) { play->transitionTrigger = TRANS_TRIGGER_START; - if ((IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE) || IS_BOSS_RUSH)) { - Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); - play->nextEntranceIndex = ENTR_GANON_BOSS_0; - } - else { - play->nextEntranceIndex = ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0; - } + play->nextEntranceIndex = ENTR_GANONS_TOWER_COLLAPSE_EXTERIOR_0; play->transitionType = TRANS_TYPE_FADE_WHITE_FAST; } break; case 100: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamIndex = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamIndex, CAM_STAT_ACTIVE); @@ -1651,11 +1645,11 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { this->csCamAt.z = -135.0f; if (this->csTimer == 5) { - func_8002DF54(play, &this->actor, 0x4C); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4C); } if (this->csTimer == 70) { - func_8002DF54(play, &this->actor, 0x4D); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4D); } if (this->csTimer == 90) { @@ -1754,7 +1748,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { if (this->csTimer == 20) { sBossGanonZelda->unk_3C8 = 5; - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); } if (this->csTimer == 40) { @@ -1821,7 +1815,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { this->csState = 107; this->csTimer = 0; Message_StartTextbox(play, 0x70D2, NULL); - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); } break; @@ -1863,7 +1857,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, PlayState* play) { this->csState = 109; this->csCamIndex = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Flags_SetSwitch(play, 0x37); } break; diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index ba4a4fbc6..28febacd4 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -228,7 +228,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { objectIdx = Object_GetIndex(&play->objectCtx, OBJECT_GANON_ANIME3); if (Object_IsLoaded(&play->objectCtx, objectIdx)) { func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->unk_39E = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); @@ -306,11 +306,11 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { } if (this->csTimer == 40) { sBossGanon2Zelda->unk_3C8 = 1; - func_8002DF54(play, &this->actor, 0x4E); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4E); } if (this->csTimer == 85) { sBossGanon2Zelda->unk_3C8 = 2; - func_8002DF54(play, &this->actor, 0x4F); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x4F); } this->unk_3A4.x = 930.0f; this->unk_3A4.y = 1129.0f; @@ -339,14 +339,14 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { } if (this->csTimer == 20) { sBossGanon2Zelda->unk_3C8 = 3; - func_8002DF54(play, &this->actor, 0x50); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x50); } if (this->csTimer == 55) { this->csState = 4; this->csTimer = 0; this->unk_410.x = 0.0f; sBossGanon2Zelda->unk_3C8 = 4; - func_8002DF54(play, &this->actor, 0x50); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x50); } break; case 4: @@ -363,7 +363,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 5; this->csTimer = 0; } @@ -409,7 +409,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { } if (this->csTimer == 30) { sBossGanon2Zelda->unk_3C8 = 5; - func_8002DF54(play, &this->actor, 0x51); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x51); } if (this->csTimer == 50) { this->csTimer = 0; @@ -440,7 +440,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_80078884(NA_SE_EV_STONE_BOUND); } if (this->csTimer == 30) { - func_8002DF54(play, &this->actor, 0x52); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x52); } if (this->csTimer == 50) { this->csTimer = 0; @@ -505,7 +505,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { this->unk_3B0.y = player->actor.world.pos.y; this->unk_3B0.z = player->actor.world.pos.z - 200.0f; if (this->csTimer == 20) { - func_8002DF54(play, &this->actor, 0x1E); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x1E); } if (this->csTimer == 60) { this->unk_3A4.x = (this->actor.world.pos.x + 200.0f) - 154.0f; @@ -593,7 +593,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { SkelAnime_Free(&this->skelAnime, play); SkelAnime_InitFlex(play, &this->skelAnime, &gGanonSkel, NULL, NULL, NULL, 0); BossGanon2_SetObjectSegment(this, play, OBJECT_GANON_ANIME3, false); - func_8002DF54(play, &this->actor, 0x54); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x54); this->unk_314 = 3; // At this point, the actor has Ganon's skeleton but is still playing an animation for Ganondorf. This @@ -657,7 +657,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { this->actor.world.pos.x += 250; this->actor.world.pos.y = 1886.0f; this->unk_394 = 0.0f; - func_8002DF54(play, &this->actor, 0x53); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x53); this->unk_30C = 5.0f; this->unk_228 = 1.0f; } @@ -742,7 +742,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { if (this->csTimer == 215) { this->csState = 23; this->unk_224 = 0.0f; - func_8002DF54(play, &this->actor, 0x55); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x55); } break; case 23: @@ -762,7 +762,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { this->unk_3B0.z = player->actor.world.pos.z; if (this->csTimer == 228) { func_80078884(NA_SE_IT_SHIELD_REFLECT_SW); - func_8002DF54(play, &this->actor, 0x56); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x56); func_800A9F6C(0.0f, 0xFF, 0xA, 0x32); } if (this->csTimer >= 229) { @@ -799,7 +799,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_80078884(NA_SE_IT_SWORD_SWING); } if (this->csTimer == 25) { - func_8002DF54(play, &this->actor, 0x57); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x57); this->csState = 25; this->csTimer = 0; } @@ -846,7 +846,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { case 27: this->unk_3BC.z = 0.0f; if (this->csTimer == 4) { - func_8002DF54(play, &this->actor, 0x58); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x58); } this->unk_3A4.x = player->actor.world.pos.x - 20.0f; this->unk_3A4.y = player->actor.world.pos.y + 50.0f; @@ -919,7 +919,7 @@ void func_808FD5F4(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 0; this->unk_337 = 1; func_808FFDB0(this, play); @@ -1340,7 +1340,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { this->unk_39E = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csState = 1; this->unk_3A4 = sp4C->eye; this->unk_3B0 = sp4C->at; @@ -1388,7 +1388,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 3; } break; @@ -1399,7 +1399,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); this->csState = 11; this->unk_334 = 1; - func_8002DF54(play, &this->actor, 0x60); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x60); this->csTimer = 0; case 11: player->actor.world.pos.x = sBossGanon2Zelda->actor.world.pos.x + 50.0f + 10.0f; @@ -1420,7 +1420,7 @@ void func_80900890(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } break; } @@ -1536,7 +1536,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { this->unk_39E = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->unk_39E, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csState = 1; this->csTimer = 0; sBossGanon2Zelda->unk_3C8 = 9; @@ -1572,7 +1572,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { this->skelAnime.playSpeed = 3.0f; } if (this->csTimer == 120) { - func_8002DF54(play, &this->actor, 0x63); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x63); } this->actor.world.rot.y = 0x4000; this->actor.world.pos.x = this->actor.world.pos.z = 0.0f; @@ -1640,7 +1640,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { this->csState = 5; this->csTimer = 40; this->skelAnime.playSpeed = 1.0f; - func_8002DF54(play, &this->actor, 0x64); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x64); } break; case 5: @@ -1654,10 +1654,10 @@ void func_8090120C(BossGanon2* this, PlayState* play) { Math_ApproachZeroF(&this->unk_38C, 1.0f, 8.0f); } if (this->csTimer == 70) { - func_8002DF54(play, &this->actor, 0x65); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x65); } if (this->csTimer == 150) { - func_8002DF54(play, &this->actor, 0x66); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x66); } this->unk_30C = 10.0f; player->actor.world.pos.x = 250.0f; @@ -1676,7 +1676,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { func_800C08AC(play, this->unk_39E, 0); this->unk_39E = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->csState = 6; } break; @@ -1764,7 +1764,7 @@ void func_8090120C(BossGanon2* this, PlayState* play) { if (this->csTimer == 55) { Animation_MorphToPlayOnce(&this->skelAnime, &gGanonDeadStartAnim, 0.0f); this->unk_194 = Animation_GetLastFrame(&gGanonDeadStartAnim); - func_8002DF54(play, &this->actor, 0x62); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x62); this->csState = 8; this->csTimer = 1000; } diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 111380f0b..0b025dcd6 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -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); @@ -926,7 +911,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { switch (this->deathState) { case DEATH_START: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->deathCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); osSyncPrintf("7\n"); @@ -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: @@ -1104,7 +1075,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) { func_800C08AC(play, this->deathCamera, 0); this->deathCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); if (!IS_BOSS_RUSH) { Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0, true); diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h index ff4a841d6..1e45ca766 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h @@ -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; diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index 6de72fd2d..489350ad0 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -628,7 +628,7 @@ void BossGoma_SetupEncounterState4(BossGoma* this, PlayState* play) { this->actionState = 4; this->actor.flags |= ACTOR_FLAG_TARGETABLE; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->subCameraId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, 3); Play_ChangeCameraStatus(play, this->subCameraId, 7); @@ -685,7 +685,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_SHUTTER, 164.72f, -480.0f, 397.68002f, 0, -0x705C, 0, 0x180); } else { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->actionState = 1; } } @@ -756,7 +756,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { } if (this->frameCount == 190) { - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); } if (this->frameCount >= 228) { @@ -767,7 +767,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { func_800C08AC(play, this->subCameraId, 0); this->subCameraId = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionState = 3; } break; @@ -964,7 +964,7 @@ void BossGoma_Encounter(BossGoma* this, PlayState* play) { this->disableGameplayLogic = false; this->patienceTimer = 200; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } break; } @@ -1054,7 +1054,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) { case 0: this->actionState = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->subCameraId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, 3); Play_ChangeCameraStatus(play, this->subCameraId, 7); @@ -1189,7 +1189,7 @@ void BossGoma_Defeated(BossGoma* this, PlayState* play) { func_800C08AC(play, this->subCameraId, 0); this->subCameraId = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Actor_Kill(&this->actor); } diff --git a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c index 74684df71..7d82b93a4 100644 --- a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c +++ b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c @@ -1249,7 +1249,7 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) { (fabsf(player->actor.world.pos.x - -180.0f) < 40.0f))) { // checks if Link is on one of the four platforms func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE); @@ -1357,11 +1357,11 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) { Math_ApproachF(&this->actor.speedXZ, sp80, 1.0f, sp78); Math_ApproachF(&this->cameraYawRate, sp7C, 1.0f, 128.0f); if (this->work[MO_TENT_MOVE_TIMER] == 525) { - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); } if (this->work[MO_TENT_MOVE_TIMER] > 540) { this->csState = MO_INTRO_REVEAL; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); sMorphaTent1->drawActor = true; player->actor.world.pos.x = 180.0f; player->actor.world.pos.z = -210.0f; @@ -1468,7 +1468,7 @@ void BossMo_IntroCs(BossMo* this, PlayState* play) { func_800C08AC(play, this->csCamera, 0); this->csState = this->csCamera = MO_BATTLE; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } break; } @@ -1533,7 +1533,7 @@ void BossMo_DeathCs(BossMo* this, PlayState* play) { switch (this->csState) { case MO_DEATH_START: func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->csCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->csCamera, CAM_STAT_ACTIVE); @@ -1700,7 +1700,7 @@ void BossMo_DeathCs(BossMo* this, PlayState* play) { func_800C08AC(play, this->csCamera, 0); this->csCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sMorphaTent1->actor.world.pos.y = -1000.0f; } } else { diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index b9f5c6f2c..5b8eef344 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -390,7 +390,7 @@ void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) { player->stateFlags1 |= PLAYER_STATE1_INPUT_DISABLED; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); sCutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE); @@ -423,7 +423,7 @@ void BossSst_HeadIntro(BossSst* this, PlayState* play) { sHands[LEFT]->actor.flags |= ACTOR_FLAG_TARGETABLE; player->stateFlags1 &= ~PLAYER_STATE1_INPUT_DISABLED; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sCameraAt.y += 30.0f; sCameraAt.z += 300.0f; Play_CameraSetAtEye(play, sCutsceneCamera, &sCameraAt, &sCameraEye); @@ -1032,7 +1032,7 @@ void BossSst_HeadSetupDeath(BossSst* this, PlayState* play) { Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_ACTIVE); Play_CopyCamera(play, sCutsceneCamera, MAIN_CAM); - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); func_80064520(play, &play->csCtx); Math_Vec3f_Copy(&sCameraEye, &GET_ACTIVE_CAM(play)->eye); this->actionFunc = BossSst_HeadDeath; @@ -1194,7 +1194,7 @@ void BossSst_HeadFinish(BossSst* this, PlayState* play) { Play_ChangeCameraStatus(play, sCutsceneCamera, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Play_ClearCamera(play, sCutsceneCamera); - func_8002DF54(play, &GET_PLAYER(play)->actor, 7); + Player_SetCsActionWithHaltedActors(play, &GET_PLAYER(play)->actor, 7); func_80064534(play, &play->csCtx); Actor_Kill(&this->actor); Actor_Kill(&sHands[LEFT]->actor); diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 9d0a68c38..40f8127cd 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -1466,7 +1466,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { case 0: this->csState2 = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); @@ -1606,7 +1606,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { Animation_MorphToPlayOnce(&this->skelAnime, &gTwinrovaIntroAnim, 0.0f); this->workf[ANIM_SW_TGT] = Animation_GetLastFrame(&gTwinrovaIntroAnim); this->timers[0] = 50; - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_TRANSFORM); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS); } @@ -1649,7 +1649,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { } if (this->timers[3] == 19) { - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); } if (this->timers[3] == 16) { @@ -1682,7 +1682,7 @@ void BossTw_TwinrovaMergeCS(BossTw* this, PlayState* play) { this->subCamId = 0; this->csState2 = this->subCamId; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->work[TW_PLLR_IDX] = 0; this->targetPos = sTwinrovaPillarPos[0]; BossTw_TwinrovaSetupFly(this, play); @@ -1762,7 +1762,7 @@ void BossTw_TwinrovaIntroCS(BossTw* this, PlayState* play) { player->actor.world.pos.x = player->actor.world.pos.z = .0f; this->csState2 = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 0x39); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x39); this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); @@ -2245,7 +2245,7 @@ void BossTw_TwinrovaIntroCS(BossTw* this, PlayState* play) { this->subCamId = 0; this->csState2 = this->subCamId; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); BossTw_SetupWait(this, play); } break; @@ -2666,7 +2666,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { case 0: this->csState2 = 1; func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, 0, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); @@ -2705,7 +2705,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { sKoumePtr->actor.world.pos.z = sKotakePtr->actor.world.pos.z; sKoumePtr->work[YAW_TGT] = sKotakePtr->work[YAW_TGT] = sKoumePtr->actor.shape.rot.x = sKotakePtr->actor.shape.rot.x = sKoumePtr->actor.shape.rot.y = sKotakePtr->actor.shape.rot.y = 0; - func_8002DF54(play, &sKoumePtr->actor, 1); + Player_SetCsActionWithHaltedActors(play, &sKoumePtr->actor, 1); sKoumePtr->actor.flags |= ACTOR_FLAG_TARGETABLE; } break; @@ -2793,7 +2793,7 @@ void BossTw_TwinrovaDeathCS(BossTw* this, PlayState* play) { this->csState2 = 4; this->subCamId = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS_CLEAR); if (!IS_BOSS_RUSH) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 600.0f, 230.0f, 0.0f, 0, diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index 0e5a95608..77a497e7a 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -657,7 +657,7 @@ void BossVa_Init(Actor* thisx, PlayState* play2) { } else { sCsState = INTRO_CALL_BARI; sDoorState = 100; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); play->envCtx.screenFillColor[0] = 0xDC; play->envCtx.screenFillColor[1] = 0xDC; play->envCtx.screenFillColor[2] = 0xBE; @@ -799,7 +799,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { play->envCtx.screenFillColor[1] = 0xDC; play->envCtx.screenFillColor[2] = 0xBE; play->envCtx.screenFillColor[3] = 0xD2; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); player->actor.world.rot.y = player->actor.shape.rot.y = 0x7FFF; sCsState++; break; @@ -827,7 +827,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { case INTRO_CLOSE_DOOR: this->timer--; if (this->timer == 0) { - func_8002DF54(play, &this->actor, 2); + Player_SetCsActionWithHaltedActors(play, &this->actor, 2); sCsState++; this->timer = 30; } @@ -842,7 +842,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { } break; case INTRO_CRACKLE: - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); sCsState++; break; case INTRO_SPAWN_BARI: @@ -973,7 +973,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { sCameraAtMaxVel = sCameraEyeMaxVel; if (this->timer >= 45000) { play->envCtx.unk_BF = 1; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); } else if (this->timer >= 35000) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_BOSS); } @@ -1030,7 +1030,7 @@ void BossVa_BodyIntro(BossVa* this, PlayState* play) { sCsCamera = 0; func_80064534(play, &play->csCtx); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sCsState++; Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE); player->actor.shape.rot.y = player->actor.world.rot.y = this->actor.yawTowardsPlayer + 0x8000; @@ -1550,7 +1550,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { switch (sCsState) { case DEATH_START: - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); func_80064520(play, &play->csCtx); sCsCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); @@ -1613,7 +1613,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { 0x28); this->onCeiling = 2; // Not used by body BossVa_SetDeathEnv(play); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); } break; case DEATH_CORE_BURST: @@ -1654,7 +1654,7 @@ void BossVa_BodyDeath(BossVa* this, PlayState* play) { camera->at = sCameraAt; - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sCsState++; if (!IS_BOSS_RUSH) { @@ -2444,7 +2444,7 @@ void BossVa_BariIntro(BossVa* this, PlayState* play) { switch (sCsState) { case INTRO_LOOK_BARI: if (this->actor.params == BOSSVA_BARI_UPPER_1) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if (Math_SmoothStepToF(&this->actor.world.pos.y, 60.0f, 0.3f, 1.0f, 0.15f) == 0.0f) { this->timer--; if (this->timer == 0) { diff --git a/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c b/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c index 1c2f4c16b..cffdbea38 100644 --- a/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c +++ b/soh/src/overlays/actors/ovl_Demo_Du/z_demo_du.c @@ -3,6 +3,7 @@ #include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -184,7 +185,9 @@ void func_80969F38(DemoDu* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, DEMO_EFFECT_MEDAL_FIRE); - Item_Give(play, ITEM_MEDALLION_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FIRE); + } } void func_80969FB4(DemoDu* this, PlayState* play) { @@ -201,7 +204,9 @@ void DemoDu_CsFireMedallion_AdvanceTo01(DemoDu* this, PlayState* play) { this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1); play->csCtx.segment = D_8096C1A4; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FIRE); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 9e4dd6119..4af2e9f87 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -142,7 +142,7 @@ f32 DemoEffect_InterpolateCsFrames(PlayState* play, s32 csActionId) { */ void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) { this->initDrawFunc = DemoEffect_DrawJewel; - if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { + if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) { this->initDrawFunc = DemoEffect_DrawGetItem; } if (!LINK_IS_ADULT) { @@ -156,7 +156,7 @@ void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) { Actor_SetScale(&this->actor, 0.10f); } this->csActionId = 1; - this->actor.shape.rot.x = (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) ? 0 : 16384; + this->actor.shape.rot.x = (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) ? 0 : 16384; DemoEffect_InitJewelColor(this); this->jewel.alpha = 0; this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0; @@ -2087,13 +2087,48 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { this->getItem.isLoaded = 1; return; } - if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); - this->getItem.drawId = getItemEntry.gid; - func_8002EBCC(thisx, play, 0); - func_8002ED80(thisx, play, 0); - GetItemEntry_Draw(play, getItemEntry); - return; + if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) { + GetItemEntry getItemEntry = GET_ITEM_NONE; + + switch (this->actor.params) { + case DEMO_EFFECT_JEWEL_KOKIRI: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD); + break; + case DEMO_EFFECT_JEWEL_GORON: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY); + break; + case DEMO_EFFECT_JEWEL_ZORA: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + break; + case DEMO_EFFECT_MEDAL_FOREST: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_FIRE: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_WATER: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_SPIRIT: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_SHADOW: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION); + break; + case DEMO_EFFECT_MEDAL_LIGHT: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION); + break; + case DEMO_EFFECT_LIGHTARROW: + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS); + break; + } + if (getItemEntry.getItemId != GI_NONE) { + this->getItem.drawId = getItemEntry.gid; + func_8002EBCC(thisx, play, 0); + func_8002ED80(thisx, play, 0); + GetItemEntry_Draw(play, getItemEntry); + return; + } } func_8002EBCC(thisx, play, 0); func_8002ED80(thisx, play, 0); diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index 4ddeec155..1df2325e8 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -10,6 +10,7 @@ #include "scenes/indoors/nakaniwa/nakaniwa_scene.h" #include "objects/object_im/object_im.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -318,7 +319,9 @@ void func_809853B4(DemoIm* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0, 0, 0, 0xD); - Item_Give(play, ITEM_MEDALLION_SHADOW); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SHADOW); + } } void func_80985430(DemoIm* this, PlayState* play) { @@ -334,7 +337,9 @@ void func_8098544C(DemoIm* this, PlayState* play) { this->action = 1; play->csCtx.segment = D_8098786C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_SHADOW); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SHADOW); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } } @@ -875,7 +880,7 @@ void func_80986B2C(PlayState* play) { } play->transitionType = TRANS_TYPE_CIRCLE(TCA_STARBURST, TCC_BLACK, TCS_FAST); play->transitionTrigger = TRANS_TRIGGER_START; - func_8002DF54(play, &player->actor, 8); + Player_SetCsActionWithHaltedActors(play, &player->actor, 8); } } @@ -903,40 +908,17 @@ void func_80986BF8(DemoIm* this, PlayState* play) { } } -void GivePlayerRandoRewardImpa(Actor* impa, PlayState* play, RandomizerCheck check) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY); - - if (impa->parent != NULL && impa->parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - } else if (!Flags_GetTreasure(play, 0x1F) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { - GiveItemEntryFromActor(impa, play, getItemEntry, 75.0f, 50.0f); - } else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) { - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); - play->transitionTrigger = TRANS_TRIGGER_START; - play->transitionType = TRANS_TYPE_FADE_WHITE; - gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE; - // In entrance rando have impa bring link back to the front of castle grounds - if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) { - play->nextEntranceIndex = ENTR_HYRULE_CASTLE_0; - } else { - play->nextEntranceIndex = ENTR_HYRULE_FIELD_17; - } - gSaveContext.nextCutsceneIndex = 0; - } -} - void func_80986C30(DemoIm* this, PlayState* play) { if (func_80986A5C(this, play)) { - if (IS_RANDO) { - GivePlayerRandoRewardImpa(this, play, RC_SONG_FROM_IMPA); - } else { + if (GameInteractor_Should(GI_VB_PLAY_ZELDAS_LULLABY_CS, true, this)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); - Item_Give(play, ITEM_SONG_LULLABY); func_80985F54(this); } + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) { + Item_Give(play, ITEM_SONG_LULLABY); + } } } @@ -960,7 +942,7 @@ void func_80986D40(DemoIm* this, PlayState* play) { if (gSaveContext.sceneSetupIndex == 6) { this->action = 19; this->drawConfig = 1; - } else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { + } else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { // SoH [Randomizer] Not sure why we're not killing impa here. Actor_Kill(&this->actor); } else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) { this->action = 23; diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h index 3697733e1..06d6e5d7e 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.h @@ -51,4 +51,6 @@ typedef struct DemoIm { /* 0x02D4 */ NpcInteractInfo interactInfo; } DemoIm; // size = 0x02FC +void func_80986794(DemoIm* demoIm); + #endif diff --git a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c index 01a2ab047..09a45856b 100644 --- a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c +++ b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c @@ -64,66 +64,23 @@ static u8 sEnergyColors[] = { /* Forest prim */ 255, 255, 170, /* env */ 0, 200, 0, }; -// Translates from the barrier's actor params to their corresponding randInf flags. -RandomizerInf trialParamToRandInf(u16 params) { - switch (params) { - case KEKKAI_LIGHT: - return RAND_INF_TRIALS_DONE_LIGHT_TRIAL; - case KEKKAI_FOREST: - return RAND_INF_TRIALS_DONE_FOREST_TRIAL; - case KEKKAI_FIRE: - return RAND_INF_TRIALS_DONE_FIRE_TRIAL; - case KEKKAI_WATER: - return RAND_INF_TRIALS_DONE_WATER_TRIAL; - case KEKKAI_SPIRIT: - return RAND_INF_TRIALS_DONE_SPIRIT_TRIAL; - case KEKKAI_SHADOW: - return RAND_INF_TRIALS_DONE_SHADOW_TRIAL; - } -} - s32 DemoKekkai_CheckEventFlag(s32 params) { - static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB }; + static s32 eventFlags[] = { + EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER, + EVENTCHKINF_COMPLETED_WATER_TRIAL, + EVENTCHKINF_COMPLETED_LIGHT_TRIAL, + EVENTCHKINF_COMPLETED_FIRE_TRIAL, + EVENTCHKINF_COMPLETED_SHADOW_TRIAL, + EVENTCHKINF_COMPLETED_SPIRIT_TRIAL, + EVENTCHKINF_COMPLETED_FOREST_TRIAL, + }; if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) { return true; } - if (IS_RANDO && params > KEKKAI_TOWER) { - return Flags_GetRandomizerInf(trialParamToRandInf(params)); - } return Flags_GetEventChkInf(eventFlags[params]); } -u32 TrialsDoneCount() { - u8 trialCount = 0; - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) { - trialCount++; - } - - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) { - trialCount++; - } - - return trialCount; -} - void DemoKekkai_Init(Actor* thisx, PlayState* play) { s32 pad; DemoKekkai* this = (DemoKekkai*)thisx; @@ -147,13 +104,6 @@ void DemoKekkai_Init(Actor* thisx, PlayState* play) { this->collider2.dim.radius = thisx->scale.x * 6100.0f; this->collider2.dim.height = thisx->scale.y * 5000.0f; this->collider2.dim.yShift = 300; - - if (IS_RANDO) { - if (TrialsDoneCount() == NUM_TRIALS) { - Actor_Kill(thisx); - return; - } - } break; case KEKKAI_WATER: case KEKKAI_LIGHT: @@ -161,10 +111,6 @@ void DemoKekkai_Init(Actor* thisx, PlayState* play) { case KEKKAI_SHADOW: case KEKKAI_SPIRIT: case KEKKAI_FOREST: - if (IS_RANDO && Flags_GetRandomizerInf(trialParamToRandInf(thisx->params))) { - Actor_Kill(thisx); - return; - } this->energyAlpha = 1.0f; this->orbScale = 1.0f; Actor_SetScale(thisx, 0.1f); @@ -265,18 +211,10 @@ void DemoKekkai_Update(Actor* thisx, PlayState* play2) { } void DemoKekkai_TrialBarrierDispel(Actor* thisx, PlayState* play) { - static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB }; static u16 csFrames[] = { 0, 280, 280, 280, 280, 280, 280 }; s32 pad; DemoKekkai* this = (DemoKekkai*)thisx; - if (IS_RANDO) { - Flags_SetRandomizerInf(trialParamToRandInf(thisx->params)); - // May or may not be needed. Not sure if needed for anything - // that randoInf isn't already covering. Leaving it for safety. - Flags_SetEventChkInf(eventFlags[thisx->params]); - } - if (play->csCtx.frames == csFrames[this->actor.params]) { func_800F3F3C(0xA); } diff --git a/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c b/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c index 6da87ab3c..85dcb4ebe 100644 --- a/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c +++ b/soh/src/overlays/actors/ovl_Demo_Sa/z_demo_sa.c @@ -9,6 +9,7 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "objects/object_sa/object_sa.h" #include "soh/Enhancements/boss-rush/BossRush.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "vt.h" @@ -241,7 +242,9 @@ void func_8098E8C8(DemoSa* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0xB); - Item_Give(play, ITEM_MEDALLION_FOREST); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FOREST); + } } void func_8098E944(DemoSa* this, PlayState* play) { @@ -258,7 +261,9 @@ void func_8098E960(DemoSa* this, PlayState* play) { this->action = 1; play->csCtx.segment = D_8099010C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_FOREST); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_FOREST); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } else { this->action = 1; diff --git a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index 22c850111..04f388b39 100644 --- a/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/soh/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -20,7 +20,6 @@ void DoorAna_WaitClosed(DoorAna* this, PlayState* play); void DoorAna_WaitOpen(DoorAna* this, PlayState* play); void DoorAna_GrabPlayer(DoorAna* this, PlayState* play); -s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, PlayState* play); void Grotto_OverrideActorEntrance(Actor* thisx); const ActorInit Door_Ana_InitVars = { diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index c61822f67..34c0a0f20 100644 --- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -23,6 +23,7 @@ #include "objects/object_menkuri_objects/object_menkuri_objects.h" #include "objects/object_demo_kekkai/object_demo_kekkai.h" #include "objects/object_ouke_haka/object_ouke_haka.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -354,9 +355,11 @@ void func_80996A54(DoorShutter* this, PlayState* play) { if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) { Flags_SetClear(play, this->dyna.actor.room); DoorShutter_SetupAction(this, func_80997150); - OnePointCutscene_Attention(play, &this->dyna.actor); - OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor); - this->unk_16F = -100; + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Attention(play, &this->dyna.actor); + OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor); + this->unk_16F = -100; + } } else if (func_809968D4(this, play) != 0) { Player* player = GET_PLAYER(play); @@ -470,8 +473,10 @@ void func_80996EE8(DoorShutter* this, PlayState* play) { if (func_80996E08(this, play, 1.0f)) { if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) { DoorShutter_SetupAction(this, func_80997150); - OnePointCutscene_Attention(play, &this->dyna.actor); - this->unk_16F = -100; + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_Attention(play, &this->dyna.actor); + this->unk_16F = -100; + } } else if (func_809968D4(this, play)) { Player* player = GET_PLAYER(play); // Jabu navi text for switch doors is different @@ -555,7 +560,7 @@ void func_80997220(DoorShutter* this, PlayState* play) { this->dyna.actor.velocity.y = 0.0f; if (DoorShutter_SetupDoor(this, play) && !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { DoorShutter_SetupAction(this, func_80997568); - func_8002DF54(play, NULL, 2); + Player_SetCsActionWithHaltedActors(play, NULL, 2); } } @@ -589,7 +594,7 @@ void func_80997528(DoorShutter* this, PlayState* play) { void func_80997568(DoorShutter* this, PlayState* play) { if (this->unk_16F++ > 30) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); DoorShutter_SetupDoor(this, play); } } diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 5ea64e232..710c138e2 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -2,6 +2,7 @@ #include "objects/object_warp1/object_warp1.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/boss-rush/BossRush.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -487,44 +488,6 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, PlayState* play) { return ret; } -void GivePlayerRandoReward(DoorWarp1* this, Player* player, PlayState* play, u8 ruto, u8 adult) { - GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, 0x00, GI_NONE); - - if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - } else if (!Flags_GetTreasure(play, 0x1F)) { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f); - } else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) { - if (adult) { - OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); - player->unk_450.x = this->actor.world.pos.x; - player->unk_450.z = this->actor.world.pos.z; - this->unk_1B2 = 20; - DoorWarp1_SetupAction(this, func_8099A508); - } else { - if (ruto) { - this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED; - func_8002DF54(play, &this->actor, 10); - this->unk_1B2 = 1; - DoorWarp1_SetupAction(this, func_80999EE0); - } else { - Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, - &D_801333E8); - OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); - - player->unk_450.x = this->actor.world.pos.x; - player->unk_450.z = this->actor.world.pos.z; - this->unk_1B2 = 1; - - DoorWarp1_SetupAction(this, DoorWarp1_ChildWarpOut); - } - } - } -} - void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) { Player* player; @@ -532,16 +495,11 @@ void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) { if (DoorWarp1_PlayerInRange(this, play)) { player = GET_PLAYER(play); - - if (IS_RANDO) { - GivePlayerRandoReward(this, player, play, 0, 0); - return; - } Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); + Player_SetCsActionWithHaltedActors(play, &this->actor, 10); player->unk_450.x = this->actor.world.pos.x; player->unk_450.z = this->actor.world.pos.z; @@ -570,36 +528,26 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) { osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START); if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN); - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_GORON_RUBY)) { Item_Give(play, ITEM_GORON_RUBY); - play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0; - gSaveContext.nextCutsceneIndex = 0xFFF1; } + play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0; + gSaveContext.nextCutsceneIndex = 0xFFF1; } else { play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5; gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD), EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE); - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11; - gSaveContext.nextCutsceneIndex = 0; - // Skip Mido complaining about dead Deku tree - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH); - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_KOKIRI_EMERALD)) { Item_Give(play, ITEM_KOKIRI_EMERALD); - play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0; - gSaveContext.nextCutsceneIndex = 0xFFF1; } + play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0; + gSaveContext.nextCutsceneIndex = 0xFFF1; } else { play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11; gSaveContext.nextCutsceneIndex = 0; @@ -635,14 +583,8 @@ void DoorWarp1_RutoWarpIdle(DoorWarp1* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG); if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) { - - if (IS_RANDO) { - GivePlayerRandoReward(this, GET_PLAYER(play), play, 1, 0); - return; - } - this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED; - func_8002DF54(play, &this->actor, 10); + Player_SetCsActionWithHaltedActors(play, &this->actor, 10); this->unk_1B2 = 1; DoorWarp1_SetupAction(this, func_80999EE0); } @@ -670,9 +612,8 @@ void func_80999EE0(DoorWarp1* this, PlayState* play) { Play_CameraSetAtEye(play, sRutoWarpSubCamId, &at, &eye); Play_CameraSetFov(play, sRutoWarpSubCamId, 90.0f); this->rutoWarpState = WARP_BLUE_RUTO_STATE_TALKING; - if (!IS_RANDO) { - Message_StartTextbox(play, 0x4022, NULL); - } + // TODO: Why was this disabled in rando? + Message_StartTextbox(play, 0x4022, NULL); DoorWarp1_SetupAction(this, func_80999FE4); } } @@ -704,17 +645,14 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, PlayState* play) { this->warpTimer++; if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) { - Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; - gSaveContext.nextCutsceneIndex = 0; - } else { - Item_Give(play, ITEM_ZORA_SAPPHIRE); - play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, true, EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) { + Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) { + Item_Give(play, ITEM_ZORA_SAPPHIRE); + } gSaveContext.nextCutsceneIndex = 0xFFF0; } + play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0; if (IS_RANDO && (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) { @@ -767,13 +705,8 @@ void DoorWarp1_AdultWarpIdle(DoorWarp1* this, PlayState* play) { player = GET_PLAYER(play); - if (IS_RANDO) { - GivePlayerRandoReward(this, player, play, 0, 1); - return; - } - OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 10); + Player_SetCsActionWithHaltedActors(play, &this->actor, 10); player->unk_450.x = this->actor.world.pos.x; player->unk_450.z = this->actor.world.pos.z; this->unk_1B2 = 20; @@ -829,19 +762,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { if (IS_BOSS_RUSH) { BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z); } else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_3; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FOREST)) { Item_Give(play, ITEM_MEDALLION_FOREST); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_2; @@ -851,20 +779,13 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5; - gSaveContext.nextCutsceneIndex = 0; - // Change Death Mountain cloud since we aren't warping to the cutscene - Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED); - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FIRE)) { Item_Give(play, ITEM_MEDALLION_FIRE); - play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; - gSaveContext.nextCutsceneIndex = 0xFFF3; } + play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0; + gSaveContext.nextCutsceneIndex = 0xFFF3; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_4; @@ -874,21 +795,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) { - if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) { Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP); - Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_LAKE_HYLIA_9; - gSaveContext.nextCutsceneIndex = 0; - // Fill Lake Hylia since we aren't warping to the cutscene - Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_WATER)) { Item_Give(play, ITEM_MEDALLION_WATER); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_LAKE_HYLIA_8; @@ -898,18 +812,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { - if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_8; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { Item_Give(play, ITEM_MEDALLION_SPIRIT); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_5; @@ -919,18 +829,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { - if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); - - if (IS_RANDO) { - play->nextEntranceIndex = ENTR_GRAVEYARD_8; - gSaveContext.nextCutsceneIndex = 0; - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { Item_Give(play, ITEM_MEDALLION_SHADOW); - play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; - gSaveContext.nextCutsceneIndex = 0; - gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW; } + play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0; + gSaveContext.nextCutsceneIndex = 0; + gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW; } else { if (!LINK_IS_ADULT) { play->nextEntranceIndex = ENTR_GRAVEYARD_7; diff --git a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c index 3fe7fc689..495ef96b8 100644 --- a/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c +++ b/soh/src/overlays/actors/ovl_Elf_Msg/z_elf_msg.c @@ -7,6 +7,7 @@ #include "z_elf_msg.h" #include "vt.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -110,7 +111,7 @@ void ElfMsg_Destroy(Actor* thisx, PlayState* play) { s32 ElfMsg_GetMessageId(ElfMsg* this) { // Negative message ID forces link to talk to Navi - if (this->actor.params & 0x8000 || CVarGetInteger("gNoForcedNavi", 0) != 0) { + if (this->actor.params & 0x8000) { return (this->actor.params & 0xFF) + 0x100; } else { return -((this->actor.params & 0xFF) + 0x100); @@ -125,8 +126,10 @@ void ElfMsg_CallNaviCuboid(ElfMsg* this, PlayState* play) { (this->actor.world.pos.y <= player->actor.world.pos.y) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) && (fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) { - player->naviTextId = ElfMsg_GetMessageId(this); - navi->elfMsg = this; + if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) { + player->naviTextId = ElfMsg_GetMessageId(this); + navi->elfMsg = this; + } } } @@ -145,8 +148,10 @@ void ElfMsg_CallNaviCylinder(ElfMsg* this, PlayState* play) { if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) && (this->actor.world.pos.y <= player->actor.world.pos.y) && ((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) { - player->naviTextId = ElfMsg_GetMessageId(this); - navi->elfMsg = this; + if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) { + player->naviTextId = ElfMsg_GetMessageId(this); + navi->elfMsg = this; + } } } diff --git a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c index 15ebd759c..57cb6045e 100644 --- a/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/soh/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -6,6 +6,7 @@ #include "z_en_ani.h" #include "objects/object_ani/object_ani.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -119,7 +120,7 @@ void func_809B0524(EnAni* this, PlayState* play) { } void func_809B0558(EnAni* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { this->actor.parent = NULL; if (!LINK_IS_ADULT) { EnAni_SetupAction(this, func_809B04F0); @@ -128,11 +129,8 @@ void func_809B0558(EnAni* this, PlayState* play) { } Flags_SetItemGetInf(ITEMGETINF_15); } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 200.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); } } } @@ -142,11 +140,8 @@ void func_809B05F0(EnAni* this, PlayState* play) { EnAni_SetupAction(this, func_809B0558); } - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_MAN_ON_ROOF, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 200.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAN_ON_ROOF, true, NULL)) { + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 200.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 76c0feac3..2110383a4 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -295,7 +295,7 @@ void EnBomBowMan_RunGame(EnBomBowlMan* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); if (this->gameResult == 2) { - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); } this->actionFunc = EnBomBowlMan_HandlePlayChoice; } else { @@ -345,7 +345,7 @@ void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play) { Message_ContinueTextbox(play, this->actor.textId); this->dialogState = TEXT_STATE_EVENT; OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnBomBowMan_SetupChooseShowPrize; } } else { @@ -381,11 +381,11 @@ void func_809C41FC(EnBomBowlMan* this, PlayState* play) { Message_ContinueTextbox(play, this->actor.textId); this->dialogState = TEXT_STATE_EVENT; OnePointCutscene_Init(play, 8010, -99, NULL, MAIN_CAM); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnBomBowMan_SetupChooseShowPrize; } else { if (this->gameResult == 2) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); } this->actionFunc = EnBomBowMan_SetupRunGame; } @@ -509,7 +509,7 @@ void EnBomBowlMan_BeginPlayGame(EnBomBowlMan* this, PlayState* play) { // "Wow" osSyncPrintf(VT_FGCOL(YELLOW) "☆ わー ☆ %d\n" VT_RST, play->bombchuBowlingStatus); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = EnBomBowMan_SetupRunGame; } } diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index 5c18c52fa..7e5cc3ef1 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -2,6 +2,7 @@ #include "vt.h" #include "overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.h" #include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -68,7 +69,7 @@ void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play) { if (((fabsf(chuPosDiff.x) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.y) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.z) < 40.0f) || (BREG(2)))) { - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); chu->timer = 1; this->camId = Play_CreateSubCamera(play); @@ -107,7 +108,7 @@ void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); this->unk_154 = TEXT_STATE_EVENT; func_80078884(NA_SE_EV_HIT_SOUND); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->status = 1; this->actionFunc = EnBomBowlPit_CameraDollyIn; break; @@ -167,7 +168,7 @@ void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play) { Play_ClearCamera(play, this->camId); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnBomBowlPit_GivePrize; } } @@ -175,58 +176,32 @@ void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play) { void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { Player* player = GET_PLAYER(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->getItemId = sGetItemIds[this->prizeIndex]; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; if ((this->getItemId == GI_BOMB_BAG_30) && (CUR_CAPACITY(UPG_BOMB_BAG) == 30)) { this->getItemId = GI_BOMB_BAG_40; } - if (IS_RANDO) { - switch (this->prizeIndex) { - case EXITEM_BOMB_BAG_BOWLING: - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); - this->getItemId = this->getItemEntry.getItemId; - break; - case EXITEM_HEART_PIECE_BOWLING: - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); - this->getItemId = this->getItemEntry.getItemId; - break; - case EXITEM_BOMBCHUS_BOWLING: - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); - this->getItemId = this->getItemEntry.getItemId; - break; - } - } - player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; this->actor.parent = NULL; - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE; this->actionFunc = EnBomBowlPit_WaitTillPrizeGiven; } void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BOMBCHU_BOWLING, true, this)) { this->actionFunc = EnBomBowlPit_Reset; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } } void EnBomBowlPit_Reset(EnBomBowlPit* this, PlayState* play) { - if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && - Message_ShouldAdvance(play)) || - (IS_RANDO && this->getItemId == GI_ICE_TRAP)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { // "Normal termination"/"completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (this->getItemId == GI_HEART_PIECE) { diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h index 97ff39ac8..48cfbd5c2 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h @@ -33,7 +33,6 @@ typedef struct EnBomBowlPit { /* 0x01D4 */ Vec3f unk_1D4; // camera eye (maxsteps) /* 0x01E0 */ EnExItem* exItem; /* 0x01E4 */ char unk_1E4[0x3520]; - /* */ GetItemEntry getItemEntry; } EnBomBowlPit; // size = 0x3704 #endif diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index dfd8fae27..f6deade38 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -3,6 +3,7 @@ #include "soh_assets.h" #include "soh/Enhancements/enhancementTypes.h" #include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -192,10 +193,12 @@ void EnBox_Init(Actor* thisx, PlayState* play2) { SkelAnime_Init(play, &this->skelanime, &gTreasureChestSkel, anim, this->jointTable, this->morphTable, 5); Animation_Change(&this->skelanime, anim, 1.5f, animFrameStart, endFrame, ANIMMODE_ONCE, 0.0f); + this->getItemEntry = ItemTable_RetrieveEntry(MOD_NONE, this->dyna.actor.params >> 5 & 0x7F); if (IS_RANDO) { - this->getItemEntry = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F); - } else { - this->getItemEntry = ItemTable_RetrieveEntry(MOD_NONE, this->dyna.actor.params >> 5 & 0x7F); + RandomizerCheck rc = Randomizer_GetCheckFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params); + if (rc != RC_UNKNOWN_CHECK) { + this->getItemEntry = Randomizer_GetItemFromKnownCheck(rc, this->dyna.actor.params >> 5 & 0x7F); + } } EnBox_UpdateSizeAndTexture(this, play); @@ -275,7 +278,9 @@ void EnBox_Fall(EnBox* this, PlayState* play) { this->dyna.actor.shape.rot.z = 0; this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; EnBox_SetupAction(this, EnBox_WaitOpen); - OnePointCutscene_EndCutscene(play, this->unk_1AC); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_EndCutscene(play, this->unk_1AC); + } } Audio_PlaySoundGeneral(NA_SE_EV_COFFIN_CAP_BOUND, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8); @@ -445,74 +450,12 @@ void EnBox_WaitOpen(EnBox* this, PlayState* play) { } osSyncPrintf("Actor_Environment_Tbox_On() %d\n", this->dyna.actor.params & 0x1F); Flags_SetTreasure(play, this->dyna.actor.params & 0x1F); - - // treasure chest game rando - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - if (IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP && (this->dyna.actor.params & 0x60) != 0x20) { - if((this->dyna.actor.params & 0xF) < 2) { - Flags_SetCollectible(play, 0x1B); - } - if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) { - Flags_SetCollectible(play, 0x1C); - } - if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) { - Flags_SetCollectible(play, 0x1D); - } - if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) { - Flags_SetCollectible(play, 0x1E); - } - if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) { - Flags_SetCollectible(play, 0x1F); - } - } - } } else { player = GET_PLAYER(play); func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && Player_IsFacingActor(&this->dyna.actor, 0x3000, play)) { - GetItemEntry sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F); - GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); - - // RANDOTODO treasure chest game rando - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - if (IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP && (this->dyna.actor.params & 0x60) != 0x20) { - if((this->dyna.actor.params & 0xF) < 2) { - if(Flags_GetCollectible(play, 0x1B)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) { - if(Flags_GetCollectible(play, 0x1C)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) { - if(Flags_GetCollectible(play, 0x1D)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) { - if(Flags_GetCollectible(play, 0x1E)) { - sItem = blueRupee; - } - } - if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) { - if(Flags_GetCollectible(play, 0x1F)) { - sItem = blueRupee; - } - } - } - } - // Chests need to have a negative getItemId in order to not immediately give their item - // when approaching. - if (IS_RANDO) { - sItem.getItemId = 0 - sItem.getItemId; - sItem.getItemFrom = ITEM_FROM_CHEST; - GiveItemEntryFromActorWithFixedRange(&this->dyna.actor, play, sItem); - } else { func_8002F554(&this->dyna.actor, play, -(this->dyna.actor.params >> 5 & 0x7F)); - } } if (Flags_GetTreasure(play, this->dyna.actor.params & 0x1F)) { EnBox_SetupAction(this, EnBox_Open); @@ -626,12 +569,9 @@ void EnBox_Update(Actor* thisx, PlayState* play) { Actor_SetFocus(&this->dyna.actor, 40.0f); } - if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) || - (IS_RANDO && this->getItemEntry.getItemId == RG_ICE_TRAP)) && - this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) { - if (!CVarGetInteger("gAddTraps.enabled", 0)) { - EnBox_SpawnIceSmoke(this, play); - } + if ((this->dyna.actor.params >> 5 & 0x7F) == GI_ICE_TRAP && this->actionFunc == EnBox_Open && + this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) { + EnBox_SpawnIceSmoke(this, play); } } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.h b/soh/src/overlays/actors/ovl_En_Box/z_en_box.h index 765779367..0168fc1a8 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.h +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.h @@ -4,6 +4,7 @@ #include #include "global.h" +#define ENBOX_PARAMS(type, itemId, treasureFlag) ((type) << 12 | (itemId) << 5 | (treasureFlag)) #define ENBOX_TREASURE_FLAG_UNK_MIN 20 #define ENBOX_TREASURE_FLAG_UNK_MAX 32 @@ -45,7 +46,7 @@ typedef struct EnBox { /* 0x01F9 */ u8 type; /* 0x01FA */ u8 iceSmokeTimer; /* 0x01FB */ u8 unk_1FB; - /* */ GetItemEntry getItemEntry; + /* */ GetItemEntry getItemEntry; // This is only to determine the Chest Style, randomzier item gives are handled elsewhere /* */ Gfx* boxLidDL; /* */ Gfx* boxBodyDL; } EnBox; // size = 0x01FC diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c index 04123c7b3..9869a0621 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.c @@ -6,6 +6,7 @@ #include "z_en_cow.h" #include "objects/object_cow/object_cow.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -18,7 +19,6 @@ void func_809E0070(Actor* thisx, PlayState* play); void func_809DF494(EnCow* this, PlayState* play); void func_809DF6BC(EnCow* this, PlayState* play); -void EnCow_MoveForRandomizer(EnCow* this, PlayState* play); void func_809DF778(EnCow* this, PlayState* play); void func_809DF7D8(EnCow* this, PlayState* play); void func_809DF870(EnCow* this, PlayState* play); @@ -107,10 +107,6 @@ void EnCow_Init(Actor* thisx, PlayState* play) { EnCow* this = (EnCow*)thisx; s32 pad; - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_COWS)) { - EnCow_MoveForRandomizer(thisx, play); - } - ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f); switch (this->actor.params) { case 0: @@ -122,18 +118,15 @@ void EnCow_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->colliders[1], &this->actor, &sCylinderInit); func_809DEE9C(this); this->actionFunc = func_809DF96C; - if (play->sceneNum == SCENE_LINKS_HOUSE) { - if (!LINK_IS_ADULT && !CVarGetInteger("gCowOfTime", 0)) { - Actor_Kill(&this->actor); - return; - } - if (!Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) { - Actor_Kill(&this->actor); - return; - } + if (GameInteractor_Should(GI_VB_DESPAWN_HORSE_RACE_COW, ( + play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) + ), this)) { + Actor_Kill(&this->actor); + return; } + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_COW, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1); + this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1); this->unk_278 = Rand_ZeroFloat(1000.0f) + 40.0f; this->unk_27A = 0; this->actor.targetMode = 6; @@ -216,36 +209,12 @@ void func_809DF730(EnCow* this, PlayState* play) { } } -void EnCow_MoveForRandomizer(EnCow* this, PlayState* play) { - // Only move the cow body (the tail will be moved with the body) - if (this->actor.params != 0) { - return; - } - - // Move left cow in lon lon tower - if (play->sceneNum == SCENE_LON_LON_BUILDINGS && this->actor.world.pos.x == -108 && this->actor.world.pos.z == -65) { - this->actor.world.pos.x = -229.0f; - this->actor.world.pos.z = 157.0f; - this->actor.shape.rot.y = 15783.0f; - // Move right cow in lon lon stable - } else if (play->sceneNum == SCENE_STABLE && this->actor.world.pos.x == -3 && this->actor.world.pos.z == -254) { - this->actor.world.pos.x += 119.0f; - } -} - -void EnCow_SetCowMilked(EnCow* this, PlayState* play) { - CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z); - Player* player = GET_PLAYER(play); - player->pendingFlag.flagID = cowIdentity.randomizerInf; - player->pendingFlag.flagType = FLAG_RANDOMIZER_INF; -} - void func_809DF778(EnCow* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actor.parent = NULL; this->actionFunc = func_809DF730; } else { - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 100.0f); } } @@ -254,7 +223,7 @@ void func_809DF7D8(EnCow* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; Message_CloseTextbox(play); this->actionFunc = func_809DF778; - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 100.0f); } } @@ -281,23 +250,6 @@ void func_809DF8FC(EnCow* this, PlayState* play) { func_809DF494(this, play); } -bool EnCow_HasBeenMilked(EnCow* this, PlayState* play) { - CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z); - return Flags_GetRandomizerInf(cowIdentity.randomizerInf); -} - -void EnCow_GivePlayerRandomizedItem(EnCow* this, PlayState* play) { - if (!EnCow_HasBeenMilked(this, play)) { - CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z); - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(cowIdentity.randomizerCheck, GI_MILK); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 100.0f); - } else { - // once we've gotten the rando reward from the cow, - // return them to the their default action function - this->actionFunc = func_809DF96C; - } -} - void func_809DF96C(EnCow* this, PlayState* play) { if ((play->msgCtx.ocarinaMode == OCARINA_MODE_00) || (play->msgCtx.ocarinaMode == OCARINA_MODE_04)) { if (DREG(53) != 0) { @@ -308,23 +260,14 @@ void func_809DF96C(EnCow* this, PlayState* play) { if ((this->actor.xzDistToPlayer < 150.0f) && (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) { DREG(53) = 0; - // when randomized with cowsanity, if we haven't gotten the - // reward from this cow yet, give that, otherwise use the - // vanilla cow behavior - if (IS_RANDO && - Randomizer_GetSettingValue(RSK_SHUFFLE_COWS) && - !EnCow_HasBeenMilked(this, play)) { - EnCow_SetCowMilked(this, play); - // setting the ocarina mode here prevents intermittent issues - // with the item get not triggering until walking away - play->msgCtx.ocarinaMode = OCARINA_MODE_00; - this->actionFunc = EnCow_GivePlayerRandomizedItem; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_COW, true, this)) { + this->actionFunc = func_809DF8FC; + this->actor.flags |= ACTOR_FLAG_WILL_TALK; + func_8002F2CC(&this->actor, play, 170.0f); + this->actor.textId = 0x2006; + } else { return; } - this->actionFunc = func_809DF8FC; - this->actor.flags |= ACTOR_FLAG_WILL_TALK; - func_8002F2CC(&this->actor, play, 170.0f); - this->actor.textId = 0x2006; } else { this->unk_276 |= 4; } diff --git a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h index 63dbbddd3..3cd244388 100644 --- a/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h +++ b/soh/src/overlays/actors/ovl_En_Cow/z_en_cow.h @@ -21,4 +21,6 @@ typedef struct EnCow { /* 0x027C */ EnCowActionFunc actionFunc; } EnCow; // size = 0x0280 +void func_809DEE9C(EnCow* enCow); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c b/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c index 8df2f8c0b..715a48c37 100644 --- a/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c +++ b/soh/src/overlays/actors/ovl_En_Daiku/z_en_daiku.c @@ -470,7 +470,7 @@ void EnDaiku_InitSubCamera(EnDaiku* this, PlayState* play) { Play_CameraSetAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); Play_CameraSetFov(play, this->subCamId, play->mainCamera.fov); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } void EnDaiku_UpdateSubCamera(EnDaiku* this, PlayState* play) { @@ -507,7 +507,7 @@ void EnDaiku_EscapeSuccess(EnDaiku* this, PlayState* play) { Actor_Kill(&this->actor); } } else { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } } diff --git a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c index df00c3cf5..b411c1427 100644 --- a/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c +++ b/soh/src/overlays/actors/ovl_En_Diving_Game/z_en_diving_game.c @@ -8,6 +8,7 @@ #include "overlays/actors/ovl_En_Ex_Ruppy/z_en_ex_ruppy.h" #include "objects/object_zo/object_zo.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -138,7 +139,7 @@ s32 EnDivingGame_HasMinigameFinished(EnDivingGame* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); this->unk_292 = TEXT_STATE_EVENT; this->allRupeesThrown = this->state = this->phase = this->unk_2A2 = this->grabbedRupeesCounter = 0; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_809EE048; return true; } else { @@ -163,7 +164,7 @@ s32 EnDivingGame_HasMinigameFinished(EnDivingGame* this, PlayState* play) { this->unk_292 = TEXT_STATE_EVENT; func_800F5B58(); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_SILVER_SCALE)) { this->actionFunc = func_809EE96C; } else { @@ -191,7 +192,7 @@ void EnDivingGame_Talk(EnDivingGame* this, PlayState* play) { if (this->unk_292 != TEXT_STATE_DONE) { switch (this->state) { case ENDIVINGGAME_STATE_NOTPLAYING: - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnDivingGame_HandlePlayChoice; break; case ENDIVINGGAME_STATE_AWARDPRIZE: @@ -258,7 +259,7 @@ void EnDivingGame_HandlePlayChoice(EnDivingGame* this, PlayState* play) { this->actionFunc = func_809EE048; } else { play->msgCtx.msgMode = MSGMODE_PAUSED; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_809EE0FC; } } @@ -270,11 +271,11 @@ void func_809EE048(EnDivingGame* this, PlayState* play) { if (this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { if (this->phase == ENDIVINGGAME_PHASE_ENDED) { Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_809EDCB0; } else { play->msgCtx.msgMode = MSGMODE_PAUSED; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_809EE0FC; } } @@ -419,7 +420,7 @@ void func_809EE800(EnDivingGame* this, PlayState* play) { func_80088B34(BREG(2) + 50); } func_800F5ACC(NA_BGM_TIMED_MINI_GAME); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.textId = 0x405B; this->unk_292 = TEXT_STATE_EVENT; this->state = ENDIVINGGAME_STATE_PLAYING; @@ -442,7 +443,7 @@ void func_809EE96C(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play))) { Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.textId = 0x4056; this->unk_292 = TEXT_STATE_EVENT; this->state = ENDIVINGGAME_STATE_AWARDPRIZE; @@ -455,11 +456,8 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { if ((this->unk_292 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play))) { Message_CloseTextbox(play); this->actor.parent = NULL; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 90.0f, 10.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { + Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); } this->actionFunc = func_809EEA90; } @@ -467,14 +465,11 @@ void func_809EEA00(EnDivingGame* this, PlayState* play) { void func_809EEA90(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { this->actionFunc = func_809EEAF8; } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_DIVING_MINIGAME, GI_SCALE_SILVER); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 90.0f, 10.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { + Actor_OfferGetItem(&this->actor, play, GI_SCALE_SILVER, 90.0f, 10.0f); } } } @@ -482,7 +477,8 @@ void func_809EEA90(EnDivingGame* this, PlayState* play) { // Award the scale? void func_809EEAF8(EnDivingGame* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) || + !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_DIVING_MINIGAME, true, &this->actor)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); this->allRupeesThrown = this->state = this->phase = this->unk_2A2 = this->grabbedRupeesCounter = 0; diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index cf73c6a94..6ea9c26e1 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -16,7 +16,6 @@ void EnDns_Destroy(Actor* thisx, PlayState* play); void EnDns_Update(Actor* thisx, PlayState* play); void EnDns_Draw(Actor* thisx, PlayState* play); -u32 EnDns_RandomizerPurchaseableCheck(EnDns* this); u32 func_809EF5A4(EnDns* this); u32 func_809EF658(EnDns* this); u32 func_809EF70C(EnDns* this); @@ -26,7 +25,6 @@ u32 func_809EF854(EnDns* this); u32 func_809EF8F4(EnDns* this); u32 func_809EF9A4(EnDns* this); -void EnDns_RandomizerPurchase(EnDns* this); void func_809EF9F8(EnDns* this); void func_809EFA28(EnDns* this); void func_809EFA58(EnDns* this); @@ -168,32 +166,6 @@ void EnDns_Init(Actor* thisx, PlayState* play) { this->actor.gravity = -1.0f; this->actor.textId = D_809F040C[this->actor.params]; this->dnsItemEntry = sItemEntries[this->actor.params]; - if (IS_RANDO) { - // Ugly, but the best way we can identify which grotto we are in, same method 3DRando uses, but we'll need to account for entrance rando - s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); - this->scrubIdentity = Randomizer_IdentifyScrub(play->sceneNum, this->actor.params, respawnData); - - if ((Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_AFFORDABLE || - Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_RANDOM) && - this->scrubIdentity.itemPrice != -1) { - this->dnsItemEntry->itemPrice = this->scrubIdentity.itemPrice; - } - - if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_EXPENSIVE) { - // temporary workaround: always use 40 rupees as price instead of 70 - if (this->actor.params == 0x0006) { - this->dnsItemEntry->itemPrice = 40; - } - } - - if (this->scrubIdentity.isShuffled) { - this->dnsItemEntry->getItemId = this->scrubIdentity.getItemId; - this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck; - this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase; - this->dnsItemEntry->itemAmount = 1; - this->actor.textId = 0x9000 + (this->scrubIdentity.randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - } - } this->actionFunc = EnDns_SetupWait; } @@ -216,13 +188,6 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) { /* Item give checking functions */ -u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) { - if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || Flags_GetRandomizerInf(this->scrubIdentity.randomizerInf)) { - return 0; - } - return 4; -} - u32 func_809EF5A4(EnDns* this) { if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) { return 1; @@ -319,10 +284,6 @@ u32 func_809EF9A4(EnDns* this) { } /* Paying and flagging functions */ -void EnDns_RandomizerPurchase(EnDns* this) { - Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); - Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf); -} void func_809EF9F8(EnDns* this) { Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); @@ -412,44 +373,39 @@ void EnDns_Talk(EnDns* this, PlayState* play) { void func_809EFDD0(EnDns* this, PlayState* play) { u16 pendingGetItemId; - if (!IS_RANDO || !this->scrubIdentity.isShuffled) { - if (this->actor.params == 0x9) { - if (CUR_UPG_VALUE(UPG_STICKS) < 2) { - pendingGetItemId = GI_STICK_UPGRADE_20; - } else { - pendingGetItemId = GI_STICK_UPGRADE_30; - } - } else if (this->actor.params == 0xA) { - if (CUR_UPG_VALUE(UPG_NUTS) < 2) { - pendingGetItemId = GI_NUT_UPGRADE_30; - } else { - pendingGetItemId = GI_NUT_UPGRADE_40; - } + if (this->actor.params == 0x9) { + if (CUR_UPG_VALUE(UPG_STICKS) < 2) { + pendingGetItemId = GI_STICK_UPGRADE_20; } else { - pendingGetItemId = this->dnsItemEntry->getItemId; + pendingGetItemId = GI_STICK_UPGRADE_30; + } + } else if (this->actor.params == 0xA) { + if (CUR_UPG_VALUE(UPG_NUTS) < 2) { + pendingGetItemId = GI_NUT_UPGRADE_30; + } else { + pendingGetItemId = GI_NUT_UPGRADE_40; } - GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } else { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - GiveItemEntryFromActor(&this->actor, play, itemEntry, 130.0f, 100.0f); + pendingGetItemId = this->dnsItemEntry->getItemId; } + GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; + Actor_OfferGetItem(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } void func_809EFEE8(EnDns* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - func_809EFDD0(this, play); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { + func_809EFDD0(this, play); + } this->actionFunc = func_809EFF50; } } void func_809EFF50(EnDns* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) { this->actor.parent = NULL; this->actionFunc = func_809EFF98; } else { @@ -533,9 +489,6 @@ void EnDns_Update(Actor* thisx, PlayState* play) { this->dustTimer++; this->actor.textId = D_809F040C[this->actor.params]; - if (IS_RANDO && this->scrubIdentity.isShuffled) { - this->actor.textId = 0x9000 + (this->scrubIdentity.randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT); - } Actor_SetFocus(&this->actor, 60.0f); Actor_SetScale(&this->actor, 0.01f); SkelAnime_Update(&this->skelAnime); diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h index bf0a3a167..0e3e50c9b 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.h @@ -32,7 +32,10 @@ typedef struct EnDns { /* 0x02BD */ u8 dropCollectible; /* 0x02C0 */ DnsItemEntry* dnsItemEntry; /* 0x02C4 */ f32 yInitPos; - /* */ ScrubIdentity scrubIdentity; + // #region SOH [Randomizer] + /* */ DnsItemEntry sohDnsItemEntry; + /* */ ScrubIdentity sohScrubIdentity; + // #endregion } EnDns; // size = 0x02C8 #endif diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c index eb9942fba..d63cb14c8 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.c @@ -135,29 +135,6 @@ void EnDntDemo_Judge(EnDntDemo* this, PlayState* play) { this->judgeTimer = 0; } } else { - if (IS_RANDO) { - Player* player = GET_PLAYER(play); - switch (Player_GetMask(play)) { - case PLAYER_MASK_SKULL: - if (!Flags_GetTreasure(play, 0x1F) && !Player_InBlockingCsMode(play, player)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_SKULL_MASK, GI_STICK_UPGRADE_30); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0x1F; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - break; - case PLAYER_MASK_TRUTH: - if (!Flags_GetTreasure(play, 0x1E) && !Player_InBlockingCsMode(play, player)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DEKU_THEATER_MASK_OF_TRUTH, GI_NUT_UPGRADE_40); - GiveItemEntryWithoutActor(play, getItemEntry); - player->pendingFlag.flagID = 0x1E; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - break; - } - return; - } - if ((Player_GetMask(play) != 0) && (this->subCamera == SUBCAM_FREE)) { this->subCamera = OnePointCutscene_Init(play, 2220, -99, &this->scrubs[3]->actor, MAIN_CAM); } diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h index 9093d451c..c6b9a7efb 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h +++ b/soh/src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h @@ -64,4 +64,6 @@ typedef enum { /* 5 */ DNT_ACTION_PRIZE } EnDntAction; +void EnDntDemo_Judge(EnDntDemo* enDntDemo, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c index 2864544c5..401ffbef4 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Jiji/z_en_dnt_jiji.c @@ -126,7 +126,7 @@ void EnDntJiji_Wait(EnDntJiji* this, PlayState* play) { !(player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) { OnePointCutscene_Init(play, 2230, -99, &this->actor, MAIN_CAM); this->timer = 0; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnDntJiji_SetupUnburrow; } } @@ -260,9 +260,9 @@ void EnDntJiji_Talk(EnDntJiji* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { func_8005B1A4(GET_ACTIVE_CAM(play)); Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.parent = NULL; - func_8002F434(&this->actor, play, this->getItemId, 400.0f, 200.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 400.0f, 200.0f); this->actionFunc = EnDntJiji_SetupGivePrize; } } @@ -272,7 +272,7 @@ void EnDntJiji_SetupGivePrize(EnDntJiji* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = EnDntJiji_GivePrize; } else { - func_8002F434(&this->actor, play, this->getItemId, 400.0f, 200.0f); + Actor_OfferGetItem(&this->actor, play, this->getItemId, 400.0f, 200.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c index f3dff79fe..102a904cf 100644 --- a/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c +++ b/soh/src/overlays/actors/ovl_En_Dnt_Nomal/z_en_dnt_nomal.c @@ -12,6 +12,7 @@ #include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" #include "objects/object_hintnuts/object_hintnuts.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -252,11 +253,11 @@ void EnDntNomal_TargetWait(EnDntNomal* this, PlayState* play) { if (!LINK_IS_ADULT && !Flags_GetItemGetInf(ITEMGETINF_1D)) { this->hitCounter++; if (this->hitCounter >= 3) { - if(IS_RANDO) { + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { this->actionFunc = EnDntNomal_TargetGivePrize; } else { OnePointCutscene_Init(play, 4140, -99, &this->actor, MAIN_CAM); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->timer4 = 50; this->actionFunc = EnDntNomal_SetupTargetUnburrow; } @@ -346,7 +347,7 @@ void EnDntNomal_TargetTalk(EnDntNomal* this, PlayState* play) { Message_CloseTextbox(play); func_8005B1A4(GET_ACTIVE_CAM(play)); GET_ACTIVE_CAM(play)->csId = 0; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = EnDntNomal_SetupTargetGivePrize; } } @@ -368,7 +369,7 @@ void EnDntNomal_TargetGivePrize(EnDntNomal* this, PlayState* play) { if (Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, itemX, itemY, itemZ, 0, 0, 0, EXITEM_BULLET_BAG) == NULL) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); Actor_Kill(&this->actor); } this->spawnedItem = true; diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index 6da75b1e7..e94ff9039 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -6,7 +6,7 @@ #include "z_en_ds.h" #include "objects/object_ds/object_ds.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -90,19 +90,12 @@ void EnDs_DisplayOddPotionText(EnDs* this, PlayState* play) { } void EnDs_GiveOddPotion(EnDs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { this->actor.parent = NULL; this->actionFunc = EnDs_DisplayOddPotionText; gSaveContext.timer2State = 0; } else { - u32 itemId = GI_ODD_POTION; - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_MUSHROOM); - return; - } - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_ODD_POTION, 10000.0f, 50.0f); } } @@ -111,13 +104,9 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, PlayState* play) { Message_CloseTextbox(play); this->actionFunc = EnDs_GiveOddPotion; u32 itemId = GI_ODD_POTION; - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_MUSHROOM); - return; + if (GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) { + Actor_OfferGetItem(&this->actor, play, itemId, 10000.0f, 50.0f); } - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); } } @@ -138,7 +127,7 @@ void EnDs_BrewOddPotion2(EnDs* this, PlayState* play) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion3; - this->brewTimer = IS_RANDO ? 0 : 60; + this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; Flags_UnsetSwitch(play, 0x3F); } } @@ -148,7 +137,7 @@ void EnDs_BrewOddPotion1(EnDs* this, PlayState* play) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion2; - this->brewTimer = IS_RANDO ? 0 : 20; + this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 20 : 0; } Math_StepToF(&this->unk_1E4, 1.0f, 0.01f); @@ -162,7 +151,7 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: // yes this->actionFunc = EnDs_BrewOddPotion1; - this->brewTimer = IS_RANDO ? 0 : 60; + this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0; Flags_SetSwitch(play, 0x3F); play->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; @@ -174,22 +163,10 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { } } -u8 EnDs_RandoCanGetGrannyItem() { - return IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && - // Traded odd mushroom when adult trade is on - ((Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && Flags_GetItemGetInf(ITEMGETINF_30)) || - // Found claim check when adult trade is off - (!Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && - INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)); -} - s32 EnDs_CheckRupeesAndBottle() { if (gSaveContext.rupees < 100) { return 0; - } else if (EnDs_RandoCanGetGrannyItem()) { // Allow buying the rando item regardless of having a bottle - return 2; - } else if (Inventory_HasEmptyBottle() == 0) { + } else if (GameInteractor_Should(GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, Inventory_HasEmptyBottle() == 0, NULL)) { return 1; } else { return 2; @@ -197,20 +174,11 @@ s32 EnDs_CheckRupeesAndBottle() { } void EnDs_GiveBluePotion(EnDs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { - if (EnDs_RandoCanGetGrannyItem()) { - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP); - } - + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { this->actor.parent = NULL; this->actionFunc = EnDs_Talk; } else { - if (EnDs_RandoCanGetGrannyItem()) { - GetItemEntry entry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE); - GiveItemEntryFromActor(&this->actor, play, entry, 10000.0f, 50.0f); - } else { - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); } } @@ -229,18 +197,14 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { case 2: // have 100 rupees and empty bottle Rupees_ChangeBy(-100); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - GetItemEntry itemEntry; - if (EnDs_RandoCanGetGrannyItem()) { - itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - } else { - itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) { + GetItemEntry itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); + Actor_OfferGetItem(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; } - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; this->actionFunc = EnDs_GiveBluePotion; return; } @@ -261,10 +225,7 @@ void EnDs_Wait(EnDs* this, PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); player->actor.textId = 0x504A; this->actionFunc = EnDs_OfferOddPotion; - } else if ( - // Always offer blue potion when adult trade is off - (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF) || - Flags_GetItemGetInf(ITEMGETINF_30)) { // Traded odd mushroom + } else if (GameInteractor_Should(GI_VB_OFFER_BLUE_POTION, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // Traded odd mushroom player->actor.textId = 0x500C; this->actionFunc = EnDs_OfferBluePotion; } else { diff --git a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c index 19af8a4c5..781c09f79 100644 --- a/soh/src/overlays/actors/ovl_En_Du/z_en_du.c +++ b/soh/src/overlays/actors/ovl_En_Du/z_en_du.c @@ -1,6 +1,7 @@ #include "z_en_du.h" #include "objects/object_du/object_du.h" #include "scenes/overworld/spot18/spot18_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -361,7 +362,7 @@ void func_809FE3C0(EnDu* this, PlayState* play) { return; } if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->interactInfo.talkState = NPC_TALK_STATE_IDLE; } if (this->actor.xzDistToPlayer < 116.0f + this->collider.dim.radius) { @@ -376,7 +377,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_00; EnDu_SetupAction(this, func_809FE3C0); } else if (play->msgCtx.ocarinaMode >= OCARINA_MODE_06) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaWrongCs); gSaveContext.cutsceneTrigger = 1; } @@ -385,7 +386,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaCorrectCs); gSaveContext.cutsceneTrigger = 1; } @@ -474,11 +475,8 @@ void func_809FE890(EnDu* this, PlayState* play) { Vec3f velocity = { 0.0f, 0.0f, 0.0f }; CsCmdActorAction* csAction; - if (play->csCtx.state == CS_STATE_IDLE || IS_RANDO) { - if (IS_RANDO) { - play->csCtx.state = CS_STATE_IDLE; - } - func_8002DF54(play, &this->actor, 1); + if (play->csCtx.state == CS_STATE_IDLE) { + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); EnDu_SetupAction(this, func_809FEB08); return; } @@ -551,16 +549,13 @@ void func_809FEB08(EnDu* this, PlayState* play) { this->unk_1EE = 0; if (this->unk_1E8 == 1) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENDU_ANIM_1); EnDu_SetupAction(this, func_809FE3C0); return; } - if ((!IS_RANDO && CUR_UPG_VALUE(UPG_STRENGTH) <= 0) || - (IS_RANDO && !Flags_GetTreasure(play, 0x1E))) { - if (IS_RANDO) { - Flags_SetTreasure(play, 0x1E); - } + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, CUR_UPG_VALUE(UPG_STRENGTH) <= 0, NULL)) { + Flags_SetRandomizerInf(RAND_INF_DARUNIAS_JOY); this->actor.textId = 0x301C; EnDu_SetupAction(this, func_809FEC14); } else { @@ -574,24 +569,20 @@ void func_809FEB08(EnDu* this, PlayState* play) { void func_809FEC14(EnDu* this, PlayState* play) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); EnDu_SetupAction(this, func_809FEC70); func_809FEC70(this, play); } } void func_809FEC70(EnDu* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_STRENGTH_1, true, NULL)) { this->actor.parent = NULL; EnDu_SetupAction(this, func_809FECE4); } else { f32 xzRange = this->actor.xzDistToPlayer + 1.0f; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_DARUNIAS_JOY, GI_BRACELET); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + + Actor_OfferGetItem(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index f996fe6c1..e08e794a3 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -677,7 +677,7 @@ void func_80A0329C(EnElf* this, PlayState* play) { if (!(this->fairyFlags & FAIRY_FLAG_BIG)) { // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 80.0f, 60.0f); + Actor_OfferGetItem(&this->actor, play, GI_MAX, 80.0f, 60.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index a3a196e31..28e89036d 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -8,6 +8,7 @@ #include "overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -137,12 +138,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { onCounter = true; case EXITEM_BOMB_BAG_BOWLING: this->unk_17C = func_8002EBCC; - if (IS_RANDO) { - this->giDrawId = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20).gid; - } else { - this->giDrawId = GID_BOMB_BAG_30; - } + this->giDrawId = GID_BOMB_BAG_30; this->timer = 65; this->prizeRotateTimer = 35; this->scale = 0.5f; @@ -150,7 +146,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { this->actionFunc = EnExItem_BowlPrize; } else { this->actionFunc = EnExItem_SetupBowlCounter; - this->actor.shape.yOffset = IS_RANDO ? -10.0f : -18.0f; + this->actor.shape.yOffset = -18.0f; } break; case EXITEM_HEART_PIECE_COUNTER: @@ -172,11 +168,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { onCounter = true; case EXITEM_BOMBCHUS_BOWLING: this->unk_17C = func_8002EBCC; - if (IS_RANDO) { - this->giDrawId = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10).gid; - } else { - this->giDrawId = GID_BOMBCHU; - } + this->giDrawId = GID_BOMBCHU; this->timer = 65; this->prizeRotateTimer = 35; this->scale = 0.5f; @@ -228,25 +220,19 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { this->scale = 0.5f; this->unkFloat = 0.5f; this->actor.velocity.y = 10.0f; - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) { - switch (this->type) { - case EXITEM_GREEN_RUPEE_CHEST: - this->giDrawId = GID_RUPEE_GREEN; - break; - case EXITEM_BLUE_RUPEE_CHEST: - this->giDrawId = GID_RUPEE_BLUE; - break; - case EXITEM_RED_RUPEE_CHEST: - this->giDrawId = GID_RUPEE_RED; - break; - case EXITEM_14: - this->giDrawId = GID_RUPEE_PURPLE; - break; - } - } else { - if (play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - this->giDrawId = GetChestGameRandoGiDrawId(play->roomCtx.curRoom.num, GID_RUPEE_GREEN, play); - } + switch (this->type) { + case EXITEM_GREEN_RUPEE_CHEST: + this->giDrawId = GID_RUPEE_GREEN; + break; + case EXITEM_BLUE_RUPEE_CHEST: + this->giDrawId = GID_RUPEE_BLUE; + break; + case EXITEM_RED_RUPEE_CHEST: + this->giDrawId = GID_RUPEE_RED; + break; + case EXITEM_14: + this->giDrawId = GID_RUPEE_PURPLE; + break; } this->actionFunc = EnExItem_ExitChest; break; @@ -376,7 +362,7 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { Math_SmoothStepToS(&this->actor.shape.rot.y, -0x4000, 5, 0x1000, 0); } - if (!IS_RANDO && this->timer != 0) { + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor) && this->timer != 0) { if (this->prizeRotateTimer != 0) { tmpf1 = play->view.lookAt.x - play->view.eye.x; tmpf2 = play->view.lookAt.y - 10.0f - play->view.eye.y; @@ -396,50 +382,41 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { this->actor.world.pos.z += (tmpf3 / tmpf4) * 5.0f; } } else { - GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; s32 getItemId; this->actor.draw = NULL; - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actor.parent = NULL; - if (IS_RANDO) { + + if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, &this->actor)) { GET_PLAYER(play)->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD); - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - getItemId = getItemEntry.getItemId; - } else { - if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { - getItemId = GI_BULLET_BAG_40; - } else { - getItemId = GI_BULLET_BAG_50; - } } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 2000.0f, 1000.0f); + if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { + getItemId = GI_BULLET_BAG_40; } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); + getItemId = GI_BULLET_BAG_50; } + + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); + } + this->actionFunc = EnExItem_TargetPrizeGive; } } void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor)) { this->actionFunc = EnExItem_TargetPrizeFinish; } else { - if (!IS_RANDO) { - s32 getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; - func_8002F434(&this->actor, play, getItemId, 2000.0f, 1000.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); - } - + s32 getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } } void EnExItem_TargetPrizeFinish(EnExItem* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TARGET_IN_WOODS, true, &this->actor) || (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); Flags_SetItemGetInf(ITEMGETINF_1D); @@ -510,43 +487,12 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { } if (this) {} func_8002ED80(&this->actor, play, 0); - if (IS_RANDO) { - GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; - switch (this->type) { - case EXITEM_BOMB_BAG_BOWLING: - case EXITEM_BOMB_BAG_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); - break; - case EXITEM_BOMBCHUS_BOWLING: - case EXITEM_BOMBCHUS_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); - break; - case EXITEM_BULLET_BAG: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); - break; - } - - if (randoGetItem.getItemId != GI_NONE) { - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - GetItemEntry_Draw(play, randoGetItem); - return; - } - } - GetItem_Draw(play, this->giDrawId); } void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); - - if (IS_RANDO) { - GetItemEntry randoGetItem = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - GetItemEntry_Draw(play, randoGetItem); - } else { - GetItem_Draw(play, GID_HEART_PIECE); - } + GetItem_Draw(play, GID_HEART_PIECE); } void EnExItem_DrawMagic(EnExItem* this, PlayState* play, s16 magicIndex) { diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h index 34a880c22..090d7028c 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h @@ -6,7 +6,7 @@ struct EnExItem; -typedef void (*EnExItemActionFunc)(struct EnExItem* this, PlayState* play); +typedef void (*EnExItemActionFunc)(struct EnExItem* enExItem, PlayState* play); typedef void (*EnExItemLightFunc)(Actor*, PlayState*, s32); typedef struct EnExItem { @@ -27,6 +27,9 @@ typedef struct EnExItem { /* 0x0170 */ Vec3f initPos; // unused /* 0x017C */ EnExItemLightFunc unk_17C; /* 0x0180 */ EnExItemLightFunc unk_180; + // #region SOH [Randomizer] Caching the get item entry for the draw function for performance + /* */ GetItemEntry sohItemEntry; + // #endregion } EnExItem; // size = 0x0184 typedef enum { @@ -52,6 +55,8 @@ typedef enum { /* 19 */ EXITEM_BULLET_BAG } EnExItemType; +void EnExItem_WaitForObject(EnExItem* enExItem, PlayState* play); + #define EXITEM_COUNTER 5 #define EXITEM_CHEST 10 #define EXITEM_MAGIC 16 diff --git a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c index e777d993f..1bd8e3202 100644 --- a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c +++ b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c @@ -716,7 +716,7 @@ void EnFish_OrdinaryUpdate(EnFish* this, PlayState* play) { EnFish_BeginRespawn(this); } else if (EnFish_InBottleRange(this, play)) { // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 80.0f, 20.0f); + Actor_OfferGetItem(&this->actor, play, GI_MAX, 80.0f, 20.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 36c9c2818..646fc5668 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -45,7 +45,6 @@ void EnFr_OcarinaMistake(EnFr* this, PlayState* play); void EnFr_SetupReward(EnFr* this, PlayState* play, u8 unkCondition); void EnFr_PrintTextBox(EnFr* this, PlayState* play); void EnFr_TalkBeforeReward(EnFr* this, PlayState* play); -RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex); void EnFr_SetReward(EnFr* this, PlayState* play); // Deactivate @@ -618,7 +617,6 @@ void EnFr_Idle(EnFr* this, PlayState* play) { player->actor.world.pos.z = this->actor.world.pos.z; // z = -1220.0f player->yaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y; this->reward = GI_NONE; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = EnFr_Activate; } else if (EnFr_IsAboveAndWithin30DistXZ(player, this)) { player->unk_6A8 = &this->actor; @@ -854,7 +852,6 @@ s32 EnFr_IsFrogSongComplete(EnFr* this, PlayState* play) { void EnFr_OcarinaMistake(EnFr* this, PlayState* play) { Message_CloseTextbox(play); this->reward = GI_NONE; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; func_80078884(NA_SE_SY_OCARINA_ERROR); Audio_OcaSetInstrument(0); sEnFrPointers.flags = 12; @@ -939,23 +936,6 @@ void EnFr_TalkBeforeReward(EnFr* this, PlayState* play) { } } -RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) { - switch (songIndex) { - case FROG_ZL: - return RC_ZR_FROGS_ZELDAS_LULLABY; - case FROG_EPONA: - return RC_ZR_FROGS_EPONAS_SONG; - case FROG_SARIA: - return RC_ZR_FROGS_SARIAS_SONG; - case FROG_SUNS: - return RC_ZR_FROGS_SUNS_SONG; - case FROG_SOT: - return RC_ZR_FROGS_SONG_OF_TIME; - default: - return RC_UNKNOWN_CHECK; - } -} - void EnFr_SetReward(EnFr* this, PlayState* play) { u16 songIndex; @@ -963,16 +943,12 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { songIndex = this->songIndex; this->actionFunc = EnFr_Deactivate; this->reward = GI_NONE; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_RUPEE_PURPLE; - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(EnFr_RandomizerCheckFromSongIndex(songIndex), GI_RUPEE_PURPLE); - this->reward = this->getItemEntry.getItemId; } } else { this->reward = GI_RUPEE_BLUE; @@ -981,11 +957,8 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_HEART_PIECE; - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_FROGS_IN_THE_RAIN, GI_HEART_PIECE); - this->reward = this->getItemEntry.getItemId; } } else { this->reward = GI_RUPEE_BLUE; @@ -994,11 +967,8 @@ void EnFr_SetReward(EnFr* this, PlayState* play) { if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->reward = GI_HEART_PIECE; - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_FROGS_OCARINA_GAME, GI_HEART_PIECE); - this->reward = this->getItemEntry.getItemId; } } else { this->reward = GI_RUPEE_PURPLE; @@ -1049,29 +1019,23 @@ void EnFr_Deactivate(EnFr* this, PlayState* play) { this->actionFunc = EnFr_Idle; } else { this->actionFunc = EnFr_GiveReward; - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 30.0f, 100.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { + Actor_OfferGetItem(&this->actor, play, this->reward, 30.0f, 100.0f); } } } void EnFr_GiveReward(EnFr* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) { this->actor.parent = NULL; this->actionFunc = EnFr_SetIdle; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 30.0f, 100.0f); - } + Actor_OfferGetItem(&this->actor, play, this->reward, 30.0f, 100.0f); } } void EnFr_SetIdle(EnFr* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || (IS_RANDO && this->reward == RG_ICE_TRAP)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { this->actionFunc = EnFr_Idle; } } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h index 19d612fdd..17b8b162e 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.h @@ -73,7 +73,6 @@ typedef struct EnFr { /* 0x03AA */ s16 xyAngleButterfly; // Butterfly Travels along random angles in the x-y plane /* 0x03AC */ Vec3f posButterfly; // Position/Coordinates of the Butterfly /* 0x03B8 */ Vec3f posButterflyLight; // Used in Lights_PointNoGlowSetInfo() - /* */ GetItemEntry getItemEntry; } EnFr; // size = 0x03C4 typedef struct { @@ -81,4 +80,7 @@ typedef struct { EnFr* frogs[5]; } EnFrPointers; +void EnFr_Idle(EnFr* enFr, PlayState* play); +void EnFr_GiveReward(EnFr* enFr, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c index 67ad97c96..98b8a4dda 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -161,20 +161,12 @@ void GivePlayerRandoRewardSongOfStorms(EnFu* windmillGuy, PlayState* play, Rando } } -void func_WaitForSongGive(EnFu* this, PlayState* play) { - GivePlayerRandoRewardSongOfStorms(this, play, RC_SONG_FROM_WINDMILL); -} - void func_80A1DB60(EnFu* this, PlayState* play) { if (play->csCtx.state == CS_STATE_IDLE) { this->actionFunc = EnFu_WaitAdult; Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS); play->msgCtx.ocarinaMode = OCARINA_MODE_04; } - - if (IS_RANDO) { - this->actionFunc = func_WaitForSongGive; - } } void func_80A1DBA0(EnFu* this, PlayState* play) { @@ -186,10 +178,6 @@ void func_80A1DBA0(EnFu* this, PlayState* play) { void func_80A1DBD4(EnFu* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (IS_RANDO && (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING)) { - play->msgCtx.ocarinaMode = OCARINA_MODE_03; - } - if (play->msgCtx.ocarinaMode >= OCARINA_MODE_04) { this->actionFunc = EnFu_WaitAdult; play->msgCtx.ocarinaMode = OCARINA_MODE_04; @@ -199,12 +187,6 @@ void func_80A1DBD4(EnFu* this, PlayState* play) { this->actionFunc = func_80A1DB60; this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - if (!IS_RANDO) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gSongOfStormsCs); - gSaveContext.cutsceneTrigger = 1; - Item_Give(play, ITEM_SONG_STORMS); - } - play->msgCtx.ocarinaMode = OCARINA_MODE_00; Flags_SetEventChkInf(EVENTCHKINF_PLAYED_SONG_OF_STORMS_IN_WINDMILL); } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_02) { @@ -249,7 +231,7 @@ void EnFu_WaitAdult(EnFu* this, PlayState* play) { } else if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { this->actor.textId = 0x5035; Message_StartTextbox(play, this->actor.textId, NULL); - this->actionFunc = IS_RANDO ? func_80A1DBD4 : EnFu_TeachSong; + this->actionFunc = EnFu_TeachSong; this->behaviorFlags |= FU_WAIT; } else if (Actor_ProcessTalkRequest(&this->actor, play)) { this->actionFunc = func_80A1DBA0; diff --git a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h index 7fddd6543..fd371000d 100644 --- a/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h +++ b/soh/src/overlays/actors/ovl_En_Fu/z_en_fu.h @@ -41,4 +41,7 @@ typedef struct EnFu { /* 0x02AC */ EnFuActionFunc actionFunc; } EnFu; // size = 0x02B0 +void EnFu_TeachSong(EnFu* enFu, PlayState* play); +void EnFu_WaitAdult(EnFu* enFu, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c index 53c149026..fb37cf0af 100644 --- a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c +++ b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c @@ -360,7 +360,7 @@ void func_80A2FA50(EnGb* this, PlayState* play) { void func_80A2FB40(EnGb* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) { if (!IS_RANDO) { - func_8002F434(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); + Actor_OfferGetItem(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE); GiveItemEntryFromActor(&this->dyna.actor, play, getItemEntry, 100.0f, 10.0f); @@ -375,7 +375,7 @@ void func_80A2FBB0(EnGb* this, PlayState* play) { this->actionFunc = func_80A2FC0C; } else { if (!IS_RANDO) { - func_8002F434(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); + Actor_OfferGetItem(&this->dyna.actor, play, GI_BOTTLE, 100.0f, 10.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_10_BIG_POES, GI_BOTTLE); GiveItemEntryFromActor(&this->dyna.actor, play, getItemEntry, 100.0f, 10.0f); diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 92a768205..2086e528f 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -8,6 +8,7 @@ #include "vt.h" #include "objects/object_ge1/object_ge1.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -133,7 +134,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_GATE_OPERATOR: this->hairstyle = GE1_HAIR_STRAIGHT; - if (EnGe1_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_CheckGate_GateOp; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -143,7 +144,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_NORMAL: this->hairstyle = GE1_HAIR_STRAIGHT; - if (EnGe1_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_SetNormalText; } else { this->actionFunc = EnGe1_WatchForAndSensePlayer; @@ -173,7 +174,7 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { if (gSaveContext.eventInf[0] & 0x100) { this->actionFunc = EnGe1_TalkAfterGame_Archery; - } else if (EnGe1_CheckCarpentersFreed()) { + } else if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { this->actionFunc = EnGe1_Wait_Archery; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; @@ -183,13 +184,8 @@ void EnGe1_Init(Actor* thisx, PlayState* play) { case GE1_TYPE_TRAINING_GROUNDS_GUARD: this->hairstyle = GE1_HAIR_STRAIGHT; - if (EnGe1_CheckCarpentersFreed()) { - // If the gtg gate is permanently open, don't let the gaurd charge to open it again - if (IS_RANDO && gSaveContext.sceneFlags[93].swch & 0x00000004) { - this->actionFunc = EnGe1_SetNormalText; - } else { - this->actionFunc = EnGe1_CheckForCard_GTGGuard; - } + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe1_CheckCarpentersFreed(), NULL)) { + this->actionFunc = EnGe1_CheckForCard_GTGGuard; } else { this->actionFunc = EnGe1_WatchForPlayerFrontOnly; } @@ -235,14 +231,6 @@ void EnGe1_SetAnimationIdle(EnGe1* this) { } s32 EnGe1_CheckCarpentersFreed(void) { - if (IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_GERUDO_CARD)) { - return 1; - } else { - return 0; - } - } - u16 carpenterFlags = gSaveContext.eventChkInf[9]; if (!((carpenterFlags & 1) && (carpenterFlags & 2) && (carpenterFlags & 4) && (carpenterFlags & 8))) { return 0; @@ -281,7 +269,7 @@ void EnGe1_KickPlayer(EnGe1* this, PlayState* play) { void EnGe1_SpotPlayer(EnGe1* this, PlayState* play) { this->cutsceneTimer = 30; this->actionFunc = EnGe1_KickPlayer; - func_8002DF54(play, &this->actor, 0x5F); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x5F); func_80078884(NA_SE_SY_FOUND); Message_StartTextbox(play, 0x6000, &this->actor); } @@ -531,16 +519,8 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; s32 getItemId; - if (Actor_HasParent(&this->actor, play)) { - if (IS_RANDO && gSaveContext.minigameScore >= 1500 && !Flags_GetInfTable(INFTABLE_190)) { - Flags_SetItemGetInf(ITEMGETINF_0F); - Flags_SetInfTable(INFTABLE_190); - this->stateFlags |= GE1_STATE_GIVE_QUIVER; - this->actor.parent = NULL; - return; - } else { - this->actionFunc = EnGe1_SetupWait_Archery; - } + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + this->actionFunc = EnGe1_SetupWait_Archery; if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { Flags_SetItemGetInf(ITEMGETINF_0F); @@ -549,33 +529,21 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { } } else { if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { - if (!IS_RANDO) { - switch (CUR_UPG_VALUE(UPG_QUIVER)) { - //! @bug Asschest. See next function for details - case 1: - getItemId = GI_QUIVER_40; - break; - case 2: - getItemId = GI_QUIVER_50; - break; - } - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1500_POINTS, CUR_UPG_VALUE(UPG_QUIVER) == 1 ? GI_QUIVER_40 : GI_QUIVER_50); - getItemId = getItemEntry.getItemId; + switch (CUR_UPG_VALUE(UPG_QUIVER)) { + //! @bug Asschest. See next function for details + case 1: + getItemId = GI_QUIVER_40; + break; + case 2: + getItemId = GI_QUIVER_50; + break; } } else { - if (!IS_RANDO) { - getItemId = GI_HEART_PIECE; - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); - getItemId = getItemEntry.getItemId; - } + getItemId = GI_HEART_PIECE; } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 10000.0f, 50.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } } } @@ -590,33 +558,21 @@ void EnGe1_BeginGiveItem_Archery(EnGe1* this, PlayState* play) { } if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { - if (!IS_RANDO) { - switch (CUR_UPG_VALUE(UPG_QUIVER)) { - //! @bug Asschest. See next function for details - case 1: - getItemId = GI_QUIVER_40; - break; - case 2: - getItemId = GI_QUIVER_50; - break; - } - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1500_POINTS, CUR_UPG_VALUE(UPG_QUIVER) == 1 ? GI_QUIVER_40 : GI_QUIVER_50); - getItemId = getItemEntry.getItemId; + switch (CUR_UPG_VALUE(UPG_QUIVER)) { + //! @bug Asschest. See next function for details + case 1: + getItemId = GI_QUIVER_40; + break; + case 2: + getItemId = GI_QUIVER_50; + break; } } else { - if (!IS_RANDO) { - getItemId = GI_HEART_PIECE; - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_HBA_1000_POINTS, GI_HEART_PIECE); - getItemId = getItemEntry.getItemId; - } + getItemId = GI_HEART_PIECE; } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 10000.0f, 50.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, true, this)) { + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } } @@ -662,7 +618,7 @@ void EnGe1_BeginGame_Archery(EnGe1* this, PlayState* play) { Flags_SetEventChkInf(EVENTCHKINF_PLAYED_HORSEBACK_ARCHERY); if (!(player->stateFlags1 & PLAYER_STATE1_ON_HORSE)) { - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } else { horse = Actor_FindNearby(play, &player->actor, ACTOR_EN_HORSE, ACTORCAT_BG, 1200.0f); player->actor.freezeTimer = 1200; diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h index 1851fdbce..afb57fb41 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h @@ -57,4 +57,6 @@ typedef struct EnGe1 { /* 0x02B8 */ EnGe1AnimFunc animFunc; } EnGe1; // size = 0x02BC +void EnGe1_SetNormalText(EnGe1* enGe1, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c index 01e0e0176..0b5b9c09e 100644 --- a/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c +++ b/soh/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c @@ -8,6 +8,7 @@ #include "vt.h" #include "objects/object_gla/object_gla.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -139,14 +140,14 @@ void EnGe2_Init(Actor* thisx, PlayState* play) { switch (this->actor.params & 0xFF) { case GE2_TYPE_PATROLLING: EnGe2_ChangeAction(this, GE2_ACTION_WALK); - if (EnGe2_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } break; case GE2_TYPE_STATIONARY: EnGe2_ChangeAction(this, GE2_ACTION_STAND); - if (EnGe2_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } @@ -227,14 +228,6 @@ s32 Ge2_DetectPlayerInUpdate(PlayState* play, EnGe2* this, Vec3f* pos, s16 yRot, } s32 EnGe2_CheckCarpentersFreed(void) { - if (IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_GERUDO_CARD)) { - return 1; - } else { - return 0; - } - } - if (CHECK_FLAG_ALL(gSaveContext.eventChkInf[EVENTCHKINF_CARPENTERS_FREE_INDEX] & (EVENTCHKINF_CARPENTERS_FREE_MASK_ALL | 0xF0), EVENTCHKINF_CARPENTERS_FREE_MASK_ALL)) { @@ -467,16 +460,11 @@ void EnGe2_WaitLookAtPlayer(EnGe2* this, PlayState* play) { } void EnGe2_WaitTillCardGiven(EnGe2* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGe2_SetActionAfterTalk; } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -485,11 +473,8 @@ void EnGe2_GiveCard(EnGe2* this, PlayState* play) { Message_CloseTextbox(play); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe2_WaitTillCardGiven; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } } @@ -510,7 +495,7 @@ void EnGe2_SetupCapturePlayer(EnGe2* this, PlayState* play) { this->stateFlags |= GE2_STATE_CAPTURING; this->actor.speedXZ = 0.0f; EnGe2_ChangeAction(this, GE2_ACTION_CAPTURETURN); - func_8002DF54(play, &this->actor, 95); + Player_SetCsActionWithHaltedActors(play, &this->actor, 95); func_80078884(NA_SE_SY_FOUND); Message_StartTextbox(play, 0x6000, &this->actor); } @@ -620,7 +605,7 @@ void EnGe2_Update(Actor* thisx, PlayState* play) { } EnGe2_MoveAndBlink(this, play); - if (EnGe2_CheckCarpentersFreed() && !(this->stateFlags & GE2_STATE_KO)) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL) && !(this->stateFlags & GE2_STATE_KO)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; } @@ -645,7 +630,7 @@ void EnGe2_UpdateStunned(Actor* thisx, PlayState* play2) { } CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); - if (EnGe2_CheckCarpentersFreed()) { + if (GameInteractor_Should(GI_VB_GERUDOS_BE_FRIENDLY, EnGe2_CheckCarpentersFreed(), NULL)) { this->actor.update = EnGe2_UpdateFriendly; this->actor.targetMode = 6; this->actor.colorFilterTimer = 0; diff --git a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c index 90d2981f0..1265ba51e 100644 --- a/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c +++ b/soh/src/overlays/actors/ovl_En_Ge3/z_en_ge3.c @@ -6,6 +6,7 @@ #include "z_en_ge3.h" #include "objects/object_geldb/object_geldb.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -140,16 +141,11 @@ void EnGe3_WaitLookAtPlayer(EnGe3* this, PlayState* play) { } void EnGe3_WaitTillCardGiven(EnGe3* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGe3_Wait; } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } @@ -158,11 +154,8 @@ void EnGe3_GiveCard(EnGe3* this, PlayState* play) { Message_CloseTextbox(play); this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; this->actionFunc = EnGe3_WaitTillCardGiven; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GF_GERUDO_MEMBERSHIP_CARD, GI_GERUDO_CARD); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_GERUDO_MEMBERSHIP_CARD, true, NULL)) { + Actor_OfferGetItem(&this->actor, play, GI_GERUDO_CARD, 10000.0f, 50.0f); } } } @@ -172,7 +165,7 @@ void EnGe3_ForceTalk(EnGe3* this, PlayState* play) { this->actionFunc = EnGe3_GiveCard; } else { if (!(this->unk_30C & 4)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->unk_30C |= 4; } this->actor.textId = 0x6004; diff --git a/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c b/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c index 4ed0e52ee..293f19669 100644 --- a/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c +++ b/soh/src/overlays/actors/ovl_En_GeldB/z_en_geldb.c @@ -918,7 +918,7 @@ void EnGeldB_SpinAttack(EnGeldB* this, PlayState* play) { if (&player->actor == this->swordCollider.base.at) { func_8002F71C(play, &this->actor, 6.0f, this->actor.yawTowardsPlayer, 6.0f); this->spinAttackState = 2; - func_8002DF54(play, &this->actor, 0x18); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x18); Message_StartTextbox(play, 0x6003, &this->actor); this->timer = 30; this->actor.speedXZ = 0.0f; diff --git a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c index 4986f24f6..7174a63f1 100644 --- a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -8,6 +8,7 @@ #include "objects/object_oF1d_map/object_oF1d_map.h" #include "objects/object_gm/object_gm.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -96,10 +97,9 @@ void EnGm_Destroy(Actor* thisx, PlayState* play) { s32 func_80A3D7C8(void) { if (LINK_AGE_IN_YEARS == YEARS_CHILD) { return 0; - } else if ((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF) && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - return 1; - } else if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON)) { // Don't have giant's knife + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, ( + !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) // Don't have giant's knife + ), NULL)) { return 1; } else if (CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE)) { // Have broken giant's knife return 2; @@ -215,11 +215,6 @@ void func_80A3DC44(EnGm* this, PlayState* play) { return; case 1: Flags_SetInfTable(INFTABLE_B1); - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - //Resets "Talked to Medigoron" flag in infTable to restore initial conversation state - Flags_UnsetInfTable(INFTABLE_B1); - } case 2: this->actionFunc = EnGm_ProcessChoiceIndex; default: @@ -254,20 +249,10 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { Message_ContinueTextbox(play, 0xC8); this->actionFunc = func_80A3DD7C; } else { - GetItemEntry itemEntry; - - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); - Flags_SetInfTable(INFTABLE_B1); - } else { - itemEntry = ItemTable_Retrieve(GI_SWORD_KNIFE); - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; this->actionFunc = func_80A3DF00; } break; @@ -280,24 +265,12 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { } void func_80A3DF00(EnGm* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); - } - + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) { + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); this->actor.parent = NULL; this->actionFunc = func_80A3DF60; } else { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); - Flags_SetInfTable(INFTABLE_B1); - } - else { - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 3094f2171..20d1c5326 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -3,7 +3,6 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -31,9 +30,11 @@ void func_80A40C78(EnGo* this, PlayState* play); void EnGo_Eyedrops(EnGo* this, PlayState* play); void func_80A40DCC(EnGo* this, PlayState* play); -void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep); -void EnGo_UpdateDust(EnGo* this); -void EnGo_DrawDust(EnGo* this, PlayState* play); + +void EnGo_SpawnEffectDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, + f32 scaleStep); +void EnGo_UpdateEffects(EnGo* this); +void EnGo_DrawEffects(EnGo* this, PlayState* play); const ActorInit En_Go_InitVars = { ACTOR_EN_GO, @@ -95,10 +96,10 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { switch (thisx->params & 0xF0) { case 0x90: - if (!IS_RANDO && gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { - if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (Environment_GetBgsDayCount() >= 3) { return 0x305E; } else { return 0x305D; @@ -113,8 +114,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { return 0x3053; } case 0x00: - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) { + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { if (Flags_GetInfTable(INFTABLE_10F)) { return 0x3042; } else { @@ -199,7 +199,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) { } s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { - s16 unkState = NPC_TALK_STATE_TALKING; + s16 talkState = NPC_TALK_STATE_TALKING; f32 xzRange; f32 yRange = fabsf(thisx->yDistToPlayer) + 1.0f; @@ -210,51 +210,51 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { switch (thisx->textId) { case 0x3008: Flags_SetInfTable(INFTABLE_E0); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x300B: Flags_SetInfTable(INFTABLE_EB); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3014: Flags_SetInfTable(INFTABLE_F0); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3016: Flags_SetInfTable(INFTABLE_F4); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3018: Flags_SetInfTable(INFTABLE_F8); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3036: - func_8002F434(thisx, play, GI_TUNIC_GORON, xzRange, yRange); + Actor_OfferGetItem(thisx, play, GI_TUNIC_GORON, xzRange, yRange); Flags_SetInfTable(INFTABLE_10D); // EnGo exclusive flag - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; case 0x3037: Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3041: Flags_SetInfTable(INFTABLE_10F); - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; case 0x3059: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; case 0x3052: case 0x3054: case 0x3055: case 0x305A: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; case 0x305E: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; default: - unkState = NPC_TALK_STATE_IDLE; + talkState = NPC_TALK_STATE_IDLE; break; } break; @@ -272,7 +272,7 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { thisx->textId = 0x300D; } Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; break; case 0x3034: if (play->msgCtx.choiceIndex == 0) { @@ -287,16 +287,16 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { thisx->textId = 0x3033; } Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; break; case 0x3054: case 0x3055: if (play->msgCtx.choiceIndex == 0) { - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; } else { thisx->textId = 0x3056; Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; } Flags_SetInfTable(INFTABLE_B4); break; @@ -312,17 +312,17 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { case 0x3033: thisx->textId = 0x3034; Message_ContinueTextbox(play, thisx->textId); - unkState = NPC_TALK_STATE_TALKING; + talkState = NPC_TALK_STATE_TALKING; break; default: - unkState = NPC_TALK_STATE_ACTION; + talkState = NPC_TALK_STATE_ACTION; break; } } break; case TEXT_STATE_DONE: if (Message_ShouldAdvance(play)) { - unkState = NPC_TALK_STATE_ITEM_GIVEN; + talkState = NPC_TALK_STATE_ITEM_GIVEN; } break; case TEXT_STATE_NONE: @@ -332,21 +332,21 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) { case TEXT_STATE_9: break; } - return unkState; + return talkState; } -s32 func_80A3ED24(PlayState* play, EnGo* this, NpcInteractInfo* interactInfo, f32 arg3, NpcGetTextIdFunc getTextId, +s32 EnGo_UpdateTalking(PlayState* play, Actor* thisx, s16* talkState, f32 interactRange, NpcGetTextIdFunc getTextId, NpcUpdateTalkStateFunc updateTalkState) { - if (interactInfo->talkState != NPC_TALK_STATE_IDLE) { - interactInfo->talkState = updateTalkState(play, &this->actor); + if (*talkState != NPC_TALK_STATE_IDLE) { + *talkState = updateTalkState(play, thisx); return false; - } else if (Actor_ProcessTalkRequest(&this->actor, play)) { - interactInfo->talkState = NPC_TALK_STATE_TALKING; + } else if (Actor_ProcessTalkRequest(thisx, play)) { + *talkState = NPC_TALK_STATE_TALKING; return true; - } else if (!func_8002F2CC(&this->actor, play, arg3)) { + } else if (!func_8002F2CC(thisx, play, interactRange)) { return false; } else { - this->actor.textId = getTextId(play, &this->actor); + thisx->textId = getTextId(play, thisx); return false; } } @@ -379,7 +379,7 @@ s32 EnGo_IsActorSpawned(EnGo* this, PlayState* play) { } } -f32 EnGo_GetGoronSize(EnGo* this) { +f32 EnGo_GetPlayerTrackingYOffset(EnGo* this) { switch (this->actor.params & 0xF0) { case 0x00: return 10.0f; @@ -398,16 +398,16 @@ f32 EnGo_GetGoronSize(EnGo* this) { void func_80A3F060(EnGo* this, PlayState* play) { Player* player = GET_PLAYER(play); - s16 npcTrackingMode; + s16 trackingMode; if (this->actionFunc != EnGo_BiggoronActionFunc && this->actionFunc != EnGo_FireGenericActionFunc && this->actionFunc != func_80A40B1C) { - npcTrackingMode = NPC_TRACKING_NONE; + trackingMode = NPC_TRACKING_NONE; } this->interactInfo.trackPos = player->actor.world.pos; - this->interactInfo.yOffset = EnGo_GetGoronSize(this); - Npc_TrackPoint(&this->actor, &this->interactInfo, 4, npcTrackingMode); + this->interactInfo.yOffset = EnGo_GetPlayerTrackingYOffset(this); + Npc_TrackPoint(&this->actor, &this->interactInfo, 4, trackingMode); } void func_80A3F0E4(EnGo* this) { @@ -421,23 +421,23 @@ void func_80A3F0E4(EnGo* this) { } s32 EnGo_IsCameraModified(EnGo* this, PlayState* play) { - f32 xyzDist; + f32 xyzDistSq; s16 yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; - Camera* camera = play->cameraPtrs[MAIN_CAM]; + Camera* mainCam = play->cameraPtrs[MAIN_CAM]; if (fabsf(yawDiff) > 10920.0f) { return 0; } - xyzDist = (this->actor.scale.x / 0.01f) * 10000.0f; + xyzDistSq = (this->actor.scale.x / 0.01f) * SQ(100.0f); if ((this->actor.params & 0xF0) == 0x90) { - Camera_ChangeSetting(camera, CAM_SET_DIRECTED_YAW); - xyzDist *= 4.8f; + Camera_ChangeSetting(mainCam, CAM_SET_DIRECTED_YAW); + xyzDistSq *= 4.8f; } - if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDist) { - if (camera->setting == CAM_SET_DIRECTED_YAW) { - Camera_ChangeSetting(camera, CAM_SET_NORMAL0); + if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDistSq) { + if (mainCam->setting == CAM_SET_DIRECTED_YAW) { + Camera_ChangeSetting(mainCam, CAM_SET_NORMAL0); } return 0; } else { @@ -480,7 +480,7 @@ s32 EnGo_FollowPath(EnGo* this, PlayState* play) { pointPos += this->unk_218; xDist = pointPos->x - this->actor.world.pos.x; zDist = pointPos->z - this->actor.world.pos.z; - Math_SmoothStepToS(&this->actor.world.rot.y, (s16)(Math_FAtan2F(xDist, zDist) * ((f32)0x8000 / M_PI)), 10, 1000, 1); + Math_SmoothStepToS(&this->actor.world.rot.y, RADF_TO_BINANG(Math_FAtan2F(xDist, zDist)), 10, 1000, 1); if ((SQ(xDist) + SQ(zDist)) < 600.0f) { this->unk_218++; @@ -536,7 +536,7 @@ s32 EnGo_SpawnDust(EnGo* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 nu accel.z = (Rand_ZeroOne() - 0.5f) * xzAccel; pos.x = (Math_SinS(angle) * radius) + this->actor.world.pos.x; pos.z = (Math_CosS(angle) * radius) + this->actor.world.pos.z; - EnGo_AddDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep); + EnGo_SpawnEffectDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep); angle += (s16)(0x10000 / numDustEffects); i--; } @@ -549,7 +549,7 @@ s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) { } else if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { return true; } else if (DECR(this->unk_21C)) { - if ((this->unk_21C & 1)) { + if (this->unk_21C & 1) { this->actor.world.pos.y += 1.5f; } else { this->actor.world.pos.y -= 1.5f; @@ -573,29 +573,29 @@ s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) { void func_80A3F908(EnGo* this, PlayState* play) { Player* player = GET_PLAYER(play); - f32 float1; - s32 isUnkCondition; + f32 interactRange; + s32 dialogStarted; if (this->actionFunc == EnGo_BiggoronActionFunc || this->actionFunc == EnGo_GoronLinkRolling || this->actionFunc == EnGo_FireGenericActionFunc || this->actionFunc == EnGo_Eyedrops || this->actionFunc == func_80A40DCC || this->actionFunc == EnGo_GetItem || this->actionFunc == func_80A40C78 || this->actionFunc == func_80A40B1C) { - float1 = (this->collider.dim.radius + 30.0f); - float1 *= (this->actor.scale.x / 0.01f); + interactRange = (this->collider.dim.radius + 30.0f); + interactRange *= (this->actor.scale.x / 0.01f); if ((this->actor.params & 0xF0) == 0x90) { - float1 *= 4.8f; + interactRange *= 4.8f; } if ((this->actor.params & 0xF0) == 0x90) { - isUnkCondition = - func_80A3ED24(play, this, &this->interactInfo, float1, EnGo_GetTextID, EnGo_UpdateTalkState); + dialogStarted = + EnGo_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, interactRange, EnGo_GetTextID, EnGo_UpdateTalkState); } else { - isUnkCondition = Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, float1, + dialogStarted = Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, interactRange, EnGo_GetTextID, EnGo_UpdateTalkState); } - if (((this->actor.params & 0xF0) == 0x90) && (isUnkCondition == true)) { + if (((this->actor.params & 0xF0) == 0x90) && (dialogStarted == true)) { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) { if (func_8002F368(play) == EXCH_ITEM_SWORD_BROKEN) { if (Flags_GetInfTable(INFTABLE_B4)) { @@ -628,7 +628,7 @@ void EnGo_Init(Actor* thisx, PlayState* play) { Vec3f D_80A41BA8 = { 0.0f, 0.0f, 0.0f }; // unused ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, NULL, 0, 0, 0); + SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, NULL, NULL, NULL, 0); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit); @@ -711,8 +711,8 @@ void EnGo_StopRolling(EnGo* this, PlayState* play) { EnBom* bomb; if (DECR(this->unk_20E) == 0) { - if (this->collider.base.ocFlags2 & 1) { - this->collider.base.ocFlags2 &= ~1; + if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { + this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; play->damagePlayer(play, -4); func_8002F71C(play, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f); this->unk_20E = 0x10; @@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, PlayState* play) { void EnGo_BiggoronActionFunc(EnGo* this, PlayState* play) { if (((this->actor.params & 0xF0) == 0x90) && (this->interactInfo.talkState == NPC_TALK_STATE_ACTION)) { - if (!IS_RANDO && gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; } else { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { @@ -958,31 +958,14 @@ void EnGo_GetItem(EnGo* this, PlayState* play) { this->unk_20C = 0; if ((this->actor.params & 0xF0) == 0x90) { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { - if (!IS_RANDO) { - getItemId = GI_SWORD_BGS; - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS); - getItemId = getItemEntry.getItemId; - } + getItemId = GI_SWORD_BGS; this->unk_20C = 1; } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { - if (IS_RANDO) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); - getItemId = getItemEntry.getItemId; - Randomizer_ConsumeAdultTradeItem(play, ITEM_EYEDROPS); - } else { - getItemId = GI_CLAIM_CHECK; - } + getItemId = GI_CLAIM_CHECK; } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) { - if (IS_RANDO) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); - Randomizer_ConsumeAdultTradeItem(play, ITEM_SWORD_BROKEN); - getItemId = getItemEntry.getItemId; - } else { - getItemId = GI_PRESCRIPTION; - } + getItemId = GI_PRESCRIPTION; } } @@ -992,11 +975,7 @@ void EnGo_GetItem(EnGo* this, PlayState* play) { yDist = fabsf(this->actor.yDistToPlayer) + 1.0f; xzDist = this->actor.xzDistToPlayer + 1.0f; - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, xzDist, yDist); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzDist, yDist); - } + Actor_OfferGetItem(&this->actor, play, getItemId, xzDist, yDist); } } @@ -1105,32 +1084,30 @@ void EnGo_DrawRolling(EnGo* this, PlayState* play) { s32 EnGo_OverrideLimbDraw(PlayState* play, s32 limb, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { EnGo* this = (EnGo*)thisx; - Vec3s vec1; + Vec3s limbRot; f32 float1; if (limb == 17) { Matrix_Translate(2800.0f, 0.0f, 0.0f, MTXMODE_APPLY); - vec1 = this->interactInfo.headRot; - float1 = (vec1.y / (f32)0x8000) * M_PI; + limbRot = this->interactInfo.headRot; + float1 = (limbRot.y / (f32)0x8000) * M_PI; Matrix_RotateX(float1, MTXMODE_APPLY); - float1 = (vec1.x / (f32)0x8000) * M_PI; + float1 = (limbRot.x / (f32)0x8000) * M_PI; Matrix_RotateZ(float1, MTXMODE_APPLY); Matrix_Translate(-2800.0f, 0.0f, 0.0f, MTXMODE_APPLY); } if (limb == 10) { - vec1 = this->interactInfo.torsoRot; - float1 = (vec1.y / (f32)0x8000) * M_PI; + limbRot = this->interactInfo.torsoRot; + float1 = (limbRot.y / (f32)0x8000) * M_PI; Matrix_RotateY(float1, MTXMODE_APPLY); - float1 = (vec1.x / (f32)0x8000) * M_PI; + float1 = (limbRot.x / (f32)0x8000) * M_PI; Matrix_RotateX(float1, MTXMODE_APPLY); } if ((limb == 10) || (limb == 11) || (limb == 14)) { - float1 = Math_SinS(this->jointTable[limb]); - rot->y += float1 * 200.0f; - float1 = Math_CosS(this->morphTable[limb]); - rot->z += float1 * 200.0f; + rot->y += Math_SinS(this->jointTable[limb]) * 200.0f; + rot->z += Math_CosS(this->morphTable[limb]) * 200.0f; } return 0; @@ -1150,9 +1127,9 @@ void EnGo_Draw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - EnGo_UpdateDust(this); + EnGo_UpdateEffects(this); Matrix_Push(); - EnGo_DrawDust(this, play); + EnGo_DrawEffects(this, play); Matrix_Pop(); if (this->actionFunc == EnGo_CurledUp) { @@ -1167,39 +1144,36 @@ void EnGo_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(gGoronCsMouthNeutralTex)); SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnGo_OverrideLimbDraw, EnGo_PostLimbDraw, &this->actor); - EnGo_DrawDust(this, play); + EnGo_DrawEffects(this, play); } CLOSE_DISPS(play->state.gfxCtx); } -void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) { - EnGoEffect* dustEffect = this->dustEffects; +void EnGo_SpawnEffectDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) { + EnGoEffect* dustEffect = this->effects; s16 i; - s16 timer; - for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) { + for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) { if (dustEffect->type != 1) { dustEffect->epoch++; dustEffect->scale = scale; dustEffect->scaleStep = scaleStep; - timer = initialTimer; - dustEffect->timer = timer; + dustEffect->initialTimer = dustEffect->timer = initialTimer; dustEffect->type = 1; - dustEffect->initialTimer = initialTimer; dustEffect->pos = *pos; dustEffect->accel = *accel; dustEffect->velocity = *velocity; - return; + break; } } } -void EnGo_UpdateDust(EnGo* this) { - EnGoEffect* dustEffect = this->dustEffects; +void EnGo_UpdateEffects(EnGo* this) { + EnGoEffect* dustEffect = this->effects; f32 randomNumber; s16 i; - for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) { + for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) { if (dustEffect->type) { dustEffect->timer--; if (dustEffect->timer == 0) { @@ -1220,24 +1194,24 @@ void EnGo_UpdateDust(EnGo* this) { } } -void EnGo_DrawDust(EnGo* this, PlayState* play) { +void EnGo_DrawEffects(EnGo* this, PlayState* play) { static void* dustTex[] = { gDust8Tex, gDust7Tex, gDust6Tex, gDust5Tex, gDust4Tex, gDust3Tex, gDust2Tex, gDust1Tex }; - EnGoEffect* dustEffect = this->dustEffects; + EnGoEffect* dustEffect = this->effects; s16 alpha; - s16 firstDone; + s16 materialFlag; s16 index; s16 i; OPEN_DISPS(play->state.gfxCtx); - firstDone = false; + materialFlag = false; Gfx_SetupDL_25Xlu(play->state.gfxCtx); - for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) { + for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) { if (dustEffect->type) { - if (!firstDone) { + if (!materialFlag) { POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 0); gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD40); gDPSetEnvColor(POLY_XLU_DISP++, 100, 60, 20, 0); - firstDone = true; + materialFlag = true; } FrameInterpolation_RecordOpenChild(dustEffect, dustEffect->epoch); diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.h b/soh/src/overlays/actors/ovl_En_Go/z_en_go.h index 7b3224aec..1b1320988 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.h +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.h @@ -16,12 +16,13 @@ typedef s16 (*callback2_80A3ED24)(PlayState*, struct EnGo*); // /* 0x20 */ GORON1_DMT_DC_ENTRANCE, // /* 0x30 */ GORON1_DMT_ROLLING_SMALL, // /* 0x40 */ GORON1_DMT_BOMB_FLOWER, -// /* 0x50 */ GORON1_CITY_ENTRANCE, +// /* 0x50 */ GORON1_CITY_ENTRANCE, // /* 0x60 */ GORON1_CITY_ISLAND, -// /* 0x70 */ GORON1_CITY_LOST_WOODS, +// /* 0x70 */ GORON1_CITY_LOST_WOODS, // /* 0x80 */ // Not Used // /* 0x90 */ GORON1_DMT_BIGGORON, +#define EN_GO_EFFECT_COUNT 20 typedef struct { /* 0x0000 */ u8 type; @@ -56,7 +57,7 @@ typedef struct EnGo { /* 0x021E */ s16 unk_21E; /* 0x0220 */ s16 jointTable[18]; /* 0x0244 */ s16 morphTable[18]; - /* 0x0268 */ EnGoEffect dustEffects[20]; + /* 0x0268 */ EnGoEffect effects[EN_GO_EFFECT_COUNT]; } EnGo; // size = 0x06C8 #endif diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index a4aede2e5..47d1d7b0d 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -3,7 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED) @@ -142,7 +142,6 @@ typedef enum { /* 10 */ ENGO2_ANIM_10, /* 11 */ ENGO2_ANIM_11, /* 12 */ ENGO2_ANIM_12, - /* 13 */ ENGO2_ANIM_13, // Added to fix spinning goron issue for biggoron } EnGo2Animation; static AnimationInfo sAnimationInfo[] = { @@ -152,7 +151,7 @@ static AnimationInfo sAnimationInfo[] = { { &gGoronAnim_002D80, 1.0f, 0.0f, -1.0f, 0x02, -8.0f }, { &gGoronAnim_00161C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_001A00, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_0021D0, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_004930, 0.0f, 0.0f, -1.0f, 0x01, -8.0f }, { &gGoronAnim_000750, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, - { &gGoronAnim_000D5C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_004930, 0.0f, 1.0f, -1.0f, 0x01, 0.0f }, + { &gGoronAnim_000D5C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, }; static EnGo2DustEffectData sDustEffectData[2][4] = { @@ -284,15 +283,10 @@ s32 EnGo2_SpawnDust(EnGo2* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 void EnGo2_GetItem(EnGo2* this, PlayState* play, s32 getItemId) { this->getItemId = getItemId; - func_8002F434(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, - fabsf(this->actor.yDistToPlayer) + 1.0f); -} - -void EnGo2_GetItemEntry(EnGo2* this, PlayState* play, GetItemEntry getItemEntry) { - this->getItemId = getItemEntry.getItemId; - this->getItemEntry = getItemEntry; - GiveItemEntryFromActor(&this->actor, play, getItemEntry, this->actor.xzDistToPlayer + 1.0f, - fabsf(this->actor.yDistToPlayer) + 1.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, this)) { + Actor_OfferGetItem(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, + fabsf(this->actor.yDistToPlayer) + 1.0f); + } } s32 EnGo2_GetDialogState(EnGo2* this, PlayState* play) { @@ -335,7 +329,8 @@ u16 EnGo2_GoronFireGenericGetTextId(EnGo2* this) { u16 EnGo2_GetTextIdGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Flags_GetInfTable(INFTABLE_11E)) { return 0x3013; - } else if ((CUR_CAPACITY(UPG_BOMB_BAG) >= 20 || IS_RANDO) && this->waypoint > 7 && this->waypoint < 12) { + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 20, this) + && this->waypoint > 7 && this->waypoint < 12) { return 0x3012; } else { return 0x3011; @@ -350,11 +345,7 @@ s16 EnGo2_UpdateTalkStateGoronCityRollingBig(PlayState* play, EnGo2* this) { if (Message_ShouldAdvance(play)) { if (this->actor.textId == 0x3012) { this->actionFunc = EnGo2_SetupGetItem; - if(!IS_RANDO) { - EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30); - } else { - EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_GC_ROLLING_GORON_AS_CHILD, GI_BOMB_BAG_40)); - } + EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30); Message_CloseTextbox(play); Flags_SetInfTable(INFTABLE_11E); return NPC_TALK_STATE_ACTION; @@ -416,11 +407,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtRollingSmall(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronDmtDcEntrance(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE) ? 0x3021 : Flags_GetInfTable(INFTABLE_E0) ? 0x302A : 0x3008; @@ -439,11 +428,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtDcEntrance(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityEntrance(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetInfTable(INFTABLE_F0) ? 0x3015 : 0x3014; @@ -462,11 +449,9 @@ s16 EnGo2_UpdateTalkStateGoronCityEntrance(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityIsland(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return Flags_GetInfTable(INFTABLE_F4) ? 0x3017 : 0x3016; @@ -485,11 +470,9 @@ s16 EnGo2_UpdateTalkStateGoronCityIsland(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityLowestFloor(PlayState* play, EnGo2* this) { - if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { return 0x3043; - } else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) { return 0x3027; } else { return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C @@ -511,23 +494,15 @@ s16 EnGo2_UpdateTalkStateGoronCityLowestFloor(PlayState* play, EnGo2* this) { } u16 EnGo2_GetTextIdGoronCityLink(PlayState* play, EnGo2* this) { - // For rando, prioritize opening the doors in GC when Link the goron has been stopped when - // the doors are not opened, otherwise let him talk about the DMC exit or that gorons are saved - if (IS_RANDO) { - if (!Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { - return 0x3030; - } else if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) { - return 0x3036; - } else if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) { - return 0x3041; - } else { - return Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; - } + // In case a hook neglects to set the override, fall back to the first dialogue + u16 overrideTextId = 0x3030; + if (GameInteractor_Should(GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, false, &overrideTextId)) { + return overrideTextId; } - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { + if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL)) { return Flags_GetInfTable(INFTABLE_10F) ? 0x3042 : 0x3041; - } else if (CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + } else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL)) { return Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037; } else if (Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) { this->unk_20C = 0; @@ -543,21 +518,9 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) { case TEXT_STATE_CLOSING: switch (this->actor.textId) { case 0x3036: - if (!IS_RANDO) { - EnGo2_GetItem(this, play, GI_TUNIC_GORON); - this->actionFunc = EnGo2_SetupGetItem; - return NPC_TALK_STATE_ACTION; - } else { - if (Flags_GetTreasure(play, 0x1F)) { - return NPC_TALK_STATE_IDLE; - } - - Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED); - EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_GC_ROLLING_GORON_AS_ADULT, GI_TUNIC_GORON)); - this->actionFunc = EnGo2_SetupGetItem; - Flags_SetTreasure(play, 0x1F); - return NPC_TALK_STATE_ACTION; - } + EnGo2_GetItem(this, play, GI_TUNIC_GORON); + this->actionFunc = EnGo2_SetupGetItem; + return NPC_TALK_STATE_ACTION; case 0x3037: Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK); default: @@ -605,7 +568,7 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(PlayState* play, EnGo2* this) { Player* player = GET_PLAYER(play); - if (!IS_RANDO && gSaveContext.bgsFlag) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { @@ -627,18 +590,14 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { switch (EnGo2_GetDialogState(this, play)) { case TEXT_STATE_DONE: if (this->actor.textId == 0x305E) { - if((!IS_RANDO && gSaveContext.bgsFlag) || (IS_RANDO && Flags_GetTreasure(play, 0x1F))) { + if (!GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) { + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK); + EnGo2_GetItem(this, play, GI_SWORD_BGS); + this->actionFunc = EnGo2_SetupGetItem; + return NPC_TALK_STATE_ACTION; + } else { return NPC_TALK_STATE_IDLE; } - - if(IS_RANDO) { - EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS)); - Flags_SetTreasure(play, 0x1F); - } else { - EnGo2_GetItem(this, play, GI_SWORD_BGS); - } - this->actionFunc = EnGo2_SetupGetItem; - return NPC_TALK_STATE_ACTION; } else { return NPC_TALK_STATE_IDLE; } @@ -663,15 +622,8 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) { if (Message_ShouldAdvance(play)) { if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) { if (play->msgCtx.choiceIndex == 0) { - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); - Randomizer_ConsumeAdultTradeItem(play, ITEM_SWORD_BROKEN); - EnGo2_GetItemEntry(this, play, getItemEntry); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD); - } else { - u32 getItemId = GI_PRESCRIPTION; - EnGo2_GetItem(this, play, getItemId); - } + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD); + EnGo2_GetItem(this, play, GI_PRESCRIPTION); this->actionFunc = EnGo2_SetupGetItem; return NPC_TALK_STATE_ACTION; } @@ -1070,7 +1022,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { u16 textId; if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { - if ((!IS_RANDO && gSaveContext.bgsFlag)) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { this->actor.textId = 0x3003; } else { @@ -1078,20 +1030,19 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) { } player->actor.textId = this->actor.textId; - } else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { + } else if ( + !GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL) && + (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) + ) { if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) { - if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) { - textId = 0x3003; - } else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x305E; } else { textId = 0x305D; } this->actor.textId = textId; } else { - if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) { - textId = 0x305E; - } else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) { + if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) { textId = 0x3002; } else { textId = 0x305D; @@ -1219,9 +1170,10 @@ s32 EnGo2_IsCameraModified(EnGo2* this, PlayState* play) { (this->actor.params & 0x1F) == GORON_CITY_STAIRWELL || (this->actor.params & 0x1F) == GORON_DMT_BIGGORON || (this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) { return true; - } else if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && - CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + } else if ( + !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + ) { return true; } else { return false; @@ -1278,9 +1230,10 @@ void EnGo2_SelectGoronWakingUp(EnGo2* this) { EnGo2_BiggoronWakingUp(this); break; case GORON_CITY_LINK: - if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && - CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + if ( + !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + ) { EnGo2_WakingUp(this); break; } @@ -1377,25 +1330,10 @@ void EnGo2_WakeUp(EnGo2* this, PlayState* play) { } if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { OnePointCutscene_Init(play, 4200, -99, &this->actor, MAIN_CAM); - // There is an issue interpolating between ENGO2_ANIM_0 and ENGO2_ANIM_1/10, the goron - // is technically in the same position at the end of ANIM_0 and beginning of ANIM_1/10 - // but something isn't getting translated correctly causing the 360 degree spin before - // then continuing the wake up animation like normal. One solution is to use ANIM_0 - // which uses the same frame data as ANIM_1/10 but no morph frames, but only when the - // current animation frame is at 0, meaning no morphing is necessary anyway. - // ANIM_13 is ANIM_0 but with the startFrame and mode adjusted for biggoron. - if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger("gUnfixGoronSpin", 0)) { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_13); - } else { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10); - } + Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10); this->skelAnime.playSpeed = 0.5f; } else { - if (this->skelAnime.curFrame == 0.0f && !CVarGetInteger("gUnfixGoronSpin", 0)) { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_0); - } else { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1); - } + Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1); this->skelAnime.playSpeed = 1.0f; } this->actionFunc = func_80A46B40; @@ -1617,15 +1555,13 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { this->unk_216 = this->actor.shape.rot.z; this->trackingMode = NPC_TRACKING_NONE; this->path = Path_GetByIndex(play, (this->actor.params & 0x3E0) >> 5, 0x1F); - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; switch (this->actor.params & 0x1F) { case GORON_CITY_ENTRANCE: case GORON_CITY_ISLAND: case GORON_CITY_LOWEST_FLOOR: case GORON_CITY_STAIRWELL: case GORON_CITY_LOST_WOODS: - if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) { + if (!GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) { Actor_Kill(&this->actor); } this->actionFunc = EnGo2_CurledUp; @@ -1640,9 +1576,10 @@ void EnGo2_Init(Actor* thisx, PlayState* play) { if ((Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED))) { Path_CopyLastPoint(this->path, &this->actor.world.pos); this->actor.home.pos = this->actor.world.pos; - if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && - CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) { + if ( + !GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && + GameInteractor_Should(GI_VB_GORONS_CONSIDER_TUNIC_COLLECTED, CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON), NULL) + ) { EnGo2_GetItemAnimation(this, play); } else { this->actionFunc = EnGo2_CurledUp; @@ -1858,44 +1795,17 @@ void EnGo2_ReverseRolling(EnGo2* this, PlayState* play) { } void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { this->actor.parent = NULL; this->actionFunc = EnGo2_SetGetItem; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } } void EnGo2_SetGetItem(EnGo2* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; - - // For randomizer, handle updating the states for the gorons after receiving the item based on - // the goron type rather then the item being received - if (IS_RANDO) { - switch (this->actor.params & 0x1F) { - case GORON_DMT_BIGGORON: - // Resolves #1301. unk_13EE is used to set the opacity of the HUD. The trade sequence discussion with Biggoron - // sets the HUD to transparent, and it is restored at z_message_PAL:3549, but by specifically watching for - // trade sequence items, this leaves it transparent for non-trade sequence items (in rando) so we fix that here - gSaveContext.unk_13EE = 0x32; - return; - case GORON_CITY_LINK: - EnGo2_GetItemAnimation(this, play); - return; - case GORON_CITY_ROLLING_BIG: - EnGo2_RollingAnimation(this, play); - this->actionFunc = EnGo2_GoronRollingBigContinueRolling; - return; - } - this->actionFunc = func_80A46B40; - return; - } - switch (this->getItemId) { case GI_CLAIM_CHECK: Environment_ClearBgsDayCount(); @@ -1906,7 +1816,9 @@ void EnGo2_SetGetItem(EnGo2* this, PlayState* play) { EnGo2_GetItemAnimation(this, play); return; case GI_SWORD_BGS: - gSaveContext.bgsFlag = true; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GORON, true, NULL)) { + gSaveContext.bgsFlag = true; + } break; case GI_BOMB_BAG_30: case GI_BOMB_BAG_40: @@ -1925,12 +1837,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; this->actor.shape.rot.y += 0x5B0; this->trackingMode = NPC_TRACKING_NONE; - this->animTimer = IS_RANDO ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer + this->animTimer = !GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL) ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer this->eyeMouthTexState = 2; this->unk_20C = 0; this->goronState++; func_800F483C(0x28, 5); - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL)) { OnePointCutscene_Init(play, 4190, -99, &this->actor, MAIN_CAM); } break; @@ -1959,15 +1871,8 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) { this->trackingMode = NPC_TRACKING_HEAD_AND_TORSO; this->skelAnime.playSpeed = 0.0f; this->skelAnime.curFrame = this->skelAnime.endFrame; - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); - Randomizer_ConsumeAdultTradeItem(play, ITEM_EYEDROPS); - EnGo2_GetItemEntry(this, play, getItemEntry); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS); - } else { - u32 getItemId = GI_CLAIM_CHECK; - EnGo2_GetItem(this, play, getItemId); - } + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS); + EnGo2_GetItem(this, play, GI_CLAIM_CHECK); this->actionFunc = EnGo2_SetupGetItem; this->goronState = 0; } @@ -2031,7 +1936,7 @@ void EnGo2_GoronFireGenericAction(EnGo2* this, PlayState* play) { (f32)((Math_SinS(this->actor.world.rot.y) * -30.0f) + this->actor.world.pos.x); player->actor.world.pos.z = (f32)((Math_CosS(this->actor.world.rot.y) * -30.0f) + this->actor.world.pos.z); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); Audio_PlayFanfare(NA_BGM_APPEAR); } break; @@ -2068,7 +1973,7 @@ void EnGo2_GoronFireGenericAction(EnGo2* this, PlayState* play) { case 4: // Finalize walking away Message_CloseTextbox(play); EnGo2_GoronFireClearCamera(this, play); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Actor_Kill(&this->actor); break; case 1: diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h index 86ac0c32e..185a036f4 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.h @@ -107,4 +107,9 @@ typedef struct EnGo2 { /* */ GetItemEntry getItemEntry; } EnGo2; // size = 0x05A0 +void EnGo2_GetItemAnimation(EnGo2* enGo2, PlayState* play); +void EnGo2_RollingAnimation(EnGo2* enGo2, PlayState* play); +void EnGo2_GoronRollingBigContinueRolling(EnGo2* enGo2, PlayState* play); +void func_80A46B40(EnGo2* enGo2, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c index ed924dd3c..5b5a97a08 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c +++ b/soh/src/overlays/actors/ovl_En_Heishi1/z_en_heishi1.c @@ -391,7 +391,7 @@ void EnHeishi1_WaitNight(EnHeishi1* this, PlayState* play) { Message_StartTextbox(play, 0x702D, &this->actor); func_80078884(NA_SE_SY_FOUND); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); // "Discovered!" - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = EnHeishi1_SetupKick; } } @@ -475,7 +475,7 @@ void EnHeishi1_Update(Actor* thisx, PlayState* play) { func_80078884(NA_SE_SY_FOUND); // "Discovered!" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); sHeishi1PlayerIsCaught = true; this->actionFunc = EnHeishi1_SetupMoveToLink; } diff --git a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c index 379ce2893..89dcc6808 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c +++ b/soh/src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.c @@ -112,7 +112,7 @@ void EnHeishi2_Init(Actor* thisx, PlayState* play) { this->actor.world.pos.z += 90.0f; this->actor.shape.rot.y = this->actor.world.rot.y; Collider_DestroyCylinder(play, &this->collider); - func_8002DF54(play, 0, 8); + Player_SetCsActionWithHaltedActors(play, 0, 8); this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; this->actionFunc = func_80A544AC; } @@ -265,7 +265,7 @@ void func_80A5344C(EnHeishi2* this, PlayState* play) { void func_80A53538(EnHeishi2* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (this->unk_300 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); play->msgCtx.msgMode = MSGMODE_PAUSED; this->actionFunc = func_80A535BC; } @@ -337,7 +337,7 @@ void func_80A53850(EnHeishi2* this, PlayState* play) { Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE); Message_CloseTextbox(play); this->unk_30C = 1; - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A531E4; } } @@ -426,7 +426,7 @@ void func_80A53AD4(EnHeishi2* this, PlayState* play) { void func_80A53C0C(EnHeishi2* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((this->unk_300 == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { - func_8002DF54(play, 0, 8); + Player_SetCsActionWithHaltedActors(play, 0, 8); play->msgCtx.msgMode = MSGMODE_PAUSED; this->actionFunc = func_80A53C90; } @@ -510,7 +510,7 @@ void func_80A53F30(EnHeishi2* this, PlayState* play) { this->actionFunc = func_80A54038; } else { Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A53908; } } else { @@ -528,7 +528,7 @@ void func_80A54038(EnHeishi2* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Flags_SetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); Message_CloseTextbox(play); - func_8002DF54(play, 0, 7); + Player_SetCsActionWithHaltedActors(play, 0, 7); this->actionFunc = func_80A53908; } } @@ -653,7 +653,7 @@ void func_80A5455C(EnHeishi2* this, PlayState* play) { EnBom* bomb; if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); Message_CloseTextbox(play); pos.x = Rand_CenteredFloat(20.0f) + this->unk_274.x; diff --git a/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c b/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c index 3ccc932ca..665a06470 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c +++ b/soh/src/overlays/actors/ovl_En_Heishi3/z_en_heishi3.c @@ -137,7 +137,7 @@ void EnHeishi3_StandSentinelInGrounds(EnHeishi3* this, PlayState* play) { Message_StartTextbox(play, 0x702D, &this->actor); func_80078884(NA_SE_SY_FOUND); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); // "Discovered!" - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = EnHeishi3_CatchStart; } } @@ -165,7 +165,7 @@ void EnHeishi3_StandSentinelInCastle(EnHeishi3* this, PlayState* play) { Message_StartTextbox(play, 0x702D, &this->actor); func_80078884(NA_SE_SY_FOUND); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST); // "Discovered!" - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); this->actionFunc = EnHeishi3_CatchStart; } } diff --git a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c index 391d7dc5d..d3b81c3d2 100644 --- a/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c +++ b/soh/src/overlays/actors/ovl_En_Heishi4/z_en_heishi4.c @@ -270,7 +270,7 @@ void func_80A56994(EnHeishi4* this, PlayState* play) { if ((this->unk_282 == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); Flags_SetInfTable(INFTABLE_6C); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A56A50; } } @@ -288,7 +288,7 @@ void func_80A56ACC(EnHeishi4* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (this->unk_288 <= currentFrame) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A5673C; } } diff --git a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c index 14b3703b8..eb3556a6e 100644 --- a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c +++ b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c @@ -7,7 +7,7 @@ #include "z_en_hs.h" #include "vt.h" #include "objects/object_hs/object_hs.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -79,25 +79,7 @@ void EnHs_Init(Actor* thisx, PlayState* play) { // "chicken shop (adult era)" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST); func_80A6E3A0(this, func_80A6E9AC); - bool shouldSpawn; - bool tradedMushroom = Flags_GetItemGetInf(ITEMGETINF_30); - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { - // To explain the logic because Fado and Grog are linked: - // - If you have Cojiro, then spawn Grog and not Fado. - // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. - // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. - // - If you don't have either but have traded the mushroom, don't spawn either. - if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { - shouldSpawn = true; - } else if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION)) { - shouldSpawn = false; - } else { - shouldSpawn = !tradedMushroom; - } - } else { - shouldSpawn = !tradedMushroom; - } - if (!shouldSpawn) { + if (GameInteractor_Should(GI_VB_DESPAWN_GROG, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // "chicken shop closed" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST); Actor_Kill(&this->actor); @@ -148,11 +130,11 @@ void func_80A6E5EC(EnHs* this, PlayState* play) { void func_80A6E630(EnHs* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_TRADE_TIMER_ODD_MUSHROOM, true, NULL)) { func_80088AA0(180); + gSaveContext.eventInf[1] &= ~1; } func_80A6E3A0(this, func_80A6E6B0); - gSaveContext.eventInf[1] &= ~1; } this->unk_2A8 |= 1; @@ -175,19 +157,12 @@ void func_80A6E70C(EnHs* this, PlayState* play) { } void func_80A6E740(EnHs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { this->actor.parent = NULL; + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); func_80A6E3A0(this, func_80A6E630); } else { - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); - Randomizer_ConsumeAdultTradeItem(play, ITEM_COJIRO); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); - } else { - s32 itemId = GI_ODD_MUSHROOM; - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } this->unk_2A8 |= 1; @@ -198,14 +173,8 @@ void func_80A6E7BC(EnHs* this, PlayState* play) { switch (play->msgCtx.choiceIndex) { case 0: func_80A6E3A0(this, func_80A6E740); - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); - Randomizer_ConsumeAdultTradeItem(play, ITEM_COJIRO); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO); - } else { - s32 itemId = GI_ODD_MUSHROOM; - func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f); } break; case 1: diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c index e0ff7470d..adb50441e 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.c @@ -14,6 +14,7 @@ #include "objects/object_cne/object_cne.h" #include "objects/object_cob/object_cob.h" #include "objects/object_os_anime/object_os_anime.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -411,7 +412,7 @@ s32 EnHy_IsOsAnimeObjectLoaded(EnHy* this, PlayState* play) { void func_80A6F7CC(EnHy* this, PlayState* play, s32 getItemId) { this->unkGetItemId = getItemId; - func_8002F434(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, + Actor_OfferGetItem(&this->actor, play, getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } @@ -659,19 +660,10 @@ s16 func_80A70058(PlayState* play, Actor* thisx) { gSaveContext.dogParams = 0; break; case 0x709F: - if (Flags_GetInfTable(INFTABLE_191)) { // Already brought the lost dog back - func_80A6F7CC(this, play, GI_RUPEE_BLUE); - } else { - if (!IS_RANDO) { - func_80A6F7CC(this, play, GI_HEART_PIECE); - } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_LOST_DOG, GI_HEART_PIECE); - // The follownig line and last arguments of GiveItemEntryFromActor are copied from func_80A6F7CC - this->unkGetItemId = this->getItemEntry.getItemId; - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LOST_DOG, true, this)) { + func_80A6F7CC(this, play, Flags_GetInfTable(INFTABLE_191) ? GI_RUPEE_BLUE : GI_HEART_PIECE); + this->actionFunc = func_80A714C4; } - this->actionFunc = func_80A714C4; break; } return NPC_TALK_STATE_IDLE; @@ -1068,36 +1060,26 @@ void func_80A714C4(EnHy* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = func_80A71530; } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->unkGetItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); - } + Actor_OfferGetItem(&this->actor, play, this->unkGetItemId, this->actor.xzDistToPlayer + 1.0f, + fabsf(this->actor.yDistToPlayer) + 1.0f); } } void func_80A71530(EnHy* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (IS_RANDO) { - if (!Flags_GetInfTable(INFTABLE_191)) { - Flags_SetInfTable(INFTABLE_191); - } - gSaveContext.dogParams = 0; - gSaveContext.dogIsLost = false; - } else { - switch (this->unkGetItemId) { - case GI_HEART_PIECE: - gSaveContext.dogParams = 0; - gSaveContext.dogIsLost = false; - Flags_SetInfTable(INFTABLE_191); - break; - case GI_RUPEE_BLUE: - Rupees_ChangeBy(5); - gSaveContext.dogParams = 0; - gSaveContext.dogIsLost = false; - break; - } + switch (this->unkGetItemId) { + case GI_HEART_PIECE: + gSaveContext.dogParams = 0; + gSaveContext.dogIsLost = false; + SET_INFTABLE(INFTABLE_191); + break; + case GI_RUPEE_BLUE: + Rupees_ChangeBy(5); + gSaveContext.dogParams = 0; + gSaveContext.dogIsLost = false; + break; } + this->actionFunc = func_80A7127C; } } diff --git a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h index 6a5ed2680..7d94a5ca6 100644 --- a/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h +++ b/soh/src/overlays/actors/ovl_En_Hy/z_en_hy.h @@ -62,4 +62,6 @@ typedef struct EnHy { /* */ GetItemEntry getItemEntry; } EnHy; // size = 0x0334 +void func_80A7127C(EnHy* enHy, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c b/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c index f412e7398..3503aef08 100644 --- a/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c +++ b/soh/src/overlays/actors/ovl_En_Ice_Hono/z_en_ice_hono.c @@ -216,7 +216,7 @@ void EnIceHono_CapturableFlame(EnIceHono* this, PlayState* play) { this->actor.parent = NULL; } else if (EnIceHono_InBottleRange(this, play)) { // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 60.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, GI_MAX, 60.0f, 100.0f); } if (this->actor.xzDistToPlayer < 200.0f) { diff --git a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c index aaf0e0342..5f1634237 100644 --- a/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/soh/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -1439,28 +1439,10 @@ void func_80A781CC(Actor* thisx, PlayState* play) { if (!Play_InCsMode(play)) { this->actor.update = EnIk_Update; this->actor.draw = EnIk_Draw; - // Don't initiate nabooru defeat CS in rando - if (!(IS_RANDO)) { + if (GameInteractor_Should(GI_VB_NABOORU_KNUCKLE_DEATH_SCENE, true, this)) { Cutscene_SetSegment(play, gSpiritBossNabooruKnuckleDefeatCs); gSaveContext.cutsceneTrigger = 1; Actor_SetScale(&this->actor, 0.01f); - } else { - // Because no CS in rando, we hide the death of the knuckle by spawning flames and kill the actor - if ((this->actor.colChkInfo.health <= 10)) { - s32 i; - Vec3f pos; - Vec3f sp7C = { 0.0f, 0.5f, 0.0f }; - int flameAmount = 100; - - for (i = flameAmount; i >= 0; i--) { - pos.x = this->actor.world.pos.x + Rand_CenteredFloat(120.0f); - pos.z = this->actor.world.pos.z + Rand_CenteredFloat(120.0f); - pos.y = this->actor.world.pos.y + 20.0f + Rand_CenteredFloat(120.0f); - EffectSsDeadDb_Spawn(play, &pos, &sp7C, &sp7C, 100, 0, 255, 255, 255, 255, 0, 0, 255, 1, 9, - true); - } - Actor_Kill(&this->actor); - } } Flags_SetEventChkInf(EVENTCHKINF_FINISHED_NABOORU_BATTLE); func_80A7735C(this, play); diff --git a/soh/src/overlays/actors/ovl_En_In/z_en_in.c b/soh/src/overlays/actors/ovl_En_In/z_en_in.c index 1d0866e6d..6edf01333 100644 --- a/soh/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/soh/src/overlays/actors/ovl_En_In/z_en_in.c @@ -434,7 +434,7 @@ void func_80A79BAC(EnIn* this, PlayState* play, s32 index, u32 transitionType) { } play->transitionType = transitionType; play->transitionTrigger = TRANS_TRIGGER_START; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); Interface_ChangeAlpha(1); if (index == 0) { AREG(6) = 0; @@ -856,7 +856,7 @@ void func_80A7ABD4(EnIn* this, PlayState* play) { void func_80A7AE84(EnIn* this, PlayState* play) { Play_ChangeCameraStatus(play, this->activeCamId, CAM_STAT_ACTIVE); Play_ClearCamera(play, this->camId); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Interface_ChangeAlpha(0x32); this->actionFunc = func_80A7AEF0; } diff --git a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c index 393e10a91..862b6f92b 100644 --- a/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c +++ b/soh/src/overlays/actors/ovl_En_Insect/z_en_insect.c @@ -786,7 +786,7 @@ void EnInsect_Update(Actor* thisx, PlayState* play) { if (!(this->unk_314 & 8) && D_80A7DEB4 < 4 && EnInsect_InBottleRange(this, play) && // GI_MAX in this case allows the player to catch the actor in a bottle - func_8002F434(&this->actor, play, GI_MAX, 60.0f, 30.0f)) { + Actor_OfferGetItem(&this->actor, play, GI_MAX, 60.0f, 30.0f)) { D_80A7DEB4++; } } diff --git a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index af10aa086..c79033250 100644 --- a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -379,9 +379,9 @@ void EnIshi_Wait(EnIshi* this, PlayState* play) { if (this->actor.xzDistToPlayer < 90.0f) { // GI_NONE in these cases allows the player to lift the actor if (type == ROCK_LARGE) { - func_8002F434(&this->actor, play, GI_NONE, 80.0f, 20.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 80.0f, 20.0f); } else { - func_8002F434(&this->actor, play, GI_NONE, 50.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 50.0f, 10.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index 50be2e458..1baf3413a 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -6,6 +6,7 @@ #include "z_en_js.h" #include "objects/object_js/object_js.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -127,23 +128,15 @@ void func_80A8910C(EnJs* this, PlayState* play) { } void func_80A89160(EnJs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this)) { this->actor.parent = NULL; En_Js_SetupAction(this, func_80A8910C); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); } else { - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); - } else { - GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); - } + GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10); + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; + Actor_OfferGetItem(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c b/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c index cf2f4499b..99cc81540 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c @@ -260,7 +260,7 @@ void func_80A8F8D0(EnKakasi* this, PlayState* play) { void func_80A8F9C8(EnKakasi* this, PlayState* play) { func_80A8F28C(this); SkelAnime_Update(&this->skelanime); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (this->unk_196 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { @@ -269,7 +269,7 @@ void func_80A8F9C8(EnKakasi* this, PlayState* play) { } this->camId = OnePointCutscene_Init(play, 2270, -99, &this->actor, MAIN_CAM); play->msgCtx.msgMode = MSGMODE_PAUSED; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); func_8010BD58(play, OCARINA_ACTION_SCARECROW_LONG_PLAYBACK); this->actionFunc = func_80A8FAA4; } @@ -308,7 +308,7 @@ void func_80A8FBB8(EnKakasi* this, PlayState* play) { if (this->unk_196 == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { func_8005B1A4(play->cameraPtrs[this->camId]); Message_CloseTextbox(play); - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A8F660; } } diff --git a/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c b/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c index 37b6236a5..9cb4e5de5 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c @@ -296,7 +296,7 @@ void func_80A91620(EnKakasi3* this, PlayState* play) { if (play->msgCtx.ocarinaMode == OCARINA_MODE_03 && play->msgCtx.msgMode == MSGMODE_NONE) { this->dialogState = TEXT_STATE_EVENT; Message_StartTextbox(play, 0x40A5, NULL); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A91A90; return; } @@ -354,7 +354,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { this->dialogState = TEXT_STATE_EVENT; OnePointCutscene_EndCutscene(play, this->camId); this->camId = SUBCAM_NONE; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A91A90; return; } @@ -370,7 +370,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { this->unk_195 = true; Message_StartTextbox(play, 0x40A7, NULL); this->dialogState = TEXT_STATE_EVENT; - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); this->actionFunc = func_80A91A90; return; } @@ -384,7 +384,7 @@ void func_80A918E4(EnKakasi3* this, PlayState* play) { void func_80A91A90(EnKakasi3* this, PlayState* play) { func_80A90E28(this); SkelAnime_Update(&this->skelAnime); - func_8002DF54(play, NULL, 8); + Player_SetCsActionWithHaltedActors(play, NULL, 8); if (this->dialogState == Message_GetState(&play->msgCtx) && Message_ShouldAdvance(play)) { if (this->unk_195) { @@ -400,7 +400,7 @@ void func_80A91A90(EnKakasi3* this, PlayState* play) { } Message_CloseTextbox(play); play->msgCtx.ocarinaMode = OCARINA_MODE_04; - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->actionFunc = func_80A911F0; } } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 25299f5b0..4e83742c3 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -10,7 +10,7 @@ #include "objects/object_km1/object_km1.h" #include "objects/object_kw1/object_kw1.h" #include "vt.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -1027,20 +1027,9 @@ s32 EnKo_CanSpawn(EnKo* this, PlayState* play) { } case SCENE_LOST_WOODS: - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { - // To explain the logic because Fado and Grog are linked: - // - If you have Cojiro, then spawn Grog and not Fado. - // - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog. - // - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom. - // - If you don't have either but have traded the mushroom, don't spawn either. - if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) { - return false; - } else { - return PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION); - } - } else { - return (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false; - } + return GameInteractor_Should(GI_VB_SPAWN_LW_FADO, ( + (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false + ), this); default: return false; } @@ -1186,18 +1175,10 @@ void func_80A99048(EnKo* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELF, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3); if (ENKO_TYPE == ENKO_TYPE_CHILD_3) { - if (!IS_RANDO) { - if (!CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { - this->collider.dim.height += 200; - this->actionFunc = func_80A995CC; - return; - } - } else { - if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) { - this->collider.dim.height += 200; - this->actionFunc = func_80A995CC; - return; - } + if (!GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { + this->collider.dim.height += 200; + this->actionFunc = func_80A995CC; + return; } Path_CopyLastPoint(this->path, &this->actor.world.pos); } @@ -1230,18 +1211,11 @@ void func_80A99438(EnKo* this, PlayState* play) { } void func_80A99504(EnKo* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_POTION, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80A99560; } else { - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW); - Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_POTION); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 120.0f, 10.0f); - } else { - s32 itemId = GI_SAW; - func_8002F434(&this->actor, play, itemId, 120.0f, 10.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_SAW, 120.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h index c247f53b9..5deeef465 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.h @@ -57,4 +57,8 @@ typedef enum { ENKO_FQS_ADULT_SAVED } KokiriForestQuestState; +void func_80A995CC(EnKo* actor, PlayState* play); +void func_80A99384(EnKo* actor, PlayState* play); +void func_80A99560(EnKo* actor, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index ad3bd0ab5..9ee9f6d0a 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -6,7 +6,7 @@ #include "z_en_kz.h" #include "objects/object_kz/object_kz.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -73,12 +73,9 @@ static AnimationInfo sAnimationInfo[] = { u16 EnKz_GetTextNoMaskChild(PlayState* play, EnKz* this) { Player* player = GET_PLAYER(play); - if ((IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) || - (!IS_RANDO && CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE))) { - // Allow turning in Ruto's letter even if you have already rescued her - if (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - player->exchangeItemId = EXCH_ITEM_LETTER_RUTO; - } + if (GameInteractor_Should(GI_VB_KING_ZORA_THANK_CHILD, ( + CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) + ), this)) { return 0x402B; } else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { return 0x401C; @@ -94,8 +91,10 @@ u16 EnKz_GetTextNoMaskAdult(PlayState* play, EnKz* this) { // this works because both ITEM_NONE and later trade items are > ITEM_FROG if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_FROG) { if (!Flags_GetInfTable(INFTABLE_139)) { - if (!IS_RANDO) { - return CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ? 0x401F : 0x4012; + if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, ( + !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) + ), this)) { + return 0x401F; } else { return 0x4012; } @@ -243,7 +242,9 @@ void func_80A9CB18(EnKz* this, PlayState* play) { Player* player = GET_PLAYER(play); if (func_80A9C95C(play, this, &this->interactInfo.talkState, 340.0f, EnKz_GetText, func_80A9C6C0)) { - if (((IS_RANDO && LINK_IS_CHILD) || this->actor.textId == 0x401A) && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { + if (GameInteractor_Should(GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, (this->actor.textId == 0x401A), this) && + !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) + { if (func_8002F368(play) == EXCH_ITEM_LETTER_RUTO) { this->actor.textId = 0x401B; this->sfxPlayed = false; @@ -257,7 +258,7 @@ void func_80A9CB18(EnKz* this, PlayState* play) { if (LINK_IS_ADULT) { if ((INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_PRESCRIPTION) && (func_8002F368(play) == EXCH_ITEM_PRESCRIPTION)) { - if (!IS_RANDO || !Flags_GetTreasure(play, 0x1F)) { + if (GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) { this->actor.textId = 0x4014; this->sfxPlayed = false; player->actor.textId = this->actor.textId; @@ -271,11 +272,11 @@ void func_80A9CB18(EnKz* this, PlayState* play) { this->actor.textId = CHECK_QUEST_ITEM(QUEST_SONG_SERENADE) ? 0x4045 : 0x401A; player->actor.textId = this->actor.textId; } else { - if (!IS_RANDO) { - this->actor.textId = CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ? 0x401F : 0x4012; - } else { - this->actor.textId = 0x4012; - } + this->actor.textId = + !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, + (!CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)), this) + ? 0x401F + : 0x4012; player->actor.textId = this->actor.textId; } @@ -344,29 +345,10 @@ void EnKz_Init(Actor* thisx, PlayState* play) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; Animation_ChangeByInfo(&this->skelanime, sAnimationInfo, ENKZ_ANIM_0); - if (!IS_RANDO) { - if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - EnKz_SetMovedPos(this, play); - } - } else { - int zorasFountain = Randomizer_GetSettingValue(RSK_ZORAS_FOUNTAIN); - switch (zorasFountain) { - case 0: - if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - EnKz_SetMovedPos(this, play); - } - break; - case 1: - if (LINK_IS_ADULT) { - EnKz_SetMovedPos(this, play); - } else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) { - EnKz_SetMovedPos(this, play); - } - break; - case 2: - EnKz_SetMovedPos(this, play); - break; - } + if (GameInteractor_Should(GI_VB_KING_ZORA_BE_MOVED, ( + Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED) + ), this)) { + EnKz_SetMovedPos(this, play); } if (LINK_IS_ADULT) { @@ -414,7 +396,7 @@ void EnKz_SetupMweep(EnKz* this, PlayState* play) { initPos.y += -100.0f; initPos.z += 260.0f; Play_CameraSetAtEye(play, this->cutsceneCamera, &pos, &initPos); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->actor.speedXZ = 0.1f * CVarGetInteger("gMweepSpeed", 1); this->actionFunc = EnKz_Mweep; } @@ -446,7 +428,7 @@ void EnKz_Mweep(EnKz* this, PlayState* play) { void EnKz_StopMweep(EnKz* this, PlayState* play) { Play_ChangeCameraStatus(play, this->gameplayCamera, CAM_STAT_ACTIVE); Play_ClearCamera(play, this->cutsceneCamera); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionFunc = EnKz_Wait; } @@ -465,37 +447,29 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) { f32 xzRange; f32 yRange; - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || ( + (this->isTrading && !GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) || + (!this->isTrading && !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, true, this)) + )) { this->actor.parent = NULL; this->interactInfo.talkState = NPC_TALK_STATE_TALKING; this->actionFunc = EnKz_StartTimer; - } else { - if (IS_RANDO) { - if (this->isTrading) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG); - getItemId = getItemEntry.getItemId; - Randomizer_ConsumeAdultTradeItem(play, ITEM_PRESCRIPTION); - Flags_SetTreasure(play, 0x1F); - } else { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA); - getItemId = getItemEntry.getItemId; - } + if (!this->isTrading) { + Flags_SetRandomizerInf(RAND_INF_KING_ZORA_THAWED); } else { - getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION); } + } else { + getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; yRange = fabsf(this->actor.yDistToPlayer) + 1.0f; xzRange = this->actor.xzDistToPlayer + 1.0f; - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, xzRange, yRange); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzRange, yRange); - } + Actor_OfferGetItem(&this->actor, play, getItemId, xzRange, yRange); } } void EnKz_StartTimer(EnKz* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !IS_RANDO) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && GameInteractor_Should(GI_VB_TRADE_TIMER_FROG, true, NULL)) { func_80088AA0(180); // start timer2 with 3 minutes gSaveContext.eventInf[1] &= ~1; } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h index 37feb841a..c97732356 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.h @@ -28,4 +28,6 @@ typedef struct EnKz { /* 0x02BE */ s16 unk_2BE[12]; } EnKz; // size = 0x02D8 +void EnKz_SetupGetItem(EnKz* enKz, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index 606bca3b8..267a49bcd 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -6,6 +6,7 @@ #include "z_en_ma1.h" #include "objects/object_ma1/object_ma1.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -25,7 +26,6 @@ void func_80AA106C(EnMa1* this, PlayState* play); void func_80AA10EC(EnMa1* this, PlayState* play); void func_80AA1150(EnMa1* this, PlayState* play); void EnMa1_DoNothing(EnMa1* this, PlayState* play); -void EnMa1_WaitForSongGive(EnMa1* this, PlayState* play); const ActorInit En_Ma1_InitVars = { ACTOR_EN_MA1, @@ -90,25 +90,16 @@ static void* sEyeTextures[] = { gMalonChildEyeClosedTex, }; -bool Randomizer_ObtainedMalonHCReward() { - return Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); -} - u16 EnMa1_GetText(PlayState* play, Actor* thisx) { - // Special case for Malon Hyrule Castle Text. Placing it here at the beginning - // has the added benefit of circumventing mask text if wearing bunny hood. - if (IS_RANDO && play->sceneNum == SCENE_HYRULE_CASTLE) { - return Randomizer_ObtainedMalonHCReward() ? 0x2044 : 0x2043; - } + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); u16 faceReaction = Text_GetFaceReaction(play, 0x17); if (faceReaction != 0) { return faceReaction; } - if (!IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_SONG_EPONA)) { - return 0x204A; - } + if (malonTaughtEponasSong) { + return 0x204A; } if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) { return 0x2049; @@ -120,7 +111,7 @@ u16 EnMa1_GetText(PlayState* play, Actor* thisx) { return 0x2048; } } - if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { + if (malonReturnedFromCastle) { return 0x2047; } if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG)) { @@ -194,6 +185,8 @@ s16 func_80AA0778(PlayState* play, Actor* thisx) { } s32 func_80AA08C4(EnMa1* this, PlayState* play) { + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + if ((this->actor.shape.rot.z == 3) && (gSaveContext.sceneSetupIndex == 5)) { return 1; } @@ -202,32 +195,24 @@ s32 func_80AA08C4(EnMa1* this, PlayState* play) { } // Causes Malon to appear in the market if you haven't met her yet. if (((play->sceneNum == SCENE_MARKET_NIGHT) || (play->sceneNum == SCENE_MARKET_DAY)) && - !Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + !malonReturnedFromCastle && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { return 1; } - if ((play->sceneNum == SCENE_HYRULE_CASTLE) && // if we're at hyrule castle - (!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || // and talon hasn't left - (IS_RANDO && - !Randomizer_ObtainedMalonHCReward()))) { // or we're rando'd and haven't gotten malon's HC check - if (Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { // if we've met malon - return 1; // make her appear at the castle - } else { // if we haven't met malon - Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); // set the flag for meeting malon - return 0; // don't make her appear at the castle + if ((play->sceneNum == SCENE_HYRULE_CASTLE) && !malonReturnedFromCastle) { + if (Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { + return 1; + } else { + Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); + return 0; } } - // Malon asleep in her bed if Talon has left Hyrule Castle and it is nighttime. - if ((play->sceneNum == SCENE_LON_LON_BUILDINGS) && IS_NIGHT && (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) { + if ((play->sceneNum == SCENE_LON_LON_BUILDINGS) && IS_NIGHT && malonReturnedFromCastle) { return 1; } - // Don't spawn Malon if none of the above are true and we are not in Lon Lon Ranch. if (play->sceneNum != SCENE_LON_LON_RANCH) { return 0; } - // If we've gotten this far, we're in Lon Lon Ranch. Spawn Malon if it is daytime, Talon has left Hyrule Castle, and - // either we are not randomized, or we are and we have received Malon's item at Hyrule Castle. - if ((this->actor.shape.rot.z == 3) && IS_DAY && (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) && - ((IS_RANDO && Randomizer_ObtainedMalonHCReward()) || !IS_RANDO)) { + if ((this->actor.shape.rot.z == 3) && IS_DAY && malonReturnedFromCastle) { return 1; } return 0; @@ -284,6 +269,8 @@ void func_80AA0B74(EnMa1* this) { void EnMa1_Init(Actor* thisx, PlayState* play) { EnMa1* this = (EnMa1*)thisx; + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); s32 pad; ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 18.0f); @@ -292,12 +279,6 @@ void EnMa1_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit); - if (IS_RANDO) { // Skip Malon's multiple textboxes before getting an item - Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); - Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET); - Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET); - } - if (!func_80AA08C4(this, play)) { Actor_Kill(&this->actor); return; @@ -308,21 +289,10 @@ void EnMa1_Init(Actor* thisx, PlayState* play) { this->actor.targetMode = 6; this->interactInfo.talkState = NPC_TALK_STATE_IDLE; - // To avoid missing a check, we want Malon to have the actionFunc for singing, but not reacting to Ocarina, if any of - // the following are true. - // 1. Talon has not left Hyrule Castle. - // 2. We are Randomized and have not obtained Malon's Weird Egg Check. - // 3. We are not Randomized and have obtained Epona's Song - if (!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || (IS_RANDO && !Randomizer_ObtainedMalonHCReward()) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !IS_RANDO) || - (IS_RANDO && Flags_GetTreasure(play, 0x1F))) { + if (!malonReturnedFromCastle || malonTaughtEponasSong) { this->actionFunc = func_80AA0D88; EnMa1_ChangeAnim(this, ENMA1_ANIM_2); - // If none of the above conditions were true, set Malon up to teach Epona's Song. } else { - if (IS_RANDO) { // Skip straight to "let's sing it together" textbox in the ranch - Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON); - } - this->actionFunc = func_80AA0F44; EnMa1_ChangeAnim(this, ENMA1_ANIM_2); } @@ -336,6 +306,9 @@ void EnMa1_Destroy(Actor* thisx, PlayState* play) { } void func_80AA0D88(EnMa1* this, PlayState* play) { + bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL); + bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL); + if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { if (this->skelAnime.animation != &gMalonChildIdleAnim) { EnMa1_ChangeAnim(this, ENMA1_ANIM_1); @@ -346,16 +319,9 @@ void func_80AA0D88(EnMa1* this, PlayState* play) { } } - // We want to Kill Malon's Actor outside of randomizer when Talon is freed. In Randomizer we don't kill Malon's - // Actor here, otherwise if we wake up Talon first and then get her check she will spontaneously - // disappear. - if ((play->sceneNum == SCENE_HYRULE_CASTLE) && (!IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) { + if ((play->sceneNum == SCENE_HYRULE_CASTLE) && malonReturnedFromCastle) { Actor_Kill(&this->actor); - // We want Malon to give the Weird Egg Check (see function below) in the following situations: - // 1. Talon as not left Hyrule Castle (Vanilla) OR - // 2. We haven't obtained Malon's Weird Egg Check (Randomizer only) OR - // 3. We have Epona's Song? (Vanilla only, not sure why it's here but I didn't write that one) - } else if ((!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || (IS_RANDO && !Randomizer_ObtainedMalonHCReward())) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !IS_RANDO)) { + } else if (!malonReturnedFromCastle || malonTaughtEponasSong) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { this->actionFunc = func_80AA0EA0; play->msgCtx.stateTimer = 4; @@ -365,21 +331,16 @@ void func_80AA0D88(EnMa1* this, PlayState* play) { } void func_80AA0EA0(EnMa1* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { this->actor.parent = NULL; this->actionFunc = func_80AA0EFC; } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_MALON_EGG, GI_WEIRD_EGG); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 10.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f); } } void func_80AA0EFC(EnMa1* this, PlayState* play) { - if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN) { + if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->actionFunc = func_80AA0D88; Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); @@ -387,24 +348,6 @@ void func_80AA0EFC(EnMa1* this, PlayState* play) { } } -void GivePlayerRandoRewardMalon(EnMa1* malon, PlayState* play, RandomizerCheck check) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_EPONAS_SONG); - // Prevents flag from getting set if we weren't able to get the item (i.e. Player is holding shield - // when closing the textbox). - if (malon->actor.parent != NULL && malon->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - // puts malon in the action that vanilla has her in after learning the song - // (confirmed via breakpoints in a vanilla save). - malon->actionFunc = func_80AA0D88; - } else if (!Flags_GetTreasure(play, 0x1F)) { - GiveItemEntryFromActor(&malon->actor, play, getItemEntry, 10000.0f, 100.0f); - } - // make malon sing again after giving the item. - malon->interactInfo.talkState = NPC_TALK_STATE_IDLE; - malon->unk_1E0 = 1; -} - void func_80AA0F44(EnMa1* this, PlayState* play) { Player* player = GET_PLAYER(play); @@ -419,7 +362,6 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { } if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) { - // When the player pulls out the Ocarina while close to Malon if (player->stateFlags2 & PLAYER_STATE2_ATTEMPT_PLAY_FOR_ACTOR) { player->stateFlags2 |= PLAYER_STATE2_PLAY_FOR_ACTOR; player->unk_6A8 = &this->actor; @@ -427,19 +369,10 @@ void func_80AA0F44(EnMa1* this, PlayState* play) { Message_StartTextbox(play, this->actor.textId, NULL); this->interactInfo.talkState = NPC_TALK_STATE_TALKING; this->actor.flags |= ACTOR_FLAG_WILL_TALK; - // when rando'ed, skip to the Item Giving. Otherwise go to the song teaching code. - this->actionFunc = IS_RANDO ? func_80AA1150 : func_80AA106C; + this->actionFunc = func_80AA106C; } else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) { - // somehow flags that the player is close to malon so that pulling out the Ocarina - // triggers the code above this. player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; } - // If rando'ed, a textbox is closing, it's malon's 'my mom wrote this song' text, AND we do have an ocarina - // in our inventory. This allows us to grant the check when talking to malon with the ocarina in our inventory. - if (IS_RANDO && (Actor_TextboxIsClosing(&this->actor, play) && play->msgCtx.textId == 0x2049) && - (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE || INV_CONTENT(ITEM_OCARINA_TIME) != ITEM_NONE)) { - this->actionFunc = EnMa1_WaitForSongGive; - } } } @@ -461,48 +394,16 @@ void func_80AA10EC(EnMa1* this, PlayState* play) { } } -void EnMa1_WaitForSongGive(EnMa1* this, PlayState* play) { - // Actually give the song check. - GivePlayerRandoRewardMalon(this, play, RC_SONG_FROM_MALON); -} - -// Sets an Ocarina State necessary to not softlock in rando. -// This function should only be called in rando. -void EnMa1_EndTeachSong(EnMa1* this, PlayState* play) { - if (play->csCtx.state == CS_STATE_IDLE) { - this->actionFunc = func_80AA0F44; - play->msgCtx.ocarinaMode = OCARINA_MODE_04; - } - - if (IS_RANDO) { - // Transition to the giving the song check on the next update run. - this->actionFunc = EnMa1_WaitForSongGive; - } -} - void func_80AA1150(EnMa1* this, PlayState* play) { GET_PLAYER(play)->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR; - // When rando'ed, trigger the "song learned" Ocarina mode. - if (IS_RANDO && (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING)) { - play->msgCtx.ocarinaMode = OCARINA_MODE_03; - } - if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { - if (!IS_RANDO) { - play->nextEntranceIndex = ENTR_LON_LON_RANCH_0; - gSaveContext.nextCutsceneIndex = 0xFFF1; - play->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST); - play->transitionTrigger = TRANS_TRIGGER_START; - this->actionFunc = EnMa1_DoNothing; - } else { - // When rando'ed, skip the cutscene, play the chime, reset some flags, - // and give the song on next update. - func_80078884(NA_SE_SY_CORRECT_CHIME); - this->actionFunc = EnMa1_EndTeachSong; - this->actor.flags &= ~ACTOR_FLAG_WILL_TALK; - play->msgCtx.ocarinaMode = OCARINA_MODE_00; - } + Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG); + play->nextEntranceIndex = ENTR_LON_LON_RANCH_0; + gSaveContext.nextCutsceneIndex = 0xFFF1; + play->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST); + play->transitionTrigger = TRANS_TRIGGER_START; + this->actionFunc = EnMa1_DoNothing; } } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h index 55b53bd72..f06f220c9 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.h @@ -20,4 +20,7 @@ typedef struct EnMa1 { /* 0x01E8 */ NpcInteractInfo interactInfo; } EnMa1; // size = 0x0210 +void func_80AA106C(EnMa1* enMa1, PlayState* play); +void func_80AA0D88(EnMa1* enMa1, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c index 9181b452b..d2e168ab1 100644 --- a/soh/src/overlays/actors/ovl_En_Md/z_en_md.c +++ b/soh/src/overlays/actors/ovl_En_Md/z_en_md.c @@ -7,6 +7,7 @@ #include "z_en_md.h" #include "objects/object_md/object_md.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -372,11 +373,7 @@ u16 EnMd_GetTextKokiriForest(PlayState* play, EnMd* this) { this->unk_208 = 0; this->unk_209 = TEXT_STATE_NONE; - // In rando, skip talking about the tree being dead so we can have the prompt for sword and shield instead - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) || - (IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && - Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) && - !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH))) { + if (GameInteractor_Should(GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) { return 0x1045; } @@ -486,25 +483,6 @@ s16 func_80AAAF04(PlayState* play, Actor* thisx) { } u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) { - // In rando, Mido's spawn logic is adjusted to support closed deku/forest options - // He will spawn in the forest if you haven't showed the sword and shield, and will remain - // in the forest until you've obtained Zelda's letter or Deku Tree dies - // This is to ensure Deku Tree can still be opened in dungeon entrance rando even if Ghoma is defeated - if (IS_RANDO) { - if (play->sceneNum == SCENE_LOST_WOODS) { - return 1; - } - - if (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && - Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && - (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) || - Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD))) { - return play->sceneNum == SCENE_MIDOS_HOUSE && !LINK_IS_ADULT; - } - - return play->sceneNum == SCENE_KOKIRI_FOREST; - } - if (play->sceneNum == SCENE_KOKIRI_FOREST) { if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) { return 1; @@ -512,7 +490,7 @@ u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) { } if (play->sceneNum == SCENE_MIDOS_HOUSE) { - if (((Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH)) != 0) || ((Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) != 0)) { + if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) || Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) { if (!LINK_IS_ADULT) { return 1; } @@ -681,9 +659,8 @@ void EnMd_Init(Actor* thisx, PlayState* play) { this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, FAIRY_KOKIRI); if (((play->sceneNum == SCENE_KOKIRI_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) || - ((play->sceneNum == SCENE_KOKIRI_FOREST) && (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && - ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) || - (IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)))) || + ((play->sceneNum == SCENE_KOKIRI_FOREST) && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) && + CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) || ((play->sceneNum == SCENE_LOST_WOODS) && !Flags_GetEventChkInf(EVENTCHKINF_PLAYED_SARIAS_SONG_FOR_MIDO_AS_ADULT))) { this->actor.home.pos = this->actor.world.pos; this->actionFunc = func_80AAB948; @@ -745,10 +722,11 @@ void func_80AAB948(EnMd* this, PlayState* play) { this->skelAnime.playSpeed = CLAMP(temp, 1.0f, 3.0f); } - if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || - IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) && - Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && + if ( + (GameInteractor_Should(GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, this->interactInfo.talkState == NPC_TALK_STATE_ACTION, this) && play->sceneNum == SCENE_KOKIRI_FOREST) || + this->interactInfo.talkState == NPC_TALK_STATE_ACTION + ) { + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && (play->sceneNum == SCENE_KOKIRI_FOREST)) { play->msgCtx.msgMode = MSGMODE_PAUSED; } @@ -815,9 +793,7 @@ void func_80AABD0C(EnMd* this, PlayState* play) { return; } - if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) || - IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) && - Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && + if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && (play->sceneNum == SCENE_KOKIRI_FOREST)) { Message_CloseTextbox(play); Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH); diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index 989b90c96..64510807c 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -6,7 +6,7 @@ #include "z_en_mk.h" #include "objects/object_mk/object_mk.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -93,37 +93,24 @@ void func_80AACA40(EnMk* this, PlayState* play) { } void func_80AACA94(EnMk* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play) != 0) { + if (Actor_HasParent(&this->actor, play) != 0 || !GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; - if (!IS_RANDO) { + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); + if (GameInteractor_Should(GI_VB_TRADE_TIMER_EYEDROPS, true, NULL)) { func_80088AA0(240); gSaveContext.eventInf[1] &= ~1; } } else { - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); - Randomizer_ConsumeAdultTradeItem(play, ITEM_FROG); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); - } else { - s32 getItemID = GI_EYEDROPS; - func_8002F434(&this->actor, play, getItemID, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } void func_80AACB14(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACA94; - if (IS_RANDO) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); - Randomizer_ConsumeAdultTradeItem(play, ITEM_FROG); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); - } else { - s32 getItemID = GI_EYEDROPS; - func_8002F434(&this->actor, play, getItemID, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f); } } } @@ -150,7 +137,7 @@ void func_80AACC04(EnMk* this, PlayState* play) { if (this->timer > 0) { this->timer--; } else { - this->timer = IS_RANDO ? 0 : 16; + this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; this->actionFunc = func_80AACBAC; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); @@ -163,7 +150,7 @@ void func_80AACCA0(EnMk* this, PlayState* play) { this->timer--; this->actor.shape.rot.y += 0x800; } else { - this->timer = IS_RANDO ? 0 : 120; + this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 120 : 0; this->actionFunc = func_80AACC04; Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f); @@ -179,7 +166,7 @@ void func_80AACD48(EnMk* this, PlayState* play) { this->actionFunc = func_80AACCA0; play->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; - this->timer = IS_RANDO ? 0 : 16; + this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); this->flags &= ~2; @@ -213,29 +200,20 @@ void func_80AACEE8(EnMk* this, PlayState* play) { } void func_80AACFA0(EnMk* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; Flags_SetItemGetInf(ITEMGETINF_10); } else { - // not sure when/how/if this is getting called - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); } } void func_80AAD014(EnMk* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { this->actionFunc = func_80AACFA0; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f); } } @@ -255,9 +233,9 @@ void EnMk_Wait(EnMk* this, PlayState* play) { player->actor.textId = this->actor.textId; this->actionFunc = func_80AACA40; } else { - // Skip eye drop text on rando if Link went in the water, so you can still receive the dive check - if (INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS && - (!IS_RANDO || this->swimFlag == 0)) { + if (GameInteractor_Should(GI_VB_USE_EYEDROP_DIALOGUE, ( + INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS + ), this)) { player->actor.textId = 0x4032; this->actionFunc = func_80AACA40; } else { diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index f89644847..244be5cde 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -6,6 +6,7 @@ #include "z_en_ms.h" #include "objects/object_ms/object_ms.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -18,7 +19,6 @@ void EnMs_SetOfferText(EnMs* this, PlayState* play); void EnMs_Wait(EnMs* this, PlayState* play); void EnMs_Talk(EnMs* this, PlayState* play); void EnMs_Sell(EnMs* this, PlayState* play); -void EnMs_Sell_Rando(EnMs* this, PlayState* play); void EnMs_TalkAfterPurchase(EnMs* this, PlayState* play); const ActorInit En_Ms_InitVars = { @@ -50,10 +50,6 @@ static s16 sPrices[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, }; -static s16 sRandoPrices[] = { - 10, 20, 30, 40, 50, 60, 70, 80, 90, 99, -}; - static u16 sOfferTextIDs[] = { 0x405E, 0x405F, 0x4060, 0x4061, 0x4062, 0x4063, 0x4064, 0x4065, 0x4066, 0x4067, }; @@ -132,30 +128,16 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } else if (Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // yes - //Randomizer Mechanic: Magic bean salesman - if (IS_RANDO){ - if (gSaveContext.rupees < ((Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? 60 : sRandoPrices[BEANS_BOUGHT])) { - Message_ContinueTextbox(play, 0x4069); // TEXT_BEAN_SALESMAN_NOT_ENOUGH_MONEY - return; - } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)){ - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f); - } else { - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); - } - this->actionFunc = EnMs_Sell_Rando; - return; - } else { // vanilla code - if(gSaveContext.rupees < sPrices[BEANS_BOUGHT]){ - Message_ContinueTextbox(play, 0x4069); // TEXT_BEAN_SALESMAN_NOT_ENOUGH_MONEY - return; - } - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); - this->actionFunc = EnMs_Sell; + if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, (gSaveContext.rupees >= sPrices[BEANS_BOUGHT]), this)) { + Message_ContinueTextbox(play, 0x4069); // not enough rupees text return; } - //Randomizer Mechanic end + + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + this->actionFunc = EnMs_Sell; + } + return; case 1: // no Message_ContinueTextbox(play, 0x4068); default: @@ -164,34 +146,13 @@ void EnMs_Talk(EnMs* this, PlayState* play) { } } -void EnMs_Sell_Rando(EnMs* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { - Rupees_ChangeBy((Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sRandoPrices[BEANS_BOUGHT]); - this->actor.parent = NULL; - this->actionFunc = (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase; - } else { - if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN); - gSaveContext.pendingSale = itemEntry.itemId; - gSaveContext.pendingSaleMod = itemEntry.modIndex; - GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f); - BEANS_BOUGHT = 10; - } else { - GetItemEntry entry = ItemTable_Retrieve(GI_BEAN); - gSaveContext.pendingSaleMod = entry.modIndex; - gSaveContext.pendingSale = entry.itemId; - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); - } - } -} - void EnMs_Sell(EnMs* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]); this->actor.parent = NULL; this->actionFunc = EnMs_TalkAfterPurchase; } else { - func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_BEAN, 90.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h index 70b105073..e626056f0 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.h @@ -18,4 +18,7 @@ typedef struct EnMs { /* 0x024C */ s16 activeTimer; } EnMs; // size = 0x0250 +void EnMs_TalkAfterPurchase(EnMs* enMs, PlayState* play); +void EnMs_Wait(EnMs* enMs, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c index a519209aa..9a3990cf8 100644 --- a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c +++ b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c @@ -8,6 +8,7 @@ #include "vt.h" #include "objects/object_nb/object_nb.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -326,7 +327,9 @@ void EnNb_GiveMedallion(EnNb* this, PlayState* play) { Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0xC); - Item_Give(play, ITEM_MEDALLION_SPIRIT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SPIRIT); + } } void EnNb_ComeUpImpl(EnNb* this, PlayState* play) { @@ -342,7 +345,9 @@ void EnNb_SetupChamberCsImpl(EnNb* this, PlayState* play) { this->action = NB_CHAMBER_UNDERGROUND; play->csCtx.segment = &D_80AB431C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_SPIRIT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_SPIRIT); + } player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000; } } diff --git a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c index 91730e5bf..0497b82e9 100644 --- a/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c +++ b/soh/src/overlays/actors/ovl_En_Niw/z_en_niw.c @@ -467,7 +467,7 @@ void func_80AB6450(EnNiw* this, PlayState* play) { this->actionFunc = func_80AB6BF8; } else { // GI_NONE in this case allows the player to lift the actor - func_8002F434(&this->actor, play, GI_NONE, 25.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 25.0f, 10.0f); func_80AB5BF8(this, play, 1); } } diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index 8ddf52fad..612abcf0e 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -3,7 +3,7 @@ #include "objects/object_os_anime/object_os_anime.h" #include "overlays/actors/ovl_En_Niw/z_en_niw.h" #include "vt.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -204,7 +204,9 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) { EnNiw* currentCucco; s32 phi_s1; - this->cuccosInPen = IS_RANDO ? (7 - Randomizer_GetSettingValue(RSK_CUCCO_COUNT)) : 0; + if (GameInteractor_Should(GI_VB_SET_CUCCO_COUNT, true, this)) { + this->cuccosInPen = 0; + } currentCucco = (EnNiw*)play->actorCtx.actorLists[ACTORCAT_PROP].head; while (currentCucco != NULL) { if (currentCucco->actor.id == ACTOR_EN_NIW) { @@ -239,9 +241,11 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) { phi_s1 = 7; } } + // Completed minigame and then threw Cucco(s) out of the pen if ((this->unk_26C != 0) && (phi_s1 < 7)) { phi_s1 = 9; } + this->actor.textId = sMissingCuccoTextIds[phi_s1]; if (Text_GetFaceReaction(play, 8) != 0) { this->actor.textId = Text_GetFaceReaction(play, 8); @@ -308,20 +312,22 @@ void func_80ABA654(EnNiwLady* this, PlayState* play) { if (!Flags_GetItemGetInf(ITEMGETINF_0C)) { this->actor.parent = NULL; - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, true, this)) { this->getItemId = GI_BOTTLE; - func_8002F434(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f); } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_CHILD, GI_BOTTLE); - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 100.0f, 50.0f); + // Circumvent the item offer action + this->actionFunc = func_80ABAC84; + return; } this->actionFunc = func_80ABAC00; return; + } if (this->unk_26C == 1) { this->getItemId = GI_RUPEE_PURPLE; - func_8002F434(&this->actor, play, GI_RUPEE_PURPLE, 100.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_RUPEE_PURPLE, 100.0f, 50.0f); this->actionFunc = func_80ABAC00; } this->actionFunc = func_80ABA244; @@ -398,15 +404,15 @@ void func_80ABA9B8(EnNiwLady* this, PlayState* play) { Message_CloseTextbox(play); this->actor.parent = NULL; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f); + this->actionFunc = func_80ABAC00; } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f); - Flags_SetItemGetInf(ITEMGETINF_2C); + // Circumvent the item offer action + this->actionFunc = func_80ABAC84; + return; } - this->actionFunc = func_80ABAC00; break; case 1: this->actor.textId = sTradeItemTextIds[3]; @@ -433,15 +439,14 @@ void func_80ABAB08(EnNiwLady* this, PlayState* play) { case 0: Message_CloseTextbox(play); this->actor.parent = NULL; - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_COJIRO, 200.0f, 100.0f); + if (GameInteractor_Should(GI_VB_TRADE_POCKET_CUCCO, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_COJIRO, 200.0f, 100.0f); + this->actionFunc = func_80ABAC00; } else { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO); - Randomizer_ConsumeAdultTradeItem(play, ITEM_POCKET_CUCCO); - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f); - Flags_SetItemGetInf(ITEMGETINF_2E); + // Circumvent the item offer action + this->actionFunc = func_80ABAC84; + return; } - this->actionFunc = func_80ABAC00; break; case 1: Message_CloseTextbox(play); @@ -462,17 +467,11 @@ void func_80ABAC00(EnNiwLady* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = func_80ABAC84; } else { - if (IS_RANDO) { - getItemId = this->getItemEntry.getItemId; - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f); - return; - } - getItemId = this->getItemId; if (LINK_IS_ADULT) { getItemId = !Flags_GetItemGetInf(ITEMGETINF_2C) ? GI_POCKET_EGG : GI_COJIRO; } - func_8002F434(&this->actor, play, getItemId, 200.0f, 100.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 200.0f, 100.0f); } } @@ -482,8 +481,7 @@ void func_80ABAC84(EnNiwLady* this, PlayState* play) { } osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (LINK_IS_ADULT) { - // Flags for randomizer gives are set in the original message prompt choice handling - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, true, this)) { if (!Flags_GetItemGetInf(ITEMGETINF_2C)) { Flags_SetItemGetInf(ITEMGETINF_2C); } else { diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index 8cb491da4..2a811ee9a 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -8,6 +8,7 @@ #include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" #include "scenes/overworld/spot02/spot02_scene.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #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->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) { 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->actor.xzDistToPlayer < (90.0f + this->interactRange)) && (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) { this->actionFunc = func_80ABF28C; } 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) { Flags_SetSwitch(play, this->switchFlag); } switch (this->type) { - case 1: + case 1: // Zora's River Waterfall Flags_SetSwitch(play, this->switchFlag); Flags_SetEventChkInf(EVENTCHKINF_OPENED_ZORAS_DOMAIN); break; - case 2: - if (!IS_RANDO) { + case 2: // Kakariko Windmill + if (GameInteractor_Should(GI_VB_PLAY_DRAIN_WELL_CS, true, this)) { play->csCtx.segment = D_80ABF9D0; 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); break; - case 4: - if (IS_RANDO) { - 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 { + case 4: // Door of Time + if (GameInteractor_Should(GI_VB_PLAY_DOOR_OF_TIME_CS, true, this)) { play->csCtx.segment = D_80ABFB40; gSaveContext.cutsceneTrigger = 1; } break; - case 6: - // Don't start the cutscene in a rando save. - if (!(IS_RANDO)) { + case 6: // Royal Family Tomb + if (GameInteractor_Should(GI_VB_PLAY_ROYAL_FAMILY_TOMB_CS, true, this)) { play->csCtx.segment = LINK_IS_ADULT ? SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_003C80) : SEGMENTED_TO_VIRTUAL(&spot02_scene_Cs_005020); gSaveContext.cutsceneTrigger = 1; @@ -311,7 +295,7 @@ void func_80ABF708(EnOkarinaTag* this, PlayState* play) { yawDiff = this->actor.yawTowardsPlayer - this->actor.world.rot.y; this->unk_15A++; 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; } 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) { // "Open sesame sesame!" osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 開けゴマゴマゴマ! ☆☆☆☆☆ %d\n" VT_RST, Message_GetState(&play->msgCtx)); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(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); gSaveContext.cutsceneTrigger = 1; - } else if (IS_RANDO && !Flags_GetTreasure(play, 0x1F)) { - GivePlayerRandoRewardSunSong(this, play, RC_SONG_FROM_ROYAL_FAMILYS_TOMB); } this->actionFunc = func_80ABF708; } diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 34ef24e40..afa825e57 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -535,7 +535,7 @@ void EnOssan_TalkGoronShopkeeper(PlayState* play) { Message_ContinueTextbox(play, 0x300F); } } else if ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) || - (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) { + (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP))) { Message_ContinueTextbox(play, 0x3057); } else { Message_ContinueTextbox(play, 0x305B); @@ -1389,7 +1389,7 @@ void EnOssan_GiveItemWithFanfare(PlayState* play, EnOssan* this) { osSyncPrintf("\n" VT_FGCOL(YELLOW) "初めて手にいれた!!" VT_RST "\n\n"); if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } else { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); // en_ossan/en_girla are also used for the happy mask shop, which never has randomized items @@ -1398,7 +1398,7 @@ void EnOssan_GiveItemWithFanfare(PlayState* play, EnOssan* this) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 120.0f); } else { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } } play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; @@ -1736,7 +1736,7 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, PlayState* play, Player* p return; } if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } else { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); // en_ossan/en_girla are also used for the happy mask shop, which never has randomized items @@ -1746,7 +1746,7 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, PlayState* play, Player* p Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 120.0f); } else { - func_8002F434(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); + Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); } } } diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c index 303c58819..d46424b0b 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -10,6 +10,7 @@ #include "scenes/overworld/spot16/spot16_scene.h" #include "vt.h" #include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -42,6 +43,7 @@ void func_80ACAF74(EnOwl* this, PlayState* play); void func_80ACC30C(EnOwl* this, PlayState* play); void func_80ACB4FC(EnOwl* this, PlayState* play); void func_80ACB680(EnOwl* this, PlayState* play); +void func_80ACA62C(EnOwl* this, PlayState* play); void func_80ACC460(EnOwl* this); void func_80ACBEA0(EnOwl*, PlayState*); @@ -137,9 +139,7 @@ void EnOwl_Init(Actor* thisx, PlayState* play) { // "conversation owl %4x no = %d, sv = %d" osSyncPrintf(VT_FGCOL(CYAN) " 会話フクロウ %4x no = %d, sv = %d\n" VT_RST, this->actor.params, owlType, switchFlag); - if (((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(play, switchFlag)) || - // Owl shortcuts at SPOT06: Lake Hylia and SPOT16: Death Mountain Trail - (IS_RANDO && !(play->sceneNum == SCENE_LAKE_HYLIA || play->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL))) { + if ((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(play, switchFlag)) { osSyncPrintf("savebitでフクロウ退避\n"); // "Save owl with savebit" Actor_Kill(&this->actor); return; @@ -283,7 +283,7 @@ s32 EnOwl_CheckInitTalk(EnOwl* this, PlayState* play, u16 textId, f32 targetDist } else { this->actor.textId = textId; distCheck = (flags & 2) ? 200.0f : 1000.0f; - if (this->actor.xzDistToPlayer < targetDist) { + if (GameInteractor_Should(GI_VB_OWL_INTERACTION, this->actor.xzDistToPlayer < targetDist, this)) { this->actor.flags |= ACTOR_FLAG_WILL_TALK; func_8002F1C4(&this->actor, play, targetDist, distCheck, 0); } @@ -345,7 +345,7 @@ void func_80ACA71C(EnOwl* this) { } void func_80ACA76C(EnOwl* this, PlayState* play) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); if (Actor_TextboxIsClosing(&this->actor, play)) { Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF); @@ -355,7 +355,7 @@ void func_80ACA76C(EnOwl* this, PlayState* play) { } void func_80ACA7E0(EnOwl* this, PlayState* play) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); if (Actor_TextboxIsClosing(&this->actor, play)) { Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF); @@ -565,7 +565,7 @@ void EnOwl_WaitLakeHylia(EnOwl* this, PlayState* play) { } void func_80ACB03C(EnOwl* this, PlayState* play) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); if (Actor_TextboxIsClosing(&this->actor, play)) { Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_FANFARE << 24 | 0xFF); diff --git a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h index 7a20eaa3a..a898dce2a 100644 --- a/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h +++ b/soh/src/overlays/actors/ovl_En_Owl/z_en_owl.h @@ -43,4 +43,6 @@ typedef struct EnOwl { /* 0x0410 */ OwlFunc unk_410; } EnOwl; // size = 0x0414 +void func_80ACA62C(EnOwl* enOwl, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c index ea324c5a5..280640efd 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c @@ -183,12 +183,6 @@ void EnPoSisters_Init(Actor* thisx, PlayState* play) { this->epoch++; - // Skip Poe Intro Cutscene - if (IS_RANDO && thisx->params == 4124 && !Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) { - Flags_SetSwitch(play, 0x1B); - Actor_Kill(thisx); - } - Actor_ProcessInitChain(&this->actor, sInitChain); ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 50.0f); SkelAnime_Init(play, &this->skelAnime, &gPoeSistersSkel, &gPoeSistersSwayAnim, this->jointTable, @@ -862,11 +856,6 @@ void func_80ADB338(EnPoSisters* this, PlayState* play) { if (Actor_WorldDistXZToPoint(&player->actor, &this->actor.home.pos) < 600.0f) { if (this->unk_19C != 0) { this->unk_19C--; - - // Force Meg to respawn instantly after getting hit - if (IS_RANDO) { - this->unk_19C = 0; - } } } else { this->unk_19C = 100; diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h index 2bd780983..5f42856a4 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.h @@ -32,4 +32,6 @@ typedef struct EnPoSisters { u32 epoch; } EnPoSisters; // size = 0x0338 +void func_80ADB338(EnPoSisters* enPoSisters, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c index 73996d58f..eafa8b82e 100644 --- a/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c +++ b/soh/src/overlays/actors/ovl_En_Rl/z_en_rl.c @@ -7,6 +7,7 @@ #include "z_en_rl.h" #include "vt.h" #include "objects/object_rl/object_rl.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -126,7 +127,9 @@ void func_80AE7590(EnRl* this, PlayState* play) { pos.y = player->actor.world.pos.y + 80.0f; pos.z = player->actor.world.pos.z; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true); - Item_Give(play, ITEM_MEDALLION_LIGHT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_LIGHT); + } this->lightMedallionGiven = 1; } } diff --git a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c index fe4a77724..93d1fd99c 100644 --- a/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c +++ b/soh/src/overlays/actors/ovl_En_Ru2/z_en_ru2.c @@ -8,6 +8,7 @@ #include "objects/object_ru2/object_ru2.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -260,7 +261,9 @@ void func_80AF2A38(EnRu2* this, PlayState* play) { f32 posZ = player->actor.world.pos.z; Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 10); - Item_Give(play, ITEM_MEDALLION_WATER); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_WATER); + } } void func_80AF2AB4(EnRu2* this, PlayState* play) { @@ -273,7 +276,9 @@ void func_80AF2AB4(EnRu2* this, PlayState* play) { this->action = 1; play->csCtx.segment = &D_80AF411C; gSaveContext.cutsceneTrigger = 2; - Item_Give(play, ITEM_MEDALLION_WATER); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) { + Item_Give(play, ITEM_MEDALLION_WATER); + } temp = this->actor.world.rot.y + 0x8000; player->actor.shape.rot.y = temp; player->actor.world.rot.y = temp; diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c index 9e09a705c..f2b2db3f9 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.c @@ -3,6 +3,7 @@ #include "objects/object_sa/object_sa.h" #include "scenes/overworld/spot04/spot04_scene.h" #include "scenes/overworld/spot05/spot05_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA) @@ -390,13 +391,10 @@ s32 func_80AF5DFC(EnSa* this, PlayState* play) { return 1; } if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW && (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER))) { - if (IS_RANDO) { - return 5; - } - return CHECK_QUEST_ITEM(QUEST_SONG_SARIA) ? 2 : 5; + return GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, !CHECK_QUEST_ITEM(QUEST_SONG_SARIA), NULL) ? 5 : 2; } if (play->sceneNum == SCENE_KOKIRI_FOREST && !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { - if (Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) { + if (GameInteractor_Should(GI_VB_NOT_BE_GREETED_BY_SARIA, Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA), NULL)) { return 1; } return 4; @@ -622,28 +620,17 @@ void func_80AF67D0(EnSa* this, PlayState* play) { } } -void GivePlayerRandoRewardSaria(EnSa* saria, PlayState* play, RandomizerCheck check) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SARIAS_SONG); - if (saria->actor.parent != NULL && saria->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1F)) { - Flags_SetTreasure(play, 0x1F); - } else if (!Flags_GetTreasure(play, 0x1F)) { - GiveItemEntryFromActor(&saria->actor, play, getItemEntry, 10000.0f, 100.0f); - } -} - void func_80AF683C(EnSa* this, PlayState* play) { Player* player = GET_PLAYER(play); if (!(player->actor.world.pos.z >= -2220.0f) && !Play_InCsMode(play)) { - if (IS_RANDO) { - GivePlayerRandoRewardSaria(this, play, RC_SONG_FROM_SARIA); - return; + // SOH [General] This flag was previously unused, but was named accordingly so we will make use of it. (Normally we should opt for soh_inf) + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG); + if (GameInteractor_Should(GI_VB_PLAY_SARIAS_SONG_CS, true, this)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730); + gSaveContext.cutsceneTrigger = 1; + this->actionFunc = func_80AF68E4; } - - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730); - gSaveContext.cutsceneTrigger = 1; - this->actionFunc = func_80AF68E4; } } @@ -721,7 +708,9 @@ void func_80AF68E4(EnSa* this, PlayState* play) { void func_80AF6B20(EnSa* this, PlayState* play) { if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW) { - Item_Give(play, ITEM_SONG_SARIA); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) { + Item_Give(play, ITEM_SONG_SARIA); + } EnSa_ChangeAnim(this, ENSA_ANIM1_6); } diff --git a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h index 2965f04ab..56d368f13 100644 --- a/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h +++ b/soh/src/overlays/actors/ovl_En_Sa/z_en_sa.h @@ -30,4 +30,6 @@ typedef struct EnSa { /* 0x0286 */ Vec3s morphTable[17]; } EnSa; // size = 0x02EC +void func_80AF6B20(EnSa* enSa, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c index 6f48314ff..0f300d16f 100644 --- a/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c +++ b/soh/src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.c @@ -1,5 +1,6 @@ #include "z_en_shopnuts.h" #include "objects/object_shopnuts/object_shopnuts.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE) @@ -69,18 +70,11 @@ void EnShopnuts_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); Collider_UpdateCylinder(&this->actor, &this->collider); - if (IS_RANDO) { - s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); - ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(play->sceneNum, this->actor.params, respawnData); - - if (scrubIdentity.isShuffled && Flags_GetRandomizerInf(scrubIdentity.randomizerInf)) { - Actor_Kill(&this->actor); - } - } - - if (((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || + if (GameInteractor_Should(GI_VB_BUSINESS_SCRUB_DESPAWN, + ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) || ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) || - ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))) { + ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))), + this)) { Actor_Kill(&this->actor); } else { EnShopnuts_SetupWait(this); diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 943a2fbb0..8eb669d2d 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -7,28 +7,17 @@ #include "z_en_si.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" -extern void func_8083C148(Player*, PlayState*); -extern void func_80078884(uint16_t); - #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOOKSHOT_DRAGS) void EnSi_Init(Actor* thisx, PlayState* play); void EnSi_Destroy(Actor* thisx, PlayState* play); void EnSi_Update(Actor* thisx, PlayState* play); void EnSi_Draw(Actor* thisx, PlayState* play); -void EnSi_Reset(); s32 func_80AFB748(EnSi* this, PlayState* play); void func_80AFB768(EnSi* this, PlayState* play); void func_80AFB89C(EnSi* this, PlayState* play); void func_80AFB950(EnSi* this, PlayState* play); -void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play); -void Randomizer_GiveSkullReward(EnSi* this, PlayState* play); - -s32 textId = 0xB4; -s32 giveItemId = ITEM_SKULL_TOKEN; -s32 getItemId; -GetItemEntry getItem; static ColliderCylinderInit sCylinderInit = { { @@ -62,7 +51,7 @@ const ActorInit En_Si_InitVars = { (ActorFunc)EnSi_Destroy, (ActorFunc)EnSi_Update, (ActorFunc)EnSi_Draw, - (ActorResetFunc)EnSi_Reset, + NULL, }; void EnSi_Init(Actor* thisx, PlayState* play) { @@ -105,36 +94,12 @@ void func_80AFB768(EnSi* this, PlayState* play) { if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; - - if (IS_RANDO) { - Randomizer_UpdateSkullReward(this, play); - } else { - Item_Give(play, giveItemId); - } - if ((!CVarGetInteger("gSkulltulaFreeze", 0) || giveItemId != ITEM_SKULL_TOKEN) && - getItemId != RG_ICE_TRAP) { - player->actor.freezeTimer = 20; - } - - if (getItemId == RG_ICE_TRAP && Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + Item_Give(play, ITEM_SKULL_TOKEN); player->actor.freezeTimer = 10; - } - - Message_StartTextbox(play, textId, NULL); - - if (IS_RANDO) { - if (getItemId != RG_ICE_TRAP) { - Randomizer_GiveSkullReward(this, play); - Audio_PlayFanfare_Rando(getItem); - } else { - gSaveContext.pendingIceTrapCount++; - Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); - } - } else { + Message_StartTextbox(play, 0xB4, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); } - - player->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = func_80AFB950; } else { Collider_UpdateCylinder(&this->actor, &this->collider); @@ -147,32 +112,18 @@ void func_80AFB768(EnSi* this, PlayState* play) { void func_80AFB89C(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); + Math_SmoothStepToF(&this->actor.scale.x, 0.25f, 0.4f, 1.0f, 0.0f); Actor_SetScale(&this->actor, this->actor.scale.x); this->actor.shape.rot.y += 0x400; if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_HOOKSHOT_ATTACHED)) { - if (IS_RANDO) { - Randomizer_UpdateSkullReward(this, play); - } else { - Item_Give(play, giveItemId); - } - - Message_StartTextbox(play, textId, NULL); - - if (IS_RANDO) { - if (getItemId != RG_ICE_TRAP) { - Randomizer_GiveSkullReward(this, play); - Audio_PlayFanfare_Rando(getItem); - } else { - gSaveContext.pendingIceTrapCount++; - Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); - } - } else { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { + Item_Give(play, ITEM_SKULL_TOKEN); + player->actor.freezeTimer = 10; + Message_StartTextbox(play, 0xB4, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); } - - player->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->actionFunc = func_80AFB950; } } @@ -180,19 +131,12 @@ void func_80AFB89C(EnSi* this, PlayState* play) { void func_80AFB950(EnSi* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && - (!CVarGetInteger("gSkulltulaFreeze", 0) || getItemId == RG_ICE_TRAP || giveItemId != ITEM_SKULL_TOKEN)) { + if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) { player->actor.freezeTimer = 10; } else { SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF); GameInteractor_ExecuteOnFlagSet(FLAG_GS_TOKEN, this->actor.params); Actor_Kill(&this->actor); - if (gSaveContext.pendingIceTrapCount > 0 && player->heldItemId == 11) { - player->actor.freezeTimer = 0; - func_8083C148(GET_PLAYER(play), play); - func_80078884(NA_SE_SY_CAMERA_ZOOM_UP); - player->yaw = player->actor.shape.rot.y; - } } } @@ -211,49 +155,6 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (this->actionFunc != func_80AFB950) { func_8002ED80(&this->actor, play, 0); func_8002EBCC(&this->actor, play, 0); - if (!IS_RANDO) { - GetItem_Draw(play, GID_SKULL_TOKEN_2); - } else { - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); - EnItem00_CustomItemsParticles(&this->actor, play, getItem); - if (getItem.itemId != ITEM_SKULL_TOKEN) { - f32 mtxScale = 1.5f; - Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - } - GetItemEntry_Draw(play, getItem); - } - } -} - -void EnSi_Reset() { - textId = 0xB4; - giveItemId = ITEM_SKULL_TOKEN; -} - -void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); - getItemId = getItem.getItemId; - if (getItemId == RG_ICE_TRAP) { - textId = 0xF8; - } else { - textId = getItem.textId; - giveItemId = getItem.itemId; - } - player->getItemEntry = getItem; -} - -void Randomizer_GiveSkullReward(EnSi* this, PlayState* play) { - Player* player = GET_PLAYER(play); - - if (getItem.modIndex == MOD_NONE) { - // RANDOTOD: Move this into Item_Give() or some other more central location - if (getItem.getItemId == GI_SWORD_BGS) { - gSaveContext.bgsFlag = true; - } - Item_Give(play, giveItemId); - } else if (getItem.modIndex == MOD_RANDOMIZER) { - Randomizer_Item_Give(play, getItem); + GetItem_Draw(play, GID_SKULL_TOKEN_2); } } diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.h b/soh/src/overlays/actors/ovl_En_Si/z_en_si.h index dc0a3b400..318876289 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.h +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.h @@ -13,6 +13,9 @@ typedef struct EnSi { /* 0x014C */ EnSiActionFunc actionFunc; /* 0x0150 */ ColliderCylinder collider; /* 0x019C */ u8 unk_19C; + // #region SOH [Randomizer] Caching the get item entry for the draw function for performance + /* */ GetItemEntry sohGetItemEntry; + // #endregion } EnSi; // size = 0x01A0 #endif diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c index 67c695872..94df7a49f 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.c @@ -1039,11 +1039,8 @@ void EnSkj_SariaSongTalk(EnSkj* this, PlayState* play) { EnSkj_SetupWaitInRange(this); } else { func_80AFFE24(this); - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } } @@ -1054,15 +1051,12 @@ void func_80AFFE24(EnSkj* this) { } void func_80AFFE44(EnSkj* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { this->actor.parent = NULL; EnSkj_SetupPostSariasSong(this); } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_SKULL_KID, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { + Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, EnSkj_GetItemXzRange(this), EnSkj_GetItemYRange(this)); } } } @@ -1072,7 +1066,7 @@ void EnSkj_SetupPostSariasSong(EnSkj* this) { } void EnSkj_ChangeModeAfterSong(EnSkj* this, PlayState* play) { - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG, true, this)) { Flags_SetItemGetInf(ITEMGETINF_16); EnSkj_SetNaviId(this); EnSkj_SetupWaitInRange(this); @@ -1086,7 +1080,7 @@ void EnSkj_SetupMaskTrade(EnSkj* this) { void EnSkj_StartMaskTrade(EnSkj* this, PlayState* play) { u8 sp1F = Message_GetState(&play->msgCtx); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); if ((sp1F == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { EnSkj_JumpFromStump(this); } @@ -1184,7 +1178,7 @@ void EnSkj_SetupWaitForMaskTextClear(EnSkj* this) { void EnSkj_WaitForMaskTextClear(EnSkj* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->backflipFlag = 1; EnSkj_Backflip(this); } @@ -1547,7 +1541,9 @@ void EnSkj_WaitForOfferResponse(EnSkj* this, PlayState* play) { void EnSkj_WonOcarinaMiniGame(EnSkj* this, PlayState* play) { if (D_80B01EA0) { - this->actionFunc = EnSkj_WaitToGiveReward; + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_OCARINA_MEMORY_GAME, true, this)) { + this->actionFunc = EnSkj_WaitToGiveReward; + } } else { func_8002F2CC(&this->actor, play, 26.0f); } @@ -1555,13 +1551,8 @@ void EnSkj_WonOcarinaMiniGame(EnSkj* this, PlayState* play) { void EnSkj_WaitToGiveReward(EnSkj* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - if (IS_RANDO && gSaveContext.ocarinaGameRoundNum != 3) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 26.0f, 26.0f); - } else { - func_8002F434(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); - } - + Actor_OfferGetItem(&this->actor, play, + sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); this->actionFunc = EnSkj_GiveOcarinaGameReward; } } @@ -1571,12 +1562,8 @@ void EnSkj_GiveOcarinaGameReward(EnSkj* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = EnSkj_FinishOcarinaGameRound; } else { - if (IS_RANDO && gSaveContext.ocarinaGameRoundNum != 3) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_OCARINA_MEMORY_GAME, GI_HEART_PIECE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 26.0f, 26.0f); - } else { - func_8002F434(&this->actor, play, sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); - } + Actor_OfferGetItem(&this->actor, play, + sOcarinaGameRewards[gSaveContext.ocarinaGameRoundNum], 26.0f, 26.0f); } } @@ -1588,11 +1575,7 @@ void EnSkj_FinishOcarinaGameRound(EnSkj* this, PlayState* play) { gSaveContext.ocarinaGameRoundNum++; } - if (IS_RANDO) { - gSaveContext.ocarinaGameRoundNum = 3; - } - - if (ocarinaGameRoundNum == 2 || IS_RANDO) { + if (ocarinaGameRoundNum == 2) { Flags_SetItemGetInf(ITEMGETINF_17); this->actionFunc = EnSkj_CleanupOcarinaGame; } else { diff --git a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h index bc8febcd4..3f8b75ba2 100644 --- a/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h +++ b/soh/src/overlays/actors/ovl_En_Skj/z_en_skj.h @@ -37,4 +37,6 @@ typedef struct EnSkj { /* 0x02F4 */ Vec3f posCopy; } EnSkj; // size = 0x0300 +void EnSkj_CleanupOcarinaGame(EnSkj* enSkj, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c index 908a1af96..f8b50d823 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -257,66 +257,34 @@ void EnSth_ParentRewardObtainedWait(EnSth* this, PlayState* play) { void EnSth_GivePlayerItem(EnSth* this, PlayState* play) { u16 getItemId = sGetItemIds[this->actor.params]; - GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE; - - if (IS_RANDO) { - switch (getItemId) { - case GI_RUPEE_GOLD: - if (!Flags_GetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD)) { - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_100_GOLD_SKULLTULA_REWARD, GI_RUPEE_GOLD); - Flags_SetRandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD); - } - break; - case GI_WALLET_ADULT: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_10_GOLD_SKULLTULA_REWARD, GI_WALLET_ADULT); - break; - case GI_STONE_OF_AGONY: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_20_GOLD_SKULLTULA_REWARD, GI_STONE_OF_AGONY); - break; - case GI_WALLET_GIANT: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_30_GOLD_SKULLTULA_REWARD, GI_WALLET_GIANT); - break; - case GI_BOMBCHUS_10: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_40_GOLD_SKULLTULA_REWARD, GI_BOMBCHUS_10); - break; - case GI_HEART_PIECE: - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_50_GOLD_SKULLTULA_REWARD, GI_HEART_PIECE); - break; - } - getItemId = getItemEntry.getItemId; - } else { - switch (this->actor.params) { - case 1: - case 3: - switch (CUR_UPG_VALUE(UPG_WALLET)) { - case 0: - getItemId = GI_WALLET_ADULT; - break; - case 1: - getItemId = GI_WALLET_GIANT; - break; - } - break; - } + switch (this->actor.params) { + case 1: + case 3: + switch (CUR_UPG_VALUE(UPG_WALLET)) { + case 0: + getItemId = GI_WALLET_ADULT; + break; + + case 1: + getItemId = GI_WALLET_GIANT; + break; + } + break; } - if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 10000.0f, 50.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, getItemId, 10000.0f, 50.0f); } void EnSth_GiveReward(EnSth* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { this->actor.parent = NULL; EnSth_SetupAction(this, EnSth_RewardObtainedTalk); gSaveContext.eventChkInf[EVENTCHKINF_SKULLTULA_REWARD_INDEX] |= this->eventFlag; if (this->eventFlag != 0) { GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SKULLTULA_REWARD_INDEX << 4) + sEventFlagsShift[this->actor.params]); } - } else { + } else if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { EnSth_GivePlayerItem(this, play); } EnSth_FacePlayer(this, play); @@ -326,7 +294,9 @@ void EnSth_RewardUnobtainedTalk(EnSth* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); EnSth_SetupAction(this, EnSth_GiveReward); - EnSth_GivePlayerItem(this, play); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SKULLTULA_REWARD, true, this)) { + EnSth_GivePlayerItem(this, play); + } } EnSth_FacePlayer(this, play); } diff --git a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h index 9391496ae..c0001f955 100644 --- a/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h +++ b/soh/src/overlays/actors/ovl_En_Sth/z_en_sth.h @@ -25,4 +25,6 @@ typedef struct EnSth { /* 0x02B8 */ EnSthActionFunc actionFunc; } EnSth; // size = 0x02BC +void EnSth_RewardObtainedTalk(EnSth* enSth, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 6ab91ddc0..a406049a9 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -4,6 +4,7 @@ #include "objects/object_ossan/object_ossan.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_LOCKON) @@ -180,7 +181,6 @@ void EnSyatekiMan_Init(Actor* thisx, PlayState* play) { this->blinkFunc = EnSyatekiMan_BlinkWait; this->actor.colChkInfo.cylRadius = 100; this->actionFunc = EnSyatekiMan_Start; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; } void EnSyatekiMan_Destroy(Actor* thisx, PlayState* play) { @@ -355,11 +355,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->tempGallery = this->actor.parent; this->actor.parent = NULL; if (!LINK_IS_ADULT) { - if(IS_RANDO && !Flags_GetTreasure(play, 0x1E)) { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_SHOOTING_GALLERY_REWARD, GI_BULLET_BAG_50); - this->getItemId = this->getItemEntry.getItemId; - Flags_SetTreasure(play, 0x1E); - } else if (!IS_RANDO && !Flags_GetItemGetInf(ITEMGETINF_0D)) { + if (!Flags_GetItemGetInf(ITEMGETINF_0D)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Pachinko ☆☆☆☆☆ %d\n" VT_RST, CUR_UPG_VALUE(UPG_BULLET_BAG)); if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { @@ -368,16 +364,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->getItemId = GI_BULLET_BAG_50; } } else { - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->getItemId = GI_RUPEE_PURPLE; } } else { // Only give the adult rando reward when the player has a quiver - if (IS_RANDO && !Flags_GetTreasure(play, 0x1F) && CUR_UPG_VALUE(UPG_QUIVER) > 0) { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_SHOOTING_GALLERY_REWARD, GI_QUIVER_50); - this->getItemId = this->getItemEntry.getItemId; - Flags_SetTreasure(play, 0x1F); - } else if (!IS_RANDO && !Flags_GetItemGetInf(ITEMGETINF_0E)) { + if (!Flags_GetItemGetInf(ITEMGETINF_0E)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Bow ☆☆☆☆☆ %d\n" VT_RST, CUR_UPG_VALUE(UPG_QUIVER)); switch (CUR_UPG_VALUE(UPG_QUIVER)) { @@ -392,14 +383,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { break; } } else { - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->getItemId = GI_RUPEE_PURPLE; } } - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } this->actionFunc = EnSyatekiMan_GivePrize; break; @@ -426,33 +414,26 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { } } } -} +} void EnSyatekiMan_GivePrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { this->actionFunc = EnSyatekiMan_FinishPrize; - } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); - } + } else { + Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } } void EnSyatekiMan_FinishPrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (!LINK_IS_ADULT) { Flags_SetItemGetInf(ITEMGETINF_0D); - } else if ((this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)) { + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50), this)) { Flags_SetItemGetInf(ITEMGETINF_0E); - } else if (IS_RANDO && LINK_IS_ADULT && CUR_UPG_VALUE(UPG_QUIVER) == 0) { - // In Rando without a quiver, display a message reminding the player to come back with a bow - Message_StartTextbox(play, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL); } this->gameResult = SYATEKI_RESULT_NONE; this->actor.parent = this->tempGallery; diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h index eaeec0429..b65364ae4 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h @@ -28,7 +28,6 @@ typedef struct EnSyatekiMan { /* 0x0220 */ Actor* tempGallery; /* 0x0224 */ EnSyatekiManOtherFunc blinkFunc; // Seems to be part of a blink system with unk_20C and unk_20E, but it's unused. /* 0x0228 */ s16 csCam; - /* */ GetItemEntry getItemEntry; } EnSyatekiMan; // size = 0x022C #endif diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 267a26c90..cdec042bc 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -7,6 +7,7 @@ #include "z_en_ta.h" #include "vt.h" #include "objects/object_ta/object_ta.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -15,21 +16,21 @@ void EnTa_Destroy(Actor* thisx, PlayState* play); void EnTa_Update(Actor* thisx, PlayState* play); void EnTa_Draw(Actor* thisx, PlayState* play); -void func_80B14634(EnTa* this, PlayState* play); -void func_80B146F8(EnTa* this, PlayState* play); -void func_80B14754(EnTa* this, PlayState* play); -void func_80B14C18(EnTa* this, PlayState* play); -void func_80B14CAC(EnTa* this, PlayState* play); -void func_80B14D98(EnTa* this, PlayState* play); -void func_80B154FC(EnTa* this, PlayState* play); -void func_80B16504(EnTa* this, PlayState* play); -void func_80B16608(EnTa* this, PlayState* play); -void func_80B166CC(EnTa* this); -void func_80B16700(EnTa* this); -void func_80B167C0(EnTa* this); -void func_80B167FC(EnTa* this); -void func_80B16854(EnTa* this); -void func_80B16938(EnTa* this); +void EnTa_IdleAsleepInCastle(EnTa* this, PlayState* play); +void EnTa_IdleAsleepInLonLonHouse(EnTa* this, PlayState* play); +void EnTa_IdleAsleepInKakariko(EnTa* this, PlayState* play); +void EnTa_IdleAwakeInCastle(EnTa* this, PlayState* play); +void EnTa_IdleAwakeInKakariko(EnTa* this, PlayState* play); +void EnTa_IdleAtRanch(EnTa* this, PlayState* play); +void EnTa_RunCuccoGame(EnTa* this, PlayState* play); +void EnTa_IdleSittingInLonLonHouse(EnTa* this, PlayState* play); +void EnTa_IdleAfterCuccoGameFinished(EnTa* this, PlayState* play); +void EnTa_BlinkWaitUntilNext(EnTa* this); +void EnTa_BlinkAdvanceState(EnTa* this); +void EnTa_AnimRepeatCurrent(EnTa* this); +void EnTa_AnimSleeping(EnTa* this); +void EnTa_AnimSitSleeping(EnTa* this); +void EnTa_AnimRunToEnd(EnTa* this); const ActorInit En_Ta_InitVars = { ACTOR_EN_TA, @@ -64,7 +65,7 @@ static ColliderCylinderInit sCylinderInit = { { 30, 40, 0, { 0, 0, 0 } }, }; -void func_80B13AA0(EnTa* this, EnTaActionFunc arg1, EnTaUnkFunc arg2) { +void EnTa_SetupAction(EnTa* this, EnTaActionFunc arg1, EnTaUnkFunc arg2) { this->actionFunc = arg1; this->unk_260 = arg2; } @@ -113,7 +114,7 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { this->unk_2CE = 0; this->unk_2E2 = 0; this->blinkTimer = 20; - this->unk_2B0 = func_80B166CC; + this->unk_2B0 = EnTa_BlinkWaitUntilNext; Actor_SetScale(&this->actor, 0.01f); this->actor.targetMode = 6; this->actor.velocity.y = -4.0f; @@ -128,12 +129,12 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { } else if (!LINK_IS_ADULT) { Actor_Kill(&this->actor); } else if (Flags_GetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_KAKARIKO)) { - func_80B13AA0(this, func_80B14CAC, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInKakariko, EnTa_AnimRepeatCurrent); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonStandAnim); this->currentAnimation = &gTalonStandAnim; } else { - func_80B13AA0(this, func_80B14754, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInKakariko, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -150,7 +151,7 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { Actor_Kill(&this->actor); osSyncPrintf(VT_FGCOL(CYAN) " 夜はいない \n" VT_RST); } else { - func_80B13AA0(this, func_80B14D98, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAtRanch, EnTa_AnimRepeatCurrent); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonStandAnim); this->currentAnimation = &gTalonStandAnim; @@ -162,12 +163,12 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) { Actor_Kill(&this->actor); } else if (Flags_GetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE)) { - func_80B13AA0(this, func_80B14C18, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInCastle, EnTa_AnimRepeatCurrent); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonStandAnim); this->currentAnimation = &gTalonStandAnim; } else { - func_80B13AA0(this, func_80B14634, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInCastle, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -195,19 +196,19 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { func_80B13AAC(this, play); if (gSaveContext.eventInf[0] & 0x400) { - func_80B13AA0(this, func_80B16608, func_80B16938); + EnTa_SetupAction(this, EnTa_IdleAfterCuccoGameFinished, EnTa_AnimRunToEnd); Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim) - 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim), ANIMMODE_ONCE, 0.0f); gSaveContext.eventInf[0] &= ~0x400; } else { - func_80B13AA0(this, func_80B16504, func_80B16854); + EnTa_SetupAction(this, EnTa_IdleSittingInLonLonHouse, EnTa_AnimSitSleeping); this->eyeIndex = 0; Animation_PlayOnce(&this->skelAnime, &gTalonSitSleepingAnim); this->currentAnimation = &gTalonSitSleepingAnim; } } else { - func_80B13AA0(this, func_80B146F8, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInLonLonHouse, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -215,7 +216,7 @@ void EnTa_Init(Actor* thisx, PlayState* play2) { } } } else { - func_80B13AA0(this, func_80B14634, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInCastle, EnTa_AnimSleeping); this->eyeIndex = 2; Animation_PlayOnce(&this->skelAnime, &gTalonSleepAnim); this->currentAnimation = &gTalonSleepAnim; @@ -264,22 +265,22 @@ s32 func_80B142F4(EnTa* this, PlayState* play, u16 textId) { void func_80B14398(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14754, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInKakariko, EnTa_AnimSleeping); } } void func_80B143D4(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B146F8, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInLonLonHouse, EnTa_AnimSleeping); } } void func_80B14410(EnTa* this) { if (!LINK_IS_ADULT) { - func_80B13AA0(this, func_80B14C18, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInCastle, EnTa_AnimRepeatCurrent); Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE); } else { - func_80B13AA0(this, func_80B14CAC, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInKakariko, EnTa_AnimRepeatCurrent); Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_KAKARIKO); } } @@ -296,12 +297,12 @@ void func_80B144D8(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { func_80B14410(this); this->blinkTimer = 1; - this->unk_2B0 = func_80B16700; + this->unk_2B0 = EnTa_BlinkAdvanceState; } if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) { this->eyeIndex = 1; - func_80B13AA0(this, func_80B1448C, func_80B167C0); + EnTa_SetupAction(this, func_80B1448C, EnTa_AnimRepeatCurrent); } func_80B14248(this); this->unk_2E0 |= 4; @@ -311,7 +312,7 @@ void func_80B14570(EnTa* this, PlayState* play) { this->unk_2E0 |= 4; if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B144D8, func_80B167C0); + EnTa_SetupAction(this, func_80B144D8, EnTa_AnimRepeatCurrent); this->unk_2CE = 3; this->unk_2CC = 60; Animation_PlayOnce(&this->skelAnime, &gTalonWakeUpAnim); @@ -322,11 +323,11 @@ void func_80B14570(EnTa* this, PlayState* play) { void func_80B145F8(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14634, func_80B167FC); + EnTa_SetupAction(this, EnTa_IdleAsleepInCastle, EnTa_AnimSleeping); } } -void func_80B14634(EnTa* this, PlayState* play) { +void EnTa_IdleAsleepInCastle(EnTa* this, PlayState* play) { Player* player = GET_PLAYER(play); if (Actor_ProcessTalkRequest(&this->actor, play)) { @@ -335,14 +336,14 @@ void func_80B14634(EnTa* this, PlayState* play) { switch (exchangeItemId) { case EXCH_ITEM_CHICKEN: player->actor.textId = 0x702B; - func_80B13AA0(this, func_80B14570, func_80B167C0); + EnTa_SetupAction(this, func_80B14570, EnTa_AnimRepeatCurrent); this->unk_2CC = 40; break; default: if (exchangeItemId != EXCH_ITEM_NONE) { player->actor.textId = 0x702A; } - func_80B13AA0(this, func_80B145F8, func_80B167FC); + EnTa_SetupAction(this, func_80B145F8, EnTa_AnimSleeping); break; } } else { @@ -351,15 +352,15 @@ void func_80B14634(EnTa* this, PlayState* play) { } } -void func_80B146F8(EnTa* this, PlayState* play) { +void EnTa_IdleAsleepInLonLonHouse(EnTa* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, play)) { - func_80B13AA0(this, func_80B143D4, func_80B167FC); + EnTa_SetupAction(this, func_80B143D4, EnTa_AnimSleeping); } this->actor.textId = 0x204B; func_8002F2CC(&this->actor, play, 100.0f); } -void func_80B14754(EnTa* this, PlayState* play) { +void EnTa_IdleAsleepInKakariko(EnTa* this, PlayState* play) { Player* player = GET_PLAYER(play); if (Actor_ProcessTalkRequest(&this->actor, play)) { @@ -368,14 +369,14 @@ void func_80B14754(EnTa* this, PlayState* play) { switch (exchangeItemId) { case EXCH_ITEM_POCKET_CUCCO: player->actor.textId = 0x702B; - func_80B13AA0(this, func_80B14570, func_80B167C0); + EnTa_SetupAction(this, func_80B14570, EnTa_AnimRepeatCurrent); this->unk_2CC = 40; break; default: if (exchangeItemId != EXCH_ITEM_NONE) { player->actor.textId = 0x5015; } - func_80B13AA0(this, func_80B14398, func_80B167FC); + EnTa_SetupAction(this, func_80B14398, EnTa_AnimSleeping); break; } } else { @@ -410,7 +411,7 @@ void func_80B1490C(EnTa* this, PlayState* play) { this->actor.shape.rot.y += 0xC00; if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B14898, func_80B167C0); + EnTa_SetupAction(this, func_80B14898, EnTa_AnimRepeatCurrent); this->unk_2CC = 60; } } @@ -420,7 +421,7 @@ void func_80B1496C(EnTa* this, PlayState* play) { func_80B14818(this, play); if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B1490C, func_80B167C0); + EnTa_SetupAction(this, func_80B1490C, EnTa_AnimRepeatCurrent); this->unk_2CC = 5; } } @@ -430,7 +431,7 @@ void func_80B149F4(EnTa* this, PlayState* play) { this->actor.shape.rot.y -= 0xD00; if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B1496C, func_80B167C0); + EnTa_SetupAction(this, func_80B1496C, EnTa_AnimRepeatCurrent); this->unk_2CC = 65; } } @@ -444,7 +445,7 @@ void func_80B14A54(EnTa* this, PlayState* play) { } if (this->unk_2CC == 0) { this->unk_2CC = 5; - func_80B13AA0(this, func_80B149F4, func_80B167C0); + EnTa_SetupAction(this, func_80B149F4, EnTa_AnimRepeatCurrent); } } @@ -454,7 +455,7 @@ void func_80B14AF4(EnTa* this, PlayState* play) { if (this->unk_2CC == 0) { Audio_PlayActorSound2(&this->actor, NA_SE_VO_TA_CRY_1); - func_80B13AA0(this, func_80B14A54, func_80B167C0); + EnTa_SetupAction(this, func_80B14A54, EnTa_AnimRepeatCurrent); this->unk_2CC = 65; this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; } @@ -463,10 +464,10 @@ void func_80B14AF4(EnTa* this, PlayState* play) { void func_80B14B6C(EnTa* this, PlayState* play) { if (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) { s16 csCamIdx = OnePointCutscene_Init(play, 4175, -99, &this->actor, MAIN_CAM); - func_80B13AA0(this, func_80B14AF4, func_80B167C0); + EnTa_SetupAction(this, func_80B14AF4, EnTa_AnimRepeatCurrent); this->unk_2CC = 5; Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE); - if (IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { OnePointCutscene_EndCutscene(play, csCamIdx); } Animation_PlayOnce(&this->skelAnime, &gTalonRunTransitionAnim); @@ -475,42 +476,42 @@ void func_80B14B6C(EnTa* this, PlayState* play) { this->unk_2E0 |= 1; } -void func_80B14C18(EnTa* this, PlayState* play) { +void EnTa_IdleAwakeInCastle(EnTa* this, PlayState* play) { if (func_80B142F4(this, play, 0x702C)) { - func_80B13AA0(this, func_80B14B6C, func_80B167C0); + EnTa_SetupAction(this, func_80B14B6C, EnTa_AnimRepeatCurrent); } func_80B14248(this); } void func_80B14C60(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14CAC, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAwakeInKakariko, EnTa_AnimRepeatCurrent); } this->unk_2E0 |= 1; } -void func_80B14CAC(EnTa* this, PlayState* play) { +void EnTa_IdleAwakeInKakariko(EnTa* this, PlayState* play) { if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) { if (func_80B142F4(this, play, 0x5017)) { - func_80B13AA0(this, func_80B14C60, func_80B167C0); + EnTa_SetupAction(this, func_80B14C60, EnTa_AnimRepeatCurrent); Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_KAKARIKO); } } else if (func_80B142F4(this, play, 0x5016)) { - func_80B13AA0(this, func_80B14C60, func_80B167C0); + EnTa_SetupAction(this, func_80B14C60, EnTa_AnimRepeatCurrent); } func_80B14248(this); } void func_80B14D4C(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B13AA0(this, func_80B14D98, func_80B167C0); + EnTa_SetupAction(this, EnTa_IdleAtRanch, EnTa_AnimRepeatCurrent); } this->unk_2E0 |= 1; } -void func_80B14D98(EnTa* this, PlayState* play) { +void EnTa_IdleAtRanch(EnTa* this, PlayState* play) { if (func_80B142F4(this, play, 0x2055)) { - func_80B13AA0(this, func_80B14D4C, func_80B167C0); + EnTa_SetupAction(this, func_80B14D4C, EnTa_AnimRepeatCurrent); } } @@ -550,7 +551,7 @@ void func_80B14EDC(EnTa* this, PlayState* play) { } void func_80B14F20(EnTa* this, EnTaActionFunc arg1) { - func_80B13AA0(this, arg1, func_80B16854); + EnTa_SetupAction(this, arg1, EnTa_AnimSitSleeping); this->eyeIndex = 2; Animation_Change(&this->skelAnime, &gTalonSitSleepingAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gTalonSitSleepingAnim), ANIMMODE_ONCE, -5.0f); @@ -560,7 +561,7 @@ void func_80B14F20(EnTa* this, EnTaActionFunc arg1) { void func_80B14FAC(EnTa* this, EnTaActionFunc arg1) { this->eyeIndex = 1; - func_80B13AA0(this, arg1, func_80B16938); + EnTa_SetupAction(this, arg1, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim), ANIMMODE_ONCE, -5.0f); @@ -569,7 +570,7 @@ void func_80B14FAC(EnTa* this, EnTaActionFunc arg1) { void func_80B15034(EnTa* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); } this->unk_2E0 |= 1; @@ -601,7 +602,7 @@ void func_80B15100(EnTa* this, PlayState* play) { this->unk_2E0 &= ~0x10; Message_CloseTextbox(play); unk_2CA = this->unk_2CA; - this->actionFunc = func_80B154FC; + this->actionFunc = EnTa_RunCuccoGame; this->superCuccos[unk_2CA]->actor.gravity = 0.1f; this->superCuccos[unk_2CA]->actor.velocity.y = 0.0f; this->superCuccos[unk_2CA]->actor.speedXZ = 0.0f; @@ -686,7 +687,7 @@ void func_80B15424(EnTa* this, PlayState* play) { } } -void func_80B154FC(EnTa* this, PlayState* play) { +void EnTa_RunCuccoGame(EnTa* this, PlayState* play) { s32 i; for (i = 0; i < ARRAY_COUNT(this->superCuccos); i++) { @@ -706,7 +707,7 @@ void func_80B154FC(EnTa* this, PlayState* play) { switch (EnTa_GetSuperCuccosCount(this, play)) { case 1: gSaveContext.timer1State = 0; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Message_StartTextbox(play, 0x2084, &this->actor); this->actionFunc = func_80B15424; @@ -748,7 +749,7 @@ void func_80B154FC(EnTa* this, PlayState* play) { this->unk_2E0 &= ~0x200; func_80078884(NA_SE_SY_FOUND); gSaveContext.timer1State = 0; - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Message_StartTextbox(play, 0x2081, &this->actor); this->actionFunc = func_80B15424; func_80B14E28(this, play); @@ -796,18 +797,18 @@ void func_80B1585C(EnTa* this, PlayState* play) { } if (this->unk_2CC == 0) { - func_80B13AA0(this, func_80B154FC, func_80B16938); + EnTa_SetupAction(this, EnTa_RunCuccoGame, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitWakeUpAnim, 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim) - 1.0f, Animation_GetLastFrame(&gTalonSitWakeUpAnim), ANIMMODE_ONCE, 10.0f); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); } } void func_80B15AD4(EnTa* this, PlayState* play) { if (this->unk_2CC == 0 && this->unk_2E0 & 0x20) { - func_80B13AA0(this, func_80B1585C, func_80B16938); + EnTa_SetupAction(this, func_80B1585C, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, 1.0f, 1.0f, Animation_GetLastFrame(&gTalonSitHandsUpAnim), ANIMMODE_ONCE, 0.0f); @@ -816,7 +817,7 @@ void func_80B15AD4(EnTa* this, PlayState* play) { func_800F5ACC(NA_BGM_TIMED_MINI_GAME); this->unk_2E0 |= 0x200; Message_CloseTextbox(play); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); } if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { @@ -828,7 +829,7 @@ void func_80B15AD4(EnTa* this, PlayState* play) { void func_80B15BF8(EnTa* this, PlayState* play) { if (this->unk_2E0 & 0x10) { - func_80B13AA0(this, func_80B15AD4, func_80B16938); + EnTa_SetupAction(this, func_80B15AD4, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, 1.0f, 0.0f, 1.0f, ANIMMODE_ONCE, 0.0f); this->unk_2CC = 5; @@ -841,7 +842,7 @@ void func_80B15BF8(EnTa* this, PlayState* play) { void func_80B15CC8(EnTa* this, PlayState* play) { if (this->unk_2E0 & 0x10) { - func_80B13AA0(this, func_80B15BF8, func_80B16938); + EnTa_SetupAction(this, func_80B15BF8, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, -1.0f, 29.0f, 0.0f, ANIMMODE_ONCE, 10.0f); } @@ -852,52 +853,46 @@ void func_80B15CC8(EnTa* this, PlayState* play) { } void func_80B15D90(EnTa* this, PlayState* play) { - func_80B13AA0(this, func_80B15CC8, func_80B16938); + EnTa_SetupAction(this, func_80B15CC8, EnTa_AnimRunToEnd); this->unk_2E0 &= ~0x10; Animation_Change(&this->skelAnime, &gTalonSitHandsUpAnim, 1.0f, 8.0f, 29.0f, ANIMMODE_ONCE, -10.0f); Message_ContinueTextbox(play, 0x2080); this->unk_2E0 &= ~0x20; } -void func_80B15E28(EnTa* this, PlayState* play) { +void EnTa_TalkGeneralInLonLonHouse(EnTa* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); } this->unk_2E0 |= 1; } -void func_80B15E80(EnTa* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { +void EnTa_GiveItemInLonLonHouse(EnTa* this, PlayState* play) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { this->actor.parent = NULL; - this->actionFunc = func_80B15E28; + this->actionFunc = EnTa_TalkGeneralInLonLonHouse; if (!(this->unk_2E0 & 0x2)) { Flags_SetItemGetInf(ITEMGETINF_TALON_BOTTLE); } this->unk_2E0 &= ~0x2; } else if (this->unk_2E0 & 2) { - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { + Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } } this->unk_2E0 |= 1; } -void func_80B15F54(EnTa* this, PlayState* play) { +void EnTa_TalkAfterCuccoGameFirstWon(EnTa* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); this->unk_2E0 &= ~0x2; - func_80B13AA0(this, func_80B15E80, func_80B16938); - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LLR_TALONS_CHICKENS, GI_MILK_BOTTLE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f); + EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_TALONS_CHICKENS, true, &this->actor)) { + Actor_OfferGetItem(&this->actor, play, GI_MILK_BOTTLE, 10000.0f, 50.0f); } } } @@ -909,34 +904,34 @@ void func_80B15FE8(EnTa* this, PlayState* play) { switch (func_80B14DD8()) { case 0: Message_ContinueTextbox(play, 0x85); - func_80B13AA0(this, func_80B15034, func_80B16938); + EnTa_SetupAction(this, func_80B15034, EnTa_AnimRunToEnd); break; case 1: Message_ContinueTextbox(play, 0x208A); - func_80B13AA0(this, func_80B15E28, func_80B16938); + EnTa_SetupAction(this, EnTa_TalkGeneralInLonLonHouse, EnTa_AnimRunToEnd); break; case 2: this->unk_2E0 |= 2; - func_80B13AA0(this, func_80B15E80, func_80B16938); + EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); Rupees_ChangeBy(-30); GetItemEntry itemEntry = ItemTable_Retrieve(GI_MILK); gSaveContext.pendingSale = itemEntry.itemId; gSaveContext.pendingSaleMod = itemEntry.modIndex; - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); break; } break; case 1: if (gSaveContext.rupees < 10) { Message_ContinueTextbox(play, 0x85); - func_80B13AA0(this, func_80B15034, func_80B16938); + EnTa_SetupAction(this, func_80B15034, EnTa_AnimRunToEnd); } else { Rupees_ChangeBy(-10); func_80B15D90(this, play); } break; case 2: - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); break; } @@ -961,14 +956,14 @@ void func_80B161C0(EnTa* this, PlayState* play) { case 0: if (gSaveContext.rupees < price) { Message_ContinueTextbox(play, 0x85); - func_80B13AA0(this, func_80B15034, func_80B16938); + EnTa_SetupAction(this, func_80B15034, EnTa_AnimRunToEnd); } else { Rupees_ChangeBy(-price); func_80B15D90(this, play); } break; case 1: - func_80B14F20(this, func_80B16504); + func_80B14F20(this, EnTa_IdleSittingInLonLonHouse); func_80B13AAC(this, play); break; } @@ -982,7 +977,7 @@ void func_80B161C0(EnTa* this, PlayState* play) { void func_80B162E8(EnTa* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { Message_ContinueTextbox(play, 0x2087); - func_80B13AA0(this, func_80B15F54, func_80B16938); + EnTa_SetupAction(this, EnTa_TalkAfterCuccoGameFirstWon, EnTa_AnimRunToEnd); } if (this->unk_2E0 & 0x10) { @@ -995,10 +990,10 @@ void func_80B16364(EnTa* this, PlayState* play) { Flags_SetInfTable(INFTABLE_TALKED_TO_TALON_IN_RANCH_HOUSE); if (Flags_GetItemGetInf(ITEMGETINF_TALON_BOTTLE)) { Message_ContinueTextbox(play, 0x208B); - func_80B13AA0(this, func_80B15FE8, func_80B16938); + EnTa_SetupAction(this, func_80B15FE8, EnTa_AnimRunToEnd); } else { Message_ContinueTextbox(play, 0x207F); - func_80B13AA0(this, func_80B161C0, func_80B16938); + EnTa_SetupAction(this, func_80B161C0, EnTa_AnimRunToEnd); } } @@ -1012,16 +1007,16 @@ void func_80B1642C(EnTa* this, PlayState* play) { if (Inventory_HasEmptyBottle()) { Message_CloseTextbox(play); this->unk_2E0 |= 2; - func_80B13AA0(this, func_80B15E80, func_80B16938); - func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); + EnTa_SetupAction(this, EnTa_GiveItemInLonLonHouse, EnTa_AnimRunToEnd); + Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 50.0f); } else { Message_ContinueTextbox(play, 0x208A); - func_80B13AA0(this, func_80B15E28, func_80B16938); + EnTa_SetupAction(this, EnTa_TalkGeneralInLonLonHouse, EnTa_AnimRunToEnd); } } } -void func_80B16504(EnTa* this, PlayState* play) { +void EnTa_IdleSittingInLonLonHouse(EnTa* this, PlayState* play) { u16 faceReaction = Text_GetFaceReaction(play, 0x18); func_80B13AAC(this, play); @@ -1030,7 +1025,7 @@ void func_80B16504(EnTa* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_VO_TA_SURPRISE); if (faceReaction != 0) { - func_80B14FAC(this, func_80B15E28); + func_80B14FAC(this, EnTa_TalkGeneralInLonLonHouse); } else { Flags_SetInfTable(INFTABLE_TALKED_TO_TALON_IN_RANCH_HOUSE); @@ -1051,7 +1046,7 @@ void func_80B16504(EnTa* this, PlayState* play) { this->unk_2E0 &= ~1; } -void func_80B16608(EnTa* this, PlayState* play) { +void EnTa_IdleAfterCuccoGameFinished(EnTa* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, play)) { switch (this->actor.textId) { case 0x2085: @@ -1072,17 +1067,17 @@ void func_80B16608(EnTa* this, PlayState* play) { this->unk_2E0 |= 1; } -void func_80B166CC(EnTa* this) { +void EnTa_BlinkWaitUntilNext(EnTa* this) { s16 temp_v0 = this->blinkTimer - 1; if (temp_v0 != 0) { this->blinkTimer = temp_v0; } else { - this->unk_2B0 = func_80B16700; + this->unk_2B0 = EnTa_BlinkAdvanceState; } } -void func_80B16700(EnTa* this) { +void EnTa_BlinkAdvanceState(EnTa* this) { s16 blinkTimer = this->blinkTimer - 1; if (blinkTimer != 0) { @@ -1100,7 +1095,7 @@ void func_80B16700(EnTa* this) { blinkTimer = (s32)(Rand_ZeroOne() * 60.0f) + 20; } this->blinkTimer = blinkTimer; - this->unk_2B0 = func_80B166CC; + this->unk_2B0 = EnTa_BlinkWaitUntilNext; } else { this->eyeIndex = nextEyeIndex; this->blinkTimer = 1; @@ -1108,13 +1103,13 @@ void func_80B16700(EnTa* this) { } } -void func_80B167C0(EnTa* this) { +void EnTa_AnimRepeatCurrent(EnTa* this) { if (SkelAnime_Update(&this->skelAnime)) { Animation_PlayOnce(&this->skelAnime, this->currentAnimation); } } -void func_80B167FC(EnTa* this) { +void EnTa_AnimSleeping(EnTa* this) { if (SkelAnime_Update(&this->skelAnime)) { Animation_PlayOnce(&this->skelAnime, this->currentAnimation); Audio_PlayActorSound2(&this->actor, NA_SE_VO_TA_SLEEP); @@ -1122,7 +1117,7 @@ void func_80B167FC(EnTa* this) { this->unk_2E0 |= 0xC; } -void func_80B16854(EnTa* this) { +void EnTa_AnimSitSleeping(EnTa* this) { if (this->unk_2E2 > 0) { this->unk_2E2--; } else { @@ -1141,7 +1136,7 @@ void func_80B16854(EnTa* this) { this->unk_2E0 |= 4; } -void func_80B16938(EnTa* this) { +void EnTa_AnimRunToEnd(EnTa* this) { if (!(this->unk_2E0 & 0x10)) { if (SkelAnime_Update(&this->skelAnime)) { this->unk_2E0 |= 0x10; diff --git a/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c b/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c index f614e0f4c..e15d481fd 100644 --- a/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c +++ b/soh/src/overlays/actors/ovl_En_Takara_Man/z_en_takara_man.c @@ -147,7 +147,7 @@ void func_80B17934(EnTakaraMan* this, PlayState* play) { Rupees_ChangeBy(-10); this->unk_214 = 1; this->actor.parent = NULL; - func_8002F434(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); this->actionFunc = func_80B17A6C; } else { Message_CloseTextbox(play); @@ -172,7 +172,7 @@ void func_80B17A6C(EnTakaraMan* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { this->actionFunc = func_80B17AC4; } else { - func_8002F434(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, GI_DOOR_KEY, 2000.0f, 1000.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c index 55fbed824..342eed149 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -8,12 +8,9 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_tk/object_tk.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) -#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19 -#define ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE 0x1000 - -bool heartPieceSpawned; void EnTk_Init(Actor* thisx, PlayState* play); void EnTk_Destroy(Actor* thisx, PlayState* play); @@ -408,10 +405,6 @@ s32 EnTk_ChooseReward(EnTk* this) { f32 luck; s32 reward; - if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { - return 3; - } - luck = Rand_ZeroOne(); if (luck < 0.4f) { @@ -502,12 +495,7 @@ void EnTk_Init(Actor* thisx, PlayState* play) { CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit); - if (CVarGetInteger("gDampeAllNight", 0)) { - if (!!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) { - Actor_Kill(&this->actor); - return; - } - } else if (gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || !!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) { + if (GameInteractor_Should(GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD, this)) { Actor_Kill(&this->actor); return; } @@ -519,7 +507,6 @@ void EnTk_Init(Actor* thisx, PlayState* play) { this->currentReward = -1; this->currentSpot = NULL; this->actionFunc = EnTk_Rest; - heartPieceSpawned = false; } void EnTk_Destroy(Actor* thisx, PlayState* play) { @@ -599,7 +586,11 @@ void EnTk_Dig(EnTk* this, PlayState* play) { Vec3f rewardOrigin; Vec3f rewardPos; s32 rewardParams[] = { - ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, ITEM00_HEART_PIECE, + ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, + // #region SOH [General] Typically this heart piece would have no collectible flag set when it's picked up, but for both randomizer + // and gGravediggingTourFix we want to set one, and rely on it instead of the ItemGetInf flag that is set when the heart is spawned + ((COLLECTFLAG_GRAVEDIGGING_HEART_PIECE & 0x3F) << 8) | ITEM00_HEART_PIECE, + // #endregion }; EnTk_DigEff(this); @@ -610,7 +601,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->rewardTimer = 0; - if (this->validDigHere == 1 || IS_RANDO || CVarGetInteger("gDampeWin", 0)) { + if (GameInteractor_Should(GI_VB_BE_VALID_GRAVEDIGGING_SPOT, this->validDigHere == 1, this)) { rewardOrigin.x = 0.0f; rewardOrigin.y = 0.0f; rewardOrigin.z = -40.0f; @@ -624,51 +615,24 @@ void EnTk_Dig(EnTk* this, PlayState* play) { this->currentReward = EnTk_ChooseReward(this); - if (this->currentReward == 3) { - if (IS_RANDO || CVarGetInteger("gDampeWin", 0)) { - /* - * Upgrade the purple rupee reward to the heart piece if this - * is the first grand prize dig. - */ - if (!Flags_GetItemGetInf(ITEMGETINF_1C) && !(IS_RANDO || CVarGetInteger("gDampeWin", 0))) { - Flags_SetItemGetInf(ITEMGETINF_1C); - this->currentReward = 4; - } else if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) { - this->currentReward = 4; - } - } + if (GameInteractor_Should(GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, this->currentReward == 3, this)) { /* - * Upgrade the purple rupee reward to the heart piece if this - * is the first grand prize dig. - */ - // If vanilla itemGetInf flag is not set, it's impossible for the new flag to be set, so return true. - // Otherwise if the gGravediggingTourFix is enabled and the new flag hasn't been set, return true. - // If true, spawn the heart piece and set the vanilla itemGetInf flag and new temp clear flag. - if (!heartPieceSpawned && - (!(gSaveContext.itemGetInf[1] & ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE) || - CVarGetInteger("gGravediggingTourFix", 0) && - !Flags_GetCollectible(play, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE))) { + * Upgrade the purple rupee reward to the heart piece if this + * is the first grand prize dig. + */ + if (GameInteractor_Should(GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, !Flags_GetItemGetInf(ITEMGETINF_1C), this)) { + Flags_SetItemGetInf(ITEMGETINF_1C); this->currentReward = 4; - gSaveContext.itemGetInf[1] |= ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE; - heartPieceSpawned = true; } } - if (IS_RANDO && this->currentReward == 4) { - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, rewardPos.x, rewardPos.y, rewardPos.z, 0, 0, 0, 0x1906, true); - this->heartPieceSpawned = 1; - } else { - EnItem00* reward = Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]); - if (this->currentReward == 4) { - reward->collectibleFlag = COLLECTFLAG_GRAVEDIGGING_HEART_PIECE; - } - } + Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]); } } if (this->skelAnime.curFrame >= 32.0f && this->rewardTimer == 10) { /* Play a reward sound shortly after digging */ - if (!(IS_RANDO || CVarGetInteger("gDampeWin", 0)) && this->validDigHere == 0) { + if (this->validDigHere == 0) { /* Bad dig spot */ Audio_PlayActorSound2(&this->actor, NA_SE_SY_ERROR); } else if (this->currentReward == 4) { diff --git a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h index c60cb5200..c2dee0fce 100644 --- a/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h +++ b/soh/src/overlays/actors/ovl_En_Tk/z_en_tk.h @@ -8,6 +8,8 @@ /* Dirt particle effect */ struct EnTkEff; +#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19 + typedef struct EnTkEff { /* 0x0000 */ u8 active; /* 0x0001 */ u8 timeLeft; diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index d52b82d8d..275b62ba1 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -6,7 +6,7 @@ #include "z_en_toryo.h" #include "objects/object_toryo/object_toryo.h" -#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -291,10 +291,7 @@ void func_80B20768(EnToryo* this, PlayState* play) { s16 sp32; s16 sp30; - // Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw - // As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled. - bool checkAnim = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? play->animationCtx.animationCount <= 1 : true; - if (this->unk_1E4 == 3 && checkAnim) { + if (this->unk_1E4 == 3 && !GameInteractor_Should(GI_VB_FIX_SAW_SOFTLOCK, false, NULL)) { Actor_ProcessTalkRequest(&this->actor, play); Message_ContinueTextbox(play, this->actor.textId); this->unk_1E4 = 1; @@ -315,19 +312,12 @@ void func_80B20768(EnToryo* this, PlayState* play) { } if (this->unk_1E4 == 4) { - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_SAW, true, this)) { this->actor.parent = NULL; this->unk_1E4 = 5; + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW); } else { - if (IS_RANDO) { - GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN); - Randomizer_ConsumeAdultTradeItem(play, ITEM_SAW); - GiveItemEntryFromActor(&this->actor, play, itemEntry, 100.0f, 10.0f); - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW); - } else { - s32 itemId = GI_SWORD_BROKEN; - func_8002F434(&this->actor, play, itemId, 100.0f, 10.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_SWORD_BROKEN, 100.0f, 10.0f); } return; } diff --git a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c index 2b90e1ff7..5aeb0a86b 100644 --- a/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c +++ b/soh/src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.c @@ -6,6 +6,7 @@ #include "z_en_wonder_talk2.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_LOCKON) @@ -194,7 +195,9 @@ void func_80B3A3D4(EnWonderTalk2* this, PlayState* play) { this->unk_15A = true; } this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED); - func_8002DF54(play, NULL, 7); + if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { + Player_SetCsActionWithHaltedActors(play, NULL, 7); + } this->unk_156 = true; this->actionFunc = func_80B3A4F8; break; @@ -252,42 +255,12 @@ void func_80B3A4F8(EnWonderTalk2* this, PlayState* play) { } this->unk_158 = 0; if (!this->unk_156) { - // Whether or not to skip the text in rando - bool randoSkipText = false; - if (IS_RANDO) { - // Scenes for which all of this type of wonder talk should be skipped. - switch (play->sceneNum) { - case SCENE_SHADOW_TEMPLE: // Shadow Temple - randoSkipText = true; - break; - case SCENE_GERUDO_TRAINING_GROUND: // Gerudo Training Grounds - randoSkipText = true; - break; - case SCENE_THIEVES_HIDEOUT: // Inside Gerudo Fortress - randoSkipText = true; - break; - default: - break; - } - // individual textIds that should be skipped, or that should be preserved - // in a scene that otherwise has all wonder talk skipped. - //switch (this->actor.textId) { - // case: 0x023c //textId we want to skip - // randoSkipText = true; - // break; - // case 0x023c: // textId in a skipped scene that we don't want to skip - // randoSkipText = false; - // break; - // default: - // break; - //} - } - if (!(randoSkipText)) { + if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) { Message_StartTextbox(play, this->actor.textId, NULL); - func_8002DF54(play, NULL, 8); - this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; - this->actionFunc = func_80B3A3D4; + Player_SetCsActionWithHaltedActors(play, NULL, 8); } + this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED; + this->actionFunc = func_80B3A3D4; } } else { diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 012531f66..283283804 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -13,6 +13,7 @@ #include "scenes/indoors/tokinoma/tokinoma_scene.h" #include "scenes/dungeons/ice_doukutu/ice_doukutu_scene.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -274,6 +275,7 @@ void func_80B3C9EC(EnXc* this) { this->action = SHEIK_ACTION_BLOCK_PEDESTAL; this->drawMode = SHEIK_DRAW_DEFAULT; this->unk_30C = 1; + // SOH [Randomizer] We don't want sheik blocking the pedestal in randomizer if (IS_RANDO) { Actor_Kill(&this->actor); } @@ -289,24 +291,6 @@ void func_80B3CA38(EnXc* this, PlayState* play) { } } -void GivePlayerRandoRewardSheikSong(EnXc* sheik, PlayState* play, RandomizerCheck check, int sheikType, GetItemID ogSongId) { - Player* player = GET_PLAYER(play); - if (!(gSaveContext.eventChkInf[5] & sheikType)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, ogSongId); - if (check == RC_SHEIK_AT_TEMPLE && !Flags_GetTreasure(play, 0x1F)) { - if (GiveItemEntryFromActor(&sheik->actor, play, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = 0x1F; - player->pendingFlag.flagType = FLAG_SCENE_TREASURE; - } - } else if (check != RC_SHEIK_AT_TEMPLE) { - if (GiveItemEntryFromActor(&sheik->actor, play, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = (0x5 << 4) | (sheikType & 0xF) >> 1; - player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; - } - } - } -} - s32 EnXc_MinuetCS(EnXc* this, PlayState* play) { if (this->actor.params == SHEIK_TYPE_MINUET) { Player* player = GET_PLAYER(play); @@ -314,16 +298,17 @@ s32 EnXc_MinuetCS(EnXc* this, PlayState* play) { if (z < -2225.0f) { if (!Play_InCsMode(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gMinuetCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST); - Item_Give(play, ITEM_SONG_MINUET); - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_FOREST, 1, RG_MINUET_OF_FOREST); - return false; } - return true; + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) { + Item_Give(play, ITEM_SONG_MINUET); + } + if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) { + return true; + } } } return false; @@ -350,16 +335,17 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) { if ((posRot->pos.x > -784.0f) && (posRot->pos.x < -584.0f) && (posRot->pos.y > 447.0f) && (posRot->pos.y < 647.0f) && (posRot->pos.z > -446.0f) && (posRot->pos.z < -246.0f) && !Play_InCsMode(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gDeathMountainCraterBoleroCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE); - Item_Give(play, ITEM_SONG_BOLERO); - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_CRATER, 2, RG_BOLERO_OF_FIRE); - return false; } - return true; + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) { + Item_Give(play, ITEM_SONG_BOLERO); + } + if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) { + return true; + } } return false; } @@ -367,13 +353,8 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) { } void EnXc_SetupSerenadeAction(EnXc* this, PlayState* play) { - if (IS_RANDO) { - this->action = SHEIK_ACTION_SERENADE; - return; - } - // Player is adult and does not have iron boots and has not learned Serenade - if ((!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT) { + if (GameInteractor_Should(GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT, NULL)) { this->action = SHEIK_ACTION_SERENADE; osSyncPrintf("水のセレナーデ シーク誕生!!!!!!!!!!!!!!!!!!\n"); } else { @@ -386,22 +367,20 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { if (this->actor.params == SHEIK_TYPE_SERENADE) { Player* player = GET_PLAYER(play); s32 stateFlags = player->stateFlags1; - - if (((CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !IS_RANDO) || - (Flags_GetTreasure(play, 2) && IS_RANDO)) && - !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !(stateFlags & PLAYER_STATE1_IN_CUTSCENE) && - !Play_InCsMode(play)) { - if (!IS_RANDO) { + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), NULL) && + !(stateFlags & PLAYER_STATE1_IN_CUTSCENE) && !Play_InCsMode(play)) { + if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { Cutscene_SetSegment(play, &gIceCavernSerenadeCs); gSaveContext.cutsceneTrigger = 1; - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag + } + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag + if (GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) { Item_Give(play, ITEM_SONG_SERENADE); - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_ICE_CAVERN, 4, RG_SERENADE_OF_WATER); - return false; } osSyncPrintf("ブーツを取った!!!!!!!!!!!!!!!!!!\n"); - return true; + if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) { + return true; + } } osSyncPrintf("はやくブーツを取るべし!!!!!!!!!!!!!!!!!!\n"); return false; @@ -412,7 +391,7 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) { void EnXc_DoNothing(EnXc* this, PlayState* play) { } -void EnXc_RandoStand(EnXc* this, PlayState* play) { +void SoH_EnXc_RandoStand(EnXc* this, PlayState* play) { //Replaces Ganondorf Light Arrow hint. also stands in ToT if (play->sceneNum == SCENE_TEMPLE_OF_TIME) { EnXc_ChangeAnimation(this, &gSheikArmsCrossedIdleAnim, ANIMMODE_LOOP, 0.0f, false); @@ -2206,22 +2185,21 @@ void EnXc_InitTempleOfTime(EnXc* this, PlayState* play) { if (LINK_IS_ADULT) { if (!Flags_GetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL)) { Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL); - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs); - gSaveContext.cutsceneTrigger = 1; + if (GameInteractor_Should(GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, true, NULL)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs); + gSaveContext.cutsceneTrigger = 1; + } func_80B3EBF0(this, play); - } else if ((!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) && - !IS_RANDO) || - (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && - IS_RANDO)) { - if (!IS_RANDO) { - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), NULL)) { + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) { Item_Give(play, ITEM_SONG_PRELUDE); + } + if (GameInteractor_Should(GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, true, NULL)) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimePreludeCs); gSaveContext.cutsceneTrigger = 1; - this->action = SHEIK_ACTION_30; - } else { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_AT_TEMPLE, 0x20, RG_PRELUDE_OF_LIGHT); } + this->action = SHEIK_ACTION_30; // Not sure what this does exactly } else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) { func_80B3C9EC(this); } else { @@ -2359,14 +2337,6 @@ void EnXc_Update(Actor* thisx, PlayState* play) { EnXc* this = (EnXc*)thisx; s32 action = this->action; - if (this->actor.params == SHEIK_TYPE_9) { - if (IS_RANDO && LINK_IS_ADULT) { - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) { - GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_AT_TEMPLE, 0x20, RG_PRELUDE_OF_LIGHT); - } - } - } - if ((action < 0) || (action >= ARRAY_COUNT(sActionFuncs)) || (sActionFuncs[action] == NULL)) { osSyncPrintf(VT_FGCOL(RED) "メインモードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST); } else { @@ -2414,7 +2384,7 @@ void EnXc_Init(Actor* thisx, PlayState* play) { EnXc_DoNothing(this, play); break; case SHEIK_TYPE_RANDO: - EnXc_RandoStand(this, play); + SoH_EnXc_RandoStand(this, play); break; default: osSyncPrintf(VT_FGCOL(RED) " En_Oa2 の arg_data がおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST); diff --git a/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c b/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c index 133556f52..7234ed57f 100644 --- a/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c +++ b/soh/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c @@ -421,7 +421,7 @@ void func_80B4BBC4(EnZl1* this, PlayState* play) { Player* player = GET_PLAYER(play); Animation_Change(&this->skelAnime, &gChildZelda1Anim_00438, 1.0f, 0.0f, frameCount, ANIMMODE_LOOP, 0.0f); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Player_PlaySfx(&player->actor, NA_SE_VO_LI_SURPRISE_KID); this->actor.textId = 0x7039; Message_StartTextbox(play, this->actor.textId, NULL); @@ -510,7 +510,7 @@ void func_80B4BF2C(EnZl1* this, PlayState* play) { if ((Message_GetState(msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { this->actor.textId = 0xFFFF; play->talkWithPlayer(play, &this->actor); - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; play->msgCtx.stateTimer = 4; this->unk_1E2++; @@ -525,7 +525,7 @@ void func_80B4BF2C(EnZl1* this, PlayState* play) { this->actor.parent = NULL; this->unk_1E2++; } else { - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, 120.0f, 10.0f); } break; case 3: @@ -554,7 +554,7 @@ void func_80B4BF2C(EnZl1* this, PlayState* play) { break; case 6: if (Actor_TextboxIsClosing(&this->actor, play)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); Interface_ChangeAlpha(50); this->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO; this->unk_1E2 = 4; diff --git a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c index 4a47b456e..9bc53169b 100644 --- a/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c +++ b/soh/src/overlays/actors/ovl_En_Zl2/z_en_zl2.c @@ -10,6 +10,7 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "objects/object_zl2/object_zl2.h" #include "objects/object_zl2_anime1/object_zl2_anime1.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -633,7 +634,9 @@ void EnZl2_GiveLightArrows(EnZl2* this, PlayState* play) { posY = player->actor.world.pos.y + 80.0f; posZ = player->actor.world.pos.z; Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17, true); - Item_Give(play, ITEM_ARROW_LIGHT); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) { + Item_Give(play, ITEM_ARROW_LIGHT); + } this->unk_244 = 1; } } diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index 08c3857e0..f2abefd97 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -7,6 +7,7 @@ #include "z_en_zl4.h" #include "objects/object_zl4/object_zl4.h" #include "scenes/indoors/nakaniwa/nakaniwa_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED) @@ -227,20 +228,6 @@ u16 EnZl4_GetText(PlayState* play, Actor* thisx) { return ret; } -void GivePlayerRandoRewardZeldaChild(EnZl4* zelda, PlayState* play, RandomizerCheck check) { - if (zelda->actor.parent != NULL && zelda->actor.parent->id == GET_PLAYER(play)->actor.id && - !Flags_GetTreasure(play, 0x1E)) { - Flags_SetTreasure(play, 0x1E); - } else if (!Flags_GetTreasure(play, 0x1E) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA) && Actor_TextboxIsClosing(&zelda->actor, play) && - (play->msgCtx.textId == 0x703C || play->msgCtx.textId == 0x703D)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, GI_LETTER_ZELDA); - GiveItemEntryFromActor(&zelda->actor, play, getItemEntry, 10000.0f, 100.0f); - } else if (Flags_GetTreasure(play, 0x1E) && !Player_InBlockingCsMode(play, GET_PLAYER(play))) { - gSaveContext.unk_13EE = 0x32; - Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER); - } -} - s16 func_80B5B9B0(PlayState* play, Actor* thisx) { EnZl4* this = (EnZl4*)thisx; @@ -338,7 +325,7 @@ s32 EnZl4_SetupFromLegendCs(EnZl4* this, PlayState* play) { Actor* playerx = &GET_PLAYER(play)->actor; s16 rotY; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); playerx->world.pos = this->actor.world.pos; rotY = this->actor.shape.rot.y; playerx->world.pos.x += 56.0f * Math_SinS(rotY); @@ -389,12 +376,6 @@ void EnZl4_Init(Actor* thisx, PlayState* play) { this->actor.textId = -1; this->eyeExpression = this->mouthExpression = ZL4_MOUTH_NEUTRAL; - if (IS_RANDO) { - Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); - this->actionFunc = EnZl4_Idle; - return; - } - if (gSaveContext.sceneSetupIndex >= 4) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->actionFunc = EnZl4_TheEnd; @@ -930,7 +911,7 @@ s32 EnZl4_CsLookWindow(EnZl4* this, PlayState* play) { play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardGanonCs); gSaveContext.cutsceneTrigger = 1; this->talkState++; - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); } break; case 2: @@ -940,7 +921,7 @@ s32 EnZl4_CsLookWindow(EnZl4* this, PlayState* play) { } } else { func_800AA000(0.0f, 0xA0, 0xA, 0x28); - func_8002DF54(play, &this->actor, 1); + Player_SetCsActionWithHaltedActors(play, &this->actor, 1); Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_30); EnZl4_SetCsCameraAngle(play, 11); Message_StartTextbox(play, 0x7039, NULL); @@ -1127,18 +1108,20 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) { Camera_ChangeSetting(GET_ACTIVE_CAM(play), 1); this->talkState = 7; play->talkWithPlayer(play, &this->actor); - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, - fabsf(this->actor.yDistToPlayer) + 1.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, + fabsf(this->actor.yDistToPlayer) + 1.0f); + } play->msgCtx.stateTimer = 4; play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING; } break; case 7: - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->talkState++; } else { - func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, + Actor_OfferGetItem(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f); } // no break here is required for matching @@ -1206,7 +1189,7 @@ void EnZl4_Cutscene(EnZl4* this, PlayState* play) { break; case ZL4_CS_PLAN: if (EnZl4_CsMakePlan(this, play)) { - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); gSaveContext.unk_13EE = 0x32; Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER); this->actionFunc = EnZl4_Idle; @@ -1225,11 +1208,6 @@ void EnZl4_Idle(EnZl4* this, PlayState* play) { Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->collider.dim.radius + 60.0f, EnZl4_GetText, func_80B5B9B0); func_80B5BB78(this, play); - - if (IS_RANDO) { - GivePlayerRandoRewardZeldaChild(this, play, RC_HC_ZELDAS_LETTER); - return; - } } void EnZl4_TheEnd(EnZl4* this, PlayState* play) { diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h index 601ed6905..4b14121c6 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.h @@ -31,4 +31,9 @@ typedef struct EnZl4 { /* 0x0284 */ Vec3s morphTable[18]; } EnZl4; // size = 0x02F0 +s16 func_80B5B9B0(PlayState* play, Actor* actor); +void func_80B5BB78(EnZl4* enZl4, PlayState* play); +void EnZl4_Cutscene(EnZl4* enZl4, PlayState* play); +s32 EnZl4_SetNextAnim(EnZl4* enZl4, s32 nextAnim); + #endif diff --git a/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c b/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c index 9212362d6..0601a7f5b 100644 --- a/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c +++ b/soh/src/overlays/actors/ovl_En_fHG/z_en_fhg.c @@ -153,7 +153,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { break; } func_80064520(play, &play->csCtx); - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); this->cutsceneCamera = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->cutsceneCamera, CAM_STAT_ACTIVE); @@ -193,7 +193,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_HORSE_GROAN); } if (this->timers[0] == 20) { - func_8002DF54(play, &this->actor, 9); + Player_SetCsActionWithHaltedActors(play, &this->actor, 9); } if (this->timers[0] == 1) { Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_OPENING_GANON); @@ -354,7 +354,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { this->bossGndSignal = FHG_FINISH; } if (this->timers[0] == 170) { - func_8002DF54(play, &this->actor, 8); + Player_SetCsActionWithHaltedActors(play, &this->actor, 8); Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC2); } Math_ApproachF(&this->cameraEye.z, this->cameraPanZ + (GND_BOSSROOM_CENTER_Z + 100.0f), 0.1f, @@ -401,7 +401,7 @@ void EnfHG_Intro(EnfHG* this, PlayState* play) { func_800C08AC(play, this->cutsceneCamera, 0); this->cutsceneCamera = 0; func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); this->actionFunc = EnfHG_Retreat; } break; diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c index 48d85723e..8b7c77aca 100644 --- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -5160,7 +5160,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { this->actor.parent = NULL; if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); } else { GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); } @@ -5215,7 +5215,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) { this->stateAndTimer = 24; } else { if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_SCALE_GOLD, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, GI_SCALE_GOLD, 2000.0f, 1000.0f); } else { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_ADULT_FISHING, GI_SCALE_GOLD); GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f); @@ -5572,7 +5572,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { sSubCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); mainCam = Play_GetCamera(play, MAIN_CAM); sCameraEye.x = mainCam->eye.x; sCameraEye.y = mainCam->eye.y; @@ -5604,7 +5604,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { mainCam->at = sCameraAt; func_800C08AC(play, sSubCamId, 0); func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sFishingPlayerCinematicState = 0; sSubCamId = 0; sFishingCinematicTimer = 30; @@ -5620,7 +5620,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { sSubCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE); - func_8002DF54(play, &this->actor, 5); + Player_SetCsActionWithHaltedActors(play, &this->actor, 5); mainCam = Play_GetCamera(play, MAIN_CAM); sCameraEye.x = mainCam->eye.x; sCameraEye.y = mainCam->eye.y; @@ -5639,7 +5639,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { if ((sFishingCinematicTimer == 0) && Message_ShouldAdvance(play)) { sFishingPlayerCinematicState = 22; sFishingCinematicTimer = 40; - func_8002DF54(play, &this->actor, 0x1C); + Player_SetCsActionWithHaltedActors(play, &this->actor, 0x1C); sSinkingLureHeldY = 0.0f; } break; @@ -5708,7 +5708,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) { mainCam->at = sCameraAt; func_800C08AC(play, sSubCamId, 0); func_80064534(play, &play->csCtx); - func_8002DF54(play, &this->actor, 7); + Player_SetCsActionWithHaltedActors(play, &this->actor, 7); sFishingPlayerCinematicState = 0; sSubCamId = 0; player->unk_860 = -5; diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index abb65c191..5015a3908 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -59,12 +59,7 @@ void ItemBHeart_Update(Actor* thisx, PlayState* play) { Flags_SetCollectible(play, 0x1F); Actor_Kill(&this->actor); } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_HEART_CONTAINER_2); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 40.0f); - } + Actor_OfferGetItem(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f); } } @@ -98,23 +93,18 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { actorIt = actorIt->next; } - if (IS_RANDO) { - GetItemEntry_Draw(play, Randomizer_GetItemFromActor(this->actor.id, - play->sceneNum,this->actor.params, GI_HEART_CONTAINER_2)); + if (flag) { + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); } else { - if (flag) { - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL); - } else { - Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); - gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); - } + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); + gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h index d9483b48c..434aa775b 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h @@ -13,6 +13,11 @@ typedef struct ItemBHeart { /* 0x015C */ char unk_15C[0x8]; /* 0x0164 */ s16 unk_164; /* 0x0166 */ char unk_166[0x6]; + // #region SOH [Randomizer] Cached for drawing for performance + /* */ GetItemEntry sohItemEntry; + // #endregion } ItemBHeart; // size = 0x016C +void func_80B85264(ItemBHeart* itemBHeart, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index b12d7b4b0..796b157a3 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -83,8 +83,7 @@ void ItemEtcetera_Init(Actor* thisx, PlayState* play) { case ITEM_ETC_LETTER: Actor_SetScale(&this->actor, 0.5f); this->futureActionFunc = func_80B858B4; - if ((Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER) && !IS_RANDO) || - (IS_RANDO && Flags_GetTreasure(play, 0x1E))) { + if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER)) { Actor_Kill(&this->actor); } break; @@ -121,24 +120,13 @@ void func_80B857D0(ItemEtcetera* this, PlayState* play) { void func_80B85824(ItemEtcetera* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { - if ((this->actor.params & 0xFF) == 7) { - if (IS_RANDO) { - Flags_SetTreasure(play, 0x1F); - } - } - if ((this->actor.params & 0xFF) == 1) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); Flags_SetSwitch(play, 0xB); } Actor_Kill(&this->actor); } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->getItemId, 30.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); } } @@ -147,21 +135,11 @@ void func_80B858B4(ItemEtcetera* this, PlayState* play) { if ((this->actor.params & 0xFF) == 1) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER); Flags_SetSwitch(play, 0xB); - - if (IS_RANDO) { - Flags_SetTreasure(play, 0x1E); - } } + Actor_Kill(&this->actor); } else { - if (0) {} // Necessary to match - - if (!IS_RANDO) { - func_8002F434(&this->actor, play, this->getItemId, 30.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); - } + Actor_OfferGetItem(&this->actor, play, this->getItemId, 30.0f, 50.0f); if ((play->gameplayFrames & 0xD) == 0) { EffectSsBubble_Spawn(play, &this->actor.world.pos, 0.0f, 0.0f, 10.0f, 0.13f); @@ -228,41 +206,12 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { if (play->actorCtx.lensActive) { func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); - - if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - if (randoGetItem.itemId != ITEM_NONE) { - GetItemEntry_Draw(play, randoGetItem); - return; - } - } - GetItem_Draw(play, this->giDrawId); } } void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { ItemEtcetera* this = (ItemEtcetera*)thisx; - s32 type = this->actor.params & 0xFF; - - if (IS_RANDO) { - GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; - if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); - } else if (type == ITEM_ETC_LETTER) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); - } - - EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); - - if (randoGetItem.itemId != ITEM_NONE) { - func_8002EBCC(&this->actor, play, 0); - func_8002ED80(&this->actor, play, 0); - GetItemEntry_Draw(play, randoGetItem); - return; - } - } func_8002EBCC(&this->actor, play, 0); func_8002ED80(&this->actor, play, 0); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h index 3ec33b926..5293292a4 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.h @@ -16,6 +16,9 @@ typedef struct ItemEtcetera { /* 0x0154 */ u8 objBankIndex; /* 0x0158 */ ActorFunc drawFunc; /* 0x015C */ ItemEtceteraActionFunc actionFunc; + // #region SOH [Randomizer] Caching the get item entry for the draw function for performance + /* */ GetItemEntry sohItemEntry; + // #endregion } ItemEtcetera; // size = 0x0160 typedef enum { @@ -35,4 +38,6 @@ typedef enum { /* 0x0D */ ITEM_ETC_KEY_SMALL_CHEST_GAME } ItemEtceteraType; +void ItemEtcetera_SpawnSparkles(ItemEtcetera* ItemEtcetera, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index a9cd36446..d14862553 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -6,6 +6,7 @@ #include "z_item_ocarina.h" #include "scenes/overworld/spot00/spot00_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -169,31 +170,27 @@ void ItemOcarina_DoNothing(ItemOcarina* this, PlayState* play) { void ItemOcarina_StartSoTCutscene(ItemOcarina* this, PlayState* play) { if (Actor_TextboxIsClosing(&this->actor, play)) { - if (!IS_RANDO) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs); - gSaveContext.cutsceneTrigger = 1; - } else { - play->transitionTrigger = TRANS_TRIGGER_START; - play->transitionType = TRANS_TYPE_FADE_WHITE; - gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE; - play->nextEntranceIndex = ENTR_HYRULE_FIELD_16; - gSaveContext.nextCutsceneIndex = 0; - } + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs); + gSaveContext.cutsceneTrigger = 1; } } void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) { - if (Actor_HasParent(&this->actor, play)) { + if ( + Actor_HasParent(&this->actor, play) || + ( + !GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL) && + (this->actor.xzDistToPlayer < 20.0f) && (fabsf(this->actor.yDistToPlayer) < 10.0f) && + GET_PLAYER(play)->stateFlags2 & PLAYER_STATE2_DIVING + ) + ) { Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_OCARINA_OF_TIME); Flags_SetSwitch(play, 3); this->actionFunc = ItemOcarina_StartSoTCutscene; this->actor.draw = NULL; } else { - if (!IS_RANDO) { - func_8002F434(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f); - } else { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); - GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL)) { + Actor_OfferGetItem(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f); } if ((play->gameplayFrames & 13) == 0) { diff --git a/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c b/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c index e54b343fc..beecbf759 100644 --- a/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c +++ b/soh/src/overlays/actors/ovl_Item_Shield/z_item_shield.c @@ -103,7 +103,7 @@ void func_80B86AC8(ItemShield* this, PlayState* play) { Actor_Kill(&this->actor); return; } - func_8002F434(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); Actor_UpdateBgCheckInfo(play, &this->actor, 10.0f, 10.0f, 0.0f, 5); if (this->actor.bgCheckFlags & 1) { this->timer--; @@ -125,7 +125,7 @@ void func_80B86BC8(ItemShield* this, PlayState* play) { Actor_Kill(&this->actor); return; } - func_8002F434(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); + Actor_OfferGetItem(&this->actor, play, GI_SHIELD_DEKU, 30.0f, 50.0f); if (this->collider.base.acFlags & AC_HIT) { ItemShield_SetupAction(this, func_80B86AC8); this->actor.velocity.y = 4.0f; diff --git a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c index 0dde415e0..e17de7597 100644 --- a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c +++ b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c @@ -132,21 +132,6 @@ void ObjComb_Break(ObjComb* this, PlayState* play) { void ObjComb_ChooseItemDrop(ObjComb* this, PlayState* play) { s16 params = this->actor.params & 0x1F; - if ( - IS_RANDO && - Randomizer_GetSettingValue(RSK_SHUFFLE_BEEHIVES) && - !Flags_GetRandomizerInf(this->beehiveIdentity.randomizerInf) - ) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(this->beehiveIdentity.randomizerCheck, GI_NONE); - - EnItem00* actor = (EnItem00*)Item_DropCollectible2(play, &this->actor.world.pos, ITEM00_SMALL_KEY); - actor->randoCheck = this->beehiveIdentity.randomizerCheck; - actor->randoGiEntry = getItemEntry; - actor->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; - actor->randoInf = this->beehiveIdentity.randomizerInf; - return; - } - if ((params > 0) || (params < 0x1A)) { if (params == 6) { if (Flags_GetCollectible(play, (this->actor.params >> 8) & 0x3F)) { @@ -170,10 +155,6 @@ void ObjComb_Init(Actor* thisx, PlayState* play) { Collider_InitJntSph(play, &this->collider); Collider_SetJntSph(play, &this->collider, &this->actor, &sJntSphInit, this->colliderItems); ObjComb_SetupWait(this); - if (IS_RANDO) { - s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); - this->beehiveIdentity = Randomizer_IdentifyBeehive(play->sceneNum, (s16)this->actor.world.pos.x, respawnData); - } } void ObjComb_Destroy(Actor* thisx, PlayState* play2) { @@ -191,15 +172,7 @@ void ObjComb_Wait(ObjComb* this, PlayState* play) { s32 dmgFlags; this->unk_1B0 -= 50; - if ( - IS_RANDO && - Randomizer_GetSettingValue(RSK_SHUFFLE_BEEHIVES) && - !Flags_GetRandomizerInf(this->beehiveIdentity.randomizerInf) - ) { - if (this->unk_1B0 <= -5000) { - this->unk_1B0 = 1500; - } - } else if (this->unk_1B0 < 0) { + if (this->unk_1B0 < 0) { this->unk_1B0 = 0; } diff --git a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h index f7713a961..ded72dfc4 100644 --- a/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h +++ b/soh/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.h @@ -18,4 +18,6 @@ typedef struct ObjComb { /* */ BeehiveIdentity beehiveIdentity; } ObjComb; // size = 0x01B4 +void ObjComb_Break(ObjComb* objComb, PlayState* play); + #endif diff --git a/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c b/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c index ae9545825..9463d45af 100644 --- a/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c +++ b/soh/src/overlays/actors/ovl_Obj_Dekujr/z_obj_dekujr.c @@ -6,6 +6,7 @@ #include "z_obj_dekujr.h" #include "objects/object_dekujr/object_dekujr.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY) @@ -56,7 +57,7 @@ void ObjDekujr_Init(Actor* thisx, PlayState* play) { this->unk_19C = 0; this->unk_19B = 1; } - if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { + if (!GameInteractor_Should(GI_VB_DEKU_JR_CONSIDER_FOREST_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST), this)) { Actor_Kill(thisx); } else { ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f); diff --git a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c index 34defede5..9220c6be4 100644 --- a/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c +++ b/soh/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.c @@ -7,6 +7,7 @@ #include "z_obj_switch.h" #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED @@ -249,10 +250,12 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) { subType = (this->dyna.actor.params >> 4 & 7); Flags_SetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F)); - if (subType == 0 || subType == 4) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); - } else { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + if (subType == 0 || subType == 4) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME); + } else { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } } this->cooldownOn = true; @@ -266,7 +269,9 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) { Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F)); if ((this->dyna.actor.params >> 4 & 7) == 1) { - OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) { + OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR); + } this->cooldownOn = true; } } diff --git a/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c b/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c index 2346b34ff..0dd03a5be 100644 --- a/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c +++ b/soh/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c @@ -274,7 +274,7 @@ void ObjTsubo_Idle(ObjTsubo* this, PlayState* play) { phi_v1 = ABS(temp_v0); if (phi_v1 >= 0x5556) { // GI_NONE in this case allows the player to lift the actor - func_8002F434(&this->actor, play, GI_NONE, 30.0f, 30.0f); + Actor_OfferGetItem(&this->actor, play, GI_NONE, 30.0f, 30.0f); } } } diff --git a/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c b/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c index eefaf9c0c..2600acd6b 100644 --- a/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c +++ b/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c @@ -136,27 +136,6 @@ void ObjectKankyo_Init(Actor* thisx, PlayState* play) { this->effects[5].size = 0.0f; } - if (IS_RANDO) { - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) { - this->effects[0].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) { - this->effects[1].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) { - this->effects[2].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) { - this->effects[3].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) { - this->effects[4].size = 0.0f; - } - if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) { - this->effects[5].size = 0.0f; - } - } - if (gSaveContext.cutsceneTrigger != 0) { if (gSaveContext.entranceIndex == ENTR_INSIDE_GANONS_CASTLE_2) { this->effects[0].size = 0.1f; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index ac53d3ab8..43a34c778 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -31,6 +31,7 @@ #include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "soh/Enhancements/randomizer/fishsanity.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include #include @@ -6800,7 +6801,14 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO; // Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies. - uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) || + uint8_t isDropToSkip = + ( + interactedActor->id == ACTOR_EN_ITEM00 && + interactedActor->params != ITEM00_HEART_PIECE && + interactedActor->params != ITEM00_SMALL_KEY && + interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY && + interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI + ) || interactedActor->id == ACTOR_EN_KAREBABA || interactedActor->id == ACTOR_EN_DEKUBABA; @@ -6858,8 +6866,10 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) { } func_80836898(play, this, func_8083A434); + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CHEST, true, chest)) { this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE; func_8083AE40(this, giEntry.objectId); + } this->actor.world.pos.x = chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f); this->actor.world.pos.z = @@ -8505,15 +8515,14 @@ void func_80842A28(PlayState* play, Player* this) { } void func_80842A88(PlayState* play, Player* this) { - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { - Inventory_ChangeAmmo(ITEM_STICK, -1); - Player_UseItem(play, this, ITEM_NONE); - } + Inventory_ChangeAmmo(ITEM_STICK, -1); + Player_UseItem(play, this, ITEM_NONE); } s32 func_80842AC4(PlayState* play, Player* this) { if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && (this->unk_85C > 0.5f)) { - if (AMMO(ITEM_STICK) != 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + + if (GameInteractor_Should(GI_VB_DEKU_STICK_BREAK, AMMO(ITEM_STICK) != 0, NULL)) { EffectSsStick_Spawn(play, &this->bodyPartsPos[PLAYER_BODYPART_R_HAND], this->actor.shape.rot.y + 0x8000); this->unk_85C = 0.5f; @@ -10229,7 +10238,7 @@ void Player_Init(Actor* thisx, PlayState* play2) { if ((sp50 == 0) || (sp50 < -1)) { titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart; - if (gSaveContext.showTitleCard) { + if (GameInteractor_Should(GI_VB_SHOW_TITLE_CARD, gSaveContext.showTitleCard, NULL)) { if ((gSaveContext.sceneSetupIndex < 4) && (gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field & ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) && @@ -10932,37 +10941,30 @@ static Vec3f D_808547B0 = { 0.0f, 0.5f, 0.0f }; static Color_RGBA8 D_808547BC = { 255, 255, 100, 255 }; static Color_RGBA8 D_808547C0 = { 255, 50, 0, 0 }; -void func_80848A04(PlayState* play, Player* this) { +void Player_UpdateBurningDekuStick(PlayState* play, Player* this) { f32 temp; - if (CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) { - f32 temp2 = 1.0f; // Secondary temporary variable to use with the alleged draw flame function - this->unk_860 = 200; // Keeps the stick's flame lit - this->unk_85C = 1.0f; // Ensures the stick is the proper length - func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, temp2 * 200.0f, - 0, 8); // I believe this draws the flame effect - } - - if (this->unk_85C == 0.0f && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { - Player_UseItem(play, this, 0xFF); + if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_OUT, this->unk_85C == 0.0f, NULL)) { + Player_UseItem(play, this, ITEM_NONE); return; } temp = 1.0f; - if (DECR(this->unk_860) == 0 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + uint8_t vanillaShouldBurnOutCondition = DECR(this->unk_860) == 0; + if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_OUT, vanillaShouldBurnOutCondition, NULL)) { Inventory_ChangeAmmo(ITEM_STICK, -1); this->unk_860 = 1; temp = 0.0f; this->unk_85C = temp; } else if (this->unk_860 > 200) { temp = (210 - this->unk_860) / 10.0f; - } else if (this->unk_860 < 20 && CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_NORMAL) { + } else if (GameInteractor_Should(GI_VB_DEKU_STICK_BURN_DOWN, this->unk_860 < 20, NULL)) { temp = this->unk_860 / 20.0f; this->unk_85C = temp; } - func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, temp * 200.0f, - 0, 8); + func_8002836C(play, &this->meleeWeaponInfo[0].tip, &D_808547A4, &D_808547B0, &D_808547BC, &D_808547C0, + temp * 200.0f, 0, 8); } void Player_UpdateBodyShock(PlayState* play, Player* this) { @@ -11257,8 +11259,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { func_808473D4(play, this); func_80836BEC(this, play); - if ((this->heldItemAction == PLAYER_IA_DEKU_STICK) && ((this->unk_860 != 0) || CVarGetInteger("gDekuStickCheat", DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE)) { - func_80848A04(play, this); + if (this->heldItemAction == PLAYER_IA_DEKU_STICK && + GameInteractor_Should(GI_VB_DEKU_STICK_BE_ON_FIRE, this->unk_860 != 0, NULL)) { + Player_UpdateBurningDekuStick(play, this); } else if ((this->heldItemAction == PLAYER_IA_FISHING_POLE) && (this->unk_860 < 0)) { this->unk_860++; } @@ -11467,11 +11470,11 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { CsCmdActorAction* linkActionCsCmd = play->csCtx.linkAction; if ((linkActionCsCmd != NULL) && (D_808547C4[linkActionCsCmd->action] != 0)) { - func_8002DF54(play, NULL, 6); + Player_SetCsActionWithHaltedActors(play, NULL, 6); Player_ZeroSpeedXZ(this); } else if ((this->csAction == 0) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER) && (play->csCtx.state != CS_STATE_UNSKIPPABLE_INIT)) { - func_8002DF54(play, NULL, 0x31); + Player_SetCsActionWithHaltedActors(play, NULL, 0x31); Player_ZeroSpeedXZ(this); } } @@ -13542,7 +13545,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) { play->msgCtx.msgMode = MSGMODE_TEXT_DONE; } else { if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) { - if (this->getItemId == GI_GAUNTLETS_SILVER && !IS_RANDO) { + if (GameInteractor_Should(GI_VB_PLAY_NABOORU_CAPTURED_CS, this->getItemId == GI_GAUNTLETS_SILVER, NULL)) { play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0; play->transitionTrigger = TRANS_TRIGGER_START; gSaveContext.nextCutsceneIndex = 0xFFF1; @@ -13558,11 +13561,13 @@ s32 func_8084DFF4(PlayState* play, Player* this) { this->unk_862 = 0; } + // #region SOH [Randomizer] TODO Better Ice trap handling? if (this->getItemEntry.itemId == RG_ICE_TRAP && this->getItemEntry.modIndex == MOD_RANDOMIZER) { this->unk_862 = 0; gSaveContext.pendingIceTrapCount++; Player_SetPendingFlag(this, play); } + // #endregion this->getItemId = GI_NONE; this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; @@ -15330,7 +15335,7 @@ void func_808515A4(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_80851688(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (func_8084B3CC(play, this) == 0) { if ((this->csAction == 0x31) && (play->csCtx.state == CS_STATE_IDLE)) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); return; } @@ -15827,6 +15832,7 @@ void func_808526EC(PlayState* play, Player* this, CsCmdActorAction* arg2) { void func_8085283C(PlayState* play, Player* this, CsCmdActorAction* arg2) { if (LinkAnimation_Update(play, &this->skelAnime)) { func_80852944(play, this, arg2); + // This is when link picks up the sword in the Ganon fight } else if (this->av2.actionVar2 == 0) { Item_Give(play, ITEM_SWORD_MASTER); func_80846720(play, this, 0); @@ -15910,7 +15916,7 @@ void func_80852C50(PlayState* play, Player* this, CsCmdActorAction* arg2) { s32 sp24; if (play->csCtx.state == CS_STATE_UNSKIPPABLE_INIT) { - func_8002DF54(play, NULL, 7); + Player_SetCsActionWithHaltedActors(play, NULL, 7); this->cueId = 0; Player_ZeroSpeedXZ(this); return; @@ -16052,7 +16058,7 @@ void Player_StartTalking(PlayState* play, Actor* actor) { this->exchangeItemId = EXCH_ITEM_NONE; if (actor->textId == 0xFFFF) { - func_8002DF54(play, actor, 1); + Player_SetCsActionWithHaltedActors(play, actor, 1); actor->flags |= ACTOR_FLAG_PLAYER_TALKED_TO; func_80832528(play, this); } else {