diff --git a/soh/soh/Enhancements/Cheats/NoLikeLikeItemSteal.cpp b/soh/soh/Enhancements/Cheats/NoLikeLikeItemSteal.cpp new file mode 100644 index 00000000000..825ecbe1bfb --- /dev/null +++ b/soh/soh/Enhancements/Cheats/NoLikeLikeItemSteal.cpp @@ -0,0 +1,17 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "macros.h" +} + +static constexpr int32_t CVAR_NOLIKELIKEITEMSTEAL_DEFAULT = 0; +#define CVAR_NOLIKELIKEITEMSTEAL_NAME CVAR_CHEAT("NoLikeLikeItemSteal") +#define CVAR_NOLIKELIKEITEMSTEAL_VALUE CVarGetInteger(CVAR_NOLIKELIKEITEMSTEAL_NAME, CVAR_NOLIKELIKEITEMSTEAL_DEFAULT) + +void RegisterNoLikeLikeItemSteal() { + COND_VB_SHOULD(VB_LIKE_LIKE_STEAL_EQUIPMENT, CVAR_NOLIKELIKEITEMSTEAL_VALUE, { *should = false; }); +} + +static RegisterShipInitFunc initFunc(RegisterNoLikeLikeItemSteal, { CVAR_NOLIKELIKEITEMSTEAL_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/cosmetics/CustomSkeletons.cpp b/soh/soh/Enhancements/CustomSkeletons.cpp similarity index 100% rename from soh/soh/Enhancements/cosmetics/CustomSkeletons.cpp rename to soh/soh/Enhancements/CustomSkeletons.cpp diff --git a/soh/soh/Enhancements/DropThrowOnlyActors.cpp b/soh/soh/Enhancements/DropThrowOnlyActors.cpp new file mode 100644 index 00000000000..260f1f183d8 --- /dev/null +++ b/soh/soh/Enhancements/DropThrowOnlyActors.cpp @@ -0,0 +1,17 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +void OnAllowThrowOnlyDrop(void* actor) { + Actor* thisx = (Actor*)actor; + if (CVarGetInteger(CVAR_ENHANCEMENT("DropThrowOnlyObjects"), 0)) { + thisx->flags &= ~ACTOR_FLAG_THROW_ONLY; + } else { + thisx->flags |= ACTOR_FLAG_THROW_ONLY; + } +} + +void RegisterAllowThrowOnlyDrop() { + GameInteractor::Instance->RegisterGameHook(OnAllowThrowOnlyDrop); +} + +static RegisterShipInitFunc initFunc(RegisterAllowThrowOnlyDrop, { CVAR_ENHANCEMENT("DropThrowOnlyObjects") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp index c54f593b791..f788411a1dd 100644 --- a/soh/soh/Enhancements/ExtraTraps.cpp +++ b/soh/soh/Enhancements/ExtraTraps.cpp @@ -3,6 +3,8 @@ #include "soh/Enhancements/randomizer/3drando/random.hpp" #include "soh/Notification/Notification.h" #include "soh/OTRGlobals.h" +#include "soh/SohGui/ImGuiUtils.h" +#include "soh/SaveManager.h" extern "C" { #include "variables.h" @@ -10,6 +12,8 @@ extern "C" { #include "macros.h" extern PlayState* gPlayState; GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID); +GetItemID RetrieveGetItemIDFromItemID(ItemID itemID); +RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID); } #define CVAR_EXTRA_TRAPS_NAME CVAR_ENHANCEMENT("ExtraTraps.Enabled") @@ -27,19 +31,49 @@ typedef enum { ADD_AMMO_TRAP, ADD_KILL_TRAP, ADD_TELEPORT_TRAP, + ADD_POCKET_TRAP, + ADD_PERMADEATH_TRAP, ADD_TRAP_MAX } AltTrapType; static AltTrapType roll = ADD_TRAP_MAX; static int statusTimer = -1; static int eventTimer = -1; +static int permaDeathTimer = -1; +bool shouldFileDelete = false; const char* altTrapTypeCvars[] = { - CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"), - CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"), - CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"), - CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"), - CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"), + CVAR_ENHANCEMENT("ExtraTraps.Ice"), CVAR_ENHANCEMENT("ExtraTraps.Burn"), + CVAR_ENHANCEMENT("ExtraTraps.Shock"), CVAR_ENHANCEMENT("ExtraTraps.Knockback"), + CVAR_ENHANCEMENT("ExtraTraps.Speed"), CVAR_ENHANCEMENT("ExtraTraps.Bomb"), + CVAR_ENHANCEMENT("ExtraTraps.Void"), CVAR_ENHANCEMENT("ExtraTraps.Ammo"), + CVAR_ENHANCEMENT("ExtraTraps.Kill"), CVAR_ENHANCEMENT("ExtraTraps.Teleport"), + CVAR_ENHANCEMENT("ExtraTraps.Pocket"), CVAR_ENHANCEMENT("ExtraTraps.Permadeath"), +}; + +static std::unordered_map itemToQuestMap = { + { ITEM_MEDALLION_FOREST, QUEST_MEDALLION_FOREST }, + { ITEM_MEDALLION_FIRE, QUEST_MEDALLION_FIRE }, + { ITEM_MEDALLION_WATER, QUEST_MEDALLION_WATER }, + { ITEM_MEDALLION_SPIRIT, QUEST_MEDALLION_SPIRIT }, + { ITEM_MEDALLION_SHADOW, QUEST_MEDALLION_SHADOW }, + { ITEM_MEDALLION_LIGHT, QUEST_MEDALLION_LIGHT }, + { ITEM_SONG_MINUET, QUEST_SONG_MINUET }, + { ITEM_SONG_BOLERO, QUEST_SONG_BOLERO }, + { ITEM_SONG_SERENADE, QUEST_SONG_SERENADE }, + { ITEM_SONG_REQUIEM, QUEST_SONG_REQUIEM }, + { ITEM_SONG_NOCTURNE, QUEST_SONG_NOCTURNE }, + { ITEM_SONG_PRELUDE, QUEST_SONG_PRELUDE }, + { ITEM_SONG_LULLABY, QUEST_SONG_LULLABY }, + { ITEM_SONG_EPONA, QUEST_SONG_EPONA }, + { ITEM_SONG_SARIA, QUEST_SONG_SARIA }, + { ITEM_SONG_SUN, QUEST_SONG_SUN }, + { ITEM_SONG_TIME, QUEST_SONG_TIME }, + { ITEM_SONG_STORMS, QUEST_SONG_STORMS }, + { ITEM_KOKIRI_EMERALD, QUEST_KOKIRI_EMERALD }, + { ITEM_GORON_RUBY, QUEST_GORON_RUBY }, + { ITEM_ZORA_SAPPHIRE, QUEST_ZORA_SAPPHIRE }, + { ITEM_GERUDO_CARD, QUEST_GERUDO_CARD }, }; std::vector getEnabledAddTraps() { @@ -59,11 +93,149 @@ std::vector getEnabledAddTraps() { return enabledAddTraps; }; +void TriggerVoidOut() { + Player* player = GET_PLAYER(gPlayState); + + Audio_PlaySoundGeneral(NA_SE_EN_BUBLE_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + // Hyrule Castle: Very likely to fall through floor, so we force a specific entrance + if (gPlayState->sceneNum == SCENE_HYRULE_CASTLE || gPlayState->sceneNum == SCENE_OUTSIDE_GANONS_CASTLE) { + gPlayState->nextEntranceIndex = ENTR_CASTLE_GROUNDS_SOUTH_EXIT; + } else { + gSaveContext.respawnFlag = 1; + gPlayState->nextEntranceIndex = gSaveContext.entranceIndex; + + // Preserve the player's position and orientation + gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = gPlayState->nextEntranceIndex; + gSaveContext.respawn[RESPAWN_MODE_DOWN].roomIndex = gPlayState->roomCtx.curRoom.num; + gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = player->actor.world.pos; + gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = player->actor.shape.rot.y; + + if (gPlayState->roomCtx.curRoom.behaviorType2 < 4) { + gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0DFF; + } else { + // Scenes with static backgrounds use a special camera we need to preserve + Camera* camera = GET_ACTIVE_CAM(gPlayState); + s16 camId = camera->camDataIdx; + gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0D00 | camId; + } + } + + gPlayState->transitionTrigger = TRANS_TRIGGER_START; + gPlayState->transitionType = TRANS_TYPE_INSTANT; + gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST; +} + +void ExecutePocketTrap() { + std::vector currentLoadout; + + for (auto& items : itemMapping) { + if (INV_CONTENT(items.second.id) == items.second.id) { + currentLoadout.push_back(items.second.id); + continue; + } + auto questItem = itemToQuestMap.find( + (ItemID)items.second.id); // std::find(itemToQuestMap.begin(), itemToQuestMap.end(), items.second.id); + if (questItem == itemToQuestMap.end()) { + continue; + } + if (CHECK_QUEST_ITEM(questItem->second)) { + currentLoadout.push_back(items.second.id); + continue; + } + } + + if (currentLoadout.size() == 0) { + GameInteractor::RawAction::FreezePlayer(); + return; + } + + RandomizerGet rgItem = RG_NONE; + + uint32_t roll = Random(0, currentLoadout.size() - 1); + if (currentLoadout[roll] >= ITEM_SONG_MINUET) { + rgItem = RetrieveRandomizerGetFromItemID((ItemID)currentLoadout[roll]); + } else { + GetItemID getItemId = RetrieveGetItemIDFromItemID((ItemID)currentLoadout[roll]); + for (auto& randoGet : Rando::StaticData::GetItemTable()) { + if (randoGet.GetItemID() == getItemId) { + rgItem = randoGet.GetRandomizerGet(); + break; + } + } + } + + if (rgItem == RG_NONE) { + GameInteractor::RawAction::FreezePlayer(); + return; + } + + for (auto& check : Rando::StaticData::GetLocationTable()) { + if (Rando::Context::GetInstance()->GetItemLocation(check.GetRandomizerCheck())->GetPlacedRandomizerGet() == + rgItem) { + if (check.GetRandomizerCheck() == RC_UNKNOWN_CHECK || check.GetRandomizerCheck() == RC_LINKS_POCKET) { + GameInteractor::RawAction::FreezePlayer(); + return; + } + switch (check.GetActorID()) { + case ACTOR_EN_BOX: + GameInteractor::RawAction::UnsetSceneFlag(check.GetScene(), FLAG_SCENE_TREASURE, + check.GetActorParams() & 0x1F); + break; + default: + if (check.GetCollectionCheck().type != SPOILER_CHK_NONE) { + switch (check.GetCollectionCheck().type) { + case SPOILER_CHK_ITEM_GET_INF: + Flags_UnsetItemGetInf(check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_RANDOMIZER_INF: + Flags_UnsetRandomizerInf((RandomizerInf)check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_EVENT_CHK_INF: + Flags_UnsetEventInf(check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_CHEST: + GameInteractor::RawAction::UnsetSceneFlag(check.GetScene(), FLAG_SCENE_TREASURE, + check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_COLLECTABLE: + GameInteractor::RawAction::UnsetSceneFlag(check.GetScene(), FLAG_SCENE_COLLECTIBLE, + check.GetCollectionCheck().flag); + break; + case SPOILER_CHK_INF_TABLE: + Flags_UnsetInfTable(check.GetCollectionCheck().flag); + break; + default: + GameInteractor::RawAction::FreezePlayer(); + return; + } + } + break; + } + + Rando::Context::GetInstance()->GetItemLocation(check.GetRandomizerCheck())->SetCheckStatus(RCSHOW_SEEN); + INV_CONTENT(currentLoadout[roll]) = ITEM_NONE; + break; + } + } + + Notification::Emit({ .itemIcon = (const char*)gItemIcons[currentLoadout[roll]], + .prefix = "You've lost your", + .prefixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), + .message = Rando::StaticData::RetrieveItem(rgItem).GetName().english.c_str(), + .messageColor = UIWidgets::ColorValues.at(UIWidgets::Colors::Green), + .suffix = ". I remember seeing it somewhere...", + .suffixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White) }); + + TriggerVoidOut(); +} + static void RollRandomTrap(uint32_t seed) { uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : static_cast(gSaveContext.ship.stats.fileCreatedAt)); Random_Init(finalSeed); - + // roll = ADD_PERMADEATH_TRAP; roll = RandomElement(getEnabledAddTraps()); switch (roll) { case ADD_ICE_TRAP: @@ -103,6 +275,18 @@ static void RollRandomTrap(uint32_t seed) { case ADD_TELEPORT_TRAP: eventTimer = 3; break; + case ADD_POCKET_TRAP: + ExecutePocketTrap(); + break; + case ADD_PERMADEATH_TRAP: + permaDeathTimer = 180; + shouldFileDelete = true; + Notification::Emit({ .itemIcon = (const char*)gItemIcons[ITEM_BOMB], + .message = "Collect a Check or Perma Death executes in ", + .messageColor = UIWidgets::ColorValues.at(UIWidgets::Colors::White), + .suffix = "60 seconds.", + .suffixColor = UIWidgets::ColorValues.at(UIWidgets::Colors::Red) }); + break; default: break; } @@ -167,6 +351,17 @@ static void OnPlayerUpdate() { break; } } + if (permaDeathTimer == 0) { + if (shouldFileDelete) { + SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); + std::reinterpret_pointer_cast( + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) + ->Dispatch("reset"); + } + } + if (permaDeathTimer >= 0) { + permaDeathTimer--; + } if (statusTimer >= 0) { statusTimer--; } @@ -195,6 +390,20 @@ void RegisterExtraTraps() { GameInteractor::RawAction::FreezePlayer(); } }); + + COND_HOOK(OnFlagSet, CVAR_EXTRA_TRAPS_NAME, [](int16_t flagType, int16_t flag) { + SPDLOG_INFO("Flag Set Here {}", std::to_string(flagType).c_str()); + if (flagType != FLAG_SCENE_CLEAR) { + shouldFileDelete = false; + } + }); + + COND_HOOK(OnSceneFlagSet, CVAR_EXTRA_TRAPS_NAME, [](int16_t sceneNum, int16_t flagType, int16_t flag) { + SPDLOG_INFO("Scene Flag Set Here {}", std::to_string(flagType).c_str()); + if (flagType != FLAG_SCENE_CLEAR) { + shouldFileDelete = false; + } + }); } static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME }); diff --git a/soh/soh/Enhancements/Presets/Presets.cpp b/soh/soh/Enhancements/Presets/Presets.cpp index e611a028a2f..fee5246ace2 100644 --- a/soh/soh/Enhancements/Presets/Presets.cpp +++ b/soh/soh/Enhancements/Presets/Presets.cpp @@ -250,18 +250,25 @@ void SavePreset(std::string& presetName) { } presets[presetName].presetValues["presetName"] = presetName; presets[presetName].presetValues["fileType"] = FILE_TYPE_PRESET; - std::ofstream file( - fmt::format("{}/{}.json", Ship::Context::GetInstance()->LocateFileAcrossAppDirs("presets"), presetName)); + std::ofstream file(FormatPresetPath(presetName)); file << presets[presetName].presetValues.dump(4); file.close(); LoadPresets(); } -static std::string newPresetName; +void DeletePreset(std::string& presetName) { + std::string presetPath = FormatPresetPath(presetName); + if (fs::exists(presetPath)) { + fs::remove(presetPath); + } + presets.erase(presetName); +} + +static std::string newPresetName, oldPresetName; static bool saveSection[PRESET_SECTION_MAX]; -void DrawNewPresetPopup() { - bool nameExists = presets.contains(newPresetName); +void DrawEditPresetPopup() { + bool nameExists = presets.contains(newPresetName) && newPresetName != oldPresetName; UIWidgets::InputString("Preset Name", &newPresetName, UIWidgets::InputOptions() .Color(THEME_COLOR) @@ -270,7 +277,7 @@ void DrawNewPresetPopup() { .LabelPosition(UIWidgets::LabelPositions::Near) .ErrorText("Preset name already exists") .HasError(nameExists)); - nameExists = presets.contains(newPresetName); + nameExists = presets.contains(newPresetName) && newPresetName != oldPresetName; bool noneSelected = true; for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) { if (saveSection[i]) { @@ -348,10 +355,15 @@ void DrawNewPresetPopup() { presets[newPresetName].fileName = newPresetName; std::fill_n(presets[newPresetName].apply, PRESET_SECTION_MAX, true); SavePreset(newPresetName); + if (newPresetName != oldPresetName) { + DeletePreset(oldPresetName); + } newPresetName = ""; + oldPresetName = ""; ImGui::CloseCurrentPopup(); } if (UIWidgets::Button("Cancel", UIWidgets::ButtonOptions().Padding({ 6.0f, 6.0f }).Color(THEME_COLOR))) { + oldPresetName = ""; ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); @@ -364,25 +376,32 @@ void PresetsCustomWidget(WidgetInfo& info) { .disabledTooltip = "Disabled because of race lockout" } }) .Size(UIWidgets::Sizes::Inline) .Color(THEME_COLOR))) { - ImGui::OpenPopup("newPreset"); + oldPresetName = ""; + newPresetName = ""; + std::fill_n(saveSection, PRESET_SECTION_MAX, true); + ImGui::OpenPopup("editPreset"); + } else if (oldPresetName != "") { + ImGui::OpenPopup("editPreset"); } - if (ImGui::BeginPopup("newPreset", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar)) { - DrawNewPresetPopup(); + if (ImGui::BeginPopup("editPreset", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar)) { + DrawEditPresetPopup(); } ImGui::SameLine(); UIWidgets::CVarCheckbox("Hide built-in presets", CVAR_GENERAL("HideBuiltInPresets"), UIWidgets::CheckboxOptions().Color(THEME_COLOR)); bool hideBuiltIn = CVarGetInteger(CVAR_GENERAL("HideBuiltInPresets"), 0); UIWidgets::PushStyleTabs(THEME_COLOR); - if (ImGui::BeginTable("PresetWidgetTable", PRESET_SECTION_MAX + 3)) { + if (ImGui::BeginTable("PresetWidgetTable", PRESET_SECTION_MAX + 4)) { ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 400); for (int i = PRESET_SECTION_SETTINGS; i < PRESET_SECTION_MAX; i++) { ImGui::TableSetupColumn(blockInfo[i].names[0].c_str()); } ImGui::TableSetupColumn("Apply", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("Apply").x + ImGui::GetStyle().FramePadding.x * 2); + ImGui::TableSetupColumn("Edit", ImGuiTableColumnFlags_WidthFixed, + ImGui::CalcTextSize("Edit").x + ImGui::GetStyle().FramePadding.x * 2); ImGui::TableSetupColumn("Delete", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("Delete").x + ImGui::GetStyle().FramePadding.x * 2); BlankButton(); @@ -431,13 +450,17 @@ void PresetsCustomWidget(WidgetInfo& info) { ImGui::TableNextColumn(); UIWidgets::PushStyleButton(THEME_COLOR); if (!info.isBuiltIn) { + if (UIWidgets::Button(("Edit##" + name).c_str(), UIWidgets::ButtonOptions().Padding({ 6.0f, 6.0f }))) { + std::copy(info.apply, info.apply + PRESET_SECTION_MAX, saveSection); + newPresetName = name; + oldPresetName = name; + } + UIWidgets::PopStyleButton(); + ImGui::TableNextColumn(); + UIWidgets::PushStyleButton(THEME_COLOR); if (UIWidgets::Button(("Delete##" + name).c_str(), UIWidgets::ButtonOptions().Padding({ 6.0f, 6.0f }))) { - auto path = FormatPresetPath(info.fileName); - if (fs::exists(path)) { - fs::remove(path); - } - presets.erase(name); + DeletePreset(info.fileName); UIWidgets::PopStyleButton(); break; } diff --git a/soh/soh/Enhancements/QoL/ResetNaviTimer.cpp b/soh/soh/Enhancements/QoL/ResetNaviTimer.cpp index b3048be538f..6f88067757c 100644 --- a/soh/soh/Enhancements/QoL/ResetNaviTimer.cpp +++ b/soh/soh/Enhancements/QoL/ResetNaviTimer.cpp @@ -14,4 +14,4 @@ static void RegisterResetNaviTimer() { COND_HOOK(OnSceneInit, CVAR_RESET_NAVI_VALUE, [](int32_t) { gSaveContext.naviTimer = 0; }); } -static RegisterShipInitFunc initFunc(RegisterResetNaviTimer, { CVAR_RESET_NAVI_NAME }); +static RegisterShipInitFunc initFunc(RegisterResetNaviTimer, { CVAR_RESET_NAVI_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/audio/DisableNaviCallAudio.cpp b/soh/soh/Enhancements/audio/DisableNaviCallAudio.cpp new file mode 100644 index 00000000000..2a2cfbc5780 --- /dev/null +++ b/soh/soh/Enhancements/audio/DisableNaviCallAudio.cpp @@ -0,0 +1,13 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +static constexpr int32_t CVAR_DISABLENAVICALLAUDIO_DEFAULT = 0; +#define CVAR_DISABLENAVICALLAUDIO_NAME CVAR_AUDIO("DisableNaviCallAudio") +#define CVAR_DISABLENAVICALLAUDIO_VALUE \ + CVarGetInteger(CVAR_DISABLENAVICALLAUDIO_NAME, CVAR_DISABLENAVICALLAUDIO_DEFAULT) + +void RegisterDisableNaviCallAudio() { + COND_VB_SHOULD(VB_PLAY_NAVI_CALL_SOUND, CVAR_DISABLENAVICALLAUDIO_VALUE, { *should = false; }); +} + +static RegisterShipInitFunc initFunc(RegisterDisableNaviCallAudio, { CVAR_DISABLENAVICALLAUDIO_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 49e74f69cf1..f2f77a68ebd 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1889,6 +1889,10 @@ void DrawSillyTab() { UIWidgets::Separator(true, true, 2.0f, 2.0f); + UIWidgets::CVarCheckbox( + "Invisible Navi", CVAR_COSMETIC("InvisibleNavi"), + UIWidgets::CheckboxOptions().Color(THEME_COLOR).Tooltip("Makes Navi invisible and disables her sounds.")); + UIWidgets::CVarCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"), UIWidgets::CheckboxOptions() .Color(THEME_COLOR) diff --git a/soh/soh/Enhancements/cosmetics/InvisibleNavi.cpp b/soh/soh/Enhancements/cosmetics/InvisibleNavi.cpp new file mode 100644 index 00000000000..ce1006e83e3 --- /dev/null +++ b/soh/soh/Enhancements/cosmetics/InvisibleNavi.cpp @@ -0,0 +1,63 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "src/overlays/actors/ovl_En_Elf/z_en_elf.h" +} + +static constexpr int32_t CVAR_INVISIBLENAVI_DEFAULT = 0; +#define CVAR_INVISIBLENAVI_NAME CVAR_COSMETIC("InvisibleNavi") +#define CVAR_INVISIBLENAVI_VALUE CVarGetInteger(CVAR_INVISIBLENAVI_NAME, CVAR_INVISIBLENAVI_DEFAULT) + +void RegisterInvisibleNavi() { + COND_VB_SHOULD(VB_FAIRY_DRAW, CVAR_INVISIBLENAVI_VALUE, { + EnElf* enElf = va_arg(args, EnElf*); + if (enElf->actor.params == FAIRY_NAVI) { + *should = false; + } + }); + + COND_VB_SHOULD(VB_FAIRY_SPAWN_SPARKLES, CVAR_INVISIBLENAVI_VALUE, { + EnElf* enElf = va_arg(args, EnElf*); + if (enElf->actor.params == FAIRY_NAVI) { + *should = false; + } + }); + + COND_VB_SHOULD(VB_FAIRY_PLAY_C_UP_TALK_SOUND, CVAR_INVISIBLENAVI_VALUE, { + EnElf* enElf = va_arg(args, EnElf*); + if (enElf->actor.params == FAIRY_NAVI) { + *should = false; + } + }); + + COND_VB_SHOULD(VB_FAIRY_PLAY_DASH_SOUND, CVAR_INVISIBLENAVI_VALUE, { + EnElf* enElf = va_arg(args, EnElf*); + if (enElf->actor.params == FAIRY_NAVI) { + *should = false; + } + }); + + COND_VB_SHOULD(VB_FAIRY_PLAY_VANISH_SOUND, CVAR_INVISIBLENAVI_VALUE, { + EnElf* enElf = va_arg(args, EnElf*); + if (enElf->actor.params == FAIRY_NAVI) { + *should = false; + } + }); + + COND_VB_SHOULD(VB_FAIRY_UPDATE_LIGHTS, CVAR_INVISIBLENAVI_VALUE, { + EnElf* enElf = va_arg(args, EnElf*); + if (enElf->actor.params == FAIRY_NAVI) { + // Force Navi's light radius to zero. + Lights_PointGlowSetInfo(&enElf->lightInfoGlow, enElf->actor.world.pos.x, enElf->actor.world.pos.y, + enElf->actor.world.pos.z, 255, 255, 255, 0); + *should = false; + } + }); + + COND_VB_SHOULD(VB_PLAY_NAVI_CALL_SOUND, CVAR_INVISIBLENAVI_VALUE, { *should = false; }); + + COND_VB_SHOULD(VB_PLAY_INTRO_NAVI_SOUNDS, CVAR_INVISIBLENAVI_VALUE, { *should = false; }); +} + +static RegisterShipInitFunc initFunc(RegisterInvisibleNavi, { CVAR_INVISIBLENAVI_NAME }); \ No newline at end of file diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 342dc34fa44..89ecfe3a564 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1843,7 +1843,6 @@ void SaveEditorWindow::DrawElement() { DrawPlayerTab(); ImGui::EndTabItem(); } - ImGui::EndTabBar(); } diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 03b256172b8..a98b684055b 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -236,6 +236,15 @@ typedef enum { // - `*Actor` (interactRangeActor) VB_BOTTLE_ACTOR, + // #### `result` + // Actor is ACTOR_OBJ_BOMBIWA, or ACTOR_OBJ_HAMISHI + // ```c + // Flags_GetSwitch(play, this->actor.params & 0x3F) + // ``` + // #### `args` + // - `*Actor` (interactRangeActor) + VB_BOULDER_BREAK_FLAG, + // #### `result` // ```c // true @@ -326,6 +335,14 @@ typedef enum { // - `*ObjKibako2` VB_CRATE_SETUP_DRAW, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - None + VB_ROLL, + // #### `result` // ```c // true @@ -562,6 +579,14 @@ typedef enum { // - `int32_t` (startMode) VB_EXECUTE_PLAYER_STARTMODE_FUNC, + // #### `result` + // ```c + // ((this->unk_2A8 != 8) && !(this->fairyFlags & 8)) + // ``` + // #### `args` + // - `*EnElf` + VB_FAIRY_DRAW, + // #### `result` // ```c // true @@ -570,6 +595,47 @@ typedef enum { // - `*EnElf` VB_FAIRY_HEAL, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnElf` + // - `int32_t` (sparkleLife) + VB_FAIRY_SPAWN_SPARKLES, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnElf` + VB_FAIRY_PLAY_C_UP_TALK_SOUND, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnElf` + VB_FAIRY_PLAY_DASH_SOUND, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnElf` + VB_FAIRY_PLAY_VANISH_SOUND, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnElf` + VB_FAIRY_UPDATE_LIGHTS, + // #### `result` // ```c // false @@ -1461,6 +1527,14 @@ typedef enum { // - `*EnOkarinaTag` VB_OKARINA_TAG_COMPLETED, + // #### `result` + // ```c + // this->getItemId != GI_NONE + // ``` + // #### `args` + // - `None` + VB_OPEN_CHEST, + // #### `result` // ```c // CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) @@ -1663,6 +1737,14 @@ typedef enum { // - None VB_PLAY_GORON_FREE_CS, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*ObjectKankyo` + VB_PLAY_INTRO_NAVI_SOUNDS, + // #### `result` // ```c // true @@ -1687,6 +1769,14 @@ typedef enum { // - None VB_PLAY_NABOORU_CAPTURED_CS, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `int32_t` (naviCallState) (promoted from `uint16_t` by va_arg) + VB_PLAY_NAVI_CALL_SOUND, + // #### `result` // ```c // true @@ -1895,6 +1985,14 @@ typedef enum { // - None VB_REVERT_SPOILING_ITEMS, + // #### `result` + // ```c + // false + // ``` + // #### `args` + // - `*EnIshi` + VB_ROCK_DROP_ITEM, + // #### `result` // ```c // !Flags_GetInfTable(INFTABLE_145) @@ -2329,6 +2427,14 @@ typedef enum { // - `*Actor` VB_RECIEVE_FALL_DAMAGE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnRr` + VB_LIKE_LIKE_DROP_COLLECTIBLE, + // #### `result` // ```c // true @@ -2337,6 +2443,14 @@ typedef enum { // - `*EnRr` VB_LIKE_LIKE_GRAB_PLAYER, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnRr` + VB_LIKE_LIKE_STEAL_EQUIPMENT, + // #### `result` // ```c // entry != NULL diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp index 628ce24a58e..1c6ad2d2fe2 100644 --- a/soh/soh/Enhancements/gameplaystats.cpp +++ b/soh/soh/Enhancements/gameplaystats.cpp @@ -448,7 +448,7 @@ void DrawGameplayStatsHeader() { // if tag is empty (not a release build) if (gGitCommitTag[0] == 0) { GameplayStatsRow("Git Branch:", (char*)gGitBranch); - GameplayStatsRow("Git Commit Hash:", (char*)gGitCommitHash); + GameplayStatsRow("Version : 12 | Git Commit Hash:", (char*)gGitCommitHash); } else { GameplayStatsRow("Build Version:", (char*)gBuildVersion); } diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp index aa375716f68..87880711616 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp @@ -131,6 +131,10 @@ void StaticData::HintTable_Init_Exclude_Dungeon() { /*german*/ "Man erzählt sich, daß eine #Kiste im Deku-Baum# #[[1]]# enthielte.", /*french*/ "Selon moi, une #caisse dans l'Arbre Mojo# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DEKU_BOULDER] = HintText(CustomMessage("They say that a #boulder in the Deku Tree# contains #[[1]]#.", + /*german*/ "!!!", + /*french*/ "!!!", {QM_RED, QM_GREEN})); + /*-------------------------- | DODONGOS CAVERN | ---------------------------*/ @@ -313,6 +317,10 @@ void StaticData::HintTable_Init_Exclude_Dungeon() { /*german*/ "Man erzählt sich, daß eine #Kiste in Dodongos Höhle# #[[1]]# enthielte.", /*french*/ "Selon moi, une #caisse dans la Caverne Dodongo# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DODONGOS_BOULDER] = HintText(CustomMessage("They say that a #boulder in Dodongo's Cavern# contains #[[1]]#.", + /*german*/ "!!!", + /*french*/ "!!!", {QM_RED, QM_GREEN})); + /*-------------------------- | JABU JABUS BELLY | ---------------------------*/ @@ -480,6 +488,10 @@ void StaticData::HintTable_Init_Exclude_Dungeon() { /*german*/ "Man erzählt sich, daß eine #Kiste in Jabu-Jabus Bauch# #[[1]]# enthielte.", /*french*/ "Selon moi, une #caisse dans le Ventre de Jabu-Jabu# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_JABU_BOULDER] = HintText(CustomMessage("They say that a #boulder in Jabu Jabu's Belly# contains #[[1]]#.", + /*german*/ "!!!", + /*french*/ "!!!", {QM_RED, QM_GREEN})); + /*-------------------------- | FOREST TEMPLE | ---------------------------*/ @@ -1322,6 +1334,10 @@ void StaticData::HintTable_Init_Exclude_Dungeon() { /*german*/ "Man erzählt sich, daß eine #Kiste im Geistertempel# #[[1]]# enthielte.", /*french*/ "Selon moi, une #caisse dans le Temple de l'Esprit# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_SPIRIT_TEMPLE_BOULDER] = HintText(CustomMessage("They say that a #boulder in the Spirit Temple# contains #[[1]]#.", + /*german*/ "!!!", + /*french*/ "!!!", {QM_RED, QM_GREEN})); + /*-------------------------- | SHADOW TEMPLE | ---------------------------*/ @@ -1735,6 +1751,9 @@ void StaticData::HintTable_Init_Exclude_Dungeon() { /*german*/ "Man erzählt sich, daß etwas #Gras auf dem Grund des Brunnens# #[[1]]# verstecke.", /*french*/ "Selon moi, de l'#herbe dans le Puits# cache #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_BOTW_BOULDER] = HintText(CustomMessage("They say that a #boulder in Bottom of the Well# contains #[[1]]#.", + /*german*/ "!!!", + /*french*/ "!!!", {QM_RED, QM_GREEN})); /*-------------------------- | ICE CAVERN | diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index 487c761584b..d1cfdd1f866 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -2126,6 +2126,113 @@ void StaticData::HintTable_Init_Exclude_Overworld() { HintText(CustomMessage("They say that a #tree in Lon Lon Ranch# contains #[[1]]#.", /*german*/ "", /*french*/ "Selon moi, un #arbre au Ranch Lon Lon# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_KF_ROCK] = HintText(CustomMessage("They say that a #rock in Kokiri Forest# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, une #roche dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_LW_BOULDER] = HintText(CustomMessage("They say that a #boulder in the Lost Woods# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_HC_ROCK] = HintText(CustomMessage("They say that a #rock at Hyrule Castle# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_HC_BOULDER] = HintText(CustomMessage("They say that a #boulder at Hyrule Castle# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_OGC_BRONZE_BOULDER] = HintText(CustomMessage("They say that a #bronze boulder outside Ganon's Castle# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_OGC_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder outside Ganon's Castle# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DMC_ROCK] = HintText(CustomMessage("They say that a #rock in Death Mountain Crater# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DMC_BOULDER] = HintText(CustomMessage("They say that a #boulder in Death Mountain Crater# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DMC_BRONZE_BOULDER] = HintText(CustomMessage("They say that a #bronze boulder in Death Mountain Crater# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GV_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder in Gerudo Valley# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GV_ROCK] = HintText(CustomMessage("They say that a #rock in Gerudo Valley# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GV_BOULDER] = HintText(CustomMessage("They say that a #boulder in Gerudo Valley# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GV_BRONZE_BOULDER] = HintText(CustomMessage("They say that a #bronze boulder in Gerudo Valley# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_HF_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder on Hyrule Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_HF_ROCK] = HintText(CustomMessage("They say that a #rock on Hyrule Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_HF_BOULDER] = HintText(CustomMessage("They say that a #boulder on Hyrule Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_HF_BRONZE_BOULDER] = HintText(CustomMessage("They say that a #bronze boulder on Hyrule Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_KAK_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder at Kakariko Village# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_KAK_ROCK] = HintText(CustomMessage("They say that a #rock at Kakariko Village# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GY_ROCK] = HintText(CustomMessage("They say that a #rock in a graveyard# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_LA_ROCK] = HintText(CustomMessage("They say that a #rock at Lake Hylia# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_ZD_ROCK] = HintText(CustomMessage("They say that a #rock in Zora's Domain# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_ZF_BOULDER] = HintText(CustomMessage("They say that a #boulder in Zora's Fountain# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_ZF_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder in Zora's Fountain# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_ZR_ROCK] = HintText(CustomMessage("They say that a #rock along a river# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_ZR_BOULDER] = HintText(CustomMessage("They say that a #boulder along a river# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DMT_ROCK] = HintText(CustomMessage("They say that a #rock on Death Mountain Trail# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DMT_BOULDER] = HintText(CustomMessage("They say that a #boulder on Death Mountain Trail# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_DMT_BRONZE_BOULDER] = HintText(CustomMessage("They say that a #bronze boulder on Death Mountain Trail# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GC_ROCK] = HintText(CustomMessage("They say that a #rock in Goron City# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GC_BOULDER] = HintText(CustomMessage("They say that a #boulder in Goron City# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GC_BRONZE_BOULDER] = HintText(CustomMessage("They say that a #bronze boulder in Goron City# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_GC_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder in Goron City# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_COLOSSUS_SILVER_BOULDER] = HintText(CustomMessage("They say that a #silver boulder in a desert# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); + hintTextTable[RHT_COLOSSUS_ROCK] = HintText(CustomMessage("They say that a #rock in a desert# contains #[[1]]#.", + /*german*/ "", + /*french*/ "", {QM_RED, QM_GREEN})); hintTextTable[RHT_BUSH_HYRULE_FIELD] = HintText(CustomMessage("They say that a #bush in Hyrle Field# contains #[[1]]#.", diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index dacd6a28ad4..7bcf52e9342 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2109,6 +2109,10 @@ void StaticData::HintTable_Init_Item() { // /*spanish*/un desbloqueador maestro hintTextTable[RHT_CRAWL] = HintText(CustomMessage("the ability to crawl", /*german*/TODO_TRANSLATE, /*french*/"la capacité de ramper")); + hintTextTable[RHT_ROLL] = HintText(CustomMessage("the ability to roll", /*german*/"die Fähigkeit zu rollen", /*french*/"la capacité de faire des roulades")); + + hintTextTable[RHT_OPEN_CHEST] = HintText(CustomMessage("the ability to open chests", /*german*/"!!!", /*french*/"!!!")); + //RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini")); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index ec5a646d79b..4860a571f09 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -392,6 +392,13 @@ void GenerateItemPool() { int bronzeScale = ctx->GetOption(RSK_SHUFFLE_SWIM) ? 1 : 0; AddItemToPool(RG_PROGRESSIVE_SCALE, 3 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale, 2 + bronzeScale); + if (ctx->GetOption(RSK_SHUFFLE_ROLL)) { + AddItemToPool(RG_ROLL, 2, 1, 1, 1); + } + + if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST)) { + AddItemToPool(RG_OPEN_CHEST, 2, 1, 1, 1); + if (ctx->GetOption(RSK_SHUFFLE_CRAWL)) { AddItemToPool(RG_CRAWL, 2, 1, 1, 1); } @@ -428,6 +435,17 @@ void GenerateItemPool() { ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) && dungeonCratesActive); PlaceItemsForType(RCTYPE_SMALL_CRATE, overworldCratesActive, dungeonCratesActive); + // Shuffle Rocks + bool rocksActive = ctx->GetOption(RSK_SHUFFLE_ROCKS).Get(); + PlaceItemsForType(RCTYPE_ROCK, rocksActive, rocksActive); + + // Shuffle Boulders + bool overworldBouldersActive = ctx->GetOption(RSK_SHUFFLE_BOULDERS).Is(RO_SHUFFLE_BOULDERS_OVERWORLD) || + ctx->GetOption(RSK_SHUFFLE_BOULDERS).Is(RO_SHUFFLE_BOULDERS_ALL); + bool dungeonBouldersActive = ctx->GetOption(RSK_SHUFFLE_BOULDERS).Is(RO_SHUFFLE_BOULDERS_DUNGEONS) || + ctx->GetOption(RSK_SHUFFLE_BOULDERS).Is(RO_SHUFFLE_BOULDERS_ALL); + PlaceItemsForType(RCTYPE_BOULDER, overworldBouldersActive, dungeonBouldersActive); + if (ctx->GetOption(RSK_FISHSANITY).Is(RO_FISHSANITY_HYRULE_LOACH)) { AddFixedItemToPool(RG_PURPLE_RUPEE, 1); } else { @@ -919,3 +937,4 @@ void GenerateItemPool() { assert(itemPool.size() == locCount); } +} diff --git a/soh/soh/Enhancements/randomizer/SeedContext.cpp b/soh/soh/Enhancements/randomizer/SeedContext.cpp index 41a6cb02b3d..21658b3f709 100644 --- a/soh/soh/Enhancements/randomizer/SeedContext.cpp +++ b/soh/soh/Enhancements/randomizer/SeedContext.cpp @@ -50,6 +50,8 @@ Context::Context() { &mOptions[RSK_SHUFFLE_COWS], &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], + &mOptions[RSK_SHUFFLE_ROCKS], + &mOptions[RSK_SHUFFLE_BOULDERS], &mOptions[RSK_SHUFFLE_FREESTANDING], &mOptions[RSK_SHUFFLE_MERCHANTS], &mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES], @@ -214,6 +216,8 @@ void Context::GenerateLocationPool() { (location.GetRCType() == RCTYPE_TREE && !mOptions[RSK_SHUFFLE_TREES]) || (location.GetRCType() == RCTYPE_NLTREE && (!mOptions[RSK_SHUFFLE_TREES] || mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC))) || + (location.GetRCType() == RCTYPE_ROCK && !mOptions[RSK_SHUFFLE_ROCKS]) || + (location.GetRCType() == RCTYPE_BOULDER && mOptions[RSK_SHUFFLE_BOULDERS].Is(RO_SHUFFLE_BOULDERS_OFF)) || (location.GetRCType() == RCTYPE_BUSH && !mOptions[RSK_SHUFFLE_BUSHES]) || (location.GetRCType() == RCTYPE_FREESTANDING && mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OFF)) || @@ -232,7 +236,9 @@ void Context::GenerateLocationPool() { mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS) && mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) || (location.GetRCType() == RCTYPE_SMALL_CRATE && - mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS))) { + mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_DUNGEONS)) && + (location.GetRCType() == RCTYPE_BOULDER && + mOptions[RSK_SHUFFLE_BOULDERS].Is(RO_SHUFFLE_BOULDERS_DUNGEONS))) { continue; } // If we've gotten past all the conditions where an overworld location should not be @@ -253,7 +259,9 @@ void Context::GenerateLocationPool() { mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD) && mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC)) || (location.GetRCType() == RCTYPE_SMALL_CRATE && - mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD))) { + mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OVERWORLD)) && + (location.GetRCType() == RCTYPE_BOULDER && + mOptions[RSK_SHUFFLE_BOULDERS].Is(RO_SHUFFLE_BOULDERS_OVERWORLD))) { continue; } // also add to that dungeon's location list. diff --git a/soh/soh/Enhancements/randomizer/ShuffleRocks.cpp b/soh/soh/Enhancements/randomizer/ShuffleRocks.cpp new file mode 100644 index 00000000000..64c68563205 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleRocks.cpp @@ -0,0 +1,725 @@ +#include "ShuffleRocks.h" +#include "soh/Enhancements/enhancementTypes.h" +#include "soh_assets.h" +#include "static_data.h" +#include "soh/ObjectExtension/ObjectExtension.h" + +extern "C" { +#include "variables.h" +#include "overlays/actors/ovl_En_Ishi/z_en_ishi.h" +#include "overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.h" +#include "overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.h" +#include "objects/gameplay_field_keep/gameplay_field_keep.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "objects/object_bombiwa/object_bombiwa.h" +extern PlayState* gPlayState; +} + +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get() + +extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); + +extern "C" void DrawItemCircle(PlayState* play, float scale, RockIdentity rockIdentity) { + GraphicsContext* __gfxCtx = play->state.gfxCtx; + int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), 0); + int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); + + u8 r1 = 200, g1 = 200, b1 = 200, r2 = 100, g2 = 100, b2 = 100; + + if ((!requiresStoneAgony || (requiresStoneAgony && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { + auto itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rockIdentity.randomizerCheck, true, GI_NONE); + GetItemCategory getItemCategory = itemEntry.getItemCategory; + + switch (getItemCategory) { + case ITEM_CATEGORY_LESSER: + switch (itemEntry.itemId) { + case ITEM_HEART_PIECE: + case ITEM_HEART_PIECE_2: + case ITEM_HEART_CONTAINER: + r1 = 160; + g1 = 80; + b1 = 20; + r2 = 40; + g2 = 160; + b2 = 160; + break; + default: + r1 = 160; + g1 = 140; + b1 = 80; + r2 = 80; + g2 = 70; + b2 = 40; + break; + } + break; + case ITEM_CATEGORY_SMALL_KEY: + r1 = 144; + g1 = 144; + b1 = 144; + r2 = 128; + g2 = 128; + b2 = 128; + break; + case ITEM_CATEGORY_BOSS_KEY: + r1 = 240; + g1 = 220; + b1 = 0; + r2 = 128; + g2 = 128; + b2 = 128; + break; + case ITEM_CATEGORY_SKULLTULA_TOKEN: + r1 = 24; + g1 = 20; + b1 = 0; + r2 = 96; + g2 = 80; + b2 = 0; + break; + case ITEM_CATEGORY_MAJOR: + r1 = 240; + g1 = 220; + b1 = 0; + r2 = 240; + g2 = 220; + b2 = 0; + break; + default: + break; + } + } + + Matrix_Scale(scale, 1.0, scale, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(POLY_XLU_DISP++, 0x08, + (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 16, 32, 1, 0, (play->gameplayFrames * 10) % 128, + 16, 32)); + gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, r1, g1, b1, 255); + gDPSetEnvColor(POLY_XLU_DISP++, r2, g2, b2, 255); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gHoverBootsCircleDL); +} + +extern "C" void EnIshi_RandomizerDraw(Actor* thisx, PlayState* play) { + auto rockActor = ((EnIshi*)thisx); + const auto rockIdentity = ObjectExtension::GetInstance().Get(thisx); + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + if (rockActor->actor.params & 1) { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gSilverRockDL); + } else { + Gfx_DrawDListOpa(play, (Gfx*)gFieldKakeraDL); + } + + if (rockIdentity != nullptr && rockIdentity->randomizerCheck != RC_MAX && + Flags_GetRandomizerInf(rockIdentity->randomizerInf) == 0) { + + Matrix_Translate(rockActor->actor.world.pos.x, + rockActor->actor.world.pos.y + (rockActor->actor.params & 1 ? 32 : 8), + rockActor->actor.world.pos.z, MTXMODE_NEW); + DrawItemCircle(play, (rockActor->actor.params & 1 ? 8 : 2), *rockIdentity); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +extern "C" void ObjBombiwa_RandomizerDraw(Actor* thisx, PlayState* play) { + auto rockActor = ((ObjBombiwa*)thisx); + const auto rockIdentity = ObjectExtension::GetInstance().Get(thisx); + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Gfx_DrawDListOpa(play, (Gfx*)object_bombiwa_DL_0009E0); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)object_bombiwa_DL_0009E0); + + if (rockIdentity != nullptr && rockIdentity->randomizerCheck != RC_MAX && + Flags_GetRandomizerInf(rockIdentity->randomizerInf) == 0) { + Matrix_Translate(rockActor->actor.world.pos.x, rockActor->actor.world.pos.y + 32, rockActor->actor.world.pos.z, + MTXMODE_NEW); + DrawItemCircle(play, 8, *rockIdentity); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +extern "C" void ObjHamishi_RandomizerDraw(Actor* thisx, PlayState* play) { + auto rockActor = ((ObjHamishi*)thisx); + const auto rockIdentity = ObjectExtension::GetInstance().Get(thisx); + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 170, 130, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gSilverRockDL); + + if (rockIdentity != nullptr && rockIdentity->randomizerCheck != RC_MAX && + Flags_GetRandomizerInf(rockIdentity->randomizerInf) == 0) { + Matrix_Translate(rockActor->actor.world.pos.x, rockActor->actor.world.pos.y + 32, rockActor->actor.world.pos.z, + MTXMODE_NEW); + DrawItemCircle(play, 8, *rockIdentity); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +uint8_t Rock_RandomizerHoldsItem(RockIdentity rockIdentity, PlayState* play, bool isBoulder) { + RandomizerCheck rc = rockIdentity.randomizerCheck; + if (rc == RC_MAX || rc == RC_UNKNOWN_CHECK) + return false; + + uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon(); + uint8_t setting = + Rando::Context::GetInstance()->GetOption(isBoulder ? RSK_SHUFFLE_BOULDERS : RSK_SHUFFLE_ROCKS).Get(); + + // Don't pull randomized item if rock isn't randomized or is already checked + return IS_RANDO && + ((!isBoulder && setting) || (isBoulder && (setting == RO_SHUFFLE_BOULDERS_ALL || + (isDungeon && setting == RO_SHUFFLE_BOULDERS_DUNGEONS) || + (!isDungeon && setting == RO_SHUFFLE_BOULDERS_OVERWORLD)))) && + !Flags_GetRandomizerInf(rockIdentity.randomizerInf); +} + +void Rock_RandomizerSpawnCollectible(Actor* actor, RockIdentity rockIdentity, PlayState* play) { + LUSLOG_INFO("ROCKdrop %d\t:\t%d, %d", rockIdentity.randomizerCheck, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &actor->world.pos, ITEM00_SOH_DUMMY); + item00->randoInf = rockIdentity.randomizerInf; + item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rockIdentity.randomizerCheck, true, GI_NONE); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + item00->actor.velocity.y = 9.0f; + item00->actor.speedXZ = 2.0f; + item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f); +} + +void EnIshi_RandomizerInit(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id != ACTOR_EN_ISHI) + return; + + EnIshi* rockActor = static_cast(actorRef); + + auto rockIdentity = OTRGlobals::Instance->gRandomizer->IdentifyRock(gPlayState->sceneNum, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + if (rockIdentity.randomizerCheck == RC_MAX) { + LUSLOG_WARN("ROCK ishi %d\t:\t%d, %d", rockIdentity.randomizerCheck, actor->params & 1, + (s16)actor->world.pos.x, (s16)actor->world.pos.z); + } else { + LUSLOG_INFO("ROCK ishi%d %d\t:\t%d, %d", rockIdentity.randomizerCheck, actor->params & 1, + (s16)actor->world.pos.x, (s16)actor->world.pos.z); + } + + if (Rock_RandomizerHoldsItem(rockIdentity, gPlayState, actor->params & 1)) { + ObjectExtension::GetInstance().Set(actor, std::move(rockIdentity)); + rockActor->actor.draw = EnIshi_RandomizerDraw; + } +} + +void ObjBombiwa_RandomizerInit(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id != ACTOR_OBJ_BOMBIWA) + return; + + ObjBombiwa* rockActor = static_cast(actorRef); + + auto rockIdentity = OTRGlobals::Instance->gRandomizer->IdentifyRock(gPlayState->sceneNum, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + if (rockIdentity.randomizerCheck == RC_MAX) { + LUSLOG_INFO("ROCK bombiwa\t:\t%d, %d", rockIdentity.randomizerCheck, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + } else { + LUSLOG_INFO("ROCK bombiwa%d\t:\t%d, %d", rockIdentity.randomizerCheck, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + } + if (Rock_RandomizerHoldsItem(rockIdentity, gPlayState, true)) { + ObjectExtension::GetInstance().Set(actor, std::move(rockIdentity)); + rockActor->actor.draw = ObjBombiwa_RandomizerDraw; + } +} + +void ObjHamishi_RandomizerInit(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id != ACTOR_OBJ_HAMISHI) + return; + + ObjHamishi* rockActor = static_cast(actorRef); + + auto rockIdentity = OTRGlobals::Instance->gRandomizer->IdentifyRock(gPlayState->sceneNum, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + if (rockIdentity.randomizerCheck == RC_MAX) { + LUSLOG_WARN("ROCK hamishi\t:\t%d, %d", rockIdentity.randomizerCheck, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + } else { + LUSLOG_INFO("ROCK hamishi%d\t:\t%d, %d", rockIdentity.randomizerCheck, (s16)actor->world.pos.x, + (s16)actor->world.pos.z); + } + if (Rock_RandomizerHoldsItem(rockIdentity, gPlayState, true)) { + ObjectExtension::GetInstance().Set(actor, std::move(rockIdentity)); + rockActor->actor.draw = ObjHamishi_RandomizerDraw; + } +} + +void ObjBombiwa_RandomizerKill(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id != ACTOR_OBJ_BOMBIWA) + return; + + ObjBombiwa* rockActor = static_cast(actorRef); + const auto rockIdentity = ObjectExtension::GetInstance().Get(actorRef); + + if (rockIdentity != nullptr && Rock_RandomizerHoldsItem(*rockIdentity, gPlayState, true)) { + Rock_RandomizerSpawnCollectible(&rockActor->actor, *rockIdentity, gPlayState); + rockIdentity->randomizerCheck = RC_MAX; + rockIdentity->randomizerInf = RAND_INF_MAX; + } +} + +void ObjHamishi_RandomizerKill(void* actorRef) { + Actor* actor = static_cast(actorRef); + + if (actor->id != ACTOR_OBJ_HAMISHI) + return; + + ObjHamishi* rockActor = static_cast(actorRef); + const auto rockIdentity = ObjectExtension::GetInstance().Get(actorRef); + + if (rockIdentity != nullptr && Rock_RandomizerHoldsItem(*rockIdentity, gPlayState, true)) { + Rock_RandomizerSpawnCollectible(&rockActor->actor, *rockIdentity, gPlayState); + rockIdentity->randomizerCheck = RC_MAX; + rockIdentity->randomizerInf = RAND_INF_MAX; + } +} + +void RegisterShuffleRock() { + bool shouldRegister = IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_ROCKS) || RAND_GET_OPTION(RSK_SHUFFLE_BOULDERS)); + bool shouldRegisterBoulder = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_BOULDERS); + + COND_ID_HOOK(OnActorInit, ACTOR_EN_ISHI, shouldRegister, EnIshi_RandomizerInit); + COND_ID_HOOK(OnActorInit, ACTOR_OBJ_BOMBIWA, shouldRegisterBoulder, ObjBombiwa_RandomizerInit); + COND_ID_HOOK(OnActorInit, ACTOR_OBJ_HAMISHI, shouldRegisterBoulder, ObjHamishi_RandomizerInit); + COND_ID_HOOK(OnActorKill, ACTOR_OBJ_BOMBIWA, shouldRegisterBoulder, ObjBombiwa_RandomizerKill); + COND_ID_HOOK(OnActorKill, ACTOR_OBJ_HAMISHI, shouldRegisterBoulder, ObjHamishi_RandomizerKill); + + COND_VB_SHOULD(VB_ROCK_DROP_ITEM, shouldRegister, { + EnIshi* rockActor = va_arg(args, EnIshi*); + const auto rockIdentity = ObjectExtension::GetInstance().Get(rockActor); + if (rockIdentity != nullptr && + Rock_RandomizerHoldsItem(*rockIdentity, gPlayState, rockActor->actor.params & 1)) { + Rock_RandomizerSpawnCollectible(&rockActor->actor, *rockIdentity, gPlayState); + rockIdentity->randomizerCheck = RC_MAX; + rockIdentity->randomizerInf = RAND_INF_MAX; + *should = false; + } + }); + + COND_VB_SHOULD(VB_BOULDER_BREAK_FLAG, shouldRegisterBoulder, { + Actor* rockActor = va_arg(args, Actor*); + // hook called before OnActorInit sets up object extension + auto rockIdentity = OTRGlobals::Instance->gRandomizer->IdentifyRock( + gPlayState->sceneNum, (s16)rockActor->world.pos.x, (s16)rockActor->world.pos.z); + if (rockIdentity.randomizerCheck != RC_UNKNOWN_CHECK && + Rock_RandomizerHoldsItem(rockIdentity, gPlayState, true)) { + *should = false; + } + }); +} + +void Rando::StaticData::RegisterRockLocations() { +#define ROCKLOC(id, area, scene, hint, x, z) \ + (locationTable[RC_##id] = Location::Rock(RC_##id, RCQUEST_BOTH, area, scene, TWO_ACTOR_PARAMS(x, z), #id, hint, \ + RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_##id))) +#define BOLDLOC(id, area, scene, hint, x, z) \ + (locationTable[RC_##id] = Location::Boulder(RC_##id, RCQUEST_BOTH, area, scene, TWO_ACTOR_PARAMS(x, z), #id, hint, \ + SpoilerCollectionCheck::RandomizerInf(RAND_INF_##id))) + ROCKLOC(KF_CIRCLE_ROCK_1, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -292, -350); + ROCKLOC(KF_CIRCLE_ROCK_2, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -235, -373); + ROCKLOC(KF_CIRCLE_ROCK_3, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -212, -430); + ROCKLOC(KF_CIRCLE_ROCK_4, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -235, -486); + ROCKLOC(KF_CIRCLE_ROCK_5, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -292, -510); + ROCKLOC(KF_CIRCLE_ROCK_6, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -348, -486); + ROCKLOC(KF_CIRCLE_ROCK_7, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -372, -430); + ROCKLOC(KF_CIRCLE_ROCK_8, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -348, -373); + ROCKLOC(KF_ROCK_BY_SARIAS_HOUSE, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, 248, 601); + ROCKLOC(KF_ROCK_BEHIND_SARIAS_HOUSE, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, 726, 961); + ROCKLOC(KF_ROCK_BY_MIDOS_HOUSE, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -672, -623); + ROCKLOC(KF_ROCK_BY_KNOW_IT_ALLS_HOUSE, RCAREA_KOKIRI_FOREST, SCENE_KOKIRI_FOREST, RHT_KF_ROCK, -1361, 145); + BOLDLOC(LW_BOULDER_BY_GORON_CITY, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, RHT_LW_BOULDER, 915, -925); + BOLDLOC(LW_BOULDER_BY_SACRED_FOREST_MEADOW, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, RHT_LW_BOULDER, 670, -2520); + BOLDLOC(LW_RUPEE_BOULDER, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, RHT_LW_BOULDER, 1720, -2510); + + locationTable[RC_HC_ROCK_1] = Location::Rock( + RC_HC_ROCK_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-216, 2977), + "HC Rock 1", RHT_HC_ROCK, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_1)); + locationTable[RC_HC_ROCK_2] = Location::Rock( + RC_HC_ROCK_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-110, 3006), + "HC Rock 2", RHT_HC_ROCK, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_2)); + locationTable[RC_HC_ROCK_3] = Location::Rock( + RC_HC_ROCK_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-129, 2897), + "HC Rock 3", RHT_HC_ROCK, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_ROCK_3)); + BOLDLOC(HC_BOULDER, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, RHT_HC_BOULDER, 2730, 2540); + BOLDLOC(OGC_BRONZE_BOULDER_1, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_BRONZE_BOULDER, 2324, 533); + BOLDLOC(OGC_BRONZE_BOULDER_2, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_BRONZE_BOULDER, 1590, 787); + BOLDLOC(OGC_BRONZE_BOULDER_3, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_BRONZE_BOULDER, 1661, 748); + BOLDLOC(OGC_SILVER_BOULDER_1, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_SILVER_BOULDER, 1606, 685); + BOLDLOC(OGC_SILVER_BOULDER_2, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_SILVER_BOULDER, 1766, 726); + BOLDLOC(OGC_SILVER_BOULDER_3, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_SILVER_BOULDER, 1701, 661); + BOLDLOC(OGC_SILVER_BOULDER_4, RCAREA_HYRULE_CASTLE, SCENE_OUTSIDE_GANONS_CASTLE, RHT_OGC_SILVER_BOULDER, 2260, 560); + + ROCKLOC(DMC_ROCK_BY_FIRE_TEMPLE_1, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, -50, + -714); + ROCKLOC(DMC_ROCK_BY_FIRE_TEMPLE_2, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, -26, + -807); + ROCKLOC(DMC_ROCK_BY_FIRE_TEMPLE_3, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 61, + -763); + ROCKLOC(DMC_ROCK_BY_FIRE_TEMPLE_4, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 71, + -610); + ROCKLOC(DMC_ROCK_BY_FIRE_TEMPLE_5, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 79, + -700); + ROCKLOC(DMC_CIRCLE_ROCK_1, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 40, 1850); + ROCKLOC(DMC_CIRCLE_ROCK_2, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 96, 1826); + ROCKLOC(DMC_CIRCLE_ROCK_3, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 120, 1770); + ROCKLOC(DMC_CIRCLE_ROCK_4, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 96, 1713); + ROCKLOC(DMC_CIRCLE_ROCK_5, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 40, 1690); + ROCKLOC(DMC_CIRCLE_ROCK_6, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, -16, 1713); + ROCKLOC(DMC_CIRCLE_ROCK_7, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, -40, 1770); + ROCKLOC(DMC_CIRCLE_ROCK_8, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, -16, 1826); + ROCKLOC(DMC_GOSSIP_ROCK_1, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 1261, 1533); + ROCKLOC(DMC_GOSSIP_ROCK_2, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_ROCK, 1356, 1541); + BOLDLOC(DMC_BOULDER_1, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BOULDER, -504, 1070); + BOLDLOC(DMC_BOULDER_2, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BOULDER, 236, 1199); + BOLDLOC(DMC_BOULDER_3, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BOULDER, 40, 1770); + BOLDLOC(DMC_BRONZE_BOULDER_1, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BRONZE_BOULDER, + -1699, -472); + BOLDLOC(DMC_BRONZE_BOULDER_2, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BRONZE_BOULDER, + -1332, 921); + BOLDLOC(DMC_BRONZE_BOULDER_3, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BRONZE_BOULDER, + -1303, 975); + BOLDLOC(DMC_BRONZE_BOULDER_4, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, RHT_DMC_BRONZE_BOULDER, + -1060, 944); + + BOLDLOC(GV_SILVER_BOULDER, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_SILVER_BOULDER, 280, 1470); + ROCKLOC(GV_ROCK_1, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, 2738, 297); + ROCKLOC(GV_ROCK_2, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, 2715, 316); + ROCKLOC(GV_ROCK_3, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, 2699, 275); + ROCKLOC(GV_UNDERWATER_ROCK_1, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, 1559, -63); + ROCKLOC(GV_UNDERWATER_ROCK_2, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, 1605, 26); + ROCKLOC(GV_UNDERWATER_ROCK_3, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, 1686, -33); + ROCKLOC(GV_ROCK_ACROSS_BRIDGE_1, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, -666, -899); + ROCKLOC(GV_ROCK_ACROSS_BRIDGE_2, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, -526, -890); + ROCKLOC(GV_ROCK_ACROSS_BRIDGE_3, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, -607, -791); + ROCKLOC(GV_ROCK_ACROSS_BRIDGE_4, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_ROCK, -458, -782); + BOLDLOC(GV_BOULDER_1, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BOULDER, 751, 569); + BOLDLOC(GV_BOULDER_2, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BOULDER, 545, -510); + BOLDLOC(GV_BOULDER_ACROSS_BRIDGE, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BOULDER, -954, 577); + BOLDLOC(GV_BRONZE_BOULDER_1, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, 861, -778); + BOLDLOC(GV_BRONZE_BOULDER_2, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, 735, 375); + BOLDLOC(GV_BRONZE_BOULDER_ACROSS_BRIDGE_1, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, -1352, + 767); + BOLDLOC(GV_BRONZE_BOULDER_ACROSS_BRIDGE_2, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, -1695, + -350); + BOLDLOC(GV_BRONZE_BOULDER_ACROSS_BRIDGE_3, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, -1001, + 637); + BOLDLOC(GV_BRONZE_BOULDER_ACROSS_BRIDGE_4, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, -1291, + 787); + BOLDLOC(GV_BRONZE_BOULDER_ACROSS_BRIDGE_5, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, -1416, + 778); + BOLDLOC(GV_BRONZE_BOULDER_ACROSS_BRIDGE_6, RCAREA_GERUDO_VALLEY, SCENE_GERUDO_VALLEY, RHT_GV_BRONZE_BOULDER, -1256, + 856); + + BOLDLOC(HF_SILVER_BOULDER, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_SILVER_BOULDER, 674, 8256); + ROCKLOC(HF_ROCK_1, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7875, 6995); + ROCKLOC(HF_ROCK_2, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7818, 6971); + ROCKLOC(HF_ROCK_3, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7795, 6915); + ROCKLOC(HF_ROCK_4, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7818, 6858); + ROCKLOC(HF_ROCK_5, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7875, 6835); + ROCKLOC(HF_ROCK_6, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7931, 6858); + ROCKLOC(HF_ROCK_7, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7955, 6915); + ROCKLOC(HF_ROCK_8, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_ROCK, -7931, 6971); + BOLDLOC(HF_BOULDER_NORTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BOULDER, -4450, -425); + BOLDLOC(HF_BOULDER_BY_MARKET, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BOULDER, -1425, 810); + BOLDLOC(HF_BOULDER_SOUTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BOULDER, -270, 12350); + BOLDLOC(HF_BRONZE_BOULDER_1, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BRONZE_BOULDER, -7870, 6920); + BOLDLOC(HF_BRONZE_BOULDER_2, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BRONZE_BOULDER, -7804, 7983); + BOLDLOC(HF_BRONZE_BOULDER_3, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BRONZE_BOULDER, -8397, 7947); + BOLDLOC(HF_BRONZE_BOULDER_4, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, RHT_HF_BRONZE_BOULDER, -6461, 8220); + + BOLDLOC(KAK_SILVER_BOULDER, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, RHT_KAK_SILVER_BOULDER, 1436, 1361); + ROCKLOC(KAK_ROCK_1, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, RHT_KAK_ROCK, 220, -1236); + ROCKLOC(KAK_ROCK_2, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, RHT_KAK_ROCK, -664, 1288); + ROCKLOC(GY_ROCK, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, RHT_GY_ROCK, -1193, 693); + ROCKLOC(LA_ROCK, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, RHT_LA_ROCK, 1222, 3953); + + ROCKLOC(ZD_CIRCLE_ROCK_1, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 462, -696); + ROCKLOC(ZD_CIRCLE_ROCK_2, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 518, -719); + ROCKLOC(ZD_CIRCLE_ROCK_3, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 542, -776); + ROCKLOC(ZD_CIRCLE_ROCK_4, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 518, -832); + ROCKLOC(ZD_CIRCLE_ROCK_5, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 462, -856); + ROCKLOC(ZD_CIRCLE_ROCK_6, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 405, -832); + ROCKLOC(ZD_CIRCLE_ROCK_7, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 382, -776); + ROCKLOC(ZD_CIRCLE_ROCK_8, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, RHT_ZD_ROCK, 405, -719); + BOLDLOC(ZF_BOULDER, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, RHT_ZF_BOULDER, 189, 2586); + BOLDLOC(ZF_SILVER_BOULDER, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, RHT_ZF_SILVER_BOULDER, 316, 2634); + BOLDLOC(ZF_UNDERGROUND_BOULDER, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, RHT_ZF_BOULDER, 317, 2631); + BOLDLOC(ZR_BOULDER_1, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_BOULDER, -1456, 434); + BOLDLOC(ZR_BOULDER_2, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_BOULDER, -1518, 435); + BOLDLOC(ZR_BOULDER_3, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_BOULDER, -1576, 430); + BOLDLOC(ZR_BOULDER_4, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_BOULDER, -1400, 482); + ROCKLOC(ZR_CIRCLE_ROCK_1, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1635, -53); + ROCKLOC(ZR_CIRCLE_ROCK_2, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1578, -76); + ROCKLOC(ZR_CIRCLE_ROCK_3, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1555, -133); + ROCKLOC(ZR_CIRCLE_ROCK_4, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1578, -189); + ROCKLOC(ZR_CIRCLE_ROCK_5, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1635, -213); + ROCKLOC(ZR_CIRCLE_ROCK_6, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1691, -189); + ROCKLOC(ZR_CIRCLE_ROCK_7, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1715, -133); + ROCKLOC(ZR_CIRCLE_ROCK_8, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, -1691, -76); + ROCKLOC(ZR_UPPER_CIRCLE_BOULDER, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_BOULDER, 672, -366); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_1, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 668, -290); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_2, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 724, -313); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_3, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 748, -370); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_4, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 724, -426); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_5, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 668, -450); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_6, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 611, -426); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_7, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 588, -370); + ROCKLOC(ZR_UPPER_CIRCLE_ROCK_8, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 611, -313); + ROCKLOC(ZR_ROCK, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 2044, -786); + ROCKLOC(ZR_UNDERWATER_ROCK_1, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 2425, -446); + ROCKLOC(ZR_UNDERWATER_ROCK_2, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 2425, -524); + ROCKLOC(ZR_UNDERWATER_ROCK_3, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 2503, -571); + ROCKLOC(ZR_UNDERWATER_ROCK_4, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, RHT_ZR_ROCK, 2550, -415); + + // 5 rocks by dc + ROCKLOC(DMT_ROCK_1, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -1816, -513); + ROCKLOC(DMT_ROCK_2, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -1831, -614); + ROCKLOC(DMT_ROCK_3, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -1857, -536); + ROCKLOC(DMT_ROCK_4, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -1878, -465); + ROCKLOC(DMT_ROCK_5, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -1787, -550); + // child only + ROCKLOC(DMT_SUMMIT_ROCK, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -327, -4286); + // ring in front of gc + ROCKLOC(DMT_CIRCLE_ROCK_1, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -383, -1126); + ROCKLOC(DMT_CIRCLE_ROCK_2, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -326, -1149); + ROCKLOC(DMT_CIRCLE_ROCK_3, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -303, -1206); + ROCKLOC(DMT_CIRCLE_ROCK_4, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -326, -1262); + ROCKLOC(DMT_CIRCLE_ROCK_5, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -383, -1286); + ROCKLOC(DMT_CIRCLE_ROCK_6, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -439, -1262); + ROCKLOC(DMT_CIRCLE_ROCK_7, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -463, -1206); + ROCKLOC(DMT_CIRCLE_ROCK_8, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_ROCK, -439, -1149); + BOLDLOC(DMT_BOULDER_1, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BOULDER, -625, -55); + BOLDLOC(DMT_BOULDER_2, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BOULDER, -808, -59); + BOLDLOC(DMT_BOULDER_3, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BOULDER, -1060, -51); + BOLDLOC(DMT_COW_BOULDER, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BOULDER, -688, -285); + BOLDLOC(DMT_BRONZE_BOULDER_1, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1175, -803); + BOLDLOC(DMT_BRONZE_BOULDER_2, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1948, 1706); + BOLDLOC(DMT_BRONZE_BOULDER_3, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -2019, 1101); + BOLDLOC(DMT_BRONZE_BOULDER_4, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1658, -88); + BOLDLOC(DMT_BRONZE_BOULDER_5, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1753, 445); + BOLDLOC(DMT_BRONZE_BOULDER_6, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1018, 1283); + BOLDLOC(DMT_BRONZE_BOULDER_7, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1986, 727); + BOLDLOC(DMT_BRONZE_BOULDER_8, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, -23, + -3196); + BOLDLOC(DMT_BRONZE_BOULDER_9, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, -343, + -2794); + BOLDLOC(DMT_BRONZE_BOULDER_10, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -154, -2484); + BOLDLOC(DMT_BRONZE_BOULDER_11, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, RHT_DMT_BRONZE_BOULDER, + -1590, -402); + BOLDLOC(GC_LW_BOULDER_1, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, 416, 1049); + BOLDLOC(GC_LW_BOULDER_2, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, 470, 1031); + BOLDLOC(GC_LW_BOULDER_3, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, 367, 1078); + BOLDLOC(GC_ENTRANCE_BOULDER_1, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -670, 470); + BOLDLOC(GC_ENTRANCE_BOULDER_2, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -607, 419); + BOLDLOC(GC_ENTRANCE_BOULDER_3, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -756, 474); + BOLDLOC(GC_MAZE_SILVER_BOULDER_1, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1479, -794); + BOLDLOC(GC_MAZE_SILVER_BOULDER_2, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1478, -855); + BOLDLOC(GC_MAZE_SILVER_BOULDER_3, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1474, -624); + BOLDLOC(GC_MAZE_SILVER_BOULDER_4, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1471, -993); + BOLDLOC(GC_MAZE_SILVER_BOULDER_5, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1467, -1064); + BOLDLOC(GC_MAZE_SILVER_BOULDER_6, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1460, -1121); + BOLDLOC(GC_MAZE_SILVER_BOULDER_7, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1451, -567); + BOLDLOC(GC_MAZE_SILVER_BOULDER_8, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1448, -672); + BOLDLOC(GC_MAZE_SILVER_BOULDER_9, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1440, -1174); + BOLDLOC(GC_MAZE_SILVER_BOULDER_10, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1437, -1342); + BOLDLOC(GC_MAZE_SILVER_BOULDER_11, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1424, -1245); + BOLDLOC(GC_MAZE_SILVER_BOULDER_12, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1424, -609); + BOLDLOC(GC_MAZE_SILVER_BOULDER_13, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1399, -1300); + BOLDLOC(GC_MAZE_SILVER_BOULDER_14, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1394, -654); + BOLDLOC(GC_MAZE_SILVER_BOULDER_15, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1343, -698); + BOLDLOC(GC_MAZE_SILVER_BOULDER_16, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1319, -1086); + BOLDLOC(GC_MAZE_SILVER_BOULDER_17, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1312, -1039); + BOLDLOC(GC_MAZE_SILVER_BOULDER_18, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1306, -837); + BOLDLOC(GC_MAZE_SILVER_BOULDER_19, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1279, -656); + BOLDLOC(GC_MAZE_SILVER_BOULDER_20, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1255, -840); + BOLDLOC(GC_MAZE_SILVER_BOULDER_21, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1246, -1075); + BOLDLOC(GC_MAZE_SILVER_BOULDER_22, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1244, -589); + BOLDLOC(GC_MAZE_SILVER_BOULDER_23, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1210, -852); + BOLDLOC(GC_MAZE_SILVER_BOULDER_24, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1206, -627); + BOLDLOC(GC_MAZE_SILVER_BOULDER_25, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1187, -896); + BOLDLOC(GC_MAZE_SILVER_BOULDER_26, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1157, -954); + BOLDLOC(GC_MAZE_SILVER_BOULDER_27, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1130, -1137); + BOLDLOC(GC_MAZE_SILVER_BOULDER_28, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1120, -1001); + BOLDLOC(GC_MAZE_SILVER_BOULDER_29, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_SILVER_BOULDER, -1179, -1098); + BOLDLOC(GC_MAZE_BOULDER_1, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1342, -628); + BOLDLOC(GC_MAZE_BOULDER_2, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1456, -501); + BOLDLOC(GC_MAZE_BOULDER_3, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1233, -511); + BOLDLOC(GC_MAZE_BOULDER_4, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1137, -657); + BOLDLOC(GC_MAZE_BOULDER_5, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1124, -913); + BOLDLOC(GC_MAZE_BOULDER_6, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1326, -771); + BOLDLOC(GC_MAZE_BOULDER_7, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1469, -737); + BOLDLOC(GC_MAZE_BOULDER_8, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1476, -921); + BOLDLOC(GC_MAZE_BOULDER_9, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1391, -1087); + BOLDLOC(GC_MAZE_BOULDER_10, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BOULDER, -1222, -997); + BOLDLOC(GC_MAZE_BRONZE_BOULDER_1, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BRONZE_BOULDER, -1541, -631); + BOLDLOC(GC_MAZE_BRONZE_BOULDER_2, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BRONZE_BOULDER, -1536, -861); + BOLDLOC(GC_MAZE_BRONZE_BOULDER_3, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BRONZE_BOULDER, -1536, -1102); + BOLDLOC(GC_MAZE_BRONZE_BOULDER_4, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BRONZE_BOULDER, -1534, -752); + BOLDLOC(GC_MAZE_BRONZE_BOULDER_5, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_BRONZE_BOULDER, -1536, -991); + ROCKLOC(GC_MAZE_ROCK, RCAREA_GORON_CITY, SCENE_GORON_CITY, RHT_GC_ROCK, -1197, -1329); + BOLDLOC(COLOSSUS_SILVER_BOULDER, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_SILVER_BOULDER, 61, + -1301); + ROCKLOC(COLOSSUS_ROCK, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, 1537, 667); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_1, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -250, -1272); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_2, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -193, -1295); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_3, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -170, -1352); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_4, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -193, -1408); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_5, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -250, -1432); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_6, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -306, -1408); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_7, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -330, -1352); + ROCKLOC(COLOSSUS_CIRCLE_1_ROCK_8, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -306, -1295); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_1, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -834, -766); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_2, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -777, -789); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_3, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -754, -846); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_4, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -777, -902); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_5, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -834, -926); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_6, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -890, -902); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_7, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -914, -846); + ROCKLOC(COLOSSUS_CIRCLE_2_ROCK_8, RCAREA_DESERT_COLOSSUS, SCENE_DESERT_COLOSSUS, RHT_COLOSSUS_ROCK, -890, -789); + ROCKLOC(HC_STORMS_GROTTO_ROCK_1, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1811, 813); + ROCKLOC(HC_STORMS_GROTTO_ROCK_2, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1867, 789); + ROCKLOC(HC_STORMS_GROTTO_ROCK_3, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1891, 733); + ROCKLOC(HC_STORMS_GROTTO_ROCK_4, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1867, 676); + ROCKLOC(HC_STORMS_GROTTO_ROCK_5, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1811, 653); + ROCKLOC(HC_STORMS_GROTTO_ROCK_6, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1754, 676); + ROCKLOC(HC_STORMS_GROTTO_ROCK_7, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1731, 733); + ROCKLOC(HC_STORMS_GROTTO_ROCK_8, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, RHT_HC_STORMS_GROTTO_ROCK, 1754, 789); + locationTable[RC_BOTW_BOULDER_1] = + Location::Boulder(RC_BOTW_BOULDER_1, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, + TWO_ACTOR_PARAMS(-684, -734), "BOTW Boulder 1", RHT_BOTW_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_BOULDER_1)); + locationTable[RC_BOTW_BOULDER_2] = + Location::Boulder(RC_BOTW_BOULDER_2, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, + TWO_ACTOR_PARAMS(-632, -805), "BOTW Boulder 2", RHT_BOTW_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_BOULDER_2)); + locationTable[RC_BOTW_BOULDER_3] = + Location::Boulder(RC_BOTW_BOULDER_3, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, + TWO_ACTOR_PARAMS(333, -681), "BOTW Boulder 3", RHT_BOTW_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_BOULDER_3)); + locationTable[RC_BOTW_BOULDER_4] = + Location::Boulder(RC_BOTW_BOULDER_4, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, + TWO_ACTOR_PARAMS(409, -637), "BOTW Boulder 4", RHT_BOTW_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_BOULDER_4)); + locationTable[RC_BOTW_BOULDER_5] = + Location::Boulder(RC_BOTW_BOULDER_5, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, + TWO_ACTOR_PARAMS(334, -8), "BOTW Boulder 5", RHT_BOTW_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_BOULDER_5)); + locationTable[RC_BOTW_BOULDER_6] = + Location::Boulder(RC_BOTW_BOULDER_6, RCQUEST_VANILLA, RCAREA_BOTTOM_OF_THE_WELL, SCENE_BOTTOM_OF_THE_WELL, + TWO_ACTOR_PARAMS(312, 64), "BOTW Boulder 6", RHT_BOTW_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_BOULDER_6)); +#define MQBOLD(id, area, hint, x, z) \ + (locationTable[RC_##id] = \ + Location::Boulder(RC_##id, RCQUEST_MQ, RCAREA_##area, SCENE_##area, TWO_ACTOR_PARAMS(x, z), #id, hint, \ + SpoilerCollectionCheck::RandomizerInf(RAND_INF_##id))) + MQBOLD(DEKU_TREE_MQ_BOULDER_1, DEKU_TREE, RHT_DEKU_BOULDER, -1237, 1558); + MQBOLD(DEKU_TREE_MQ_BOULDER_2, DEKU_TREE, RHT_DEKU_BOULDER, -1183, 1522); + MQBOLD(DEKU_TREE_MQ_BOULDER_3, DEKU_TREE, RHT_DEKU_BOULDER, -1129, 1469); + MQBOLD(DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, -435, -1720); + MQBOLD(DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 432, -1719); + MQBOLD(DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 807, -874); + MQBOLD(DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_2, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 802, -972); + MQBOLD(DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_3, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 783, -923); + MQBOLD(DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_1, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 2464, -402); + MQBOLD(DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_2, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 2942, -495); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4219, -1651); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4178, -1602); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4162, -1581); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_4, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4133, -1561); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_5, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4091, -1510); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_6, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4067, -1487); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_7, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 4028, -1472); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_8, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 3965, -1473); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_9, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 3898, -1467); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_10, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 3832, -1437); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_11, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 3799, -1383); + MQBOLD(DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_12, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 3760, -1318); + MQBOLD(DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER, DODONGOS_CAVERN, RHT_DODONGOS_BOULDER, 2737, -1058); + locationTable[RC_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER] = + Location::Boulder(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(-1, -296), "RC_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER)); + locationTable[RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(350, -3533), "RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1)); + locationTable[RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(-192, -3211), "RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2)); + locationTable[RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(245, -2792), "RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1)); + locationTable[RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(220, -2790), "RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2)); + locationTable[RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(274, -2790), "RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3)); + locationTable[RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(31, -5177), "RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1)); + locationTable[RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(-37, -5173), "RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2)); + locationTable[RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(-885, -5907), "RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER)); + locationTable[RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER] = Location::Boulder( + RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER, RCQUEST_MQ, RCAREA_JABU_JABUS_BELLY, SCENE_JABU_JABU, + TWO_ACTOR_PARAMS(-411, -5682), "RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER", RHT_JABU_BOULDER, + SpoilerCollectionCheck::RandomizerInf(RAND_INF_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER)); + // skip spirit temple boulder, so adult can clear without collecting check for child to pass + MQBOLD(SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_1, SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOULDER, -160, 270); + MQBOLD(SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_2, SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOULDER, 160, 270); + MQBOLD(SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_3, SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOULDER, 350, 220); + MQBOLD(SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER, SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOULDER, 0, -60); + MQBOLD(SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER, SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOULDER, 1070, -290); + MQBOLD(BOTW_MQ_BOULDER_1, BOTTOM_OF_THE_WELL, RHT_BOTW_BOULDER, -370, -160); + MQBOLD(BOTW_MQ_BOULDER_2, BOTTOM_OF_THE_WELL, RHT_BOTW_BOULDER, -521, -353); + MQBOLD(BOTW_MQ_BOULDER_3, BOTTOM_OF_THE_WELL, RHT_BOTW_BOULDER, -541, -404); +} + +static ObjectExtension::Register RegisterRockIdentity; +static RegisterShipInitFunc initFunc(RegisterShuffleRock, { "IS_RANDO" }); +static RegisterShipInitFunc initFunc2(Rando::StaticData::RegisterRockLocations); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/ShuffleRocks.h b/soh/soh/Enhancements/randomizer/ShuffleRocks.h new file mode 100644 index 00000000000..ad7ea4d7a83 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleRocks.h @@ -0,0 +1,15 @@ +#ifndef SHUFFLEROCKS_H +#define SHUFFLEROCKS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +void EnIshi_RandomizerInit(void* actorRef); +#ifdef __cplusplus +}; +#endif + +#endif // SHUFFLEROCKS_H \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 62971a2841e..645b9d8cec1 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -34,7 +34,11 @@ extern "C" { #include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" #include "objects/object_tw/object_tw.h" #include "objects/object_ganon2/object_ganon2.h" +#include "objects/object_vase/object_vase.h" +#include "objects/object_link_child/object_link_child.h" +#include "roll_animation_data.h" #include "objects/object_gi_shield_1/object_gi_shield_1.h" + extern PlayState* gPlayState; extern SaveContext gSaveContext; } @@ -117,6 +121,17 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawBeanSprout(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + Matrix_Scale(0.3f, 0.3f, 0.3f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMagicBeanSeedlingDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawMap(PlayState* play, GetItemEntry* getItemEntry) { s16 color_slot = getItemEntry->drawItemId - RG_DEKU_TREE_MAP; s16 colors[12][3] = { @@ -945,17 +960,6 @@ extern "C" void DrawGanon(PlayState* play) { CLOSE_DISPS(play->state.gfxCtx); } -extern "C" void Randomizer_DrawBeanSprout(PlayState* play, GetItemEntry* getItemEntry) { - OPEN_DISPS(play->state.gfxCtx); - - Gfx_SetupDL_25Opa(play->state.gfxCtx); - Matrix_Scale(0.3f, 0.3f, 0.3f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gMagicBeanSeedlingDL); - - CLOSE_DISPS(play->state.gfxCtx); -} - extern "C" void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry) { s16 slot; if (getItemEntry->getItemId != RG_ICE_TRAP) { @@ -1136,6 +1140,64 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawRollAbility(PlayState* play, GetItemEntry* getItemEntry) { + static bool initialized = false; + static SkelAnime skelAnime; + static Vec3s jointTable[ROLL_ANIMATION_LIMBS]; + static Vec3s morphTable[ROLL_ANIMATION_LIMBS]; + static u32 lastUpdate = 0; + static int currentFrame = 0; + + if (!initialized) { + initialized = true; + SkelAnime_InitFlex(play, &skelAnime, (FlexSkeletonHeader*)gLinkChildSkel, NULL, jointTable, morphTable, + ROLL_ANIMATION_LIMBS); + } + + // Animation manuelle avec les frames capturées + if (lastUpdate != play->state.frames) { + lastUpdate = play->state.frames; + + // Avance d'une frame toutes les 2 frames de jeu + if ((play->state.frames % 2) == 0) { + currentFrame = (currentFrame + 1) % ROLL_ANIMATION_FRAMES; + } + + // Copie les données de la frame actuelle + for (int i = 0; i < ROLL_ANIMATION_LIMBS; i++) { + jointTable[i] = rollAnimationData[currentFrame][i]; + } + } + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + Matrix_Translate(0.0f, -30.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateY(play->gameplayFrames * 0.05f, MTXMODE_APPLY); + Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY); + + SkelAnime_DrawFlexOpa(play, skelAnime.skeleton, jointTable, skelAnime.dListCount, NULL, NULL, NULL); + + CLOSE_DISPS(play->state.gfxCtx); +} + +extern "C" void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetGrayscaleColor(POLY_OPA_DISP++, 255, 255, 255, 255); + gSPGrayscale(POLY_OPA_DISP++, true); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL); + gSPGrayscale(POLY_OPA_DISP++, false); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry) { OPEN_DISPS(play->state.gfxCtx); @@ -1265,4 +1327,4 @@ extern "C" void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getIt gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gHouseKeyDL); CLOSE_DISPS(play->state.gfxCtx); -} +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index e00678f9bf0..1f00d5a5086 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -22,6 +22,8 @@ void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawRollAbility(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 57afb717bc8..da1462fcba0 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1,4 +1,4 @@ -#include +#include #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/enhancementTypes.h" @@ -850,8 +850,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l va_copy(args, originalArgs); switch (id) { + case VB_ROLL: + *should = !RAND_GET_OPTION(RSK_SHUFFLE_ROLL) || Flags_GetRandomizerInf(RAND_INF_CAN_ROLL); + case VB_CRAWL: *should = !RAND_GET_OPTION(RSK_SHUFFLE_CRAWL) || Flags_GetRandomizerInf(RAND_INF_CAN_CRAWL); + break; case VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE: { s32 entranceIndex = va_arg(args, s32); @@ -921,6 +925,9 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l case VB_MIDO_CONSIDER_DEKU_TREE_DEAD: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); break; + case VB_OPEN_CHEST: + *should = *should && Flags_GetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); + break; case VB_OPEN_KOKIRI_FOREST: *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_CLOSED_FOREST_ON; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 0b49429743a..827b5ea180f 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -369,15 +369,22 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "C-Rechts-Taste der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - + itemTable[RG_CRAWL] = Item(RG_CRAWL, Text{ "Crawl", "Ramper", "Kriechen" }, ITEMTYPE_ITEM, GI_SHIELD_DEKU, true, LOGIC_NONE, RHT_CRAWL, RG_CRAWL, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_CRAWL].SetCustomDrawFunc(Randomizer_DrawKneePads); - itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ROLL] = Item(RG_ROLL, Text{ "Roll", "Rouler", "Rolle" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_ROLL, RG_ROLL, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ROLL].SetCustomDrawFunc(Randomizer_DrawRollAbility); + + itemTable[RG_OPEN_CHEST] = Item(RG_OPEN_CHEST, Text{ "Open Chests", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_KEY_SMALL, true, LOGIC_NONE, RHT_OPEN_CHEST, RG_OPEN_CHEST, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OPEN_CHEST].SetCustomDrawFunc(Randomizer_DrawOpenChest); + + itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); + itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "Sac de Graines Infinis", "Unendliche Munitionstasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index 250af2cfb74..e6308fe0459 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -585,6 +585,23 @@ Rando::Location Rando::Location::NLTree(RandomizerCheck rc, RandomizerCheckQuest false, collectionCheck }; } +Rando::Location Rando::Location::Rock(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_ROCK, area_, ACTOR_EN_ISHI, + scene_, actorParams_, std::move(shortName_), hintKey, vanillaItem, + false, collectionCheck }; +} + +Rando::Location Rando::Location::Boulder(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_BOULDER, area_, ACTOR_EN_ISHI, + scene_, actorParams_, std::move(shortName_), hintKey, RG_BOMBS_5, + false, collectionCheck }; +} + Rando::Location Rando::Location::Bush(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index 9556012204a..6b352ab1bc3 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -67,15 +67,7 @@ class Location { actorParams(actorParams_), shortName(std::move(shortName_)), spoilerName(std::move(spoilerName_)), hintKey(hintKey_), vanillaItem(vanillaItem_), isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) { - if (spoilerName.length() < 23) { - excludedOption = LocationOption(rc, spoilerName); - } else { - const size_t lastSpace = spoilerName.rfind(' ', 23); - std::string settingText = spoilerName; - settingText.replace(lastSpace, 1, "\n "); - - excludedOption = LocationOption(rc, spoilerName); - } + excludedOption = LocationOption(rc, spoilerName); } Location(const RandomizerCheck rc_, const RandomizerCheckQuest quest_, const RandomizerCheckType checkType_, @@ -87,15 +79,7 @@ class Location { actorParams(actorParams_), shortName(shortName_), spoilerName(SpoilerNameFromShortName(shortName_, area_)), hintKey(hintKey_), vanillaItem(vanillaItem_), isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) { - if (spoilerName.length() < 23) { - excludedOption = LocationOption(rc, spoilerName); - } else { - const size_t lastSpace = spoilerName.rfind(' ', 23); - std::string settingText = spoilerName; - settingText.replace(lastSpace, 1, "\n "); - - excludedOption = LocationOption(rc, spoilerName); - } + excludedOption = LocationOption(rc, spoilerName); } static std::string SpoilerNameFromShortName(std::string shortName, RandomizerCheckArea area) { @@ -254,6 +238,14 @@ class Location { int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location Rock(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, + int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + + static Location Boulder(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, + int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, + SpoilerCollectionCheck collectionCheck); + static Location Bush(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index b2d51eeb656..d21d47d580e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -31,12 +31,12 @@ void RegionTable_Init_BottomOfTheWell() { EventAccess(LOGIC_BOTW_LOWERED_WATER, []{return logic->CanUse(RG_ZELDAS_LULLABY);}), }, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, (logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetTrickOption(RT_LENS_BOTW)) || (logic->CanUse(RG_LENS_OF_TRUTH))))), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_POT, (logic->CanBreakPots() && logic->Get(LOGIC_BOTW_LOWERED_WATER)) || logic->CanUse(RG_BOOMERANG)), @@ -61,7 +61,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MIDDLE] = Region("Bottom of the Well Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations //You can just barely pass the spider on the right side without damage or items, but it's probably tight enough to count as as a trick - LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()), + LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), @@ -91,7 +91,7 @@ void RegionTable_Init_BottomOfTheWell() { //Passing through this area needs lens, but entering doesn't, so that the fire keese can be killed without crossing the pits if enemy drops are ever shuffled areaTable[RR_BOTW_HIDDEN_PITS_ROOM] = Region("Bottom of the Well Hidden Pits Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_POT_1, logic->CanBreakPots() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), }, { //Exits @@ -103,7 +103,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_LOCKED_CAGE] = Region("Bottom of the Well Locked Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -112,7 +112,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_PIT_CAGE] = Region("Bottom of the Well Pit Cage", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_PERIMETER, []{return ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH);}), @@ -143,7 +143,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_BEHIND_MOAT] = Region("Bottom of the Well Behind Moat", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) || logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Climb always needed in case water is lowered out of logic @@ -178,8 +178,8 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_DEAD_HAND_ROOM] = Region("Bottom of the Well Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), - LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_NEAR_BOSS_UPPER, []{return logic->CanKillEnemy(RE_DEAD_HAND);}), @@ -231,6 +231,12 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_7, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_8, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_BEHIND_ROCKS_GRASS_9, logic->CanCutShrubs()), + LOCATION(RC_BOTW_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_BOTW_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_BOTW_BOULDER_3, logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT))), + LOCATION(RC_BOTW_BOULDER_4, logic->BlastOrSmash()), + LOCATION(RC_BOTW_BOULDER_5, logic->BlastOrSmash()), + LOCATION(RC_BOTW_BOULDER_6, logic->BlastOrSmash()), }, { //Exits Entrance(RR_BOTW_B3_OOZE, []{return AnyAgeTime([]{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}), @@ -238,7 +244,13 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_B3_CHEST_AREA] = Region("Bottom of the Well B3 Chest Area", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTW_BOULDER_1, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_BOTW_BOULDER_2, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_BOTW_BOULDER_3, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_BOTW_BOULDER_4, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_BOTW_BOULDER_5, logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_BOTW_BOULDER_6, logic->HasItem(RG_GORONS_BRACELET)), }, { //Exits Entrance(RR_BOTW_B3_OOZE, []{return AnyAgeTime([]{return logic->BlastOrSmash();});}), @@ -278,6 +290,9 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT, AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART, logic->HasExplosives()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, logic->HasExplosives()), + LOCATION(RC_BOTW_MQ_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_BOTW_MQ_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_BOTW_MQ_BOULDER_3, logic->BlastOrSmash()), }, { //Exits Entrance(RR_BOTW_ENTRYWAY, []{return logic->CanUse(RG_CRAWL) /* && CanClimb()*/;}), @@ -293,7 +308,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_MIDDLE] = Region("Bottom of the Well MQ Middle", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, true), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_1, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_2, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_INNER_LOBBY_POT_3, logic->CanBreakPots()), @@ -398,7 +413,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_DEAD_HAND_ROOM] = Region("Bottom of the Well MQ Dead Hand Room", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, logic->HasExplosives() || (ctx->GetTrickOption(RT_BOTW_MQ_DEADHAND_KEY) && logic->CanUse(RG_BOOMERANG))), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_GRASS_2, logic->CanCutShrubs()), @@ -425,7 +440,7 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_MQ_B3_PLATFORM] = Region("Bottom of the Well MQ B3 Platform", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations //Assumes RR_BOTW_MQ_B3 access - LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->CanPassEnemy(RE_REDEAD)), + LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, logic->CanPassEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_BOTW_MQ_B3, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp index b2be1d7fcdb..d7a63e4f1d5 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp @@ -22,7 +22,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_LOBBY_LOWER_HEART, true), LOCATION(RC_DEKU_TREE_LOBBY_UPPER_HEART, logic->CanPassEnemy(RE_BIG_SKULLTULA)), LOCATION(RC_DEKU_TREE_LOBBY_GRASS_1, logic->CanCutShrubs()), @@ -48,8 +48,8 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Region("Deku Tree Slingshot Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, true), - LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_SLINGSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_1, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_2, logic->CanCutShrubs() && logic->CanReflectNuts()), LOCATION(RC_DEKU_TREE_SLINGSHOT_GRASS_3, logic->CanCutShrubs() && logic->CanReflectNuts()), @@ -65,8 +65,8 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_COMPASS_CHEST, true), - LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, true), + LOCATION(RC_DEKU_TREE_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_GS_COMPASS_ROOM, logic->CanAttack()), LOCATION(RC_DEKU_TREE_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_COMPASS_GRASS_2, logic->CanCutShrubs()), @@ -82,7 +82,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, true), + LOCATION(RC_DEKU_TREE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_GS_BASEMENT_GATE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)), LOCATION(RC_DEKU_TREE_GS_BASEMENT_VINES, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS) ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW)), LOCATION(RC_DEKU_TREE_BASEMENT_GRASS_1, logic->CanCutShrubs()), @@ -218,7 +218,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_TREE_MQ_2F_BURNED_WEB, []{return logic->HasFireSource();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_GS_LOBBY, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)), LOCATION(RC_DEKU_TREE_MQ_LOBBY_HEART, true), LOCATION(RC_DEKU_TREE_MQ_LOBBY_GRASS_6, logic->CanCutShrubs()), @@ -252,8 +252,8 @@ void RegionTable_Init_DekuTree() { }, { //Locations //Implies CanKillEnemy(RE_GOHMA_LARVA) - LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanKillEnemy(RE_DEKU_BABA)), - LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, logic->HasFireSourceWithTorch() || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, logic->CanKillEnemy(RE_DEKU_BABA) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, (logic->HasFireSourceWithTorch() || (logic->IsAdult && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_HEART, true), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_SLINGSHOT_GRASS_2, logic->CanCutShrubs()), @@ -284,7 +284,7 @@ void RegionTable_Init_DekuTree() { areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Region("Deku Tree MQ Compass Room", SCENE_DEKU_TREE, {}, { //Locations - LOCATION(RC_DEKU_TREE_MQ_COMPASS_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -299,6 +299,9 @@ void RegionTable_Init_DekuTree() { //Locations LOCATION(RC_DEKU_TREE_MQ_GS_PAST_BOULDER_VINES, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_DEKU_TREE_MQ_COMPASS_ROOM_HEART, true), + LOCATION(RC_DEKU_TREE_MQ_BOULDER_1, true), + LOCATION(RC_DEKU_TREE_MQ_BOULDER_2, true), + LOCATION(RC_DEKU_TREE_MQ_BOULDER_3, true), }, { //Exits Entrance(RR_DEKU_TREE_MQ_COMPASS_ROOM, []{return logic->BlastOrSmash();}), @@ -310,7 +313,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_DEKU_TREE_MQ_BASEMENT_CHEST, (logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_LOWER_GRASS_3, logic->CanCutShrubs()), @@ -346,7 +349,7 @@ void RegionTable_Init_DekuTree() { EventAccess(LOGIC_DEKU_TREE_MQ_WATER_ROOM_TORCHES, []{return logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_STICKS) && (ctx->GetTrickOption(RT_DEKU_MQ_LOG) || (logic->IsChild && logic->CanShield())));}), }, { //Locations - LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, true), + LOCATION(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_FRONT_GRASS_3, logic->CanCutShrubs()), @@ -363,7 +366,7 @@ void RegionTable_Init_DekuTree() { }, { //Locations //it blocks the chest while stunned unless you stun it from afar while it's slightly off the ground - LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DEKU_TREE_MQ_BASEMENT_SPIKE_ROLLER_BACK_GRASS_2, logic->CanCutShrubs()), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp index a0f380fd5a1..fa51e775dff 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -28,7 +28,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_EYES_LIT, []{return ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);), + LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST);), LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, (logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); }) && logic->CallGossipFairy()), LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); }) && logic->CanUse(RG_SONG_OF_STORMS)), @@ -147,7 +147,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_COMPASS_ROOM] = Region("Dodongos Cavern Compass Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET);}), @@ -161,7 +161,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Region("Dodongos Cavern Bomb Room Lower", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_ROOM_HEART, true), LOCATION(RC_DODONGOS_CAVERN_FIRST_BRIDGE_GRASS, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_BLADE_GRASS, logic->CanCutShrubs()), @@ -225,7 +225,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Region("Dodongos Cavern Bomb Room Upper", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_BLADE_POT_2, logic->CanBreakPots()), }, { @@ -241,7 +241,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_LIFT_PLATFORM, []{return true;}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls()), + LOCATION(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, logic->CanBreakMudWalls() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}), @@ -288,9 +288,11 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_EYES_LIT, []{return ctx->GetTrickOption(RT_DC_EYES_CHU) && logic->CanUse(RG_BOMBCHU_5);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1, logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2, logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, []{return true;}), @@ -317,7 +319,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_OUTSIDE_POES_ROOM] = Region("Dodongos Cavern MQ Outside Poes Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Events Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}), @@ -328,7 +330,12 @@ void RegionTable_Init_DodongosCavern() { //Events EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), EventAccess(LOGIC_DC_EYES_LIT, []{return logic->HasExplosives() || (logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS) && logic->HasItem(RG_GORONS_BRACELET) && ((logic->IsAdult && ctx->GetTrickOption(RT_DC_MQ_ADULT_EYES)) || (logic->IsChild && ctx->GetTrickOption(RT_DC_MQ_CHILD_EYES))));}), - }, {}, { + }, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1, logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS)), + LOCATION(RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_2, logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS)), + LOCATION(RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_3, logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS)), + }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}), Entrance(RR_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_UPPER, []{return logic->Get(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS);}), @@ -390,7 +397,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM] = Region("Dodongos Cavern MQ Dodongo Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)), + LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, (logic->CanKillEnemy(RE_DODONGO) || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_DODONGOS_CAVERN_MQ_COMPASS_GRASS_3, logic->CanCutShrubs()), @@ -431,7 +438,7 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_LARVAE_ROOM] = Region("Dodongos Cavern MQ Larvae Room", SCENE_DODONGOS_CAVERN, {}, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, true), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts + LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), //implied logic->CanKillEnemy(RE_GOHMA_LARVA) based on entry reqs with a trick to kill with nuts LOCATION(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, logic->CanBreakCrates()), //implied logic->CanKillEnemy(RE_GOLD_SKULTULLA) based on entry reqs. Add crate logic when BONKO is added LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CRATE_2, logic->CanBreakCrates()), @@ -452,6 +459,18 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS_POT_3, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS_POT_4, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_HEART, logic->BlastOrSmash()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_4, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_5, logic->BlastOrSmash()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_6, logic->BlastOrSmash()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_7, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_8, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_9, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_10, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_11, logic->BlastOrSmash() && logic->TakeDamage()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_12, logic->BlastOrSmash() && logic->TakeDamage()), }, { //Exits //Falling down gets you stuck with nothing there, not a useful exit for logic @@ -465,6 +484,7 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_CRATE_2, logic->CanBreakCrates()), + LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER, logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET)), }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return true;}), @@ -476,7 +496,7 @@ void RegionTable_Init_DodongosCavern() { EventAccess(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations - LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_CORNER_POT, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_MIDDLE_POT, logic->CanBreakPots()), }, { @@ -494,6 +514,8 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_POT_3, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_POT_4, logic->CanBreakPots()), + LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_1, logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET) || logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_2, logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE) && (logic->EffectiveHealth() != 1 || logic->CanUse(RG_NAYRUS_LOVE)))), }, { //Exits Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return true;}), @@ -582,7 +604,7 @@ void RegionTable_Init_DodongosCavern() { }); areaTable[RR_DODONGOS_CAVERN_MQ_BACK_POE_ROOM] = Region("Dodongos Cavern MQ Back Poe Room", SCENE_DODONGOS_CAVERN, {}, { - LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, true), //pulling the grave isn't required, as you can open the chest through it + LOCATION(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)), //pulling the grave isn't required, as you can open the chest through it LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_1, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACKROOM_POT_2, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_BACK_POE_GRASS, logic->CanCutShrubs()), @@ -629,7 +651,7 @@ void RegionTable_Init_DodongosCavern() { && logic->CanKillEnemy(RE_KING_DODONGO);}), }, { // Locations - LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true), + LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), LOCATION(RC_KING_DODONGO, logic->Get(LOGIC_DODONGOS_CAVERN_CLEAR)), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index a0d39399c39..db6434727db 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -27,7 +27,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Region("Fire Temple Near Boss Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, logic->FireTimer() >= 16), + LOCATION(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, logic->FireTimer() >= 16 && logic->HasItem(RG_OPEN_CHEST)), //It's plausible to get the pots with rang from the larger square platform, but it's a blind shot that likely needs a setup //and I've only been able to get the nearest 2, regardless it's a trick and probably a specific one like GY crate freestanding with rang }, { @@ -68,7 +68,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_FLARE_DANCER] = Region("Fire Temple Loop Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);}) && (logic->IsAdult || logic->CanGroundJump() || logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);}) && (logic->IsAdult || logic->CanGroundJump() || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_5_TILE_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);});}), @@ -86,7 +86,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_LOOP_GORON_CAGE] = Region("Fire Temple Loop Goron Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_LOOP_CAGE_SWITCH, []{return logic->Get(LOGIC_FIRE_LOOP_SWITCH);}), @@ -116,7 +116,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_1F_CURVED_CAGE] = Region("Fire Temple 1F Curved Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return true;}), @@ -134,7 +134,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_STRAIGHTFORWARD_CAGE] = Region("Fire Temple Straightforward Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return true;}), @@ -184,7 +184,7 @@ void RegionTable_Init_FireTemple() { EventAccess(LOGIC_FIRE_OPENED_UPPER_SHORTCUT, []{return true;}), }, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, []{return true;}), @@ -193,7 +193,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Region("Fire Temple Boulder Maze Lower", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, logic->HasExplosives() && (logic->IsAdult || logic->HookshotOrBoomerang() || logic->CanGroundJumpJumpSlash())), }, { //Exits @@ -205,7 +205,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_3F_CURVED_CAGE] = Region("Fire Temple 3F Curved Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, []{return true;}), @@ -240,7 +240,7 @@ void RegionTable_Init_FireTemple() { //firetimer for entering this area from RR_FIRE_TEMPLE_FIRE_WALL_CHASE is handled there areaTable[RR_FIRE_TEMPLE_FIRE_WALL_CAGE] = Region("Fire Temple Fire Wall Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, logic->FireTimer() >= 8), + LOCATION(RC_FIRE_TEMPLE_MAP_CHEST, logic->FireTimer() >= 8 && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_NARROW_PATH_ROOM, []{return true;}), @@ -249,7 +249,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER] = Region("Fire Temple Boulder Maze Upper", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return logic->HasExplosives();}), @@ -276,7 +276,7 @@ void RegionTable_Init_FireTemple() { //RANDOTODO find a better name areaTable[RR_FIRE_TEMPLE_5F_RUINS] = Region("Fire Temple 5F Ruins", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_SCARECROW_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_SCARECROW_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), }, { //Exits @@ -302,7 +302,7 @@ void RegionTable_Init_FireTemple() { Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->Get(LOGIC_FIRE_HIT_PLATFORM) && (logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || logic->TakeDamage());}), Entrance(RR_FIRE_TEMPLE_CORRIDOR, []{return true;}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_PLATFORMS, []{return logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && (logic->Get(LOGIC_FIRE_HIT_ABOVE_MAZE_PLATFORM) || logic->CanGroundJump()));}), - Entrance(RR_FIRE_TEMPLE_CAGELESS_CHEST_ROOM, []{return true;}), + Entrance(RR_FIRE_TEMPLE_CAGELESS_CHEST_ROOM, []{return logic->HasItem(RG_OPEN_CHEST);}), Entrance(RR_FIRE_TEMPLE_SOT_CAGE_LOWER, []{return logic->SmallKeys(SCENE_FIRE_TEMPLE, 8);}), Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_SWITCH, []{return (bool)ctx->GetTrickOption(RT_FIRE_SKIP_FLAME_WALLS);}), }); @@ -318,7 +318,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_CAGELESS_CHEST_ROOM] = Region("Fire Temple Cageless Chest Room", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_MAIN, []{return true;}), @@ -342,7 +342,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_SOT_CAGE_SWITCH] = Region("Fire Temple Sot Cage Switch", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || ctx->GetTrickOption(RT_RUSTED_SWITCHES)) && logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return false;}), @@ -389,7 +389,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_NARROW_STAIRS] = Region("Fire Temple Narrow Stairs", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_SOT_CAGE_UPPER_DOOR, []{return logic->TakeDamage();}), @@ -464,7 +464,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOOP_CAGE_FOYER_SIDE] = Region("Fire Temple MQ Loop Cage Foyer Side", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_FOYER_LOWER, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_LIKE_LIKE);});}), @@ -502,7 +502,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOOP_FLARE_DANCER] = Region("Fire Temple MQ Loop Flare Dancer", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump()) && AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER);})), + LOCATION(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, (logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump()) && AnyAgeTime([]{return logic->CanKillEnemy(RE_FLARE_DANCER) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOOP_5_TILE_ROOM, []{return true;}), @@ -520,7 +520,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_LOOP_GORON_CAGE] = Region("Fire Temple MQ Loop Goron Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_LOOP_CAGE_SWITCH, []{return logic->Get(LOGIC_FIRE_OPENED_LOWEST_GORON_CAGE);}), @@ -530,7 +530,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM] = Region("Fire Temple MQ Near Boss Room", SCENE_FIRE_TEMPLE, {}, { //Locations //If we're using the south torch as the initial torch, or using FAs, we either have to cross to the north to remove the crate, or use a trick to ignore it - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->FireTimer() >= 24 && ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW)))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, (logic->FireTimer() >= 24 && ctx->GetTrickOption(RT_FIRE_MQ_NEAR_BOSS) && (logic->CanUse(RG_FIRE_ARROWS) || (logic->IsAdult && logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST))), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_1, logic->FireTimer() >= 24 && logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_2, logic->FireTimer() >= 24 && logic->CanBreakCrates()), @@ -551,7 +551,7 @@ void RegionTable_Init_FireTemple() { //Fairies cannot be used for this as it is time sensetive, and NL is only useful with sticks as it disables other magic while in use, so it's tunic or raw damage taking ability. //testing tells me you take 3 ticks of lava damage, which is 12 internal damage or 3/4 of a heart at x1 damage multiplier, performing this run //logic->EffectiveHealth() works in half hearts for whatever reason, meaning this needs a deeper refactor to be perfect, but it should be good enough for now - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_DINS_FIRE) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS)))))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_GORON_TUNIC) || logic->EffectiveHealth() >= 2 || (logic->CanUse(RG_NAYRUS_LOVE) && logic->CanUse(RG_STICKS)))))), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_POT_2, logic->CanBreakPots()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_5, logic->CanBreakCrates()), @@ -567,7 +567,7 @@ void RegionTable_Init_FireTemple() { //Locations //If we have FAs, we can just remove the crate and use those to light the torches. //otherwise, with Dins, we first light them with dins and then use a bow shot - LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))), + LOCATION(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || (logic->CanUse(RG_DINS_FIRE) && logic->CanUse(RG_FAIRY_BOW))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_3, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_OUTSIDE_BOSS_CRATE_4, logic->CanBreakCrates()), }, { @@ -612,7 +612,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_TORCH_LOCKED_CAGE] = Region("Fire Temple MQ Torch Locked Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasFireSource()), + LOCATION(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, []{return true;}), @@ -623,7 +623,7 @@ void RegionTable_Init_FireTemple() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanUse(RG_HOOKSHOT);}), }, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_POT_1, logic->HookshotOrBoomerang()), LOCATION(RC_FIRE_TEMPLE_MQ_LAVA_TORCH_POT_2, logic->HookshotOrBoomerang()), }, { @@ -718,7 +718,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_3F_CURVED_CAGE] = Region("Fire Temple MQ 3F Curved Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_MAZE_SWITCH_DOOR, []{return true;}), @@ -726,7 +726,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAZE_CRATE_CAGE] = Region("Fire Temple MQ Maze Crate Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CRATE_3, logic->CanBreakCrates()), @@ -751,7 +751,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_MAZE_BOX_CAGE] = Region("Fire Temple MQ Maze Box Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CRATE_3, logic->CanBreakCrates()), @@ -789,7 +789,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_MQ_SHORTCUT_CAGE] = Region("Fire Temple MQ Shortcut Cage", SCENE_FIRE_TEMPLE, {}, { //Locations - LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, true), + LOCATION(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FIRE_TEMPLE_MQ_SHORTCUT_CLIMB, []{return logic->Get(LOGIC_FIRE_OPENED_UPPER_SHORTCUT);}), @@ -1006,7 +1006,7 @@ void RegionTable_Init_FireTemple() { //Locations //This requires nothing in N64 logic, but is tight enough to need rollspam with the one-point on which is stricter than I would normally consider in logic //Child basically needs the scarecrow or a bunny hood though due to a worse ledge grab. - LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, logic->IsAdult || logic->ReachScarecrow()), + LOCATION(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, (logic->IsAdult || logic->ReachScarecrow()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //The dropdown here is unusual in that it hits 1 of 3 locations: RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_LOWER, RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR, and RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_SWITCH diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp index 05253e5b2e8..8ec32fc509c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/forest_temple.cpp @@ -20,7 +20,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_TREES] = Region("Forest Temple Trees", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_FIRST_ROOM, (logic->IsAdult && logic->CanUse(RG_BOMB_BAG)) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_FOREST_FIRST_GS) && (logic->CanJumpslashExceptHammer() || (logic->IsChild && logic->CanUse(RG_BOMB_BAG))))), }, { //Exits @@ -76,7 +76,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH)), + LOCATION(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_LOWER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_LOWER_STALFOS_POT_2, logic->CanBreakPots()), }, { @@ -160,7 +160,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND] = Region("Forest Temple NE Courtyard Island", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return true;}), @@ -181,7 +181,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Region("Forest Temple Map Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_BLUE_BUBBLE)), + LOCATION(RC_FOREST_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_BLUE_BUBBLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_LOWER, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_BLUE_BUBBLE);});}), @@ -190,7 +190,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_SEWER] = Region("Forest Temple Sewer", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8 && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8), }, { @@ -201,7 +201,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_DRAINED_SEWER] = Region("Forest Temple Drained Well", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_WELL_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_WELL_WEST_HEART, true), LOCATION(RC_FOREST_TEMPLE_WELL_EAST_HEART, true), }, { @@ -217,7 +217,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FLOORMASTER_ROOM] = Region("Forest Temple Floormaster Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanDamage()), + LOCATION(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, logic->CanDamage() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return true;}), @@ -244,7 +244,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MIDDLE_BLOCK_PUSH_ROOM] = Region("Forest Temple Middle Block Push Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_LOWER_BLOCK_PUSH_ROOM, []{return true;}), @@ -273,7 +273,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_NW_HALLWAY_STRAIGHTENED] = Region("Forest Temple NW Hallway Straightened", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return true;}), @@ -285,7 +285,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), + LOCATION(RC_FOREST_TEMPLE_RED_POE_CHEST, logic->Get(LOGIC_FOREST_JOELLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NW_HALLWAY_TWISTED, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 3);}), @@ -298,7 +298,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_UPPER_STALFOS_POT_3, logic->CanBreakPots()), @@ -314,7 +314,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH)), + LOCATION(RC_FOREST_TEMPLE_BLUE_POE_CHEST, logic->Get(LOGIC_FOREST_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -348,7 +348,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_FALLING_ROOM] = Region("Forest Temple Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_SCARECROW_LEDGE, []{return true;}), @@ -385,7 +385,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return true;}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_GS_BASEMENT, logic->HookshotOrBoomerang()), }, { //Exits @@ -399,7 +399,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_TREES] = Region("Forest Temple MQ Trees", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA, ED_SHORT_JUMPSLASH, false) || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_ENTRYWAY, []{return true;}), @@ -456,7 +456,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH)), + LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_WOLFOS_POT_2, logic->CanBreakPots()), }, { @@ -511,7 +511,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_STRAIGHT_HALLWAY] = Region("Forest Temple MQ Straight Hallway", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, logic->SmallKeys(SCENE_FOREST_TEMPLE, 3) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_FLOORMASTER_ROOM, []{return true;}), @@ -546,7 +546,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_REDEAD_ROOM] = Region("Forest Temple MQ Redead Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);});}), @@ -599,7 +599,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_DRAINED_WELL, []{return logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)), + LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, (logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), //implies logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), @@ -615,7 +615,6 @@ void RegionTable_Init_ForestTemple() { }); areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD_DOORFRAME] = Region("Forest Temple MQ NE Courtyard Doorframe", SCENE_FOREST_TEMPLE, {}, { - //Locations //Actually killing the skull from the doorframe with melee is annoying. Hammer swing hits low enough unaided, other swords need to crouch stab but the spot is precise based on range. kokiri sword doesn't reach at all for adult. LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) || logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanStandingShield() && (logic->CanUse(RG_STICKS) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MASTER_SWORD) || (logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD))))), @@ -627,7 +626,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES] = Region("Forest Temple MQ Courtyard Top Ledges", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, []{return true;}), @@ -641,7 +640,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD_ISLAND] = Region("Forest Temple MQ NE Courtyard Island", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Skipping swim here is non-trival, needs a roll-jump. If a swim lock is added it's probably wise to copy deku baba events here @@ -659,7 +658,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_JOELLE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE)), + LOCATION(RC_FOREST_TEMPLE_MQ_MAP_CHEST, logic->Get(LOGIC_FOREST_JOELLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_UPPER_BLOCK_PUZZLE, []{return logic->SmallKeys(SCENE_FOREST_TEMPLE, 4);}), @@ -672,7 +671,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH, []{return logic->CanKillEnemy(RE_WOLFOS);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3)), + LOCATION(RC_FOREST_TEMPLE_MQ_BOW_CHEST, logic->Get(LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 3) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_UPPER_STALFOS_POT_3, logic->CanBreakPots()), @@ -688,7 +687,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_BETH, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH)), + LOCATION(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_FOREST_BETH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_1, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_2, logic->CanBreakPots()), LOCATION(RC_FOREST_TEMPLE_MQ_BLUE_POE_POT_3, logic->CanBreakPots()), @@ -715,7 +714,7 @@ void RegionTable_Init_ForestTemple() { areaTable[RR_FOREST_TEMPLE_MQ_FALLING_ROOM] = Region("Forest Temple MQ Falling Room", SCENE_FOREST_TEMPLE, {}, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD_LEDGE_ABOVE_ISLAND, []{return true;}), @@ -747,7 +746,7 @@ void RegionTable_Init_ForestTemple() { EventAccess(LOGIC_FOREST_OPEN_BOSS_HALLWAY, []{return logic->CanHitEyeTargets();}), }, { //Locations - LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, true), + LOCATION(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index b96441b31a6..efa6a3492e9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -63,7 +63,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_WOLFOS_ROOM] = Region("Ganon's Castle Forest Trial Wolfos Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS)), + LOCATION(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, logic->CanKillEnemy(RE_WOLFOS) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -137,8 +137,8 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, true), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -177,7 +177,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL_START] = Region("Ganon's Castle Shadow Trial Start", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -201,7 +201,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SHADOW_TRIAL_RUSTED_SWITCH, []{return (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_MEGATON_HAMMER);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH)), + LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_1, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_2, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_SHADOW_TRIAL_HEART_3, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_BOOMERANG)), @@ -256,7 +256,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH] = Region("Ganon's Castle Spirit Trial Before Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_GIANTS_KNIFE)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (logic->CanJumpslash() || logic->HasExplosives() || logic->CanUse(RG_GIANTS_KNIFE)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEAMOS_ROOM, []{return true;}), @@ -265,8 +265,8 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_AFTER_SWITCH] = Region("Ganon's Castle Spirit Trial After Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, logic->CanHitSwitch()), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, (logic->CanHitSwitch()) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH, []{return true;}), @@ -288,13 +288,13 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_CHESTS_ROOM] = Region("Ganon's Castle Light Trial Chests Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, true), - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanKillEnemy(RE_BIG_SKULLTULA) && logic->CanKillEnemy(RE_KEESE, ED_CLOSE, true, 3))), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, (ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanKillEnemy(RE_BIG_SKULLTULA) && logic->CanKillEnemy(RE_KEESE, ED_CLOSE, true, 3)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MAIN, []{return true;}), @@ -303,7 +303,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_TRIFORCE_ROOM] = Region("Ganon's Castle Light Trial Triforce Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL_CHESTS_ROOM, []{return true;}), @@ -400,7 +400,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST, []{return logic->CanHitEyeTargets();}) }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_STALFOS_ROOM, []{return true;}), @@ -412,7 +412,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST, []{return logic->CanHitEyeTargets();}) }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, logic->HasFireSource()), + LOCATION(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM, []{return logic->Get(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) && (logic->CanAvoidEnemy(RE_BEAMOS) || logic->CanKillEnemy(RE_ARMOS)) && logic->CanUse(RG_LONGSHOT);}), @@ -462,7 +462,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->CanJumpslash() || logic->HasExplosives();}), // bow can also hit at right angle }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire()), + LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_HEART, logic->BlueFire()), }, { //Exits @@ -513,7 +513,7 @@ void RegionTable_Init_GanonsCastle() { EventAccess(LOGIC_SHADOW_TRIAL_FIRST_CHEST, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, []{return logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}), @@ -542,7 +542,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE] = Region("Ganon's Castle MQ Shadow Trial Far Side", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH, []{return logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -574,7 +574,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH] = Region("Ganon's Castle MQ Spirit Trial Before Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->CanPassEnemy(RE_GREEN_BUBBLE)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, logic->CanPassEnemy(RE_GREEN_BUBBLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}), @@ -583,12 +583,12 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_AFTER_SWITCH] = Region("Ganon's Castle MQ Spirit Trial After Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), //better names for these would be nice. - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), - LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, (logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, ((logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH, []{return AnyAgeTime([]{return logic->CanUse(RG_BOMBCHU_5);});}), @@ -617,7 +617,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_TRIFORCE_ROOM] = Region("Ganon's Castle MQ Light Trial Triforce Room", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), + LOCATION(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return true;}), @@ -690,7 +690,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_TOWER_FLOOR_2] = Region("Ganon's Tower Floor 2", SCENE_GANONS_TOWER, {}, { //Locations - LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_GANONS_TOWER_BOSS_KEY_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GANONS_TOWER_STAIRS_2, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 6cf954250c6..b98124b8b29 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -18,8 +18,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LOBBY] = Region("Gerudo Training Ground Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets()), - LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets()), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_ENTRANCE_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), }, { //Exits @@ -31,7 +31,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_SAND_ROOM] = Region("Gerudo Training Ground Sand Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return true;}), @@ -45,11 +45,11 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE] = Region("Gerudo Training Ground Central Maze", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, (logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 3) && (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 4) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 6) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 7) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 9) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return true;}), @@ -58,8 +58,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT] = Region("Gerudo Training Ground Central Maze Right", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, true), }, { //Exits @@ -73,7 +73,7 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_PUSHED_HEAVY_BLOCK, []{return logic->CanUse(RG_SILVER_GAUNTLETS);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 4, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM_UPPER, []{return (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_FAKE_WALL) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || (logic->IsAdult && logic->CanGroundJump()));}), @@ -98,10 +98,10 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM] = Region("Gerudo Training Ground Like Like Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_LIKE_LIKE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, (ctx->GetTrickOption(RT_LENS_GTG) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_LIKE_LIKE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_BEHIND_HEAVY_BLOCK, []{return true;}), @@ -116,7 +116,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_ABOVE_MAZE] = Region("Gerudo Training Ground Above Eye", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER, []{return true;}), @@ -127,7 +127,7 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_CLEARED_EYE_STATUE, []{return logic->CanUse(RG_FAIRY_BOW);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->Get(LOGIC_GTG_CLEARED_EYE_STATUE)), + LOCATION(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, logic->Get(LOGIC_GTG_CLEARED_EYE_STATUE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM, []{return true;}), @@ -135,8 +135,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM] = Region("Gerudo Training Ground Hammer Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAttack()), - LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS))), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, logic->CanAttack() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_FAIRY_BOW);}), @@ -161,7 +161,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_UNDERWATER] = Region("Gerudo Training Ground Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 24), + LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 24 && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, []{return true;}), @@ -169,7 +169,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_DINALFOS] = Region("Gerudo Training Dinalfos", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_SOUTH_HEART, true), LOCATION(RC_GERUDO_TRAINING_GROUND_BEAMOS_EAST_HEART, true), }, { @@ -184,8 +184,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LOBBY] = Region("Gerudo Training Ground MQ Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_1, logic->CanBreakPots()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_POT_2, logic->CanBreakPots()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_POT_1, logic->CanBreakPots()), @@ -201,9 +201,9 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_BY_LOBBY] = Region("Gerudo Training Ground MQ Maze By Lobby", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, (ctx->GetTrickOption(RT_LENS_GTG_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -212,7 +212,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_FIRST_LOCK] = Region("Gerudo Training Ground MQ Maze First Lock", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return logic->SmallKeys(SCENE_GERUDO_TRAINING_GROUND, 1);}), @@ -233,7 +233,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM] = Region("Gerudo Training Ground MQ Sand Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -254,7 +254,7 @@ void RegionTable_Init_GerudoTrainingGround() { }, { //Locations //implies logic->CanKillEnemy(RE_BIG_SKULLTULA) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM, []{return true;}), @@ -270,7 +270,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_ROOM_BEHIND_BLOCK] = Region("Gerudo Training Ground MQ Room Behind Block", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //implies logic->CanKillEnemy(RE_SPIKE) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_FREEZARD)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, logic->CanKillEnemy(RE_FREEZARD) && logic->HasItem(RG_OPEN_CHEST)), }, { Entrance(RR_GERUDO_TRAINING_GROUND_MQ_BEHIND_BLOCK, []{return true;}), }); @@ -285,7 +285,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAGENTA_FIRE_ROOM] = Region("Gerudo Training Ground MQ Magenta Fire Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, logic->Get(LOGIC_GTG_MQ_MAZE_SWITCH) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return true;}), @@ -293,7 +293,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM] = Region("Gerudo Training Ground MQ Statue Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, logic->CanUse(RG_FAIRY_BOW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM_LEDGE, []{return logic->CanUse(RG_LONGSHOT);}), @@ -303,8 +303,8 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SLUG_ROOM] = Region("Gerudo Training Ground MQ Torch Slug Room", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //implies logic->CanKillEnemy(RE_TORCH_SLUG) - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE)), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_STATUE_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}), @@ -368,7 +368,7 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER] = Region("Gerudo Training Ground MQ Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { //Locations //it is possible to snipe the stingers with bow or sling before dropping in, or just get really lucky, and avoid needing to take damage, but that might be trick worthy - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage()), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, []{return true;}), @@ -380,8 +380,8 @@ void RegionTable_Init_GerudoTrainingGround() { EventAccess(LOGIC_GTG_PLATFORM_SILVER_RUPEES, []{return logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS);}), }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, true), - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, true), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -400,7 +400,7 @@ void RegionTable_Init_GerudoTrainingGround() { //is logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2, true) && logic->CanKillEnemy(RE_ARMOS, ED_CLOSE, true, 1, true) broken down to exclude sticks, as it takes too many to clear the room //Proper enemy kill room ammo logic is needed to handle this room //some combinations may be impossible without taking damage, keep an eye out for issues here - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_BOW) || ((logic->CanUse(RG_NUTS) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_BOOMERANG)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_FAIRY_SLINGSHOT)))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return true;}), @@ -409,4 +409,4 @@ void RegionTable_Init_GerudoTrainingGround() { #pragma endregion // clang-format on -} +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index 9def5685084..cb266125a61 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -48,7 +48,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), // very easy to break pot through ice LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, (logic->CanBreakPots() && logic->BlueFire()) || logic->HasExplosives() || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && ((logic->CanStandingShield() && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER))) || @@ -66,7 +66,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, (logic->IsChild || logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)) && logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_COMPASS_CHEST, (logic->IsChild || logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)) && logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ICE_CAVERN_FREESTANDING_POH, (logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)) && logic->BlueFire()), // can skip blue fire with rang trick LOCATION(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, logic->HookshotOrBoomerang()), }, { @@ -104,7 +104,7 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_FINAL_ROOM] = Region("Ice Cavern Final Room", SCENE_ICE_CAVERN, {}, { //Locations - LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);})), + LOCATION(RC_ICE_CAVERN_IRON_BOOTS_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS) && logic->HasItem(RG_OPEN_CHEST);})), LOCATION(RC_SHEIK_IN_ICE_CAVERN, AnyAgeTime([]{return logic->CanKillEnemy(RE_WOLFOS);})), // rando enables this for child }, { //Exits @@ -165,7 +165,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return logic->IsChild || logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP);}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && AnyAgeTime([]{return logic->CanHitSwitch();})), + LOCATION(RC_ICE_CAVERN_MQ_MAP_CHEST, logic->BlueFire() && AnyAgeTime([]{return logic->CanHitSwitch() && logic->HasItem(RG_OPEN_CHEST);})), }, {}); areaTable[RR_ICE_CAVERN_MQ_SCARECROW_ROOM] = Region("Ice Cavern MQ Scarecrow Room", SCENE_ICE_CAVERN, { @@ -197,7 +197,7 @@ void RegionTable_Init_IceCavern() { EventAccess(LOGIC_BLUE_FIRE_ACCESS, []{return true;}), }, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, true), + LOCATION(RC_ICE_CAVERN_MQ_COMPASS_CHEST, logic->HasItem(RG_OPEN_CHEST)), //It is possible for child with master, BGS or sticks, or adult with BGS, to hit this switch through the ice with a crouchstab, but it's precise and unintuitive for a trick LOCATION(RC_ICE_CAVERN_MQ_FREESTANDING_POH, logic->HasExplosives()), // can get with rang trick //doing RT_ICE_MQ_RED_ICE_GS as child is untested, as I could not perform the trick reliably even as adult @@ -209,8 +209,8 @@ void RegionTable_Init_IceCavern() { areaTable[RR_ICE_CAVERN_MQ_STALFOS_ROOM] = Region("Ice Cavern MQ Stalfos Room", SCENE_ICE_CAVERN, {}, { //Locations - LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->CanKillEnemy(RE_STALFOS)), - LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS)), // rando enables this for child + LOCATION(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, logic->CanKillEnemy(RE_STALFOS) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHEIK_IN_ICE_CAVERN, logic->CanKillEnemy(RE_STALFOS) && logic->HasItem(RG_OPEN_CHEST)), // rando enables this for child }, { //Exits Entrance(RR_ICE_CAVERN_MQ_WEST_CORRIDOR, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS);});}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp index ec0d3245751..3e58bd6beb4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -130,7 +130,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_WEST_TENTACLE, []{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE)), + LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->Get(LOGIC_JABU_WEST_TENTACLE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, []{return true;}), @@ -146,7 +146,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_FORK_NORTH_WEST] = Region("Jabu Jabus Belly Fork North West", SCENE_JABU_JABU, {}, { //Locations //ruto could theoretically clear this room, but it's hard because of the timer and she doesn't appear with you when you respawn after failing, which would force a savewarp - LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM, ED_CLOSE, false, 9)), + LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM, ED_CLOSE, false, 9) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_TO_FORK_NORTH_WEST, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_SHABOM, ED_CLOSE, false, 9);});}), @@ -186,7 +186,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_FORK_EAST] = Region("Jabu Jabus Belly Fork East", SCENE_JABU_JABU, {}, { //Locations //We can kill the Stingers with ruto - LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->Get(LOGIC_JABU_RUTO_IN_1F) || logic->CanKillEnemy(RE_STINGER, ED_CLOSE, true, 4)), + LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->Get(LOGIC_JABU_RUTO_IN_1F) || logic->CanKillEnemy(RE_STINGER, ED_CLOSE, true, 4) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, []{return true;}), @@ -259,12 +259,13 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash()), - LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, logic->BlastOrSmash() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FIRST_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER, logic->BlastOrSmash()), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return true;}), @@ -276,7 +277,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_LIFT_ROOM_COW, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, true), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_HEART_1, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_HEART_2, true), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIFT_RUPEE_1, logic->CanUse(RG_IRON_BOOTS)), @@ -296,7 +297,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_HOLES_ROOM_DOOR, []{return true;}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, (logic->CanHitSwitch(ED_HOOKSHOT, true) || (ctx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG) && logic->HasItem(RG_BRONZE_SCALE))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GEYSER_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_GEYSER_POT_2, logic->CanBreakPots()), //Getting the ones closest to the ledge with rang may be a trick due to the awkward angle without blind shooting through the flesh @@ -329,11 +330,16 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_HOLES_BASEMENT] = Region("Jabu Jabus Belly MQ Holes Basement", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_2, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_GRASS_3, logic->CanCutShrubs()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1, logic->HasExplosives()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2, logic->HasExplosives()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3, logic->HasExplosives()), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return true /* logic->HasItem(RG_CLIMB) */;}), @@ -347,9 +353,9 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_JABU_MQ_WATER_SWITCH_LIFT_ACCESS, []{return logic->CanKillEnemy(RE_LIZALFOS);}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, true), - LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS)), - LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, (logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, logic->CanKillEnemy(RE_LIZALFOS) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, ((logic->CanUse(RG_SONG_OF_TIME) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->CanUse(RG_BOOMERANG))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_TIME_BLOCK_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_BOOMERANG_GRASS, logic->CanCutShrubs()), @@ -424,12 +430,14 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_FORK_NORTH_EAST] = Region("Jabu Jabus Belly MQ Fork North East", SCENE_JABU_JABU, {}, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) - LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIKE_LIKES_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_LIKE_LIKES_POT_2, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_GRASS, logic->CanCutShrubs()), LOCATION(RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_1, logic->CanBreakSmallCrates()), LOCATION(RC_JABU_JABUS_BELLY_MQ_TRIPLE_HALLWAY_SMALL_CRATE_2, logic->CanBreakSmallCrates()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2, logic->BlastOrSmash()), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, []{return true;}), @@ -510,7 +518,7 @@ void RegionTable_Init_JabuJabusBelly() { areaTable[RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM_EAST_LEDGE] = Region("Jabu Jabus Belly MQ Lift Room East Ledge", SCENE_JABU_JABU, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, logic->Get(LOGIC_JABU_MQ_LIFT_ROOM_COW) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, []{return true;}), @@ -530,7 +538,7 @@ void RegionTable_Init_JabuJabusBelly() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), + LOCATION(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT))), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_POT_1, logic->CanBreakPots()), LOCATION(RC_JABU_JABUS_BELLY_MQ_BEFORE_BOSS_GRASS_1, logic->CanCutShrubs()), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp index 45973796d68..289469af9be 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -65,7 +65,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WHISPERING_WALLS_SIDE_ROOM] = Region("Shadow Temple Whispering Walls Side Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->CanKillEnemy(RE_KEESE)), + LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->CanKillEnemy(RE_KEESE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MAP_CHEST_POT_2, logic->CanBreakPots()), }, { @@ -75,7 +75,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_DEAD_HAND] = Region("Shadow Temple Dead Hand", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_WHISPERING_WALLS_END, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_DEAD_HAND);});}), @@ -94,7 +94,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_COMPASS_ROOM] = Region("Shadow Temple Compass Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanKillEnemy(RE_GIBDO)), + LOCATION(RC_SHADOW_TEMPLE_COMPASS_CHEST, logic->CanKillEnemy(RE_GIBDO) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_GIBDO);});}), @@ -102,7 +102,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_SPINNING_BLADES] = Region("Shadow Temple Spinning Blades", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, ((logic->IsAdult && logic->HasItem(RG_OPEN_CHEST)) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, []{return true;}), @@ -148,7 +148,7 @@ void RegionTable_Init_ShadowTemple() { // See MQ for comments areaTable[RR_SHADOW_TEMPLE_STONE_UMBRELLA] = Region("Shadow Temple Stone Umbrella", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_2, logic->CanBreakPots()), @@ -161,8 +161,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_STONE_UMBRELLA_UPPER] = Region("Shadow Temple Stone Umbrella Upper", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. LOCATION(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)), LOCATION(RC_SHADOW_TEMPLE_FALLING_SPIKES_POT_3, logic->CanBreakPots()), @@ -180,8 +180,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPINNING_BLADES] = Region("Shadow Temple Invisible Spinning Blades", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE)), - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, AnyAgeTime([]{return logic->CanKillEnemy(RE_LIKE_LIKE) && logic->CanKillEnemy(RE_KEESE);}) && ((logic->IsAdult && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)) || logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG))), //We cannot repeat the MQ invisible blades trick for these hearts as the like-like does not respawn if the room is cleared LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || logic->CanUse(RG_BOOMERANG)), @@ -193,7 +193,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPIKES] = Region("Shadow Temple Invisible Spikes", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC))), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC))), }, { //Exits Entrance(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2);}), @@ -237,7 +237,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL_HINT_ROOM] = Region("Shadow Temple Wind Tunnel Hint Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -246,8 +246,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_ROOM_TO_BOAT] = Region("Shadow Temple Room to Boat", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2)), - LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives()), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_AFTER_WIND_POT_2, logic->CanBreakPots()), }, { @@ -313,7 +313,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_X_CROSS] = Region("Shadow Temple X-Cross", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanKillEnemy(RE_FLOORMASTER)), + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanKillEnemy(RE_FLOORMASTER) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_FLOORMASTER_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_FLOORMASTER_POT_2, logic->CanBreakPots()), }, { @@ -331,8 +331,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_WOODEN_SPIKES] = Region("Shadow Temple Wooden Spikes", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_SPIKE_WALLS_POT_1, logic->CanBreakPots()), }, { //Exits @@ -406,7 +406,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_SIDE_ROOM] = Region("Shadow Temple MQ Whispering Walls Redeads", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_ENTRANCE_REDEAD_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_ENTRANCE_REDEAD_POT_2, logic->CanBreakPots()), }, { @@ -416,7 +416,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_DEAD_HAND] = Region("Shadow Temple MQ Whispering Walls Dead Hand", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND)), + LOCATION(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, logic->CanKillEnemy(RE_DEAD_HAND) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS_END, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_DEAD_HAND);});}), @@ -436,7 +436,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B2_GIBDO_ROOM] = Region("Shadow Temple MQ B2 Gibdo Room", SCENE_SHADOW_TEMPLE, {}, { //Locations //Doing this sets the shared flag for the glass in RR_SHADOW_TEMPLE_MQ_WHISPERING_WALLS, but doesn't seem to affect the chest - LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanKillEnemy(RE_GIBDO) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, logic->CanKillEnemy(RE_GIBDO) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_GIBDO);});}), @@ -444,7 +444,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM] = Region("Shadow Temple MQ B2 Spinning Blade Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())))), + LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, (logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));});}), @@ -453,7 +453,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH] = Region("Shadow Temple MQ Shortcut Path", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA);}), @@ -497,9 +497,9 @@ void RegionTable_Init_ShadowTemple() { //you take half a heart base from a spit out, double check EffectiveHealth when damage logic gets reworked //Child is too small to get hit by the blades doesn't need the trick or lens for dodging them LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH))), - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH))), + (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && + ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), }, { @@ -509,7 +509,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Region("Shadow Temple MQ Lower Huge Pit", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR_B3, []{return logic->CanUse(RG_LONGSHOT);}), @@ -525,7 +525,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM] = Region("Shadow Temple MQ Stone Umbrella Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_WEST_POT, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_UMBRELLA_EAST_POT, logic->CanBreakPots()), @@ -539,8 +539,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA] = Region("Shadow Temple MQ Upper Stone Umbrella", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, true), - LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, true), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), //Assuming the known setup for RT_SHADOW_UMBRELLA_HOVER and RT_SHADOW_UMBRELLA_GS, probably possible without sword + shield. LOCATION(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, ctx->GetTrickOption(RT_SHADOW_UMBRELLA_GS) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && logic->CanUse(RG_MASTER_SWORD)), LOCATION(RC_SHADOW_TEMPLE_MQ_UPPER_UMBRELLA_NORTH_POT, logic->CanBreakPots()), @@ -562,7 +562,7 @@ void RegionTable_Init_ShadowTemple() { (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC));}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_GORON_TUNIC))), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, (logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_GORON_TUNIC)) && logic->HasItem(RG_OPEN_CHEST))), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, []{return logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3);}), @@ -580,7 +580,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM] = Region("Shadow Temple MQ Stalfos Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)), + LOCATION(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);});}), @@ -601,7 +601,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_WIND_HINT_ROOM] = Region("Shadow Temple MQ Wind Hint Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_REDEAD)), + LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanPassEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { @@ -619,8 +619,8 @@ void RegionTable_Init_ShadowTemple() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO)), - LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, logic->CanKillEnemy(RE_GIBDO) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, logic->HasExplosives()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_BEFORE_BOAT_POT_2, logic->CanBreakPots()), @@ -708,7 +708,7 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_X_CROSS] = Region("Shadow Temple MQ X-Cross", SCENE_SHADOW_TEMPLE, {}, { //Locations //don't use CanDetonateUprightBombFlower as blue fire logic would need to account for player having multiple bottles & taking damage multiple times - LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, (logic->CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)) && logic->CanKillEnemy(RE_DEAD_HAND) && (logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, (logic->CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_SHADOW_MQ_DEADHAND)) && logic->CanKillEnemy(RE_DEAD_HAND) && (logic->CanDetonateBombFlowers() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_DEAD_HAND_POT_1, logic->CanBreakPots()), LOCATION(RC_SHADOW_TEMPLE_MQ_DEAD_HAND_POT_2, logic->CanBreakPots()), }, { @@ -726,8 +726,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_SPIKE_WALLS_ROOM] = Region("Shadow Temple MQ Spike Walls Room", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE)), - LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_SPIKE_BARICADE_POT, logic->CanBreakPots()), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 4f37e3346c0..61f7b1171d0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -60,7 +60,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE, []{return logic->CanHitSwitch();}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH, []{return logic->CanUse(RG_HOVER_BOOTS) || (logic->Get(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE) && logic->CanPassEnemy(RE_GREEN_BUBBLE, ED_CLOSE, false));}), @@ -85,7 +85,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Locations // these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust - LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch() && logic->HasItem(RG_OPEN_CHEST)), // possible to collect without lowering fence, should be a trick LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), }, { @@ -126,8 +126,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F] = Region("Spirit Temple Sun On Floor 2F", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW);})), - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW);})), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST);})), + LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanHitSwitch(ED_BOMB_THROW) && logic->HasItem(RG_OPEN_CHEST);})), LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_2F, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->TakeDamage() ? ED_SHORT_JUMPSLASH : ED_BOMB_THROW);}, false, RR_SPIRIT_TEMPLE_SUN_ON_FLOOR_1F, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG);})), LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_BOMB_BAG) && logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash())), @@ -148,7 +148,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_SAND_PIT] = Region("Spirit Temple Sand Pit", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)))), + LOCATION(RC_SPIRIT_TEMPLE_COMPASS_CHEST, (logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, []{return true;}), @@ -177,7 +177,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_PAST_BOULDERS] = Region("Spirit Temple Past Boulders", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -192,8 +192,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM] = Region("Spirit Temple 2F Mirror Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return true/*str0 || SunlightArrows()*/;})), - LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return true/*str0 || SunlightArrows()*/;})), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return logic->HasItem(RG_OPEN_CHEST)/*str0 || SunlightArrows()*/;})), + LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR_ROOM, []{return logic->HasItem(RG_OPEN_CHEST)/*str0 || SunlightArrows()*/;})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_1F_MIRROR_ROOM, []{return true;}), @@ -203,7 +203,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD] = Region("Spirit Temple Statue Rooom Child", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM access - LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));}, false, + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return (logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST));}, false, RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();})), LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);}, false, RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) ? ED_BOOMERANG : ED_HOOKSHOT);}, @@ -250,7 +250,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM] = Region("Spirit Temple Statue Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();}, false, + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST);}, false, RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));})), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})), @@ -302,9 +302,9 @@ void RegionTable_Init_SpiritTemple() { //Locations //Spawning the chest to get here is accounted for in movement logic, so we only need to confirm it can be spawned here LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, - []{return logic->HasFireSource() || + []{return (logic->HasFireSource() || (logic->Get(LOGIC_SPIRIT_SUN_BLOCK_TORCH) && //Possible without str0 by timing a shot during a backflip from the ledge, but it's probably a separate trick - (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW)/* && str0*/)));})), + (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW)) && logic->HasItem(RG_OPEN_CHEST)/* && str0*/)));})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, []{return true;}), @@ -335,7 +335,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND] = Region("Spirit Temple Outer Right Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return true;})), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_RIGHT_HAND_EXIT, []{return true;}), @@ -358,7 +358,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_INNER_LEFT_HAND] = Region("Spirit Temple Inner Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Assumes RR_SPIRIT_TEMPLE_INNER_WEST_HAND access via RR_SPIRIT_TEMPLE_STATUE_ROOM_CHILD and RR_SPIRIT_TEMPLE_STATUE_ROOM. - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY)/* && CanClimb()*/;})), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_LEFT_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST)/* && CanClimb()*/;})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), @@ -374,7 +374,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Locations //Assumes RR_SPIRIT_TEMPLE_INNER_LEFT_HAND access - LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_ZELDAS_LULLABY);})), + LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_ZELDAS_LULLABY) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_ADULT, []{return true;}), @@ -404,7 +404,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_4_ARMOS] = Region("Spirit Temple 4 Armos", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || logic->SunlightArrows()) && logic->HasExplosives()), + LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, ((logic->CanUse(RG_MIRROR_SHIELD) || logic->SunlightArrows()) && logic->HasExplosives()) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, logic->HasExplosives() && logic->CanUse(RG_SUNS_SONG)), }, { Entrance(RR_SPIRIT_TEMPLE_BEAMOS_PITS, []{return true;}), @@ -414,7 +414,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_4_ARMOS_SIDE_ROOM] = Region("Spirit Temple 4 Armos Side Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_4_ARMOS, []{return true;}), @@ -422,8 +422,8 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHEST_STAIRS] = Region("Spirit Temple Chest Stairs", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)), - LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_4_ARMOS, []{return true;}), @@ -444,7 +444,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_OUTER_LEFT_HAND] = Region("Spirit Temple Outer Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_LEFT_HAND_EXIT, []{return true;}), @@ -480,9 +480,9 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_FAKE_DOORS_ROOM] = Region("Spirit Temple Fake Doors Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, (logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || + LOCATION(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, ((logic->TakeDamage() && ctx->GetTrickOption(RT_FLAMING_CHESTS)) || (AnyAgeTime([]{return logic->CanHitEyeTargets() && logic->CanAvoidEnemy(RE_TORCH_SLUG, true, 4);}) - && logic->CanUse(RG_HOOKSHOT))), + && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}), @@ -509,7 +509,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return logic->HasExplosives()/*&& str0*/;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()), + LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return true;}), @@ -553,14 +553,18 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_FORWARDS_SPIRIT_ADULT, []{return logic->IsAdult;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, true), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG)), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_3, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_4, logic->CanBreakPots()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_3, logic->BlastOrSmash()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER, logic->CanUse(RG_BOMBCHU_5)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}), @@ -575,10 +579,11 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_SLUGMA_POT, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_LEFT_HEART, logic->CanHitEyeTargets()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_RIGHT_HEART, logic->CanHitEyeTargets()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, logic->Get(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Nabooru's legs are technically visible one way collision here, but I'm not sure if this counts @@ -640,7 +645,7 @@ void RegionTable_Init_SpiritTemple() { logic->CanKillEnemy(RE_ANUBIS, ED_BOOMERANG) && logic->CanKillEnemy(RE_KEESE, ED_FAR)*/;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->Get(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_TURNTABLE, []{return true;}), @@ -653,7 +658,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_MAP_ROOM_ENEMIES, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE, ED_BOOMERANG);}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //The bridge is a temp flag, so not a way to cross south to north in logic @@ -663,7 +668,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_1F_CHEST_SWITCH] = Region("Spirit Temple MQ West 1F Rusted Switch", SCENE_SPIRIT_TEMPLE, { //Events - EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER);}), + EventAccess(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->HasItem(RG_OPEN_CHEST);}), EventAccess(LOGIC_SPIRIT_MQ_CRAWL_BOULDER, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}), }, {}, { //Exits @@ -685,9 +690,9 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR] = Region("Spirit Temple MQ Sun on Floor Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations //Implies CanKillEnemy(RE_LIKE_LIKE) - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->CanKillEnemy(RE_BEAMOS);})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return logic->CanKillEnemy(RE_BEAMOS) && logic->HasItem(RG_OPEN_CHEST);})), //Sunlights only temp spawn this chest, which is unintuitive/a bug. - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return (logic->HasExplosives() || logic->SunlightArrows()) && logic->CanUse(RG_HOOKSHOT);})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_ON_FLOOR, []{return ((logic->HasExplosives() || logic->SunlightArrows()) && logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}), @@ -760,7 +765,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_MQ_STATUE_ROOM_TORCHES, []{return logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE));}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST);})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_CENTER_EAST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_WEST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_EASTMOST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})), @@ -787,7 +792,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM] = Region("Spirit Temple MQ Sun Block Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return true/*str0*/;})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->HasItem(RG_OPEN_CHEST)/*str0*/;})), //RT_SPIRIT_MQ_SUN_BLOCK_GS should probably be expanded to cover all ground based methods when str0 is added, as it can be hit with longshot because the skull hitbox is larger than the model LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return (logic->CanUse(RG_HOOKSHOT)/* && (str0 || SunlightArrows())*/) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})), @@ -819,7 +824,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND] = Region("Spirit Temple MQ Outer Right Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return true;})), + LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits //If it is ever relevent for 1 age to spawn the mirror shield chest for the other can longshot across, it needs an eventAccess @@ -839,7 +844,7 @@ void RegionTable_Init_SpiritTemple() { //Locations //Hard child locked because pushing the block is a permanent flag that blocks the eye target and cannot be undone //but it resets as Child as a rando QoL feature - LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, []{return logic->IsChild && logic->CanHitEyeTargets();})), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_DOOR, []{return logic->IsChild && logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits //if going to RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_HOLE from here is ever relevant, there needs to be an event to handle the block @@ -873,7 +878,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_INNER_LEFT_HAND] = Region("Spirit Temple MQ Inner East Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanBreakCrates()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanBreakCrates() && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), @@ -884,7 +889,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE] = Region("Spirit Temple MQ Chest Ledge", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), @@ -917,6 +922,7 @@ void RegionTable_Init_SpiritTemple() { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_POT_2, logic->CanBreakPots()), + LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER, logic->BlastOrSmash()), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_FOYER, []{return logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && (logic->CanUseSword() || logic->CanUse(RG_STICKS)));}), @@ -927,7 +933,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SAND_PIT] = Region("Spirit Temple MQ Sand Pit", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, logic->CanKillEnemy(RE_PURPLE_LEEVER) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)))), + LOCATION(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, (logic->CanKillEnemy(RE_PURPLE_LEEVER) && (logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER)))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -954,7 +960,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SKULLTULA_ROOM] = Region("Spirit Temple MQ Skulltula Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)), }, { //Exits @@ -975,7 +981,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS] = Region("Spirit Temple MQ Beamos Pits", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()), }, { //Exits @@ -986,7 +992,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM] = Region("Spirit Temple MQ SoT Sun Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { //Exits @@ -1014,7 +1020,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_LEFT_HAND] = Region("Spirit Temple MQ Outer Left Hand", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->CanUse(RG_LONGSHOT);}), @@ -1024,7 +1030,7 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM] = Region("Spirit Temple MQ 3F Gibdo Room", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, true), + LOCATION(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return true;}), @@ -1099,7 +1105,7 @@ void RegionTable_Init_SpiritTemple() { EventAccess(LOGIC_SPIRIT_PUSHED_4F_MIRRORS, []{return ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows())/* && str0*/;}), }, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp index e03026bae40..656dab3071a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp @@ -175,7 +175,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_4_SPIKES_ROOM] = Region("Water Temple 4 Spikes Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MAP_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 4);})), + LOCATION(RC_WATER_TEMPLE_MAP_CHEST, AnyAgeTime([]{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 4) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_WATER_TEMPLE_SIDE_TOWER_1F, []{return AnyAgeTime([]{return logic->CanKillEnemy(RE_SPIKE, ED_CLOSE, true, 4);});}), @@ -183,7 +183,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CRACKED_WALL] = Region("Water Temple Cracked Wall", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, logic->WaterLevel(WL_LOW_OR_MID) || logic->CanOpenUnderwaterChest()), + LOCATION(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, (logic->WaterLevel(WL_LOW_OR_MID) || logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_SIDE_TOWER_2F, []{return true;}), @@ -191,8 +191,8 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_TORCH_ROOM] = Region("Water Temple Torch Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, AnyAgeTime([]{return (logic->WaterLevel(WL_LOW) && logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3)) || - logic->CanOpenUnderwaterChest();})), + LOCATION(RC_WATER_TEMPLE_TORCHES_CHEST, AnyAgeTime([]{return ((logic->WaterLevel(WL_LOW) && logic->CanKillEnemy(RE_SHELL_BLADE, ED_CLOSE, true, 3)) || + logic->CanOpenUnderwaterChest()) && logic->HasItem(RG_OPEN_CHEST);})), }, { //Exits Entrance(RR_WATER_TEMPLE_SIDE_TOWER_1F, []{return ((logic->WaterLevel(WL_LOW) || logic->CanUse(RG_IRON_BOOTS)) && @@ -215,7 +215,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BOULDERS_SOUTH] = Region("Water Temple Boulders South", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_BEHIND_SPIKE_MOAT, []{return logic->SmallKeys(SCENE_WATER_TEMPLE, 4);}), @@ -285,11 +285,11 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_CANAL_ALCOVE] = Region("Water Temple Canal Alcove", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) || //child can also do a hovers backwalk backflip to reach the token after killing the skull ((logic->IsAdult || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())) && //killing with bombchu from here is hard due to the terrain, but adult can do it much easier from the river so it's only relevant for child - logic->CanUse(RG_HOVER_BOOTS) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->HasItem(RG_BRONZE_SCALE) && logic->IsAdult ? ED_SHORT_JUMPSLASH : ED_BOOMERANG))), + logic->CanUse(RG_HOVER_BOOTS) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, logic->HasItem(RG_BRONZE_SCALE) && logic->IsAdult ? ED_SHORT_JUMPSLASH : ED_BOOMERANG))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_3_JETS_SWITCH, []{return true;}), @@ -299,7 +299,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BOULDER_CANAL] = Region("Water Temple Boulder Canal", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, (logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, ((logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //making the jump as adult without jumpslash is possible, but hard enough to be a trick @@ -311,7 +311,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_BEHIND_CANAL] = Region("Water Temple Behind Canal", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 8), + LOCATION(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->WaterTimer() >= 8 && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_BOULDER_CANAL, []{return logic->HasItem(RG_BRONZE_SCALE);}), @@ -323,7 +323,7 @@ void RegionTable_Init_WaterTemple() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, true), + LOCATION(RC_WATER_TEMPLE_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_BOSS_KEY_POT_2, logic->CanBreakPots()), }, { @@ -373,10 +373,10 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Region("Water Temple Dragon Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->HasItem(RG_BRONZE_SCALE) && + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, (logic->HasItem(RG_BRONZE_SCALE) && ((logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_IRON_BOOTS)) || (((logic->IsAdult && ctx->GetTrickOption(RT_WATER_ADULT_DRAGON)) || (logic->IsChild && ctx->GetTrickOption(RT_WATER_CHILD_DRAGON))) && - logic->CanHitSwitch(ED_BOOMERANG, true) && (logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))))), + logic->CanHitSwitch(ED_BOOMERANG, true) && (logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_OUTSIDE_DRAGON_ROOM, []{return true;}), @@ -418,7 +418,7 @@ void RegionTable_Init_WaterTemple() { //Assuming tunic and irons was checked on entry areaTable[RR_WATER_TEMPLE_PILLAR_B1] = Region("Water Temple Pillar B1", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE)), + LOCATION(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits //Can't know water level, so we'll just assume any possibility and skip to MAIN @@ -427,7 +427,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_JET_CHEST_ROOM] = Region("Water Temple Jet Chest Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile()), + LOCATION(RC_WATER_TEMPLE_COMPASS_CHEST, logic->CanUseProjectile() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_2, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_NEAR_COMPASS_POT_3, logic->CanBreakPots()), @@ -477,7 +477,7 @@ void RegionTable_Init_WaterTemple() { //Currently assumes WL_LOW_OR_MID as there's no way to reach it on WL_HIGH in logic, this will need splitting if one is added areaTable[RR_WATER_TEMPLE_BLOCK_LOOP_BACK] = Region("Water Temple Block Loop Back", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, true), + LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_1, logic->CanBreakPots()), LOCATION(RC_WATER_TEMPLE_CENTRAL_BOW_POT_2, logic->CanBreakPots()), }, {}); @@ -564,7 +564,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_SOT_PIT_ROOM] = Region("Water Temple Song Of Time Pit Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, true), + LOCATION(RC_WATER_TEMPLE_LONGSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, []{return true;}), @@ -601,10 +601,10 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_ABOVE_DRAGON] = Region("Water Temple Above Dragon", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, true), - LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, logic->IsAdult && logic->CanHitSwitch(ED_LONGSHOT) && logic->HasItem(RG_BRONZE_SCALE) && + LOCATION(RC_WATER_TEMPLE_RIVER_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_WATER_TEMPLE_DRAGON_CHEST, (logic->IsAdult && logic->CanHitSwitch(ED_LONGSHOT) && logic->HasItem(RG_BRONZE_SCALE) && ((ctx->GetTrickOption(RT_WATER_ADULT_DRAGON) && (logic->HasItem(RG_SILVER_SCALE) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8))) || - ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))), + ctx->GetTrickOption(RT_WATER_DRAGON_JUMP_DIVE))) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanJumpslash());}), @@ -791,7 +791,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_SIDE_TOWER_2F] = Region("Water Temple MQ Side Tower 2F", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, logic->CanUse(RG_HOOKSHOT) && (logic->WaterLevel(WL_MID) || logic->CanOpenUnderwaterChest())), + LOCATION(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, (logic->CanUse(RG_HOOKSHOT) && (logic->WaterLevel(WL_MID) || logic->CanOpenUnderwaterChest())) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_SIDE_TOWER_1F, []{return logic->WaterLevel(WL_LOW) || logic->CanUse(RG_IRON_BOOTS);}), @@ -812,7 +812,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_3_STALFOS_ROOM] = Region("Water Temple MQ 3 Stalfos Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_MAP_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_LOW_EMBLEM, []{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 4);}), @@ -823,7 +823,7 @@ void RegionTable_Init_WaterTemple() { EventAccess(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS, []{return logic->CanKillEnemy(RE_LIZALFOS) && logic->CanKillEnemy(RE_SPIKE);}), }, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS)), + LOCATION(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, logic->Get(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_SIDE_TOWER_1F, []{return true;}), @@ -903,7 +903,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_PILLAR_B1_FINAL] = Region("Water Temple MQ Central Pillar B1 Final", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_OPEN_CHEST)), }, {}); areaTable[RR_WATER_TEMPLE_MQ_STORAGE_ROOM] = Region("Water Temple MQ Storage Room", SCENE_WATER_TEMPLE, {}, { @@ -1181,7 +1181,7 @@ void RegionTable_Init_WaterTemple() { //Exits Entrance(RR_WATER_TEMPLE_MQ_DRAGON_ROOM_DOOR, []{return true;}), Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_PIT, []{return true;}), - Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanHitSwitch() && AnyAgeTime([]{return logic->CanUse(RG_DINS_FIRE);});}), + Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST, []{return logic->CanHitSwitch() && AnyAgeTime([]{return logic->CanUse(RG_DINS_FIRE) && logic->HasItem(RG_OPEN_CHEST);});}), }); //this exists for the crates in preparation for clips through the grate @@ -1199,7 +1199,7 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_CHEST] = Region("Water Temple MQ Boss Key Room Chest", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, true), + LOCATION(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_BOSS_KEY_ROOM_SWITCH, []{return logic->CanHitSwitch(ED_BOMB_THROW) || logic->CanUse(RG_HOVER_BOOTS);}), @@ -1221,14 +1221,14 @@ void RegionTable_Init_WaterTemple() { areaTable[RR_WATER_TEMPLE_MQ_TRIANGLE_TORCH_ROOM] = Region("Water Temple MQ Triangle Torch Room", SCENE_WATER_TEMPLE, {}, { //Locations - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_1, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()) || + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_1, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)) || (logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_2, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()) || + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_2, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)) || (logic->CanUse(RG_BOMBCHU_5) && logic->CanUse(RG_BOOMERANG))), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_TRIPLE_TORCH_ROOM_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_MAIN, []{return logic->Get(LOGIC_WATER_MQ_B1_SWITCH) && ((logic->WaterLevel(WL_LOW) && logic->HasItem(RG_GOLDEN_SCALE)) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 40 && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_LONGSHOT))));}), @@ -1280,12 +1280,12 @@ void RegionTable_Init_WaterTemple() { //Locations LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_FRONT_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_FRONT_CRATE_2, logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_1, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_2, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), - LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->CanBreakCrates()), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_1, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_2, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_3, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_4, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_5, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), + LOCATION(RC_WATER_TEMPLE_MQ_WHIRLPOOL_SUBMERGED_CRATE_6, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16 && logic->HasItem(RG_ROLL)), }, { //Exits Entrance(RR_WATER_TEMPLE_MQ_BEHIND_SPIKE_MOAT, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index 2afda0fa85a..e37729a6aba 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -28,6 +28,10 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_HC_ROCK_1, true), + LOCATION(RC_HC_ROCK_2, true), + LOCATION(RC_HC_ROCK_3, true), + LOCATION(RC_HC_BOULDER, logic->BlastOrSmash()), LOCATION(RC_HC_MALON_GOSSIP_STONE, true), LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true), LOCATION(RC_HC_GRASS_1, logic->CanCutShrubs()), @@ -97,6 +101,14 @@ void RegionTable_Init_CastleGrounds() { LOCATION(RC_HC_STORMS_GROTTO_POT_2, logic->CanBreakPots()), LOCATION(RC_HC_STORMS_GROTTO_POT_3, logic->CanBreakPots()), LOCATION(RC_HC_STORMS_GROTTO_POT_4, logic->CanBreakPots()), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_1, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_2, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_3, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_4, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_5, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_6, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_7, true), + LOCATION(RC_HC_STORMS_GROTTO_ROCK_8, true), }, { //Exits Entrance(RR_HC_STORMS_GROTTO, []{return true;}), @@ -107,7 +119,14 @@ void RegionTable_Init_CastleGrounds() { EventAccess(LOGIC_BUILD_RAINBOW_BRIDGE, []{return logic->CanBuildRainbowBridge();}), }, { //Locations - LOCATION(RC_OGC_GS, logic->CanJumpslashExceptHammer() || logic->CanUseProjectile() || (logic->CanShield() && logic->CanUse(RG_MEGATON_HAMMER)) || logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_OGC_GS, logic->CanJumpslashExceptHammer() || logic->CanUseProjectile() || (logic->CanShield() && logic->CanUse(RG_MEGATON_HAMMER)) || logic->CanUse(RG_DINS_FIRE)), + LOCATION(RC_OGC_BRONZE_BOULDER_1, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_OGC_BRONZE_BOULDER_2, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_OGC_BRONZE_BOULDER_3, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_OGC_SILVER_BOULDER_1, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_OGC_SILVER_BOULDER_2, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_OGC_SILVER_BOULDER_3, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_OGC_SILVER_BOULDER_4, logic->CanUse(RG_SILVER_GAUNTLETS)), }, { //Exits Entrance(RR_CASTLE_GROUNDS, []{return logic->AtNight;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index 5d337222354..5d076005dd3 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp @@ -5,7 +5,21 @@ using namespace Rando; void RegionTable_Init_DeathMountainCrater() { // clang-format off - areaTable[RR_DMC_UPPER_NEARBY] = Region("DMC Upper Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, {}, { + areaTable[RR_DMC_UPPER_NEARBY] = Region("DMC Upper Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, { + LOCATION(RC_DMC_CIRCLE_ROCK_1, true), + LOCATION(RC_DMC_CIRCLE_ROCK_2, true), + LOCATION(RC_DMC_CIRCLE_ROCK_3, true), + LOCATION(RC_DMC_CIRCLE_ROCK_4, true), + LOCATION(RC_DMC_CIRCLE_ROCK_5, true), + LOCATION(RC_DMC_CIRCLE_ROCK_6, true), + LOCATION(RC_DMC_CIRCLE_ROCK_7, true), + LOCATION(RC_DMC_CIRCLE_ROCK_8, true), + LOCATION(RC_DMC_GOSSIP_ROCK_1, logic->IsChild), + LOCATION(RC_DMC_GOSSIP_ROCK_2, logic->IsChild), + LOCATION(RC_DMC_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_DMC_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_DMC_BOULDER_3, logic->BlastOrSmash()), + }, { //Exits Entrance(RR_DMC_UPPER_LOCAL, []{return logic->FireTimer() >= 48;}), Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return true;}), @@ -48,6 +62,14 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_NEAR_GC_POT_2, logic->CanBreakPots()), LOCATION(RC_DMC_NEAR_GC_POT_3, logic->CanBreakPots()), LOCATION(RC_DMC_NEAR_GC_POT_4, logic->CanBreakPots()), + LOCATION(RC_DMC_NEAR_GC_POT_1, logic->CanBreakPots()), + LOCATION(RC_DMC_NEAR_GC_POT_2, logic->CanBreakPots()), + LOCATION(RC_DMC_NEAR_GC_POT_3, logic->CanBreakPots()), + LOCATION(RC_DMC_NEAR_GC_POT_4, logic->CanBreakPots()), + LOCATION(RC_DMC_BRONZE_BOULDER_1, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMC_BRONZE_BOULDER_2, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMC_BRONZE_BOULDER_3, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMC_BRONZE_BOULDER_4, logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_DMC_LOWER_LOCAL, []{return logic->FireTimer() >= 48;}), @@ -90,6 +112,11 @@ void RegionTable_Init_DeathMountainCrater() { LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), LOCATION(RC_DMC_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->FireTimer() >= 8 || logic->Hearts() >= 3)), + LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_1, logic->IsAdult), + LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_2, logic->IsAdult), + LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_3, logic->IsAdult), + LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_4, logic->IsAdult), + LOCATION(RC_DMC_ROCK_BY_FIRE_TEMPLE_5, logic->IsAdult), }, { //Exits Entrance(RR_DMC_CENTRAL_NEARBY, []{return true;}), @@ -109,7 +136,7 @@ void RegionTable_Init_DeathMountainCrater() { areaTable[RR_DMC_UPPER_GROTTO] = Region("DMC Upper Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_DMC_UPPER_GROTTO_CHEST, true), + LOCATION(RC_DMC_UPPER_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMC_UPPER_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index d59043ab487..4296e338fe0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -10,7 +10,7 @@ void RegionTable_Init_DeathMountainTrail() { EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET));}), }, { //Locations - LOCATION(RC_DMT_CHEST, logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))), + LOCATION(RC_DMT_CHEST, (logic->BlastOrSmash() || (ctx->GetTrickOption(RT_DMT_BOMBABLE) && logic->IsChild && logic->HasItem(RG_GORONS_BRACELET))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMT_FREESTANDING_POH, logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL, RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET)))), LOCATION(RC_DMT_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET) || (ctx->GetTrickOption(RT_DMT_SOIL_GS) && (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS)) && logic->CanUse(RG_BOOMERANG)))), LOCATION(RC_DMT_GS_NEAR_KAK, logic->BlastOrSmash()), @@ -21,6 +21,33 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_2, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_DMT_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS) && (logic->HasExplosives() || logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_DMT_FLAG_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_DMT_ROCK_1, true), + LOCATION(RC_DMT_ROCK_2, true), + LOCATION(RC_DMT_ROCK_3, true), + LOCATION(RC_DMT_ROCK_4, true), + LOCATION(RC_DMT_ROCK_5, true), + LOCATION(RC_DMT_CIRCLE_ROCK_1, true), + LOCATION(RC_DMT_CIRCLE_ROCK_2, true), + LOCATION(RC_DMT_CIRCLE_ROCK_3, true), + LOCATION(RC_DMT_CIRCLE_ROCK_4, true), + LOCATION(RC_DMT_CIRCLE_ROCK_5, true), + LOCATION(RC_DMT_CIRCLE_ROCK_6, true), + LOCATION(RC_DMT_CIRCLE_ROCK_7, true), + LOCATION(RC_DMT_CIRCLE_ROCK_8, true), + LOCATION(RC_DMT_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_DMT_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_DMT_BOULDER_3, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_DMT_BRONZE_BOULDER_1, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_2, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_3, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_4, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_5, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_6, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_7, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_8, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_9, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_10, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_DMT_BRONZE_BOULDER_11, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_KAK_BEHIND_GATE, []{return true;}), @@ -43,6 +70,8 @@ void RegionTable_Init_DeathMountainTrail() { LOCATION(RC_DMT_GS_FALLING_ROCKS_PATH, logic->IsAdult && logic->CanGetNightTimeGS() && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DMT_UPPER_GS) && (logic->CanJumpslash() || logic->HasExplosives() || ((ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_HOOKSHOT_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))))) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), LOCATION(RC_DMT_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMT_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_DMT_COW_BOULDER, logic->BlastOrSmash()), + LOCATION(RC_DMT_SUMMIT_ROCK, logic->IsChild), LOCATION(RC_DMT_GOSSIP_STONE, true), }, { //Exits @@ -83,7 +112,7 @@ void RegionTable_Init_DeathMountainTrail() { areaTable[RR_DMT_STORMS_GROTTO] = Region("DMT Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_DMT_STORMS_GROTTO_CHEST, true), + LOCATION(RC_DMT_STORMS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_DMT_STORMS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_DMT_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp index 428281602fc..325cf85228f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp @@ -19,6 +19,24 @@ void RegionTable_Init_DesertColossus() { LOCATION(RC_COLOSSUS_BEAN_SPROUT_FAIRY_3, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_DESERT_COLOSSUS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_COLOSSUS_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_COLOSSUS_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_COLOSSUS_SILVER_BOULDER, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_COLOSSUS_ROCK, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_1, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_2, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_3, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_4, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_5, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_6, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_7, true), + LOCATION(RC_COLOSSUS_CIRCLE_1_ROCK_8, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_1, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_2, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_3, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_4, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_5, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_6, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_7, true), + LOCATION(RC_COLOSSUS_CIRCLE_2_ROCK_8, true), LOCATION(RC_COLOSSUS_GOSSIP_STONE, true), }, { //Exits diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp index f921c5483cd..839f118e6d6 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -152,7 +152,7 @@ void RegionTable_Init_GerudoFortress() { areaTable[RR_GF_NEAR_CHEST] = Region("GF Near Chest", SCENE_GERUDOS_FORTRESS, {}, { //Locations - LOCATION(RC_GF_CHEST, true), + LOCATION(RC_GF_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GF_GS_TOP_FLOOR, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) && logic->CanGetNightTimeGS()), }, { //Exits @@ -225,9 +225,8 @@ void RegionTable_Init_GerudoFortress() { LOCATION(RC_GF_HBA_CANOPY_EAST_CRATE, logic->CanBreakCrates()), LOCATION(RC_GF_HBA_CANOPY_WEST_CRATE, logic->CanBreakCrates()), LOCATION(RC_GF_NORTH_TARGET_EAST_CRATE, logic->CanBreakCrates()), - LOCATION(RC_GF_NORTH_TARGET_WEST_CRATE, logic->IsAdult || (logic->BlastOrSmash() || logic->HookshotOrBoomerang() || logic->CanUse(RG_HOVER_BOOTS))), - //implies logic->CanBreakCrates() - LOCATION(RC_GF_NORTH_TARGET_CHILD_CRATE, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_GF_NORTH_TARGET_WEST_CRATE, (logic->IsAdult || (logic->BlastOrSmash() || logic->HookshotOrBoomerang() || logic->CanUse(RG_HOVER_BOOTS))) && logic->CanBreakCrates()), + LOCATION(RC_GF_NORTH_TARGET_CHILD_CRATE, logic->IsChild && logic->BlastOrSmash() && logic->CanBreakCrates()), LOCATION(RC_GF_SOUTH_TARGET_EAST_CRATE, logic->CanBreakCrates()), LOCATION(RC_GF_SOUTH_TARGET_WEST_CRATE, logic->CanBreakCrates()), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index 370fdf0b1a9..9db0e0436e2 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -10,7 +10,17 @@ void RegionTable_Init_GerudoValley() { EventAccess(LOGIC_BUG_ACCESS, []{return logic->IsChild;}), }, { //Locations - LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_GS_SMALL_BRIDGE, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), + LOCATION(RC_GV_ROCK_1, true), + LOCATION(RC_GV_ROCK_2, true), + LOCATION(RC_GV_ROCK_3, true), + LOCATION(RC_GV_UNDERWATER_ROCK_1, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), + LOCATION(RC_GV_UNDERWATER_ROCK_2, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), + LOCATION(RC_GV_UNDERWATER_ROCK_3, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), + LOCATION(RC_GV_BOULDER_1, logic->IsAdult && logic->BlastOrSmash()), + LOCATION(RC_GV_BOULDER_2, logic->IsAdult && logic->BlastOrSmash()), + LOCATION(RC_GV_BRONZE_BOULDER_1, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_BRONZE_BOULDER_2, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), @@ -48,7 +58,10 @@ void RegionTable_Init_GerudoValley() { Entrance(RR_LAKE_HYLIA, []{return true;}), }); - areaTable[RR_GV_GROTTO_LEDGE] = Region("GV Grotto Ledge", SCENE_GERUDO_VALLEY, {}, {}, { + areaTable[RR_GV_GROTTO_LEDGE] = Region("GV Grotto Ledge", SCENE_GERUDO_VALLEY, {}, { + //Locations + LOCATION(RC_GV_SILVER_BOULDER, logic->CanUse(RG_SILVER_GAUNTLETS)), + }, { //Exits Entrance(RR_GV_UPPER_STREAM, []{return ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives();}), Entrance(RR_GV_LOWER_STREAM, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS);}), @@ -68,7 +81,7 @@ void RegionTable_Init_GerudoValley() { areaTable[RR_GV_FORTRESS_SIDE] = Region("GV Fortress Side", SCENE_GERUDO_VALLEY, {}, { //Locations - LOCATION(RC_GV_CHEST, logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))), + LOCATION(RC_GV_CHEST, (logic->IsAdult && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)))) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GV_TRADE_SAW, logic->IsAdult && logic->CanUse(RG_POACHERS_SAW)), LOCATION(RC_GV_GS_BEHIND_TENT, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), LOCATION(RC_GV_GS_PILLAR, logic->IsAdult && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()), @@ -76,6 +89,17 @@ void RegionTable_Init_GerudoValley() { LOCATION(RC_GV_CRATE_BRIDGE_2, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_GV_CRATE_BRIDGE_3, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_GV_CRATE_BRIDGE_4, logic->IsChild && logic->CanBreakCrates()), + LOCATION(RC_GV_ROCK_ACROSS_BRIDGE_1, logic->IsAdult), + LOCATION(RC_GV_ROCK_ACROSS_BRIDGE_2, logic->IsAdult), + LOCATION(RC_GV_ROCK_ACROSS_BRIDGE_3, logic->IsAdult), + LOCATION(RC_GV_ROCK_ACROSS_BRIDGE_4, logic->IsAdult), + LOCATION(RC_GV_BOULDER_ACROSS_BRIDGE, logic->IsAdult && logic->BlastOrSmash()), + LOCATION(RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_1, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_2, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_3, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_4, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_5, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_6, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits Entrance(RR_GF_OUTSKIRTS, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index 9641da2fae3..78c3359d14a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -18,9 +18,9 @@ void RegionTable_Init_GoronCity() { (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && (logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE)))));}), }, { //Locations - LOCATION(RC_GC_MAZE_LEFT_CHEST, logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))), - LOCATION(RC_GC_MAZE_CENTER_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), - LOCATION(RC_GC_MAZE_RIGHT_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_LEFT_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GC_MAZE_CENTER_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GC_MAZE_RIGHT_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) && (logic->CanUse(RG_BOMB_BAG) || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_GC_POT)))), LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && (logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))), LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)), @@ -35,7 +35,57 @@ void RegionTable_Init_GoronCity() { LOCATION(RC_GC_UPPER_STAIRCASE_POT_2, logic->CanBreakPots()), LOCATION(RC_GC_UPPER_STAIRCASE_POT_3, logic->CanBreakPots()), LOCATION(RC_GC_MAZE_CRATE, logic->BlastOrSmash() || (logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanBreakCrates())), - + LOCATION(RC_GC_ENTRANCE_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_GC_ENTRANCE_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_GC_ENTRANCE_BOULDER_3, logic->BlastOrSmash()), + LOCATION(RC_GC_LW_BOULDER_1, logic->Get(LOGIC_GORON_CITY_WOODS_WARP_OPEN)), + LOCATION(RC_GC_LW_BOULDER_2, logic->Get(LOGIC_GORON_CITY_WOODS_WARP_OPEN)), + LOCATION(RC_GC_LW_BOULDER_3, logic->Get(LOGIC_GORON_CITY_WOODS_WARP_OPEN)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_1, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_2, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_3, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_4, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_5, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_6, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_7, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_8, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_9, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_10, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_11, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_12, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_13, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_14, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_15, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_16, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_17, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_18, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_19, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_20, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_21, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_22, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_23, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_24, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_25, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_26, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_27, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_28, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_SILVER_BOULDER_29, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_GC_MAZE_BOULDER_1, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_2, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_3, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_4, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_5, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_6, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_7, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_8, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_9, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BOULDER_10, logic->BlastOrSmash()), + LOCATION(RC_GC_MAZE_BRONZE_BOULDER_1, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GC_MAZE_BRONZE_BOULDER_2, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GC_MAZE_BRONZE_BOULDER_3, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GC_MAZE_BRONZE_BOULDER_4, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GC_MAZE_BRONZE_BOULDER_5, logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_GC_MAZE_ROCK, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)), }, { //Exits Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index fc5ff2cc647..3ce3bcd4d4f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -32,6 +32,7 @@ void RegionTable_Init_Graveyard() { LOCATION(RC_GY_GRASS_11, logic->CanCutShrubs()), LOCATION(RC_GY_GRASS_12, logic->CanCutShrubs()), LOCATION(RC_GRAVEYARD_CRATE, ((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()), + LOCATION(RC_GY_ROCK, true), }, { //Exits Entrance(RR_GRAVEYARD_SHIELD_GRAVE, []{return logic->IsAdult || logic->AtNight;}), @@ -45,7 +46,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_SHIELD_GRAVE] = Region("Graveyard Shield Grave", SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN, {}, { //Locations - LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, true), + LOCATION(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -69,7 +70,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Region("Graveyard Heart Piece Grave", SCENE_REDEAD_GRAVE, {}, { //Locations - LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, logic->CanUse(RG_SUNS_SONG) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_THE_GRAVEYARD, []{return true;}), @@ -77,7 +78,7 @@ void RegionTable_Init_Graveyard() { areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Region("Graveyard Composers Grave", SCENE_ROYAL_FAMILYS_TOMB, {}, { //Locations - LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()), + LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()), LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), }, { @@ -90,7 +91,7 @@ void RegionTable_Init_Graveyard() { EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanBreakPots();}), }, { //Locations - LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true), + LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)), LOCATION(RC_GY_DAMPES_GRAVE_POT_1, logic->CanBreakPots()), LOCATION(RC_GY_DAMPES_GRAVE_POT_2, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp index b3730c982e5..991a6eaa9a3 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp @@ -22,7 +22,7 @@ void RegionTable_Init_HauntedWasteland() { EventAccess(LOGIC_CARPET_MERCHANT, []{return logic->HasItem(RG_ADULT_WALLET) && GetCheckPrice(RC_WASTELAND_BOMBCHU_SALESMAN) <= GetWalletCapacity() && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}), }, { //Locations - LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource()), + LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang() || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), // need to jumpslash immediately with two handed weapons LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 83bbfcff7ed..e46c2a058b6 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -110,6 +110,22 @@ void RegionTable_Init_HyruleField() { LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_5, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_6, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_HF_TEKTITE_GROTTO_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_SILVER_BOULDER, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_HF_ROCK_1, true), + LOCATION(RC_HF_ROCK_2, true), + LOCATION(RC_HF_ROCK_3, true), + LOCATION(RC_HF_ROCK_4, true), + LOCATION(RC_HF_ROCK_5, true), + LOCATION(RC_HF_ROCK_6, true), + LOCATION(RC_HF_ROCK_7, true), + LOCATION(RC_HF_ROCK_8, true), + LOCATION(RC_HF_BOULDER_NORTH, logic->BlastOrSmash()), + LOCATION(RC_HF_BOULDER_BY_MARKET, logic->BlastOrSmash()), + LOCATION(RC_HF_BOULDER_SOUTH, logic->BlastOrSmash()), + LOCATION(RC_HF_BRONZE_BOULDER_1, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_HF_BRONZE_BOULDER_2, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_HF_BRONZE_BOULDER_3, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), + LOCATION(RC_HF_BRONZE_BOULDER_4, logic->IsAdult && logic->CanUse(RG_MEGATON_HAMMER)), LOCATION(RC_HF_BUSH_NEAR_LAKE_1, true), LOCATION(RC_HF_BUSH_NEAR_LAKE_2, true), LOCATION(RC_HF_BUSH_NEAR_LAKE_3, true), @@ -189,7 +205,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_SOUTHEAST_GROTTO] = Region("HF Southeast Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, true), + LOCATION(RC_HF_SOUTHEAST_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_SOUTHEAST_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_SOUTHEAST_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -207,7 +223,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_OPEN_GROTTO] = Region("HF Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_OPEN_GROTTO_CHEST, true), + LOCATION(RC_HF_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), @@ -261,7 +277,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HF_NEAR_MARKET_GROTTO] = Region("HF Near Market Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, true), + LOCATION(RC_HF_NEAR_MARKET_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_HF_NEAR_MARKET_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_HF_NEAR_MARKET_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 77444333a78..ae5cf869fcd 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -15,7 +15,7 @@ void RegionTable_Init_Kakariko() { }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), - LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay), + LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->CanBreakCrates()), //Need Break one crate for get cucoo LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay), LOCATION(RC_KAK_TRADE_POCKET_CUCCO, logic->IsAdult && logic->AtDay && (logic->CanUse(RG_POCKET_EGG) && logic->Get(LOGIC_WAKE_UP_ADULT_TALON))), //Can kill lower kak skulls with pots @@ -60,6 +60,9 @@ void RegionTable_Init_Kakariko() { LOCATION(RC_KAK_NEAR_BOARDING_HOUSE_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_KAK_NEAR_BAZAAR_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_KAK_TREE, logic->CanBonkTrees()), + LOCATION(RC_KAK_SILVER_BOULDER, logic->IsAdult && logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_KAK_ROCK_1, true), + LOCATION(RC_KAK_ROCK_2, true), }, { //Exits Entrance(RR_HYRULE_FIELD, []{return true;}), @@ -247,7 +250,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_REDEAD_GROTTO] = Region("Kak Redead Grotto", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanKillEnemy(RE_REDEAD, ED_CLOSE, true, 2)), + LOCATION(RC_KAK_REDEAD_GROTTO_CHEST, logic->CanKillEnemy(RE_REDEAD, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_KAKARIKO_VILLAGE, []{return true;}), @@ -255,7 +258,7 @@ void RegionTable_Init_Kakariko() { areaTable[RR_KAK_OPEN_GROTTO] = Region("Kak Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_KAK_OPEN_GROTTO_CHEST, true), + LOCATION(RC_KAK_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KAK_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_KAK_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 0588ea0c25b..7bbccd2b409 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -70,6 +70,18 @@ void RegionTable_Init_KokiriForest() { LOCATION(RC_KF_ADULT_GRASS_18, logic->IsAdult && logic->CanCutShrubs()), LOCATION(RC_KF_ADULT_GRASS_19, logic->IsAdult && logic->CanCutShrubs()), LOCATION(RC_KF_ADULT_GRASS_20, logic->IsAdult && logic->CanCutShrubs()), + LOCATION(RC_KF_CIRCLE_ROCK_1, true), + LOCATION(RC_KF_CIRCLE_ROCK_2, true), + LOCATION(RC_KF_CIRCLE_ROCK_3, true), + LOCATION(RC_KF_CIRCLE_ROCK_4, true), + LOCATION(RC_KF_CIRCLE_ROCK_5, true), + LOCATION(RC_KF_CIRCLE_ROCK_6, true), + LOCATION(RC_KF_CIRCLE_ROCK_7, true), + LOCATION(RC_KF_CIRCLE_ROCK_8, true), + LOCATION(RC_KF_ROCK_BY_SARIAS_HOUSE, logic->IsChild), + LOCATION(RC_KF_ROCK_BEHIND_SARIAS_HOUSE, logic->IsChild), + LOCATION(RC_KF_ROCK_BY_MIDOS_HOUSE, logic->IsChild), + LOCATION(RC_KF_ROCK_BY_KNOW_IT_ALLS_HOUSE, logic->IsChild), }, { //Exits Entrance(RR_KF_BOULDER_LOOP, []{return logic->CanUse(RG_CRAWL);}), @@ -87,7 +99,7 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_BOULDER_LOOP] = Region("KF Boulder Loop", SCENE_KOKIRI_FOREST, {}, { //Locations - LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), + LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KF_BOULDER_RUPEE_1, logic->IsChild), LOCATION(RC_KF_BOULDER_RUPEE_2, logic->IsChild), LOCATION(RC_KF_CHILD_GRASS_MAZE_1, logic->IsChild && logic->CanCutShrubs()), @@ -129,10 +141,10 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_MIDOS_HOUSE] = Region("KF Mido's House", SCENE_MIDOS_HOUSE, {}, { //Locations - LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, true), - LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, true), - LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, true), - LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, true), + LOCATION(RC_KF_MIDOS_TOP_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_TOP_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_KOKIRI_FOREST, []{return true;}), @@ -184,7 +196,7 @@ void RegionTable_Init_KokiriForest() { areaTable[RR_KF_STORMS_GROTTO] = Region("KF Storms Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_KF_STORMS_GROTTO_CHEST, true), + LOCATION(RC_KF_STORMS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_KF_STORMS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_KF_STORMS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp index 344b609dace..f0d9ed200f5 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp @@ -102,7 +102,10 @@ void RegionTable_Init_LakeHylia() { Entrance(RR_WATER_TEMPLE_ENTRYWAY, []{return logic->CanUse(RG_HOOKSHOT) && ((logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LH_WATER_HOOKSHOT) && logic->HasItem(RG_GOLDEN_SCALE))) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_GOLDEN_SCALE)));}), }); - areaTable[RR_LH_FISHING_ISLAND] = Region("LH Fishing Island", SCENE_LAKE_HYLIA, {}, {}, { + areaTable[RR_LH_FISHING_ISLAND] = Region("LH Fishing Island", SCENE_LAKE_HYLIA, {}, { + //Locations + LOCATION(RC_LA_ROCK, true), + }, { //Exits Entrance(RR_LAKE_HYLIA, []{return logic->HasItem(RG_BRONZE_SCALE);}), Entrance(RR_LH_FISHING_POND, []{return logic->CanOpenOverworldDoor(RG_FISHING_HOLE_KEY);}), @@ -117,11 +120,11 @@ void RegionTable_Init_LakeHylia() { //Locations LOCATION(RC_LH_LAB_DIVE, logic->HasItem(RG_GOLDEN_SCALE) || (ctx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE))), LOCATION(RC_LH_TRADE_FROG, logic->IsAdult && logic->CanUse(RG_EYEBALL_FROG)), - LOCATION(RC_LH_GS_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->CanBreakCrates()), + LOCATION(RC_LH_GS_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_ROLL)), LOCATION(RC_LH_LAB_FRONT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)), LOCATION(RC_LH_LAB_LEFT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)), LOCATION(RC_LH_LAB_RIGHT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)), - LOCATION(RC_LH_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->CanBreakCrates()), + LOCATION(RC_LH_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_ROLL)), }, { //Exits Entrance(RR_LAKE_HYLIA, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 0dc30809619..6bcb5595234 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -48,6 +48,7 @@ void RegionTable_Init_LostWoods() { LOCATION(RC_LW_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()), LOCATION(RC_LW_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), LOCATION(RC_LW_SHORTCUT_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)), + LOCATION(RC_LW_BOULDER_BY_GORON_CITY, logic->BlastOrSmash()), LOCATION(RC_LW_GOSSIP_STONE, true), LOCATION(RC_LW_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_2, logic->CanCutShrubs()), @@ -81,6 +82,8 @@ void RegionTable_Init_LostWoods() { LOCATION(RC_LW_GRASS_7, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_8, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_9, logic->CanCutShrubs()), + LOCATION(RC_LW_BOULDER_BY_SACRED_FOREST_MEADOW, logic->BlastOrSmash()), + LOCATION(RC_LW_RUPEE_BOULDER, logic->BlastOrSmash()), }, { //Exits Entrance(RR_LW_FOREST_EXIT, []{return true;}), @@ -92,7 +95,7 @@ void RegionTable_Init_LostWoods() { areaTable[RR_LW_NEAR_SHORTCUTS_GROTTO] = Region("LW Near Shortcuts Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, true), + LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index f6cdecde11e..c95b691d66b 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -23,10 +23,10 @@ void RegionTable_Init_Market() { LOCATION(RC_MARKET_GRASS_6, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_MARKET_GRASS_7, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), LOCATION(RC_MARKET_GRASS_8, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))), - LOCATION(RC_MK_NEAR_BAZAAR_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/), - LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/), - LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/), - LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/), + LOCATION(RC_MK_NEAR_BAZAAR_CRATE_1, logic->IsChild && logic->HasItem(RG_ROLL)), + LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild && logic->HasItem(RG_ROLL)), + LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild && logic->HasItem(RG_ROLL)), + LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild && logic->HasItem(RG_ROLL)), LOCATION(RC_MARKET_TREE, logic->IsChild && logic->CanBonkTrees()), }, { //Exits @@ -56,7 +56,7 @@ void RegionTable_Init_Market() { }, { //Locations LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->Get(LOGIC_BIG_POE_KILL) || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())), - LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild), + LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild && logic->CanBreakCrates()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_3, logic->IsChild && logic->CanBreakPots()), @@ -193,17 +193,17 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Region("Market Treasure Chest Game", SCENE_TREASURE_BOX_SHOP, {}, { //Locations LOCATION(RC_GREG_HINT, logic->HasItem(RG_CHILD_WALLET)), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), - LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), + LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))), }, { //Exits Entrance(RR_THE_MARKET, []{return true;}), @@ -227,7 +227,7 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_DOG_LADY_HOUSE] = Region("Market Dog Lady House", SCENE_DOG_LADY_HOUSE, {}, { //Locations LOCATION(RC_MARKET_LOST_DOG, logic->IsChild && logic->AtNight), - LOCATION(RC_MK_LOST_DOG_HOUSE_CRATE, logic->CanBreakCrates()), + LOCATION(RC_MK_LOST_DOG_HOUSE_CRATE, logic->HasItem(RG_ROLL)), }, { //Exits Entrance(RR_MARKET_BACK_ALLEY, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp index c813a812157..b838e890c5e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp @@ -57,7 +57,7 @@ void RegionTable_Init_SacredForestMeadow() { areaTable[RR_SFM_WOLFOS_GROTTO] = Region("SFM Wolfos Grotto", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 2)), + LOCATION(RC_SFM_WOLFOS_GROTTO_CHEST, logic->CanKillEnemy(RE_WOLFOS, ED_CLOSE, true, 2) && logic->HasItem(RG_OPEN_CHEST)), }, { //Exits Entrance(RR_SFM_ENTRYWAY, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp index b1ad49080c1..e41d0294218 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp @@ -16,7 +16,7 @@ void RegionTable_Init_ZorasDomain() { }, { //Locations LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild), - LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS)), + LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED)), LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->CanUse(RG_PRESCRIPTION)), LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && (logic->HookshotOrBoomerang() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || (logic->CanUse(RG_MAGIC_SINGLE) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (ctx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()), @@ -35,6 +35,14 @@ void RegionTable_Init_ZorasDomain() { LOCATION(RC_ZD_NEAR_SHOP_POT_3, logic->CanBreakPots()), LOCATION(RC_ZD_NEAR_SHOP_POT_4, logic->CanBreakPots()), LOCATION(RC_ZD_NEAR_SHOP_POT_5, logic->CanBreakPots()), + LOCATION(RC_ZD_CIRCLE_ROCK_1, true), + LOCATION(RC_ZD_CIRCLE_ROCK_2, true), + LOCATION(RC_ZD_CIRCLE_ROCK_3, true), + LOCATION(RC_ZD_CIRCLE_ROCK_4, true), + LOCATION(RC_ZD_CIRCLE_ROCK_5, true), + LOCATION(RC_ZD_CIRCLE_ROCK_6, true), + LOCATION(RC_ZD_CIRCLE_ROCK_7, true), + LOCATION(RC_ZD_CIRCLE_ROCK_8, true), }, { //Exits Entrance(RR_ZR_BEHIND_WATERFALL, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index 83ce7061fa9..3b1f7986abf 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -23,6 +23,9 @@ void RegionTable_Init_ZorasFountain() { LOCATION(RC_ZF_NEAR_JABU_POT_3, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_NEAR_JABU_POT_4, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_ZF_BOULDER, logic->BlastOrSmash()), + LOCATION(RC_ZF_SILVER_BOULDER, logic->CanUse(RG_SILVER_GAUNTLETS)), + LOCATION(RC_ZF_UNDERGROUND_BOULDER, logic->CanUse(RG_SILVER_GAUNTLETS) && logic->BlastOrSmash()), LOCATION(RC_ZF_BUSH_1, logic->IsChild), LOCATION(RC_ZF_BUSH_2, logic->IsChild), LOCATION(RC_ZF_BUSH_3, logic->IsChild), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp index 883a3f8a749..9b5c2d28fba 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -7,20 +7,24 @@ void RegionTable_Init_ZoraRiver() { // clang-format off areaTable[RR_ZR_FRONT] = Region("ZR Front", SCENE_ZORAS_RIVER, {}, { //Locations - LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()), - LOCATION(RC_ZR_GRASS_1, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_2, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_3, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_4, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_5, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_6, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_7, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_8, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_9, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_10, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_11, logic->CanCutShrubs()), - LOCATION(RC_ZR_GRASS_12, logic->CanCutShrubs()), - LOCATION(RC_ZR_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()), + LOCATION(RC_ZR_GRASS_1, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_3, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_4, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_5, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_6, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_7, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_8, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_9, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_10, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_11, logic->CanCutShrubs()), + LOCATION(RC_ZR_GRASS_12, logic->CanCutShrubs()), + LOCATION(RC_ZR_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_ZR_BOULDER_1, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_ZR_BOULDER_2, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_ZR_BOULDER_3, logic->IsChild && logic->BlastOrSmash()), + LOCATION(RC_ZR_BOULDER_4, logic->IsChild && logic->BlastOrSmash()), }, { //Exits Entrance(RR_ZORAS_RIVER, []{return logic->IsAdult || logic->BlastOrSmash();}), @@ -54,6 +58,28 @@ void RegionTable_Init_ZoraRiver() { LOCATION(RC_ZR_BENEATH_WATERFALL_MIDDLE_LEFT_RUPEE, logic->IsAdult && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ZR_BENEATH_WATERFALL_MIDDLE_RIGHT_RUPEE, logic->IsAdult && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ZR_BENEATH_WATERFALL_RIGHT_RUPEE, logic->IsAdult && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_BOOMERANG))), + LOCATION(RC_ZR_CIRCLE_ROCK_1, true), + LOCATION(RC_ZR_CIRCLE_ROCK_2, true), + LOCATION(RC_ZR_CIRCLE_ROCK_3, true), + LOCATION(RC_ZR_CIRCLE_ROCK_4, true), + LOCATION(RC_ZR_CIRCLE_ROCK_5, true), + LOCATION(RC_ZR_CIRCLE_ROCK_6, true), + LOCATION(RC_ZR_CIRCLE_ROCK_7, true), + LOCATION(RC_ZR_CIRCLE_ROCK_8, true), + LOCATION(RC_ZR_UPPER_CIRCLE_BOULDER, logic->BlastOrSmash()), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_1, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_2, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_3, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_4, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_5, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_6, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_7, true), + LOCATION(RC_ZR_UPPER_CIRCLE_ROCK_8, true), + LOCATION(RC_ZR_ROCK, true), + LOCATION(RC_ZR_UNDERWATER_ROCK_1, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), + LOCATION(RC_ZR_UNDERWATER_ROCK_2, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), + LOCATION(RC_ZR_UNDERWATER_ROCK_3, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), + LOCATION(RC_ZR_UNDERWATER_ROCK_4, logic->IsAdult || logic->CanUse(RG_BOMBCHU_5)), LOCATION(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, true), LOCATION(RC_ZR_NEAR_FREESTANDING_POH_GRASS, logic->CanUse(RG_BOOMERANG)), }, { @@ -109,7 +135,7 @@ void RegionTable_Init_ZoraRiver() { areaTable[RR_ZR_OPEN_GROTTO] = Region("ZR Open Grotto", SCENE_GROTTOS, grottoEvents, { //Locations - LOCATION(RC_ZR_OPEN_GROTTO_CHEST, true), + LOCATION(RC_ZR_OPEN_GROTTO_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_ZR_OPEN_GROTTO_FISH, logic->HasBottle()), LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()), LOCATION(RC_ZR_OPEN_GROTTO_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index c27918aec1c..bc366367143 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -220,6 +220,8 @@ bool Logic::HasItem(RandomizerGet itemName) { return CurrentUpgrade(UPG_WALLET) >= 2; case RG_TYCOON_WALLET: return CurrentUpgrade(UPG_WALLET) >= 3; + case RG_OPEN_CHEST: + return CheckRandoInf(RAND_INF_CAN_OPEN_CHEST); // Scales case RG_BRONZE_SCALE: return CheckRandoInf(RAND_INF_CAN_SWIM); @@ -227,8 +229,13 @@ bool Logic::HasItem(RandomizerGet itemName) { return CurrentUpgrade(UPG_SCALE) >= 1; case RG_GOLDEN_SCALE: return CurrentUpgrade(UPG_SCALE) >= 2; + + case RG_ROLL: + return CheckRandoInf(RAND_INF_CAN_ROLL); + case RG_CRAWL: return CheckRandoInf(RAND_INF_CAN_CRAWL); + case RG_POCKET_EGG: return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG); case RG_COJIRO: @@ -1283,7 +1290,7 @@ bool Logic::CanBreakPots(EnemyDistance distance, bool wallOrFloor, bool inWater) } bool Logic::CanBreakCrates() { - return true; + return HasItem(RG_ROLL) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_BOMB_BAG) || CanUse(RG_BOMBCHU_5); } bool Logic::CanBreakSmallCrates() { @@ -1291,7 +1298,7 @@ bool Logic::CanBreakSmallCrates() { } bool Logic::CanBonkTrees() { - return true; + return HasItem(RG_ROLL); } bool Logic::HasExplosives() { @@ -1717,6 +1724,11 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_CLAIM_CHECK: SetRandoInf(randoGet - RG_COJIRO + RAND_INF_ADULT_TRADES_HAS_COJIRO, state); break; + case RG_ROLL: + SetRandoInf(RAND_INF_CAN_ROLL, state); + break; + case RG_OPEN_CHEST: + SetRandoInf(RAND_INF_CAN_OPEN_CHEST, state); case RG_CRAWL: SetRandoInf(RAND_INF_CAN_CRAWL, state); break; @@ -2583,6 +2595,16 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_SWIM, true); } + // If we're not shuffling open chest, we start with it + if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST).Is(false)) { + SetRandoInf(RAND_INF_CAN_OPEN_CHEST, true); + } + + // If we're not shuffling roll, we start with it + if (ctx->GetOption(RSK_SHUFFLE_ROLL).Is(false)) { + SetRandoInf(RAND_INF_CAN_ROLL, true); + } + // If we're not shuffling crawl, we start with it if (ctx->GetOption(RSK_SHUFFLE_CRAWL).Is(false)) { SetRandoInf(RAND_INF_CAN_CRAWL, true); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index c200135a58b..d8b5ff0cf91 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -256,6 +256,8 @@ void Settings::CreateOptionDescriptions() { "\n" "If you enter a water entrance without swim you will be respawned on land to prevent infinite death loops.\n" "If you void out in Water Temple you will immediately be kicked out to prevent a softlock."; + mOptionDescriptions[RSK_SHUFFLE_ROLL] = "Shuffles the ability do a roll into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST] = "Shuffles the ability to open chests into the item pool."; mOptionDescriptions[RSK_SHUFFLE_CRAWL] = "Shuffles the ability to use crawlspaces into the item pool."; mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" @@ -509,6 +511,8 @@ void Settings::CreateOptionDescriptions() { "Overworld - Only shuffle grass/bushes that are outside of dungeons.\n" "\n" "All Grass/Bushes - Shuffle all grass/bushes."; + mOptionDescriptions[RSK_SHUFFLE_ROCKS] = "Shuffle rock locations."; + mOptionDescriptions[RSK_SHUFFLE_BOULDERS] = "Shuffle boulder locations."; mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS] = "Shuffles the location of Spiritual Stones and medallions.\n" "Vanilla - Spiritual Stones and medallions will be given from their respective boss.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index c346cd6cb26..359679cb0b7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3431,6 +3431,286 @@ std::map rcToRandomizerInf = { { RC_ZR_TREE, RAND_INF_ZR_TREE }, { RC_KAK_TREE, RAND_INF_KAK_TREE }, { RC_LLR_TREE, RAND_INF_LLR_TREE }, + { RC_KF_CIRCLE_ROCK_1, RAND_INF_KF_CIRCLE_ROCK_1 }, + { RC_KF_CIRCLE_ROCK_2, RAND_INF_KF_CIRCLE_ROCK_2 }, + { RC_KF_CIRCLE_ROCK_3, RAND_INF_KF_CIRCLE_ROCK_3 }, + { RC_KF_CIRCLE_ROCK_4, RAND_INF_KF_CIRCLE_ROCK_4 }, + { RC_KF_CIRCLE_ROCK_5, RAND_INF_KF_CIRCLE_ROCK_5 }, + { RC_KF_CIRCLE_ROCK_6, RAND_INF_KF_CIRCLE_ROCK_6 }, + { RC_KF_CIRCLE_ROCK_7, RAND_INF_KF_CIRCLE_ROCK_7 }, + { RC_KF_CIRCLE_ROCK_8, RAND_INF_KF_CIRCLE_ROCK_8 }, + { RC_KF_ROCK_BY_SARIAS_HOUSE, RAND_INF_KF_ROCK_BY_SARIAS_HOUSE }, + { RC_KF_ROCK_BEHIND_SARIAS_HOUSE, RAND_INF_KF_ROCK_BEHIND_SARIAS_HOUSE }, + { RC_KF_ROCK_BY_MIDOS_HOUSE, RAND_INF_KF_ROCK_BY_MIDOS_HOUSE }, + { RC_KF_ROCK_BY_KNOW_IT_ALLS_HOUSE, RAND_INF_KF_ROCK_BY_KNOW_IT_ALLS_HOUSE }, + { RC_LW_BOULDER_BY_GORON_CITY, RAND_INF_LW_BOULDER_BY_GORON_CITY }, + { RC_LW_BOULDER_BY_SACRED_FOREST_MEADOW, RAND_INF_LW_BOULDER_BY_SACRED_FOREST_MEADOW }, + { RC_LW_RUPEE_BOULDER, RAND_INF_LW_RUPEE_BOULDER }, + { RC_HC_ROCK_1, RAND_INF_HC_ROCK_1 }, + { RC_HC_ROCK_2, RAND_INF_HC_ROCK_2 }, + { RC_HC_ROCK_3, RAND_INF_HC_ROCK_3 }, + { RC_HC_BOULDER, RAND_INF_HC_BOULDER }, + { RC_OGC_BRONZE_BOULDER_1, RAND_INF_OGC_BRONZE_BOULDER_1 }, + { RC_OGC_BRONZE_BOULDER_2, RAND_INF_OGC_BRONZE_BOULDER_2 }, + { RC_OGC_BRONZE_BOULDER_3, RAND_INF_OGC_BRONZE_BOULDER_3 }, + { RC_OGC_SILVER_BOULDER_1, RAND_INF_OGC_SILVER_BOULDER_1 }, + { RC_OGC_SILVER_BOULDER_2, RAND_INF_OGC_SILVER_BOULDER_2 }, + { RC_OGC_SILVER_BOULDER_3, RAND_INF_OGC_SILVER_BOULDER_3 }, + { RC_OGC_SILVER_BOULDER_4, RAND_INF_OGC_SILVER_BOULDER_4 }, + { RC_DMC_CIRCLE_ROCK_1, RAND_INF_DMC_CIRCLE_ROCK_1 }, + { RC_DMC_CIRCLE_ROCK_2, RAND_INF_DMC_CIRCLE_ROCK_2 }, + { RC_DMC_CIRCLE_ROCK_3, RAND_INF_DMC_CIRCLE_ROCK_3 }, + { RC_DMC_CIRCLE_ROCK_4, RAND_INF_DMC_CIRCLE_ROCK_4 }, + { RC_DMC_CIRCLE_ROCK_5, RAND_INF_DMC_CIRCLE_ROCK_5 }, + { RC_DMC_CIRCLE_ROCK_6, RAND_INF_DMC_CIRCLE_ROCK_6 }, + { RC_DMC_CIRCLE_ROCK_7, RAND_INF_DMC_CIRCLE_ROCK_7 }, + { RC_DMC_CIRCLE_ROCK_8, RAND_INF_DMC_CIRCLE_ROCK_8 }, + { RC_DMC_ROCK_BY_FIRE_TEMPLE_1, RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_1 }, + { RC_DMC_ROCK_BY_FIRE_TEMPLE_2, RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_2 }, + { RC_DMC_ROCK_BY_FIRE_TEMPLE_3, RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_3 }, + { RC_DMC_ROCK_BY_FIRE_TEMPLE_4, RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_4 }, + { RC_DMC_ROCK_BY_FIRE_TEMPLE_5, RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_5 }, + { RC_DMC_GOSSIP_ROCK_1, RAND_INF_DMC_GOSSIP_ROCK_1 }, + { RC_DMC_GOSSIP_ROCK_2, RAND_INF_DMC_GOSSIP_ROCK_2 }, + { RC_DMC_BOULDER_1, RAND_INF_DMC_BOULDER_1 }, + { RC_DMC_BOULDER_2, RAND_INF_DMC_BOULDER_2 }, + { RC_DMC_BOULDER_3, RAND_INF_DMC_BOULDER_3 }, + { RC_DMC_BRONZE_BOULDER_1, RAND_INF_DMC_BRONZE_BOULDER_1 }, + { RC_DMC_BRONZE_BOULDER_2, RAND_INF_DMC_BRONZE_BOULDER_2 }, + { RC_DMC_BRONZE_BOULDER_3, RAND_INF_DMC_BRONZE_BOULDER_3 }, + { RC_DMC_BRONZE_BOULDER_4, RAND_INF_DMC_BRONZE_BOULDER_4 }, + { RC_GV_SILVER_BOULDER, RAND_INF_GV_SILVER_BOULDER }, + { RC_GV_ROCK_1, RAND_INF_GV_ROCK_1 }, + { RC_GV_ROCK_2, RAND_INF_GV_ROCK_2 }, + { RC_GV_ROCK_3, RAND_INF_GV_ROCK_3 }, + { RC_GV_UNDERWATER_ROCK_1, RAND_INF_GV_UNDERWATER_ROCK_1 }, + { RC_GV_UNDERWATER_ROCK_2, RAND_INF_GV_UNDERWATER_ROCK_2 }, + { RC_GV_UNDERWATER_ROCK_3, RAND_INF_GV_UNDERWATER_ROCK_3 }, + { RC_GV_ROCK_ACROSS_BRIDGE_1, RAND_INF_GV_ROCK_ACROSS_BRIDGE_1 }, + { RC_GV_ROCK_ACROSS_BRIDGE_2, RAND_INF_GV_ROCK_ACROSS_BRIDGE_2 }, + { RC_GV_ROCK_ACROSS_BRIDGE_3, RAND_INF_GV_ROCK_ACROSS_BRIDGE_3 }, + { RC_GV_ROCK_ACROSS_BRIDGE_4, RAND_INF_GV_ROCK_ACROSS_BRIDGE_4 }, + { RC_GV_BOULDER_1, RAND_INF_GV_BOULDER_1 }, + { RC_GV_BOULDER_2, RAND_INF_GV_BOULDER_2 }, + { RC_GV_BOULDER_ACROSS_BRIDGE, RAND_INF_GV_BOULDER_ACROSS_BRIDGE }, + { RC_GV_BRONZE_BOULDER_1, RAND_INF_GV_BRONZE_BOULDER_1 }, + { RC_GV_BRONZE_BOULDER_2, RAND_INF_GV_BRONZE_BOULDER_2 }, + { RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_1, RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_1 }, + { RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_2, RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_2 }, + { RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_3, RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_3 }, + { RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_4, RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_4 }, + { RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_5, RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_5 }, + { RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_6, RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_6 }, + { RC_HF_SILVER_BOULDER, RAND_INF_HF_SILVER_BOULDER }, + { RC_HF_ROCK_1, RAND_INF_HF_ROCK_1 }, + { RC_HF_ROCK_2, RAND_INF_HF_ROCK_2 }, + { RC_HF_ROCK_3, RAND_INF_HF_ROCK_3 }, + { RC_HF_ROCK_4, RAND_INF_HF_ROCK_4 }, + { RC_HF_ROCK_5, RAND_INF_HF_ROCK_5 }, + { RC_HF_ROCK_6, RAND_INF_HF_ROCK_6 }, + { RC_HF_ROCK_7, RAND_INF_HF_ROCK_7 }, + { RC_HF_ROCK_8, RAND_INF_HF_ROCK_8 }, + { RC_HF_BOULDER_NORTH, RAND_INF_HF_BOULDER_NORTH }, + { RC_HF_BOULDER_BY_MARKET, RAND_INF_HF_BOULDER_BY_MARKET }, + { RC_HF_BOULDER_SOUTH, RAND_INF_HF_BOULDER_SOUTH }, + { RC_HF_BRONZE_BOULDER_1, RAND_INF_HF_BRONZE_BOULDER_1 }, + { RC_HF_BRONZE_BOULDER_2, RAND_INF_HF_BRONZE_BOULDER_2 }, + { RC_HF_BRONZE_BOULDER_3, RAND_INF_HF_BRONZE_BOULDER_3 }, + { RC_HF_BRONZE_BOULDER_4, RAND_INF_HF_BRONZE_BOULDER_4 }, + { RC_KAK_SILVER_BOULDER, RAND_INF_KAK_SILVER_BOULDER }, + { RC_KAK_ROCK_1, RAND_INF_KAK_ROCK_1 }, + { RC_KAK_ROCK_2, RAND_INF_KAK_ROCK_2 }, + { RC_GY_ROCK, RAND_INF_GY_ROCK }, + { RC_LA_ROCK, RAND_INF_LA_ROCK }, + { RC_ZD_CIRCLE_ROCK_1, RAND_INF_ZD_CIRCLE_ROCK_1 }, + { RC_ZD_CIRCLE_ROCK_2, RAND_INF_ZD_CIRCLE_ROCK_2 }, + { RC_ZD_CIRCLE_ROCK_3, RAND_INF_ZD_CIRCLE_ROCK_3 }, + { RC_ZD_CIRCLE_ROCK_4, RAND_INF_ZD_CIRCLE_ROCK_4 }, + { RC_ZD_CIRCLE_ROCK_5, RAND_INF_ZD_CIRCLE_ROCK_5 }, + { RC_ZD_CIRCLE_ROCK_6, RAND_INF_ZD_CIRCLE_ROCK_6 }, + { RC_ZD_CIRCLE_ROCK_7, RAND_INF_ZD_CIRCLE_ROCK_7 }, + { RC_ZD_CIRCLE_ROCK_8, RAND_INF_ZD_CIRCLE_ROCK_8 }, + { RC_ZF_BOULDER, RAND_INF_ZF_BOULDER }, + { RC_ZF_SILVER_BOULDER, RAND_INF_ZF_SILVER_BOULDER }, + { RC_ZF_UNDERGROUND_BOULDER, RAND_INF_ZF_UNDERGROUND_BOULDER }, + { RC_ZR_BOULDER_1, RAND_INF_ZR_BOULDER_1 }, + { RC_ZR_BOULDER_2, RAND_INF_ZR_BOULDER_2 }, + { RC_ZR_BOULDER_3, RAND_INF_ZR_BOULDER_3 }, + { RC_ZR_BOULDER_4, RAND_INF_ZR_BOULDER_4 }, + { RC_ZR_CIRCLE_ROCK_1, RAND_INF_ZR_CIRCLE_ROCK_1 }, + { RC_ZR_CIRCLE_ROCK_2, RAND_INF_ZR_CIRCLE_ROCK_2 }, + { RC_ZR_CIRCLE_ROCK_3, RAND_INF_ZR_CIRCLE_ROCK_3 }, + { RC_ZR_CIRCLE_ROCK_4, RAND_INF_ZR_CIRCLE_ROCK_4 }, + { RC_ZR_CIRCLE_ROCK_5, RAND_INF_ZR_CIRCLE_ROCK_5 }, + { RC_ZR_CIRCLE_ROCK_6, RAND_INF_ZR_CIRCLE_ROCK_6 }, + { RC_ZR_CIRCLE_ROCK_7, RAND_INF_ZR_CIRCLE_ROCK_7 }, + { RC_ZR_CIRCLE_ROCK_8, RAND_INF_ZR_CIRCLE_ROCK_8 }, + { RC_ZR_UPPER_CIRCLE_BOULDER, RAND_INF_ZR_UPPER_CIRCLE_BOULDER }, + { RC_ZR_UPPER_CIRCLE_ROCK_1, RAND_INF_ZR_UPPER_CIRCLE_ROCK_1 }, + { RC_ZR_UPPER_CIRCLE_ROCK_2, RAND_INF_ZR_UPPER_CIRCLE_ROCK_2 }, + { RC_ZR_UPPER_CIRCLE_ROCK_3, RAND_INF_ZR_UPPER_CIRCLE_ROCK_3 }, + { RC_ZR_UPPER_CIRCLE_ROCK_4, RAND_INF_ZR_UPPER_CIRCLE_ROCK_4 }, + { RC_ZR_UPPER_CIRCLE_ROCK_5, RAND_INF_ZR_UPPER_CIRCLE_ROCK_5 }, + { RC_ZR_UPPER_CIRCLE_ROCK_6, RAND_INF_ZR_UPPER_CIRCLE_ROCK_6 }, + { RC_ZR_UPPER_CIRCLE_ROCK_7, RAND_INF_ZR_UPPER_CIRCLE_ROCK_7 }, + { RC_ZR_UPPER_CIRCLE_ROCK_8, RAND_INF_ZR_UPPER_CIRCLE_ROCK_8 }, + { RC_ZR_ROCK, RAND_INF_ZR_ROCK }, + { RC_ZR_UNDERWATER_ROCK_1, RAND_INF_ZR_UNDERWATER_ROCK_1 }, + { RC_ZR_UNDERWATER_ROCK_2, RAND_INF_ZR_UNDERWATER_ROCK_2 }, + { RC_ZR_UNDERWATER_ROCK_3, RAND_INF_ZR_UNDERWATER_ROCK_3 }, + { RC_ZR_UNDERWATER_ROCK_4, RAND_INF_ZR_UNDERWATER_ROCK_4 }, + { RC_DMT_ROCK_1, RAND_INF_DMT_ROCK_1 }, + { RC_DMT_ROCK_2, RAND_INF_DMT_ROCK_2 }, + { RC_DMT_ROCK_3, RAND_INF_DMT_ROCK_3 }, + { RC_DMT_ROCK_4, RAND_INF_DMT_ROCK_4 }, + { RC_DMT_ROCK_5, RAND_INF_DMT_ROCK_5 }, + { RC_DMT_SUMMIT_ROCK, RAND_INF_DMT_SUMMIT_ROCK }, + { RC_DMT_CIRCLE_ROCK_1, RAND_INF_DMT_CIRCLE_ROCK_1 }, + { RC_DMT_CIRCLE_ROCK_2, RAND_INF_DMT_CIRCLE_ROCK_2 }, + { RC_DMT_CIRCLE_ROCK_3, RAND_INF_DMT_CIRCLE_ROCK_3 }, + { RC_DMT_CIRCLE_ROCK_4, RAND_INF_DMT_CIRCLE_ROCK_4 }, + { RC_DMT_CIRCLE_ROCK_5, RAND_INF_DMT_CIRCLE_ROCK_5 }, + { RC_DMT_CIRCLE_ROCK_6, RAND_INF_DMT_CIRCLE_ROCK_6 }, + { RC_DMT_CIRCLE_ROCK_7, RAND_INF_DMT_CIRCLE_ROCK_7 }, + { RC_DMT_CIRCLE_ROCK_8, RAND_INF_DMT_CIRCLE_ROCK_8 }, + { RC_DMT_BOULDER_1, RAND_INF_DMT_BOULDER_1 }, + { RC_DMT_BOULDER_2, RAND_INF_DMT_BOULDER_2 }, + { RC_DMT_BOULDER_3, RAND_INF_DMT_BOULDER_3 }, + { RC_DMT_COW_BOULDER, RAND_INF_DMT_COW_BOULDER }, + { RC_DMT_BRONZE_BOULDER_1, RAND_INF_DMT_BRONZE_BOULDER_1 }, + { RC_DMT_BRONZE_BOULDER_2, RAND_INF_DMT_BRONZE_BOULDER_2 }, + { RC_DMT_BRONZE_BOULDER_3, RAND_INF_DMT_BRONZE_BOULDER_3 }, + { RC_DMT_BRONZE_BOULDER_4, RAND_INF_DMT_BRONZE_BOULDER_4 }, + { RC_DMT_BRONZE_BOULDER_5, RAND_INF_DMT_BRONZE_BOULDER_5 }, + { RC_DMT_BRONZE_BOULDER_6, RAND_INF_DMT_BRONZE_BOULDER_6 }, + { RC_DMT_BRONZE_BOULDER_7, RAND_INF_DMT_BRONZE_BOULDER_7 }, + { RC_DMT_BRONZE_BOULDER_8, RAND_INF_DMT_BRONZE_BOULDER_8 }, + { RC_DMT_BRONZE_BOULDER_9, RAND_INF_DMT_BRONZE_BOULDER_9 }, + { RC_DMT_BRONZE_BOULDER_10, RAND_INF_DMT_BRONZE_BOULDER_10 }, + { RC_DMT_BRONZE_BOULDER_11, RAND_INF_DMT_BRONZE_BOULDER_11 }, + { RC_GC_LW_BOULDER_1, RAND_INF_GC_LW_BOULDER_1 }, + { RC_GC_LW_BOULDER_2, RAND_INF_GC_LW_BOULDER_2 }, + { RC_GC_LW_BOULDER_3, RAND_INF_GC_LW_BOULDER_3 }, + { RC_GC_ENTRANCE_BOULDER_1, RAND_INF_GC_ENTRANCE_BOULDER_1 }, + { RC_GC_ENTRANCE_BOULDER_2, RAND_INF_GC_ENTRANCE_BOULDER_2 }, + { RC_GC_ENTRANCE_BOULDER_3, RAND_INF_GC_ENTRANCE_BOULDER_3 }, + { RC_GC_MAZE_SILVER_BOULDER_1, RAND_INF_GC_MAZE_SILVER_BOULDER_1 }, + { RC_GC_MAZE_SILVER_BOULDER_2, RAND_INF_GC_MAZE_SILVER_BOULDER_2 }, + { RC_GC_MAZE_SILVER_BOULDER_3, RAND_INF_GC_MAZE_SILVER_BOULDER_3 }, + { RC_GC_MAZE_SILVER_BOULDER_4, RAND_INF_GC_MAZE_SILVER_BOULDER_4 }, + { RC_GC_MAZE_SILVER_BOULDER_5, RAND_INF_GC_MAZE_SILVER_BOULDER_5 }, + { RC_GC_MAZE_SILVER_BOULDER_6, RAND_INF_GC_MAZE_SILVER_BOULDER_6 }, + { RC_GC_MAZE_SILVER_BOULDER_7, RAND_INF_GC_MAZE_SILVER_BOULDER_7 }, + { RC_GC_MAZE_SILVER_BOULDER_8, RAND_INF_GC_MAZE_SILVER_BOULDER_8 }, + { RC_GC_MAZE_SILVER_BOULDER_9, RAND_INF_GC_MAZE_SILVER_BOULDER_9 }, + { RC_GC_MAZE_SILVER_BOULDER_10, RAND_INF_GC_MAZE_SILVER_BOULDER_10 }, + { RC_GC_MAZE_SILVER_BOULDER_11, RAND_INF_GC_MAZE_SILVER_BOULDER_11 }, + { RC_GC_MAZE_SILVER_BOULDER_12, RAND_INF_GC_MAZE_SILVER_BOULDER_12 }, + { RC_GC_MAZE_SILVER_BOULDER_13, RAND_INF_GC_MAZE_SILVER_BOULDER_13 }, + { RC_GC_MAZE_SILVER_BOULDER_14, RAND_INF_GC_MAZE_SILVER_BOULDER_14 }, + { RC_GC_MAZE_SILVER_BOULDER_15, RAND_INF_GC_MAZE_SILVER_BOULDER_15 }, + { RC_GC_MAZE_SILVER_BOULDER_16, RAND_INF_GC_MAZE_SILVER_BOULDER_16 }, + { RC_GC_MAZE_SILVER_BOULDER_17, RAND_INF_GC_MAZE_SILVER_BOULDER_17 }, + { RC_GC_MAZE_SILVER_BOULDER_18, RAND_INF_GC_MAZE_SILVER_BOULDER_18 }, + { RC_GC_MAZE_SILVER_BOULDER_19, RAND_INF_GC_MAZE_SILVER_BOULDER_19 }, + { RC_GC_MAZE_SILVER_BOULDER_20, RAND_INF_GC_MAZE_SILVER_BOULDER_20 }, + { RC_GC_MAZE_SILVER_BOULDER_21, RAND_INF_GC_MAZE_SILVER_BOULDER_21 }, + { RC_GC_MAZE_SILVER_BOULDER_22, RAND_INF_GC_MAZE_SILVER_BOULDER_22 }, + { RC_GC_MAZE_SILVER_BOULDER_23, RAND_INF_GC_MAZE_SILVER_BOULDER_23 }, + { RC_GC_MAZE_SILVER_BOULDER_24, RAND_INF_GC_MAZE_SILVER_BOULDER_24 }, + { RC_GC_MAZE_SILVER_BOULDER_25, RAND_INF_GC_MAZE_SILVER_BOULDER_25 }, + { RC_GC_MAZE_SILVER_BOULDER_26, RAND_INF_GC_MAZE_SILVER_BOULDER_26 }, + { RC_GC_MAZE_SILVER_BOULDER_27, RAND_INF_GC_MAZE_SILVER_BOULDER_27 }, + { RC_GC_MAZE_SILVER_BOULDER_28, RAND_INF_GC_MAZE_SILVER_BOULDER_28 }, + { RC_GC_MAZE_SILVER_BOULDER_29, RAND_INF_GC_MAZE_SILVER_BOULDER_29 }, + { RC_GC_MAZE_BOULDER_1, RAND_INF_GC_MAZE_BOULDER_1 }, + { RC_GC_MAZE_BOULDER_2, RAND_INF_GC_MAZE_BOULDER_2 }, + { RC_GC_MAZE_BOULDER_3, RAND_INF_GC_MAZE_BOULDER_3 }, + { RC_GC_MAZE_BOULDER_4, RAND_INF_GC_MAZE_BOULDER_4 }, + { RC_GC_MAZE_BOULDER_5, RAND_INF_GC_MAZE_BOULDER_5 }, + { RC_GC_MAZE_BOULDER_6, RAND_INF_GC_MAZE_BOULDER_6 }, + { RC_GC_MAZE_BOULDER_7, RAND_INF_GC_MAZE_BOULDER_7 }, + { RC_GC_MAZE_BOULDER_8, RAND_INF_GC_MAZE_BOULDER_8 }, + { RC_GC_MAZE_BOULDER_9, RAND_INF_GC_MAZE_BOULDER_9 }, + { RC_GC_MAZE_BOULDER_10, RAND_INF_GC_MAZE_BOULDER_10 }, + { RC_GC_MAZE_BRONZE_BOULDER_1, RAND_INF_GC_MAZE_BRONZE_BOULDER_1 }, + { RC_GC_MAZE_BRONZE_BOULDER_2, RAND_INF_GC_MAZE_BRONZE_BOULDER_2 }, + { RC_GC_MAZE_BRONZE_BOULDER_3, RAND_INF_GC_MAZE_BRONZE_BOULDER_3 }, + { RC_GC_MAZE_BRONZE_BOULDER_4, RAND_INF_GC_MAZE_BRONZE_BOULDER_4 }, + { RC_GC_MAZE_BRONZE_BOULDER_5, RAND_INF_GC_MAZE_BRONZE_BOULDER_5 }, + { RC_GC_MAZE_ROCK, RAND_INF_GC_MAZE_ROCK }, + { RC_COLOSSUS_SILVER_BOULDER, RAND_INF_COLOSSUS_SILVER_BOULDER }, + { RC_COLOSSUS_ROCK, RAND_INF_COLOSSUS_ROCK }, + { RC_COLOSSUS_CIRCLE_1_ROCK_1, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_1 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_2, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_2 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_3, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_3 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_4, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_4 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_5, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_5 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_6, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_6 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_7, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_7 }, + { RC_COLOSSUS_CIRCLE_1_ROCK_8, RAND_INF_COLOSSUS_CIRCLE_1_ROCK_8 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_1, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_1 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_2, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_2 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_3, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_3 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_4, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_4 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_5, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_5 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_6, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_6 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_7, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_7 }, + { RC_COLOSSUS_CIRCLE_2_ROCK_8, RAND_INF_COLOSSUS_CIRCLE_2_ROCK_8 }, + { RC_HC_STORMS_GROTTO_ROCK_1, RAND_INF_HC_STORMS_GROTTO_ROCK_1 }, + { RC_HC_STORMS_GROTTO_ROCK_2, RAND_INF_HC_STORMS_GROTTO_ROCK_2 }, + { RC_HC_STORMS_GROTTO_ROCK_3, RAND_INF_HC_STORMS_GROTTO_ROCK_3 }, + { RC_HC_STORMS_GROTTO_ROCK_4, RAND_INF_HC_STORMS_GROTTO_ROCK_4 }, + { RC_HC_STORMS_GROTTO_ROCK_5, RAND_INF_HC_STORMS_GROTTO_ROCK_5 }, + { RC_HC_STORMS_GROTTO_ROCK_6, RAND_INF_HC_STORMS_GROTTO_ROCK_6 }, + { RC_HC_STORMS_GROTTO_ROCK_7, RAND_INF_HC_STORMS_GROTTO_ROCK_7 }, + { RC_HC_STORMS_GROTTO_ROCK_8, RAND_INF_HC_STORMS_GROTTO_ROCK_8 }, + { RC_BOTW_BOULDER_1, RAND_INF_BOTW_BOULDER_1 }, + { RC_BOTW_BOULDER_2, RAND_INF_BOTW_BOULDER_2 }, + { RC_BOTW_BOULDER_3, RAND_INF_BOTW_BOULDER_3 }, + { RC_BOTW_BOULDER_4, RAND_INF_BOTW_BOULDER_4 }, + { RC_BOTW_BOULDER_5, RAND_INF_BOTW_BOULDER_5 }, + { RC_BOTW_BOULDER_6, RAND_INF_BOTW_BOULDER_6 }, + { RC_DEKU_TREE_MQ_BOULDER_1, RAND_INF_DEKU_TREE_MQ_BOULDER_1 }, + { RC_DEKU_TREE_MQ_BOULDER_2, RAND_INF_DEKU_TREE_MQ_BOULDER_2 }, + { RC_DEKU_TREE_MQ_BOULDER_3, RAND_INF_DEKU_TREE_MQ_BOULDER_3 }, + { RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1, RAND_INF_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1 }, + { RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2, RAND_INF_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2 }, + { RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1, RAND_INF_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1 }, + { RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_2, RAND_INF_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_2 }, + { RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_3, RAND_INF_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_3 }, + { RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_1, RAND_INF_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_1 }, + { RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_2, RAND_INF_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_2 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_4, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_4 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_5, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_5 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_6, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_6 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_7, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_7 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_8, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_8 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_9, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_9 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_10, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_10 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_11, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_11 }, + { RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_12, RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_12 }, + { RC_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER, RAND_INF_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER }, + { RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1, RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1 }, + { RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2, RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2 }, + { RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1, RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1 }, + { RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2, RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2 }, + { RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3, RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3 }, + { RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1, RAND_INF_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1 }, + { RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2, RAND_INF_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2 }, + { RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER, RAND_INF_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER }, + { RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER, RAND_INF_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER }, + { RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_1, RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_1 }, + { RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_2, RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_2 }, + { RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_3, RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_3 }, + { RC_SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER, RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER }, + { RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER, RAND_INF_SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER }, + { RC_BOTW_MQ_BOULDER_1, RAND_INF_BOTW_MQ_BOULDER_1 }, + { RC_BOTW_MQ_BOULDER_2, RAND_INF_BOTW_MQ_BOULDER_2 }, + { RC_BOTW_MQ_BOULDER_3, RAND_INF_BOTW_MQ_BOULDER_3 }, { RC_HF_BUSH_NEAR_LAKE_1, RAND_INF_HF_BUSH_NEAR_LAKE_1 }, { RC_HF_BUSH_NEAR_LAKE_2, RAND_INF_HF_BUSH_NEAR_LAKE_2 }, { RC_HF_BUSH_NEAR_LAKE_3, RAND_INF_HF_BUSH_NEAR_LAKE_3 }, @@ -3520,7 +3800,6 @@ CheckIdentity Randomizer::IdentifyBeehive(s32 sceneNum, s16 xPosition, s32 respa } Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) { - auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity(); RandomizerCheck specialRc = RC_UNKNOWN_CHECK; // TODO: Migrate these special cases into table, or at least document why they are special switch (sceneNum) { @@ -3939,6 +4218,22 @@ CheckIdentity Randomizer::IdentifyTree(s32 sceneNum, s32 posX, s32 posZ) { return treeIdentity; } +RockIdentity Randomizer::IdentifyRock(s32 sceneNum, s32 posX, s32 posZ) { + struct RockIdentity rockIdentity; + + rockIdentity.randomizerInf = RAND_INF_MAX; + rockIdentity.randomizerCheck = RC_UNKNOWN_CHECK; + + Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_ISHI, sceneNum, TWO_ACTOR_PARAMS(posX, posZ)); + + if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) { + rockIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()]; + rockIdentity.randomizerCheck = location->GetRandomizerCheck(); + } + + return rockIdentity; +} + u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get(); } @@ -4945,7 +5240,8 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = { { + const std::array getItemMessages = { { + GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn&wirklich gefunden!", "Félicitation! Vous avez trouvé %gGreg%w!"), GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!", @@ -5290,6 +5586,11 @@ void Randomizer::CreateCustomMessages() { GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!", "Du hast die %rBronzene Schuppe%w&erhalten! Die Fähigkeit zu&Schwimmen ist nun dein!", "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), + GIMESSAGE(RG_ROLL, ITEM_SCALE_SILVER, "You got the %rAbility do a roll%w!", + "Du hast die Fähigkeit, %reinen Wurf&zu machen%w!", + "Vous obtenez la %rCapacité de faire&des roulades%w!"), + GIMESSAGE(RG_OPEN_CHEST, ITEM_KEY_SMALL, "You got the %rAbility to Open Chests%w!", TODO_TRANSLATE, + TODO_TRANSLATE), GIMESSAGE_NO_GERMAN(RG_CRAWL, ITEM_SCALE_SILVER, // TODO_TRANSLATE "You got the %rAbility to Crawl%w!&The power of kneecaps is yours!", "Vous obtenez la %rCapacité à Ramper%w!"), @@ -5457,6 +5758,8 @@ extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem); std::map randomizerGetToRandInf = { { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, + { RG_ROLL, RAND_INF_CAN_ROLL }, + { RG_OPEN_CHEST, RAND_INF_CAN_OPEN_CHEST }, { RG_CRAWL, RAND_INF_CAN_CRAWL }, { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, { RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG }, diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index b745edd3835..403e281fae6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -59,6 +59,7 @@ class Randomizer { CheckIdentity IdentifyCrate(s32 sceneNum, s32 posX, s32 posZ); CheckIdentity IdentifySmallCrate(s32 sceneNum, s32 posX, s32 posZ); CheckIdentity IdentifyTree(s32 sceneNum, s32 posX, s32 posZ); + RockIdentity IdentifyRock(s32 sceneNum, s32 posX, s32 posZ); GetItemEntry GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability = true); GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index c1e4b5af84b..3a526dcddfc 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -466,6 +466,8 @@ typedef enum { RCTYPE_BEAN_FAIRY, // Fairies from Beans RCTYPE_SONG_FAIRY, // Fairies from Songs RCTYPE_GRASS, // Grass + RCTYPE_ROCK, // Rocks + RCTYPE_BOULDER, // Boulders } RandomizerCheckType; typedef enum { RCQUEST_VANILLA, RCQUEST_MQ, RCQUEST_BOTH } RandomizerCheckQuest; @@ -4095,6 +4097,288 @@ typedef enum { RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8, // End Grass + RC_KF_CIRCLE_ROCK_1, + RC_KF_CIRCLE_ROCK_2, + RC_KF_CIRCLE_ROCK_3, + RC_KF_CIRCLE_ROCK_4, + RC_KF_CIRCLE_ROCK_5, + RC_KF_CIRCLE_ROCK_6, + RC_KF_CIRCLE_ROCK_7, + RC_KF_CIRCLE_ROCK_8, + RC_KF_ROCK_BY_SARIAS_HOUSE, + RC_KF_ROCK_BEHIND_SARIAS_HOUSE, + RC_KF_ROCK_BY_MIDOS_HOUSE, + RC_KF_ROCK_BY_KNOW_IT_ALLS_HOUSE, + RC_LW_BOULDER_BY_GORON_CITY, + RC_LW_BOULDER_BY_SACRED_FOREST_MEADOW, + RC_LW_RUPEE_BOULDER, + RC_HC_ROCK_1, + RC_HC_ROCK_2, + RC_HC_ROCK_3, + RC_HC_BOULDER, + RC_OGC_BRONZE_BOULDER_1, + RC_OGC_BRONZE_BOULDER_2, + RC_OGC_BRONZE_BOULDER_3, + RC_OGC_SILVER_BOULDER_1, + RC_OGC_SILVER_BOULDER_2, + RC_OGC_SILVER_BOULDER_3, + RC_OGC_SILVER_BOULDER_4, + RC_DMC_CIRCLE_ROCK_1, + RC_DMC_CIRCLE_ROCK_2, + RC_DMC_CIRCLE_ROCK_3, + RC_DMC_CIRCLE_ROCK_4, + RC_DMC_CIRCLE_ROCK_5, + RC_DMC_CIRCLE_ROCK_6, + RC_DMC_CIRCLE_ROCK_7, + RC_DMC_CIRCLE_ROCK_8, + RC_DMC_ROCK_BY_FIRE_TEMPLE_1, + RC_DMC_ROCK_BY_FIRE_TEMPLE_2, + RC_DMC_ROCK_BY_FIRE_TEMPLE_3, + RC_DMC_ROCK_BY_FIRE_TEMPLE_4, + RC_DMC_ROCK_BY_FIRE_TEMPLE_5, + RC_DMC_GOSSIP_ROCK_1, + RC_DMC_GOSSIP_ROCK_2, + RC_DMC_BOULDER_1, + RC_DMC_BOULDER_2, + RC_DMC_BOULDER_3, + RC_DMC_BRONZE_BOULDER_1, + RC_DMC_BRONZE_BOULDER_2, + RC_DMC_BRONZE_BOULDER_3, + RC_DMC_BRONZE_BOULDER_4, + RC_GV_SILVER_BOULDER, + RC_GV_ROCK_1, + RC_GV_ROCK_2, + RC_GV_ROCK_3, + RC_GV_UNDERWATER_ROCK_1, + RC_GV_UNDERWATER_ROCK_2, + RC_GV_UNDERWATER_ROCK_3, + RC_GV_ROCK_ACROSS_BRIDGE_1, + RC_GV_ROCK_ACROSS_BRIDGE_2, + RC_GV_ROCK_ACROSS_BRIDGE_3, + RC_GV_ROCK_ACROSS_BRIDGE_4, + RC_GV_BOULDER_1, + RC_GV_BOULDER_2, + RC_GV_BOULDER_ACROSS_BRIDGE, + RC_GV_BRONZE_BOULDER_1, + RC_GV_BRONZE_BOULDER_2, + RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_1, + RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_2, + RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_3, + RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_4, + RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_5, + RC_GV_BRONZE_BOULDER_ACROSS_BRIDGE_6, + RC_HF_SILVER_BOULDER, + RC_HF_ROCK_1, + RC_HF_ROCK_2, + RC_HF_ROCK_3, + RC_HF_ROCK_4, + RC_HF_ROCK_5, + RC_HF_ROCK_6, + RC_HF_ROCK_7, + RC_HF_ROCK_8, + RC_HF_BOULDER_NORTH, + RC_HF_BOULDER_BY_MARKET, + RC_HF_BOULDER_SOUTH, + RC_HF_BRONZE_BOULDER_1, + RC_HF_BRONZE_BOULDER_2, + RC_HF_BRONZE_BOULDER_3, + RC_HF_BRONZE_BOULDER_4, + RC_KAK_SILVER_BOULDER, + RC_KAK_ROCK_1, + RC_KAK_ROCK_2, + RC_GY_ROCK, + RC_LA_ROCK, + RC_ZD_CIRCLE_ROCK_1, + RC_ZD_CIRCLE_ROCK_2, + RC_ZD_CIRCLE_ROCK_3, + RC_ZD_CIRCLE_ROCK_4, + RC_ZD_CIRCLE_ROCK_5, + RC_ZD_CIRCLE_ROCK_6, + RC_ZD_CIRCLE_ROCK_7, + RC_ZD_CIRCLE_ROCK_8, + RC_ZF_BOULDER, + RC_ZF_SILVER_BOULDER, + RC_ZF_UNDERGROUND_BOULDER, + RC_ZR_BOULDER_1, + RC_ZR_BOULDER_2, + RC_ZR_BOULDER_3, + RC_ZR_BOULDER_4, + RC_ZR_CIRCLE_ROCK_1, + RC_ZR_CIRCLE_ROCK_2, + RC_ZR_CIRCLE_ROCK_3, + RC_ZR_CIRCLE_ROCK_4, + RC_ZR_CIRCLE_ROCK_5, + RC_ZR_CIRCLE_ROCK_6, + RC_ZR_CIRCLE_ROCK_7, + RC_ZR_CIRCLE_ROCK_8, + RC_ZR_UPPER_CIRCLE_BOULDER, + RC_ZR_UPPER_CIRCLE_ROCK_1, + RC_ZR_UPPER_CIRCLE_ROCK_2, + RC_ZR_UPPER_CIRCLE_ROCK_3, + RC_ZR_UPPER_CIRCLE_ROCK_4, + RC_ZR_UPPER_CIRCLE_ROCK_5, + RC_ZR_UPPER_CIRCLE_ROCK_6, + RC_ZR_UPPER_CIRCLE_ROCK_7, + RC_ZR_UPPER_CIRCLE_ROCK_8, + RC_ZR_ROCK, + RC_ZR_UNDERWATER_ROCK_1, + RC_ZR_UNDERWATER_ROCK_2, + RC_ZR_UNDERWATER_ROCK_3, + RC_ZR_UNDERWATER_ROCK_4, + RC_DMT_ROCK_1, + RC_DMT_ROCK_2, + RC_DMT_ROCK_3, + RC_DMT_ROCK_4, + RC_DMT_ROCK_5, + RC_DMT_SUMMIT_ROCK, + RC_DMT_CIRCLE_ROCK_1, + RC_DMT_CIRCLE_ROCK_2, + RC_DMT_CIRCLE_ROCK_3, + RC_DMT_CIRCLE_ROCK_4, + RC_DMT_CIRCLE_ROCK_5, + RC_DMT_CIRCLE_ROCK_6, + RC_DMT_CIRCLE_ROCK_7, + RC_DMT_CIRCLE_ROCK_8, + RC_DMT_BOULDER_1, + RC_DMT_BOULDER_2, + RC_DMT_BOULDER_3, + RC_DMT_COW_BOULDER, + RC_DMT_BRONZE_BOULDER_1, + RC_DMT_BRONZE_BOULDER_2, + RC_DMT_BRONZE_BOULDER_3, + RC_DMT_BRONZE_BOULDER_4, + RC_DMT_BRONZE_BOULDER_5, + RC_DMT_BRONZE_BOULDER_6, + RC_DMT_BRONZE_BOULDER_7, + RC_DMT_BRONZE_BOULDER_8, + RC_DMT_BRONZE_BOULDER_9, + RC_DMT_BRONZE_BOULDER_10, + RC_DMT_BRONZE_BOULDER_11, + RC_GC_LW_BOULDER_1, + RC_GC_LW_BOULDER_2, + RC_GC_LW_BOULDER_3, + RC_GC_ENTRANCE_BOULDER_1, + RC_GC_ENTRANCE_BOULDER_2, + RC_GC_ENTRANCE_BOULDER_3, + RC_GC_MAZE_SILVER_BOULDER_1, + RC_GC_MAZE_SILVER_BOULDER_2, + RC_GC_MAZE_SILVER_BOULDER_3, + RC_GC_MAZE_SILVER_BOULDER_4, + RC_GC_MAZE_SILVER_BOULDER_5, + RC_GC_MAZE_SILVER_BOULDER_6, + RC_GC_MAZE_SILVER_BOULDER_7, + RC_GC_MAZE_SILVER_BOULDER_8, + RC_GC_MAZE_SILVER_BOULDER_9, + RC_GC_MAZE_SILVER_BOULDER_10, + RC_GC_MAZE_SILVER_BOULDER_11, + RC_GC_MAZE_SILVER_BOULDER_12, + RC_GC_MAZE_SILVER_BOULDER_13, + RC_GC_MAZE_SILVER_BOULDER_14, + RC_GC_MAZE_SILVER_BOULDER_15, + RC_GC_MAZE_SILVER_BOULDER_16, + RC_GC_MAZE_SILVER_BOULDER_17, + RC_GC_MAZE_SILVER_BOULDER_18, + RC_GC_MAZE_SILVER_BOULDER_19, + RC_GC_MAZE_SILVER_BOULDER_20, + RC_GC_MAZE_SILVER_BOULDER_21, + RC_GC_MAZE_SILVER_BOULDER_22, + RC_GC_MAZE_SILVER_BOULDER_23, + RC_GC_MAZE_SILVER_BOULDER_24, + RC_GC_MAZE_SILVER_BOULDER_25, + RC_GC_MAZE_SILVER_BOULDER_26, + RC_GC_MAZE_SILVER_BOULDER_27, + RC_GC_MAZE_SILVER_BOULDER_28, + RC_GC_MAZE_SILVER_BOULDER_29, + RC_GC_MAZE_BOULDER_1, + RC_GC_MAZE_BOULDER_2, + RC_GC_MAZE_BOULDER_3, + RC_GC_MAZE_BOULDER_4, + RC_GC_MAZE_BOULDER_5, + RC_GC_MAZE_BOULDER_6, + RC_GC_MAZE_BOULDER_7, + RC_GC_MAZE_BOULDER_8, + RC_GC_MAZE_BOULDER_9, + RC_GC_MAZE_BOULDER_10, + RC_GC_MAZE_BRONZE_BOULDER_1, + RC_GC_MAZE_BRONZE_BOULDER_2, + RC_GC_MAZE_BRONZE_BOULDER_3, + RC_GC_MAZE_BRONZE_BOULDER_4, + RC_GC_MAZE_BRONZE_BOULDER_5, + RC_GC_MAZE_ROCK, + RC_COLOSSUS_SILVER_BOULDER, + RC_COLOSSUS_ROCK, + RC_COLOSSUS_CIRCLE_1_ROCK_1, + RC_COLOSSUS_CIRCLE_1_ROCK_2, + RC_COLOSSUS_CIRCLE_1_ROCK_3, + RC_COLOSSUS_CIRCLE_1_ROCK_4, + RC_COLOSSUS_CIRCLE_1_ROCK_5, + RC_COLOSSUS_CIRCLE_1_ROCK_6, + RC_COLOSSUS_CIRCLE_1_ROCK_7, + RC_COLOSSUS_CIRCLE_1_ROCK_8, + RC_COLOSSUS_CIRCLE_2_ROCK_1, + RC_COLOSSUS_CIRCLE_2_ROCK_2, + RC_COLOSSUS_CIRCLE_2_ROCK_3, + RC_COLOSSUS_CIRCLE_2_ROCK_4, + RC_COLOSSUS_CIRCLE_2_ROCK_5, + RC_COLOSSUS_CIRCLE_2_ROCK_6, + RC_COLOSSUS_CIRCLE_2_ROCK_7, + RC_COLOSSUS_CIRCLE_2_ROCK_8, + RC_HC_STORMS_GROTTO_ROCK_1, + RC_HC_STORMS_GROTTO_ROCK_2, + RC_HC_STORMS_GROTTO_ROCK_3, + RC_HC_STORMS_GROTTO_ROCK_4, + RC_HC_STORMS_GROTTO_ROCK_5, + RC_HC_STORMS_GROTTO_ROCK_6, + RC_HC_STORMS_GROTTO_ROCK_7, + RC_HC_STORMS_GROTTO_ROCK_8, + RC_BOTW_BOULDER_1, + RC_BOTW_BOULDER_2, + RC_BOTW_BOULDER_3, + RC_BOTW_BOULDER_4, + RC_BOTW_BOULDER_5, + RC_BOTW_BOULDER_6, + RC_DEKU_TREE_MQ_BOULDER_1, + RC_DEKU_TREE_MQ_BOULDER_2, + RC_DEKU_TREE_MQ_BOULDER_3, + RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1, + RC_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2, + RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1, + RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_2, + RC_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_3, + RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_1, + RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_2, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_4, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_5, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_6, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_7, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_8, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_9, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_10, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_11, + RC_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_12, + RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER, + RC_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER, + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1, + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2, + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1, + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2, + RC_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3, + RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1, + RC_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2, + RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER, + RC_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER, + RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_1, + RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_2, + RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_3, + RC_SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER, + RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER, + RC_BOTW_MQ_BOULDER_1, + RC_BOTW_MQ_BOULDER_2, + RC_BOTW_MQ_BOULDER_3, + RC_MAX } RandomizerCheck; @@ -4605,6 +4889,8 @@ typedef enum { RG_HINT, RG_TYCOON_WALLET, RG_BRONZE_SCALE, + RG_ROLL, + RG_OPEN_CHEST, RG_CRAWL, RG_CHILD_WALLET, RG_PROGRESSIVE_BOMBCHU_BAG, @@ -5812,6 +6098,8 @@ typedef enum { RHT_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RHT_BRONZE_SCALE, + RHT_ROLL, + RHT_OPEN_CHEST, RHT_CRAWL, RHT_FISHING_POLE, RHT_SKELETON_KEY, @@ -6284,6 +6572,48 @@ typedef enum { RHT_DODONGOS_CAVERN_GRASS, RHT_BOTTOM_OF_THE_WELL_GRASS, RHT_JABU_JABUS_BELLY_GRASS, + + RHT_KF_ROCK, + RHT_LW_BOULDER, + RHT_HC_ROCK, + RHT_HC_BOULDER, + RHT_OGC_BRONZE_BOULDER, + RHT_OGC_SILVER_BOULDER, + RHT_DMC_ROCK, + RHT_DMC_BOULDER, + RHT_DMC_BRONZE_BOULDER, + RHT_GV_SILVER_BOULDER, + RHT_GV_ROCK, + RHT_GV_BOULDER, + RHT_GV_BRONZE_BOULDER, + RHT_HF_SILVER_BOULDER, + RHT_HF_ROCK, + RHT_HF_BOULDER, + RHT_HF_BRONZE_BOULDER, + RHT_KAK_SILVER_BOULDER, + RHT_KAK_ROCK, + RHT_GY_ROCK, + RHT_LA_ROCK, + RHT_ZD_ROCK, + RHT_ZF_BOULDER, + RHT_ZF_SILVER_BOULDER, + RHT_ZR_BOULDER, + RHT_ZR_ROCK, + RHT_DMT_ROCK, + RHT_DMT_BOULDER, + RHT_DMT_BRONZE_BOULDER, + RHT_GC_BOULDER, + RHT_GC_SILVER_BOULDER, + RHT_GC_BRONZE_BOULDER, + RHT_GC_ROCK, + RHT_COLOSSUS_SILVER_BOULDER, + RHT_COLOSSUS_ROCK, + RHT_HC_STORMS_GROTTO_ROCK, + RHT_BOTW_BOULDER, + RHT_DEKU_BOULDER, + RHT_DODONGOS_BOULDER, + RHT_JABU_BOULDER, + RHT_SPIRIT_TEMPLE_BOULDER, // MAX RHT_MAX, } RandomizerHintTextKey; @@ -6409,6 +6739,8 @@ typedef enum { RSK_SHUFFLE_OCARINA, RSK_SHUFFLE_OCARINA_BUTTONS, RSK_SHUFFLE_SWIM, + RSK_SHUFFLE_ROLL, + RSK_SHUFFLE_OPEN_CHEST, RSK_SHUFFLE_CRAWL, RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, @@ -6609,6 +6941,8 @@ typedef enum { RSK_SHUFFLE_SONG_FAIRIES, RSK_LOCK_OVERWORLD_DOORS, RSK_SHUFFLE_GRASS, + RSK_SHUFFLE_ROCKS, + RSK_SHUFFLE_BOULDERS, RSK_ROCS_FEATHER, RSK_MAX } RandomizerSettingKey; @@ -6975,6 +7309,14 @@ typedef enum { RO_SHUFFLE_CRATES_ALL, } RandoOptionShuffleCrates; +// Shuffle Boulder settings (off, dungeons, overworld, all) +typedef enum { + RO_SHUFFLE_BOULDERS_OFF, + RO_SHUFFLE_BOULDERS_DUNGEONS, + RO_SHUFFLE_BOULDERS_OVERWORLD, + RO_SHUFFLE_BOULDERS_ALL, +} RandoOptionShuffleBoulders; + // Link's Pocket Settings (dungeon reward, advancement, anything, nothing) typedef enum { RO_LINKS_POCKET_DUNGEON_REWARD, @@ -7058,6 +7400,11 @@ typedef struct ShopItemIdentity { int32_t itemPrice; } ShopItemIdentity; +typedef struct RockIdentity { + RandomizerInf randomizerInf; + RandomizerCheck randomizerCheck; +} RockIdentity; + typedef enum { TRACKER_WINDOW_FLOATING, TRACKER_WINDOW_WINDOW, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 9902ae32d63..d0b7f83f317 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -83,6 +83,9 @@ bool showDungeonGrass; bool showOverworldCrates; bool showDungeonCrates; bool showTrees; +bool showRocks; +bool showOverworldBoulders; +bool showDungeonBoulders; bool showBushes; bool showFrogSongRupees; bool showFountainFairies; @@ -1489,7 +1492,28 @@ void LoadSettings() { showDungeonCrates = false; break; } + showTrees = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TREES); + + showRocks = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ROCKS); + switch (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BOULDERS)) { + case RO_SHUFFLE_BOULDERS_ALL: + showOverworldBoulders = true; + showDungeonBoulders = true; + break; + case RO_SHUFFLE_BOULDERS_OVERWORLD: + showOverworldBoulders = true; + showDungeonBoulders = false; + break; + case RO_SHUFFLE_BOULDERS_DUNGEONS: + showOverworldBoulders = false; + showDungeonBoulders = true; + break; + default: + showOverworldBoulders = false; + showDungeonBoulders = false; + break; + } showBushes = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BUSHES); } else { // Vanilla showOverworldTokens = true; @@ -1501,6 +1525,9 @@ void LoadSettings() { showOverworldCrates = false; showDungeonCrates = false; showTrees = false; + showRocks = false; + showOverworldBoulders = false; + showDungeonBoulders = false; showBushes = false; } @@ -1618,6 +1645,10 @@ bool IsCheckShuffled(RandomizerCheck rc) { (loc->GetRCType() != RCTYPE_NLTREE || (showTrees && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) == RO_LOGIC_NO_LOGIC)) && + (loc->GetRCType() != RCTYPE_ROCK || showRocks) && + (loc->GetRCType() != RCTYPE_BOULDER || + (showOverworldBoulders && RandomizerCheckObjects::AreaIsOverworld(loc->GetArea())) || + (showDungeonBoulders && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))) && (loc->GetRCType() != RCTYPE_BUSH || showBushes) && (loc->GetRCType() != RCTYPE_COW || showCows) && (loc->GetRCType() != RCTYPE_FISH || OTRGlobals::Instance->gRandoContext->GetFishsanity()->GetFishLocationIncluded(loc)) && diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index b0eae934278..2cfbeac62cf 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1139,6 +1139,8 @@ DEFINE_RAND_INF(RAND_INF_ZF_BUSH_6) DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH) DEFINE_RAND_INF(RAND_INF_CAN_SWIM) +DEFINE_RAND_INF(RAND_INF_CAN_ROLL) +DEFINE_RAND_INF(RAND_INF_CAN_OPEN_CHEST) DEFINE_RAND_INF(RAND_INF_CAN_CRAWL) DEFINE_RAND_INF(RAND_INF_HAS_WALLET) @@ -2100,6 +2102,288 @@ DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_6) DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_7) DEFINE_RAND_INF(RAND_INF_DEKU_TREE_QUEEN_GOHMA_GRASS_8) // End Grass +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_1) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_2) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_3) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_4) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_5) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_6) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_7) +DEFINE_RAND_INF(RAND_INF_KF_CIRCLE_ROCK_8) +DEFINE_RAND_INF(RAND_INF_KF_ROCK_BY_SARIAS_HOUSE) +DEFINE_RAND_INF(RAND_INF_KF_ROCK_BEHIND_SARIAS_HOUSE) +DEFINE_RAND_INF(RAND_INF_KF_ROCK_BY_MIDOS_HOUSE) +DEFINE_RAND_INF(RAND_INF_KF_ROCK_BY_KNOW_IT_ALLS_HOUSE) +DEFINE_RAND_INF(RAND_INF_LW_BOULDER_BY_GORON_CITY) +DEFINE_RAND_INF(RAND_INF_LW_BOULDER_BY_SACRED_FOREST_MEADOW) +DEFINE_RAND_INF(RAND_INF_LW_RUPEE_BOULDER) +DEFINE_RAND_INF(RAND_INF_HC_ROCK_1) +DEFINE_RAND_INF(RAND_INF_HC_ROCK_2) +DEFINE_RAND_INF(RAND_INF_HC_ROCK_3) +DEFINE_RAND_INF(RAND_INF_HC_BOULDER) +DEFINE_RAND_INF(RAND_INF_OGC_BRONZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_OGC_BRONZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_OGC_BRONZE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_OGC_SILVER_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_OGC_SILVER_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_OGC_SILVER_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_OGC_SILVER_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_1) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_2) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_3) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_4) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_5) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_6) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_7) +DEFINE_RAND_INF(RAND_INF_DMC_CIRCLE_ROCK_8) +DEFINE_RAND_INF(RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_1) +DEFINE_RAND_INF(RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_2) +DEFINE_RAND_INF(RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_3) +DEFINE_RAND_INF(RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_4) +DEFINE_RAND_INF(RAND_INF_DMC_ROCK_BY_FIRE_TEMPLE_5) +DEFINE_RAND_INF(RAND_INF_DMC_GOSSIP_ROCK_1) +DEFINE_RAND_INF(RAND_INF_DMC_GOSSIP_ROCK_2) +DEFINE_RAND_INF(RAND_INF_DMC_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DMC_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DMC_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DMC_BRONZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DMC_BRONZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DMC_BRONZE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DMC_BRONZE_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_GV_SILVER_BOULDER) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_1) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_2) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_3) +DEFINE_RAND_INF(RAND_INF_GV_UNDERWATER_ROCK_1) +DEFINE_RAND_INF(RAND_INF_GV_UNDERWATER_ROCK_2) +DEFINE_RAND_INF(RAND_INF_GV_UNDERWATER_ROCK_3) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_ACROSS_BRIDGE_1) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_ACROSS_BRIDGE_2) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_ACROSS_BRIDGE_3) +DEFINE_RAND_INF(RAND_INF_GV_ROCK_ACROSS_BRIDGE_4) +DEFINE_RAND_INF(RAND_INF_GV_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GV_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GV_BOULDER_ACROSS_BRIDGE) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_1) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_2) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_3) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_4) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_5) +DEFINE_RAND_INF(RAND_INF_GV_BRONZE_BOULDER_ACROSS_BRIDGE_6) +DEFINE_RAND_INF(RAND_INF_HF_SILVER_BOULDER) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_1) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_2) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_3) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_4) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_5) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_6) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_7) +DEFINE_RAND_INF(RAND_INF_HF_ROCK_8) +DEFINE_RAND_INF(RAND_INF_HF_BOULDER_NORTH) +DEFINE_RAND_INF(RAND_INF_HF_BOULDER_BY_MARKET) +DEFINE_RAND_INF(RAND_INF_HF_BOULDER_SOUTH) +DEFINE_RAND_INF(RAND_INF_HF_BRONZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_HF_BRONZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_HF_BRONZE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_HF_BRONZE_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_KAK_SILVER_BOULDER) +DEFINE_RAND_INF(RAND_INF_KAK_ROCK_1) +DEFINE_RAND_INF(RAND_INF_KAK_ROCK_2) +DEFINE_RAND_INF(RAND_INF_GY_ROCK) +DEFINE_RAND_INF(RAND_INF_LA_ROCK) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_1) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_2) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_3) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_4) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_5) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_6) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_7) +DEFINE_RAND_INF(RAND_INF_ZD_CIRCLE_ROCK_8) +DEFINE_RAND_INF(RAND_INF_ZF_BOULDER) +DEFINE_RAND_INF(RAND_INF_ZF_SILVER_BOULDER) +DEFINE_RAND_INF(RAND_INF_ZF_UNDERGROUND_BOULDER) +DEFINE_RAND_INF(RAND_INF_ZR_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_ZR_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_ZR_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_ZR_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_1) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_2) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_3) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_4) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_5) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_6) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_7) +DEFINE_RAND_INF(RAND_INF_ZR_CIRCLE_ROCK_8) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_BOULDER) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_1) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_2) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_3) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_4) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_5) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_6) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_7) +DEFINE_RAND_INF(RAND_INF_ZR_UPPER_CIRCLE_ROCK_8) +DEFINE_RAND_INF(RAND_INF_ZR_ROCK) +DEFINE_RAND_INF(RAND_INF_ZR_UNDERWATER_ROCK_1) +DEFINE_RAND_INF(RAND_INF_ZR_UNDERWATER_ROCK_2) +DEFINE_RAND_INF(RAND_INF_ZR_UNDERWATER_ROCK_3) +DEFINE_RAND_INF(RAND_INF_ZR_UNDERWATER_ROCK_4) +DEFINE_RAND_INF(RAND_INF_DMT_ROCK_1) +DEFINE_RAND_INF(RAND_INF_DMT_ROCK_2) +DEFINE_RAND_INF(RAND_INF_DMT_ROCK_3) +DEFINE_RAND_INF(RAND_INF_DMT_ROCK_4) +DEFINE_RAND_INF(RAND_INF_DMT_ROCK_5) +DEFINE_RAND_INF(RAND_INF_DMT_SUMMIT_ROCK) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_1) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_2) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_3) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_4) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_5) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_6) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_7) +DEFINE_RAND_INF(RAND_INF_DMT_CIRCLE_ROCK_8) +DEFINE_RAND_INF(RAND_INF_DMT_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DMT_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DMT_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DMT_COW_BOULDER) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_5) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_6) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_7) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_8) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_9) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_10) +DEFINE_RAND_INF(RAND_INF_DMT_BRONZE_BOULDER_11) +DEFINE_RAND_INF(RAND_INF_GC_LW_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GC_LW_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GC_LW_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_GC_ENTRANCE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GC_ENTRANCE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GC_ENTRANCE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_5) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_6) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_7) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_8) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_9) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_10) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_11) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_12) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_13) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_14) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_15) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_16) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_17) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_18) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_19) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_20) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_21) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_22) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_23) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_24) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_25) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_26) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_27) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_28) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_SILVER_BOULDER_29) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_5) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_6) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_7) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_8) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_9) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BOULDER_10) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BRONZE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BRONZE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BRONZE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BRONZE_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_BRONZE_BOULDER_5) +DEFINE_RAND_INF(RAND_INF_GC_MAZE_ROCK) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_SILVER_BOULDER) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_ROCK) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_1) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_2) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_3) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_4) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_5) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_6) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_7) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_1_ROCK_8) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_1) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_2) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_3) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_4) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_5) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_6) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_7) +DEFINE_RAND_INF(RAND_INF_COLOSSUS_CIRCLE_2_ROCK_8) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_1) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_2) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_3) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_4) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_5) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_6) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_7) +DEFINE_RAND_INF(RAND_INF_HC_STORMS_GROTTO_ROCK_8) +DEFINE_RAND_INF(RAND_INF_BOTW_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_BOTW_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_BOTW_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_BOTW_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_BOTW_BOULDER_5) +DEFINE_RAND_INF(RAND_INF_BOTW_BOULDER_6) +DEFINE_RAND_INF(RAND_INF_DEKU_TREE_MQ_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DEKU_TREE_MQ_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DEKU_TREE_MQ_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LOBBY_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_RIGHT_SIDE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_4) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_5) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_6) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_7) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_8) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_9) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_10) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_11) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_LIZALFOS_ROOM_BOULDER_12) +DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_TWO_FLAMES_BOULDER) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_ENTRANCE_BOULDER) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_HOLES_ROOM_WALL_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_TAILPASARAN_BOULDER) +DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_MQ_TAILPASARAN_WALL_BOULDER) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_BOULDER_3) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER) +DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER) +DEFINE_RAND_INF(RAND_INF_BOTW_MQ_BOULDER_1) +DEFINE_RAND_INF(RAND_INF_BOTW_MQ_BOULDER_2) +DEFINE_RAND_INF(RAND_INF_BOTW_MQ_BOULDER_3) + DEFINE_RAND_INF(RAND_INF_OBTAINED_RUTOS_LETTER) DEFINE_RAND_INF(RAND_INF_OBTAINED_NAYRUS_LOVE) DEFINE_RAND_INF(RAND_INF_OBTAINED_ROCS_FEATHER) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 7c846ec3290..796c36003bb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -2225,6 +2225,7 @@ void RegisterItemTrackerWidgets() { .ComboMap(extendedDisplayTypes)) .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); ; + SohGui::mSohMenu->AddSearchWidget( { fishingPoleTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); diff --git a/soh/soh/Enhancements/randomizer/roll_animation_data.h b/soh/soh/Enhancements/randomizer/roll_animation_data.h new file mode 100644 index 00000000000..5d0700721c0 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/roll_animation_data.h @@ -0,0 +1,348 @@ +#ifndef ROLL_ANIMATION_DATA_H +#define ROLL_ANIMATION_DATA_H + +#include "z64.h" + +#define ROLL_ANIMATION_FRAMES 20 +#define ROLL_ANIMATION_LIMBS 22 + +static const Vec3s rollAnimationData[ROLL_ANIMATION_FRAMES][ROLL_ANIMATION_LIMBS] = { + { + // Frame 0 + { 74, 3528, -37 }, + { 0, 0, 0 }, + { -16384, -626, -16384 }, + { 0, 0, 0 }, + { 135, 5446, -5887 }, + { 0, 0, 23451 }, + { 2115, 1887, -20292 }, + { 1024, -219, -1846 }, + { 0, 0, 5914 }, + { -443, -1625, -21253 }, + { 16384, 417, 16384 }, + { 476, -93, 19351 }, + { 0, 0, 23344 }, + { 0, 0, 0 }, + { -21137, -12435, -10526 }, + { 0, 0, -6675 }, + { -36, -503, -16171 }, + { 12851, 7298, -17081 }, + { 0, 0, -19713 }, + { 4373, 5305, -15750 }, + { -16384, 27240, -730 }, + { 0, 0, 0 }, + }, + { + // Frame 1 + { 54, 3227, -89 }, + { 2313, 0, 0 }, + { -16384, -685, -16384 }, + { 0, 0, 0 }, + { -152, 5099, -11115 }, + { 0, 0, 24427 }, + { 2059, 1815, -21046 }, + { -59, -710, -6843 }, + { 0, 0, 10860 }, + { -979, -1386, -22412 }, + { 16183, -133, 16490 }, + { 503, -59, 18352 }, + { 0, 0, 25530 }, + { 0, 0, 0 }, + { -20393, -12323, -12080 }, + { 0, 0, -6726 }, + { -25, -562, -16150 }, + { 14095, 8887, -16891 }, + { 0, 0, -18784 }, + { 3073, 5837, -17586 }, + { -15392, 27325, 1213 }, + { 0, 0, 0 }, + }, + { + // Frame 2 + { -25, 2218, -133 }, + { 7607, 0, 0 }, + { -16384, -781, -16384 }, + { 0, 0, 0 }, + { -654, 1069, -20519 }, + { 0, 0, 20760 }, + { 1304, 1666, -23774 }, + { -518, -3910, -15614 }, + { 0, 0, 22754 }, + { -1707, -1918, -22925 }, + { 16384, -4331, 16384 }, + { 641, 74, 13206 }, + { 0, 0, 30948 }, + { 0, 0, 0 }, + { -15708, -11590, -21423 }, + { 0, 0, -6949 }, + { 37, -880, -16032 }, + { -12778, 15014, 15677 }, + { 0, 0, -13974 }, + { -4182, 8702, -27734 }, + { -13006, 28312, 6371 }, + { 0, 0, 0 }, + }, + { + // Frame 3 + { -57, 2670, 558 }, { 13602, 0, 0 }, + { -16384, 0, -16384 }, { 0, 0, 0 }, + { 1852, 198, -7548 }, { 0, 0, 1654 }, + { 1472, 2843, -23780 }, { -2685, -3676, -6545 }, + { 0, 0, 15549 }, { 1676, -2089, -20933 }, + { -1427, -19182, -27019 }, { 698, -257, 10968 }, + { 0, 0, 18514 }, { 0, 0, 0 }, + { 23192, -22237, 548 }, { 0, 0, -6929 }, + { 86, -1131, -15938 }, { -11355, 7097, 10885 }, + { 0, 0, -11056 }, { -10661, 10872, 29098 }, + { -15580, 27296, 800 }, { 0, 0, 0 }, + }, + { + // Frame 4 + { -60, 2207, 382 }, { 20068, 0, 0 }, + { -16384, 2162, -16384 }, { 0, 0, 0 }, + { 219, 581, -17012 }, { 0, 0, 16199 }, + { 1446, 2552, -20834 }, { -1193, -3974, -12795 }, + { 0, 0, 22901 }, { 1355, -1424, -20722 }, + { -24738, -12007, -7558 }, { 462, -469, 19859 }, + { 0, 0, 17568 }, { 0, 0, 0 }, + { -1152, -8811, 22716 }, { 0, 0, -5124 }, + { 43, -913, -16019 }, { -2615, 21391, 18299 }, + { 0, 0, -20972 }, { -7167, 7353, -29571 }, + { -16740, 27249, -1447 }, { 0, 0, 0 }, + }, + { + // Frame 5 + { -60, 1477, 314 }, { 26774, 0, 0 }, + { -16384, 4992, -16384 }, { 0, 0, 0 }, + { 1331, 909, -8175 }, { 0, 0, 8190 }, + { 538, 2622, -21124 }, { -443, -603, -1212 }, + { 0, 0, 24711 }, { 491, -584, -20713 }, + { -21267, -11295, -7882 }, { 552, 479, 16219 }, + { 0, 0, 17341 }, { 0, 0, 0 }, + { 2866, -7762, 19771 }, { 0, 0, -3812 }, + { -416, 862, -16656 }, { -2940, 16895, 20702 }, + { 0, 0, -18661 }, { -5100, 10643, -25824 }, + { -15495, 27304, 1032 }, { 0, 0, 0 }, + }, + { + // Frame 6 + { -60, 771, 241 }, { -32044, 0, 0 }, { -16384, 7684, -16384 }, { 0, 0, 0 }, + { -27, 459, -14461 }, { 0, 0, 13541 }, { 63, 2434, -21507 }, { 140, -3557, -8362 }, + { 0, 0, 25043 }, { -525, 149, -20932 }, { -18194, -11230, -7652 }, { 519, 2089, 15610 }, + { 0, 0, 17631 }, { 0, 0, 0 }, { 3504, -7332, 22086 }, { 0, 0, -4207 }, + { -1489, 5198, -18222 }, { 967, 12936, 27541 }, { 0, 0, -17131 }, { -2949, 6188, -22075 }, + { -16864, 27258, -1679 }, { 0, 0, 0 }, + }, + { + // Frame 7 + { -60, 511, -4 }, { -25546, 0, 0 }, + { -16384, 8878, -16384 }, { 0, 0, 0 }, + { -799, 63, -16740 }, { 0, 0, 14954 }, + { 943, 1296, -21262 }, { 1564, -3136, -16443 }, + { 0, 0, 25526 }, { -1303, 490, -21402 }, + { -18554, -11994, -7123 }, { 464, 3612, 15275 }, + { 0, 0, 18235 }, { 0, 0, 0 }, + { 3231, -6977, 25545 }, { 0, 0, -4847 }, + { -321, 5196, -18440 }, { 2710, 9642, 31101 }, + { 0, 0, -15600 }, { -985, 4840, -20355 }, + { -16899, 27261, -1747 }, { 0, 0, 0 }, + }, + { + // Frame 8 + { -60, 771, -444 }, { -19497, 0, 0 }, + { -16384, 6684, -16384 }, { 0, 0, 0 }, + { -2556, 1051, -17674 }, { 0, 0, 27472 }, + { 1977, 423, -21477 }, { 1754, -2055, -18579 }, + { 0, 0, 25919 }, { -1681, 96, -22354 }, + { -20790, -12983, -5802 }, { 376, 4598, 14848 }, + { 0, 0, 18950 }, { 0, 0, 0 }, + { 3130, -6330, 27866 }, { 0, 0, -5576 }, + { 2725, 2012, -17715 }, { 4493, 6440, -31020 }, + { 0, 0, -14167 }, { 1055, 3881, -18845 }, + { -16739, 27250, -1432 }, { 0, 0, 0 }, + }, + { + // Frame 9 + { -59, 940, -590 }, { -16713, 0, 0 }, + { -16384, 5073, -16384 }, { 0, 0, 0 }, + { -2448, 996, -16808 }, { 0, 0, 26712 }, + { 2021, 695, -22206 }, { 1957, -1988, -18219 }, + { 0, 0, 26656 }, { -1789, -334, -23017 }, + { -22257, -13213, -4844 }, { 333, 4517, 14584 }, + { 0, 0, 19285 }, { 0, 0, 0 }, + { 2948, -5849, 28856 }, { 0, 0, -5925 }, + { 4383, 81, -17239 }, { 5329, 5036, -29493 }, + { 0, 0, -13518 }, { 1992, 3521, -18202 }, + { -16629, 27244, -1214 }, { 0, 0, 0 }, + }, + { + // Frame 10 + { -59, 1348, -649 }, { -11768, 0, 0 }, + { -16384, 1883, -16384 }, { 0, 0, 0 }, + { -2196, 778, -10577 }, { 0, 0, 28012 }, + { 1653, 2033, -24440 }, { 2855, -2524, -11436 }, + { 0, 0, 27911 }, { -1938, -1318, -24470 }, + { -25057, -12419, -3692 }, { 177, 3296, 14007 }, + { 0, 0, 19787 }, { 0, 0, 0 }, + { 2482, -4950, 30438 }, { 0, 0, -6494 }, + { 6915, -3159, -16394 }, { 6751, 2940, -27054 }, + { 0, 0, -12420 }, { 3479, 2992, -17208 }, + { -16434, 27240, -830 }, { 0, 0, 0 }, + }, + { + // Frame 11 + { -58, 1735, -542 }, { -7750, 0, 0 }, + { -16384, 184, -16384 }, { 0, 0, 0 }, + { -1205, 108, -8043 }, { 0, 0, 25981 }, + { 1346, 2790, -26757 }, { 2029, -1692, -8455 }, + { 0, 0, 25863 }, { -1961, -2047, -25988 }, + { -28048, -11954, -2090 }, { -470, 3031, 12591 }, + { 0, 0, 19948 }, { 0, 0, 0 }, + { 2309, -4596, 31084 }, { 0, 0, -6786 }, + { 7219, -4155, -16045 }, { 7656, 2711, -26079 }, + { 0, 0, -11861 }, { 4229, 2661, -16666 }, + { -16363, 27240, -688 }, { 0, 0, 0 }, + }, + { + // Frame 12 + { 74, 3528, -37 }, + { 0, 0, 0 }, + { -16384, -626, -16384 }, + { 0, 0, 0 }, + { 135, 5446, -5887 }, + { 0, 0, 23451 }, + { 2115, 1887, -20292 }, + { 1024, -219, -1846 }, + { 0, 0, 5914 }, + { -443, -1625, -21253 }, + { 16384, 417, 16384 }, + { 476, -93, 19351 }, + { 0, 0, 23344 }, + { 0, 0, 0 }, + { -21137, -12435, -10526 }, + { 0, 0, -6675 }, + { -36, -503, -16171 }, + { 12851, 7298, -17081 }, + { 0, 0, -19713 }, + { 4373, 5305, -15750 }, + { -16384, 27240, -730 }, + { 0, 0, 0 }, + }, + { + // Frame 13 + { 54, 3227, -89 }, + { 2313, 0, 0 }, + { -16384, -685, -16384 }, + { 0, 0, 0 }, + { -152, 5099, -11115 }, + { 0, 0, 24427 }, + { 2059, 1815, -21046 }, + { -59, -710, -6843 }, + { 0, 0, 10860 }, + { -979, -1386, -22412 }, + { 16183, -133, 16490 }, + { 503, -59, 18352 }, + { 0, 0, 25530 }, + { 0, 0, 0 }, + { -20393, -12323, -12080 }, + { 0, 0, -6726 }, + { -25, -562, -16150 }, + { 14095, 8887, -16891 }, + { 0, 0, -18784 }, + { 3073, 5837, -17586 }, + { -15392, 27325, 1213 }, + { 0, 0, 0 }, + }, + { + // Frame 14 + { -25, 2218, -133 }, + { 7607, 0, 0 }, + { -16384, -781, -16384 }, + { 0, 0, 0 }, + { -654, 1069, -20519 }, + { 0, 0, 20760 }, + { 1304, 1666, -23774 }, + { -518, -3910, -15614 }, + { 0, 0, 22754 }, + { -1707, -1918, -22925 }, + { 16384, -4331, 16384 }, + { 641, 74, 13206 }, + { 0, 0, 30948 }, + { 0, 0, 0 }, + { -15708, -11590, -21423 }, + { 0, 0, -6949 }, + { 37, -880, -16032 }, + { -12778, 15014, 15677 }, + { 0, 0, -13974 }, + { -4182, 8702, -27734 }, + { -13006, 28312, 6371 }, + { 0, 0, 0 }, + }, + { + // Frame 15 + { -57, 2670, 558 }, { 13602, 0, 0 }, + { -16384, 0, -16384 }, { 0, 0, 0 }, + { 1852, 198, -7548 }, { 0, 0, 1654 }, + { 1472, 2843, -23780 }, { -2685, -3676, -6545 }, + { 0, 0, 15549 }, { 1676, -2089, -20933 }, + { -1427, -19182, -27019 }, { 698, -257, 10968 }, + { 0, 0, 18514 }, { 0, 0, 0 }, + { 23192, -22237, 548 }, { 0, 0, -6929 }, + { 86, -1131, -15938 }, { -11355, 7097, 10885 }, + { 0, 0, -11056 }, { -10661, 10872, 29098 }, + { -15580, 27296, 800 }, { 0, 0, 0 }, + }, + { + // Frame 16 + { -60, 2207, 382 }, { 20068, 0, 0 }, + { -16384, 2162, -16384 }, { 0, 0, 0 }, + { 219, 581, -17012 }, { 0, 0, 16199 }, + { 1446, 2552, -20834 }, { -1193, -3974, -12795 }, + { 0, 0, 22901 }, { 1355, -1424, -20722 }, + { -24738, -12007, -7558 }, { 462, -469, 19859 }, + { 0, 0, 17568 }, { 0, 0, 0 }, + { -1152, -8811, 22716 }, { 0, 0, -5124 }, + { 43, -913, -16019 }, { -2615, 21391, 18299 }, + { 0, 0, -20972 }, { -7167, 7353, -29571 }, + { -16740, 27249, -1447 }, { 0, 0, 0 }, + }, + { + // Frame 17 + { -60, 1477, 314 }, { 26774, 0, 0 }, + { -16384, 4992, -16384 }, { 0, 0, 0 }, + { 1331, 909, -8175 }, { 0, 0, 8190 }, + { 538, 2622, -21124 }, { -443, -603, -1212 }, + { 0, 0, 24711 }, { 491, -584, -20713 }, + { -21267, -11295, -7882 }, { 552, 479, 16219 }, + { 0, 0, 17341 }, { 0, 0, 0 }, + { 2866, -7762, 19771 }, { 0, 0, -3812 }, + { -416, 862, -16656 }, { -2940, 16895, 20702 }, + { 0, 0, -18661 }, { -5100, 10643, -25824 }, + { -15495, 27304, 1032 }, { 0, 0, 0 }, + }, + { + // Frame 18 + { -60, 771, 241 }, { -32044, 0, 0 }, { -16384, 7684, -16384 }, { 0, 0, 0 }, + { -27, 459, -14461 }, { 0, 0, 13541 }, { 63, 2434, -21507 }, { 140, -3557, -8362 }, + { 0, 0, 25043 }, { -525, 149, -20932 }, { -18194, -11230, -7652 }, { 519, 2089, 15610 }, + { 0, 0, 17631 }, { 0, 0, 0 }, { 3504, -7332, 22086 }, { 0, 0, -4207 }, + { -1489, 5198, -18222 }, { 967, 12936, 27541 }, { 0, 0, -17131 }, { -2949, 6188, -22075 }, + { -16864, 27258, -1679 }, { 0, 0, 0 }, + }, + { + // Frame 19 + { -60, 511, -4 }, { -25546, 0, 0 }, + { -16384, 8878, -16384 }, { 0, 0, 0 }, + { -799, 63, -16740 }, { 0, 0, 14954 }, + { 943, 1296, -21262 }, { 1564, -3136, -16443 }, + { 0, 0, 25526 }, { -1303, 490, -21402 }, + { -18554, -11994, -7123 }, { 464, 3612, 15275 }, + { 0, 0, 18235 }, { 0, 0, 0 }, + { 3231, -6977, 25545 }, { 0, 0, -4847 }, + { -321, 5196, -18440 }, { 2710, 9642, 31101 }, + { 0, 0, -15600 }, { -985, 4840, -20355 }, + { -16899, 27261, -1747 }, { 0, 0, 0 }, + }, +}; + +#endif // ROLL_ANIMATION_DATA_H \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index dc35afdfa1b..992ab921653 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -313,175 +313,184 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_SWIM); } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CRAWL) == RO_GENERIC_OFF) { - Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL); + if (Randomizer_GetSettingValue(RSK_SHUFFLE_ROLL) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_ROLL); } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_WALLET) == RO_GENERIC_OFF) { - Flags_SetRandomizerInf(RAND_INF_HAS_WALLET); - } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OPEN_CHEST) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CRAWL) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL); + } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_FISHING_POLE) == RO_GENERIC_OFF) { - Flags_SetRandomizerInf(RAND_INF_FISHING_POLE_FOUND); - } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_WALLET) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_HAS_WALLET); + } - // Give Link's pocket item - GiveLinksPocketItem(); + if (Randomizer_GetSettingValue(RSK_SHUFFLE_FISHING_POLE) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_FISHING_POLE_FOUND); + } - // Remove One Time Scrubs with Scrubsanity off - if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_OFF) { - Flags_SetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE); - Flags_SetInfTable(INFTABLE_BOUGHT_STICK_UPGRADE); - Flags_SetInfTable(INFTABLE_BOUGHT_NUT_UPGRADE); - } + // Give Link's pocket item + GiveLinksPocketItem(); - int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get(); - gSaveContext.savedSceneNum = -1; - switch (startingAge) { - case RO_AGE_ADULT: // Adult - gSaveContext.linkAge = LINK_AGE_ADULT; - gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_WARP_PAD; - gSaveContext.cutsceneIndex = 0; - break; - case RO_AGE_CHILD: // Child - gSaveContext.linkAge = LINK_AGE_CHILD; - break; - default: - break; - } + // Remove One Time Scrubs with Scrubsanity off + if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_OFF) { + Flags_SetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE); + Flags_SetInfTable(INFTABLE_BOUGHT_STICK_UPGRADE); + Flags_SetInfTable(INFTABLE_BOUGHT_NUT_UPGRADE); + } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS)) { - // Override the spawn entrance so entrance rando can take control, - // and to prevent remember save location from breaking initial spawn. - gSaveContext.entranceIndex = -1; - } + int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get(); + gSaveContext.savedSceneNum = -1; + switch (startingAge) { + case RO_AGE_ADULT: // Adult + gSaveContext.linkAge = LINK_AGE_ADULT; + gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_WARP_PAD; + gSaveContext.cutsceneIndex = 0; + break; + case RO_AGE_CHILD: // Child + gSaveContext.linkAge = LINK_AGE_CHILD; + break; + default: + break; + } - 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); + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS)) { + // Override the spawn entrance so entrance rando can take control, + // and to prevent remember save location from breaking initial spawn. + gSaveContext.entranceIndex = -1; } - } - if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, (GetItemID)RG_ZELDAS_LULLABY); - StartingItemGive(getItemEntry, RC_SONG_FROM_IMPA); - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_MALON_EGG, (GetItemID)RG_WEIRD_EGG); - StartingItemGive(getItemEntry, RC_HC_ZELDAS_LETTER); - getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_ZELDAS_LETTER, (GetItemID)RG_ZELDAS_LETTER); - StartingItemGive(getItemEntry, RC_HC_MALON_EGG); - - // Malon/Talon back at ranch. - Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); - Flags_SetRandomizerInf(RAND_INF_WEIRD_EGG); - Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE); - Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE); - - // Set "Got Zelda's Letter" flag. Also ensures Saria is back at SFM. - Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER); - Flags_SetRandomizerInf(RAND_INF_ZELDAS_LETTER); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_LETTER_ZELDA); - - // Got item from Impa. - Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); - - gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x4); // Move milk crates in Hyrule Castle to moat. - - // Set this at the end to ensure we always start with the letter. - // This is for the off chance, we got the Weird Egg from Impa (which should never happen). - INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA; - } + 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); + } + } - if (Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && startingAge == RO_AGE_ADULT) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_MASTER_SWORD, GI_NONE); - StartingItemGive(getItemEntry, RC_TOT_MASTER_SWORD); - Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD); - } + if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { + GetItemEntry getItemEntry = + Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, (GetItemID)RG_ZELDAS_LULLABY); + StartingItemGive(getItemEntry, RC_SONG_FROM_IMPA); + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_MALON_EGG, (GetItemID)RG_WEIRD_EGG); + StartingItemGive(getItemEntry, RC_HC_ZELDAS_LETTER); + getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_ZELDAS_LETTER, (GetItemID)RG_ZELDAS_LETTER); + StartingItemGive(getItemEntry, RC_HC_MALON_EGG); + + // Malon/Talon back at ranch. + Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); + Flags_SetRandomizerInf(RAND_INF_WEIRD_EGG); + Flags_SetEventChkInf(EVENTCHKINF_TALON_WOKEN_IN_CASTLE); + Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE); + + // Set "Got Zelda's Letter" flag. Also ensures Saria is back at SFM. + Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER); + Flags_SetRandomizerInf(RAND_INF_ZELDAS_LETTER); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_LETTER_ZELDA); + + // Got item from Impa. + Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY); + + gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= + (1 << 0x4); // Move milk crates in Hyrule Castle to moat. + + // Set this at the end to ensure we always start with the letter. + // This is for the off chance, we got the Weird Egg from Impa (which should never happen). + INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA; + } - HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); + if (Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && startingAge == RO_AGE_ADULT) { + GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_MASTER_SWORD, GI_NONE); + StartingItemGive(getItemEntry, RC_TOT_MASTER_SWORD); + Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD); + } - if (Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) { - Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED); - } + HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); - // Open lowest Vanilla Fire Temple locked door (to prevent key logic lockouts). - // Not done on Keysanity since this lockout is a non-issue when Fire Keys can be found outside the temple. - u8 keysanity = Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE || - Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD || - Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON; - if (!ResourceMgr_IsSceneMasterQuest(SCENE_FIRE_TEMPLE) && !keysanity) { - gSaveContext.sceneFlags[SCENE_FIRE_TEMPLE].swch |= (1 << 0x17); - } + if (Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) { + Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED); + } - // Opens locked Water Temple door in vanilla to prevent softlocks. - // West door on the middle level that leads to the water raising thing. - // Happens in 3DS rando and N64 rando as well. - if (!ResourceMgr_IsSceneMasterQuest(SCENE_WATER_TEMPLE)) { - gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); - } + // Open lowest Vanilla Fire Temple locked door (to prevent key logic lockouts). + // Not done on Keysanity since this lockout is a non-issue when Fire Keys can be found outside the temple. + u8 keysanity = Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE || + Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD || + Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON; + if (!ResourceMgr_IsSceneMasterQuest(SCENE_FIRE_TEMPLE) && !keysanity) { + gSaveContext.sceneFlags[SCENE_FIRE_TEMPLE].swch |= (1 << 0x17); + } - int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); - switch (doorOfTime) { - case RO_DOOROFTIME_OPEN: - Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME); - break; - } + // Opens locked Water Temple door in vanilla to prevent softlocks. + // West door on the middle level that leads to the water raising thing. + // Happens in 3DS rando and N64 rando as well. + if (!ResourceMgr_IsSceneMasterQuest(SCENE_WATER_TEMPLE)) { + gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); + } - if (Randomizer_GetSettingValue(RSK_KAK_GATE) == RO_KAK_GATE_OPEN) { - Flags_SetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); - Flags_UnsetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_LETTER_ZELDA); - } + int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); + switch (doorOfTime) { + case RO_DOOROFTIME_OPEN: + Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME); + break; + } - if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FAST || - Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FREE) { - Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(1)); - Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(2)); - Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(3)); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x02); // heard yells and unlocked doors - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x03); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x04); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x06); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x07); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x08); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x10); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x12); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x13); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0A); // picked up keys - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0E); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0F); - } + if (Randomizer_GetSettingValue(RSK_KAK_GATE) == RO_KAK_GATE_OPEN) { + Flags_SetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); + Flags_UnsetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_LETTER_ZELDA); + } + + if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FAST || + Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FREE) { + Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(1)); + Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(2)); + Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(3)); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x02); // heard yells and unlocked doors + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x03); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x04); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x06); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x07); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x08); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x10); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x12); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x13); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0A); // picked up keys + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0E); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0F); + } - if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FREE) { - Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(0)); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x01); // heard yell and unlocked door - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x05); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x11); - gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0C); // picked up key + if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FREE) { + Flags_SetEventChkInf(EVENTCHKINF_CARPENTERS_FREE(0)); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x01); // heard yell and unlocked door + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x05); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].swch |= (1 << 0x11); + gSaveContext.sceneFlags[SCENE_THIEVES_HIDEOUT].collect |= (1 << 0x0C); // picked up key - if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { - Item_Give(NULL, ITEM_GERUDO_CARD); + if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { + Item_Give(NULL, ITEM_GERUDO_CARD); + } } - } - // complete mask quest - if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) { - Flags_SetInfTable(INFTABLE_GATE_GUARD_PUT_ON_KEATON_MASK); - Flags_SetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE); - - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_KEATON); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_SKULL); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_SPOOKY); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_GORON); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_ZORA); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_GERUDO); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH); - - gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask - gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask - gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask - gSaveContext.itemGetInf[3] |= 0x800; // Bunny Hood related - gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth + // complete mask quest + if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) { + Flags_SetInfTable(INFTABLE_GATE_GUARD_PUT_ON_KEATON_MASK); + Flags_SetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE); + + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_KEATON); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_SKULL); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_SPOOKY); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_GORON); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_ZORA); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_GERUDO); + Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH); + + gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask + gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask + gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask + gSaveContext.itemGetInf[3] |= 0x800; // Bunny Hood related + gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth + } } -} +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 8652bb5ef89..8a70731ad9f 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -778,6 +778,8 @@ void Settings::CreateOptions() { }); OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]); OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]); + OPT_BOOL(RSK_SHUFFLE_ROLL, "Shuffle Roll", CVAR_RANDOMIZER_SETTING("ShuffleRoll"), mOptionDescriptions[RSK_SHUFFLE_ROLL]); + OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]); OPT_BOOL(RSK_SHUFFLE_CRAWL, "Shuffle Crawl", CVAR_RANDOMIZER_SETTING("ShuffleCrawl"), mOptionDescriptions[RSK_SHUFFLE_CRAWL]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); @@ -785,6 +787,8 @@ void Settings::CreateOptions() { OPT_U8(RSK_SHUFFLE_GRASS, "Shuffle Grass", {"Off", "Dungeons", "Overworld", "All Grass/Bushes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGrass"), mOptionDescriptions[RSK_SHUFFLE_GRASS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_GRASS_OFF); OPT_U8(RSK_SHUFFLE_CRATES, "Shuffle Crates", {"Off", "Dungeons", "Overworld", "All Crates"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleCrates"), mOptionDescriptions[RSK_SHUFFLE_CRATES], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_CRATES_OFF); OPT_BOOL(RSK_SHUFFLE_TREES, "Shuffle Trees", CVAR_RANDOMIZER_SETTING("ShuffleTrees"), mOptionDescriptions[RSK_SHUFFLE_TREES]); + OPT_BOOL(RSK_SHUFFLE_ROCKS, "Shuffle Rocks", CVAR_RANDOMIZER_SETTING("ShuffleRocks"), mOptionDescriptions[RSK_SHUFFLE_ROCKS]); + OPT_U8(RSK_SHUFFLE_BOULDERS, "Shuffle Boulders", {"Off", "Dungeons", "Overworld", "All Boulders"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBoulders"), mOptionDescriptions[RSK_SHUFFLE_BOULDERS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_BOULDERS_OFF); OPT_BOOL(RSK_SHUFFLE_BUSHES, "Shuffle Bushes", CVAR_RANDOMIZER_SETTING("ShuffleBushes"), mOptionDescriptions[RSK_SHUFFLE_BUSHES]); OPT_BOOL(RSK_SHUFFLE_FISHING_POLE, "Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]); OPT_CALLBACK(RSK_SHUFFLE_FISHING_POLE, { @@ -2322,6 +2326,8 @@ void Settings::CreateOptions() { &mOptions[RSK_FISHSANITY_AGE_SPLIT], &mOptions[RSK_SHUFFLE_FREESTANDING], &mOptions[RSK_SHUFFLE_BEEHIVES], + &mOptions[RSK_SHUFFLE_ROCKS], + &mOptions[RSK_SHUFFLE_BOULDERS], &mOptions[RSK_SHUFFLE_COWS], &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_GRASS], @@ -2365,6 +2371,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT], &mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT], &mOptions[RSK_SCRUBS_PRICES_AFFORDABLE], + &mOptions[RSK_SHUFFLE_MERCHANTS], &mOptions[RSK_MERCHANT_PRICES], &mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE], @@ -2389,6 +2396,8 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_OPEN_CHEST], + &mOptions[RSK_SHUFFLE_ROLL], &mOptions[RSK_SHUFFLE_CRAWL], &mOptions[RSK_SHUFFLE_BEAN_SOULS], &mOptions[RSK_ROCS_FEATHER], @@ -2603,10 +2612,14 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_CRATES], &mOptions[RSK_SHUFFLE_TREES], &mOptions[RSK_SHUFFLE_BUSHES], + &mOptions[RSK_SHUFFLE_ROCKS], + &mOptions[RSK_SHUFFLE_BOULDERS], &mOptions[RSK_SHUFFLE_KOKIRI_SWORD], &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], &mOptions[RSK_SHUFFLE_SWIM], + &mOptions[RSK_SHUFFLE_ROLL], + &mOptions[RSK_SHUFFLE_OPEN_CHEST], &mOptions[RSK_SHUFFLE_CRAWL], &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h index 0b837179ba2..a0b084e6caf 100644 --- a/soh/soh/Enhancements/randomizer/static_data.h +++ b/soh/soh/Enhancements/randomizer/static_data.h @@ -62,6 +62,7 @@ class StaticData { static void RegisterGrassLocations(); static void RegisterCrateLocations(); static void RegisterTreeLocations(); + static void RegisterRockLocations(); static void InitHashMaps(); static std::array, 17> randomizerFishingPondFish; static std::unordered_map randomizerGrottoFishMap; diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 017676b7ca9..0cf177acd5a 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -290,6 +290,10 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("BetterOwl")) .Options(CheckboxOptions().Tooltip( "The default response to Kaepora Gaebora is always that you understood what he said.")); + AddWidget(path, "Allow Dropping Throw-Only Objects", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("DropThrowOnlyObjects")) + .Options(CheckboxOptions().Tooltip("Allows normally throw-only objects (such as Cuccos, pots, grass, and small " + "rocks) to be dropped by pressing A while standing still.")); AddWidget(path, "Convenience", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Quit Fishing at Door", WIDGET_CVAR_CHECKBOX) @@ -1644,6 +1648,17 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("ExtraTraps.Teleport")) .PreFunc( [](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; }); + AddWidget(path, "Nightmare Traps:", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { + info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; + }); + AddWidget(path, "Pocket Traps", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("ExtraTraps.Pocket")) + .PreFunc( + [](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; }); + AddWidget(path, "Perma Death Traps", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("ExtraTraps.Permadeath")) + .PreFunc( + [](WidgetInfo& info) { info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) == 0; }); path.column = SECTION_COLUMN_2; AddWidget(path, "Enemy Randomizer", WIDGET_CVAR_COMBOBOX) @@ -1754,6 +1769,9 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "Keese and Guay no longer target you and simply ignore you as if you were wearing the " "Skull Mask.")); + AddWidget(path, "Like Like don't Steal Items", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_CHEAT("NoLikeLikeItemSteal")) + .Options(CheckboxOptions().Tooltip("Prevents Like Likes from being able to steal your equipments.")); AddWidget(path, "Disable Haunted Wasteland Sandstorm", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_CHEAT("DisableSandstorm")) .Options(CheckboxOptions().Tooltip("Disables sandstorm effect in Haunted Wasteland.")); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 86a72456fd2..0c7a433149f 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2814,7 +2814,7 @@ void Interface_SetNaviCall(PlayState* play, u16 naviCallState) { if (((naviCallState == 0x1D) || (naviCallState == 0x1E)) && !interfaceCtx->naviCalling && (play->csCtx.state == CS_STATE_IDLE)) { - if (!CVarGetInteger(CVAR_AUDIO("DisableNaviCallAudio"), 0)) { + if (GameInteractor_Should(VB_PLAY_NAVI_CALL_SOUND, true, naviCallState)) { // clang-format off if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index 96a9297b969..94f3d75a411 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -817,28 +817,30 @@ void EnElf_UpdateLights(EnElf* this, PlayState* play) { s16 glowLightRadius; Player* player; - glowLightRadius = 100; + if (GameInteractor_Should(VB_FAIRY_UPDATE_LIGHTS, true, this)) { + glowLightRadius = 100; - if (this->unk_2A8 == 8) { - glowLightRadius = 0; - } + if (this->unk_2A8 == 8) { + glowLightRadius = 0; + } - if (this->fairyFlags & 0x20) { - player = GET_PLAYER(play); - Lights_PointNoGlowSetInfo(&this->lightInfoNoGlow, player->actor.world.pos.x, - (s16)(player->actor.world.pos.y) + 60.0f, player->actor.world.pos.z, 255, 255, 255, - 200); - } else { - Lights_PointNoGlowSetInfo(&this->lightInfoNoGlow, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 255, 255, 255, -1); - } + if (this->fairyFlags & 0x20) { + player = GET_PLAYER(play); + Lights_PointNoGlowSetInfo(&this->lightInfoNoGlow, player->actor.world.pos.x, + (s16)(player->actor.world.pos.y) + 60.0f, player->actor.world.pos.z, 255, 255, + 255, 200); + } else { + Lights_PointNoGlowSetInfo(&this->lightInfoNoGlow, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 255, 255, 255, -1); + } - Lights_PointGlowSetInfo(&this->lightInfoGlow, this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z, 255, 255, 255, glowLightRadius); + Lights_PointGlowSetInfo(&this->lightInfoGlow, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 255, 255, 255, glowLightRadius); - this->unk_2BC = Math_Atan2S(this->actor.velocity.z, this->actor.velocity.x); + this->unk_2BC = Math_Atan2S(this->actor.velocity.z, this->actor.velocity.x); - Actor_SetScale(&this->actor, this->actor.scale.x); + Actor_SetScale(&this->actor, this->actor.scale.x); + } } void func_80A03CF8(EnElf* this, PlayState* play) { @@ -872,7 +874,9 @@ void func_80A03CF8(EnElf* this, PlayState* play) { if ((play->sceneNum == SCENE_LINKS_HOUSE) && (gSaveContext.sceneSetupIndex == 4)) { // play dash sound as Navi enters Links house in the intro if (play->csCtx.frames == 55) { - Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + if (GameInteractor_Should(VB_FAIRY_PLAY_DASH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + } } // play dash sound in intervals as Navi is waking up Link in the intro @@ -884,7 +888,9 @@ void func_80A03CF8(EnElf* this, PlayState* play) { } else { if (this->actor.world.pos.y < prevPos.y) { this->fairyFlags |= 0x40; - Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + if (GameInteractor_Should(VB_FAIRY_PLAY_DASH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + } } } } @@ -967,7 +973,9 @@ void func_80A03CF8(EnElf* this, PlayState* play) { this->fairyFlags |= 2; if (this->unk_2C7 == 0) { - Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + if (GameInteractor_Should(VB_FAIRY_PLAY_DASH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + } } this->unk_2C0 = 0x64; @@ -1015,7 +1023,9 @@ void func_80A04414(EnElf* this, PlayState* play) { this->unk_29C = 1.0f; if (this->unk_2C7 == 0) { - Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + if (GameInteractor_Should(VB_FAIRY_PLAY_DASH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + } } } else { @@ -1105,7 +1115,9 @@ void func_80A0461C(EnElf* this, PlayState* play) { temp = 0; } else { if (this->unk_2C7 == 0) { - Audio_PlayActorSound2(&this->actor, NA_SE_EV_NAVY_VANISH); + if (GameInteractor_Should(VB_FAIRY_PLAY_VANISH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_NAVY_VANISH); + } } temp = 7; } @@ -1149,7 +1161,9 @@ void func_80A0461C(EnElf* this, PlayState* play) { if (!(player->stateFlags2 & PLAYER_STATE2_NAVI_ACTIVE)) { temp = 7; if (this->unk_2C7 == 0) { - Audio_PlayActorSound2(&this->actor, NA_SE_EV_NAVY_VANISH); + if (GameInteractor_Should(VB_FAIRY_PLAY_VANISH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_NAVY_VANISH); + } } } break; @@ -1159,7 +1173,9 @@ void func_80A0461C(EnElf* this, PlayState* play) { this->unk_2C0 = 42; temp = 11; if (this->unk_2C7 == 0) { - Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + if (GameInteractor_Should(VB_FAIRY_PLAY_DASH_SOUND, true, this)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FAIRY_DASH); + } } } break; @@ -1190,20 +1206,22 @@ void EnElf_SpawnSparkles(EnElf* this, PlayState* play, s32 sparkleLife) { Color_RGBA8 primColor; Color_RGBA8 envColor; - sparklePos.x = Rand_CenteredFloat(6.0f) + this->actor.world.pos.x; - sparklePos.y = (Rand_ZeroOne() * 6.0f) + this->actor.world.pos.y; - sparklePos.z = Rand_CenteredFloat(6.0f) + this->actor.world.pos.z; + if (GameInteractor_Should(VB_FAIRY_SPAWN_SPARKLES, true, this, sparkleLife)) { + sparklePos.x = Rand_CenteredFloat(6.0f) + this->actor.world.pos.x; + sparklePos.y = (Rand_ZeroOne() * 6.0f) + this->actor.world.pos.y; + sparklePos.z = Rand_CenteredFloat(6.0f) + this->actor.world.pos.z; - primColor.r = this->innerColor.r; - primColor.g = this->innerColor.g; - primColor.b = this->innerColor.b; + primColor.r = this->innerColor.r; + primColor.g = this->innerColor.g; + primColor.b = this->innerColor.b; - envColor.r = this->outerColor.r; - envColor.g = this->outerColor.g; - envColor.b = this->outerColor.b; + envColor.r = this->outerColor.r; + envColor.g = this->outerColor.g; + envColor.b = this->outerColor.b; - EffectSsKiraKira_SpawnDispersed(play, &sparklePos, &sparkleVelocity, &sparkleAccel, &primColor, &envColor, 1000, - sparkleLife); + EffectSsKiraKira_SpawnDispersed(play, &sparklePos, &sparkleVelocity, &sparkleAccel, &primColor, &envColor, 1000, + sparkleLife); + } } void func_80A04D90(EnElf* this, PlayState* play) { @@ -1392,7 +1410,9 @@ void func_80A053F0(Actor* thisx, PlayState* play) { } if (Actor_ProcessTalkRequest(thisx, play)) { - func_800F4524(&gSfxDefaultPos, NA_SE_VO_SK_LAUGH, 0x20); + if (GameInteractor_Should(VB_FAIRY_PLAY_C_UP_TALK_SOUND, true, this)) { + func_800F4524(&gSfxDefaultPos, NA_SE_VO_SK_LAUGH, 0x20); + } thisx->focus.pos = thisx->world.pos; if (thisx->textId == ElfMessage_GetCUpText(play)) { @@ -1506,7 +1526,7 @@ void EnElf_Draw(Actor* thisx, PlayState* play) { Gfx* dListHead; Player* player = GET_PLAYER(play); - if ((this->unk_2A8 != 8) && !(this->fairyFlags & 8)) { + if (GameInteractor_Should(VB_FAIRY_DRAW, ((this->unk_2A8 != 8) && !(this->fairyFlags & 8)), this)) { if (!(player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON) || (kREG(90) < this->actor.projectedPos.z)) { dListHead = Graph_Alloc(play->state.gfxCtx, sizeof(Gfx) * 4); diff --git a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index 37dc1fa9db7..fccc1a0d222 100644 --- a/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/soh/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -8,6 +8,7 @@ #include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "soh/OTRGlobals.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "vt.h" @@ -251,6 +252,10 @@ void EnIshi_SpawnDustLarge(EnIshi* this, PlayState* play) { void EnIshi_DropCollectible(EnIshi* this, PlayState* play) { s16 dropParams; + if (!GameInteractor_Should(VB_ROCK_DROP_ITEM, true, this)) { + return; + } + if ((this->actor.params & 1) == ROCK_SMALL) { dropParams = (this->actor.params >> 8) & 0xF; diff --git a/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c b/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c index 831e11b8c38..d94e6dd220b 100644 --- a/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c +++ b/soh/src/overlays/actors/ovl_En_Rr/z_en_rr.c @@ -300,32 +300,35 @@ void EnRr_SetupReleasePlayer(EnRr* this, PlayState* play) { this->wobbleSizeTarget = 2048.0f; tunic = 0; shield = 0; - if (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) != EQUIP_VALUE_SHIELD_MIRROR) { - shield = Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); - if (shield != 0) { - this->eatenShield = shield; - this->retreat = true; + if (GameInteractor_Should(VB_LIKE_LIKE_STEAL_EQUIPMENT, true, this)) { + if (CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) != EQUIP_VALUE_SHIELD_MIRROR) { + shield = Inventory_DeleteEquipment(play, EQUIP_TYPE_SHIELD); + if (shield != 0) { + this->eatenShield = shield; + this->retreat = true; + } } - } - if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) != EQUIP_VALUE_TUNIC_KOKIRI && !IS_RANDO /* Randomizer Save File */) { - tunic = Inventory_DeleteEquipment(play, EQUIP_TYPE_TUNIC); - if (tunic != 0) { - this->eatenTunic = tunic; - this->retreat = true; + if (CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC) != EQUIP_VALUE_TUNIC_KOKIRI && !IS_RANDO /* Randomizer Save File */) { + tunic = Inventory_DeleteEquipment(play, EQUIP_TYPE_TUNIC); + if (tunic != 0) { + this->eatenTunic = tunic; + this->retreat = true; + } + } + + switch (EnRr_GetMessage(shield, tunic)) { + case RR_MESSAGE_SHIELD: + Message_StartTextbox(play, 0x305F, NULL); + break; + case RR_MESSAGE_TUNIC: + Message_StartTextbox(play, 0x3060, NULL); + break; + case RR_MESSAGE_TUNIC | RR_MESSAGE_SHIELD: + Message_StartTextbox(play, 0x3061, NULL); + break; } } player->actor.parent = NULL; - switch (EnRr_GetMessage(shield, tunic)) { - case RR_MESSAGE_SHIELD: - Message_StartTextbox(play, 0x305F, NULL); - break; - case RR_MESSAGE_TUNIC: - Message_StartTextbox(play, 0x3060, NULL); - break; - case RR_MESSAGE_TUNIC | RR_MESSAGE_SHIELD: - Message_StartTextbox(play, 0x3061, NULL); - break; - } osSyncPrintf(VT_FGCOL(YELLOW) "%s[%d] : Rr_Catch_Cancel" VT_RST "\n", __FILE__, __LINE__); func_8002F6D4(play, &this->actor, 4.0f, this->actor.shape.rot.y, 12.0f, 8); if (this->actor.colorFilterTimer == 0) { @@ -666,50 +669,53 @@ void EnRr_Death(EnRr* this, PlayState* play) { (SQ(4 - i) * (f32)this->frameCount * 0.003f) + 1.0f; } } else if (this->frameCount >= 95) { - Vec3f dropPos; - - dropPos.x = this->actor.world.pos.x; - dropPos.y = this->actor.world.pos.y; - dropPos.z = this->actor.world.pos.z; - switch (this->eatenShield) { - case 1: - Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_DEKU); - break; - case 2: - Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_HYLIAN); - break; - } - switch (this->eatenTunic) { - case 2: - Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_GORON); - break; - case 3: - Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_ZORA); - break; - } - // "dropped" - osSyncPrintf(VT_FGCOL(GREEN) "「%s」が出た!!" VT_RST "\n", sDropNames[this->dropType]); - switch (this->dropType) { - case RR_DROP_MAGIC: - Item_DropCollectible(play, &dropPos, ITEM00_MAGIC_SMALL); - break; - case RR_DROP_ARROW: - Item_DropCollectible(play, &dropPos, ITEM00_ARROWS_SINGLE); - break; - case RR_DROP_FLEXIBLE: - Item_DropCollectible(play, &dropPos, ITEM00_FLEXIBLE); - break; - case RR_DROP_RUPEE_PURPLE: - Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_PURPLE); - break; - case RR_DROP_RUPEE_RED: - Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_RED); - break; - case RR_DROP_RANDOM_RUPEE: - default: - Item_DropCollectibleRandom(play, &this->actor, &dropPos, 12 << 4); - break; + if (GameInteractor_Should(VB_LIKE_LIKE_DROP_COLLECTIBLE, true, this)) { + Vec3f dropPos; + + dropPos.x = this->actor.world.pos.x; + dropPos.y = this->actor.world.pos.y; + dropPos.z = this->actor.world.pos.z; + switch (this->eatenShield) { + case 1: + Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_DEKU); + break; + case 2: + Item_DropCollectible(play, &dropPos, ITEM00_SHIELD_HYLIAN); + break; + } + switch (this->eatenTunic) { + case 2: + Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_GORON); + break; + case 3: + Item_DropCollectible(play, &dropPos, ITEM00_TUNIC_ZORA); + break; + } + // "dropped" + osSyncPrintf(VT_FGCOL(GREEN) "「%s」が出た!!" VT_RST "\n", sDropNames[this->dropType]); + switch (this->dropType) { + case RR_DROP_MAGIC: + Item_DropCollectible(play, &dropPos, ITEM00_MAGIC_SMALL); + break; + case RR_DROP_ARROW: + Item_DropCollectible(play, &dropPos, ITEM00_ARROWS_SINGLE); + break; + case RR_DROP_FLEXIBLE: + Item_DropCollectible(play, &dropPos, ITEM00_FLEXIBLE); + break; + case RR_DROP_RUPEE_PURPLE: + Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_PURPLE); + break; + case RR_DROP_RUPEE_RED: + Item_DropCollectible(play, &dropPos, ITEM00_RUPEE_RED); + break; + case RR_DROP_RANDOM_RUPEE: + default: + Item_DropCollectibleRandom(play, &this->actor, &dropPos, 12 << 4); + break; + } } + Actor_Kill(&this->actor); } else if (this->frameCount == 88) { Vec3f pos; diff --git a/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c b/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c index 602236816e0..019a09320c1 100644 --- a/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c +++ b/soh/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c @@ -7,6 +7,7 @@ #include "z_obj_bombiwa.h" #include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h" #include "objects/object_bombiwa/object_bombiwa.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -75,7 +76,7 @@ void ObjBombiwa_InitCollision(Actor* thisx, PlayState* play) { void ObjBombiwa_Init(Actor* thisx, PlayState* play) { Actor_ProcessInitChain(thisx, sInitChain); ObjBombiwa_InitCollision(thisx, play); - if ((Flags_GetSwitch(play, thisx->params & 0x3F) != 0)) { + if (GameInteractor_Should(VB_BOULDER_BREAK_FLAG, Flags_GetSwitch(play, thisx->params & 0x3F), thisx)) { Actor_Kill(thisx); } else { CollisionCheck_SetInfo(&thisx->colChkInfo, NULL, &sColChkInfoInit); diff --git a/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c b/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c index d4d952cc0bc..c609992d72b 100644 --- a/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c +++ b/soh/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c @@ -6,6 +6,7 @@ #include "z_obj_hamishi.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -150,7 +151,7 @@ void ObjHamishi_Init(Actor* thisx, PlayState* play) { ObjHamishi_InitCollision(&this->actor, play); CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); - if (Flags_GetSwitch(play, this->actor.params & 0x3F)) { + if (GameInteractor_Should(VB_BOULDER_BREAK_FLAG, Flags_GetSwitch(play, this->actor.params & 0x3F), this)) { Actor_Kill(&this->actor); return; } diff --git a/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c b/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c index 2b8cfcb7a10..8582f2e3ea3 100644 --- a/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c +++ b/soh/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c @@ -8,6 +8,7 @@ #include "objects/object_demo_kekkai/object_demo_kekkai.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_spot02_objects/object_spot02_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/frame_interpolation.h" #include @@ -205,23 +206,25 @@ void ObjectKankyo_Fairies(ObjectKankyo* this, PlayState* play) { dist = 1.0f; } - func_800F436C(&sSoundPos, NA_SE_EV_NAVY_FLY - SFX_FLAG, (0.4f * dist) + 0.6f); - switch (play->csCtx.frames) { - case 473: - Sfx_PlaySfxCentered2(NA_SE_VO_NA_HELLO_3); - break; + if (GameInteractor_Should(VB_PLAY_INTRO_NAVI_SOUNDS, true, this)) { + func_800F436C(&sSoundPos, NA_SE_EV_NAVY_FLY - SFX_FLAG, (0.4f * dist) + 0.6f); + switch (play->csCtx.frames) { + case 473: + Sfx_PlaySfxCentered2(NA_SE_VO_NA_HELLO_3); + break; - case 583: - func_800F4524(&gSfxDefaultPos, NA_SE_VO_NA_HELLO_2, 32); - break; + case 583: + func_800F4524(&gSfxDefaultPos, NA_SE_VO_NA_HELLO_2, 32); + break; - case 763: - Sfx_PlaySfxCentered(NA_SE_EV_NAVY_CRASH - SFX_FLAG); - break; + case 763: + Sfx_PlaySfxCentered(NA_SE_EV_NAVY_CRASH - SFX_FLAG); + break; - case 771: - Sfx_PlaySfxCentered(NA_SE_VO_RT_THROW); - break; + case 771: + Sfx_PlaySfxCentered(NA_SE_VO_RT_THROW); + break; + } } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 025aeb97651..6fe51b616ad 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6305,11 +6305,13 @@ s32 func_8083BBA0(Player* this, PlayState* play) { } void Player_SetupRoll(Player* this, PlayState* play) { - Player_SetupAction(play, this, Player_Action_Roll, 0); - LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, - GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing_roll, this->modelAnimType), - 1.25f * sWaterSpeedFactor); - gSaveContext.ship.stats.count[COUNT_ROLLS]++; + if (GameInteractor_Should(VB_ROLL, true)) { + Player_SetupAction(play, this, Player_Action_Roll, 0); + LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, + GET_PLAYER_ANIM(PLAYER_ANIMGROUP_landing_roll, this->modelAnimType), + 1.25f * sWaterSpeedFactor); + gSaveContext.ship.stats.count[COUNT_ROLLS]++; + } } s32 Player_TryRoll(Player* this, PlayState* play) { @@ -7386,7 +7388,7 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) { } else if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && !(this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) && !(this->stateFlags2 & PLAYER_STATE2_UNDERWATER)) { - if (this->getItemId != GI_NONE) { + if (GameInteractor_Should(VB_OPEN_CHEST, this->getItemId != GI_NONE)) { GetItemEntry giEntry; if (this->getItemEntry.objectId == OBJECT_INVALID) { giEntry = ItemTable_Retrieve(-this->getItemId);