Merge pull request #3755 from garrettjoecox/develop-rando-changes

Vanilla Behavior Overhaul
This commit is contained in:
Garrett Cox 2024-05-05 15:12:43 -05:00 committed by GitHub
commit 04f9ec1b78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
208 changed files with 6144 additions and 4529 deletions

@ -1 +1 @@
Subproject commit b135db823aaabf6e848fcbd2796933b0771f9968
Subproject commit 493639d5daf75c8fa5d374f96fc95b652714299f

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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);
}

View File

@ -0,0 +1,56 @@
#include <libultraship/bridge.h>
#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<GameInteractor::OnLoadGame>([](int32_t fileNum) mutable {
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook);
onVanillaBehaviorHook = 0;
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(CheatsOnVanillaBehaviorHandler);
});
}

View File

@ -0,0 +1,6 @@
#ifndef CHEAT_HOOK_HANDLERS_H
#define CHEAT_HOOK_HANDLERS_H
void CheatsRegisterHooks();
#endif // CHEAT_HOOK_HANDLERS_H

View File

@ -349,22 +349,9 @@ const std::vector<FlagTable> 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<FlagTable> 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<FlagTable> 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<FlagTable> 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" },
} },
};

View File

@ -34,6 +34,8 @@ std::vector<ValueTableElement> 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

View File

@ -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,

View File

@ -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 <z64.h>
@ -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 <thread>
#include <unordered_map>
#include <vector>
#include <functional>
#include <string>
@ -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));

View File

@ -90,6 +90,11 @@ void GameInteractor_ExecuteOnPlayDrawEnd() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawEnd>();
}
bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnVanillaBehavior>(flag, &result, opt);
return result;
}
// MARK: - Save Files
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {

View File

@ -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);

View File

@ -10,6 +10,9 @@
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include <soh/Enhancements/item-tables/ItemTableManager.h>
#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();

View File

@ -280,6 +280,20 @@ const std::vector<const char*> 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<const char*> cheatCvars = {

View File

@ -1121,7 +1121,19 @@ int Fill() {
std::vector<RandomizerGet> 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);

View File

@ -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}),

View File

@ -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)) {

View File

@ -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

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
#ifndef RANDOMIZER_HOOK_HANDLERS_H
#define RANDOMIZER_HOOK_HANDLERS_H
void RandomizerRegisterHooks();
#endif // RANDOMIZER_HOOK_HANDLERS_H

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
};

View File

