diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index b241fe8904c..8ae9a74b218 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -93,7 +93,17 @@ jobs: readme.txt build-linux: needs: extract-assets - runs-on: ubuntu-20.04 + strategy: + fail-fast: true + matrix: + include: + - os: ubuntu-20.04 + gcc: 10 + archive-suffix: compatibility + - os: ubuntu-22.04 + gcc: 12 + archive-suffix: performance + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 with: @@ -105,7 +115,7 @@ jobs: - name: ccache uses: hendrikmuhs/ccache-action@v1.2 with: - key: ${{ runner.os }}-ccache + key: ${{ matrix.os }}-ccache - name: Install latest SDL run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" @@ -143,12 +153,12 @@ jobs: mv README.md readme.txt mv build-cmake/*.appimage soh.appimage env: - CC: gcc-10 - CXX: g++-10 + CC: gcc-${{ matrix.gcc }} + CXX: g++-${{ matrix.gcc }} - name: Upload build uses: actions/upload-artifact@v3 with: - name: soh-linux + name: soh-linux-${{ matrix.archive-suffix }} path: | soh.appimage readme.txt diff --git a/BUILDING.md b/BUILDING.md index 80e4fe0fa8a..cc1b63db0e2 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -22,6 +22,9 @@ You can also find the v142 toolset by searching through the individual component While you're there, you can also install Python 3 and Git if needed. 1. Clone the Ship of Harkinian repository + +_Note: Be sure to either clone with the ``--recursive`` flag or do ``git submodule init`` after cloning to pull in the libultraship submodule!_ + 2. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice _Note: Instructions assume using powershell_ diff --git a/CMakeLists.txt b/CMakeLists.txt index 84da81a1220..0f0f6b8df6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE) project(Ship LANGUAGES C CXX - VERSION 5.1.3) -set(PROJECT_BUILD_NAME "BRADLEY DELTA" CACHE STRING "") + VERSION 5.1.4) +set(PROJECT_BUILD_NAME "BRADLEY ECHO" CACHE STRING "") set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh) diff --git a/OTRGui/CMakeLists.txt b/OTRGui/CMakeLists.txt index 2933c05d37b..9eec59c8459 100644 --- a/OTRGui/CMakeLists.txt +++ b/OTRGui/CMakeLists.txt @@ -59,7 +59,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE . ) -INSTALL(TARGETS OTRGui DESTINATION . COMPONENT ship) +INSTALL(TARGETS OTRGui DESTINATION . COMPONENT ship OPTIONAL) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/assets DESTINATION . COMPONENT ship diff --git a/README.md b/README.md index 89e8b5c539a..97c1dd614d4 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,10 @@ Assuming you have done everything correctly, boot up SoH and open up the SFX Edi Refer to the [building instructions](BUILDING.md) to compile SoH. ## Nightly Builds -Nightly builds of Ship of Harkinian are available here: [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip), [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip), [Linux](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux.zip), [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip), [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip) +Nightly builds of Ship of Harkinian are available here: [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip), [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip), [Linux (compatibility*)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-compatiblity.zip), [Linux (performance*)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-performance.zip), [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip), [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip) + +_*compatibility: compatible with most Linux distributions, but may not be as performant as the perf build._\ +_*performance: requires glibc 2.35 or newer, but will be more performant than the compat build._ ## Take The Survey Want to use cartridge readers in tandem with the OTRGui? diff --git a/libultraship b/libultraship index abed8876231..120c60b54a7 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit abed8876231d7b1e52c6c2127234c7a199809d7f +Subproject commit 120c60b54a75d656e88be8027ac5430ba72ebbf5 diff --git a/soh/include/functions.h b/soh/include/functions.h index 7bf9028c600..70def4ac2d6 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -531,10 +531,10 @@ void func_8003424C(PlayState* play, Vec3f* arg1); void Actor_SetColorFilter(Actor* actor, s16 colorFlag, s16 colorIntensityMax, s16 xluFlag, s16 duration); Hilite* func_800342EC(Vec3f* object, PlayState* play); Hilite* func_8003435C(Vec3f* object, PlayState* play); -s32 func_800343CC(PlayState* play, Actor* actor, s16* arg2, f32 interactRange, - u16 (*unkFunc1)(PlayState*, Actor*), s16 (*unkFunc2)(PlayState*, Actor*)); -s16 func_800347E8(s16 arg0); -void func_80034A14(Actor* actor, struct_80034A14_arg1* arg1, s16 arg2, s16 arg3); +s32 Npc_UpdateTalking(PlayState* play, Actor* actor, s16* talkState, f32 interactRange, + NpcGetTextIdFunc getTextId, NpcUpdateTalkStateFunc updateTalkState); +s16 Npc_GetTrackingPresetMaxPlayerYaw(s16 presetIndex); +void Npc_TrackPoint(Actor* actor, NpcInteractInfo* interactInfo, s16 presetIndex, s16 trackingMode); void func_80034BA0(PlayState* play, SkelAnime* skelAnime, OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor, s16 alpha); void func_80034CC4(PlayState* play, SkelAnime* skelAnime, OverrideLimbDraw overrideLimbDraw, diff --git a/soh/include/z64.h b/soh/include/z64.h index 7b5aa83eddd..46a236cd63a 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -1508,18 +1508,6 @@ typedef struct { /* 0x08 */ f32 morphFrames; } AnimationMinimalInfo; // size = 0xC -typedef struct { - /* 0x00 */ s16 unk_00; - /* 0x02 */ s16 unk_02; - /* 0x04 */ s16 unk_04; - /* 0x06 */ s16 unk_06; - /* 0x08 */ Vec3s unk_08; - /* 0x0E */ Vec3s unk_0E; - /* 0x14 */ f32 unk_14; - /* 0x18 */ Vec3f unk_18; - /* 0x24 */ s16 unk_24; -} struct_80034A14_arg1; // size = 0x28 - typedef struct { /* 0x00 */ s8 scene; /* 0x01 */ s8 spawn; diff --git a/soh/include/z64actor.h b/soh/include/z64actor.h index 11cf861386c..abcc1f2e19d 100644 --- a/soh/include/z64actor.h +++ b/soh/include/z64actor.h @@ -20,8 +20,8 @@ struct Lights; typedef void (*ActorFunc)(struct Actor*, struct PlayState*); typedef void (*ActorResetFunc)(void); typedef void (*ActorShadowFunc)(struct Actor*, struct Lights*, struct PlayState*); -typedef u16 (*callback1_800343CC)(struct PlayState*, struct Actor*); -typedef s16 (*callback2_800343CC)(struct PlayState*, struct Actor*); +typedef u16 (*NpcGetTextIdFunc)(struct PlayState*, struct Actor*); +typedef s16 (*NpcUpdateTalkStateFunc)(struct PlayState*, struct Actor*); typedef struct { Vec3f pos; @@ -369,4 +369,31 @@ typedef enum { DOORLOCK_NORMAL_SPIRIT } DoorLockType; +typedef enum { + /* 0x0 */ NPC_TALK_STATE_IDLE, // NPC not currently talking to player + /* 0x1 */ NPC_TALK_STATE_TALKING, // NPC is currently talking to player + /* 0x2 */ NPC_TALK_STATE_ACTION, // An NPC-defined action triggered in the conversation + /* 0x3 */ NPC_TALK_STATE_ITEM_GIVEN // NPC finished giving an item and text box is done +} NpcTalkState; + +typedef enum { + /* 0x0 */ NPC_TRACKING_PLAYER_AUTO_TURN, // Determine tracking mode based on player position, see Npc_UpdateAutoTurn + /* 0x1 */ NPC_TRACKING_NONE, // Don't track the target (usually the player) + /* 0x2 */ NPC_TRACKING_HEAD_AND_TORSO, // Track target by turning the head and the torso + /* 0x3 */ NPC_TRACKING_HEAD, // Track target by turning the head + /* 0x4 */ NPC_TRACKING_FULL_BODY // Track target by turning the body, torso and head +} NpcTrackingMode; + +typedef struct { + /* 0x00 */ s16 talkState; + /* 0x02 */ s16 trackingMode; + /* 0x04 */ s16 autoTurnTimer; + /* 0x06 */ s16 autoTurnState; + /* 0x08 */ Vec3s headRot; + /* 0x0E */ Vec3s torsoRot; + /* 0x14 */ f32 yOffset; // Y position offset to add to actor position when calculating angle to target + /* 0x18 */ Vec3f trackPos; + /* 0x24 */ char unk_24[0x4]; +} NpcInteractInfo; // size = 0x28 + #endif diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 4ee45564ba6..79e6470860c 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -264,6 +264,7 @@ typedef struct { /* */ char adultAltarText[750]; /* */ char ganonHintText[150]; /* */ char ganonText[250]; + /* */ char dampeText[150]; /* */ char warpMinuetText[100]; /* */ char warpBoleroText[100]; /* */ char warpSerenadeText[100]; diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 9117445d8ef..8603343e166 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1669,6 +1669,25 @@ void DrawCosmeticsEditor(bool& open) { ImGui::SameLine(); UIWidgets::EnhancementCombobox("gCosmetics.DefaultColorScheme", colorSchemes, 2, 0); UIWidgets::EnhancementCheckbox("Advanced Mode", "gCosmetics.AdvancedMode"); + if (CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + if (ImGui::Button("Lock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if (cosmeticOption.advancedOption) { + CVarSetInteger(cosmeticOption.lockedCvar, 1); + } + } + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + if (ImGui::Button("Unlock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if (cosmeticOption.advancedOption) { + CVarSetInteger(cosmeticOption.lockedCvar, 0); + } + } + SohImGui::RequestCvarSaveOnNextTick(); + } + } UIWidgets::EnhancementCheckbox("Sync Rainbow colors", "gCosmetics.RainbowSync"); UIWidgets::EnhancementSliderFloat("Rainbow Speed: %f", "##rainbowSpeed", "gCosmetics.RainbowSpeed", 0.03f, 1.0f, "", 0.6f, false); if (ImGui::Button("Randomize All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { @@ -1691,6 +1710,24 @@ void DrawCosmeticsEditor(bool& open) { SohImGui::RequestCvarSaveOnNextTick(); } + if (ImGui::Button("Lock All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + CVarSetInteger(cosmeticOption.lockedCvar, 1); + } + } + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + if (ImGui::Button("Unlock All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if (!cosmeticOption.advancedOption || CVarGetInteger("gCosmetics.AdvancedMode", 0)) { + CVarSetInteger(cosmeticOption.lockedCvar, 0); + } + } + SohImGui::RequestCvarSaveOnNextTick(); + } + if (ImGui::BeginTabBar("CosmeticsContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Link & Items")) { DrawCosmeticGroup(GROUP_LINK); diff --git a/soh/soh/Enhancements/crowd-control/CrowdControl.cpp b/soh/soh/Enhancements/crowd-control/CrowdControl.cpp index 01c6937a5d7..48af4c34ebf 100644 --- a/soh/soh/Enhancements/crowd-control/CrowdControl.cpp +++ b/soh/soh/Enhancements/crowd-control/CrowdControl.cpp @@ -101,7 +101,7 @@ void CrowdControl::Disable() { void CrowdControl::ListenToServer() { while (isEnabled) { - while (!connected) { + while (!connected && isEnabled) { SPDLOG_TRACE("[CrowdControl] Attempting to make connection to server..."); tcpsock = SDLNet_TCP_Open(&ip); @@ -112,8 +112,10 @@ void CrowdControl::ListenToServer() { } } - auto socketSet = SDLNet_AllocSocketSet(1); - SDLNet_TCP_AddSocket(socketSet, tcpsock); + SDLNet_SocketSet socketSet = SDLNet_AllocSocketSet(1); + if (tcpsock) { + SDLNet_TCP_AddSocket(socketSet, tcpsock); + } // Listen to socket messages while (connected && tcpsock && isEnabled) { diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 0df6b1862c3..bde49f521aa 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -1,6 +1,8 @@ #pragma once typedef enum { + TEXT_CURSED_SKULLTULA_PEOPLE = 0x22, + TEXT_DAMPES_DIARY = 0x5003, TEXT_BUY_BOMBCHU_10_PROMPT = 0x8C, TEXT_BUY_BOMBCHU_10_DESC = 0xBC, TEXT_GS_NO_FREEZE = 0xB4, diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 2a0194cfc94..9d389a1997c 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -86,6 +86,7 @@ const std::vector enhancementsCvars = { "gNoHeartDrops", "gBombchuDrops", "gGoronPot", + "gFullHealthSpawn", "gDampeWin", "gRedPotionEffect", "gRedPotionHealth", @@ -172,16 +173,25 @@ const std::vector enhancementsCvars = { "gBombchuBowlingNoBigCucco", "gBombchuBowlingAmmunition", "gCreditsFix", + "gSilverRupeeJingleExtend", + "gStaticExplosionRadius" }; const std::vector randomizerCvars = { + "gRandomize10GSHint", + "gRandomize20GSHint", + "gRandomize30GSHint", + "gRandomize40GSHint", + "gRandomize50GSHint", "gRandomizeAllLocationsReachable", + "gRandomizeAltarHint", "gRandomizeBigPoeTargetCount", "gRandomizeBlueFireArrows", "gRandomizeBombchusInLogic", "gRandomizeBossKeysanity", "gRandomizeCompleteMaskQuest", "gRandomizeCuccosToReturn", + "gRandomizeDampeHint", "gRandomizeDecoupleEntrances", "gRandomizeDoorOfTime", "gRandomizeDungeonCount", @@ -207,6 +217,7 @@ const std::vector randomizerCvars = { "gRandomizeLacsRewardCount", "gRandomizeLacsStoneCount", "gRandomizeLacsTokenCount", + "gRandomizeLAHint", "gRandomizeLinksPocket", "gRandomizeLogicRules", "gRandomizeMedallionCount", @@ -219,9 +230,11 @@ const std::vector randomizerCvars = { "gRandomizeMqDungeons", "gRandomizeRainbowBridge", "gRandomizeRewardCount", + "gRandomizeScrubText", "gRandomizeShopsanity", "gRandomizeShuffleAdultTrade", "gRandomizeShuffleBeans", + "gRandomizeShuffleBossEntrances", "gRandomizeShuffleCows", "gRandomizeShuffleDungeonReward", "gRandomizeShuffleDungeonsEntrances", @@ -258,14 +271,27 @@ const std::vector randomizerCvars = { "gRandomizeSkipTowerEscape", "gRandomizeStartingAge", "gRandomizeStartingConsumables", + "gRandomizeStartingBoleroOfFire", "gRandomizeStartingDekuShield", + "gRandomizeStartingEponasSong", "gRandomizeStartingKokiriSword", "gRandomizeStartingMapsCompasses", + "gRandomizeStartingMinuetOfForest", + "gRandomizeStartingNocturneOfShadow", "gRandomizeStartingOcarina", + "gRandomizeStartingPreludeOfLight", + "gRandomizeStartingRequiemOfSpirit", + "gRandomizeStartingSariasSong", + "gRandomizeStartingSerenadeOfWater", "gRandomizeStartingSkulltulaToken", + "gRandomizeStartingSongOfStorms", + "gRandomizeStartingSongOfTime", + "gRandomizeStartingSunsSong", + "gRandomizeStartingZeldasLullaby", "gRandomizeStoneCount", "gRandomizeSunlightArrows", "gRandomizeTokenCount", + "gRandomizeWarpSongText", "gRandomizeZorasFountain", }; @@ -319,6 +345,8 @@ const std::vector vanillaPlusPresetEntries = { PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1), // Fix Navi text HUD position PRESET_ENTRY_S32("gNaviTextFix", 1), + // Extend Silver Rupee Jingle + PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), // Red Ganon blood PRESET_ENTRY_S32("gRedGanonBlood", 1), @@ -382,6 +410,8 @@ const std::vector enhancedPresetEntries = { PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1), // Fix Navi text HUD position PRESET_ENTRY_S32("gNaviTextFix", 1), + // Extend Silver Rupee Jingle + PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), // Red Ganon blood PRESET_ENTRY_S32("gRedGanonBlood", 1), @@ -491,6 +521,8 @@ const std::vector randomizerPresetEntries = { PRESET_ENTRY_S32("gDekuNutUpgradeFix", 1), // Fix Navi text HUD position PRESET_ENTRY_S32("gNaviTextFix", 1), + // Extend Silver Rupee Jingle + PRESET_ENTRY_S32("gSilverRupeeJingleExtend", 1), // Red Ganon blood PRESET_ENTRY_S32("gRedGanonBlood", 1), diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp index 442d07f0885..e1eeb69d9d6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp @@ -81,12 +81,25 @@ void SetAllEntrancesData(std::vector& entranceShuffleTable) { forwardEntrance->SetBlueWarp(forwardEntry.blueWarp); forwardEntrance->SetType(forwardEntry.type); forwardEntrance->SetAsPrimary(); + + // When decouple entrances is on, mark it for entrances except boss rooms + if (Settings::DecoupleEntrances && forwardEntry.type != EntranceType::ChildBoss && + forwardEntry.type != EntranceType::AdultBoss) { + forwardEntrance->SetDecoupled(); + } + if (returnEntry.parentRegion != NONE) { Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion); returnEntrance->SetIndex(returnEntry.index); returnEntrance->SetBlueWarp(returnEntry.blueWarp); returnEntrance->SetType(returnEntry.type); forwardEntrance->BindTwoWay(returnEntrance); + + // Mark reverse entrance as decoupled + if (Settings::DecoupleEntrances && returnEntry.type != EntranceType::ChildBoss && + returnEntry.type != EntranceType::AdultBoss) { + returnEntrance->SetDecoupled(); + } } } } @@ -96,7 +109,7 @@ static std::vector AssumeEntrancePool(std::vector& entranc for (Entrance* entrance : entrancePool) { totalRandomizableEntrances++; Entrance* assumedForward = entrance->AssumeReachable(); - if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) { + if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { Entrance* assumedReturn = entrance->GetReverse()->AssumeReachable(); if (!(Settings::MixedEntrancePools && (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)))) { auto type = entrance->GetType(); @@ -218,7 +231,7 @@ static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) { SPDLOG_DEBUG(message); entrance->Connect(targetEntrance->Disconnect()); entrance->SetReplacement(targetEntrance->GetReplacement()); - if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) { + if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { targetEntrance->GetReplacement()->GetReverse()->Connect(entrance->GetReverse()->GetAssumed()->Disconnect()); targetEntrance->GetReplacement()->GetReverse()->SetReplacement(entrance->GetReverse()); } @@ -229,7 +242,7 @@ static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) { static void RestoreConnections(Entrance* entrance, Entrance* targetEntrance) { targetEntrance->Connect(entrance->Disconnect()); entrance->SetReplacement(nullptr); - if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) { + if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { entrance->GetReverse()->GetAssumed()->Connect(targetEntrance->GetReplacement()->GetReverse()->Disconnect()); targetEntrance->GetReplacement()->GetReverse()->SetReplacement(nullptr); } @@ -247,7 +260,7 @@ static void DeleteTargetEntrance(Entrance* targetEntrance) { static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) { DeleteTargetEntrance(targetEntrance); - if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) { + if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) { auto replacedReverse = targetEntrance->GetReplacement()->GetReverse(); DeleteTargetEntrance(replacedReverse->GetReverse()->GetAssumed()); } @@ -786,9 +799,9 @@ int ShuffleAllEntrances() { {EntranceType::SpecialInterior, KAK_POTION_SHOP_BACK, KAK_BACKYARD, 0x04FF}}, // Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the - // grottoLoadTable in src/grotto.c + // grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c // Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the - // grottoReturnTable in src/grotto.c + // grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c {{EntranceType::GrottoGrave, DESERT_COLOSSUS, COLOSSUS_GROTTO, 0x0700}, {EntranceType::GrottoGrave, COLOSSUS_GROTTO, DESERT_COLOSSUS, 0x0800}}, {{EntranceType::GrottoGrave, LAKE_HYLIA, LH_GROTTO, 0x0701}, @@ -933,6 +946,23 @@ int ShuffleAllEntrances() { {{EntranceType::WarpSong, REQUIEM_OF_SPIRIT_WARP, DESERT_COLOSSUS, 0x01F1}, NO_RETURN_ENTRANCE}, {{EntranceType::WarpSong, NOCTURNE_OF_SHADOW_WARP, GRAVEYARD_WARP_PAD_REGION, 0x0568}, NO_RETURN_ENTRANCE}, {{EntranceType::WarpSong, PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME, 0x05F4}, NO_RETURN_ENTRANCE}, + + {{EntranceType::ChildBoss, DEKU_TREE_BOSS_ENTRYWAY, DEKU_TREE_BOSS_ROOM, 0x040F}, + {EntranceType::ChildBoss, DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457}}, + {{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ENTRYWAY, DODONGOS_CAVERN_BOSS_ROOM, 0x040B}, + {EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A}}, + {{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ENTRYWAY, JABU_JABUS_BELLY_BOSS_ROOM, 0x0301}, + {EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, 0x010E}}, + {{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ENTRYWAY, FOREST_TEMPLE_BOSS_ROOM, 0x000C}, + {EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608}}, + {{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ENTRYWAY, FIRE_TEMPLE_BOSS_ROOM, 0x0305}, + {EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564}}, + {{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ENTRYWAY, WATER_TEMPLE_BOSS_ROOM, 0x0417}, + {EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C}}, + {{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ENTRYWAY, SPIRIT_TEMPLE_BOSS_ROOM, 0x008D}, + {EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610}}, + {{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ENTRYWAY, SHADOW_TEMPLE_BOSS_ROOM, 0x0413}, + {EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580}}, }; std::map priorityEntranceTable = { @@ -971,6 +1001,28 @@ int ShuffleAllEntrances() { } } + // Shuffle Bosses + if (Settings::ShuffleBossEntrances.IsNot(SHUFFLEBOSSES_OFF)) { + if (Settings::ShuffleBossEntrances.Is(SHUFFLEBOSSES_FULL)) { + entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss); + AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss)); + // If forest is closed, ensure Ghoma is inside the Deku tree + // Deku tree being in its vanilla location is handled below + if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) { + FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY && + entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;}); + } + } else { + entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); + entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); + // If forest is closed, ensure Ghoma is inside the Deku tree + if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) { + FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY && + entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;}); + } + } + } + //Shuffle Dungeon Entrances if (Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) { entrancePools[EntranceType::Dungeon] = GetShuffleableEntrances(EntranceType::Dungeon); diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.hpp b/soh/soh/Enhancements/randomizer/3drando/entrance.hpp index 42ef1cb508b..6634820b152 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.hpp @@ -22,6 +22,9 @@ enum class EntranceType { Dungeon, GanonDungeon, DungeonReverse, + Boss, + ChildBoss, + AdultBoss, Interior, InteriorReverse, SpecialInterior, @@ -180,6 +183,14 @@ class Entrance { return primary; } + bool IsDecoupled() const { + return decoupled; + } + + void SetDecoupled() { + decoupled = true; + } + int16_t GetIndex() const { return index; } @@ -269,6 +280,7 @@ class Entrance { bool shuffled = false; bool primary = false; bool addedToPool = false; + bool decoupled = false; std::string name = ""; }; diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 7d166ef8066..0e8ab67e1a4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -296,7 +296,7 @@ std::vector GetAccessibleLocations(const std::vector& allowe entranceSphere.push_back(&exit); exit.AddToPool(); // Don't list a two-way coupled entrance from both directions - if (exit.GetReverse() != nullptr && exit.GetReplacement()->GetReverse() != nullptr && !Settings::DecoupleEntrances) { + if (exit.GetReverse() != nullptr && exit.GetReplacement()->GetReverse() != nullptr && !exit.IsDecoupled()) { exit.GetReplacement()->GetReverse()->AddToPool(); } } @@ -1074,6 +1074,14 @@ int Fill() { if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) { CreateMerchantsHints(); } + //Always execute ganon hint generation for the funny line + CreateGanonText(); + if (AltarHintText) { + CreateAltarText(); + } + if (DampeHintText) { + CreateDampesDiaryText(); + } if (ShuffleWarpSongs) { CreateWarpSongTexts(); } diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 8111d3fb517..f52d1091c6f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2519,93 +2519,61 @@ void HintTable_Init() { | BOSS HINT TEXT | ---------------------------*/ - hintTable[QUEEN_GOHMA] = HintText::Boss( - { - // obscure text - Text{ "An #ancient tree# rewards", /*french*/ "le #vieil arbre# octroie", - /*spanish*/ "un #ancestral árbol# premia con" }, - }, - {}, - // clear text - Text{ "the #Deku Tree# rewards", /*french*/ "l'#Arbre Mojo# octroie", - /*spanish*/ "el #Gran Árbol Deku# premia con" }); - - hintTable[KING_DODONGO] = HintText::Boss( - { - // obscure text - Text{ "An #immense cavern# rewards", /*french*/ "l'#immense caverne# octroie", - /*spanish*/ "una #descomunal cueva# premia con" }, - }, - {}, - // clear text - Text{ "#Dodongo's Cavern# rewards", /*french*/ "la #Caverne Dodongo# octroie", - /*spanish*/ "la #Cueva de los Dodongos# premia con" }); - - hintTable[BARINADE] = HintText::Boss( - { - // obscure text - Text{ "the #belly of a deity# rewards", /*french*/ "le #ventre du gardien# octroie", - /*spanish*/ "la #tripa de cierta deidad# premia con" }, - }, - {}, - // clear text - Text{ "#Jabu-Jabu's Belly# rewards", /*french*/ "le #Ventre de Jabu-Jabu# octroie", - /*spanish*/ "la #tripa de Jabu-Jabu# premia con" }); - - hintTable[PHANTOM_GANON] = HintText::Boss( - { - // obscure text - Text{ "a #deep forest# rewards", /*french*/ "la #profonde forêt# octroie", - /*spanish*/ "el #profundo bosque# premia con" }, - }, - {}, - // clear text - Text{ "the #Forest Temple# rewards", /*french*/ "le #Temple de la Forêt# octroie", - /*spanish*/ "el #Templo del Bosque# premia con" }); - - hintTable[VOLVAGIA] = HintText::Boss( - { - // obscure text - Text{ "a #high mountain# rewards", /*french*/ "la #grande montagne# octroie", - /*spanish*/ "una #alta montaña# premia con" }, - }, - {}, - // clear text - Text{ "the #Fire Temple# rewards", /*french*/ "le #Temple du Feu# octroie", - /*spanish*/ "el #Templo del Fuego# premia con" }); - - hintTable[MORPHA] = HintText::Boss( - { - // obscure text - Text{ "a #vast lake# rewards", /*french*/ "le #vaste lac# octroie", - /*spanish*/ "un #lago inmenso# premia con" }, - }, - {}, - // clear text - Text{ "the #Water Temple# rewards", /*french*/ "le #Temple de l'Eau# octroie", - /*spanish*/ "el #Templo del Agua# premia con" }); - - hintTable[BONGO_BONGO] = HintText::Boss( - { - // obscure text - Text{ "the #house of the dead# rewards", /*french*/ "la #maison des morts# octroie", - /*spanish*/ "la #casa de la muerte# premia con" }, - }, - {}, - // clear text - Text{ "the #Shadow Temple# rewards", /*french*/ "le #Temple de l'Ombre# octroie", - /*spanish*/ "el #Templo de las Sombras#" }); - - hintTable[TWINROVA] = HintText::Boss( - { - // obscure text - Text{ "a #goddess of the sand# rewards", /*french*/ "la #déesse des sables# octroie", - /*spanish*/ "la #diosa de la arena# premia con" }, - }, - {}, - // clear text - Text{ "the #Spirit Temple# rewards", /*french*/ "le #Temple de l'Esprit# octroie", - /*spanish*/ "el #Templo del Espíritu# premia con" }); + hintTable[QUEEN_GOHMA] = HintText::Boss({ + // obscure text + Text{"the #Parasitic Armored Arachnid# holds", /*french*/"le #monstre insectoïde géant# possède", /*spanish*/"el #arácnido parasitario acorazado# porta"}, + }, {}, + //clear text + Text{"#Queen Gohma# holds", /*french*/"la #Reine Gohma# possède", /*spanish*/"la #Reina Goma# porta"}); + + hintTable[KING_DODONGO] = HintText::Boss({ + //obscure text + Text{"the #Infernal Dinosaur# holds", /*french*/"le #dinosaure infernal# possède", /*spanish*/"el #dinosaurio infernal# porta"}, + }, {}, + //clear text + Text{"#King Dodongo# holds", /*french*/"le #Roi Dodongo# possède", /*spanish*/"el #Rey Dodongo# porta"}); + + hintTable[BARINADE] = HintText::Boss({ + //obscure text + Text{"the #Bio-Electric Anemone# holds", /*french*/"l'#anémone bioélectrique# possède", /*spanish*/"la #anémona bioeléctrica# porta"}, + }, {}, + //clear text + Text{"#Barinade# holds", /*french*/"#Barinade# possède", /*spanish*/"#Barinade# porta"}); + + hintTable[PHANTOM_GANON] = HintText::Boss({ + //obscure text + Text{"the #Evil Spirit from Beyond# holds", /*french*/"l'#esprit maléfique de l'au-delà# possède", /*spanish*/"el #espíritu maligno de ultratumba# porta"}, + }, {}, + //clear text + Text{"#Phantom Ganon# holds", /*french*/"#Ganon Spectral# possède", /*spanish*/"#Ganon Fantasma# porta"}); + + hintTable[VOLVAGIA] = HintText::Boss({ + //obscure text + Text{"the #Subterranean Lava Dragon# holds", /*french*/"le #dragon des profondeurs# possède", /*spanish*/"el #dragón de lava subterráneo# porta"}, + }, {}, + //clear text + Text{"#Volvagia# holds", /*french*/"#Volvagia# possède", /*spanish*/"#Volvagia# porta"}); + + hintTable[MORPHA] = HintText::Boss({ + //obscure text + Text{"the #Giant Aquatic Amoeba# holds", /*french*/"l'#amibe aquatique géante# possède", /*spanish*/"la #ameba acuática gigante# porta"}, + }, {}, + //clear text + Text{"#Morpha# holds", /*french*/"#Morpha# possède", /*spanish*/"#Morpha# porta"}); + + hintTable[BONGO_BONGO] = HintText::Boss({ + //obscure text + Text{"the #Phantom Shadow Beast# holds", /*french*/"le #monstre de l'ombre# possède", /*spanish*/"la #alimaña oscura espectral# porta"}, + }, {}, + //clear text + Text{"#Bongo Bongo# holds", /*french*/"#Bongo Bongo# possède", /*spanish*/"#Bongo Bongo# porta"}); + + hintTable[TWINROVA] = HintText::Boss({ + //obscure text + Text{"the #Sorceress Sisters# hold", /*french*/"#les sorcières jumelles# possède", /*spanish*/"las #hermanas hechiceras# portan"}, + }, {}, + //clear text + Text{"#Twinrova# holds", /*french*/"#Twinrova# possède", /*spanish*/"#Birova# porta"}); // // [LINKS_POCKET_BOSS] = HintText::Boss({ // //obscure text diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 8516ecb76fd..6b613246b8d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -116,6 +116,7 @@ Text childAltarText; Text adultAltarText; Text ganonText; Text ganonHintText; +Text dampesText; Text warpMinuetText; Text warpBoleroText; Text warpSerenadeText; @@ -139,6 +140,10 @@ Text& GetGanonHintText() { return ganonHintText; } +Text& GetDampeHintText() { + return dampesText; +} + Text& GetWarpMinuetText() { return warpMinuetText; } @@ -312,17 +317,12 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) { Location(hintedLocation)->SetAsHinted(); uint32_t gossipStone = RandomElement(gossipStoneLocations); - // form hint text - Text locationText; if (Location(hintedLocation)->IsDungeon()) { *remainingDungeonWothHints -= 1; - uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey(); - locationText = AreaTable(parentRegion)->GetHint().GetText(); - - } else { - uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey(); - locationText = GetHintRegion(parentRegion)->GetHint().GetText(); } + + // form hint text + Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); Text finalWothHint = Hint(PREFIX).GetText() + "#" + locationText + "#" + Hint(WAY_OF_THE_HERO).GetText(); SPDLOG_DEBUG("\tMessage: "); SPDLOG_DEBUG(finalWothHint.english); @@ -360,16 +360,12 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vectorSetAsHinted(); uint32_t gossipStone = RandomElement(gossipStoneLocations); - // form hint text - Text locationText; if (Location(hintedLocation)->IsDungeon()) { *remainingDungeonBarrenHints -= 1; - uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey(); - locationText = Hint(AreaTable(parentRegion)->hintKey).GetText(); - } else { - uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey(); - locationText = Hint(GetHintRegion(parentRegion)->hintKey).GetText(); } + + // form hint text + Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); Text finalBarrenHint = Hint(PREFIX).GetText() + Hint(PLUNDERING).GetText() + "#" + locationText + "#" + Hint(FOOLISH).GetText(); SPDLOG_DEBUG("\tMessage: "); @@ -414,16 +410,15 @@ static void CreateRandomLocationHint(const bool goodItem = false) { //form hint text Text itemText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText(); + Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); + // RANDOTODO: reconsider dungeon vs non-dungeon item location hints when boss shuffle mixed pools happens if (Location(hintedLocation)->IsDungeon()) { - uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey(); - Text locationText = AreaTable(parentRegion)->GetHint().GetText(); Text finalHint = Hint(PREFIX).GetText()+"#"+locationText+"# "+Hint(HOARDS).GetText()+" #"+itemText+"#."; SPDLOG_DEBUG("\tMessage: "); SPDLOG_DEBUG(finalHint.english); SPDLOG_DEBUG("\n\n"); AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}); } else { - Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); Text finalHint = Hint(PREFIX).GetText()+"#"+itemText+"# "+Hint(CAN_BE_FOUND_AT).GetText()+" #"+locationText+"#."; SPDLOG_DEBUG("\tMessage: "); SPDLOG_DEBUG(finalHint.english); @@ -546,7 +541,7 @@ static void CreateTrialHints() { } } -static void CreateGanonText() { +void CreateGanonText() { //funny ganon line ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); @@ -680,7 +675,7 @@ static Text BuildGanonBossKeyText() { return Text()+"$b"+ganonBossKeyText+"^"; } -static void CreateAltarText() { +void CreateAltarText() { //Child Altar Text childAltarText = Hint(SPIRITUAL_STONE_TEXT_START).GetText()+"^"+ @@ -737,6 +732,25 @@ void CreateMerchantsHints() { CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED})); } +void CreateDampesDiaryText() { + uint32_t item = PROGRESSIVE_HOOKSHOT; + uint32_t location = FilterFromPool(allLocations, [item](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == item;})[0]; + Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText(); + Text temp1 = Text{ + "Whoever reads this, please enter %g", + "Toi qui lit ce journal, rends-toi dans %g", + "Wer immer dies liest, der möge folgenden Ort aufsuchen: %g" + }; + + Text temp2 = { + "%w. I will let you have my stretching, shrinking keepsake.^I'm waiting for you.&--Dampé", + "%w. Et peut-être auras-tu droit à mon précieux %rtrésor%w.^Je t'attends...&--Igor", + "%w. Ihm gebe ich meinen langen, kurzen Schatz.^Ich warte!&Boris" + }; + + dampesText = temp1 + area + temp2; +} + void CreateWarpSongTexts() { auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false); @@ -777,9 +791,6 @@ void CreateWarpSongTexts() { void CreateAllHints() { - CreateGanonText(); - CreateAltarText(); - SPDLOG_DEBUG("\nNOW CREATING HINTS\n"); const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value()]; diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp index 568708a79b1..5e8df528661 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp @@ -221,11 +221,15 @@ extern uint32_t GetHintRegionHintKey(const uint32_t area); extern void CreateAllHints(); extern void CreateMerchantsHints(); extern void CreateWarpSongTexts(); +extern void CreateDampesDiaryText(); +extern void CreateGanonText(); +extern void CreateAltarText(); Text& GetChildAltarText(); Text& GetAdultAltarText(); Text& GetGanonText(); Text& GetGanonHintText(); +Text& GetDampeHintText(); Text& GetWarpMinuetText(); Text& GetWarpBoleroText(); diff --git a/soh/soh/Enhancements/randomizer/3drando/keys.hpp b/soh/soh/Enhancements/randomizer/3drando/keys.hpp index 46486299a4b..0016ff205d7 100644 --- a/soh/soh/Enhancements/randomizer/3drando/keys.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/keys.hpp @@ -1083,6 +1083,8 @@ typedef enum { DEATH_MOUNTAIN_CRATER, //AREAS + MARKER_AREAS_START, // Used for area key count + ROOT, ROOT_EXITS, CHILD_SPAWN, @@ -1263,6 +1265,16 @@ typedef enum { DEKU_TREE_BASEMENT_BACK_ROOM, DEKU_TREE_BASEMENT_UPPER, DEKU_TREE_OUTSIDE_BOSS_ROOM, + + DEKU_TREE_MQ_LOBBY, + DEKU_TREE_MQ_COMPASS_ROOM, + DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, + DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, + DEKU_TREE_MQ_BASEMENT_BACK_ROOM, + DEKU_TREE_MQ_BASEMENT_LEDGE, + DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, + + DEKU_TREE_BOSS_ENTRYWAY, DEKU_TREE_BOSS_ROOM, DODONGOS_CAVERN_BEGINNING, @@ -1287,6 +1299,14 @@ typedef enum { DODONGOS_CAVERN_FAR_BRIDGE, DODONGOS_CAVERN_BOSS_AREA, DODONGOS_CAVERN_BACK_ROOM, + + DODONGOS_CAVERN_MQ_BEGINNING, + DODONGOS_CAVERN_MQ_LOBBY, + DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, + DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, + DODONGOS_CAVERN_MQ_BOSS_AREA, + + DODONGOS_CAVERN_BOSS_ENTRYWAY, DODONGOS_CAVERN_BOSS_ROOM, JABU_JABUS_BELLY_BEGINNING, @@ -1306,6 +1326,13 @@ typedef enum { JABU_JABUS_BELLY_ABOVE_BIGOCTO, JABU_JABUS_BELLY_LIFT_UPPER, JABU_JABUS_BELLY_NEAR_BOSS_ROOM, + + JABU_JABUS_BELLY_MQ_BEGINNING, + JABU_JABUS_BELLY_MQ_MAIN, + JABU_JABUS_BELLY_MQ_DEPTHS, + JABU_JABUS_BELLY_MQ_BOSS_AREA, + + JABU_JABUS_BELLY_BOSS_ENTRYWAY, JABU_JABUS_BELLY_BOSS_ROOM, FOREST_TEMPLE_FIRST_ROOM, @@ -1335,11 +1362,24 @@ typedef enum { FOREST_TEMPLE_GREEN_POE_ROOM, FOREST_TEMPLE_EAST_CORRIDOR, FOREST_TEMPLE_BOSS_REGION, + + FOREST_TEMPLE_MQ_LOBBY, + FOREST_TEMPLE_MQ_CENTRAL_AREA, + FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, + FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, + FOREST_TEMPLE_MQ_NW_OUTDOORS, + FOREST_TEMPLE_MQ_NE_OUTDOORS, + FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, + FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, + FOREST_TEMPLE_MQ_BOW_REGION, + FOREST_TEMPLE_MQ_FALLING_ROOM, + FOREST_TEMPLE_MQ_BOSS_REGION, + + FOREST_TEMPLE_BOSS_ENTRYWAY, FOREST_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_FIRST_ROOM, FIRE_TEMPLE_NEAR_BOSS_ROOM, - FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_LOOP_ENEMIES, FIRE_TEMPLE_LOOP_TILES, FIRE_TEMPLE_LOOP_FLARE_DANCER, @@ -1374,6 +1414,16 @@ typedef enum { FIRE_TEMPLE_HAMMER_RETURN_PATH, FIRE_TEMPLE_ABOVE_FIRE_MAZE, + FIRE_TEMPLE_MQ_LOWER, + FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, + FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, + FIRE_TEMPLE_MQ_LOWER_MAZE, + FIRE_TEMPLE_MQ_UPPER_MAZE, + FIRE_TEMPLE_MQ_UPPER, + + FIRE_TEMPLE_BOSS_ENTRYWAY, + FIRE_TEMPLE_BOSS_ROOM, + WATER_TEMPLE_LOBBY, WATER_TEMPLE_EAST_LOWER, WATER_TEMPLE_MAP_ROOM, @@ -1401,6 +1451,14 @@ typedef enum { WATER_TEMPLE_LONGSHOT_ROOM, WATER_TEMPLE_RIVER, WATER_TEMPLE_PRE_BOSS_ROOM, + + WATER_TEMPLE_MQ_LOBBY, + WATER_TEMPLE_MQ_DIVE, + WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, + WATER_TEMPLE_MQ_DARK_LINK_REGION, + WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, + + WATER_TEMPLE_BOSS_ENTRYWAY, WATER_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_LOBBY, @@ -1411,82 +1469,7 @@ typedef enum { SPIRIT_TEMPLE_OUTDOOR_HANDS, SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, - - SHADOW_TEMPLE_BEGINNING, - SHADOW_TEMPLE_FIRST_BEAMOS, - SHADOW_TEMPLE_HUGE_PIT, - SHADOW_TEMPLE_WIND_TUNNEL, - SHADOW_TEMPLE_BEYOND_BOAT, - - BOTTOM_OF_THE_WELL, - BOTTOM_OF_THE_WELL_MAIN_AREA, - - ICE_CAVERN_BEGINNING, - ICE_CAVERN_MAIN, - - GERUDO_TRAINING_GROUNDS_LOBBY, - GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, - GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, - GERUDO_TRAINING_GROUNDS_LAVA_ROOM, - GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, - GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, - GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, - GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, - GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, - - GANONS_CASTLE_LOBBY, - GANONS_CASTLE_DEKU_SCRUBS, - GANONS_CASTLE_FOREST_TRIAL, - GANONS_CASTLE_FIRE_TRIAL, - GANONS_CASTLE_WATER_TRIAL, - GANONS_CASTLE_SHADOW_TRIAL, - GANONS_CASTLE_SPIRIT_TRIAL, - GANONS_CASTLE_LIGHT_TRIAL, - GANONS_CASTLE_TOWER, - - DEKU_TREE_MQ_LOBBY, - DEKU_TREE_MQ_COMPASS_ROOM, - DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, - DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, - DEKU_TREE_MQ_BASEMENT_BACK_ROOM, - DEKU_TREE_MQ_BASEMENT_LEDGE, - - DODONGOS_CAVERN_MQ_BEGINNING, - DODONGOS_CAVERN_MQ_LOBBY, - DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, - DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, - DODONGOS_CAVERN_MQ_BOSS_AREA, - - JABU_JABUS_BELLY_MQ_BEGINNING, - JABU_JABUS_BELLY_MQ_MAIN, - JABU_JABUS_BELLY_MQ_DEPTHS, - JABU_JABUS_BELLY_MQ_BOSS_AREA, - - FOREST_TEMPLE_MQ_LOBBY, - FOREST_TEMPLE_MQ_CENTRAL_AREA, - FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, - FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, - FOREST_TEMPLE_MQ_NW_OUTDOORS, - FOREST_TEMPLE_MQ_NE_OUTDOORS, - FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, - FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, - FOREST_TEMPLE_MQ_BOW_REGION, - FOREST_TEMPLE_MQ_FALLING_ROOM, - FOREST_TEMPLE_MQ_BOSS_REGION, - - FIRE_TEMPLE_MQ_LOWER, - FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, - FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, - FIRE_TEMPLE_MQ_LOWER_MAZE, - FIRE_TEMPLE_MQ_UPPER_MAZE, - FIRE_TEMPLE_MQ_UPPER, - FIRE_TEMPLE_MQ_BOSS_ROOM, - - WATER_TEMPLE_MQ_LOBBY, - WATER_TEMPLE_MQ_DIVE, - WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, - WATER_TEMPLE_MQ_DARK_LINK_REGION, - WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, + SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, SPIRIT_TEMPLE_MQ_LOBBY, SPIRIT_TEMPLE_MQ_CHILD, @@ -1496,6 +1479,16 @@ typedef enum { SPIRIT_TEMPLE_MQ_BOSS_AREA, SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, + SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, + + SPIRIT_TEMPLE_BOSS_ENTRYWAY, + SPIRIT_TEMPLE_BOSS_ROOM, + + SHADOW_TEMPLE_BEGINNING, + SHADOW_TEMPLE_FIRST_BEAMOS, + SHADOW_TEMPLE_HUGE_PIT, + SHADOW_TEMPLE_WIND_TUNNEL, + SHADOW_TEMPLE_BEYOND_BOAT, SHADOW_TEMPLE_MQ_ENTRYWAY, SHADOW_TEMPLE_MQ_BEGINNING, @@ -1507,15 +1500,32 @@ typedef enum { SHADOW_TEMPLE_MQ_BEYOND_BOAT, SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, - BOTTOM_OF_THE_WELL_MQ, + SHADOW_TEMPLE_BOSS_ENTRYWAY, + SHADOW_TEMPLE_BOSS_ROOM, + + BOTTOM_OF_THE_WELL_MAIN_AREA, + BOTTOM_OF_THE_WELL_MQ_PERIMETER, BOTTOM_OF_THE_WELL_MQ_MIDDLE, + ICE_CAVERN_BEGINNING, + ICE_CAVERN_MAIN, + ICE_CAVERN_MQ_BEGINNING, ICE_CAVERN_MQ_MAP_ROOM, ICE_CAVERN_MQ_IRON_BOOTS_REGION, ICE_CAVERN_MQ_COMPASS_ROOM, + GERUDO_TRAINING_GROUNDS_LOBBY, + GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, + GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, + GERUDO_TRAINING_GROUNDS_LAVA_ROOM, + GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, + GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, + GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, + GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, + GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, + GERUDO_TRAINING_GROUNDS_MQ_LOBBY, GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, @@ -1524,6 +1534,16 @@ typedef enum { GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT, + GANONS_CASTLE_LOBBY, + GANONS_CASTLE_DEKU_SCRUBS, + GANONS_CASTLE_FOREST_TRIAL, + GANONS_CASTLE_FIRE_TRIAL, + GANONS_CASTLE_WATER_TRIAL, + GANONS_CASTLE_SHADOW_TRIAL, + GANONS_CASTLE_SPIRIT_TRIAL, + GANONS_CASTLE_LIGHT_TRIAL, + GANONS_CASTLE_TOWER, + GANONS_CASTLE_MQ_LOBBY, GANONS_CASTLE_MQ_DEKU_SCRUBS, GANONS_CASTLE_MQ_FOREST_TRIAL, @@ -1533,6 +1553,8 @@ typedef enum { GANONS_CASTLE_MQ_SPIRIT_TRIAL, GANONS_CASTLE_MQ_LIGHT_TRIAL, + MARKER_AREAS_END, // Used for area key count + //DUNGEONS DEKU_TREE, DODONGOS_CAVERN, @@ -1542,8 +1564,8 @@ typedef enum { WATER_TEMPLE, SPIRIT_TEMPLE, SHADOW_TEMPLE, + BOTTOM_OF_THE_WELL, ICE_CAVERN, - //BOTTOM_OF_THE_WELL, GERUDO_TRAINING_GROUNDS, GANONS_CASTLE, @@ -1762,6 +1784,7 @@ typedef enum { VALIDATION_LINE, LIGHT_ARROW_LOCATION_HINT, + DAMPE_DIARY, YOUR_POCKET, GANON_LINE01, diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index e77d7943c7f..cefa5229f01 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -371,458 +371,24 @@ void AreaTable_Init() { namespace Areas { - static std::array allAreas = { - ROOT, - ROOT_EXITS, - - CHILD_SPAWN, - ADULT_SPAWN, - MINUET_OF_FOREST_WARP, - BOLERO_OF_FIRE_WARP, - SERENADE_OF_WATER_WARP, - REQUIEM_OF_SPIRIT_WARP, - NOCTURNE_OF_SHADOW_WARP, - PRELUDE_OF_LIGHT_WARP, - - KOKIRI_FOREST, - KF_LINKS_HOUSE, - KF_MIDOS_HOUSE, - KF_SARIAS_HOUSE, - KF_HOUSE_OF_TWINS, - KF_KNOW_IT_ALL_HOUSE, - KF_KOKIRI_SHOP, - KF_STORMS_GROTTO, - KF_OUTSIDE_DEKU_TREE, - DEKU_TREE_ENTRYWAY, - - THE_LOST_WOODS, - LW_BRIDGE_FROM_FOREST, - LW_BRIDGE, - LW_FOREST_EXIT, - LW_BEYOND_MIDO, - LW_NEAR_SHORTCUTS_GROTTO, - DEKU_THEATER, - LW_SCRUBS_GROTTO, - SFM_ENTRYWAY, - SACRED_FOREST_MEADOW, - SFM_WOLFOS_GROTTO, - SFM_FAIRY_GROTTO, - SFM_STORMS_GROTTO, - FOREST_TEMPLE_ENTRYWAY, - - KAKARIKO_VILLAGE, - KAK_CARPENTER_BOSS_HOUSE, - KAK_HOUSE_OF_SKULLTULA, - KAK_IMPAS_HOUSE, - KAK_IMPAS_LEDGE, - KAK_IMPAS_HOUSE_BACK, - KAK_IMPAS_HOUSE_NEAR_COW, - KAK_WINDMILL, - KAK_BAZAAR, - KAK_SHOOTING_GALLERY, - KAK_POTION_SHOP_FRONT, - KAK_POTION_SHOP_BACK, - KAK_ROOFTOP, - KAK_IMPAS_ROOFTOP, - KAK_BEHIND_GATE, - KAK_BACKYARD, - KAK_ODD_POTION_BUILDING, - KAK_REDEAD_GROTTO, - KAK_OPEN_GROTTO, - BOTTOM_OF_THE_WELL_ENTRYWAY, - - THE_GRAVEYARD, - GRAVEYARD_DAMPES_GRAVE, - GRAVEYARD_DAMPES_HOUSE, - GRAVEYARD_SHIELD_GRAVE, - GRAVEYARD_COMPOSERS_GRAVE, - GRAVEYARD_HEART_PIECE_GRAVE, - GRAVEYARD_WARP_PAD_REGION, - SHADOW_TEMPLE_ENTRYWAY, - - DEATH_MOUNTAIN_TRAIL, - DEATH_MOUNTAIN_SUMMIT, - DMT_OWL_FLIGHT, - DMT_GREAT_FAIRY_FOUNTAIN, - DMT_COW_GROTTO, - DMT_STORMS_GROTTO, - DODONGOS_CAVERN_ENTRYWAY, - - DMC_UPPER_LOCAL, - DMC_CENTRAL_LOCAL, - DMC_LOWER_LOCAL, - DMC_LOWER_NEARBY, - DMC_UPPER_NEARBY, - DMC_CENTRAL_NEARBY, - DMC_LADDER_AREA_NEARBY, - DMC_UPPER_GROTTO, - DMC_HAMMER_GROTTO, - DMC_GREAT_FAIRY_FOUNTAIN, - FIRE_TEMPLE_ENTRYWAY, - - GORON_CITY, - GC_WOODS_WARP, - GC_DARUNIAS_CHAMBER, - GC_GROTTO_PLATFORM, - GC_SHOP, - GC_GROTTO, - - ZR_FRONT, - ZORAS_RIVER, - ZR_BEHIND_WATERFALL, - ZR_OPEN_GROTTO, - ZR_FAIRY_GROTTO, - ZR_STORMS_GROTTO, - ZORAS_DOMAIN, - ZD_BEHIND_KING_ZORA, - ZD_SHOP, - ZD_STORMS_GROTTO, - ZORAS_FOUNTAIN, - ZF_GREAT_FAIRY_FOUNTAIN, - JABU_JABUS_BELLY_ENTRYWAY, - ICE_CAVERN_ENTRYWAY, - - HYRULE_FIELD, - HF_SOUTHEAST_GROTTO, - HF_OPEN_GROTTO, - HF_INSIDE_FENCE_GROTTO, - HF_COW_GROTTO, - HF_NEAR_MARKET_GROTTO, - HF_FAIRY_GROTTO, - HF_NEAR_KAK_GROTTO, - HF_TEKTITE_GROTTO, - - LON_LON_RANCH, - LLR_TALONS_HOUSE, - LLR_STABLES, - LLR_TOWER, - LLR_GROTTO, - - LAKE_HYLIA, - LH_OWL_FLIGHT, - LH_LAB, - LH_FISHING_ISLAND, - LH_FISHING_HOLE, - LH_GROTTO, - WATER_TEMPLE_ENTRYWAY, - - GERUDO_VALLEY, - GV_UPPER_STREAM, - GV_LOWER_STREAM, - GV_GROTTO_LEDGE, - GV_CRATE_LEDGE, - GV_OCTOROK_GROTTO, - GV_FORTRESS_SIDE, - GV_CARPENTER_TENT, - GV_STORMS_GROTTO, - GERUDO_FORTRESS, - GF_OUTSIDE_GATE, - GF_STORMS_GROTTO, - GERUDO_TRAINING_GROUNDS_ENTRYWAY, - - WASTELAND_NEAR_FORTRESS, - HAUNTED_WASTELAND, - WASTELAND_NEAR_COLOSSUS, - DESERT_COLOSSUS, - DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, - COLOSSUS_GREAT_FAIRY_FOUNTAIN, - COLOSSUS_GROTTO, - SPIRIT_TEMPLE_ENTRYWAY, - - MARKET_ENTRANCE, - THE_MARKET, - MARKET_GUARD_HOUSE, - MARKET_BAZAAR, - MARKET_MASK_SHOP, - MARKET_SHOOTING_GALLERY, - MARKET_BOMBCHU_BOWLING, - MARKET_TREASURE_CHEST_GAME, - MARKET_POTION_SHOP, - MARKET_BACK_ALLEY, - MARKET_BOMBCHU_SHOP, - MARKET_DOG_LADY_HOUSE, - MARKET_MAN_IN_GREEN_HOUSE, - TOT_ENTRANCE, - TEMPLE_OF_TIME, - TOT_BEYOND_DOOR_OF_TIME, - - CASTLE_GROUNDS, - HYRULE_CASTLE_GROUNDS, - HC_GARDEN, - HC_GREAT_FAIRY_FOUNTAIN, - HC_STORMS_GROTTO, - GANONS_CASTLE_GROUNDS, - OGC_GREAT_FAIRY_FOUNTAIN, - GANONS_CASTLE_ENTRYWAY, - - DEKU_TREE_LOBBY, - DEKU_TREE_2F_MIDDLE_ROOM, - DEKU_TREE_SLINGSHOT_ROOM, - DEKU_TREE_COMPASS_ROOM, - DEKU_TREE_BASEMENT_LOWER, - DEKU_TREE_BASEMENT_SCRUB_ROOM, - DEKU_TREE_BASEMENT_WATER_ROOM, - DEKU_TREE_BASEMENT_TORCH_ROOM, - DEKU_TREE_BASEMENT_BACK_LOBBY, - DEKU_TREE_BASEMENT_BACK_ROOM, - DEKU_TREE_BASEMENT_UPPER, - DEKU_TREE_OUTSIDE_BOSS_ROOM, - DEKU_TREE_BOSS_ROOM, - - DODONGOS_CAVERN_BEGINNING, - DODONGOS_CAVERN_LOBBY, - DODONGOS_CAVERN_LOBBY_SWITCH, - DODONGOS_CAVERN_SE_CORRIDOR, - DODONGOS_CAVERN_SE_ROOM, - DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, - DODONGOS_CAVERN_LOWER_LIZALFOS, - DODONGOS_CAVERN_DODONGO_ROOM, - DODONGOS_CAVERN_NEAR_DODONGO_ROOM, - DODONGOS_CAVERN_STAIRS_LOWER, - DODONGOS_CAVERN_STAIRS_UPPER, - DODONGOS_CAVERN_COMPASS_ROOM, - DODONGOS_CAVERN_ARMOS_ROOM, - DODONGOS_CAVERN_BOMB_ROOM_LOWER, - DODONGOS_CAVERN_2F_SIDE_ROOM, - DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, - DODONGOS_CAVERN_UPPER_LIZALFOS, - DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, - DODONGOS_CAVERN_BOMB_ROOM_UPPER, - DODONGOS_CAVERN_FAR_BRIDGE, - DODONGOS_CAVERN_BOSS_AREA, - DODONGOS_CAVERN_BACK_ROOM, - DODONGOS_CAVERN_BOSS_ROOM, - - JABU_JABUS_BELLY_BEGINNING, - JABU_JABUS_BELLY_LIFT_MIDDLE, - JABU_JABUS_BELLY_MAIN_UPPER, - JABU_JABUS_BELLY_MAIN_LOWER, - JABU_JABUS_BELLY_SHABOMB_CORRIDOR, - JABU_JABUS_BELLY_LOWER_SIDE_ROOM, - JABU_JABUS_BELLY_LIFT_LOWER, - JABU_JABUS_BELLY_FORKED_CORRIDOR, - JABU_JABUS_BELLY_BOOMERANG_ROOM, - JABU_JABUS_BELLY_MAP_ROOM, - JABU_JABUS_BELLY_COMPASS_ROOM, - JABU_JABUS_BELLY_BLUE_TENTACLE, - JABU_JABUS_BELLY_GREEN_TENTACLE, - JABU_JABUS_BELLY_BIGOCTO_ROOM, - JABU_JABUS_BELLY_ABOVE_BIGOCTO, - JABU_JABUS_BELLY_LIFT_UPPER, - JABU_JABUS_BELLY_NEAR_BOSS_ROOM, - JABU_JABUS_BELLY_BOSS_ROOM, - - FOREST_TEMPLE_FIRST_ROOM, - FOREST_TEMPLE_SOUTH_CORRIDOR, - FOREST_TEMPLE_LOBBY, - FOREST_TEMPLE_NORTH_CORRIDOR, - FOREST_TEMPLE_LOWER_STALFOS, - FOREST_TEMPLE_NW_OUTDOORS_LOWER, - FOREST_TEMPLE_NW_OUTDOORS_UPPER, - FOREST_TEMPLE_NE_OUTDOORS_LOWER, - FOREST_TEMPLE_NE_OUTDOORS_UPPER, - FOREST_TEMPLE_MAP_ROOM, - FOREST_TEMPLE_SEWER, - FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, - FOREST_TEMPLE_FLOORMASTER_ROOM, - FOREST_TEMPLE_WEST_CORRIDOR, - FOREST_TEMPLE_BLOCK_PUSH_ROOM, - FOREST_TEMPLE_NW_CORRIDOR_TWISTED, - FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, - FOREST_TEMPLE_RED_POE_ROOM, - FOREST_TEMPLE_UPPER_STALFOS, - FOREST_TEMPLE_BLUE_POE_ROOM, - FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, - FOREST_TEMPLE_NE_CORRIDOR_TWISTED, - FOREST_TEMPLE_FROZEN_EYE_ROOM, - FOREST_TEMPLE_FALLING_ROOM, - FOREST_TEMPLE_GREEN_POE_ROOM, - FOREST_TEMPLE_EAST_CORRIDOR, - FOREST_TEMPLE_BOSS_REGION, - FOREST_TEMPLE_BOSS_ROOM, - - FIRE_TEMPLE_FIRST_ROOM, - FIRE_TEMPLE_NEAR_BOSS_ROOM, - FIRE_TEMPLE_BOSS_ROOM, - FIRE_TEMPLE_LOOP_ENEMIES, - FIRE_TEMPLE_LOOP_TILES, - FIRE_TEMPLE_LOOP_FLARE_DANCER, - FIRE_TEMPLE_LOOP_HAMMER_SWITCH, - FIRE_TEMPLE_LOOP_GORON_ROOM, - FIRE_TEMPLE_LOOP_EXIT, - FIRE_TEMPLE_BIG_LAVA_ROOM, - FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, - FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, - FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, - FIRE_TEMPLE_FIRE_PILLAR_ROOM, - FIRE_TEMPLE_SHORTCUT_ROOM, - FIRE_TEMPLE_SHORTCUT_CLIMB, - FIRE_TEMPLE_BOULDER_MAZE_LOWER, - FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM, - FIRE_TEMPLE_EAST_CENTRAL_ROOM, - FIRE_TEMPLE_FIRE_WALL_CHASE, - FIRE_TEMPLE_MAP_AREA, - FIRE_TEMPLE_BOULDER_MAZE_UPPER, - FIRE_TEMPLE_SCARECROW_ROOM, - FIRE_TEMPLE_EAST_PEAK, - FIRE_TEMPLE_CORRIDOR, - FIRE_TEMPLE_FIRE_MAZE_ROOM, - FIRE_TEMPLE_FIRE_MAZE_UPPER, - FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, - FIRE_TEMPLE_WEST_CENTRAL_LOWER, - FIRE_TEMPLE_WEST_CENTRAL_UPPER, - FIRE_TEMPLE_LATE_FIRE_MAZE, - FIRE_TEMPLE_UPPER_FLARE_DANCER, - FIRE_TEMPLE_WEST_CLIMB, - FIRE_TEMPLE_WEST_PEAK, - FIRE_TEMPLE_HAMMER_RETURN_PATH, - FIRE_TEMPLE_ABOVE_FIRE_MAZE, - - WATER_TEMPLE_LOBBY, - WATER_TEMPLE_EAST_LOWER, - WATER_TEMPLE_MAP_ROOM, - WATER_TEMPLE_CRACKED_WALL, - WATER_TEMPLE_TORCH_ROOM, - WATER_TEMPLE_NORTH_LOWER, - WATER_TEMPLE_BOULDERS_LOWER, - WATER_TEMPLE_BLOCK_ROOM, - WATER_TEMPLE_JETS_ROOM, - WATER_TEMPLE_BOULDERS_UPPER, - WATER_TEMPLE_BOSS_KEY_ROOM, - WATER_TEMPLE_SOUTH_LOWER, - WATER_TEMPLE_WEST_LOWER, - WATER_TEMPLE_DRAGON_ROOM, - WATER_TEMPLE_CENTRAL_PILLAR_LOWER, - WATER_TEMPLE_CENTRAL_PILLAR_UPPER, - WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, - WATER_TEMPLE_EAST_MIDDLE, - WATER_TEMPLE_WEST_MIDDLE, - WATER_TEMPLE_HIGH_WATER, - WATER_TEMPLE_BLOCK_CORRIDOR, - WATER_TEMPLE_FALLING_PLATFORM_ROOM, - WATER_TEMPLE_DRAGON_PILLARS_ROOM, - WATER_TEMPLE_DARK_LINK_ROOM, - WATER_TEMPLE_LONGSHOT_ROOM, - WATER_TEMPLE_RIVER, - WATER_TEMPLE_PRE_BOSS_ROOM, - WATER_TEMPLE_BOSS_ROOM, - - SPIRIT_TEMPLE_LOBBY, - SPIRIT_TEMPLE_CHILD, - SPIRIT_TEMPLE_CHILD_CLIMB, - SPIRIT_TEMPLE_EARLY_ADULT, - SPIRIT_TEMPLE_CENTRAL_CHAMBER, - SPIRIT_TEMPLE_OUTDOOR_HANDS, - SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, - SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, - SHADOW_TEMPLE_BEGINNING, - SHADOW_TEMPLE_FIRST_BEAMOS, - SHADOW_TEMPLE_HUGE_PIT, - SHADOW_TEMPLE_WIND_TUNNEL, - SHADOW_TEMPLE_BEYOND_BOAT, - BOTTOM_OF_THE_WELL, - BOTTOM_OF_THE_WELL_MAIN_AREA, - ICE_CAVERN_BEGINNING, - ICE_CAVERN_MAIN, - GERUDO_TRAINING_GROUNDS_LOBBY, - GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, - GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, - GERUDO_TRAINING_GROUNDS_LAVA_ROOM, - GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, - GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, - GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, - GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, - GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, - GANONS_CASTLE_LOBBY, - GANONS_CASTLE_DEKU_SCRUBS, - GANONS_CASTLE_FOREST_TRIAL, - GANONS_CASTLE_FIRE_TRIAL, - GANONS_CASTLE_WATER_TRIAL, - GANONS_CASTLE_SHADOW_TRIAL, - GANONS_CASTLE_SPIRIT_TRIAL, - GANONS_CASTLE_LIGHT_TRIAL, - GANONS_CASTLE_TOWER, - DEKU_TREE_MQ_LOBBY, - DEKU_TREE_MQ_COMPASS_ROOM, - DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, - DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, - DEKU_TREE_MQ_BASEMENT_BACK_ROOM, - DEKU_TREE_MQ_BASEMENT_LEDGE, - DODONGOS_CAVERN_MQ_BEGINNING, - DODONGOS_CAVERN_MQ_LOBBY, - DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, - DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, - DODONGOS_CAVERN_MQ_BOSS_AREA, - JABU_JABUS_BELLY_MQ_BEGINNING, - JABU_JABUS_BELLY_MQ_MAIN, - JABU_JABUS_BELLY_MQ_DEPTHS, - JABU_JABUS_BELLY_MQ_BOSS_AREA, - FOREST_TEMPLE_MQ_LOBBY, - FOREST_TEMPLE_MQ_CENTRAL_AREA, - FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, - FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, - FOREST_TEMPLE_MQ_NW_OUTDOORS, - FOREST_TEMPLE_MQ_NE_OUTDOORS, - FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, - FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, - FOREST_TEMPLE_MQ_BOW_REGION, - FOREST_TEMPLE_MQ_FALLING_ROOM, - FOREST_TEMPLE_MQ_BOSS_REGION, - FIRE_TEMPLE_MQ_LOWER, - FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, - FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, - FIRE_TEMPLE_MQ_LOWER_MAZE, - FIRE_TEMPLE_MQ_UPPER_MAZE, - FIRE_TEMPLE_MQ_UPPER, - FIRE_TEMPLE_MQ_BOSS_ROOM, - WATER_TEMPLE_MQ_LOBBY, - WATER_TEMPLE_MQ_DIVE, - WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, - WATER_TEMPLE_MQ_DARK_LINK_REGION, - WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, - SPIRIT_TEMPLE_MQ_LOBBY, - SPIRIT_TEMPLE_MQ_CHILD, - SPIRIT_TEMPLE_MQ_ADULT, - SPIRIT_TEMPLE_MQ_SHARED, - SPIRIT_TEMPLE_MQ_LOWER_ADULT, - SPIRIT_TEMPLE_MQ_BOSS_AREA, - SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, - SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, - SHADOW_TEMPLE_MQ_ENTRYWAY, - SHADOW_TEMPLE_MQ_BEGINNING, - SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, - SHADOW_TEMPLE_MQ_FIRST_BEAMOS, - SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, - SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, - SHADOW_TEMPLE_MQ_WIND_TUNNEL, - SHADOW_TEMPLE_MQ_BEYOND_BOAT, - SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, - BOTTOM_OF_THE_WELL_MQ, - BOTTOM_OF_THE_WELL_MQ_PERIMETER, - BOTTOM_OF_THE_WELL_MQ_MIDDLE, - ICE_CAVERN_MQ_BEGINNING, - ICE_CAVERN_MQ_MAP_ROOM, - ICE_CAVERN_MQ_IRON_BOOTS_REGION, - ICE_CAVERN_MQ_COMPASS_ROOM, - GERUDO_TRAINING_GROUNDS_MQ_LOBBY, - GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, - GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, - GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE, - GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, - GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, - GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT, - GANONS_CASTLE_MQ_LOBBY, - GANONS_CASTLE_MQ_DEKU_SCRUBS, - GANONS_CASTLE_MQ_FOREST_TRIAL, - GANONS_CASTLE_MQ_FIRE_TRIAL, - GANONS_CASTLE_MQ_WATER_TRIAL, - GANONS_CASTLE_MQ_SHADOW_TRIAL, - GANONS_CASTLE_MQ_SPIRIT_TRIAL, - GANONS_CASTLE_MQ_LIGHT_TRIAL, - }; + const auto GetAllAreas() { + static const size_t areaCount = MARKER_AREAS_END - (MARKER_AREAS_START + 1); + + static std::array allAreas = {}; + + static bool intialized = false; + if (!intialized) { + for (size_t i = 0; i < areaCount; i++) { + allAreas[i] = (MARKER_AREAS_START + 1) + i; + } + intialized = true; + } + + return allAreas; + } void AccessReset() { - for (const uint32_t area : allAreas) { + for (const uint32_t area : GetAllAreas()) { AreaTable(area)->ResetVariables(); } @@ -843,7 +409,7 @@ namespace Areas { //Reset exits and clear items from locations void ResetAllLocations() { - for (const uint32_t area : allAreas) { + for (const uint32_t area : GetAllAreas()) { AreaTable(area)->ResetVariables(); //Erase item from every location in this exit for (LocationAccess& locPair : AreaTable(area)->locations) { @@ -868,7 +434,7 @@ namespace Areas { } bool HasTimePassAccess(uint8_t age) { - for (const uint32_t areaKey : allAreas) { + for (const uint32_t areaKey : GetAllAreas()) { auto area = AreaTable(areaKey); if (area->timePass && ((age == AGE_CHILD && area->Child()) || (age == AGE_ADULT && area->Adult()))) { return true; @@ -886,7 +452,7 @@ namespace Areas { worldGraph.open (str + ".dot"); worldGraph << "digraph {\n\tcenter=true;\n"; - for (const uint32_t areaKey : allAreas) { + for (const uint32_t areaKey : GetAllAreas()) { auto area = AreaTable(areaKey); for (auto exit : area->exits) { if (exit.GetConnectedRegion()->regionName != "Invalid Area") { @@ -939,7 +505,7 @@ Area* AreaTable(const uint32_t areaKey) { //Retrieve all the shuffable entrances of a specific type std::vector GetShuffleableEntrances(EntranceType type, bool onlyPrimary /*= true*/) { std::vector entrancesToShuffle = {}; - for (uint32_t area : Areas::allAreas) { + for (uint32_t area : Areas::GetAllAreas()) { for (auto& exit: AreaTable(area)->exits) { if ((exit.GetType() == type || type == EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != EntranceType::None) { entrancesToShuffle.push_back(&exit); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp index c67e5d3bddc..9f22eea63f9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp @@ -38,7 +38,7 @@ void AreaTable_Init_DekuTree() { /*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}), Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}, /*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE);}}), - Entrance(DEKU_TREE_BOSS_ROOM, {[]{return false;}, + Entrance(DEKU_TREE_BOSS_ENTRYWAY, {[]{return false;}, /*Glitched*/[]{return IsChild && CanUse(KOKIRI_SWORD) && Nuts && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::EXPERT);}}), }); @@ -72,7 +72,7 @@ void AreaTable_Init_DekuTree() { }, { //Exits Entrance(DEKU_TREE_LOBBY, {[]{return HasFireSourceWithTorch || CanUse(BOW);}}), - Entrance(DEKU_TREE_BOSS_ROOM, {[]{return false;}, + Entrance(DEKU_TREE_BOSS_ENTRYWAY, {[]{return false;}, /*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED);}}), }); @@ -161,21 +161,7 @@ void AreaTable_Init_DekuTree() { areaTable[DEKU_TREE_OUTSIDE_BOSS_ROOM] = Area("Deku Tree Outside Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(DEKU_TREE_BASEMENT_UPPER, {[]{return true;}}), - Entrance(DEKU_TREE_BOSS_ROOM, {[]{return Here(DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return HasShield;});}}), - }); - - areaTable[DEKU_TREE_BOSS_ROOM] = Area("Deku Tree Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&DekuTreeClear, {[]{return DekuTreeClear || ((IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang));}, - /*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}), - }, { - //Locations - LocationAccess(QUEEN_GOHMA, {[]{return DekuTreeClear;}}), - LocationAccess(DEKU_TREE_QUEEN_GOHMA_HEART, {[]{return DekuTreeClear;}}), - }, { - //Exits - Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return true;}}), - Entrance(DEKU_TREE_ENTRYWAY, {[]{return DekuTreeClear;}}), + Entrance(DEKU_TREE_BOSS_ENTRYWAY, {[]{return Here(DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return HasShield;});}}), }); } @@ -261,6 +247,51 @@ void AreaTable_Init_DekuTree() { //Exits Entrance(DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return IsChild;}}), Entrance(DEKU_TREE_MQ_LOBBY, {[]{return true;}}), + Entrance(DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, + { [] { return Here(DEKU_TREE_MQ_BASEMENT_LEDGE, [] { return HasFireSourceWithTorch; }); } }), }); + + areaTable[DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM] = + Area("Deku Tree MQ Outside Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(DEKU_TREE_MQ_BASEMENT_LEDGE, { [] { return true; } }), + Entrance(DEKU_TREE_BOSS_ENTRYWAY, + { [] { return Here(DEKU_TREE_MQ_BASEMENT_LEDGE, [] { return HasShield; }); } }), + }); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[DEKU_TREE_BOSS_ENTRYWAY] = + Area("Deku Tree Boss Entryway", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsVanilla(); } }), + Entrance(DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsMQ(); } }), + Entrance(DEKU_TREE_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[DEKU_TREE_BOSS_ROOM] = + Area("Deku Tree Boss Room", "Deku Tree", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&DekuTreeClear, { [] { + return DekuTreeClear || + (CanJumpslash && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || + HookshotOrBoomerang)); + }, + /*Glitched*/ + [] { return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE); } }), + }, + { + // Locations + LocationAccess(QUEEN_GOHMA, { [] { return DekuTreeClear; } }), + LocationAccess(DEKU_TREE_QUEEN_GOHMA_HEART, { [] { return DekuTreeClear; } }), + }, + { + // Exits + Entrance(DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp index 6c57b161b34..fa698507732 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp @@ -50,7 +50,7 @@ void AreaTable_Init_DodongosCavern() { Entrance(DODONGOS_CAVERN_FAR_BRIDGE, {[]{return HasAccessTo(DODONGOS_CAVERN_FAR_BRIDGE);}, /*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE);}}), Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return HasExplosives;});}}), - Entrance(DODONGOS_CAVERN_BOSS_ROOM, {[]{return false;}, + Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY,{[]{return false;}, /*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED);}}), }); @@ -220,7 +220,7 @@ void AreaTable_Init_DodongosCavern() { Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}), Entrance(DODONGOS_CAVERN_BACK_ROOM, {[]{return Here(DODONGOS_CAVERN_BOSS_AREA, []{return CanBlastOrSmash;});}, /*Glitched*/[]{return Here(DODONGOS_CAVERN_BOSS_AREA, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));});}}), - Entrance(DODONGOS_CAVERN_BOSS_ROOM, {[]{return true;}}), + Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}), }); areaTable[DODONGOS_CAVERN_BACK_ROOM] = Area("Dodongos Cavern Back Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, { @@ -231,21 +231,6 @@ void AreaTable_Init_DodongosCavern() { //Exits Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}), }); - - areaTable[DODONGOS_CAVERN_BOSS_ROOM] = Area("Dodongos Cavern Boss Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&DodongosCavernClear, {[]{return DodongosCavernClear || (Here(DODONGOS_CAVERN_BOSS_ROOM, []{return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield);}) && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword));}, - /*Glitched*/[]{return Here(DODONGOS_CAVERN_BOSS_ROOM, []{return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield) || (GlitchBlueFireWall && HasBottle && BlueFireAccess);}) && (HasExplosives || GoronBracelet) && (IsAdult || Sticks || KokiriSword || CanUse(MEGATON_HAMMER));}}), - }, { - //Locations - LocationAccess(DODONGOS_CAVERN_BOSS_ROOM_CHEST, {[]{return true;}}), - LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, {[]{return DodongosCavernClear;}}), - LocationAccess(KING_DODONGO, {[]{return DodongosCavernClear;}}), - }, { - //Exits - Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}), - Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return DodongosCavernClear;}}), - }); } /*--------------------------- @@ -314,6 +299,53 @@ void AreaTable_Init_DodongosCavern() { LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, {[]{return CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword);}}), LocationAccess(KING_DODONGO, {[]{return CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword);}}), LocationAccess(DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}), - }, {}); + }, { + //Exits + Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}), + }); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[DODONGOS_CAVERN_BOSS_ENTRYWAY] = + Area("Dodongos Cavern Boss Entryway", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(DODONGOS_CAVERN_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsVanilla(); } }), + Entrance(DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsMQ(); } }), + Entrance(DODONGOS_CAVERN_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[DODONGOS_CAVERN_BOSS_ROOM] = + Area("Dodongos Cavern Boss Room", "Dodongos Cavern", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&DodongosCavernClear, + { [] { + return DodongosCavernClear || + (Here(DODONGOS_CAVERN_BOSS_ROOM, + [] { return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield); }) && + (Bombs || GoronBracelet) && CanJumpslash); + }, + /*Glitched*/ + [] { + return Here(DODONGOS_CAVERN_BOSS_ROOM, + [] { + return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield) || + (GlitchBlueFireWall && BlueFire); + }) && + (HasExplosives || GoronBracelet) && CanJumpslash; + } }), + }, + { + // Locations + LocationAccess(DODONGOS_CAVERN_BOSS_ROOM_CHEST, { [] { return true; } }), + LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, { [] { return DodongosCavernClear; } }), + LocationAccess(KING_DODONGO, { [] { return DodongosCavernClear; } }), + }, + { + // Exits + Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp index ae3c0837445..3cbd1c6a71c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp @@ -42,25 +42,11 @@ void AreaTable_Init_FireTemple() { }, { //Exits Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}), - Entrance(FIRE_TEMPLE_BOSS_ROOM, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(HOVER_BOOTS) || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}));}, + Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(HOVER_BOOTS) || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}));}, /*Glitched*/[]{return BossKeyFireTemple && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)));}}), }); - areaTable[FIRE_TEMPLE_BOSS_ROOM] = Area("Fire Temple Boss Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&FireTempleClear, {[]{return FireTempleClear || (FireTimer >= 64 && CanUse(MEGATON_HAMMER));}, - /*Glitched*/[]{return FireTimer >= 48 && ((CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || - CanUse(MEGATON_HAMMER)) && Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}), - }, { - //Locations - LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, {[]{return FireTempleClear;}}), - LocationAccess(VOLVAGIA, {[]{return FireTempleClear;}}), - }, { - //Exits - Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return FireTempleClear;}}), - }); - areaTable[FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 8) || !IsKeysanity;}}), @@ -308,7 +294,7 @@ void AreaTable_Init_FireTemple() { areaTable[FIRE_TEMPLE_WEST_CENTRAL_UPPER] = Area("Fire Temple West Central Upper", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(FIRE_TEMPLE_BOSS_ROOM, {[]{return false;}, + Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}, /*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE);}}), Entrance(FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return true;}}), Entrance(FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return true;}}), @@ -375,7 +361,7 @@ void AreaTable_Init_FireTemple() { }, { //Exits Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}), - Entrance(FIRE_TEMPLE_MQ_BOSS_ROOM, {[]{return IsAdult && CanUse(GORON_TUNIC) && CanUse(MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (LogicFireBossDoorJump || HoverBoots)) || HasAccessTo(FIRE_TEMPLE_MQ_UPPER));}}), + Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(GORON_TUNIC) && CanUse(MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (LogicFireBossDoorJump || HoverBoots)) || HasAccessTo(FIRE_TEMPLE_MQ_UPPER));}}), Entrance(FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, {[]{return SmallKeys(FIRE_TEMPLE, 5) && (IsAdult || KokiriSword);}}), Entrance(FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return IsAdult && FireTimer >= 24 && CanUse(MEGATON_HAMMER);}}), }); @@ -443,14 +429,41 @@ void AreaTable_Init_FireTemple() { LocationAccess(FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return IsAdult && CanUse(HOOKSHOT) && SmallKeys(FIRE_TEMPLE, 5);}}), //Trick: (IsAdult && CanUse(HOOKSHOT) && SmallKeys(FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(LONGSHOT)) }, {}); - - areaTable[FIRE_TEMPLE_MQ_BOSS_ROOM] = Area("Fire Temple MQ Boss Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&FireTempleClear, {[]{return true;}}), - }, { - //Locations - LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, {[]{return true;}}), - LocationAccess(VOLVAGIA, {[]{return true;}}), - }, {}); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[FIRE_TEMPLE_BOSS_ENTRYWAY] = + Area("Fire Temple Boss Entryway", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return Dungeon::FireTemple.IsVanilla() && false; } }), + Entrance(FIRE_TEMPLE_MQ_LOWER, { [] { return Dungeon::FireTemple.IsMQ() && false; } }), + Entrance(FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[FIRE_TEMPLE_BOSS_ROOM] = + Area("Fire Temple Boss Room", "Fire Temple", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&FireTempleClear, + { [] { return FireTempleClear || (FireTimer >= 64 && CanUse(MEGATON_HAMMER)); }, + /*Glitched*/ + [] { + return FireTimer >= 48 && + ((CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || + CanUse(MEGATON_HAMMER)) && + Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE); + } }), + }, + { + // Locations + LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, { [] { return FireTempleClear; } }), + LocationAccess(VOLVAGIA, { [] { return FireTempleClear; } }), + }, + { + // Exits + Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp index 138f6672b7e..cfed92c33d5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp @@ -58,7 +58,7 @@ void AreaTable_Init_ForestTemple() { Entrance(FOREST_TEMPLE_EAST_CORRIDOR, {[]{return false;}, /*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}), Entrance(FOREST_TEMPLE_BOSS_REGION, {[]{return ForestTempleMeg;}}), - Entrance(FOREST_TEMPLE_BOSS_ROOM, {[]{return false;}, + Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}, /*Glitched*/[]{return IsAdult && (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT)) && GlitchForestBKSkip;}}), }); @@ -97,7 +97,7 @@ void AreaTable_Init_ForestTemple() { /*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE) || (IsAdult && CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::NOVICE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}), Entrance(FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}), Entrance(FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(IRON_BOOTS) || HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}), - Entrance(FOREST_TEMPLE_BOSS_ROOM, {[]{return false;}, + Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}, /*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE);}}), }); @@ -304,19 +304,7 @@ void AreaTable_Init_ForestTemple() { }, { //Exits Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}), - Entrance(FOREST_TEMPLE_BOSS_ROOM, {[]{return BossKeyForestTemple;}}), - }); - - areaTable[FOREST_TEMPLE_BOSS_ROOM] = Area("Forest Temple Boss Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&ForestTempleClear, {[]{return ForestTempleClear || ((IsAdult || KokiriSword) && (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT)));}}), - }, { - //Locations - LocationAccess(FOREST_TEMPLE_PHANTOM_GANON_HEART, {[]{return ForestTempleClear;}}), - LocationAccess(PHANTOM_GANON, {[]{return ForestTempleClear;}}), - }, { - //Exits - Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return ForestTempleClear;}}), + Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyForestTemple;}}), }); } @@ -439,14 +427,43 @@ void AreaTable_Init_ForestTemple() { Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return true;}}), }); - areaTable[FOREST_TEMPLE_MQ_BOSS_REGION] = Area("Forest Temple MQ Boss Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&ForestTempleClear, {[]{return ForestTempleClear || BossKeyForestTemple;}}), - }, { + areaTable[FOREST_TEMPLE_MQ_BOSS_REGION] = Area("Forest Temple MQ Boss Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(FOREST_TEMPLE_MQ_BASEMENT_CHEST, {[]{return true;}}), - LocationAccess(FOREST_TEMPLE_PHANTOM_GANON_HEART, {[]{return BossKeyForestTemple;}}), - LocationAccess(PHANTOM_GANON, {[]{return BossKeyForestTemple;}}), - }, {}); + }, { + //Exits + Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyForestTemple;}}), + }); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[FOREST_TEMPLE_BOSS_ENTRYWAY] = + Area("Forest Temple Boss Entryway", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(FOREST_TEMPLE_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsVanilla() && false; } }), + Entrance(FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsMQ() && false; } }), + Entrance(FOREST_TEMPLE_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[FOREST_TEMPLE_BOSS_ROOM] = Area( + "Forest Temple Boss Room", "Forest Temple", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&ForestTempleClear, { [] { + return ForestTempleClear || ((CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && + (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT))); + } }), + }, + { + // Locations + LocationAccess(FOREST_TEMPLE_PHANTOM_GANON_HEART, { [] { return ForestTempleClear; } }), + LocationAccess(PHANTOM_GANON, { [] { return ForestTempleClear; } }), + }, + { + // Exits + Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp index 9d24ab03169..5cb561c7e1f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp @@ -162,23 +162,10 @@ void AreaTable_Init_JabuJabusBelly() { }, { //Exits Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), - Entrance(JABU_JABUS_BELLY_BOSS_ROOM, {[]{return CanUse(BOOMERANG);}, + Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(BOOMERANG);}, /*Glitched*/[]{return (CanUse(HOVER_BOOTS) && (CanUse(BOW) || CanUse(SLINGSHOT))) || CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || (Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE);}}), }); - - areaTable[JABU_JABUS_BELLY_BOSS_ROOM] = Area("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&JabuJabusBellyClear, {[]{return JabuJabusBellyClear || CanUse(BOOMERANG);}}), - }, { - //Locations - LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, {[]{return JabuJabusBellyClear;}}), - LocationAccess(BARINADE, {[]{return JabuJabusBellyClear;}}), - }, { - //Exits - Entrance(JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return JabuJabusBellyClear;}}), - Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return JabuJabusBellyClear;}}), - }); } /*--------------------------- @@ -234,12 +221,39 @@ void AreaTable_Init_JabuJabusBelly() { //Locations LocationAccess(JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}), LocationAccess(JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}), - LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, {[]{return true;}}), - LocationAccess(BARINADE, {[]{return true;}}), LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}), }, { //Exits Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}), + Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(SLINGSHOT);}}), }); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[JABU_JABUS_BELLY_BOSS_ENTRYWAY] = + Area("Jabu Jabus Belly Boss Entryway", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return Dungeon::JabuJabusBelly.IsVanilla(); } }), + Entrance(JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return Dungeon::JabuJabusBelly.IsMQ(); } }), + Entrance(JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[JABU_JABUS_BELLY_BOSS_ROOM] = + Area("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&JabuJabusBellyClear, { [] { return JabuJabusBellyClear || CanUse(BOOMERANG); } }), + }, + { + // Locations + LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, { [] { return JabuJabusBellyClear; } }), + LocationAccess(BARINADE, { [] { return JabuJabusBellyClear; } }), + }, + { + // Exits + Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp index e9216f74316..5d0a4e08584 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp @@ -81,18 +81,16 @@ void AreaTable_Init_ShadowTemple() { Entrance(SHADOW_TEMPLE_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(SHADOW_TEMPLE, 4, 5);}}), }); - areaTable[SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&ShadowTempleClear, {[]{return ShadowTempleClear || (SmallKeys(SHADOW_TEMPLE, 5) && BossKeyShadowTemple && (Bow || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)));}}), - }, { + areaTable[SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(DINS_FIRE);}}), LocationAccess(SHADOW_TEMPLE_BOSS_KEY_CHEST, {[]{return CanUse(DINS_FIRE);}}), LocationAccess(SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, {[]{return true;}}), - LocationAccess(SHADOW_TEMPLE_BONGO_BONGO_HEART, {[]{return SmallKeys(SHADOW_TEMPLE, 5) && BossKeyShadowTemple && (Bow || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus));}}), - LocationAccess(BONGO_BONGO, {[]{return SmallKeys(SHADOW_TEMPLE, 5) && BossKeyShadowTemple && (Bow || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus));}}), LocationAccess(SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return true;}}), - }, {}); + }, { + //Exits + Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(BOW) || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)) && SmallKeys(SHADOW_TEMPLE, 5) && CanUse(HOVER_BOOTS) && BossKeyShadowTemple;}}) + }); } /*--------------------------- @@ -164,18 +162,14 @@ void AreaTable_Init_ShadowTemple() { Entrance(SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(SHADOW_TEMPLE, 5);}}), }); - areaTable[SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&ShadowTempleClear, {[]{return ShadowTempleClear || ((Bow || (LogicShadowStatue && HasBombchus)) && BossKeyShadowTemple);}}), - }, { + areaTable[SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LocationAccess(SHADOW_TEMPLE_BONGO_BONGO_HEART, {[]{return (Bow || (LogicShadowStatue && HasBombchus)) && BossKeyShadowTemple;}}), - LocationAccess(BONGO_BONGO, {[]{return (Bow || (LogicShadowStatue && HasBombchus)) && BossKeyShadowTemple;}}), LocationAccess(SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}), LocationAccess(SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (LogicShadowStatue && HasBombchus);}}), }, { //Exits Entrance(SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(LONGSHOT);}}), + Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(BOW) || (LogicShadowStatue && HasBombchus)) && CanUse(HOVER_BOOTS) && BossKeyShadowTemple;}}), }); areaTable[SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -186,4 +180,37 @@ void AreaTable_Init_ShadowTemple() { LocationAccess(SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}), }, {}); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[SHADOW_TEMPLE_BOSS_ENTRYWAY] = + Area("Shadow Temple Boss Entryway", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(SHADOW_TEMPLE_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsVanilla() && false; } }), + Entrance(SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsMQ() && false; } }), + Entrance(SHADOW_TEMPLE_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[SHADOW_TEMPLE_BOSS_ROOM] = + Area("Shadow Temple Boss Room", "Shadow Temple", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&ShadowTempleClear, { [] { + return ShadowTempleClear || + ((CanUse(LENS_OF_TRUTH) || ((Dungeon::ShadowTemple.IsVanilla() && LogicLensShadowBack) || + (Dungeon::ShadowTemple.IsMQ() && LogicLensShadowMQBack))) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))); + } }), + }, + { + // Locations + LocationAccess(SHADOW_TEMPLE_BONGO_BONGO_HEART, { [] { return ShadowTempleClear; } }), + LocationAccess(BONGO_BONGO, { [] { return ShadowTempleClear; } }), + }, + { + // Exits + Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp index cfe99555bcb..32e71cb8e60 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp @@ -122,16 +122,22 @@ void AreaTable_Init_SpiritTemple() { Entrance(SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(SPIRIT_TEMPLE, 5) && (LogicSpiritWall || CanUse(LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(DINS_FIRE)) && (Bow || CanUse(HOOKSHOT) || Hammer)));}}), }); - areaTable[SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&SpiritTempleClear, {[]{return SpiritTempleClear || (MirrorShield && HasExplosives && Hookshot && BossKeySpiritTemple);}}), - }, { + areaTable[SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot));}}), LocationAccess(SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return MirrorShield || (SunlightArrows && CanUse(LIGHT_ARROWS));}}), - LocationAccess(SPIRIT_TEMPLE_TWINROVA_HEART, {[]{return MirrorShield && HasExplosives && Hookshot && BossKeySpiritTemple;}}), - LocationAccess(TWINROVA, {[]{return MirrorShield && HasExplosives && Hookshot && BossKeySpiritTemple;}}), - }, {}); + }, { + //Exits + Entrance(SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, {[]{return MirrorShield && HasExplosives && Hookshot;}}), + }); + + areaTable[SPIRIT_TEMPLE_INSIDE_STATUE_HEAD] = + Area("Spirit Temple Inside Statue Head", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(SPIRIT_TEMPLE_CENTRAL_CHAMBER, { [] { return true; } }), + Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return BossKeySpiritTemple; } }), + }); } /*--------------------------- @@ -209,15 +215,21 @@ void AreaTable_Init_SpiritTemple() { LocationAccess(SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, {[]{return SmallKeys(SPIRIT_TEMPLE, 7) && Hammer && Ocarina && SongOfTime && EponasSong && SunsSong && SongOfStorms && ZeldasLullaby;}}), }, {}); - areaTable[SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&SpiritTempleClear, {[]{return SpiritTempleClear || (MirrorShield && BossKeySpiritTemple);}}), - }, { + areaTable[SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations LocationAccess(SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH);}}), - LocationAccess(SPIRIT_TEMPLE_TWINROVA_HEART, {[]{return MirrorShield && BossKeySpiritTemple;}}), - LocationAccess(TWINROVA, {[]{return MirrorShield && BossKeySpiritTemple;}}), - }, {}); + }, { + //Exits + Entrance(SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return MirrorShield && Hookshot;}}), + }); + + areaTable[SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD] = + Area("Spirit Temple MQ Inside Statue Head", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(SPIRIT_TEMPLE_MQ_SHARED, { [] { return true; } }), + Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return BossKeySpiritTemple; } }), + }); areaTable[SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Area("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { //Locations @@ -229,4 +241,35 @@ void AreaTable_Init_SpiritTemple() { LocationAccess(SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return true;}}), }, {}); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[SPIRIT_TEMPLE_BOSS_ENTRYWAY] = Area( + "Spirit Temple Boss Entryway", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsVanilla() && false; } }), + Entrance(SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsMQ() && false; } }), + Entrance(SPIRIT_TEMPLE_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[SPIRIT_TEMPLE_BOSS_ROOM] = Area( + "Spirit Temple Boss Room", "Spirit Temple", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&SpiritTempleClear, { [] { + return SpiritTempleClear || (CanUse(MIRROR_SHIELD) && + (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))); + } }), + }, + { + // Locations + LocationAccess(SPIRIT_TEMPLE_TWINROVA_HEART, { [] { return SpiritTempleClear; } }), + LocationAccess(TWINROVA, { [] { return SpiritTempleClear; } }), + }, + { + // Exits + Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp index d2f566b2c06..212f4bf1ac1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp @@ -275,19 +275,7 @@ void AreaTable_Init_WaterTemple() { }, {}, { //Exits Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}), - Entrance(WATER_TEMPLE_BOSS_ROOM, {[]{return BossKeyWaterTemple;}}), - }); - - areaTable[WATER_TEMPLE_BOSS_ROOM] = Area("Water Temple Boss Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&WaterTempleClear, {[]{return WaterTempleClear || (CanUse(HOOKSHOT) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)));}}), - }, { - //Locations - LocationAccess(WATER_TEMPLE_MORPHA_HEART, {[]{return WaterTempleClear;}}), - LocationAccess(MORPHA, {[]{return WaterTempleClear;}}), - }, { - //Exits - Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return WaterTempleClear;}}), + Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyWaterTemple;}}), }); } @@ -295,18 +283,12 @@ void AreaTable_Init_WaterTemple() { | MASTER QUEST DUNGEON | ---------------------------*/ if (Dungeon::WaterTemple.IsMQ()) { - areaTable[WATER_TEMPLE_MQ_LOBBY] = Area("Water Temple MQ Lobby", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&WaterTempleClear, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}), - }, { - //Locations - LocationAccess(WATER_TEMPLE_MORPHA_HEART, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}), - LocationAccess(MORPHA, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}), - }, { + areaTable[WATER_TEMPLE_MQ_LOBBY] = Area("Water Temple MQ Lobby", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return true;}}), Entrance(WATER_TEMPLE_MQ_DIVE, {[]{return IsAdult && WaterTimer >= 24 && CanUse(IRON_BOOTS);}}), Entrance(WATER_TEMPLE_MQ_DARK_LINK_REGION, {[]{return SmallKeys(WATER_TEMPLE, 1) && IsAdult && CanUse(LONGSHOT);}}), + Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}), }); areaTable[WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, { @@ -348,4 +330,35 @@ void AreaTable_Init_WaterTemple() { //Trick: LogicWaterMQLockedGS || (SmallKeys(WATER_TEMPLE, 2) && (HoverBoots || CanUse(SCARECROW) || LogicWaterNorthBasementLedgeJump)) }, {}); } + + /*--------------------------- + | BOSS ROOM | + ---------------------------*/ + areaTable[WATER_TEMPLE_BOSS_ENTRYWAY] = + Area("Water Temple Boss Entryway", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, + { + // Exits + Entrance(WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return Dungeon::WaterTemple.IsVanilla() && false; } }), + Entrance(WATER_TEMPLE_MQ_LOBBY, { [] { return Dungeon::WaterTemple.IsMQ() && false; } }), + Entrance(WATER_TEMPLE_BOSS_ROOM, { [] { return true; } }), + }); + + areaTable[WATER_TEMPLE_BOSS_ROOM] = Area( + "Water Temple Boss Room", "Water Temple", NONE, NO_DAY_NIGHT_CYCLE, + { + // Events + EventAccess(&WaterTempleClear, { [] { + return WaterTempleClear || + (CanUse(HOOKSHOT) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))); + } }), + }, + { + // Locations + LocationAccess(WATER_TEMPLE_MORPHA_HEART, { [] { return WaterTempleClear; } }), + LocationAccess(MORPHA, { [] { return WaterTempleClear; } }), + }, + { + // Exits + Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }), + }); } diff --git a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp index bcadae7edae..8c404f35475 100644 --- a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp @@ -164,6 +164,17 @@ string_view dungeonEntrancesDesc = "Shuffle the pool of dungeon entrances, "Temple, Bottom of the Well and Gerudo Training\n" // "Ground are opened for both adult and child."; // /*------------------------------ // +| BOSS ENTRANCES | // +------------------------------*/ // +string_view bossEntrancesDesc = "Shuffle the pool of dungeon boss entrances.\n" // + "This affects the boss rooms of all stone and\n" // + "medallion dungeons.\n" // + "\n" // + "Child and adult boss rooms can be shuffled\n" // + "separately.\n" // + "Child may be expected to defeat Phantom Ganon\n" // + "and/or Bongo Bongo."; // +/*------------------------------ // | OVERWORLD ENTRANCES | // ------------------------------*/ // string_view overworldEntrancesDesc = "Shuffle the pool of Overworld entrances, which\n" // @@ -238,7 +249,9 @@ string_view decoupledEntrancesDesc = "Decouple entrances when shuffling them. "you came from when you go back through an\n" // "entrance. This also adds the one-way entrance from" "Gerudo Valley to Lake Hylia in the pool of\n" // - "overworld entrances when they are shuffled."; // + "overworld entrances when they are shuffled.\n" // + "Boss entrances are currently excluded from this\n"// + "and remain coupled regardless."; // /*------------------------------ // | BOMBCHUS IN LOGIC | // ------------------------------*/ // diff --git a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp index 4594cc3a654..096ebf658fd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp @@ -57,6 +57,8 @@ extern string_view shuffleEntrancesDesc; extern string_view dungeonEntrancesDesc; +extern string_view bossEntrancesDesc; + extern string_view overworldEntrancesDesc; extern string_view grottoEntrancesDesc; diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 4dfa26afb69..1a4e10a652f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -89,6 +89,7 @@ namespace Settings { uint8_t ResolvedStartingAge; Option ShuffleEntrances = Option::Bool("Shuffle Entrances", {"Off", "On"}, {shuffleEntrancesDesc}); Option ShuffleDungeonEntrances = Option::U8 ("Dungeon Entrances", {"Off", "On", "On + Ganon"}, {dungeonEntrancesDesc}); + Option ShuffleBossEntrances = Option::U8 ("Boss Entrances", {"Off", "Age Restricted", "Full"}, {bossEntrancesDesc}); Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc}); Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll}); Option ShuffleGrottoEntrances = Option::Bool("Grottos Entrances", {"Off", "On"}, {grottoEntrancesDesc}); @@ -125,6 +126,7 @@ namespace Settings { &StartingAge, &ShuffleEntrances, &ShuffleDungeonEntrances, + &ShuffleBossEntrances, &ShuffleOverworldEntrances, &ShuffleInteriorEntrances, &ShuffleGrottoEntrances, @@ -314,6 +316,16 @@ namespace Settings { Option GossipStoneHints = Option::U8 ("Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, {gossipStonesHintsDesc}, OptionCategory::Setting, HINTS_NEED_NOTHING); Option ClearerHints = Option::U8 ("Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, {obscureHintsDesc, ambiguousHintsDesc, clearHintsDesc}); Option HintDistribution = Option::U8 ("Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, {uselessHintsDesc, balancedHintsDesc, strongHintsDesc, veryStrongHintsDesc}, OptionCategory::Setting, 1); // Balanced + Option AltarHintText = Option::Bool("ToT Altar Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 1); + Option GanondorfHintText = Option::Bool("Ganondorf LA Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 1); + Option DampeHintText = Option::Bool("Dampe's Diary Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option WarpSongHints = Option::Bool("Warp Songs Hints", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak10GSHintText = Option::Bool("10 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak20GSHintText = Option::Bool("20 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak30GSHintText = Option::Bool("30 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak40GSHintText = Option::Bool("40 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option Kak50GSHintText = Option::Bool("50 GS Hint", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); + Option ScrubHintText = Option::Bool("Scrub Hint Text", {"Off", "On"}, {"", ""}, OptionCategory::Setting, 0); Option CompassesShowReward = Option::U8 ("Compasses Show Rewards", {"No", "Yes"}, {compassesShowRewardsDesc}, OptionCategory::Setting, 1); Option CompassesShowWotH = Option::U8 ("Compasses Show WotH", {"No", "Yes"}, {compassesShowWotHDesc}, OptionCategory::Setting, 1); Option MapsShowDungeonMode = Option::U8 ("Maps Show Dungeon Modes",{"No", "Yes"}, {mapsShowDungeonModesDesc}, OptionCategory::Setting, 1); @@ -332,6 +344,16 @@ namespace Settings { &GossipStoneHints, &ClearerHints, &HintDistribution, + &AltarHintText, + &GanondorfHintText, + &DampeHintText, + &WarpSongHints, + &Kak10GSHintText, + &Kak20GSHintText, + &Kak30GSHintText, + &Kak40GSHintText, + &Kak50GSHintText, + &ScrubHintText, &CompassesShowReward, &CompassesShowWotH, &MapsShowDungeonMode, @@ -509,18 +531,18 @@ namespace Settings { &StartingRutoBottle, }; - Option StartingZeldasLullaby = Option::U8 ("Zelda's Lullaby", {"Off", "On"}, {""}); - Option StartingEponasSong = Option::U8 ("Epona's Song", {"Off", "On"}, {""}); - Option StartingSariasSong = Option::U8 ("Saria's Song", {"Off", "On"}, {""}); - Option StartingSunsSong = Option::U8 ("Sun's Song", {"Off", "On"}, {""}); - Option StartingSongOfTime = Option::U8 ("Song of Time", {"Off", "On"}, {""}); - Option StartingSongOfStorms = Option::U8 ("Song of Storms", {"Off", "On"}, {""}); - Option StartingMinuetOfForest = Option::U8 ("Minuet of Forest", {"Off", "On"}, {""}); - Option StartingBoleroOfFire = Option::U8 ("Bolero of Fire", {"Off", "On"}, {""}); - Option StartingSerenadeOfWater = Option::U8 ("Serenade of Water", {"Off", "On"}, {""}); - Option StartingRequiemOfSpirit = Option::U8 ("Requiem of Spirit", {"Off", "On"}, {""}); - Option StartingNocturneOfShadow = Option::U8 ("Nocturne of Shadow", {"Off", "On"}, {""}); - Option StartingPreludeOfLight = Option::U8 ("Prelude of Light", {"Off", "On"}, {""}); + Option StartingZeldasLullaby = Option::U8 ("Start with Zelda's Lullaby", {"Off", "On"}, {""}); + Option StartingEponasSong = Option::U8 ("Start with Epona's Song", {"Off", "On"}, {""}); + Option StartingSariasSong = Option::U8 ("Start with Saria's Song", {"Off", "On"}, {""}); + Option StartingSunsSong = Option::U8 ("Start with Sun's Song", {"Off", "On"}, {""}); + Option StartingSongOfTime = Option::U8 ("Start with Song of Time", {"Off", "On"}, {""}); + Option StartingSongOfStorms = Option::U8 ("Start with Song of Storms", {"Off", "On"}, {""}); + Option StartingMinuetOfForest = Option::U8 ("Start with Minuet of Forest", {"Off", "On"}, {""}); + Option StartingBoleroOfFire = Option::U8 ("Start with Bolero of Fire", {"Off", "On"}, {""}); + Option StartingSerenadeOfWater = Option::U8 ("Start with Serenade of Water", {"Off", "On"}, {""}); + Option StartingRequiemOfSpirit = Option::U8 ("Start with Requiem of Spirit", {"Off", "On"}, {""}); + Option StartingNocturneOfShadow = Option::U8 ("Start with Nocturne of Shadow", {"Off", "On"}, {""}); + Option StartingPreludeOfLight = Option::U8 ("Start with Prelude of Light", {"Off", "On"}, {""}); std::vector