@ -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<RandomizerCheck> 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<RandomizerCheck> 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,10 +603,9 @@ 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
// 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);
@ -609,77 +615,82 @@ void Rando::StaticData::InitLocationTable() {
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_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_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_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_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::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_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_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::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_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_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_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_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_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_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(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_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);
@ -691,14 +702,14 @@ void Rando::StaticData::InitLocationTable() {
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_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
@ -708,37 +719,37 @@ void Rando::StaticData::InitLocationTable() {
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_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_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_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::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_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_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_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);
@ -748,25 +759,24 @@ void Rando::StaticData::InitLocationTable() {
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_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_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);
// 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_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::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_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);
@ -782,9 +792,8 @@ void Rando::StaticData::InitLocationTable() {
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_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);
// Dodongo's Cavern Vanilla
@ -793,10 +802,10 @@ void Rando::StaticData::InitLocationTable() {
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_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);
@ -804,17 +813,16 @@ void Rando::StaticData::InitLocationTable() {
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_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_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);
@ -828,7 +836,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -857,7 +864,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -887,7 +893,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -907,7 +912,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -951,7 +955,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -992,7 +995,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -1007,7 +1009,7 @@ void Rando::StaticData::InitLocationTable() {
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_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);
@ -1015,7 +1017,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -1027,7 +1028,6 @@ void Rando::StaticData::InitLocationTable() {
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);
@ -1070,7 +1070,6 @@ void Rando::StaticData::InitLocationTable() {
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);
// Ganon's Castle Vanilla
@ -1089,10 +1088,10 @@ void Rando::StaticData::InitLocationTable() {
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_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);
@ -1107,16 +1106,16 @@ void Rando::StaticData::InitLocationTable() {
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_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
// 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);
@ -1213,7 +1212,7 @@ void Rando::StaticData::InitLocationTable() {
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
// 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);
@ -1283,20 +1282,20 @@ void Rando::StaticData::InitLocationTable() {
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);
// 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::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP, true);
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
// 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);
@ -1306,76 +1305,76 @@ void Rando::StaticData::InitLocationTable() {
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);
// 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::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);
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
// 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::Chest(0x43, 0x1F), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, 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::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);
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,7 +1382,6 @@ 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);
@ -1462,7 +1460,7 @@ void Rando::StaticData::InitLocationTable() {
| 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
// 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);
@ -1514,8 +1512,7 @@ void Rando::StaticData::InitLocationTable() {
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
// 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", {});

View File

@ -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] =

View File

@ -145,21 +145,6 @@ Randomizer::Randomizer() {
Randomizer::~Randomizer() {
}
std::unordered_map<std::string, RandomizerInf> 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<std::string, SceneID> 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<s32, TrialKey> 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;

View File

@ -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);

View File

@ -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,

View File

@ -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<GameInteractor::OnExitGame>([](uint32_t fileNum) {
Teardown();
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
// GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet);
// GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet);
// GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet);
hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1);
alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0);

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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) {

View File

@ -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") {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
#ifndef TIMESAVER_HOOK_HANDLERS_H
#define TIMESAVER_HOOK_HANDLERS_H
void TimeSaverRegisterHooks();
#endif // TIMESAVER_HOOK_HANDLERS_H

View File

@ -3,6 +3,7 @@
#include <cassert>
#include <File.h>
#include <Json.h>
#include <libultraship/classes.h>
#include <nlohmann/json.hpp>
#include <spdlog/fmt/fmt.h>
@ -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<LUS::ResourceInitData>();
initData->Format = RESOURCE_FORMAT_BINARY;
initData->Type = static_cast<uint32_t>(SOH::ResourceType::SOH_RawJson);
initData->Type = static_cast<uint32_t>(LUS::ResourceType::Json);
initData->ResourceVersion = 0;
sceneMap = std::static_pointer_cast<SOH::RawJson>(
sceneMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/scenes" + languageSuffix, true, initData))->Data;
miscMap = std::static_pointer_cast<SOH::RawJson>(
miscMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/misc" + languageSuffix, true, initData))->Data;
kaleidoMap = std::static_pointer_cast<SOH::RawJson>(
kaleidoMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/kaleidoscope" + languageSuffix, true, initData))->Data;
fileChooseMap = std::static_pointer_cast<SOH::RawJson>(
fileChooseMap = std::static_pointer_cast<LUS::Json>(
LUS::Context::GetInstance()->GetResourceManager()->LoadResource("accessibility/texts/filechoose" + languageSuffix, true, initData))->Data;
}

View File

@ -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<SOH::ResourceFactoryBinaryAudioSoundFontV2>(), RESOURCE_FORMAT_BINARY, "AudioSoundFont", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(), RESOURCE_FORMAT_BINARY, "AudioSequence", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY, "Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0);
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryRawJsonV0>(), RESOURCE_FORMAT_BINARY, "RawJson", static_cast<uint32_t>(SOH::ResourceType::SOH_RawJson), 0);
gSaveStateMgr = std::make_shared<SaveStateMgr>();
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)

View File

@ -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);

View File

@ -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++) {

View File

@ -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);
@ -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");

View File

@ -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<LUS::IResource> ResourceFactoryBinaryRawJsonV0::ReadResource(std::shared_ptr<LUS::File> file) {
if (!FileHasValidFormatAndReader(file)) {
return nullptr;
}
auto rawJson = std::make_shared<RawJson>(file->InitData);
auto reader = std::get<std::shared_ptr<LUS::BinaryReader>>(file->Reader);
rawJson->DataSize = file->Buffer->size();
rawJson->Data = nlohmann::json::parse(reader->ReadCString(), nullptr, true, true);
return rawJson;
}
} // namespace SOH

View File

@ -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<LUS::IResource> ReadResource(std::shared_ptr<LUS::File> file) override;
};
}; // namespace SOH

View File

@ -1,14 +0,0 @@
#include "RawJson.h"
namespace SOH {
RawJson::RawJson() : Resource(std::shared_ptr<LUS::ResourceInitData>()) {
}
void* RawJson::GetPointer() {
return &Data;
}
size_t RawJson::GetPointerSize() {
return DataSize * sizeof(char);
}
} // namespace SOH

View File

@ -1,20 +0,0 @@
#pragma once
#include "resource/Resource.h"
#include <nlohmann/json.hpp>
namespace SOH {
class RawJson : public LUS::Resource<void> {
public:
using Resource::Resource;
RawJson();
void* GetPointer() override;
size_t GetPointerSize() override;
nlohmann::json Data;
size_t DataSize;
};
}; // namespace SOH

View File

@ -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

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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:
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;
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:
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);
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) {
} 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);
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) {
} 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) ||
(bShouldTowerRandoSkip &&
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR)) {
} 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;
}
}

View File

@ -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;
}
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) {
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) {
func_8002F554(&this->actor, play, getItemId);
} else {
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(this->randoInf);
}
}
}
}
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);
}
}
}
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,17 +1440,6 @@ 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;
}
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);
@ -1481,7 +1452,6 @@ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
}
/**
* Sometimes convert the given drop ID into a bombchu.

View File

@ -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) {

View File

@ -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));

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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,6 +225,7 @@ 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 (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 {
@ -231,15 +233,18 @@ void func_8086D4B4(BgBdanSwitch* this, PlayState* play) {
}
}
}
}
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) {
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
}
}
}
}
void func_8086D5C4(BgBdanSwitch* this) {
this->actionFunc = func_8086D5E0;

View File

@ -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);
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) {

View File

@ -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) {
isEligible = false;
}
}
if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GREAT_FAIRY_REWARD, isEligible, this)) {
Actor_Kill(&this->actor);
return;
}
}
func_8002DF54(play, &this->actor, 1);
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) {

View File

@ -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) {
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);

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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,9 +150,11 @@ 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);
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM);
}
}
}
void BgMoriBigst_SetupFall(BgMoriBigst* this, PlayState* play) {
BgMoriBigst_SetupAction(this, BgMoriBigst_Fall);
@ -163,10 +166,12 @@ 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);
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);
}
}
}
void BgMoriBigst_SetupLanding(BgMoriBigst* this, PlayState* play) {
s32 pad;

View File

@ -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 {

View File

@ -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) {

View File

@ -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;

View File

@ -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;
@ -153,7 +141,6 @@ void func_808AC908(BgSpot02Objects* this, PlayState* play) {
this->actionFunc = func_808ACA08;
}
}
}
void func_808ACA08(BgSpot02Objects* this, PlayState* play) {
Player* player = GET_PLAYER(play);
@ -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++;

View File

@ -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

View File

@ -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;
}

View File

@ -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--;
}

View File

@ -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);
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;

View File

@ -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,11 +154,13 @@ void func_808BC8B8(BgTreemouth* this, PlayState* play) {
}
} else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) {
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
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 {
this->unk_168 = 1.0f;
}

View File

@ -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

View File

@ -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 {

View File

@ -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 };

View File

@ -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);

View File

@ -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->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;

View File

@ -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;
}

View File

@ -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) {
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;
} 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;
}
}
break;
case DEATH_LIMP:
@ -991,9 +963,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
bodyDecayLevel = 1;
break;
}
if (IS_RANDO || IS_BOSS_RUSH) {
break;
}
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);
@ -1012,6 +982,7 @@ void BossGanondrof_Death(BossGanondrof* this, PlayState* play) {
holdCamera = true;
bodyDecayLevel = 1;
}
}
break;
case DEATH_WARP:
if (this->timers[1] == 1) {
@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);

View File

@ -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,

View File

@ -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) {

View File

@ -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,8 +185,10 @@ 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);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FIRE);
}
}
void func_80969FB4(DemoDu* this, PlayState* play) {
this->actor.shape.yOffset += 250.0f / 3.0f;
@ -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;
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;
}

View File

@ -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,14 +2087,49 @@ 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);
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);
GetItem_Draw(play, this->getItem.drawId);

View File

@ -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,8 +319,10 @@ void func_809853B4(DemoIm* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0,
0, 0, 0xD);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_SHADOW);
}
}
void func_80985430(DemoIm* this, PlayState* play) {
this->actor.shape.yOffset += 250.0f / 3.0f;
@ -334,7 +337,9 @@ void func_8098544C(DemoIm* this, PlayState* play) {
this->action = 1;
play->csCtx.segment = D_8098786C;
gSaveContext.cutsceneTrigger = 2;
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;

View File

@ -51,4 +51,6 @@ typedef struct DemoIm {
/* 0x02D4 */ NpcInteractInfo interactInfo;
} DemoIm; // size = 0x02FC
void func_80986794(DemoIm* demoIm);
#endif

View File

@ -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);
}

View File

@ -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,8 +242,10 @@ void func_8098E8C8(DemoSa* this, PlayState* play) {
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
0xB);
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) {
Item_Give(play, ITEM_MEDALLION_FOREST);
}
}
void func_8098E944(DemoSa* this, PlayState* play) {
this->actor.shape.yOffset += (250.0f / 3.0f);
@ -258,7 +261,9 @@ void func_8098E960(DemoSa* this, PlayState* play) {
this->action = 1;
play->csCtx.segment = D_8099010C;
gSaveContext.cutsceneTrigger = 2;
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;

View File

@ -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 = {

View File

@ -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);
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);
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);
}
}

View File

@ -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;
@ -533,15 +496,10 @@ 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;
}
} 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;
}
} 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) {
// 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) {
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);
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY);
if (IS_RANDO) {
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
gSaveContext.nextCutsceneIndex = 0;
} else {
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) {
Item_Give(play, ITEM_ZORA_SAPPHIRE);
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
}
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;
}
} 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;
}
} 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;
}
} 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;
}
} 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;
}
} else {
if (!LINK_IS_ADULT) {
play->nextEntranceIndex = ENTR_GRAVEYARD_7;

View File

@ -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,10 +126,12 @@ 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))) {
if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) {
player->naviTextId = ElfMsg_GetMessageId(this);
navi->elfMsg = this;
}
}
}
s32 ElfMsg_WithinXZDistance(Vec3f* pos1, Vec3f* pos2, f32 distance) {
return (SQ(pos2->x - pos1->x) + SQ(pos2->z - pos1->z)) < SQ(distance);
@ -145,10 +148,12 @@ 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))) {
if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) {
player->naviTextId = ElfMsg_GetMessageId(this);
navi->elfMsg = this;
}
}
}
void ElfMsg_Update(Actor* thisx, PlayState* play) {
ElfMsg* this = (ElfMsg*)thisx;

View File

@ -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);
}
}

View File

@ -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;
}
}

Some files were not shown because too many files have changed in this diff Show More