diff --git a/.gitignore b/.gitignore
index 9c499abb0..ec5401c38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,9 @@ __pycache__/
.DS_Store
# Text editor remnants
-.vscode/
+.vscode/*
+!.vscode/tasks.json
+
.vs/
.idea/
cmake-build-**
@@ -400,7 +402,6 @@ ASALocalRun/
lib/libgfxd/libgfxd.a
ExporterTest/ExporterTest.a
ZAPDUtils/ZAPDUtils.a
-.vscode/
build/
external/
ZAPDUtils/build/
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 000000000..be763065e
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,61 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Setup CMake Project",
+ "type": "shell",
+ "command": "cmake",
+ "args": [
+ "-S",
+ ".",
+ "-B",
+ "build/x64",
+ "-G",
+ "Visual Studio 17 2022",
+ "-T",
+ "v143",
+ "-A",
+ "x64"
+ ],
+ "group": "build",
+ "problemMatcher": []
+ },
+ {
+ "label": "Generate SOH OTR",
+ "type": "shell",
+ "command": "cmake",
+ "args": [
+ "--build",
+ "./build/x64",
+ "--target",
+ "GenerateSohOtr"
+ ],
+ "group": "build",
+ "problemMatcher": []
+ },
+ {
+ "label": "Build Project",
+ "type": "shell",
+ "command": "cmake",
+ "args": [
+ "--build",
+ "./build/x64"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "dependsOn": ["Generate SOH OTR"],
+ "problemMatcher": []
+ },
+ {
+ "label": "Build All",
+ "dependsOrder": "sequence",
+ "dependsOn": [
+ "Setup CMake Project",
+ "Generate SOH OTR",
+ "Build Project"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/docs/BUILDING.md b/docs/BUILDING.md
index 963037465..4e37a27e9 100644
--- a/docs/BUILDING.md
+++ b/docs/BUILDING.md
@@ -58,7 +58,7 @@ To develop using Visual Studio you only need to use cmake to generate the soluti
To develop using Visual Studio Code or another editor you only need to open the repository in it.
To build you'll need to follow the instructions from the building section.
-_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
+_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
_Experimental: You can also use another build system entirely rather than MSVC like [Ninja](https://ninja-build.org/) for possibly better performance._
@@ -177,7 +177,7 @@ Requires Xcode (or xcode-tools) && `sdl2, libpng, glew, ninja, cmake, tinyxml2,
**Important: For maximum performance make sure you have ninja build tools installed!**
-_Note: If you're using Visual Studio Code, the [cpack plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
+_Note: If you're using Visual Studio Code, the [CMake Tools plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) makes it very easy to just press run and debug._
```bash
# Clone the repo
diff --git a/libultraship b/libultraship
index 9a974e002..5341b0172 160000
--- a/libultraship
+++ b/libultraship
@@ -1 +1 @@
-Subproject commit 9a974e002f84cd1fe834ee9d2fa4ccf16d899e0f
+Subproject commit 5341b017254a186da3ffe6d681d4e293769f23f4
diff --git a/soh/assets/custom/objects/object_boss_soul/BarkOrHorns b/soh/assets/custom/objects/object_boss_soul/BarkOrHorns
new file mode 100644
index 000000000..d546ce9bd
Binary files /dev/null and b/soh/assets/custom/objects/object_boss_soul/BarkOrHorns differ
diff --git a/soh/assets/custom/objects/object_boss_soul/LightNoise b/soh/assets/custom/objects/object_boss_soul/LightNoise
new file mode 100644
index 000000000..73bcf2a59
Binary files /dev/null and b/soh/assets/custom/objects/object_boss_soul/LightNoise differ
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_cull b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_cull
new file mode 100644
index 000000000..0e8c716c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/heart1 b/soh/assets/custom/objects/object_boss_soul/heart1
new file mode 100644
index 000000000..1fdc62cbd
Binary files /dev/null and b/soh/assets/custom/objects/object_boss_soul/heart1 differ
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Black b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Black
new file mode 100644
index 000000000..03ecd61f5
--- /dev/null
+++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Black
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Horns b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Horns
new file mode 100644
index 000000000..28fdc0d1b
--- /dev/null
+++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Horns
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Jewel b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Jewel
new file mode 100644
index 000000000..dbe5cfd53
--- /dev/null
+++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Jewel
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Skull1 b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Skull1
new file mode 100644
index 000000000..c32c4ee24
--- /dev/null
+++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Skull1
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_f3dlite_material b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_f3dlite_material
new file mode 100644
index 000000000..a3dd769f6
--- /dev/null
+++ b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_f3dlite_material
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/Hilite_new b/soh/assets/custom/objects/object_housekey/Hilite_new
new file mode 100644
index 000000000..5438695fa
Binary files /dev/null and b/soh/assets/custom/objects/object_housekey/Hilite_new differ
diff --git a/soh/assets/custom/objects/object_housekey/HouseKey_Tag b/soh/assets/custom/objects/object_housekey/HouseKey_Tag
new file mode 100644
index 000000000..4939ef966
Binary files /dev/null and b/soh/assets/custom/objects/object_housekey/HouseKey_Tag differ
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL b/soh/assets/custom/objects/object_housekey/gHouseKeyDL
new file mode 100644
index 000000000..3d6787c3c
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_0 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_0
new file mode 100644
index 000000000..4c8002a6a
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_0
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_1 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_1
new file mode 100644
index 000000000..06fdafc2d
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_1
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_2 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_2
new file mode 100644
index 000000000..a606298d1
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_2
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_0 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_0
new file mode 100644
index 000000000..cd0885c1c
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_0
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_1 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_1
new file mode 100644
index 000000000..c4f2d8850
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_1
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_2 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_2
new file mode 100644
index 000000000..dc377511e
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_2
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeymetal b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeymetal
new file mode 100644
index 000000000..90c65bd06
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeymetal
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeyringmetal b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeyringmetal
new file mode 100644
index 000000000..d7d19e315
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeyringmetal
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeytag b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeytag
new file mode 100644
index 000000000..05f2afc64
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeytag
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 78f4d281e..ace158854 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -237,6 +237,9 @@ static const ALIGN_ASSET(2) char gKeyringKeysShadowTempleMQDL[] = dgKeyringKeysS
#define dgKeyringKeysGanonsCastleMQDL "__OTR__objects/object_keyring/gKeyringKeysGanonsCastleMQDL"
static const ALIGN_ASSET(2) char gKeyringKeysGanonsCastleMQDL[] = dgKeyringKeysGanonsCastleMQDL;
+#define dgHouseKeyDL "__OTR__objects/object_housekey/gHouseKeyDL"
+static const ALIGN_ASSET(2) char gHouseKeyDL[] = dgHouseKeyDL;
+
// overlays
#define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx"
static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx;
@@ -335,3 +338,10 @@ static const ALIGN_ASSET(2) char gLinkAdultGoronTunicSkel[] = dgLinkAdultGoronTu
#define dgLinkAdultZoraTunicSkel "__OTR__objects/object_link_boy_zora/gLinkAdultZoraTunicSkel"
static const ALIGN_ASSET(2) char gLinkAdultZoraTunicSkel[] = dgLinkAdultZoraTunicSkel;
+
+// LUS Logo
+#define dgShipLogoDL "__OTR__textures/nintendo_rogo_static/gShipLogoDL"
+static const ALIGN_ASSET(2) char gShipLogoDL[] = dgShipLogoDL;
+
+#define dnintendo_rogo_static_Tex_LUS_000000 "__OTR__textures/nintendo_rogo_static/nintendo_rogo_static_Tex_LUS_000000"
+static const ALIGN_ASSET(2) char nintendo_rogo_static_Tex_LUS_000000[] = dnintendo_rogo_static_Tex_LUS_000000;
diff --git a/soh/include/macros.h b/soh/include/macros.h
index 5db738735..acff90f19 100644
--- a/soh/include/macros.h
+++ b/soh/include/macros.h
@@ -275,7 +275,12 @@ extern GraphicsContext* __gfxCtx;
: (((a2) >= (a3)) ? (a2) : (((a3) >= (a1)) ? (a1) : (a3))))
#define MATRIX_TOMTX(dest) Matrix_ToMtx(dest, __FILE__, __LINE__)
+#ifdef __cplusplus
+#define MATRIX_NEWMTX(gfxCtx) Matrix_NewMtx(gfxCtx, const_cast(__FILE__), __LINE__)
+#else
#define MATRIX_NEWMTX(gfxCtx) Matrix_NewMtx(gfxCtx, __FILE__, __LINE__)
+#endif
+
#define MATRIX_CHECKFLOATS(mf) Matrix_CheckFloats(mf, __FILE__, __LINE__)
#define ZELDA_ARENA_MALLOC_DEBUG(size) ZeldaArena_MallocDebug(size, __FILE__, __LINE__)
diff --git a/soh/soh/AboutWindow.cpp b/soh/soh/AboutWindow.cpp
new file mode 100644
index 000000000..e5d51300c
--- /dev/null
+++ b/soh/soh/AboutWindow.cpp
@@ -0,0 +1,103 @@
+#include "AboutWindow.h"
+#include
+#include
+#include "soh/ResourceManagerHelpers.h"
+
+extern "C" {
+#include "variables.h"
+}
+
+AboutWindow::~AboutWindow() {
+ SPDLOG_TRACE("destruct about window");
+}
+
+void AboutWindow::InitElement() {
+ mIsTaggedVersion = gGitCommitTag[0] != 0;
+
+ strncpy(mGitCommitHashTruncated, (char*)gGitCommitHash, 7);
+ mGitCommitHashTruncated[7] = 0;
+}
+
+void AboutWindow::Draw() {
+ if (!IsVisible()) {
+ return;
+ }
+
+ ImGuiWindowFlags windowFlags = ImGuiWindowFlags_AlwaysAutoResize |
+ ImGuiWindowFlags_NoResize |
+ ImGuiWindowFlags_NoDocking |
+ ImGuiWindowFlags_NoScrollWithMouse |
+ ImGuiWindowFlags_NoScrollbar;
+
+ ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(16 * ImGui::GetIO().FontGlobalScale, 8 * ImGui::GetIO().FontGlobalScale));
+
+ if (!ImGui::Begin(GetName().c_str(), &mIsVisible, windowFlags)) {
+ ImGui::End();
+ } else {
+ DrawElement();
+ ImGui::End();
+ }
+
+ ImGui::PopStyleVar();
+
+ // Sync up the IsVisible flag if it was changed by ImGui
+ SyncVisibilityConsoleVariable();
+}
+
+const char* AboutWindow::GetGameVersionString(uint32_t index) {
+ uint32_t gameVersion = ResourceMgr_GetGameVersion(index);
+ switch (gameVersion) {
+ case OOT_NTSC_US_10:
+ return "NTSC-U 1.0";
+ case OOT_NTSC_US_11:
+ return "NTSC-U 1.1";
+ case OOT_NTSC_US_12:
+ return "NTSC-U 1.2";
+ case OOT_PAL_10:
+ return "PAL 1.0";
+ case OOT_PAL_11:
+ return "PAL 1.1";
+ case OOT_PAL_GC:
+ return "PAL GC";
+ case OOT_PAL_MQ:
+ return "PAL MQ";
+ case OOT_PAL_GC_DBG1:
+ case OOT_PAL_GC_DBG2:
+ return "PAL GC-D";
+ case OOT_PAL_GC_MQ_DBG:
+ return "PAL MQ-D";
+ case OOT_IQUE_CN:
+ return "IQUE CN";
+ case OOT_IQUE_TW:
+ return "IQUE TW";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+void AboutWindow::DrawElement() {
+ // The icon is already padded - adjust for that
+ ImVec2 cursorPos = ImGui::GetCursorScreenPos();
+ cursorPos.x -= 16 * ImGui::GetIO().FontGlobalScale;
+ ImGui::SetCursorScreenPos(cursorPos);
+
+ ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Game_Icon"), ImVec2(64.0f * ImGui::GetIO().FontGlobalScale, 64.0f * ImGui::GetIO().FontGlobalScale));
+
+ ImGui::SameLine();
+
+ ImGui::BeginGroup();
+ ImGui::Text("Ship of Harkinian");
+ if (mIsTaggedVersion) {
+ ImGui::Text("%s", gBuildVersion);
+ } else {
+ ImGui::Text("%s", gGitBranch);
+ ImGui::Text("%s", mGitCommitHashTruncated);
+ }
+ ImGui::EndGroup();
+
+ ImGui::Dummy(ImVec2(0, 2 * ImGui::GetIO().FontGlobalScale));
+ ImGui::Text("Game Archives:");
+ for (uint32_t i = 0; i < ResourceMgr_GetNumGameVersions(); i++) {
+ ImGui::BulletText(GetGameVersionString(i));
+ }
+}
diff --git a/soh/soh/AboutWindow.h b/soh/soh/AboutWindow.h
new file mode 100644
index 000000000..5a731fdc1
--- /dev/null
+++ b/soh/soh/AboutWindow.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include
+
+class AboutWindow : public Ship::GuiWindow {
+ public:
+ using GuiWindow::GuiWindow;
+ ~AboutWindow();
+
+ private:
+ void InitElement() override;
+ void Draw() override;
+ void DrawElement() override;
+ void UpdateElement() override {};
+
+ const char* GetGameVersionString(uint32_t index);
+
+ bool mIsTaggedVersion;
+ char mGitCommitHashTruncated[8];
+};
diff --git a/soh/soh/Enhancements/Cheats/EasyFrameAdvance.cpp b/soh/soh/Enhancements/Cheats/EasyFrameAdvance.cpp
new file mode 100644
index 000000000..ab7bba377
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/EasyFrameAdvance.cpp
@@ -0,0 +1,40 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+#include "variables.h"
+#include "overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h"
+}
+
+#define CVAR_FRAME_ADVANCE_NAME CVAR_CHEAT("EasyFrameAdvance")
+#define CVAR_FRAME_ADVANCE_DEFAULT 0
+#define CVAR_FRAME_ADVANCE_VALUE CVarGetInteger(CVAR_FRAME_ADVANCE_NAME, CVAR_FRAME_ADVANCE_DEFAULT)
+
+static int frameAdvanceTimer = 0;
+#define PAUSE_STATE_OFF 0
+#define PAUSE_STATE_UNPAUSE_CLOSE 19
+
+void RegisterEasyFrameAdvance() {
+ COND_HOOK(OnGameStateMainStart, CVAR_FRAME_ADVANCE_VALUE, []() {
+ if (gPlayState == NULL) {
+ return;
+ }
+
+ Input* input = &gPlayState->state.input[0];
+ PauseContext* pauseCtx = &gPlayState->pauseCtx;
+
+ if (frameAdvanceTimer > 0 && pauseCtx->state == PAUSE_STATE_OFF) {
+ frameAdvanceTimer--;
+ if (frameAdvanceTimer == 0 && CHECK_BTN_ALL(input->cur.button, BTN_START)) {
+ input->press.button |= BTN_START;
+ }
+ }
+
+ if (pauseCtx->state == PAUSE_STATE_UNPAUSE_CLOSE) {
+ frameAdvanceTimer = 2;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterEasyFrameAdvance, { CVAR_FRAME_ADVANCE_NAME });
diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp
new file mode 100644
index 000000000..196fc63f4
--- /dev/null
+++ b/soh/soh/Enhancements/ExtraTraps.cpp
@@ -0,0 +1,203 @@
+#include "libultraship/bridge.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "soh/Enhancements/randomizer/3drando/random.hpp"
+#include "soh/Notification/Notification.h"
+#include "soh/OTRGlobals.h"
+
+extern "C" {
+#include "variables.h"
+#include "functions.h"
+#include "macros.h"
+extern PlayState* gPlayState;
+GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID);
+}
+
+#define CVAR_EXTRA_TRAPS_NAME CVAR_ENHANCEMENT("ExtraTraps.Enabled")
+#define CVAR_EXTRA_TRAPS_DEFAULT 0
+#define CVAR_EXTRA_TRAPS_VALUE CVarGetInteger(CVAR_EXTRA_TRAPS_NAME, CVAR_EXTRA_TRAPS_DEFAULT)
+
+typedef enum {
+ ADD_ICE_TRAP,
+ ADD_BURN_TRAP,
+ ADD_SHOCK_TRAP,
+ ADD_KNOCK_TRAP,
+ ADD_SPEED_TRAP,
+ ADD_BOMB_TRAP,
+ ADD_VOID_TRAP,
+ ADD_AMMO_TRAP,
+ ADD_KILL_TRAP,
+ ADD_TELEPORT_TRAP,
+ ADD_TRAP_MAX
+} AltTrapType;
+
+static AltTrapType roll = ADD_TRAP_MAX;
+static int statusTimer = -1;
+static int eventTimer = -1;
+
+const char* altTrapTypeCvars[] = {
+ CVAR_ENHANCEMENT("ExtraTraps.Ice"),
+ CVAR_ENHANCEMENT("ExtraTraps.Burn"),
+ CVAR_ENHANCEMENT("ExtraTraps.Shock"),
+ CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
+ CVAR_ENHANCEMENT("ExtraTraps.Speed"),
+ CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
+ CVAR_ENHANCEMENT("ExtraTraps.Void"),
+ CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
+ CVAR_ENHANCEMENT("ExtraTraps.Kill"),
+ CVAR_ENHANCEMENT("ExtraTraps.Teleport")
+};
+
+std::vector getEnabledAddTraps () {
+ std::vector enabledAddTraps;
+ for (int i = 0; i < ADD_TRAP_MAX; i++) {
+ if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
+ if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
+ continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
+ }
+ enabledAddTraps.push_back(static_cast(i));
+ }
+ }
+ if (enabledAddTraps.size() == 0) {
+ enabledAddTraps.push_back(ADD_ICE_TRAP);
+ }
+ return enabledAddTraps;
+};
+
+static void RollRandomTrap(uint32_t seed) {
+ uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
+ Random_Init(finalSeed);
+
+ roll = RandomElement(getEnabledAddTraps());
+ switch (roll) {
+ case ADD_ICE_TRAP:
+ GameInteractor::RawAction::FreezePlayer();
+ break;
+ case ADD_BURN_TRAP:
+ GameInteractor::RawAction::BurnPlayer();
+ break;
+ case ADD_SHOCK_TRAP:
+ GameInteractor::RawAction::ElectrocutePlayer();
+ break;
+ case ADD_KNOCK_TRAP:
+ eventTimer = 3;
+ break;
+ case ADD_SPEED_TRAP:
+ Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ GameInteractor::State::RunSpeedModifier = -2;
+ statusTimer = 200;
+ Notification::Emit({ .message = "Speed Decreased!" });
+ break;
+ case ADD_BOMB_TRAP:
+ eventTimer = 3;
+ break;
+ case ADD_VOID_TRAP:
+ Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ eventTimer = 3;
+ break;
+ case ADD_AMMO_TRAP:
+ eventTimer = 3;
+ Notification::Emit({ .message = "Ammo Halved!" });
+ break;
+ case ADD_KILL_TRAP:
+ GameInteractor::RawAction::SetPlayerHealth(0);
+ break;
+ case ADD_TELEPORT_TRAP:
+ eventTimer = 3;
+ break;
+ default:
+ break;
+ }
+}
+
+static void OnPlayerUpdate() {
+ Player* player = GET_PLAYER(gPlayState);
+ if (statusTimer == 0) {
+ GameInteractor::State::RunSpeedModifier = 0;
+ }
+ if (eventTimer == 0) {
+ switch (roll) {
+ case ADD_KNOCK_TRAP:
+ GameInteractor::RawAction::KnockbackPlayer(1);
+ break;
+ case ADD_BOMB_TRAP:
+ GameInteractor::RawAction::SpawnActor(ACTOR_EN_BOM, 1);
+ break;
+ case ADD_VOID_TRAP:
+ Play_TriggerRespawn(gPlayState);
+ break;
+ case ADD_AMMO_TRAP:
+ AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5;
+ AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5;
+ AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5;
+ AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
+ AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
+ AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
+ Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ break;
+ case ADD_TELEPORT_TRAP: {
+ int entrance;
+ int index = Random(0, 7);
+ switch (index) {
+ case 0:
+ entrance = GI_TP_DEST_SERENADE;
+ break;
+ case 1:
+ entrance = GI_TP_DEST_REQUIEM;
+ break;
+ case 2:
+ entrance = GI_TP_DEST_BOLERO;
+ break;
+ case 3:
+ entrance = GI_TP_DEST_MINUET;
+ break;
+ case 4:
+ entrance = GI_TP_DEST_NOCTURNE;
+ break;
+ case 5:
+ entrance = GI_TP_DEST_PRELUDE;
+ break;
+ default:
+ entrance = GI_TP_DEST_LINKSHOUSE;
+ break;
+ }
+ GameInteractor::RawAction::TeleportPlayer(entrance);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (statusTimer >= 0) {
+ statusTimer--;
+ }
+ if (eventTimer >= 0) {
+ eventTimer--;
+ }
+}
+
+void RegisterExtraTraps() {
+ COND_HOOK(OnPlayerUpdate, CVAR_EXTRA_TRAPS_VALUE, OnPlayerUpdate);
+
+ COND_VB_SHOULD(VB_SHORT_CIRCUIT_GIVE_ITEM_PROCESS, true, {
+ if (!gSaveContext.ship.pendingIceTrapCount) {
+ return;
+ }
+
+ Player* player = GET_PLAYER(gPlayState);
+
+ *should = true;
+ gSaveContext.ship.pendingIceTrapCount--;
+ gSaveContext.ship.stats.count[COUNT_ICE_TRAPS]++;
+ GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP));
+ if (CVAR_EXTRA_TRAPS_VALUE) {
+ RollRandomTrap(gPlayState->sceneNum + player->getItemEntry.drawItemId);
+ } else {
+ GameInteractor::RawAction::FreezePlayer();
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME });
+
+
diff --git a/soh/soh/Enhancements/FileSelectEnhancements.cpp b/soh/soh/Enhancements/FileSelectEnhancements.cpp
index 43b2f1966..84cff9d12 100644
--- a/soh/soh/Enhancements/FileSelectEnhancements.cpp
+++ b/soh/soh/Enhancements/FileSelectEnhancements.cpp
@@ -13,7 +13,7 @@ std::array RandomizerSettingsMenuText[RSM_MAX] = {
// German
"Start Randomizer",
// French
- "Start Randomizer",
+ "Commencer le Randomizer",
},
{
// English
@@ -21,7 +21,7 @@ std::array RandomizerSettingsMenuText[RSM_MAX] = {
// German
"Generate New Randomizer Seed",
// French
- "Generate New Randomizer Seed",
+ "Générer une nouvelle seed pour le Randomizer",
},
{
// English
@@ -29,7 +29,7 @@ std::array RandomizerSettingsMenuText[RSM_MAX] = {
// German
"Open Randomizer Settings",
// French
- "Open Randomizer Settings",
+ "Ouvrir les paramètres du Randomizer",
},
{
// English
@@ -37,7 +37,7 @@ std::array RandomizerSettingsMenuText[RSM_MAX] = {
// German
"Generating...",
// French
- "Generating...",
+ "Génération en cours...",
},
{
// English
diff --git a/soh/soh/Enhancements/Restorations/PauseBufferInputs.cpp b/soh/soh/Enhancements/Restorations/PauseBufferInputs.cpp
new file mode 100644
index 000000000..4604c00ca
--- /dev/null
+++ b/soh/soh/Enhancements/Restorations/PauseBufferInputs.cpp
@@ -0,0 +1,83 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+#include "variables.h"
+#include "overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h"
+}
+
+#define CVAR_BUFFER_NAME CVAR_ENHANCEMENT("PauseBufferWindow")
+#define CVAR_BUFFER_DEFAULT 0
+#define CVAR_BUFFER_VALUE CVarGetInteger(CVAR_BUFFER_NAME, CVAR_BUFFER_DEFAULT)
+
+#define CVAR_INCLUDE_NAME CVAR_ENHANCEMENT("IncludeHeldInputsBufferWindow")
+#define CVAR_INCLUDE_DEFAULT 0
+#define CVAR_INCLUDE_VALUE CVarGetInteger(CVAR_INCLUDE_NAME, CVAR_INCLUDE_DEFAULT)
+
+#define CVAR_FRAME_ADVANCE_NAME CVAR_CHEAT("EasyFrameAdvance")
+#define CVAR_FRAME_ADVANCE_DEFAULT 0
+#define CVAR_FRAME_ADVANCE_VALUE CVarGetInteger(CVAR_FRAME_ADVANCE_NAME, CVAR_FRAME_ADVANCE_DEFAULT)
+
+static u16 inputBufferTimer = 0;
+static u16 prePauseInputs = 0;
+static u16 pauseInputs = 0;
+#define PAUSE_STATE_OFF 0
+#define PAUSE_STATE_OPENING_1 2
+#define PAUSE_STATE_UNPAUSE_SETUP 18
+
+void RegisterPauseBufferInputs() {
+ COND_VB_SHOULD(VB_KALEIDO_UNPAUSE_CLOSE, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, {
+ Input* input = &gPlayState->state.input[0];
+
+ // Store all inputs that were pressed during the buffer window
+ pauseInputs |= input->press.button;
+
+ // If the user opts to include held inputs in the buffer window, store the held inputs, minus the held inputs when the pause menu was opened
+ if (CVAR_INCLUDE_VALUE && inputBufferTimer == 0) {
+ pauseInputs |= input->cur.button & ~prePauseInputs;
+ prePauseInputs = 0;
+ }
+
+ // Wait a specified number of frames before continuing the unpause
+ inputBufferTimer++;
+ if (inputBufferTimer < CVAR_BUFFER_VALUE) {
+ *should = false;
+ }
+ });
+
+ COND_HOOK(OnGameStateMainStart, CVAR_BUFFER_VALUE || CVAR_INCLUDE_VALUE, []() {
+ if (gPlayState == NULL) {
+ return;
+ }
+
+ Input* input = &gPlayState->state.input[0];
+ PauseContext* pauseCtx = &gPlayState->pauseCtx;
+
+ // if the input buffer timer is not 0 and the pause state is off, then the player just unpaused
+ if (inputBufferTimer != 0 && pauseCtx->state == PAUSE_STATE_OFF) {
+ inputBufferTimer = 0;
+
+ // If the user opts into easy frame advance, remove START input
+ if (CVAR_FRAME_ADVANCE_VALUE) {
+ pauseInputs &= ~BTN_START;
+ }
+
+ // So we need to re-apply the inputs that were pressed during the buffer window
+ input->press.button |= pauseInputs;
+ }
+
+ // Reset the timer and stored inputs at the beginning of the unpause process
+ if (pauseCtx->state == PAUSE_STATE_UNPAUSE_SETUP && pauseCtx->unk_1F4 != 160.0f) {
+ inputBufferTimer = 0;
+ pauseInputs = 0;
+ }
+
+ // If the user opts to include held inputs in the buffer window, store the held inputs at the beginning of the pause process, minus the START input
+ if (pauseCtx->state == PAUSE_STATE_OPENING_1 && CVAR_INCLUDE_VALUE) {
+ prePauseInputs = input->cur.button & ~BTN_START;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterPauseBufferInputs, { CVAR_BUFFER_NAME, CVAR_INCLUDE_NAME });
diff --git a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp
index cb9dfbb46..09f037570 100644
--- a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp
+++ b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp
@@ -196,7 +196,6 @@ void TimeDisplayWindow::Draw() {
uint16_t textureIndex = 0;
for (size_t i = 0; i < textLength; i++) {
- ImVec2 originalCursorPos = ImGui::GetCursorPos();
if (textToDecode[i] == ':' || textToDecode[i] == '.') {
textureIndex = 10;
} else {
diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp
index 9f9b67fec..c9a999cb1 100644
--- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp
+++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp
@@ -10,7 +10,7 @@ extern "C" {
#include "variables.h"
}
-#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
+#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
static bool sEnteredBlueWarp = false;
diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c
index c010067da..ac2ae2bc5 100644
--- a/soh/soh/Enhancements/bootcommands.c
+++ b/soh/soh/Enhancements/bootcommands.c
@@ -12,14 +12,6 @@
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
-uint8_t gLoadFileSelect = 0, gSkipLogoTest = 0;
-
-extern BootCommandFunc BootCommands_Command_SkipLogo(char** argv, s32 argc);
-extern BootCommandFunc BootCommands_Command_LoadFileSelect(char** argv, s32 argc);
-
-static BootCommand sCommands[] = { { "--skiplogo", BootCommands_Command_SkipLogo },
- { "--loadfileselect", BootCommands_Command_LoadFileSelect } };
-
void BootCommands_Init()
{
// Clears vars to prevent randomizer menu from being disabled
@@ -28,48 +20,7 @@ void BootCommands_Init()
CVarClear(CVAR_GENERAL("OnFileSelectNameEntry")); // Clear when soh is killed on the file name entry page
CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQMode"));
CVarClear(CVAR_GENERAL("BetterDebugWarpScreenMQModeScene"));
- CVarClear(CVAR_GENERAL("CheatEasyPauseBufferLastInputs"));
- CVarClear(CVAR_GENERAL("CheatEasyPauseBufferTimer"));
#if defined(__SWITCH__) || defined(__WIIU__)
CVarRegisterInteger(CVAR_IMGUI_CONTROLLER_NAV, 1); // always enable controller nav on switch/wii u
#endif
}
-
-//void BootCommands_ParseBootArgs(char* str)
-void BootCommands_ParseBootArgs(s32 argc, char** argv)
-{
- s32 i;
-
- // Parse the commands
- for (i = 0; i < argc; i++) {
- s32 j;
-
- for (j = 0; j < ARRAY_COUNT(sCommands); j++) {
- if (!strcmp(argv[i], sCommands[j].name)) {
- s32 numArgsProcessed = sCommands[j].func(&argv[i], argc - i);
- i += numArgsProcessed;
- break;
- }
- }
- }
-}
-
-/*
- * Command Name: --skiplogo
- * Description: Skips the N64 Logo Screen
- * Arguments: None
- */
-BootCommandFunc BootCommands_Command_SkipLogo(char** argv, s32 argc) {
- gSkipLogoTest = 1;
- return 0;
-}
-
-/*
- * Command Name: --loadfileselect
- * Description: Loads the file select screen on bootup.
- * Arguments: None
- */
-BootCommandFunc BootCommands_Command_LoadFileSelect(char** argv, s32 argc) {
- gLoadFileSelect = 1;
- return 0;
-}
diff --git a/soh/soh/Enhancements/bootcommands.h b/soh/soh/Enhancements/bootcommands.h
index fdf362e97..5c6cb8c8c 100644
--- a/soh/soh/Enhancements/bootcommands.h
+++ b/soh/soh/Enhancements/bootcommands.h
@@ -3,19 +3,6 @@
#include
#include
-typedef s32 (*BootCommandFunc)(char** argv, s32 argc); // Returns the number of arguments it read
-
-typedef struct BootCommand
-{
- char* name;
- BootCommandFunc func;
-} BootCommand;
-
-extern uint8_t gLoadFileSelect;
-extern uint8_t gSkipLogoTest;
-
void BootCommands_Init();
-//void BootCommands_ParseBootArgs(char* str);
-void BootCommands_ParseBootArgs(s32 argc, char** argv);
#endif
\ No newline at end of file
diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp
index 492517738..7967c3d15 100644
--- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp
+++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp
@@ -46,13 +46,6 @@ void SohInputEditorWindow::InitElement() {
addButtonName(BTN_DLEFT, "D-pad left");
addButtonName(BTN_DRIGHT, "D-pad right");
addButtonName(0, "None");
-
- mDeviceIndexVisiblity.clear();
- mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = true;
- mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Blue] = true;
- for (auto index = 1; index < Ship::ShipDeviceIndex::Max; index++) {
- mDeviceIndexVisiblity[static_cast(index)] = false;
- }
}
#define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929
@@ -176,6 +169,9 @@ void SohInputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, fl
#define BUTTON_COLOR_KEYBOARD_BEIGE ImVec4(0.651f, 0.482f, 0.357f, 0.5f)
#define BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED ImVec4(0.651f, 0.482f, 0.357f, 1.0f)
+#define BUTTON_COLOR_MOUSE_BEIGE ImVec4(0.5f, 0.5f, 0.5f, 0.5f)
+#define BUTTON_COLOR_MOUSE_BEIGE_HOVERED ImVec4(0.5f, 0.5f, 0.5f, 1.0f)
+
#define BUTTON_COLOR_GAMEPAD_BLUE ImVec4(0.0f, 0.255f, 0.976f, 0.5f)
#define BUTTON_COLOR_GAMEPAD_BLUE_HOVERED ImVec4(0.0f, 0.255f, 0.976f, 1.0f)
@@ -191,29 +187,21 @@ void SohInputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, fl
#define BUTTON_COLOR_GAMEPAD_PURPLE ImVec4(0.431f, 0.369f, 0.706f, 0.5f)
#define BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED ImVec4(0.431f, 0.369f, 0.706f, 1.0f)
-void SohInputEditorWindow::GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor,
+void SohInputEditorWindow::GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor) {
switch (lusIndex) {
- case Ship::ShipDeviceIndex::Keyboard:
+ case Ship::PhysicalDeviceType::Keyboard:
buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE;
buttonHoveredColor = BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED;
break;
- case Ship::ShipDeviceIndex::Blue:
+ case Ship::PhysicalDeviceType::Mouse:
+ buttonColor = BUTTON_COLOR_MOUSE_BEIGE;
+ buttonHoveredColor = BUTTON_COLOR_MOUSE_BEIGE_HOVERED;
+ break;
+ case Ship::PhysicalDeviceType::SDLGamepad:
buttonColor = BUTTON_COLOR_GAMEPAD_BLUE;
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_BLUE_HOVERED;
break;
- case Ship::ShipDeviceIndex::Red:
- buttonColor = BUTTON_COLOR_GAMEPAD_RED;
- buttonHoveredColor = BUTTON_COLOR_GAMEPAD_RED_HOVERED;
- break;
- case Ship::ShipDeviceIndex::Orange:
- buttonColor = BUTTON_COLOR_GAMEPAD_ORANGE;
- buttonHoveredColor = BUTTON_COLOR_GAMEPAD_ORANGE_HOVERED;
- break;
- case Ship::ShipDeviceIndex::Green:
- buttonColor = BUTTON_COLOR_GAMEPAD_GREEN;
- buttonHoveredColor = BUTTON_COLOR_GAMEPAD_GREEN_HOVERED;
- break;
default:
buttonColor = BUTTON_COLOR_GAMEPAD_PURPLE;
buttonHoveredColor = BUTTON_COLOR_GAMEPAD_PURPLE_HOVERED;
@@ -266,9 +254,6 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
if (mapping == nullptr) {
return;
}
- if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) {
- return;
- }
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
std::string icon = "";
@@ -287,7 +272,7 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
auto physicalInputDisplayName =
StringHelper::Sprintf("%s %s", icon.c_str(), mapping->GetPhysicalInputName().c_str());
- GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
+ GetButtonColorsForDeviceType(mapping->GetPhysicalDeviceType(), buttonColor, buttonHoveredColor);
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
auto popupId = StringHelper::Sprintf("editButtonMappingPopup##%s", id.c_str());
@@ -324,19 +309,12 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
ImGui::PopStyleVar();
ImGui::SameLine(0, 0);
-#ifndef __WIIU__
auto sdlAxisDirectionToButtonMapping = std::dynamic_pointer_cast(mapping);
- auto indexMapping = Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetDeviceIndexMappingFromShipDeviceIndex(mapping->GetShipDeviceIndex());
- auto sdlIndexMapping = std::dynamic_pointer_cast(indexMapping);
-
- if (sdlIndexMapping != nullptr && sdlAxisDirectionToButtonMapping != nullptr) {
+ if (sdlAxisDirectionToButtonMapping != nullptr) {
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
+ GetButtonColorsForDeviceType(mapping->GetPhysicalDeviceType(), buttonColor, buttonHoveredColor);
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f));
@@ -357,17 +335,19 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
ImGui::Text("Axis Threshold\n\nThe extent to which the joystick\nmust be moved or the trigger\npressed to "
"initiate the assigned\nbutton action.\n\n");
+ auto globalSettings = Ship::Context::GetInstance()->GetControlDeck()->GetGlobalSDLDeviceSettings();
+
if (sdlAxisDirectionToButtonMapping->AxisIsStick()) {
ImGui::Text("Stick axis threshold:");
- int32_t stickAxisThreshold = sdlIndexMapping->GetStickAxisThresholdPercentage();
+ int32_t stickAxisThreshold = globalSettings->GetStickAxisThresholdPercentage();
if (stickAxisThreshold == 0) {
ImGui::BeginDisabled();
}
ImGui::PushButtonRepeat(true);
if (ImGui::Button(StringHelper::Sprintf("-##Stick Axis Threshold%s", id.c_str()).c_str())) {
- sdlIndexMapping->SetStickAxisThresholdPercentage(stickAxisThreshold - 1);
- sdlIndexMapping->SaveToConfig();
+ globalSettings->SetStickAxisThresholdPercentage(stickAxisThreshold - 1);
+ globalSettings->SaveToConfig();
}
ImGui::PopButtonRepeat();
if (stickAxisThreshold == 0) {
@@ -377,8 +357,8 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
if (ImGui::SliderInt(StringHelper::Sprintf("##Stick Axis Threshold%s", id.c_str()).c_str(),
&stickAxisThreshold, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
- sdlIndexMapping->SetStickAxisThresholdPercentage(stickAxisThreshold);
- sdlIndexMapping->SaveToConfig();
+ globalSettings->SetStickAxisThresholdPercentage(stickAxisThreshold);
+ globalSettings->SaveToConfig();
}
ImGui::SameLine(0.0f, 0.0f);
if (stickAxisThreshold == 100) {
@@ -386,8 +366,8 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
}
ImGui::PushButtonRepeat(true);
if (ImGui::Button(StringHelper::Sprintf("+##Stick Axis Threshold%s", id.c_str()).c_str())) {
- sdlIndexMapping->SetStickAxisThresholdPercentage(stickAxisThreshold + 1);
- sdlIndexMapping->SaveToConfig();
+ globalSettings->SetStickAxisThresholdPercentage(stickAxisThreshold + 1);
+ globalSettings->SaveToConfig();
}
ImGui::PopButtonRepeat();
if (stickAxisThreshold == 100) {
@@ -398,14 +378,14 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
if (sdlAxisDirectionToButtonMapping->AxisIsTrigger()) {
ImGui::Text("Trigger axis threshold:");
- int32_t triggerAxisThreshold = sdlIndexMapping->GetTriggerAxisThresholdPercentage();
+ int32_t triggerAxisThreshold = globalSettings->GetTriggerAxisThresholdPercentage();
if (triggerAxisThreshold == 0) {
ImGui::BeginDisabled();
}
ImGui::PushButtonRepeat(true);
if (ImGui::Button(StringHelper::Sprintf("-##Trigger Axis Threshold%s", id.c_str()).c_str())) {
- sdlIndexMapping->SetTriggerAxisThresholdPercentage(triggerAxisThreshold - 1);
- sdlIndexMapping->SaveToConfig();
+ globalSettings->SetTriggerAxisThresholdPercentage(triggerAxisThreshold - 1);
+ globalSettings->SaveToConfig();
}
ImGui::PopButtonRepeat();
if (triggerAxisThreshold == 0) {
@@ -415,8 +395,8 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
ImGui::SetNextItemWidth(SCALE_IMGUI_SIZE(160.0f));
if (ImGui::SliderInt(StringHelper::Sprintf("##Trigger Axis Threshold%s", id.c_str()).c_str(),
&triggerAxisThreshold, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp)) {
- sdlIndexMapping->SetTriggerAxisThresholdPercentage(triggerAxisThreshold);
- sdlIndexMapping->SaveToConfig();
+ globalSettings->SetTriggerAxisThresholdPercentage(triggerAxisThreshold);
+ globalSettings->SaveToConfig();
}
ImGui::SameLine(0.0f, 0.0f);
if (triggerAxisThreshold == 100) {
@@ -424,8 +404,8 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
}
ImGui::PushButtonRepeat(true);
if (ImGui::Button(StringHelper::Sprintf("+##Trigger Axis Threshold%s", id.c_str()).c_str())) {
- sdlIndexMapping->SetTriggerAxisThresholdPercentage(triggerAxisThreshold + 1);
- sdlIndexMapping->SaveToConfig();
+ globalSettings->SetTriggerAxisThresholdPercentage(triggerAxisThreshold + 1);
+ globalSettings->SaveToConfig();
}
ImGui::PopButtonRepeat();
if (triggerAxisThreshold == 100) {
@@ -444,7 +424,6 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, N64Butt
ImGui::PopStyleVar();
ImGui::SameLine(0, 0);
}
-#endif
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
@@ -539,9 +518,6 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port,
if (mapping == nullptr) {
return;
}
- if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) {
- return;
- }
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f));
std::string icon = "";
@@ -560,7 +536,7 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port,
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
auto physicalInputDisplayName =
StringHelper::Sprintf("%s %s", icon.c_str(), mapping->GetPhysicalInputName().c_str());
- GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
+ GetButtonColorsForDeviceType(mapping->GetPhysicalDeviceType(), buttonColor, buttonHoveredColor);
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
auto popupId = StringHelper::Sprintf("editStickDirectionMappingPopup##%s", id.c_str());
@@ -885,7 +861,7 @@ void SohInputEditorWindow::DrawRumbleSection(uint8_t port) {
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
+ GetButtonColorsForDeviceType(mapping->GetPhysicalDeviceType(), buttonColor, buttonHoveredColor);
// begin hackaround https://github.com/ocornut/imgui/issues/282#issuecomment-123763192
// spaces to have background color for text in a tree node
std::string spaces = "";
@@ -1256,209 +1232,6 @@ void SohInputEditorWindow::DrawGyroSection(uint8_t port) {
}
}
-void SohInputEditorWindow::DrawButtonDeviceIcons(uint8_t portIndex, std::set bitmasks) {
- std::set allLusDeviceIndices;
- allLusDeviceIndices.insert(Ship::ShipDeviceIndex::Keyboard);
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappingsFromConfig()) {
- allLusDeviceIndices.insert(lusIndex);
- }
-
- std::vector> lusDeviceIndiciesWithMappings;
- for (auto lusIndex : allLusDeviceIndices) {
- for (auto [bitmask, button] :
- Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetAllButtons()) {
- if (!bitmasks.contains(bitmask)) {
- continue;
- }
-
- if (button->HasMappingsForShipDeviceIndex(lusIndex)) {
- for (auto [id, mapping] : button->GetAllButtonMappings()) {
- if (mapping->GetShipDeviceIndex() == lusIndex) {
- lusDeviceIndiciesWithMappings.push_back(
- std::pair(lusIndex, mapping->PhysicalDeviceIsConnected()));
- break;
- }
- }
- break;
- }
- }
- }
-
- for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
- auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
- auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
- ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- ImGui::SameLine();
- if (lusIndex == Ship::ShipDeviceIndex::Keyboard) {
- ImGui::SmallButton(ICON_FA_KEYBOARD_O);
- } else {
- ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
- }
- ImGui::PopStyleColor();
- ImGui::PopStyleColor();
- }
-}
-
-void SohInputEditorWindow::DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::StickIndex stickIndex) {
- std::set allLusDeviceIndices;
- allLusDeviceIndices.insert(Ship::ShipDeviceIndex::Keyboard);
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappingsFromConfig()) {
- allLusDeviceIndices.insert(lusIndex);
- }
-
- std::vector> lusDeviceIndiciesWithMappings;
- for (auto lusIndex : allLusDeviceIndices) {
- auto controllerStick =
- stickIndex == Ship::StickIndex::LEFT_STICK
- ? Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetLeftStick()
- : Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetRightStick();
- if (controllerStick->HasMappingsForShipDeviceIndex(lusIndex)) {
- for (auto [direction, mappings] : controllerStick->GetAllAxisDirectionMappings()) {
- bool foundMapping = false;
- for (auto [id, mapping] : mappings) {
- if (mapping->GetShipDeviceIndex() == lusIndex) {
- foundMapping = true;
- lusDeviceIndiciesWithMappings.push_back(
- std::pair(lusIndex, mapping->PhysicalDeviceIsConnected()));
- break;
- }
- }
- if (foundMapping) {
- break;
- }
- }
- }
- }
-
- for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
- auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
- auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
- ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- ImGui::SameLine();
- if (lusIndex == Ship::ShipDeviceIndex::Keyboard) {
- ImGui::SmallButton(ICON_FA_KEYBOARD_O);
- } else {
- ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
- }
- ImGui::PopStyleColor();
- ImGui::PopStyleColor();
- }
-}
-
-void SohInputEditorWindow::DrawRumbleDeviceIcons(uint8_t portIndex) {
- std::set allLusDeviceIndices;
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappingsFromConfig()) {
- allLusDeviceIndices.insert(lusIndex);
- }
-
- std::vector> lusDeviceIndiciesWithMappings;
- for (auto lusIndex : allLusDeviceIndices) {
- if (Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetControllerByPort(portIndex)
- ->GetRumble()
- ->HasMappingsForShipDeviceIndex(lusIndex)) {
- for (auto [id, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetControllerByPort(portIndex)
- ->GetRumble()
- ->GetAllRumbleMappings()) {
- if (mapping->GetShipDeviceIndex() == lusIndex) {
- lusDeviceIndiciesWithMappings.push_back(
- std::pair(lusIndex, mapping->PhysicalDeviceIsConnected()));
- break;
- }
- }
- }
- }
-
- for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
- auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
- auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
- ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- ImGui::SameLine();
- ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
- ImGui::PopStyleColor();
- ImGui::PopStyleColor();
- }
-}
-
-void SohInputEditorWindow::DrawGyroDeviceIcons(uint8_t portIndex) {
- auto mapping =
- Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->GetGyro()->GetGyroMapping();
- if (mapping == nullptr) {
- return;
- }
-
- auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
- auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(mapping->GetShipDeviceIndex(), buttonColor, buttonHoveredColor);
- ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- ImGui::SameLine();
- ImGui::SmallButton(mapping->PhysicalDeviceIsConnected() ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
- ImGui::PopStyleColor();
- ImGui::PopStyleColor();
-}
-
-void SohInputEditorWindow::DrawLEDDeviceIcons(uint8_t portIndex) {
- std::set allLusDeviceIndices;
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappingsFromConfig()) {
- allLusDeviceIndices.insert(lusIndex);
- }
-
- std::vector> lusDeviceIndiciesWithMappings;
- for (auto lusIndex : allLusDeviceIndices) {
- if (Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetControllerByPort(portIndex)
- ->GetRumble()
- ->HasMappingsForShipDeviceIndex(lusIndex)) {
- for (auto [id, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetControllerByPort(portIndex)
- ->GetLED()
- ->GetAllLEDMappings()) {
- if (mapping->GetShipDeviceIndex() == lusIndex) {
- lusDeviceIndiciesWithMappings.push_back(
- std::pair(lusIndex, mapping->PhysicalDeviceIsConnected()));
- break;
- }
- }
- }
- }
-
- for (auto [lusIndex, connected] : lusDeviceIndiciesWithMappings) {
- auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
- auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
- ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- ImGui::SameLine();
- ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN);
- ImGui::PopStyleColor();
- ImGui::PopStyleColor();
- }
-}
-
const ImGuiTableFlags PANEL_TABLE_FLAGS =
ImGuiTableFlags_BordersH |
ImGuiTableFlags_BordersV;
@@ -1651,66 +1424,52 @@ void SohInputEditorWindow::DrawDpadControlPanel() {
Ship::GuiWindow::EndGroupPanel(0);
}
-void SohInputEditorWindow::DrawDeviceVisibilityButtons() {
- std::map> indexMappings;
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappingsFromConfig()) {
- auto sdlIndexMapping = std::static_pointer_cast(mapping);
- if (sdlIndexMapping == nullptr) {
- continue;
- }
-
- indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 };
- }
-
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappings()) {
- auto sdlIndexMapping = std::static_pointer_cast(mapping);
- if (sdlIndexMapping == nullptr) {
- continue;
- }
-
- indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() };
- }
+void SohInputEditorWindow::DrawDeviceToggles(uint8_t portIndex) {
+ ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
auto keyboardButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
auto keyboardButtonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex::Keyboard, keyboardButtonColor, keyboardButtonHoveredColor);
+ GetButtonColorsForDeviceType(Ship::PhysicalDeviceType::Keyboard, keyboardButtonColor, keyboardButtonHoveredColor);
ImGui::PushStyleColor(ImGuiCol_Button, keyboardButtonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, keyboardButtonHoveredColor);
- bool keyboardVisible = mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard];
- if(ImGui::Button(
- StringHelper::Sprintf("%s %s Keyboard", keyboardVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, ICON_FA_KEYBOARD_O)
- .c_str())) {
- mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = !keyboardVisible;
- }
+ ImGui::Button(StringHelper::Sprintf("%s Keyboard", ICON_FA_KEYBOARD_O).c_str());
ImGui::PopStyleColor();
ImGui::PopStyleColor();
+ auto mouseButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
+ auto mouseButtonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
+ GetButtonColorsForDeviceType(Ship::PhysicalDeviceType::Mouse, mouseButtonColor, mouseButtonHoveredColor);
+ ImGui::PushStyleColor(ImGuiCol_Button, mouseButtonColor);
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, mouseButtonHoveredColor);
+ ImGui::Button(StringHelper::Sprintf("%s Mouse", ICON_FA_KEYBOARD_O).c_str());
+ ImGui::PopStyleColor();
+ ImGui::PopStyleColor();
- for (auto [lusIndex, info] : indexMappings) {
- auto [name, sdlIndex] = info;
- bool connected = sdlIndex != -1;
+ ImGui::PopItemFlag();
+ auto connectedDeviceManager = Ship::Context::GetInstance()->GetControlDeck()->GetConnectedPhysicalDeviceManager();
+ for (const auto& [instanceId, name] : connectedDeviceManager->GetConnectedSDLGamepadNames()) {
+ ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
-
+ GetButtonColorsForDeviceType(Ship::PhysicalDeviceType::SDLGamepad, buttonColor, buttonHoveredColor);
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- bool visible = mDeviceIndexVisiblity[lusIndex];
- if(ImGui::Button(
- StringHelper::Sprintf("%s %s %s (%s)", visible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, name.c_str(),
- connected ? StringHelper::Sprintf("SDL %d", sdlIndex).c_str() : "Disconnected")
- .c_str())) {
- mDeviceIndexVisiblity[lusIndex] = !visible;
- }
+ auto notIgnored = !connectedDeviceManager->PortIsIgnoringInstanceId(portIndex, instanceId);
+ ImGui::PopItemFlag();
+ if(ImGui::Checkbox(StringHelper::Sprintf("###instanceId_%d", instanceId).c_str(), ¬Ignored)) {
+ if (notIgnored) {
+ connectedDeviceManager->UnignoreInstanceIdForPort(portIndex, instanceId);
+ } else {
+ connectedDeviceManager->IgnoreInstanceIdForPort(portIndex, instanceId);
+ }
+ };
+ ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
+ ImGui::SameLine();
+ ImGui::Button(StringHelper::Sprintf("%s %s (SDL)", ICON_FA_GAMEPAD, name.c_str()).c_str());
ImGui::PopStyleColor();
ImGui::PopStyleColor();
+ ImGui::PopItemFlag();
}
}
@@ -1719,7 +1478,7 @@ void SohInputEditorWindow::DrawLinkTab() {
if (ImGui::BeginTabItem(StringHelper::Sprintf("Link (P1)###port%d", portIndex).c_str())) {
DrawClearAllButton(portIndex);
DrawSetDefaultsButton(portIndex);
- DrawDeviceVisibilityButtons();
+ DrawDeviceToggles(portIndex);
UpdateBitmaskToMappingIds(portIndex);
UpdateStickDirectionToMappingIds(portIndex);
@@ -1729,7 +1488,6 @@ void SohInputEditorWindow::DrawLinkTab() {
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
if (ImGui::CollapsingHeader("Buttons", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
DrawButtonLine("A", portIndex, BTN_A, CHIP_COLOR_N64_BLUE);
DrawButtonLine("B", portIndex, BTN_B, CHIP_COLOR_N64_GREEN);
DrawButtonLine("Start", portIndex, BTN_START, CHIP_COLOR_N64_RED);
@@ -1744,57 +1502,36 @@ void SohInputEditorWindow::DrawLinkTab() {
CHIP_COLOR_N64_YELLOW);
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_CRIGHT,
CHIP_COLOR_N64_YELLOW);
- } else {
- DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
}
if (ImGui::CollapsingHeader("D-Pad", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_DUP);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_DDOWN);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_DLEFT);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_DRIGHT);
- } else {
- DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
}
if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
DrawStickSection(portIndex, Ship::LEFT, 0);
- } else {
- DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
}
if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) {
- DrawAnalogStickDeviceIcons(portIndex, Ship::RIGHT_STICK);
DrawStickSection(portIndex, Ship::RIGHT, 1, CHIP_COLOR_N64_YELLOW);
- } else {
- DrawAnalogStickDeviceIcons(portIndex, Ship::RIGHT_STICK);
}
if (ImGui::CollapsingHeader("Rumble")) {
- DrawRumbleDeviceIcons(portIndex);
DrawRumbleSection(portIndex);
- } else {
- DrawRumbleDeviceIcons(portIndex);
}
if (ImGui::CollapsingHeader("Gyro")) {
- DrawGyroDeviceIcons(portIndex);
DrawGyroSection(portIndex);
- } else {
- DrawGyroDeviceIcons(portIndex);
}
if (ImGui::CollapsingHeader("LEDs")) {
- DrawLEDDeviceIcons(portIndex);
DrawLEDSection(portIndex);
- } else {
- DrawLEDDeviceIcons(portIndex);
}
if (ImGui::CollapsingHeader("Modifier Buttons")) {
- DrawButtonDeviceIcons(portIndex, mModifierButtonsBitmasks);
DrawButtonLine("M1", portIndex, BTN_CUSTOM_MODIFIER1);
DrawButtonLine("M2", portIndex, BTN_CUSTOM_MODIFIER2);
@@ -1827,15 +1564,10 @@ void SohInputEditorWindow::DrawLinkTab() {
Ship::GuiWindow::EndGroupPanel(0);
}
ImGui::EndDisabled();
- } else {
- DrawButtonDeviceIcons(portIndex, mModifierButtonsBitmasks);
}
if (ImGui::CollapsingHeader("Ocarina Controls")) {
- DrawButtonDeviceIcons(portIndex, mCustomOcarinaButtonsBitmasks);
DrawOcarinaControlPanel();
- } else {
- DrawButtonDeviceIcons(portIndex, mCustomOcarinaButtonsBitmasks);
}
if (ImGui::CollapsingHeader("Camera Controls")) {
@@ -1875,7 +1607,7 @@ void SohInputEditorWindow::DrawIvanTab() {
if (ImGui::BeginTabItem(StringHelper::Sprintf("Ivan (P2)###port%d", portIndex).c_str())) {
DrawClearAllButton(portIndex);
DrawSetDefaultsButton(portIndex);
- DrawDeviceVisibilityButtons();
+ DrawDeviceToggles(portIndex);
UpdateBitmaskToMappingIds(portIndex);
UpdateStickDirectionToMappingIds(portIndex);
@@ -1885,7 +1617,6 @@ void SohInputEditorWindow::DrawIvanTab() {
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
if (ImGui::CollapsingHeader("Buttons", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
DrawButtonLine("A", portIndex, BTN_A, CHIP_COLOR_N64_BLUE);
DrawButtonLine("B", portIndex, BTN_B, CHIP_COLOR_N64_GREEN);
DrawButtonLine("Z", portIndex, BTN_Z);
@@ -1897,25 +1628,17 @@ void SohInputEditorWindow::DrawIvanTab() {
CHIP_COLOR_N64_YELLOW);
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_CRIGHT,
CHIP_COLOR_N64_YELLOW);
- } else {
- DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
}
if (ImGui::CollapsingHeader("D-Pad", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_DUP);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_DDOWN);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_DLEFT);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_DRIGHT);
- } else {
- DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
}
if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
DrawStickSection(portIndex, Ship::LEFT, 0);
- } else {
- DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
}
ImGui::PopStyleColor();
@@ -1931,7 +1654,7 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo
: customName.c_str())) {
DrawClearAllButton(portIndex);
DrawSetDefaultsButton(portIndex);
- DrawDeviceVisibilityButtons();
+ DrawDeviceToggles(portIndex);
UpdateBitmaskToMappingIds(portIndex);
UpdateStickDirectionToMappingIds(portIndex);
@@ -1941,7 +1664,6 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
if (ImGui::CollapsingHeader("Buttons", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
DrawButtonLine("A", portIndex, BTN_A, CHIP_COLOR_N64_BLUE);
DrawButtonLine("B", portIndex, BTN_B, CHIP_COLOR_N64_GREEN);
DrawButtonLine("Start", portIndex, BTN_START, CHIP_COLOR_N64_RED);
@@ -1956,25 +1678,16 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo
CHIP_COLOR_N64_YELLOW);
DrawButtonLine(StringHelper::Sprintf("C %s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_CRIGHT,
CHIP_COLOR_N64_YELLOW);
- } else {
- DrawButtonDeviceIcons(portIndex, mButtonsBitmasks);
}
-
if (ImGui::CollapsingHeader("D-Pad", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_UP).c_str(), portIndex, BTN_DUP);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_DOWN).c_str(), portIndex, BTN_DDOWN);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_LEFT).c_str(), portIndex, BTN_DLEFT);
DrawButtonLine(StringHelper::Sprintf("%s", ICON_FA_ARROW_RIGHT).c_str(), portIndex, BTN_DRIGHT);
- } else {
- DrawButtonDeviceIcons(portIndex, mDpadBitmasks);
}
if (ImGui::CollapsingHeader("Analog Stick", NULL, ImGuiTreeNodeFlags_DefaultOpen)) {
- DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
DrawStickSection(portIndex, Ship::LEFT, 0);
- } else {
- DrawAnalogStickDeviceIcons(portIndex, Ship::LEFT_STICK);
}
ImGui::PopStyleColor();
@@ -2010,19 +1723,6 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
}
if (ImGui::BeginPopup(popupId.c_str())) {
- std::map> indexMappings;
- for (auto [lusIndex, mapping] : Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetDeviceIndexMappingManager()
- ->GetAllDeviceIndexMappings()) {
- auto sdlIndexMapping = std::static_pointer_cast(mapping);
- if (sdlIndexMapping == nullptr) {
- continue;
- }
-
- indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() };
- }
-
bool shouldClose = false;
ImGui::PushStyleColor(ImGuiCol_Button, BUTTON_COLOR_KEYBOARD_BEIGE);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED);
@@ -2041,49 +1741,42 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) {
Ship::Context::GetInstance()
->GetControlDeck()
->GetControllerByPort(portIndex)
- ->ClearAllMappingsForDevice(Ship::ShipDeviceIndex::Keyboard);
+ ->ClearAllMappingsForDeviceType(Ship::PhysicalDeviceType::Keyboard);
Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings(
- Ship::ShipDeviceIndex::Keyboard);
+ Ship::PhysicalDeviceType::Keyboard);
shouldClose = true;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
- for (auto [lusIndex, info] : indexMappings) {
- auto [name, sdlIndex] = info;
- auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
- auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
- GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor);
- ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
- if (ImGui::Button(StringHelper::Sprintf("%s %s (%s)", ICON_FA_GAMEPAD, name.c_str(),
- StringHelper::Sprintf("SDL %d", sdlIndex).c_str())
- .c_str())) {
- ImGui::OpenPopup(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str());
+ auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button);
+ auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
+ GetButtonColorsForDeviceType(Ship::PhysicalDeviceType::SDLGamepad, buttonColor, buttonHoveredColor);
+ ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor);
+ if (ImGui::Button(StringHelper::Sprintf("%s %s", ICON_FA_GAMEPAD, "Gamepad (SDL)").c_str())) {
+ ImGui::OpenPopup("Set Defaults for Gamepad (SDL)");
+ }
+ ImGui::PopStyleColor();
+ ImGui::PopStyleColor();
+ if (ImGui::BeginPopupModal("Set Defaults for Gamepad (SDL)", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
+ ImGui::Text("This will clear all existing mappings for\nGamepad (SDL) on port %d.\n\nContinue?", portIndex + 1);
+ if (ImGui::Button("Cancel")) {
+ shouldClose = true;
+ ImGui::CloseCurrentPopup();
}
- ImGui::PopStyleColor();
- ImGui::PopStyleColor();
- if (ImGui::BeginPopupModal(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str(), NULL,
- ImGuiWindowFlags_AlwaysAutoResize)) {
- ImGui::Text("This will clear all existing mappings for\n%s (SDL %d) on port %d.\n\nContinue?",
- name.c_str(), sdlIndex, portIndex + 1);
- if (ImGui::Button("Cancel")) {
- shouldClose = true;
- ImGui::CloseCurrentPopup();
- }
- if (ImGui::Button("Set defaults")) {
- Ship::Context::GetInstance()
- ->GetControlDeck()
- ->GetControllerByPort(portIndex)
- ->ClearAllMappingsForDevice(lusIndex);
- Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings(
- lusIndex);
- shouldClose = true;
- ImGui::CloseCurrentPopup();
- }
- ImGui::EndPopup();
+ if (ImGui::Button("Set defaults")) {
+ Ship::Context::GetInstance()
+ ->GetControlDeck()
+ ->GetControllerByPort(portIndex)
+ ->ClearAllMappingsForDeviceType(Ship::PhysicalDeviceType::SDLGamepad);
+ Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings(
+ Ship::PhysicalDeviceType::SDLGamepad);
+ shouldClose = true;
+ ImGui::CloseCurrentPopup();
}
+ ImGui::EndPopup();
}
if (ImGui::Button("Cancel") || shouldClose) {
diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.h b/soh/soh/Enhancements/controls/SohInputEditorWindow.h
index fdb3c77b0..4545f771d 100644
--- a/soh/soh/Enhancements/controls/SohInputEditorWindow.h
+++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.h
@@ -83,7 +83,7 @@ class SohInputEditorWindow : public Ship::GuiWindow {
void UpdateBitmaskToMappingIds(uint8_t port);
void UpdateStickDirectionToMappingIds(uint8_t port);
- void GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex lusIndex, ImVec4& buttonColor,
+ void GetButtonColorsForDeviceType(Ship::PhysicalDeviceType lusIndex, ImVec4& buttonColor,
ImVec4& buttonHoveredColor);
void DrawLinkTab();
void DrawIvanTab();
@@ -92,15 +92,9 @@ class SohInputEditorWindow : public Ship::GuiWindow {
std::set mDpadBitmasks;
std::set mModifierButtonsBitmasks;
std::set mCustomOcarinaButtonsBitmasks;
- void DrawButtonDeviceIcons(uint8_t portIndex, std::set bitmasks);
- void DrawAnalogStickDeviceIcons(uint8_t portIndex, Ship::StickIndex stickIndex);
- void DrawRumbleDeviceIcons(uint8_t portIndex);
- void DrawGyroDeviceIcons(uint8_t portIndex);
- void DrawLEDDeviceIcons(uint8_t portIndex);
bool mInputEditorPopupOpen;
void DrawSetDefaultsButton(uint8_t portIndex);
void DrawClearAllButton(uint8_t portIndex);
- std::map mDeviceIndexVisiblity;
- void DrawDeviceVisibilityButtons();
+ void DrawDeviceToggles(uint8_t portIndex);
};
diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
index 2351a8165..45e097df7 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
@@ -32,7 +32,6 @@ extern "C" {
#include "objects/object_st/object_st.h"
#include "objects/object_gi_boomerang/object_gi_boomerang.h"
#include "objects/object_gi_liquid/object_gi_liquid.h"
-#include "objects/object_gi_bow/object_gi_bow.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_gi_sword_1/object_gi_sword_1.h"
@@ -47,9 +46,8 @@ extern "C" {
#include "objects/object_gjyo_objects/object_gjyo_objects.h"
#include "textures/nintendo_rogo_static/nintendo_rogo_static.h"
#include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h"
-#include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h"
#include "overlays/ovl_Magic_Wind/ovl_Magic_Wind.h"
-#include "textures/nintendo_rogo_static/nintendo_rogo_static.h"
+
extern PlayState* gPlayState;
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const char* patchName, int destinationIndex, int sourceIndex);
@@ -74,7 +72,9 @@ std::map groupLabels = {
{ COSMETICS_GROUP_SWORDS, "Swords" },
{ COSMETICS_GROUP_GLOVES, "Gloves" },
{ COSMETICS_GROUP_EQUIPMENT, "Equipment" },
- { COSMETICS_GROUP_KEY, "Keys" },
+ { COSMETICS_GROUP_KEYRING, "Keyring" },
+ { COSMETICS_GROUP_SMALL_KEYS, "Small Keys" },
+ { COSMETICS_GROUP_BOSS_KEYS, "Boss Keys" },
{ COSMETICS_GROUP_CONSUMABLE, "Consumables" },
{ COSMETICS_GROUP_HUD, "HUD" },
{ COSMETICS_GROUP_KALEIDO, "Pause Menu" },
@@ -253,34 +253,41 @@ static std::map cosmeticOptions = {
COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 190, 55, 255), false, true, true),
COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 255, 255, 255), false, true, true),
- COSMETIC_OPTION("Key.KeyringRing", "Key Ring Ring", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.ForestSmallBase", "Forest Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.ForestEmblem", "Forest Key Gem/Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.ForestBossBase", "Forest Boss Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 0, 255), false, true, false),
- COSMETIC_OPTION("Key.FireSmallBase", "Fire Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.FireEmblem", "Fire Key Gem/Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.FireBossBase", "Fire Boss Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 0, 255), false, true, false),
- COSMETIC_OPTION("Key.WaterSmallBase", "Water Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.WaterEmblem", "Water Key Gem/Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.WaterBossBase", "Water Boss Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 0, 255), false, true, false),
- COSMETIC_OPTION("Key.SpiritSmallBase", "Spirit Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.SpiritEmblem", "Spirit Key Gem/Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.SpiritBossBase", "Spirit Boss Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 0, 255), false, true, false),
- COSMETIC_OPTION("Key.ShadowSmallBase", "Shadow Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.ShadowEmblem", "Shadow Key Gem/Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.ShadowBossBase", "Shadow Boss Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 0, 255), false, true, false),
- COSMETIC_OPTION("Key.WellSmallBase", "Well Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.WellEmblem", "Well Key Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.FortSmallBase", "Fortress Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.FortEmblem", "Fortress Key Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.GTGSmallBase", "GTG Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.GTGEmblem", "GTG Key Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.GanonsSmallBase", "Ganon's Small Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- COSMETIC_OPTION("Key.GanonsEmblem", "Ganon's Key Gem/Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.GanonsBossBase", "Ganon's Boss Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 0, 255), false, true, false),
- //COSMETIC_OPTION("Key.ChestGameSmallBase", "Chest Game Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 255, 255), false, true, false),
- //COSMETIC_OPTION("Key.ChestGameEmblem", "Chest Game Key Emblem", COSMETICS_GROUP_KEY, ColorRGBA8(255, 0, 0, 255), false, true, true),
- COSMETIC_OPTION("Key.Skeleton", "Skeleton Key", COSMETICS_GROUP_KEY, ColorRGBA8(255, 255, 170, 255), false, true, false),
+ COSMETIC_OPTION("Key.KeyringRing", "Key Ring Ring", COSMETICS_GROUP_KEYRING, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.ForestSmallBody", "Forest Small Key Body", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.ForestSmallEmblem", "Forest Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(4, 195, 46, 255), false, true, false),
+ COSMETIC_OPTION("Key.ForestBossBody", "Forest Boss Key Body", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 255, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.ForestBossGem", "Forest Boss Key Gem", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.FireSmallBody", "Fire Small Key Body", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.FireSmallEmblem", "Fire Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(237, 95, 95, 255), false, true, false),
+ COSMETIC_OPTION("Key.FireBossBody", "Fire Boss Key Body", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 255, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.FireBossGem", "Fire Boss Key Gem", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.WaterSmallBody", "Water Small Key Body", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.WaterSmallEmblem", "Water Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(85, 180, 223, 255), false, true, false),
+ COSMETIC_OPTION("Key.WaterBossBody", "Water Boss Key Body", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 255, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.WaterBossGem", "Water Boss Key Gem", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.SpiritSmallBody", "Spirit Small Key Body", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.SpiritSmallEmblem", "Spirit Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(222, 158, 47, 255), false, true, false),
+ COSMETIC_OPTION("Key.SpiritBossBody", "Spirit Boss Key Body", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 255, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.SpiritBossGem", "Spirit Boss Key Gem", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.ShadowSmallBody", "Shadow Small Key Body", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.ShadowSmallEmblem", "Shadow Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(126, 16, 177, 255), false, true, false),
+ COSMETIC_OPTION("Key.ShadowBossBody", "Shadow Boss Key Body", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 255, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.ShadowBossGem", "Shadow Boss Key Gem", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.GanonsSmallBody", "Ganons Small Key Body", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.GanonsSmallEmblem", "Ganons Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(80, 80, 80, 255), false, true, false),
+ COSMETIC_OPTION("Key.GanonsBossBody", "Ganons Boss Key Body", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 255, 0, 255), false, true, false),
+ COSMETIC_OPTION("Key.GanonsBossGem", "Ganons Boss Key Gem", COSMETICS_GROUP_BOSS_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, false),
+
+ COSMETIC_OPTION("Key.WellSmallBody", "Well Small Key", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.WellSmallEmblem", "Well Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(227, 110, 255, 255), false, true, true),
+ COSMETIC_OPTION("Key.FortSmallBody", "Fortress Small Key", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.FortSmallEmblem", "Fortress Small Key Emblem",COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, true),
+ COSMETIC_OPTION("Key.GTGSmallBody", "GTG Small Key", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ COSMETIC_OPTION("Key.GTGSmallEmblem", "GTG Small Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(221, 212, 60, 255), false, true, true),
+ //COSMETIC_OPTION("Key.ChestGameSmallBody", "Chest Game Key", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 255, 255), false, true, false),
+ //COSMETIC_OPTION("Key.ChestGameEmblem", "Chest Game Key Emblem", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 0, 0, 255), false, true, true),
+ COSMETIC_OPTION("Key.Skeleton", "Skeleton Key", COSMETICS_GROUP_SMALL_KEYS, ColorRGBA8(255, 255, 170, 255), false, true, false),
COSMETIC_OPTION("HUD.AButton", "A Button", COSMETICS_GROUP_HUD, ColorRGBA8( 90, 90, 255, 255), false, true, false),
COSMETIC_OPTION("HUD.BButton", "B Button", COSMETICS_GROUP_HUD, ColorRGBA8( 0, 150, 0, 255), false, true, false),
@@ -1475,10 +1482,16 @@ void Reset_Option_Double(const char* Button_Title, const char* name) {
void DrawSillyTab() {
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
if (UIWidgets::EnhancementCheckbox("Let It Snow", CVAR_GENERAL("LetItSnow"))) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
UIWidgets::Tooltip("Makes snow fall, changes chest texture colors to red and green, etc, for December holidays.\nWill reset on restart outside of December 23-25.");
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
if (UIWidgets::EnhancementSliderFloat("Link Body Scale: %.3fx", "##Link_BodyScale", CVAR_COSMETIC("Link.BodyScale.Value"), 0.001f, 0.025f, "", 0.01f, true)) {
CVarSetInteger(CVAR_COSMETIC("Link.BodyScale.Changed"), 1);
}
@@ -1494,31 +1507,64 @@ void DrawSillyTab() {
player->actor.scale.z = 0.01f;
}
}
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
if (UIWidgets::EnhancementSliderFloat("Link Head Scale: %.2fx", "##Link_HeadScale", CVAR_COSMETIC("Link.HeadScale.Value"), 0.4f, 4.0f, "", 1.0f, false)) {
CVarSetInteger(CVAR_COSMETIC("Link.HeadScale.Changed"), 1);
}
Reset_Option_Double("Reset##Link_HeadScale", CVAR_COSMETIC("Link.HeadScale"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
if (UIWidgets::EnhancementSliderFloat("Link Sword Scale: %f", "##Link_SwordScale", CVAR_COSMETIC("Link.SwordScale.Value"), 1.0f, 2.5f, "", 1.0f, false)) {
CVarSetInteger(CVAR_COSMETIC("Link.SwordScale.Changed"), 1);
}
Reset_Option_Double("Reset##Link_SwordScale", CVAR_COSMETIC("Link.SwordScale"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementSliderFloat("Bunny Hood Length: %f", "##BunnyHood_EarLength", CVAR_COSMETIC("BunnyHood.EarLength"), -300.0f, 1000.0f, "", 0.0f, false);
Reset_Option_Single("Reset##BunnyHood_EarLength", CVAR_COSMETIC("BunnyHood.EarLength"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementSliderFloat("Bunny Hood Spread: %f", "##BunnyHood_EarSpread", CVAR_COSMETIC("BunnyHood.EarSpread"), -300.0f, 500.0f, "", 0.0f, false);
Reset_Option_Single("Reset##BunnyHood_EarSpread", CVAR_COSMETIC("BunnyHood.EarSpread"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementSliderFloat("Goron Neck Length: %f", "##Goron_NeckLength", CVAR_COSMETIC("Goron.NeckLength"), 0.0f, 5000.0f, "", 0.0f, false);
Reset_Option_Single("Reset##Goron_NeckLength", CVAR_COSMETIC("Goron.NeckLength"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementCheckbox("Unfix Goron Spin", CVAR_COSMETIC("UnfixGoronSpin"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementSliderFloat("Fairies Size: %f", "##Fairies_Size", CVAR_COSMETIC("Fairies.Size"), 0.25f, 5.0f, "", 1.0f, false);
Reset_Option_Single("Reset##Fairies_Size", CVAR_COSMETIC("Fairies.Size"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementSliderFloat("N64 Logo Spin Speed: %f", "##N64Logo_SpinSpeed", CVAR_COSMETIC("N64Logo.SpinSpeed"), 0.25f, 5.0f, "", 1.0f, false);
Reset_Option_Single("Reset##N64Logo_SpinSpeed", CVAR_COSMETIC("N64Logo.SpinSpeed"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
UIWidgets::EnhancementSliderFloat("Moon Size: %f", "##Moon_Size", CVAR_COSMETIC("Moon.Size"), 0.5f, 2.0f, "", 1.0f, false);
Reset_Option_Single("Reset##Moon_Size", CVAR_COSMETIC("Moon.Size"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
if (UIWidgets::EnhancementSliderFloat("Kak Windmill Speed: %f", "##Kak_Windmill_Speed", CVAR_COSMETIC("Kak.Windmill_Speed.Value"), 100.0f, 6000.0f, "", 100.0f, false)) {
CVarSetInteger(CVAR_COSMETIC("Kak.Windmill_Speed.Changed"), 1);
}
Reset_Option_Double("Reset##Kak_Windmill_Speed", CVAR_COSMETIC("Kak.Windmill_Speed"));
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
ImGui::EndDisabled();
}
@@ -1748,6 +1794,7 @@ void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) {
DrawCosmeticRow(cosmeticOption);
}
}
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
}
static const char* colorSchemes[2] = {
@@ -1755,92 +1802,95 @@ static const char* colorSchemes[2] = {
"Gamecube",
};
-void CosmeticsEditorWindow::ApplyDungeonEmblemColors(){
- CVarSetColor(cosmeticOptions["Key.ForestEmblem"].cvar, {0, 255, 0, 255});
- CVarSetInteger(cosmeticOptions["Key.ForestEmblem"].changedCvar, 1);
- cosmeticOptions["Key.ForestEmblem"].currentColor = {0, 255/255.0f, 0, 255/255.0f};
+void CosmeticsEditorWindow::ApplyDungeonKeyColors() {
+ // Keyring
+ ResetColor(cosmeticOptions.at("Key.KeyringRing"));
- CVarSetColor(cosmeticOptions["Key.FireEmblem"].cvar, {255, 30, 0, 255});
- CVarSetInteger(cosmeticOptions["Key.FireEmblem"].changedCvar, 1);
- cosmeticOptions["Key.FireEmblem"].currentColor = {255/255.0f, 30/255.0f, 0, 255/255.0f};
+ // Forest Temple
+ CVarSetColor(cosmeticOptions["Key.ForestSmallBody"].cvar, { 4, 195, 46, 255 });
+ CVarSetInteger(cosmeticOptions["Key.ForestSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.ForestSmallBody"].currentColor = { 4 / 255.0f, 195 / 255.0f, 46 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.ForestSmallEmblem"));
+
+ ResetColor(cosmeticOptions.at("Key.ForestBossBody"));
+ CVarSetColor(cosmeticOptions["Key.ForestBossGem"].cvar, { 0, 255, 0, 255 });
+ CVarSetInteger(cosmeticOptions["Key.ForestBossGem"].changedCvar, 1);
+ cosmeticOptions["Key.ForestBossGem"].currentColor = { 0, 255 / 255.0f, 0, 255 / 255.0f };
+
+ // Fire Temple
+ CVarSetColor(cosmeticOptions["Key.FireSmallBody"].cvar, { 237, 95, 95, 255 });
+ CVarSetInteger(cosmeticOptions["Key.FireSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.FireSmallBody"].currentColor = { 237 / 255.0f, 95 / 255.0f, 95 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.FireSmallEmblem"));
+
+ ResetColor(cosmeticOptions.at("Key.FireBossBody"));
+ CVarSetColor(cosmeticOptions["Key.FireBossGem"].cvar, { 255, 30, 0, 255 });
+ CVarSetInteger(cosmeticOptions["Key.FireBossGem"].changedCvar, 1);
+ cosmeticOptions["Key.FireBossGem"].currentColor = { 255 / 255.0f, 30 / 255.0f, 0, 255 / 255.0f };
+
+ // Water Temple
+ CVarSetColor(cosmeticOptions["Key.WaterSmallBody"].cvar, { 85, 180, 223, 255 });
+ CVarSetInteger(cosmeticOptions["Key.WaterSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.WaterSmallBody"].currentColor = { 85 / 255.0f, 180 / 255.0f, 223 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.WaterSmallEmblem"));
+
+ ResetColor(cosmeticOptions.at("Key.WaterBossBody"));
+ CVarSetColor(cosmeticOptions["Key.WaterBossGem"].cvar, { 0, 137, 255, 255 });
+ CVarSetInteger(cosmeticOptions["Key.WaterBossGem"].changedCvar, 1);
+ cosmeticOptions["Key.WaterBossGem"].currentColor = { 0, 137 / 255.0f, 255 / 255.0f, 255 / 255.0f };
+
+ // Spirit Temple
+ CVarSetColor(cosmeticOptions["Key.SpiritSmallBody"].cvar, { 222, 158, 47, 255 });
+ CVarSetInteger(cosmeticOptions["Key.SpiritSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.SpiritSmallBody"].currentColor = { 222 / 255.0f, 158 / 255.0f, 47 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.SpiritSmallEmblem"));
+
+ ResetColor(cosmeticOptions.at("Key.SpiritBossBody"));
+ CVarSetColor(cosmeticOptions["Key.SpiritBossGem"].cvar, { 255, 85, 0, 255 });
+ CVarSetInteger(cosmeticOptions["Key.SpiritBossGem"].changedCvar, 1);
+ cosmeticOptions["Key.SpiritBossGem"].currentColor = { 255 / 255.0f, 85 / 255.0f, 0, 255 / 255.0f };
+
+ // Shadow Temple
+ CVarSetColor(cosmeticOptions["Key.ShadowSmallBody"].cvar, { 126, 16, 177, 255 });
+ CVarSetInteger(cosmeticOptions["Key.ShadowSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.ShadowSmallBody"].currentColor = { 126 / 255.0f, 16 / 255.0f, 177 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.ShadowSmallEmblem"));
+
+ ResetColor(cosmeticOptions.at("Key.ShadowBossBody"));
+ CVarSetColor(cosmeticOptions["Key.ShadowBossGem"].cvar, { 153, 0, 255, 255 });
+ CVarSetInteger(cosmeticOptions["Key.ShadowBossGem"].changedCvar, 1);
+ cosmeticOptions["Key.ShadowBossGem"].currentColor = { 153 / 255.0f, 0, 255 / 255.0f, 255 / 255.0f };
+
+ // Ganon's Tower
+ CVarSetColor(cosmeticOptions["Key.GanonsSmallBody"].cvar, { 80, 80, 80, 255 });
+ CVarSetInteger(cosmeticOptions["Key.GanonsSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.GanonsSmallBody"].currentColor = { 80 / 255.0f, 80 / 255.0f, 80 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.GanonsSmallEmblem"));
+
+ CVarSetColor(cosmeticOptions["Key.GanonsBossBody"].cvar, { 80, 80, 80, 255 });
+ CVarSetInteger(cosmeticOptions["Key.GanonsBossBody"].changedCvar, 1);
+ cosmeticOptions["Key.GanonsBossBody"].currentColor = { 80 / 255.0f, 80 / 255.0f, 80 / 255.0f, 255 / 255.0f };
+ CVarSetColor(cosmeticOptions["Key.GanonsBossGem"].cvar, { 255, 0, 0, 255 });
+ CVarSetInteger(cosmeticOptions["Key.GanonsBossGem"].changedCvar, 1);
+ cosmeticOptions["Key.GanonsBossGem"].currentColor = { 255 / 255.0f, 0, 0, 255 / 255.0f };
- CVarSetColor(cosmeticOptions["Key.WaterEmblem"].cvar, {0, 137, 255, 255});
- CVarSetInteger(cosmeticOptions["Key.WaterEmblem"].changedCvar, 1);
- cosmeticOptions["Key.WaterEmblem"].currentColor = {0, 137/255.0f, 255/255.0f, 255/255.0f};
+ // Bottom of the Well
+ CVarSetColor(cosmeticOptions["Key.WellSmallBody"].cvar, { 227, 110, 255, 255 });
+ CVarSetInteger(cosmeticOptions["Key.WellSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.WellSmallBody"].currentColor = { 227 / 255.0f, 110 / 255.0f, 255 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.WellSmallEmblem"));
+
+ // Gerudo Training Ground
+ CVarSetColor(cosmeticOptions["Key.GTGSmallBody"].cvar, { 221, 212, 60, 255 });
+ CVarSetInteger(cosmeticOptions["Key.GTGSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.GTGSmallBody"].currentColor = { 221 / 255.0f, 212 / 255.0f, 60 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.GTGSmallEmblem"));
- CVarSetColor(cosmeticOptions["Key.SpiritEmblem"].cvar, {255, 85, 0, 255});
- CVarSetInteger(cosmeticOptions["Key.SpiritEmblem"].changedCvar, 1);
- cosmeticOptions["Key.SpiritEmblem"].currentColor = {255/255.0f, 85/255.0f, 0, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.ShadowEmblem"].cvar, {153, 0, 255, 255});
- CVarSetInteger(cosmeticOptions["Key.ShadowEmblem"].changedCvar, 1);
- cosmeticOptions["Key.ShadowEmblem"].currentColor = {153/255.0f, 0, 255/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.WellEmblem"].cvar, { 255, 0, 188, 255});
- CVarSetInteger(cosmeticOptions["Key.WellEmblem"].changedCvar, 1);
- cosmeticOptions["Key.WellEmblem"].currentColor = {255/255.0f, 0, 188/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.GTGEmblem"].cvar, {255, 255, 0, 255});
- CVarSetInteger(cosmeticOptions["Key.GTGEmblem"].changedCvar, 1);
- cosmeticOptions["Key.GTGEmblem"].currentColor = {255/255.0f, 255/255.0f, 0, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.FortEmblem"].cvar, {255, 255, 203, 255});
- CVarSetInteger(cosmeticOptions["Key.FortEmblem"].changedCvar, 1);
- cosmeticOptions["Key.FortEmblem"].currentColor = { 255/255.0f, 255/255.0f, 203/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.GanonsEmblem"].cvar, {255, 0, 0, 255});
- CVarSetInteger(cosmeticOptions["Key.GanonsEmblem"].changedCvar, 1);
- cosmeticOptions["Key.GanonsEmblem"].currentColor = {255/255.0f, 0, 0, 255/255.0f};
-
- //CVarSetColor(cosmeticOptions["Key.ChestGameEmblem"].cvar, {255, 255, 0, 255});
- //CVarSetInteger(cosmeticOptions["Key.ChestGameEmblem"].changedCvar, 1);
- //cosmeticOptions["Key.ChestGameEmblem"].currentColor = {255/255.0f, 255/255.0f, 0, 255/255.0f};
-}
-
-void CosmeticsEditorWindow::ApplyDungeonBaseColors(){
- CVarSetColor(cosmeticOptions["Key.ForestSmallBase"].cvar, {4, 195, 46, 255});
- CVarSetInteger(cosmeticOptions["Key.ForestSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.ForestSmallBase"].currentColor = {4/255.0f, 195/255.0f, 46/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.FireSmallBase"].cvar, {237, 95, 95, 255});
- CVarSetInteger(cosmeticOptions["Key.FireSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.FireSmallBase"].currentColor = {237/255.0f, 95/255.0f, 95/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.WaterSmallBase"].cvar, {85, 180, 223, 255});
- CVarSetInteger(cosmeticOptions["Key.WaterSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.WaterSmallBase"].currentColor = {85/255.0f, 180/255.0f, 223/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.SpiritSmallBase"].cvar, {222, 158, 47, 255});
- CVarSetInteger(cosmeticOptions["Key.SpiritSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.SpiritSmallBase"].currentColor = {222/255.0f, 158/255.0f, 47/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.ShadowSmallBase"].cvar, {126, 16, 177, 255});
- CVarSetInteger(cosmeticOptions["Key.ShadowSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.ShadowSmallBase"].currentColor = {126/255.0f, 16/255.0f, 177/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.WellSmallBase"].cvar, {227, 110, 255, 255});
- CVarSetInteger(cosmeticOptions["Key.WellSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.WellSmallBase"].currentColor = {227/255.0f, 110/255.0f, 255/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.GTGSmallBase"].cvar, {221, 212, 60, 255});
- CVarSetInteger(cosmeticOptions["Key.GTGSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.GTGSmallBase"].currentColor = {221/255.0f, 212/255.0f, 60/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.FortSmallBase"].cvar, {255, 255, 255, 255});
- CVarSetInteger(cosmeticOptions["Key.FortSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.FortSmallBase"].currentColor = {255/255.0f, 255/255.0f, 255/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.GanonsSmallBase"].cvar, {80, 80, 80, 255});
- CVarSetInteger(cosmeticOptions["Key.GanonsSmallBase"].changedCvar, 1);
- cosmeticOptions["Key.GanonsSmallBase"].currentColor = {80/255.0f, 80/255.0f, 80/255.0f, 255/255.0f};
-
- CVarSetColor(cosmeticOptions["Key.GanonsBossBase"].cvar, {80, 80, 80, 255});
- CVarSetInteger(cosmeticOptions["Key.GanonsBossBase"].changedCvar, 1);
- cosmeticOptions["Key.GanonsBossBase"].currentColor = {80/255.0f, 80/255.0f, 80/255.0f, 255/255.0f};
-
- //CVarSetColor(cosmeticOptions["Key.ChestGameSmallBase"].cvar, {255, 255, 0, 255});
- //CVarSetInteger(cosmeticOptions["Key.ChestGameSmallBase"].changedCvar, 1);
- //cosmeticOptions["Key.ChestGameSmallBase"].currentColor = {255/255.0f, 255/255.0f, 0, 255/255.0f};
+ // Gerudo Fortress
+ CVarSetColor(cosmeticOptions["Key.FortSmallBody"].cvar, { 255, 255, 255, 255 });
+ CVarSetInteger(cosmeticOptions["Key.FortSmallBody"].changedCvar, 1);
+ cosmeticOptions["Key.FortSmallBody"].currentColor = { 255 / 255.0f, 255 / 255.0f, 255 / 255.0f, 255 / 255.0f };
+ ResetColor(cosmeticOptions.at("Key.FortSmallEmblem"));
}
void CosmeticsEditorWindow::DrawElement() {
@@ -1853,15 +1903,6 @@ void CosmeticsEditorWindow::DrawElement() {
"For example, if you have custom Link model, then the Link's Hair color option will most likely not apply."
);
- if (ImGui::Button("Apply Dungeon Gem/Emblem Colors", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) {
- ApplyDungeonEmblemColors();
- Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
- }
- ImGui::SameLine();
- if (ImGui::Button("Apply Dungeon Base Colors", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) {
- ApplyDungeonBaseColors();
- Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
- }
if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) {
if (ImGui::Button("Lock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) {
for (auto& [id, cosmeticOption] : cosmeticOptions) {
@@ -1950,16 +1991,40 @@ void CosmeticsEditorWindow::DrawElement() {
if (ImGui::BeginTabBar("CosmeticsContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
if (ImGui::BeginTabItem("Link & Items")) {
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
DrawCosmeticGroup(COSMETICS_GROUP_LINK);
DrawCosmeticGroup(COSMETICS_GROUP_GLOVES);
DrawCosmeticGroup(COSMETICS_GROUP_MIRRORSHIELD);
DrawCosmeticGroup(COSMETICS_GROUP_EQUIPMENT);
DrawCosmeticGroup(COSMETICS_GROUP_SWORDS);
- DrawCosmeticGroup(COSMETICS_GROUP_KEY);
DrawCosmeticGroup(COSMETICS_GROUP_CONSUMABLE);
ImGui::EndTabItem();
}
+
+ if (ImGui::BeginTabItem("Keys")) {
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
+ if (ImGui::Button("Give all keys dungeon-specific colors", ImVec2(300.0f, 30.0f))) {
+ ApplyDungeonKeyColors();
+ Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
+ }
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
+ DrawCosmeticGroup(COSMETICS_GROUP_KEYRING);
+ DrawCosmeticGroup(COSMETICS_GROUP_SMALL_KEYS);
+ DrawCosmeticGroup(COSMETICS_GROUP_BOSS_KEYS);
+
+ ImGui::EndTabItem();
+ }
+
if (ImGui::BeginTabItem("Effects")) {
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
DrawCosmeticGroup(COSMETICS_GROUP_MAGIC);
DrawCosmeticGroup(COSMETICS_GROUP_ARROWS);
DrawCosmeticGroup(COSMETICS_GROUP_SPIN_ATTACK);
@@ -1973,9 +2038,15 @@ void CosmeticsEditorWindow::DrawElement() {
CVarClear(CVAR_COSMETIC("Trails.Duration.Changed"));
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
}
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("World & NPCs")) {
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
DrawCosmeticGroup(COSMETICS_GROUP_WORLD);
DrawCosmeticGroup(COSMETICS_GROUP_NAVI);
DrawCosmeticGroup(COSMETICS_GROUP_IVAN);
@@ -1987,6 +2058,9 @@ void CosmeticsEditorWindow::DrawElement() {
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("HUD")) {
+
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
+
DrawCosmeticGroup(COSMETICS_GROUP_HUD);
DrawCosmeticGroup(COSMETICS_GROUP_TITLE);
ImGui::EndTabItem();
diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
index c9d395791..c9a28ef29 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
@@ -9,7 +9,9 @@ typedef enum {
COSMETICS_GROUP_SWORDS,
COSMETICS_GROUP_GLOVES,
COSMETICS_GROUP_EQUIPMENT,
- COSMETICS_GROUP_KEY,
+ COSMETICS_GROUP_KEYRING,
+ COSMETICS_GROUP_SMALL_KEYS,
+ COSMETICS_GROUP_BOSS_KEYS,
COSMETICS_GROUP_CONSUMABLE,
COSMETICS_GROUP_HUD,
COSMETICS_GROUP_KALEIDO,
@@ -63,8 +65,7 @@ class CosmeticsEditorWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
- void ApplyDungeonEmblemColors();
- void ApplyDungeonBaseColors();
+ void ApplyDungeonKeyColors();
void UpdateElement() override {};
};
#endif //__cplusplus
\ No newline at end of file
diff --git a/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp b/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp
new file mode 100644
index 000000000..d478f8fc3
--- /dev/null
+++ b/soh/soh/Enhancements/cosmetics/CustomLogoTitle.cpp
@@ -0,0 +1,232 @@
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+#include "textures/nintendo_rogo_static/nintendo_rogo_static.h"
+#include "assets/objects/gameplay_keep/gameplay_keep.h"
+#include "soh_assets.h"
+
+extern "C" {
+#include "macros.h"
+#include "z64.h"
+#include "functions.h"
+#include "variables.h"
+#include "soh/Enhancements/enhancementTypes.h"
+}
+
+extern "C" {
+extern void Title_Calc(TitleContext*);
+extern void Title_SetupView(TitleContext*, f32, f32, f32);
+}
+
+#define LOGO_TO_DRAW_LUS 0
+#define LOGO_TO_DRAW_N64 1
+
+static bool shouldDrawIceOnSpinningLogo = false;
+
+extern "C" void CustomLogoTitle_Draw(TitleContext* titleContext, uint8_t logoToDraw) {
+ static s16 sTitleRotY = 0;
+ static Lights1 sTitleLights = gdSPDefLights1(0x64, 0x64, 0x64, 0xFF, 0xFF, 0xFF, 0x45, 0x45, 0x45);
+
+ u16 y;
+ u16 idx;
+ s32 pad1;
+ Vec3f v3;
+ Vec3f v1;
+ Vec3f v2;
+ s32 pad2[2];
+
+ OPEN_DISPS(titleContext->state.gfxCtx);
+
+ v3.x = 69;
+ v3.y = 69;
+ v3.z = 69;
+ v2.x = -4949.148;
+ v2.y = 4002.5417;
+ v1.x = 0;
+ v1.y = 0;
+ v1.z = 0;
+ v2.z = 1119.0837;
+
+ func_8002EABC(&v1, &v2, &v3, titleContext->state.gfxCtx);
+ gSPSetLights1(POLY_OPA_DISP++, sTitleLights);
+ Title_SetupView(titleContext, 0, 150.0, 300.0);
+ Gfx_SetupDL_25Opa(titleContext->state.gfxCtx);
+ Matrix_Translate(-53.0, -5.0, 0, MTXMODE_NEW);
+ Matrix_Scale(1.0, 1.0, 1.0, MTXMODE_APPLY);
+ Matrix_RotateZYX(0, sTitleRotY, 0, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(titleContext->state.gfxCtx), G_MTX_LOAD);
+
+ if (logoToDraw == LOGO_TO_DRAW_LUS) {
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gShipLogoDL);
+ } else {
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gNintendo64LogoDL);
+ }
+
+ Gfx_SetupDL_39Opa(titleContext->state.gfxCtx);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCycleType(POLY_OPA_DISP++, G_CYC_2CYCLE);
+ gDPSetRenderMode(POLY_OPA_DISP++, G_RM_XLU_SURF2, G_RM_OPA_CI | CVG_DST_WRAP);
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, PRIMITIVE, ENV_ALPHA, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT,
+ COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
+ if (CVarGetInteger(CVAR_COSMETIC("Title.NintendoLogo.Changed"), 0)) {
+ Color_RGB8 nintendoLogoColor = CVarGetColor24(CVAR_COSMETIC("Title.NintendoLogo.Value"), Color_RGB8{0, 0, 255});
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, nintendoLogoColor.r, nintendoLogoColor.g, nintendoLogoColor.b, 128);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 170, 255, 255, 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 255, 128);
+ }
+
+ gDPLoadMultiBlock(POLY_OPA_DISP++, nintendo_rogo_static_Tex_001800, 0x100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 2, 11);
+
+ for (idx = 0, y = 94; idx < 16; idx++, y += 2)
+ {
+ gDPLoadMultiTile(POLY_OPA_DISP++, (logoToDraw == LOGO_TO_DRAW_N64) ? nintendo_rogo_static_Tex_000000 : nintendo_rogo_static_Tex_LUS_000000, 0, G_TX_RENDERTILE, G_IM_FMT_I, G_IM_SIZ_8b, 192, 32,
+ 0, idx * 2, 192 - 1, (idx + 1) * 2 - 1, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ gDPSetTileSize(POLY_OPA_DISP++, 0, 0, 0, (192 - 1) << G_TEXTURE_IMAGE_FRAC,
+ (2 - 1) << G_TEXTURE_IMAGE_FRAC);
+
+ gDPSetTileSize(POLY_OPA_DISP++, 1, titleContext->uls, (titleContext->ult & 0x7F) - idx * 4, 0, 0);
+ gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+ }
+
+ // Draw ice block around spinning N or ship.
+ if (shouldDrawIceOnSpinningLogo) {
+ f32 scale = 0.4f;
+
+ gSPSegment(POLY_OPA_DISP++, 0x08,
+ (uintptr_t)Gfx_TwoTexScroll(titleContext->state.gfxCtx, 0, 0, (0 - 1) % 128, 32, 32, 1,
+ 0, (1 * -2) % 128, 32, 32));
+
+ Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(titleContext->state.gfxCtx),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 50, 100, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gEffIceFragment3DL);
+ }
+
+ Environment_FillScreen(titleContext->state.gfxCtx, 0, 0, 0, (s16)titleContext->coverAlpha, FILL_SCREEN_XLU);
+
+ sTitleRotY += (300 * CVarGetFloat(CVAR_COSMETIC("N64Logo.SpinSpeed"), 1.0f));
+
+ CLOSE_DISPS(titleContext->state.gfxCtx);
+}
+
+#define CVAR_BOOTSEQUENCE_NAME CVAR_ENHANCEMENT("BootSequence")
+#define CVAR_BOOTSEQUENCE_DEFAULT BOOTSEQUENCE_DEFAULT
+#define CVAR_BOOTSEQUENCE_VALUE CVarGetInteger(CVAR_BOOTSEQUENCE_NAME, CVAR_BOOTSEQUENCE_DEFAULT)
+
+extern "C" void CustomLogoTitle_Main(TitleContext* titleContext) {
+ static uint8_t logosSeen = 0;
+ uint8_t logoToDraw;
+
+ if (CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_DEFAULT) {
+ if (logosSeen == 0) {
+ logoToDraw = LOGO_TO_DRAW_LUS;
+ } else {
+ logoToDraw = LOGO_TO_DRAW_N64;
+ }
+ }
+
+ if (CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_AUTHENTIC) {
+ logoToDraw = LOGO_TO_DRAW_N64;
+ }
+
+ OPEN_DISPS(titleContext->state.gfxCtx);
+
+ gSPSegment(POLY_OPA_DISP++, 0, (uintptr_t)NULL);
+ gSPSegment(POLY_OPA_DISP++, 1, (uintptr_t)titleContext->staticSegment);
+ Gfx_SetupFrame(titleContext->state.gfxCtx, 0, 0, 0);
+ Title_Calc(titleContext);
+ CustomLogoTitle_Draw(titleContext, logoToDraw);
+
+ if (titleContext->exit) {
+ gSaveContext.seqId = (u8)NA_BGM_DISABLED;
+ gSaveContext.natureAmbienceId = 0xFF;
+ gSaveContext.gameMode = GAMEMODE_TITLE_SCREEN;
+ titleContext->state.running = false;
+
+ logosSeen++;
+
+ if (CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_DEFAULT && logosSeen == 1) {
+ SET_NEXT_GAMESTATE(&titleContext->state, Title_Init, TitleContext);
+ }
+
+ if ((CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_DEFAULT && logosSeen == 2) ||
+ (CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_AUTHENTIC)) {
+ SET_NEXT_GAMESTATE(&titleContext->state, Opening_Init, OpeningContext);
+ logosSeen = 0;
+ }
+ }
+
+ GameInteractor_ExecuteOnZTitleUpdate(titleContext);
+
+ CLOSE_DISPS(titleContext->state.gfxCtx);
+}
+
+// // // //
+// Always
+//
+
+void OnZTitleInitReplaceTitleMainWithCustom(void* gameState) {
+ TitleContext* titleContext = (TitleContext*)gameState;
+ titleContext->state.main = (GameStateFunc)CustomLogoTitle_Main;
+}
+
+// Allows pressing A to skip the boot logo and go to the next state (opening or file select)
+void OnZTitleUpdatePressButtonToSkip(void* gameState) {
+ TitleContext* titleContext = (TitleContext*)gameState;
+
+ if (CHECK_BTN_ANY(titleContext->state.input->press.button, BTN_A | BTN_B | BTN_START)) {
+ // Force the title state to start fading to black and to last roughly 5 frames based on current fade in/out
+ titleContext->visibleDuration = 0;
+ titleContext->addAlpha = std::max((255 - titleContext->coverAlpha) / 5, 1);
+ }
+}
+
+void RegisterCustomLogoTitle() {
+ COND_HOOK(OnZTitleInit, true, OnZTitleInitReplaceTitleMainWithCustom);
+ COND_HOOK(OnZTitleUpdate, true, OnZTitleUpdatePressButtonToSkip);
+}
+
+static RegisterShipInitFunc initFuncAlways(RegisterCustomLogoTitle);
+
+// // // // // //
+// Bootsequence
+//
+
+void OnZTitleUpdateSkipToFileSelect(void* gameState) {
+ TitleContext* titleContext = (TitleContext*)gameState;
+
+ gSaveContext.seqId = (u8)NA_BGM_DISABLED;
+ gSaveContext.natureAmbienceId = 0xFF;
+ gSaveContext.gameMode = GAMEMODE_TITLE_SCREEN;
+ titleContext->state.running = false;
+
+ SET_NEXT_GAMESTATE(&titleContext->state, FileChoose_Init, FileChooseContext);
+}
+
+void RegisterCustomLogoTitleBootsequence() {
+ COND_HOOK(OnZTitleUpdate, CVAR_BOOTSEQUENCE_VALUE == BOOTSEQUENCE_FILESELECT, OnZTitleUpdateSkipToFileSelect);
+}
+
+static RegisterShipInitFunc initFuncBootsequence(RegisterCustomLogoTitleBootsequence, { CVAR_BOOTSEQUENCE_NAME });
+
+// // // // // //
+// Let it Snow
+//
+
+#define CVAR_LETITSNOW_NAME CVAR_GENERAL("LetItSnow")
+#define CVAR_LETITSNOW_DEFAULT 0
+#define CVAR_LETITSNOW_VALUE CVarGetInteger(CVAR_LETITSNOW_NAME, CVAR_LETITSNOW_DEFAULT)
+
+void RegisterCustomLogoTitleLetItSnow() {
+ shouldDrawIceOnSpinningLogo = CVAR_LETITSNOW_VALUE != CVAR_LETITSNOW_DEFAULT;
+}
+
+static RegisterShipInitFunc initFuncLetItSnow(RegisterCustomLogoTitleLetItSnow, { CVAR_LETITSNOW_NAME });
diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp
index 9e4b4b0e4..9ef0fe2ab 100644
--- a/soh/soh/Enhancements/debugconsole.cpp
+++ b/soh/soh/Enhancements/debugconsole.cpp
@@ -402,6 +402,7 @@ static bool EntranceHandler(std::shared_ptr Console, const std::v
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gPlayState->transitionType = TRANS_TYPE_INSTANT;
gSaveContext.nextTransitionType = TRANS_TYPE_INSTANT;
+ return 0;
}
static bool VoidHandler(std::shared_ptr Console, const std::vector& args, std::string* output) {
@@ -1297,7 +1298,9 @@ static constexpr std::array, COSMETICS_GRO
{"swords", COSMETICS_GROUP_SWORDS},
{"gloves", COSMETICS_GROUP_GLOVES},
{"equipment", COSMETICS_GROUP_EQUIPMENT},
- {"key", COSMETICS_GROUP_KEY},
+ {"keyring", COSMETICS_GROUP_KEYRING},
+ {"small_keys", COSMETICS_GROUP_SMALL_KEYS },
+ {"boss_keys", COSMETICS_GROUP_BOSS_KEYS },
{"consumable", COSMETICS_GROUP_CONSUMABLE},
{"hud", COSMETICS_GROUP_HUD},
{"kaleido", COSMETICS_GROUP_KALEIDO},
diff --git a/soh/soh/Enhancements/debugger/MessageViewer.cpp b/soh/soh/Enhancements/debugger/MessageViewer.cpp
index 4c3f62693..3c10772f3 100644
--- a/soh/soh/Enhancements/debugger/MessageViewer.cpp
+++ b/soh/soh/Enhancements/debugger/MessageViewer.cpp
@@ -180,9 +180,7 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
Font* font = &msgCtx->font;
sMessageHasSetSfx = 0;
for (u32 i = 0; i < FONT_CHAR_TEX_SIZE * 120; i += FONT_CHAR_TEX_SIZE) {
- if (&font->charTexBuf[i] != nullptr) {
- gSPInvalidateTexCache(play->state.gfxCtx->polyOpa.p++, reinterpret_cast(&font->charTexBuf[i]));
- }
+ gSPInvalidateTexCache(play->state.gfxCtx->polyOpa.p++, reinterpret_cast(&font->charTexBuf[i]));
}
R_TEXT_CHAR_SCALE = 75;
R_TEXT_LINE_SPACING = 12;
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h
index 8eb939ec8..2a77b9b0a 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.h
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h
@@ -1551,6 +1551,55 @@ const std::vector flagTables = {
{ RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, "RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY" },
+
+ { RAND_INF_GUARD_HOUSE_UNLOCKED, "RAND_INF_GUARD_HOUSE_UNLOCKED" },
+ { RAND_INF_GUARD_HOUSE_KEY_OBTAINED, "RAND_INF_GUARD_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_MARKET_BAZAAR_UNLOCKED, "RAND_INF_MARKET_BAZAAR_UNLOCKED" },
+ { RAND_INF_MARKET_BAZAAR_KEY_OBTAINED, "RAND_INF_MARKET_BAZAAR_KEY_OBTAINED" },
+ { RAND_INF_MARKET_POTION_SHOP_UNLOCKED, "RAND_INF_MARKET_POTION_SHOP_UNLOCKED" },
+ { RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED, "RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED" },
+ { RAND_INF_MASK_SHOP_UNLOCKED, "RAND_INF_MASK_SHOP_UNLOCKED" },
+ { RAND_INF_MASK_SHOP_KEY_OBTAINED, "RAND_INF_MASK_SHOP_KEY_OBTAINED" },
+ { RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED, "RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED" },
+ { RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED, "RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED" },
+ { RAND_INF_BOMBCHU_BOWLING_UNLOCKED, "RAND_INF_BOMBCHU_BOWLING_UNLOCKED" },
+ { RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED, "RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED" },
+ { RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED, "RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED" },
+ { RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED, "RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED" },
+ { RAND_INF_BOMBCHU_SHOP_UNLOCKED, "RAND_INF_BOMBCHU_SHOP_UNLOCKED" },
+ { RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED, "RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED" },
+ { RAND_INF_RICHARDS_HOUSE_UNLOCKED, "RAND_INF_RICHARDS_HOUSE_UNLOCKED" },
+ { RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED, "RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_ALLEY_HOUSE_UNLOCKED, "RAND_INF_ALLEY_HOUSE_UNLOCKED" },
+ { RAND_INF_ALLEY_HOUSE_KEY_OBTAINED, "RAND_INF_ALLEY_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_KAK_BAZAAR_UNLOCKED, "RAND_INF_KAK_BAZAAR_UNLOCKED" },
+ { RAND_INF_KAK_BAZAAR_KEY_OBTAINED, "RAND_INF_KAK_BAZAAR_KEY_OBTAINED" },
+ { RAND_INF_KAK_POTION_SHOP_UNLOCKED, "RAND_INF_KAK_POTION_SHOP_UNLOCKED" },
+ { RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED, "RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED" },
+ { RAND_INF_BOSS_HOUSE_UNLOCKED, "RAND_INF_BOSS_HOUSE_UNLOCKED" },
+ { RAND_INF_BOSS_HOUSE_KEY_OBTAINED, "RAND_INF_BOSS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED, "RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED" },
+ { RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED, "RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED" },
+ { RAND_INF_SKULLTULA_HOUSE_UNLOCKED, "RAND_INF_SKULLTULA_HOUSE_UNLOCKED" },
+ { RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED, "RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_IMPAS_HOUSE_UNLOCKED, "RAND_INF_IMPAS_HOUSE_UNLOCKED" },
+ { RAND_INF_IMPAS_HOUSE_KEY_OBTAINED, "RAND_INF_IMPAS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_WINDMILL_UNLOCKED, "RAND_INF_WINDMILL_UNLOCKED" },
+ { RAND_INF_WINDMILL_KEY_OBTAINED, "RAND_INF_WINDMILL_KEY_OBTAINED" },
+ { RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED, "RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED" },
+ { RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED, "RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED" },
+ { RAND_INF_DAMPES_HUT_UNLOCKED, "RAND_INF_DAMPES_HUT_UNLOCKED" },
+ { RAND_INF_DAMPES_HUT_KEY_OBTAINED, "RAND_INF_DAMPES_HUT_KEY_OBTAINED" },
+ { RAND_INF_TALONS_HOUSE_UNLOCKED, "RAND_INF_TALONS_HOUSE_UNLOCKED" },
+ { RAND_INF_TALONS_HOUSE_KEY_OBTAINED, "RAND_INF_TALONS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_STABLES_UNLOCKED, "RAND_INF_STABLES_UNLOCKED" },
+ { RAND_INF_STABLES_KEY_OBTAINED, "RAND_INF_STABLES_KEY_OBTAINED" },
+ { RAND_INF_BACK_TOWER_UNLOCKED, "RAND_INF_BACK_TOWER_UNLOCKED" },
+ { RAND_INF_BACK_TOWER_KEY_OBTAINED, "RAND_INF_BACK_TOWER_KEY_OBTAINED" },
+ { RAND_INF_HYLIA_LAB_UNLOCKED, "RAND_INF_HYLIA_LAB_UNLOCKED" },
+ { RAND_INF_HYLIA_LAB_KEY_OBTAINED, "RAND_INF_HYLIA_LAB_KEY_OBTAINED" },
+ { RAND_INF_FISHING_HOLE_UNLOCKED, "RAND_INF_FISHING_HOLE_UNLOCKED" },
+ { RAND_INF_FISHING_HOLE_KEY_OBTAINED, "RAND_INF_FISHING_HOLE_KEY_OBTAINED" },
} },
};
diff --git a/soh/soh/Enhancements/debugger/performanceTimer.cpp b/soh/soh/Enhancements/debugger/performanceTimer.cpp
index f52a8efac..69ffc6925 100644
--- a/soh/soh/Enhancements/debugger/performanceTimer.cpp
+++ b/soh/soh/Enhancements/debugger/performanceTimer.cpp
@@ -1,5 +1,3 @@
-#pragma once
-
#include "performanceTimer.h"
void StartPerformanceTimer(TimerID timer){
diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp
index 73042b25f..a2b72ca07 100644
--- a/soh/soh/Enhancements/enemyrandomizer.cpp
+++ b/soh/soh/Enhancements/enemyrandomizer.cpp
@@ -305,7 +305,7 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies();
}
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
- uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
+ uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return selectedEnemyList[randomNumber];
diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h
index d57a94991..4b2f825f5 100644
--- a/soh/soh/Enhancements/enhancementTypes.h
+++ b/soh/soh/Enhancements/enhancementTypes.h
@@ -52,14 +52,6 @@ typedef enum {
ENEMY_RANDOMIZER_RANDOM_SEEDED,
} EnemyRandomizerMode;
-typedef enum {
- FASTFILE_1,
- FASTFILE_2,
- FASTFILE_3,
- FASTFILE_MAP_SELECT,
- FASTFILE_FILE_SELECT
-} FastFileSelectTarget;
-
typedef enum {
AUTOSAVE_OFF,
AUTOSAVE_LOCATION_AND_MAJOR_ITEMS,
@@ -69,6 +61,12 @@ typedef enum {
AUTOSAVE_ALL_ITEMS
} AutosaveType;
+typedef enum {
+ BOOTSEQUENCE_DEFAULT,
+ BOOTSEQUENCE_AUTHENTIC,
+ BOOTSEQUENCE_FILESELECT
+} BootSequenceType;
+
typedef enum {
ZFIGHT_FIX_DISABLED,
ZFIGHT_FIX_CONSISTENT_VANISH,
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h
index 8c449ccdb..936a4be99 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h
@@ -286,6 +286,7 @@ typedef enum {
VB_RENDER_YES_ON_CONTINUE_PROMPT,
// Vanilla condition: CHECK_BTN_ALL(input->press.button, BTN_START)
VB_CLOSE_PAUSE_MENU,
+ VB_KALEIDO_UNPAUSE_CLOSE,
// Vanilla condition: true
VB_SPAWN_BLUE_WARP,
// Vanilla condition: this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF
@@ -304,6 +305,13 @@ typedef enum {
VB_FROGS_GO_TO_IDLE,
// Vanilla condition: var >= gSaveContext.health) && (gSaveContext.health > 0
VB_HEALTH_METER_BE_CRITICAL,
+ VB_CONSUME_SMALL_KEY,
+ // Vanilla condition: gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] <= 0
+ VB_NOT_HAVE_SMALL_KEY,
+ // Vanilla condition: !Flags_GetSwitch(play, this->actor.params & 0x3F)
+ VB_DOOR_BE_LOCKED,
+ // Vanilla condition: ((doorActor->params >> 7) & 7) == 3
+ VB_DOOR_PLAY_SCENE_TRANSITION,
/*** Play Cutscenes ***/
@@ -381,6 +389,7 @@ typedef enum {
/*** Give Items ***/
+ VB_SHORT_CIRCUIT_GIVE_ITEM_PROCESS,
VB_FREEZE_ON_SKULL_TOKEN,
// Opt: *EnBox
VB_GIVE_ITEM_FROM_CHEST,
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h
index a2d5c56ec..3f2f80265 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h
@@ -5,8 +5,11 @@
* - Argument 1: Name of the hook
* - Argument 2: Function type that the hook uses
*/
+DEFINE_HOOK(OnZTitleInit, (void* gameState));
+DEFINE_HOOK(OnZTitleUpdate, (void* gameState));
DEFINE_HOOK(OnLoadGame, (int32_t fileNum));
DEFINE_HOOK(OnExitGame, (int32_t fileNum));
+DEFINE_HOOK(OnGameStateMainStart, ());
DEFINE_HOOK(OnGameFrameUpdate, ());
DEFINE_HOOK(OnItemReceive, (GetItemEntry itemEntry));
DEFINE_HOOK(OnSaleEnd, (GetItemEntry itemEntry));
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
index 39fc298a8..ab69b543f 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
@@ -2,6 +2,14 @@
// MARK: - Gameplay
+void GameInteractor_ExecuteOnZTitleInit(void* gameState) {
+ GameInteractor::Instance->ExecuteHooks(gameState);
+}
+
+void GameInteractor_ExecuteOnZTitleUpdate(void* gameState) {
+ GameInteractor::Instance->ExecuteHooks(gameState);
+}
+
void GameInteractor_ExecuteOnLoadGame(int32_t fileNum) {
GameInteractor::Instance->ExecuteHooks(fileNum);
}
@@ -10,6 +18,10 @@ void GameInteractor_ExecuteOnExitGame(int32_t fileNum) {
GameInteractor::Instance->ExecuteHooks(fileNum);
}
+void GameInteractor_ExecuteOnGameStateMainStart() {
+ GameInteractor::Instance->ExecuteHooks();
+}
+
void GameInteractor_ExecuteOnGameFrameUpdate() {
GameInteractor::Instance->ExecuteHooks();
}
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
index cb238539f..b73f9fe70 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
@@ -7,8 +7,11 @@
extern "C" {
#endif
// MARK: - Gameplay
+void GameInteractor_ExecuteOnZTitleInit(void* gameState);
+void GameInteractor_ExecuteOnZTitleUpdate(void* gameState);
void GameInteractor_ExecuteOnLoadGame(int32_t fileNum);
void GameInteractor_ExecuteOnExitGame(int32_t fileNum);
+void GameInteractor_ExecuteOnGameStateMainStart();
void GameInteractor_ExecuteOnGameFrameUpdate();
void GameInteractor_ExecuteOnItemReceiveHooks(GetItemEntry itemEntry);
void GameInteractor_ExecuteOnSaleEndHooks(GetItemEntry itemEntry);
diff --git a/soh/soh/Enhancements/kaleido.cpp b/soh/soh/Enhancements/kaleido.cpp
index 42c135c94..8d578168c 100644
--- a/soh/soh/Enhancements/kaleido.cpp
+++ b/soh/soh/Enhancements/kaleido.cpp
@@ -125,8 +125,8 @@ namespace Rando {
std::make_shared(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0,
yOffset, reinterpret_cast(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
- ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1,
- ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
+ ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
+ ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18;
}
if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {
diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp
index c60691213..a7a019737 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -536,7 +536,7 @@ void UpdateMirrorModeState(int32_t sceneNum) {
(sceneNum == SCENE_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
- uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed()
+ uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}
@@ -1128,162 +1128,6 @@ void RegisterBossDefeatTimestamps() {
});
}
-typedef enum {
- ADD_ICE_TRAP,
- ADD_BURN_TRAP,
- ADD_SHOCK_TRAP,
- ADD_KNOCK_TRAP,
- ADD_SPEED_TRAP,
- ADD_BOMB_TRAP,
- ADD_VOID_TRAP,
- ADD_AMMO_TRAP,
- ADD_KILL_TRAP,
- ADD_TELEPORT_TRAP,
- ADD_TRAP_MAX
-} AltTrapType;
-
-const char* altTrapTypeCvars[] = {
- CVAR_ENHANCEMENT("ExtraTraps.Ice"),
- CVAR_ENHANCEMENT("ExtraTraps.Burn"),
- CVAR_ENHANCEMENT("ExtraTraps.Shock"),
- CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
- CVAR_ENHANCEMENT("ExtraTraps.Speed"),
- CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
- CVAR_ENHANCEMENT("ExtraTraps.Void"),
- CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
- CVAR_ENHANCEMENT("ExtraTraps.Kill"),
- CVAR_ENHANCEMENT("ExtraTraps.Teleport")
-};
-
-std::vector getEnabledAddTraps () {
- std::vector enabledAddTraps;
- for (int i = 0; i < ADD_TRAP_MAX; i++) {
- if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
- if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
- continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
- }
- enabledAddTraps.push_back(static_cast(i));
- }
- }
- if (enabledAddTraps.size() == 0) {
- enabledAddTraps.push_back(ADD_ICE_TRAP);
- }
- return enabledAddTraps;
-};
-
-void RegisterAltTrapTypes() {
- static AltTrapType roll = ADD_TRAP_MAX;
- static int statusTimer = -1;
- static int eventTimer = -1;
-
- GameInteractor::Instance->RegisterGameHook([](GetItemEntry itemEntry) {
- if (!CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) {
- return;
- }
- roll = RandomElement(getEnabledAddTraps());
- switch (roll) {
- case ADD_ICE_TRAP:
- GameInteractor::RawAction::FreezePlayer();
- break;
- case ADD_BURN_TRAP:
- GameInteractor::RawAction::BurnPlayer();
- break;
- case ADD_SHOCK_TRAP:
- GameInteractor::RawAction::ElectrocutePlayer();
- break;
- case ADD_KNOCK_TRAP:
- eventTimer = 3;
- break;
- case ADD_SPEED_TRAP:
- Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
- GameInteractor::State::RunSpeedModifier = -2;
- statusTimer = 200;
- Overlay_DisplayText(10, "Speed Decreased!");
- break;
- case ADD_BOMB_TRAP:
- eventTimer = 3;
- break;
- case ADD_VOID_TRAP:
- Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
- eventTimer = 3;
- break;
- case ADD_AMMO_TRAP:
- eventTimer = 3;
- Overlay_DisplayText(5, "Ammo Halved!");
- break;
- case ADD_KILL_TRAP:
- GameInteractor::RawAction::SetPlayerHealth(0);
- break;
- case ADD_TELEPORT_TRAP:
- eventTimer = 3;
- break;
- default:
- break;
- }
- });
- GameInteractor::Instance->RegisterGameHook([]() {
- Player* player = GET_PLAYER(gPlayState);
- if (statusTimer == 0) {
- GameInteractor::State::RunSpeedModifier = 0;
- }
- if (eventTimer == 0) {
- switch (roll) {
- case ADD_KNOCK_TRAP:
- GameInteractor::RawAction::KnockbackPlayer(1);
- break;
- case ADD_BOMB_TRAP:
- GameInteractor::RawAction::SpawnActor(ACTOR_EN_BOM, 1);
- break;
- case ADD_VOID_TRAP:
- Play_TriggerRespawn(gPlayState);
- break;
- case ADD_AMMO_TRAP:
- AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5;
- AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5;
- AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5;
- AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
- AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
- AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
- Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
- break;
- case ADD_TELEPORT_TRAP: {
- int entrance;
- int index = 1 + rand() % 10;
- switch (index) {
- case 1:
- entrance = GI_TP_DEST_SERENADE;
- break;
- case 2:
- entrance = GI_TP_DEST_REQUIEM;
- break;
- case 3:
- entrance = GI_TP_DEST_BOLERO;
- break;
- case 4:
- entrance = GI_TP_DEST_MINUET;
- break;
- case 5:
- entrance = GI_TP_DEST_NOCTURNE;
- break;
- case 6:
- entrance = GI_TP_DEST_PRELUDE;
- break;
- default:
- entrance = GI_TP_DEST_LINKSHOUSE;
- break;
- }
- GameInteractor::RawAction::TeleportPlayer(entrance);
- break;
- }
- default:
- break;
- }
- }
- statusTimer--;
- eventTimer--;
- });
-}
-
void UpdateHurtContainerModeState(bool newState) {
static bool hurtEnabled = false;
if (hurtEnabled == newState) {
@@ -1362,7 +1206,7 @@ void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook([](void* refActor) {
Actor* actor = static_cast(refActor);
- if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR)) {
+ if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) && (!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) {
switch (actor->params) {
case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop
@@ -1592,7 +1436,6 @@ void InitMods() {
RegisterBrokenGiantsKnifeFix();
RegisterEnemyDefeatCounts();
RegisterBossDefeatTimestamps();
- RegisterAltTrapTypes();
RegisterRandomizedEnemySizes();
RegisterOpenAllHours();
RegisterToTMedallions();
diff --git a/soh/soh/Enhancements/pausewarp.c b/soh/soh/Enhancements/pausewarp.c
index b87952232..c767a3412 100644
--- a/soh/soh/Enhancements/pausewarp.c
+++ b/soh/soh/Enhancements/pausewarp.c
@@ -2,22 +2,23 @@
#include "global.h"
#include "z64.h"
#include "game-interactor/GameInteractor.h"
+#include "soh/OTRGlobals.h"
static const int songMessageMap[] = {
- TEXT_WARP_MINUET_OF_FOREST,
- TEXT_WARP_BOLERO_OF_FIRE,
- TEXT_WARP_SERENADE_OF_WATER,
- TEXT_WARP_REQUIEM_OF_SPIRIT,
- TEXT_WARP_NOCTURNE_OF_SHADOW,
- TEXT_WARP_PRELUDE_OF_LIGHT
+ TEXT_WARP_MINUET_OF_FOREST,
+ TEXT_WARP_BOLERO_OF_FIRE,
+ TEXT_WARP_SERENADE_OF_WATER,
+ TEXT_WARP_REQUIEM_OF_SPIRIT,
+ TEXT_WARP_NOCTURNE_OF_SHADOW,
+ TEXT_WARP_PRELUDE_OF_LIGHT
};
static const int ocarinaSongMap[] = {
- OCARINA_SONG_MINUET,
- OCARINA_SONG_BOLERO,
- OCARINA_SONG_SERENADE,
- OCARINA_SONG_REQUIEM,
- OCARINA_SONG_NOCTURNE,
+ OCARINA_SONG_MINUET,
+ OCARINA_SONG_BOLERO,
+ OCARINA_SONG_SERENADE,
+ OCARINA_SONG_REQUIEM,
+ OCARINA_SONG_NOCTURNE,
OCARINA_SONG_PRELUDE
};
@@ -31,12 +32,12 @@ static const int entranceIndexMap[] = {
};
static const int songAudioMap[] = {
- NA_BGM_OCA_MINUET,
- NA_BGM_OCA_BOLERO,
- NA_BGM_OCA_SERENADE,
- NA_BGM_OCA_REQUIEM,
- NA_BGM_OCA_NOCTURNE,
- NA_BGM_OCA_LIGHT
+ NA_BGM_OCA_MINUET,
+ NA_BGM_OCA_BOLERO,
+ NA_BGM_OCA_SERENADE,
+ NA_BGM_OCA_REQUIEM,
+ NA_BGM_OCA_NOCTURNE,
+ NA_BGM_OCA_LIGHT
};
static bool isWarpActive = false;
@@ -87,6 +88,47 @@ void PauseWarp_HandleSelection() {
int song = gPlayState->pauseCtx.cursorPoint[PAUSE_QUEST];
if (aButtonPressed && CHECK_QUEST_ITEM(song) && song >= QUEST_SONG_MINUET && song <= QUEST_SONG_PRELUDE &&
gPlayState->pauseCtx.pageIndex == PAUSE_QUEST && gPlayState->pauseCtx.state == 6) {
+ if (gSaveContext.ship.quest.id == QUEST_RANDOMIZER && Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS)) {
+ bool canplay = false;
+ switch (song) {
+ case QUEST_SONG_MINUET:
+ canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
+ break;
+ case QUEST_SONG_BOLERO:
+ canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
+ break;
+ case QUEST_SONG_SERENADE:
+ canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
+ break;
+ case QUEST_SONG_REQUIEM:
+ canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
+ break;
+ case QUEST_SONG_NOCTURNE:
+ canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
+ break;
+ case QUEST_SONG_PRELUDE:
+ canplay = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) &&
+ Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
+ break;
+ }
+ if (!canplay) {
+ return;
+ }
+ }
ActivateWarp(&gPlayState->pauseCtx, song);
}
}
diff --git a/soh/soh/Enhancements/presets.cpp b/soh/soh/Enhancements/presets.cpp
index a823844f6..b72143247 100644
--- a/soh/soh/Enhancements/presets.cpp
+++ b/soh/soh/Enhancements/presets.cpp
@@ -75,7 +75,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
if (presetTypeId == PRESET_TYPE_RANDOMIZER){
- Rando::Context::GetInstance()->GetSettings()->ReloadOptions();
+ Rando::Settings::GetInstance()->ReloadOptions();
}
}
ImGui::PopStyleVar(1);
diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h
index 965fa2678..31df92831 100644
--- a/soh/soh/Enhancements/presets.h
+++ b/soh/soh/Enhancements/presets.h
@@ -342,8 +342,6 @@ const std::vector cheatCvars = {
CVAR_CHEAT("EasyISG"),
CVAR_CHEAT("EasyQPA"),
CVAR_CHEAT("TimelessEquipment"),
- CVAR_CHEAT("EasyPauseBuffer"),
- CVAR_CHEAT("EasyInputBuffer"),
CVAR_CHEAT("NoRestrictItems"),
CVAR_CHEAT("FreezeTime"),
CVAR_GENERAL("PrevTime"),
@@ -408,7 +406,6 @@ const std::vector randomizerCvars = {
CVAR_RANDOMIZER_SETTING("DoorOfTime"),
CVAR_RANDOMIZER_SETTING("DungeonCount"),
CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"),
- CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"),
CVAR_RANDOMIZER_SETTING("FishingPoleHint"),
CVAR_RANDOMIZER_SETTING("Fishsanity"),
CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"),
@@ -1010,7 +1007,6 @@ const std::vector spockRacePresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("GoronPot"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ForgeTime"), 0),
- PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("DampeAllNight"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("10GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("20GSHint"), 1),
@@ -1062,7 +1058,6 @@ const std::vector spockRaceNoLogicPresetEntries = {
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AdultMasks"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 6),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AssignableTunicsAndBoots"), 1),
- PRESET_ENTRY_S32(CVAR_CHEAT("EasyPauseBuffer"), 1),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 3),
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("ClimbSpeed"), 4),
PRESET_ENTRY_S32(CVAR_COSMETIC("Goron.NeckLength"), 1000),
@@ -1200,7 +1195,6 @@ const std::vector hellModePresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_OPEN),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1),
- PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_OFF),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GanonTrialCount"), 6),
diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp
index 269ad23c0..234bd6a8e 100644
--- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp
@@ -238,10 +238,10 @@ static int GetMaxGSCount() {
int maxBridge = 0;
int maxLACS = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
- maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex();
+ maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
- maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex();
+ maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get();
}
maxBridge = std::max(maxBridge, maxLACS);
//Get the max amount of GS which could be useful from token reward locations
@@ -266,7 +266,7 @@ static int GetMaxGSCount() {
maxUseful = 10;
}
//Return max of the two possible reasons tokens could be important, minus the tokens in the starting inventory
- return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex();
+ return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get();
}
std::string GetShopItemBaseName(std::string itemName) {
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
index 49d090a26..fd1f5ae4d 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
@@ -1455,915 +1455,300 @@ void StaticData::HintTable_Init() {
| JUNK HINT TEXT |
---------------------------*/
- hintTextTable[RHT_JUNK02] = HintText(CustomMessage("They say you must read the names of \"Special Deal\" shop items carefully.",
- /*german*/ "",
- /*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!"));
- // /*spanish*/"Según dicen, se debería prestar atención a los nombres de las ofertas especiales."
+ hintTextTable[RHT_JUNK01] = HintText(CustomMessage("They say you must read the names of \"Special Deal\" shop items carefully.",
+ /*german*/ "",
+ /*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!"));
- hintTextTable[RHT_JUNK03] = HintText(CustomMessage("They say that Zelda is a poor leader.",
+ hintTextTable[RHT_JUNK02] = HintText(CustomMessage("They say that Zelda is a poor leader.",
/*german*/ "",
/*french*/ "Selon moi, Zelda ne ferait pas un bon monarque."));
- // /*spanish*/Según dicen, Zelda es mala líder.
- hintTextTable[RHT_JUNK04] = HintText(CustomMessage("These hints can be quite useful. This is an exception.",
+ hintTextTable[RHT_JUNK03] = HintText(CustomMessage("These hints can be quite useful. This is an exception.",
/*german*/ "",
/*french*/ "Ces indices sont très utiles, à l'exception de celui-ci."));
- // /*spanish*/Las pistas suelen servir de ayuda. En cambio, esta no.
- hintTextTable[RHT_JUNK05] = HintText(CustomMessage("They say that the Lizalfos in Dodongo's Cavern like to play in lava.",
+ hintTextTable[RHT_JUNK04] = HintText(CustomMessage("They say that the Lizalfos in Dodongo's Cavern like to play in lava.",
/*german*/ "",
/*french*/ "Selon moi, les Lézalfos de la Caverne Dodongo aiment patauger dans la lave."));
- // /*spanish*/Según dicen, a los Lizalfos de la Cueva de los Dodongos les gusta jugar en la lava.
- hintTextTable[RHT_JUNK06] = HintText(CustomMessage("They say that all the Zora drowned in Wind Waker.",
+ hintTextTable[RHT_JUNK05] = HintText(CustomMessage("They say that all the Zora drowned in Wind Waker.",
/*german*/ "",
/*french*/ "Selon moi, les Zoras se sont noyés dans Wind Waker."));
- // /*spanish*/Según dicen, en Wind Waker todos los zora se ahogaron.
- hintTextTable[RHT_JUNK07] = HintText(CustomMessage("If Gorons eat rocks, does that mean I'm in danger?",
+ hintTextTable[RHT_JUNK06] = HintText(CustomMessage("If Gorons eat rocks, does that mean I'm in danger?",
/*german*/ "",
/*french*/ "Ne dis pas au Gorons que je suis ici. Ils mangent des roches, tu sais!"));
- // /*spanish*/Si los Goron se tragan las piedras, ¿no me hace ser una especia vulnarable o algo así
- hintTextTable[RHT_JUNK08] = HintText(CustomMessage("'Member when Ganon was a blue pig?^I 'member.",
+ hintTextTable[RHT_JUNK07] = HintText(CustomMessage("'Member when Ganon was a blue pig?^I 'member.",
/*german*/ "",
/*french*/ "Dans mon temps, Ganon était un cochon bleu...^Pff! Les jeunes de nos jours, et leur Ganondorf!"));
- // /*spanish*/¿T'acuerdas cuando Ganon era un cerdo azul?^Qué tiempos, chico.
- hintTextTable[RHT_JUNK09] = HintText(CustomMessage("One who does not have Triforce can't go in.",
+ hintTextTable[RHT_JUNK08] = HintText(CustomMessage("One who does not have Triforce can't go in.",
/*german*/ "",
/*french*/ "Ceux sans Triforce doivent rebrousser chemin."));
- // /*spanish*/Aquel que no porte la Trifuerza no podrá pasar.
- hintTextTable[RHT_JUNK10] = HintText(CustomMessage("Save your future, end the Happy Mask Salesman.",
+ hintTextTable[RHT_JUNK09] = HintText(CustomMessage("Save your future, end the Happy Mask Salesman.",
/*german*/ "",
/*french*/ "Selon moi, tu t'éviteras des jours de malheur si tu vaincs le vendeur de masques..."));
- // /*spanish*/Salva tu futuro, acaba con el dueño de La Máscara Feliz.
- hintTextTable[RHT_JUNK11] = HintText(CustomMessage("Glitches are a pathway to many abilities some consider to be... Unnatural.",
+ hintTextTable[RHT_JUNK10] = HintText(CustomMessage("Glitches are a pathway to many abilities some consider to be... Unnatural.",
/*german*/ "",
/*french*/ "Les glitchs sont un moyen d'acquérir de nombreuses facultés considérées par certains comme... contraire "));
- // /*spanish*/ Los glitches son el camino a muchas habilidades que varios consideran... nada natural.
- hintTextTable[RHT_JUNK12] = HintText(CustomMessage("I'm stoned. Get it?",
+ hintTextTable[RHT_JUNK11] = HintText(CustomMessage("I'm stoned. Get it?",
/*german*/ "",
/*french*/ "Allez, roche, papier, ciseau...&Roche."));
- // /*spanish*/Me he quedado de piedra. ¿Lo pillas?
- hintTextTable[RHT_JUNK13] = HintText(CustomMessage("Hoot! Hoot! Would you like me to repeat that?",
+ hintTextTable[RHT_JUNK12] = HintText(CustomMessage("Hoot! Hoot! Would you like me to repeat that?",
/*german*/ "",
/*french*/ "Hou hou! Veux-tu que je répète tout ça?"));
- // /*spanish*/¡Buuu, buuu! ¿Te lo vuelvo a repetir?
- hintTextTable[RHT_JUNK14] = HintText(CustomMessage("Gorons are stupid. They eat rocks.",
+ hintTextTable[RHT_JUNK13] = HintText(CustomMessage("Gorons are stupid. They eat rocks.",
/*german*/ "",
/*french*/ "Les Gorons sont des vraies têtes dures."));
- // /*spanish*/Los Goron son tontos. Se comen las piedras.
- hintTextTable[RHT_JUNK15] = HintText(CustomMessage("They say that Lon Lon Ranch prospered under Ingo.",
+ hintTextTable[RHT_JUNK14] = HintText(CustomMessage("They say that Lon Lon Ranch prospered under Ingo.",
/*german*/ "",
/*french*/ "Selon moi, le Ranch Lon Lon était plus prospère sous Ingo."));
- // /*spanish*/Según dicen, el Rancho Lon Lon prosperó gracias a Ingo.
- hintTextTable[RHT_JUNK16] = HintText(CustomMessage("The single rupee is a unique item.",
- /*german*/ "",
- /*french*/ "Nul objet n'est plus unique que le rubis vert."));
- // /*spanish*/La rupia de uno es un objeto singular.
-
- hintTextTable[RHT_JUNK17] = HintText(CustomMessage("Without the Lens of Truth, the Treasure Chest Mini-Game is a 1 out of 32 chance.^Good luck!",
+ hintTextTable[RHT_JUNK15] = HintText(CustomMessage("They say without the Lens of Truth, the Treasure Chest Mini-Game is a 1 out of 32 chance.^Good luck!",
/*german*/ "",
/*french*/ "Gagner la Chasse-aux-Trésors est 1 chance sur 32.^Bonne chance!"));
- // /*spanish*/Sin la Lupa de la Verdad, ganarías 1/32 veces en el Cofre del Tesoro.^¡Buena suerte con ello!
- hintTextTable[RHT_JUNK18] = HintText(CustomMessage("Use bombs wisely.",
+ hintTextTable[RHT_JUNK16] = HintText(CustomMessage("Use bombs wisely.",
/*german*/ "",
/*french*/ "Utilise les bombes avec précaution."));
- // /*spanish*/No desperdicies las bombas.
- hintTextTable[RHT_JUNK19] = HintText(CustomMessage("They say that Volvagia hates splinters",
- /*german*/ "",
- /*french*/ "Selon moi, Volvagia déteste les échardes."));
- // /*spanish*/Según dicen, Volvagia le teme a las astillas.
-
- hintTextTable[RHT_JUNK20] = HintText(CustomMessage("They say that funky monkeys can be spotted on Friday.",
- /*german*/ "",
- /*french*/ "Selon moi, des capucins coquins sortent le vendredi."));
- // /*spanish*/Según dicen, en los viernes puedes hallar monos marchosos.
-
- hintTextTable[RHT_JUNK21] = HintText(CustomMessage("I found you, faker!",
- /*german*/ "",
- /*french*/ "Ah-ha! Je t'ai trouvé!"));
- // /*spanish*/¡Ahí estás, impostor!
-
- hintTextTable[RHT_JUNK22] = HintText(CustomMessage("They say the Groose is loose.",
- /*german*/ "",
- /*french*/ "Selon moi, Hergo est le vrai héros."));
- // /*spanish*/Según dicen, Malton es un espanto.
-
- hintTextTable[RHT_JUNK23] = HintText(CustomMessage("They say that players who select the \"ON\" option for \"MOTION CONTROL\" are the real \"Zelda players!\"",
+ hintTextTable[RHT_JUNK17] = HintText(CustomMessage("They say that players who select the \"ON\" option for \"MOTION CONTROL\" are the real \"Zelda players!\"",
/*german*/ "",
/*french*/ "Selon moi, ceux qui utilisent les contrôles gyroscopiques sont les VRAIS joueurs."));
- // /*spanish*/ "Según dicen, aquellos que juegan usando el control por movimiento son los verdaderos jugadores de Zelda."
- hintTextTable[RHT_JUNK24] = HintText(CustomMessage("What happened to Sheik?",
- /*german*/ "",
- /*french*/ "Donc... Qu'est-ce qui arrive avec Sheik?"));
- // /*spanish*/¿Qué la habrá pasado a Sheik?
-
- hintTextTable[RHT_JUNK25] = HintText(CustomMessage("L2P @.",
+ hintTextTable[RHT_JUNK18] = HintText(CustomMessage("L2P @.",
/*german*/ "",
/*french*/ "Arrête de lire les indices et joue comme un grand, @."));
- // /*spanish*/Mira que eres novato, @.
- hintTextTable[RHT_JUNK26] = HintText(CustomMessage("I've heard you can cheat at Sploosh Kaboom.",
- /*german*/ "",
- /*french*/ "Selon moi, il y a une carte aux trésors à Mercantîle... Duh!"));
- // /*spanish*/He oído por ahí que puedes hacer trampa en el Sploosh Kaboom.
-
- hintTextTable[RHT_JUNK27] = HintText(CustomMessage("I'm Lonk from Pennsylvania.",
- /*german*/ "",
- /*french*/ "Je suis Lonk, le héros de Pennsylvanie!"));
- // /*spanish*/Soy Lonk, de Pensilvania.
-
- hintTextTable[RHT_JUNK28] = HintText(CustomMessage("I bet you'd like to have more bombs.",
+ hintTextTable[RHT_JUNK19] = HintText(CustomMessage("I bet you'd like to have more bombs.",
/*german*/ "",
/*french*/ "Je parie que tu veux plus de bombes."));
- // /*spanish*/Me apuesto a que quisieras tener más bombas.
- hintTextTable[RHT_JUNK29] = HintText(CustomMessage("When all else fails, use Fire.",
+ hintTextTable[RHT_JUNK20] = HintText(CustomMessage("When all else fails, use Fire.",
/*german*/ "",
/*french*/ "Quand rien ne marche, utilise le feu."));
- // /*spanish*/Cuando nada funcione, usa el fuego.
- hintTextTable[RHT_JUNK30] = HintText(CustomMessage("Here's a hint, @. Don't be bad.",
+ hintTextTable[RHT_JUNK21] = HintText(CustomMessage("Here's a hint, @. Don't be bad.",
/*german*/ "",
/*french*/ "Selon moi, la #Triforce# n'est pas dans le jeu... Duh!"));
- // /*spanish*/Aquí tienes una pista, @: deja de ser manco.
- hintTextTable[RHT_JUNK31] = HintText(CustomMessage("Game Over. Return of Ganon.",
+ hintTextTable[RHT_JUNK22] = HintText(CustomMessage("Game Over. Return of Ganon.",
/*german*/ "",
/*french*/ "Partie terminée. RETour de Ganon."));
- // /*spanish*/Fin de la partida. El regreso de Ganon.
- hintTextTable[RHT_JUNK32] = HintText(CustomMessage("May the way of the Hero lead to the Triforce.",
+ hintTextTable[RHT_JUNK23] = HintText(CustomMessage("May the way of the Hero lead to the Triforce.",
/*german*/ "",
/*french*/ "Que le chemin du héros te mène à la Triforce."));
- // /*spanish*/Puede que la senda del héroe te lleve hacia la Trifuerza.
- hintTextTable[RHT_JUNK33] = HintText(CustomMessage("Can't find an item? Scan an Amiibo.",
+ hintTextTable[RHT_JUNK24] = HintText(CustomMessage("Can't find an item? Scan an Amiibo.",
/*german*/ "",
/*french*/ "Tu cherches de quoi? Utilise un Amiibo!"));
- // /*spanish*/¿No encuentras algo? Escanea un amiibo.
- hintTextTable[RHT_JUNK34] = HintText(CustomMessage("They say this game has just a few glitches.",
+ hintTextTable[RHT_JUNK25] = HintText(CustomMessage("They say this game has just a few glitches.",
/*german*/ "",
/*french*/ "Selon moi, ce jeu est complètement exempt de glitchs."));
- // /*spanish*/Dicen que este juego apenas tiene glitches.
- hintTextTable[RHT_JUNK35] = HintText(CustomMessage("BRRING BRRING This is Ulrira. Wrong number?",
+ hintTextTable[RHT_JUNK26] = HintText(CustomMessage("BRRING BRRING This is Ulrira. Wrong number?",
/*german*/ "",
/*french*/ "DRING DRING!! Pépé le Ramollo à l'appareil... Quoi? Faux numéro?"));
- // /*spanish*/¡Ring! ¡Ring! Al habla Ulrira. ¿Me he equivocado de número?
- hintTextTable[RHT_JUNK36] = HintText(CustomMessage("Tingle Tingle Kooloo Limpah!",
+ hintTextTable[RHT_JUNK27] = HintText(CustomMessage("Tingle Tingle Kooloo Limpah!",
/*german*/ "",
/*french*/ "Tingle! Tingle! Kooloolin... Pah!"));
- // /*spanish*/Tingle, Tingle, Kurulín... ¡PA!
- hintTextTable[RHT_JUNK37] = HintText(CustomMessage("L is real 2401",
+ hintTextTable[RHT_JUNK28] = HintText(CustomMessage("L is real 2401",
/*german*/ "",
/*french*/ "L is real 2401"));
- // /*spanish*/L es real 2401.
- hintTextTable[RHT_JUNK38] = HintText(CustomMessage("They say that Ganondorf will appear in the next Mario Tennis.",
+ hintTextTable[RHT_JUNK29] = HintText(CustomMessage("They say that Ganondorf will appear in the next Mario Tennis.",
/*german*/ "",
/*french*/ "Selon moi, Ganondorf sera la nouvelle recrue dans Mario Tennis."));
- // /*spanish*/Según dicen, Ganondorf estará en el próximo Mario Tennis.
- hintTextTable[RHT_JUNK39] = HintText(CustomMessage("Medigoron sells the earliest Breath of the Wild demo.",
+ hintTextTable[RHT_JUNK30] = HintText(CustomMessage("They say Medigoron sells the earliest Breath of the Wild demo.",
/*german*/ "",
/*french*/ "Selon moi, Medigoron vend une démo de #Breath of the Wild#."));
- // /*spanish*/Medigoron vende la primera demo del Breath of the Wild.
- hintTextTable[RHT_JUNK40] = HintText(CustomMessage("Can you move me? I don't get great service here.",
+ hintTextTable[RHT_JUNK31] = HintText(CustomMessage("Can you move me? I don't get great service here.",
/*german*/ "",
/*french*/ "Peux-tu me déplacer? J'ai pas une bonne réception ici."));
- // /*spanish*/¿Puedes llevarme a otro lado? Aquí nadie me presta atención.
- hintTextTable[RHT_JUNK41] = HintText(CustomMessage("They say if you use Strength on the truck, you can find Mew.",
+ hintTextTable[RHT_JUNK32] = HintText(CustomMessage("They say if you use Strength on the truck, you can find Mew.",
/*german*/ "",
/*french*/ "Selon moi, #Mew# se trouve dessous le camion... Duh!"));
- // /*spanish*/Según dicen, puedes hallar un Mew usando Fuerza contra el camión de Ciudad Carmín.
- hintTextTable[RHT_JUNK42] = HintText(CustomMessage("I'm a helpful hint Gossip Stone!^See, I'm helping.",
+ hintTextTable[RHT_JUNK33] = HintText(CustomMessage("I'm a helpful hint Gossip Stone!^See, I'm helping.",
/*german*/ "",
/*french*/ "Salut! Je suis une pierre de bons conseils!^Tiens, tu vois? J'aide bien, hein?"));
- // /*spanish*/Soy una Piedra Sheikah muy útil.^¡Mira cómo te ayudo!
- hintTextTable[RHT_JUNK43] = HintText(CustomMessage("Dear @, please come to the castle. I've baked a cake for you.&Yours truly, Princess Zelda.",
+ hintTextTable[RHT_JUNK34] = HintText(CustomMessage("Dear @, please come to the castle. I've baked a cake for you.&Yours truly, Princess Zelda.",
/*german*/ "",
/*french*/ "Mon très cher @:&Viens vite au château, je t'ai préparé&un délicieux gâteau...^À bientôt, Princesse Zelda"));
- // /*spanish*/Querido @: Por favor, ven al castillo. He hecho una tarta para ti.&Sinceramente tuya: Princesa Zelda.
- hintTextTable[RHT_JUNK44] = HintText(CustomMessage("They say all toasters toast toast.",
+ hintTextTable[RHT_JUNK35] = HintText(CustomMessage("They say all toasters toast toast.",
/*german*/ "",
/*french*/ "Selon moi, les grille-pains grillent du pain."));
- // /*spanish*/Según dicen, todas las tostadoras tostan tostadas tostadas.
- hintTextTable[RHT_JUNK45] = HintText(CustomMessage("You thought it would be a useful hint, but it was me, junk hint!",
+ hintTextTable[RHT_JUNK36] = HintText(CustomMessage("You thought it would be a useful hint, but it was me, junk hint!",
/*german*/ "",
/*french*/ "Tu t'attendais à un bon indice... Mais c'était moi, un mauvais indice!"));
- // /*spanish*/Je... Creeías que iba a ser una piedra de utilidad, ¡pero no, era yo, la piedra de la agonía!
- hintTextTable[RHT_JUNK46] = HintText(CustomMessage("They say that quest guidance can be found at a talking rock.",
+ hintTextTable[RHT_JUNK37] = HintText(CustomMessage("They say that quest guidance can be found at a talking rock.",
/*german*/ "",
/*french*/ "Selon moi, des #indices# se trouvent auprès d'une pierre parlante... Duh!"));
- // /*spanish*/Según dicen, puedes consultarle ayuda a rocas parlanchinas.
- hintTextTable[RHT_JUNK47] = HintText(CustomMessage("They say that the final item you're looking for can be found somewhere in Hyrule.",
+ hintTextTable[RHT_JUNK38] = HintText(CustomMessage("They say that the final item you're looking for can be found somewhere in Hyrule.",
/*german*/ "",
/*french*/ "Selon moi, le #dernier objet# se trouve quelque part dans Hyrule... Duh!"));
- // /*spanish*/Según dicen, el último objeto que te falte puede estar en cualquier rincón de Hyrule.
- hintTextTable[RHT_JUNK48] = HintText(CustomMessage("Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.",
+ hintTextTable[RHT_JUNK39] = HintText(CustomMessage("Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.",
/*german*/ "",
/*french*/ "Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip.^Mwip."));
- // /*spanish*/Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.^Mweep.
- hintTextTable[RHT_JUNK49] = HintText(CustomMessage("They say that Barinade fears Deku Nuts.",
+ hintTextTable[RHT_JUNK40] = HintText(CustomMessage("They say that Barinade fears Deku Nuts.",
/*german*/ "",
/*french*/ "Selon moi, Barinade a la frousse des noix Mojo."));
- // /*spanish*/Según dicen, lo que más teme a Barinade son las nueces deku.
- hintTextTable[RHT_JUNK50] = HintText(CustomMessage("They say that Flare Dancers do not fear Goron-crafted blades.",
+ hintTextTable[RHT_JUNK41] = HintText(CustomMessage("They say that Flare Dancers do not fear Goron-crafted blades.",
/*german*/ "",
/*french*/ "Selon moi, le danse-flamme n'a pas peur des armes de Goron."));
- // /*spanish*/Según dicen, los Bailafuegos no le temen a las armas forjadas por Gorons.
- hintTextTable[RHT_JUNK51] = HintText(CustomMessage("They say that Morpha is easily trapped in a corner.",
+ hintTextTable[RHT_JUNK42] = HintText(CustomMessage("They say that Morpha is easily trapped in a corner.",
/*german*/ "",
/*french*/ "Selon moi, Morpha est facilement coincé."));
- // /*spanish*/Según dicen, puedes atrapar a Morpha con facilidad en una esquina.
- hintTextTable[RHT_JUNK52] = HintText(CustomMessage("They say that Bongo Bongo really hates the cold.",
+ hintTextTable[RHT_JUNK43] = HintText(CustomMessage("They say that Bongo Bongo really hates the cold.",
/*german*/ "",
/*french*/ "Selon moi, Bongo Bongo a facilement froid aux doigts."));
- // /*spanish*/Según dicen, Bongo Bongo odia a muerte el frío.
- hintTextTable[RHT_JUNK53] = HintText(CustomMessage("They say that your sword is most powerful when you put it away.",
+ hintTextTable[RHT_JUNK44] = HintText(CustomMessage("They say that your sword is most powerful when you put it away.",
/*german*/ "",
/*french*/ "Selon moi, ton épée est à pleine puissance quand tu la rengaines."));
- // /*spanish*/Según dicen, tu espada se vuelve más poderosa si la guardas.
- hintTextTable[RHT_JUNK54] = HintText(CustomMessage("They say that bombing the hole Volvagia last flew into can be rewarding.",
+ hintTextTable[RHT_JUNK45] = HintText(CustomMessage("They say that bombing the hole Volvagia last flew into can be rewarding.",
/*german*/ "",
/*french*/ "Selon moi, le trou où se creuse Volvagia est vulnérable aux bombes."));
- // /*spanish*/Según dicen, trae buena suerte colocar una bomba en el último agujero de donde salió Volvagia.
- hintTextTable[RHT_JUNK55] = HintText(CustomMessage("They say that invisible ghosts can be exposed with Deku Nuts.",
+ hintTextTable[RHT_JUNK46] = HintText(CustomMessage("They say that invisible ghosts can be exposed with Deku Nuts.",
/*german*/ "",
/*french*/ "Selon moi, des fantômes invisibles apparaissent avec des noix Mojo."));
- // /*spanish*/Según dicen, puedes exponer a los espectros invisibles con nueces deku.
- hintTextTable[RHT_JUNK56] = HintText(CustomMessage("They say that the real Phantom Ganon is bright and loud.",
+ hintTextTable[RHT_JUNK47] = HintText(CustomMessage("They say that the real Phantom Ganon is bright and loud.",
/*german*/ "",
/*french*/ "Selon moi, le vrai spectre de Ganon est clair et bruyant."));
- // /*spanish*/Según dicen, el verdadero Ganon Fantasma es brillante y ruidoso.
- hintTextTable[RHT_JUNK57] = HintText(CustomMessage("They say that walking backwards is very fast.",
+ hintTextTable[RHT_JUNK48] = HintText(CustomMessage("They say that walking backwards is very fast.",
/*german*/ "",
/*french*/ "Selon moi, tu fais marche arrière très rapidement pour un héros."));
- // /*spanish*/Según dicen, es más rápido caminar hacia atrás.
- hintTextTable[RHT_JUNK58] = HintText(CustomMessage("They say that leaping above the Market entrance enriches most children.",
- /*german*/ "",
- /*french*/ "Selon moi, les enfants riches se pavanent en haut du pont-levis."));
- // /*spanish*/Según dicen, saltar por las cadenas a la entrada de la plaza enriquece a muchos chiquillos.
-
- hintTextTable[RHT_JUNK59] = HintText(CustomMessage("They say Ingo is not very good at planning ahead.",
+ hintTextTable[RHT_JUNK49] = HintText(CustomMessage("They say Ingo is not very good at planning ahead.",
/*german*/ "",
/*french*/ "Selon moi, Ingo ne fait pas un très bon geôlier."));
- // /*spanish*/Según dicen, a Ingo no se le da especialmente bien planificar con antelación.
- hintTextTable[RHT_JUNK60] = HintText(CustomMessage("You found a spiritual Stone! By which I mean, I worship Nayru.",
+ hintTextTable[RHT_JUNK50] = HintText(CustomMessage("You found a spiritual Stone! By which I mean, I worship Nayru.",
/*german*/ "",
/*french*/ "Vous avez trouvé une Pierre Ancestrale! En effet, je vénère la déesse Hylia."));
- // /*spanish*/¡Has encontrado una piedra espiritual! Es que le rindo culto a Nayru...
- hintTextTable[RHT_JUNK61] = HintText(CustomMessage("They say that a flying strike with a Deku Stick is no stronger than a grounded one.",
- /*german*/ "",
- /*french*/ "Selon moi, un coup de bâton sauté n'est pas meilleur qu'au sol."));
- // /*spanish*/Según dicen, los golpes aéreos con palos deku son tan fuertes como los normales.
-
- hintTextTable[RHT_JUNK62] = HintText(CustomMessage("Open your eyes.^Open your eyes.^Wake up, @.",
+ hintTextTable[RHT_JUNK51] = HintText(CustomMessage("Open your eyes.^Open your eyes.^Wake up, @.",
/*german*/ "",
/*french*/ "Réveille-toi...^Réveille-toi.^Ouvre les yeux, @."));
- // /*spanish*/Abre los ojos...^Abre los ojos...^Despierta, @...
- hintTextTable[RHT_JUNK63] = HintText(CustomMessage("They say that the Nocturne of Shadow can bring you very close to Ganon.",
+ hintTextTable[RHT_JUNK52] = HintText(CustomMessage("They say that the Nocturne of Shadow can bring you very close to Ganon.",
/*german*/ "",
/*french*/ "Selon moi, le nocturne de l'ombre peut t'amener très près de Ganon."));
- // /*spanish*/Según dicen, el Nocturno de la sombra te puede acercar mucho a Ganon.
- hintTextTable[RHT_JUNK64] = HintText(CustomMessage("They say that Twinrova always casts the same spell the first three times.",
+ hintTextTable[RHT_JUNK53] = HintText(CustomMessage("They say that Twinrova always casts the same spell the first three times.",
/*german*/ "",
/*french*/ "Selon moi, Twinrova lance toujours les mêmes trois premiers sorts."));
- // /*spanish*/Según dicen, Birova siempre lanza el mismo hechizo las tres primeras veces.
- hintTextTable[RHT_JUNK65] = HintText(CustomMessage("They say that the nightly builds may be unstable.",
+ hintTextTable[RHT_JUNK54] = HintText(CustomMessage("They say that the nightly builds may be unstable.",
/*german*/ "",
/*french*/ "Selon moi, les \"nightly builds\" peuvent être instables."));
- // /*spanish*/Según dicen, las últimas nightlies pueden llegar a ser algo inestables.
- hintTextTable[RHT_JUNK66] = HintText(CustomMessage("You're playing a Randomizer. I'm randomized!^Here's a random number: #4#.&Enjoy your Randomizer!",
+ hintTextTable[RHT_JUNK55] = HintText(CustomMessage("You're playing a Randomizer. I'm randomized!^Here's a random number: #4#.&Enjoy your Randomizer!",
/*german*/ "",
/*french*/ "Tu joues à un randomizer. Je suis aléatoire!^Voici un nombre aléatoire: #4#.&Bonne partie!"));
- // /*spanish*/¡Estás jugando un Randomizer! ¡Yo también estoy aleatorizada!^Aquí tienes un número aleatorio: #8#.&¡Diviértete!
- hintTextTable[RHT_JUNK67] = HintText(CustomMessage("They say Ganondorf's bolts can be reflected with glass or steel.",
+ hintTextTable[RHT_JUNK56] = HintText(CustomMessage("They say Ganondorf's bolts can be reflected with glass or steel.",
/*german*/ "",
/*french*/ "Selon moi, les éclairs de Ganon se reflètent sur l'acier et le verre."));
- // /*spanish*/Según dicen, puedes reflejar las esferas de energía de Ganondorf con cristal y acero.
- hintTextTable[RHT_JUNK68] = HintText(CustomMessage("They say Ganon's tail is vulnerable to nuts, arrows, swords, explosives, hammers...^...sticks, seeds, "
+ hintTextTable[RHT_JUNK57] = HintText(CustomMessage("They say Ganon's tail is vulnerable to nuts, arrows, swords, explosives, hammers...^...sticks, seeds, "
"boomerangs...^...rods, shovels, iron balls, angry bees...",
/*german*/ "",
/*french*/ "Selon moi, la queue de Ganon est vulnérable aux noix, flèches, épées, bombes, marteaux...^...bâtons, "
"graines, boomerangs...^...baguettes, pelles, boulets de fer, abeilles enragées..."));
- // /*spanish*/Según dicen, la cola de Ganon es vulnerable a nueces, flechas, espadas, explosivos,
- // martillos...^...palos, semillas, bumeráns...^...cetros, palas, bolas de hierro, abejas...
- hintTextTable[RHT_JUNK69] = HintText(CustomMessage("They say that you're wasting time reading this hint, but I disagree. Talk to me again!",
+ hintTextTable[RHT_JUNK58] = HintText(CustomMessage("They say that you're wasting time reading this hint, but I disagree. Talk to me again!",
/*german*/ "",
/*french*/ "Selon moi... tu sais quoi? Parle-moi encore, et je te le dirai!"));
- // /*spanish*/Según dicen, pierdes el tiempo en leer esta pista, pero no pienso igual. ¡Vuelve a hablarme, ya verás!
- hintTextTable[RHT_JUNK70] = HintText(CustomMessage("They say Ganondorf knows where to find the instrument of his doom.",
+ hintTextTable[RHT_JUNK59] = HintText(CustomMessage("They say Ganondorf knows where to find the instrument of his doom.",
/*german*/ "",
/*french*/ "Selon moi, Ganondorf sait où il a caché son point faible."));
- // /*spanish*/Según dicen, Ganondorf sabe dónde hallar el instrumento de su perdición.
- hintTextTable[RHT_JUNK71] = HintText(CustomMessage("I heard @ is pretty good at Zelda.",
+ hintTextTable[RHT_JUNK60] = HintText(CustomMessage("I heard @ is pretty good at Zelda.",
/*german*/ "",
/*french*/ "Apparemment, @ est super bon à Zelda."));
- // /*spanish*/He oído que a @ se le dan muy bien los Zelda.
- hintTextTable[RHT_JUNK72] = HintText(CustomMessage("Hi @, we've been trying to reach you about your car's extended warranty. ",
+ hintTextTable[RHT_JUNK61] = HintText(CustomMessage("Hi @, we've been trying to reach you about your car's extended warranty. ",
/*german*/ "",
/*french*/ "Bonjour, @. Vous avez une voiture? Vous savez, nous offrons des assurances abordables..."));
- // /*spanish*/Buenas, @. Le llamamos para ofrecerle un nuevo seguro de hogar que puede pagar en cómodos plazos, sin
- // intereses ni comisiones.
- hintTextTable[RHT_JUNK73] = HintText(CustomMessage("They say that the best weapon against Iron Knuckles is item 176.",
- /*german*/ "",
- /*french*/ "Selon moi, les hache-viandes sont vulnérables contre l'objet 176."));
- // /*spanish*/Según dicen, la mejor arma para enfrentarse a los Nudillos de hierro es el objeto 176.
-
- hintTextTable[RHT_JUNK74] = HintText(CustomMessage("They say that it's actually possible to beat the running man.",
+ hintTextTable[RHT_JUNK62] = HintText(CustomMessage("They say that it's actually possible to beat the running man.",
/*german*/ "",
/*french*/ "Selon moi, il est possible de battre le coureur.&Donc, tu prends ton arc, et..."));
- // /*spanish*/Según dicen, con mucha perseverancia puedes ganarle al corredor con la capucha de conejo.
- hintTextTable[RHT_JUNK75] = HintText(CustomMessage("They say that the stone-cold guardian of the Well is only present during work hours.",
- /*german*/ "",
- /*french*/ "Selon moi, le gardien de pierre du Puits quitte le soir pour aller se coucher."));
- // /*spanish*/Según dicen, la inmensa roca que bloquea el pozo solo trabaja en horas laborales.
-
- hintTextTable[RHT_JUNK76] = HintText(CustomMessage("They say this hint makes more sense in other languages.",
+ hintTextTable[RHT_JUNK63] = HintText(CustomMessage("They say this hint makes more sense in other languages.",
/*german*/ "",
/*french*/ "Selon moi, ces indices auraient pu être mieux traduits... Duh!"));
- // /*spanish*/Según dicen, esta pista revela algo de vital importancia si cambias el idioma del juego...
- hintTextTable[RHT_JUNK77] = HintText(CustomMessage("BOK? No way.",
- /*german*/ "",
- /*french*/ "BD'accord? Hors de question."));
- // /*spanish*/¿BVale? Ni hablar.
+ // ^ Junk hints above are from 3drando
+ // v Junk hints below are new to soh rando
- // ^ junk hints above are from 3drando
- // v junk hints below are new to soh rando
+ // Please keep hints to stuff related to ship directly, or to Nintendo/Zelda related stuff.
+ // And nothing that's super obscure that no one's going to understand.
#define HINT_TEXT_NEEDS_TRANSLATION_FR \
"Erreur 0x69a504:&Traduction manquante^C'est de la faute à Purple Hato!&J'vous jure!"
-
- hintTextTable[RHT_JUNK78] = HintText(CustomMessage("They say blarg...^...or at least briaguya does.",
+
+ hintTextTable[RHT_JUNK64] = HintText(CustomMessage("They say Greg is special.",
/*german*/ "",
- /*french*/ "Tout ce que j'ai à dire, c'est blarg...^... 'fin c'est plutôt ce que briaguya dirait."));
- // /*spanish*/blarg
+ /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
- hintTextTable[RHT_JUNK79] = HintText(CustomMessage("They say this peace is what all true warriors strive for.",
+ hintTextTable[RHT_JUNK65] = HintText(CustomMessage("They say the longer the Goron's neck, the wiser they are.",
/*german*/ "",
- /*french*/ "Selon moi, cette paix est ce pour quoi luttent tous les vrais guerriers."));
- // /*spanish*/blarg
+ /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
- hintTextTable[RHT_JUNK80] = HintText(CustomMessage("They say this ship is what all true gamers strive for.",
+ hintTextTable[RHT_JUNK66] = HintText(CustomMessage("They say this ship is what all true gamers strive for.",
/*german*/ "",
/*french*/ "Selon moi, cette version du port est ce pour quoi luttent tous les vrais gamers."));
- // /*spanish*/blarg
-
- hintTextTable[RHT_JUNK81] = HintText(CustomMessage("They say that Glowsticks can be found in the Raveyard.",
+
+ hintTextTable[RHT_JUNK67] = HintText(CustomMessage("They say that Glowsticks can be found in the Raveyard.",
/*german*/ "",
/*french*/ "On peut trouver des Bâtons Lumineux sur le dancefloor du cimetière."));
- // /*spanish*/blarg
- hintTextTable[RHT_JUNK_WTC_1] = HintText(CustomMessage("They say %rthere are no more than 18&people on this island.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+ hintTextTable[RHT_JUNK68] = HintText(CustomMessage("They say @'s uncle works for Nintendo.",
+ /*german*/ "",
+ /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
- hintTextTable[RHT_JUNK_WTC_2] = HintText(CustomMessage("They say I am one yet many",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+ hintTextTable[RHT_JUNK69] = HintText(CustomMessage("They say pulling all gravestones in the graveyard leads to something magical.",
+ /*german*/ "",
+ /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
- hintTextTable[RHT_JUNK_WTC_3] = HintText(CustomMessage("They say its all in the name of guiding&humanity down the right path.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+ hintTextTable[RHT_JUNK70] = HintText(CustomMessage("They say holding L while pausing makes you win the game.",
+ /*german*/ "",
+ /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
- hintTextTable[RHT_JUNK_WTC_4] = HintText(CustomMessage("They say \"Repetition requested\"",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_5] = HintText(CustomMessage("They say %rThe red tells only the truth!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_6] = HintText(CustomMessage("They say good tidings to you^my traitorous @",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_7] = HintText(CustomMessage("They say when the seagulls cried,&none were left alive.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_8] = HintText(CustomMessage("They say she is lying with the red letters!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_9] = HintText(CustomMessage("They say we'll meet again,&when something else cries.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_10] = HintText(CustomMessage("They say \"Forgive me, but-^Your script will not be used.&....After all...^The one writing the rest of "
- "the script...&will be me.\"",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_WTC_11] = HintText(CustomMessage("They say tea is best enjoyed...^\"\"With your fellow monsters.\"\"",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
-
- hintTextTable[RHT_JUNK_WTC_12] = HintText(CustomMessage("They say I shall make you some black tea. With my own hands, not magic.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_1] = HintText(CustomMessage("They say you know I've kiboshed before...^and I will kibosh again.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_2] = HintText(CustomMessage("They say if relationship @ walks through that door,^they will KILL independent @.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_3] = HintText(CustomMessage("They say you gotta have the BIG Salad.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_4] = HintText(CustomMessage("They say it's a festivus miracle",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_5] = HintText(CustomMessage("They say there are no houses in Tuscany to rent.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_6] = HintText(CustomMessage("They say my last boyfriend had a real&Kroner comprehension problem.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_7] = HintText(CustomMessage("They say it's a festivus miracle.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_8] = HintText(CustomMessage("They say Louis quit the importing&to focus on the exporting.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_9] = HintText(CustomMessage("They say no thanks, I can't drink coffee&late at night, it keeps me up.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_10] = HintText(CustomMessage("They say it's not a lie if you believe it.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_11] = HintText(CustomMessage("They say there was a second spitter.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_12] = HintText(CustomMessage("They say there was a second spitter.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_13] = HintText(CustomMessage("They say the jerk store called,^they're running out of YOU.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_14] = HintText(CustomMessage("They say when you look annoyed all the time,&people thing you are busy.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_15] = HintText(CustomMessage("They say when you look annoyed all the time,&people think you are busy.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_16] = HintText(CustomMessage("They say he fires people like its a bodily function.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_17] = HintText(CustomMessage("They say he threatened to move the ship to New Jersey&just to upset people.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_18] = HintText(CustomMessage("They say there was significant shrinkage.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_19] = HintText(CustomMessage("They say if it wasn't for the toilet there'd be no books.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_20] = HintText(CustomMessage("They say if it wasn't for the toilet there'd be no books.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_21] = HintText(CustomMessage("They say don't trust men in capes.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_22] = HintText(CustomMessage("They say @'s uncle works for Nintendo.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_23] = HintText(CustomMessage("They say @'s stole the marble rye.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_24] = HintText(CustomMessage("They say there is no better harmony&than the black and white cookie.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_25] = HintText(CustomMessage("They say @ hasn't vomited since 1983.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_26] = HintText(CustomMessage("They say you gotta have the early bird special.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_27] = HintText(CustomMessage("They say a donation has been made in your name&to the human fund.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_28] = HintText(CustomMessage("They say you want to be my latex salesman.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SEI_29] = HintText(CustomMessage("They say if every instinct you have is wrong...^... then the opposite would have to be right.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_1] = HintText(CustomMessage("They say OTR stands for&Over the Rainbow",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_2] = HintText(CustomMessage("They say that OTR stands for&Onions, Tomatoes, and Radishes",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_3] = HintText(CustomMessage("They say that OTR stands for&Ocarina of Time Resources",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_4] = HintText(CustomMessage("They say that OTR stands for&Over the Road",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_5] = HintText(CustomMessage("They say that OTR stands for&Off the Record",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_6] = HintText(CustomMessage("They say that OTR stands for&Office of Tax and Revenue",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_7] = HintText(CustomMessage("They say OTR stands for&Over the Rainbow",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_8] = HintText(CustomMessage("They say that OTR stands for&Office of Trade Relations",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_9] = HintText(CustomMessage("They say that OTR stands for&Original Theatrical Release",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_10] = HintText(CustomMessage("They say that OTR stands for&Operational Test Requirement",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_11] = HintText(CustomMessage("They say that OTR stands for&Operational Trouble Report",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_12] = HintText(CustomMessage("They say that OTR stands for&Oxygen Transmission Rate",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_13] = HintText(CustomMessage("They say that OTR stands for&One Touch Recording",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_14] = HintText(CustomMessage("They say that OTR stands for&Olympic Torch Relay",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_15] = HintText(CustomMessage("They say that OTR stands for&Off the Rack",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_16] = HintText(CustomMessage("They say that OTR stands for&Overhead Transfer Rate",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_17] = HintText(CustomMessage("They say that OTR stands for&Operational TurnaRound",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_18] = HintText(CustomMessage("They say that OTR stands for&Opportunity to Recall",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_19] = HintText(CustomMessage("They say that OTR stands for&Operability Test Report",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_20] = HintText(CustomMessage("They say that OTR stands for&Overall Tuning Range",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_21] = HintText(CustomMessage("They say that OTR stands for&One Time Requisition",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_22] = HintText(CustomMessage("They say that OTR stands for&Oblivious to Reality",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_23] = HintText(CustomMessage("They say that OTR stands for&On the Run",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_24] = HintText(CustomMessage("They say that OTR stands for&On Time Reporting",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_25] = HintText(CustomMessage("They say that OTR stands for&Order to Receipt",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_26] = HintText(CustomMessage("They say that OTR stands for&Other Terrestrial Radio",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_27] = HintText(CustomMessage("They say that OTR stands for&On Target Reports",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_28] = HintText(CustomMessage("They say that OTR stands for&One Time Repair",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_29] = HintText(CustomMessage("They say that OTR stands for&Own the Room",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_OTR_MEANS_30] = HintText(CustomMessage("They say that OTR stands for&Online Text Repository",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_1] = HintText(CustomMessage("They say #Kenix# isn't a developer...^...Just a PR guy",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR,
- {QM_GREEN}));
-
- hintTextTable[RHT_JUNK_MISC_2] = HintText(CustomMessage("They say... No",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_3] = HintText(CustomMessage("They say BIG RIGS: OTR",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_4] = HintText(CustomMessage("They say you wanted to see me #Mr. Kenix#?",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR,
- {QM_PINK}));
-
- hintTextTable[RHT_JUNK_MISC_5] = HintText(CustomMessage("They say Louis once saw an&equals not get set equals",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_6] = HintText(CustomMessage("They say only you can find your rom.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_7] = HintText(CustomMessage("They say ZAPD is good software.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_8] = HintText(CustomMessage("They say you can encounter&a parascode in tall grass.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_9] = HintText(CustomMessage("They say the ship sails on March 32nd.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_10] = HintText(CustomMessage("They say bombing dodongos is fun.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_11] = HintText(CustomMessage("They say shopkeepers don't give credits.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_12] = HintText(CustomMessage("They say shopkeepers don't give credits.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_13] = HintText(CustomMessage("They say Malon is glitched.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_14] = HintText(CustomMessage("They say do I look like I know&what a DList is?",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_15] = HintText(CustomMessage("They say do I look like I know&what an AList is?",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_16] = HintText(CustomMessage("They say the king drinks enthusiastically",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_MISC_17] = HintText(CustomMessage("They say Rubies are on the path to&Lamp Oil, Rope, and Bombs",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_1] = HintText(CustomMessage("They say %rError. Human is dead, mismatch.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_2] = HintText(CustomMessage("They say this is the choice of the&steins gate.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_3] = HintText(CustomMessage("They say el psy kongroo.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_4] = HintText(CustomMessage("They say tutturu~.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_5] = HintText(CustomMessage("They say im not Christina!.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_6] = HintText(CustomMessage("They say you know where to find an IBN5100.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_7] = HintText(CustomMessage("They say when you're on a chicken bender&grab a box of chicken tenders.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_SG_8] = HintText(CustomMessage("Juicy Chicken #1! Wow!.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_1] = HintText(CustomMessage("They say that %gGanondorf's Mom%w is going out with %ySqueak%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_2] = HintText(CustomMessage("They say that %gProxySaw%w is still fixing %yCaladius's Bugs%w...",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_3] = HintText(CustomMessage("They say that %gItsHeckinPat%w is still just %yEyeballing it%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_4] = HintText(CustomMessage("They say that %gCaladius%w is working on %yV2%w of something.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_5] = HintText(CustomMessage("They say that %gdice%w is a funny name for a %ytaco%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_6] = HintText(CustomMessage("They say %g2Ship Rando%w is still blocked by %yV3%w...",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_7] = HintText(CustomMessage("They say if you click your heels and say %gframebuffer%w 3 times, %yArchez%w appears!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_8] = HintText(CustomMessage("They say %gVB%w stands for %yVirtual Bananas%w... Probably.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_9] = HintText(CustomMessage("They say %gZeru%w is still routing his %yHundo%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_10] = HintText(CustomMessage("They say %gRaccoonCloud%w is still looking for his %yHover Boots%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_11] = HintText(CustomMessage("They say %gItsHeckinPat%w foreclosed on his %yHut%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_12] = HintText(CustomMessage("They say %gRaccoonCloud%w is part of the %yInner Circle%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_13] = HintText(CustomMessage("They say %gMoonlitxShadows%w is the %rleader%w of the %yDork Army%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_14] = HintText(CustomMessage("They say %gGanondorf%w hates the %yInternet%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_15] = HintText(CustomMessage("They say %gMido's House%w hoards %yTrash%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_16] = HintText(CustomMessage("They say %gSweettalking Ganondorf%w rewards %yHis Heart%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_17] = HintText(CustomMessage("They say %gaMannus%w said %yGo To Bed%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_18] = HintText(CustomMessage("They say %gCaladius%w is a %yPinhead%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_19] = HintText(CustomMessage("They say %gRaccoonCloud%w loves the %yIce Cavern%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_20] = HintText(CustomMessage("They say %gNo One%w should forget %yHover Scrub%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_21] = HintText(CustomMessage("They say %gMoonlitxShadows%w likes to %ySlide%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_23] = HintText(CustomMessage("They say that %gBackwalking%w should be %rBanned%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_24] = HintText(CustomMessage("They say that %gGorons%w should always have %yLong Necks%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_25] = HintText(CustomMessage("They say that %gCaladius%w has a %ytendency to lose his shirt%w!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_26] = HintText(CustomMessage("They say that if your %rSkip keeps Failing%w, you're probably an %yESS Off%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_27] = HintText(CustomMessage("They say that %gLogic%w is just a %ySuggestion%w.",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_28] = HintText(CustomMessage("They say there's %gAlways Logic%w in %yNo Logic%w...",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
-
- hintTextTable[RHT_JUNK_CREW_29] = HintText(CustomMessage("They said that %rFredomato%w has just %yone more push up%w to do!",
- /*german*/ "",
- /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+ hintTextTable[RHT_JUNK71] = HintText(CustomMessage("They say @'s body is ready.",
+ /*german*/ "",
+ /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
/*--------------------------
| DUNGEON HINT TEXT |
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp
index 2e0350e7c..ed447fe30 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp
@@ -882,11 +882,11 @@ hintTextTable[RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST] = HintText(CustomMessage("They sa
/*german*/ "",
/*french*/ "Selon moi, un #coeur dans le Temple du Feu# cache #[[1]]#.", {QM_RED, QM_GREEN}));
- hintTextTable[RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a hot arena# reveals #[[1]]#.",
+ hintTextTable[RHT_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a hot arena# reveals #[[1]]#.",
/*german*/ "!!!",
/*french*/ "Selon moi, #appeler le soleil dans une arène chaude# révèle #[[1]]#.", {QM_RED, QM_GREEN}));
- hintTextTable[RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun behind a knight's throne in a volcano# reveals #[[1]]#.",
+ hintTextTable[RHT_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun behind a knight's throne in a volcano# reveals #[[1]]#.",
/*german*/ "!!!",
/*french*/ "Selon moi, #appeler le soleil derrière le trône d’un chevalier dans un volcan# révèle #[[1]]#.", {QM_RED, QM_GREEN}));
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp
index 7837f2cb6..a6c6b99f3 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp
@@ -1935,6 +1935,24 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
hintTextTable[RHT_DMC_UPPER_GROTTO_GOSSIP_STONE_FAIRY_BIG] = HintText(CustomMessage("They say that #playing a stormy tune for an odd stone within the side of a crater# reveals #[[1]]#.",
/*german*/ "!!!",
/*french*/ "Selon moi, jouer une mélodie orageuse pour une pierre étrange dans le côté d'un cratère révèle [[1]].", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_LH_ISLAND_SUN_FAIRY] = HintText(CustomMessage("They say that #summoning the sun on the lake's island# calls #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_HF_POND_STORMS_FAIRY] = HintText(CustomMessage("They say that #calling rain to the field's pond# summons #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_HF_FENCE_GROTTO_STORMS_FAIRY] = HintText(CustomMessage("They say that #making it rain in a scrub's cave# wakes #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_DMT_FLAG_SUN_FAIRY] = HintText(CustomMessage("They say that #changing the time in front of the trail's flag# reveals #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_DMT_COW_GROTTO_STORMS_FAIRY] = HintText(CustomMessage("They say that #calling a storm for a lonely cow# reveals #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_LW_SHORTCUT_STORMS_FAIRY] = HintText(CustomMessage("They say that #making it rain in the Lost Woods# reveals #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_GF_KITCHEN_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a guarded kitchen# exposes #[[1]]#.", {QM_RED, QM_GREEN}));
+
+ hintTextTable[RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun for scrubs in the Lost Woods# reveals #[[1]]#.", { QM_RED, QM_GREEN }));
+
+ hintTextTable[RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a royal tomb# reveals #[[1]]#.", { QM_RED, QM_GREEN }));
}
}
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp
index 89c290a40..867da2b2c 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp
@@ -1361,7 +1361,18 @@ void StaticData::HintTable_Init_Item() {
// /*spanish*/un destructor de cerraduras final
CustomMessage("a final lockpick", /*german*/"ein finaler Dietrich", /*french*/"un crochet à porte final")});
// /*spanish*/una apertura portentosa final
-
+ hintTextTable[RHT_OVERWORLD_KEY] = HintText(CustomMessage("an Overworld Key", /*german*/"ein Überwelt-Schlüssel", /*french*/"une clé de l'Overworld"),
+ // /*spanish*/una llave del mundo exterior
+ {
+ CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé")
+ // /*spanish*/una llave
+ }, {
+ CustomMessage("a key to the world", /*german*/"ein Schlüssel zur Welt", /*french*/"une clé du monde"),
+ // /*spanish*/una llave al mundo
+ CustomMessage("a key to the kingdom", /*german*/"ein Schlüssel zum Königreich", /*french*/"une clé du royaume"),
+ // /*spanish*/una llave al reino
+ CustomMessage("a key to the universe", /*german*/"ein Schlüssel zum Universum", /*french*/"une clé de l'univers")});
+ // /*spanish*/una llave al universo
hintTextTable[RHT_FOREST_TEMPLE_KEY_RING] = HintText(CustomMessage("a Forest Temple Key Ring", /*german*/"ein Schlüsselbund des Waldtempels", /*french*/"un trousseau de clés du Temple de la Forêt"),
// /*spanish*/un llavero del Templo del Bosque
{
diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
index 941f0924b..634c2ca56 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
@@ -112,10 +112,10 @@ StaticHintInfo::StaticHintInfo(HintType _type, std::vectorGetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
- stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex();
+ stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
- stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 6;
+ stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 6;
} else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
- stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 6;
+ stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 6;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
- stones = std::max({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex() });
+ stones = std::max({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
- stones = std::max({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 6 )});
+ stones = std::max({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 6 )});
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
- stones = std::max({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 6 )});
+ stones = std::max({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 6 )});
}
return stones;
}
@@ -242,18 +242,18 @@ uint8_t MedallionsRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t medallions = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
- medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex();
+ medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
- medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 3;
+ medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 3;
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
- medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 3;
+ medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 3;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
- medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex() });
+ medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
- medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 3 )});
+ medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3 )});
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
- medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 3 )});
+ medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3 )});
}
return medallions;
}
@@ -262,10 +262,10 @@ uint8_t TokensRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t tokens = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
- tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex();
+ tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
- tokens = std::max({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex() });
+ tokens = std::max({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get() });
}
return tokens;
}
@@ -273,7 +273,7 @@ uint8_t TokensRequiredBySettings() {
std::vector>> conditionalAlwaysHints = {
std::make_pair(RC_MARKET_10_BIG_POES, []() {
auto ctx = Rando::Context::GetInstance();
- return ctx->GetOption(RSK_BIG_POE_COUNT).GetContextOptionIndex() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
+ return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
}), // Remember, the option's value being 3 means 4 are required
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() {
auto ctx = Rando::Context::GetInstance();
@@ -483,7 +483,7 @@ static void CreateTrialHints(uint8_t copies) {
AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_ZERO_TRIALS});
} else {
std::vector trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment
- if (ctx->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() >= 4) {//4 or 5 required trials, get skipped trials
+ if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) {//4 or 5 required trials, get skipped trials
trials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();});
} else {//1 to 3 trials, get requried trials
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();});
@@ -611,7 +611,7 @@ uint8_t PlaceHints(std::vector& selectedHints, std::vectorGetOption(RSK_HINT_DISTRIBUTION).GetContextOptionIndex()];
+ const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Get()];
std::vector distTable = hintSetting.distTable;
// Apply impa's song exclusions when zelda is skipped
@@ -738,7 +738,7 @@ void CreateAdultAltarHint() {
void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(hint)->IsEnabled()){
- Option option = ctx->GetOption(staticData.setting);
+ OptionValue& option = ctx->GetOption(staticData.setting);
if ((std::holds_alternative(staticData.condition) && option.Is(std::get(staticData.condition))) ||
(std::holds_alternative(staticData.condition) && option.Is(std::get(staticData.condition)))){
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index cee278220..ff41c204b 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -761,7 +761,7 @@ static void SetMinimalItemPool() {
ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1);
ReplaceMaxItem(RG_PIECE_OF_HEART, 0);
// Need an extra heart container when starting with 1 heart to be able to reach 3 hearts
- ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() == 18)? 1 : 0);
+ ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Get() == 18)? 1 : 0);
}
void GenerateItemPool() {
@@ -827,7 +827,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
ctx->possibleIceTrapModels.push_back(RG_TRIFORCE_PIECE);
- AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
+ AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
ctx->PlaceItemInLocation(RC_TRIFORCE_COMPLETED, RG_TRIFORCE); // Win condition
ctx->PlaceItemInLocation(RC_GANON, GetJunkItem(), false, true);
} else {
@@ -935,7 +935,7 @@ void GenerateItemPool() {
if (fsMode.IsNot(RO_FISHSANITY_OFF)) {
if (fsMode.Is(RO_FISHSANITY_POND) || fsMode.Is(RO_FISHSANITY_BOTH)) {
// 17 max child pond fish
- uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).GetContextOptionIndex();
+ uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).Get();
for (uint8_t i = 0; i < pondCt; i++) {
AddItemToMainPool(GetJunkItem());
}
@@ -1276,6 +1276,33 @@ void GenerateItemPool() {
}
}
+ if (ctx->GetOption(RSK_LOCK_OVERWORLD_DOORS)) {
+ AddItemToPool(ItemPool, RG_GUARD_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_MARKET_BAZAAR_KEY);
+ AddItemToPool(ItemPool, RG_MARKET_POTION_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_MASK_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_MARKET_SHOOTING_GALLERY_KEY);
+ AddItemToPool(ItemPool, RG_BOMBCHU_BOWLING_KEY);
+ AddItemToPool(ItemPool, RG_TREASURE_CHEST_GAME_BUILDING_KEY);
+ AddItemToPool(ItemPool, RG_BOMBCHU_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_RICHARDS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_ALLEY_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_KAK_BAZAAR_KEY);
+ AddItemToPool(ItemPool, RG_KAK_POTION_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_BOSS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_GRANNYS_POTION_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_SKULLTULA_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_IMPAS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_WINDMILL_KEY);
+ AddItemToPool(ItemPool, RG_KAK_SHOOTING_GALLERY_KEY);
+ AddItemToPool(ItemPool, RG_DAMPES_HUT_KEY);
+ AddItemToPool(ItemPool, RG_TALONS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_STABLES_KEY);
+ AddItemToPool(ItemPool, RG_BACK_TOWER_KEY);
+ AddItemToPool(ItemPool, RG_HYLIA_LAB_KEY);
+ AddItemToPool(ItemPool, RG_FISHING_HOLE_KEY);
+ }
+
//Shopsanity
if (
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) ||
@@ -1491,7 +1518,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY);
- } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).GetContextOptionIndex() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
+ } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Get() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY);
diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp
index 07ba4fd07..6bcf21af9 100644
--- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp
@@ -44,12 +44,12 @@ bool GenerateRandomizer(std::set excludedLocations, std::setGetSettings()->SetSeedString(seedInput);
- uint32_t seedHash = boost::hash_32{}(ctx->GetSettings()->GetSeedString());
- ctx->GetSettings()->SetSeed(seedHash & 0xFFFFFFFF);
+ ctx->SetSeedString(seedInput);
+ uint32_t seedHash = boost::hash_32{}(ctx->GetSeedString());
+ ctx->SetSeed(seedHash & 0xFFFFFFFF);
ctx->ClearItemLocations();
- int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
+ int ret = Playthrough::Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);
if (ret < 0) {
if (ret == -1) { // Failed to generate after 5 tries
SPDLOG_ERROR("Failed to generate after 5 tries.");
@@ -60,14 +60,6 @@ bool GenerateRandomizer(std::set excludedLocations, std::setGetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
- for (Rando::Option* setting : ctx->GetSettings()->VanillaLogicDefaults) {
- setting->RestoreDelayedOption();
- }
- ctx->GetOption(RSK_KEYSANITY).RestoreDelayedOption();
- }
-
StopPerformanceTimer(PT_WHOLE_SEED);
SPDLOG_DEBUG("Full Seed Genration Time: {}ms", GetPerformanceTimer(PT_WHOLE_SEED).count());
SPDLOG_DEBUG("LogicReset time: {}ms", GetPerformanceTimer(PT_LOGIC_RESET).count());
diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp
index 7787ee468..144dee80a 100644
--- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp
@@ -31,10 +31,12 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations,
Regions::AccessReset();
StopPerformanceTimer(PT_REGION_RESET);
- ctx->GetSettings()->FinalizeSettings(excludedLocations, enabledTricks);
+ ctx->FinalizeSettings(excludedLocations, enabledTricks);
// once the settings have been finalized turn them into a string for hashing
std::string settingsStr;
- for (const Rando::OptionGroup& optionGroup : ctx->GetSettings()->GetOptionGroups()) {
+ auto& optionGroups = Rando::Settings::GetInstance()->GetOptionGroups();
+ for (size_t i = 0; i < RSG_MAX; i++) {
+ auto& optionGroup = optionGroups[i];
// don't go through non-menus
if (optionGroup.GetContainsType() == Rando::OptionGroupType::SUBGROUP) {
continue;
@@ -43,7 +45,15 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations,
for (Rando::Option* option : optionGroup.GetOptions()) {
if (option->IsCategory(Rando::OptionCategory::Setting)) {
if (option->GetOptionCount() > 0) {
- settingsStr += option->GetSelectedOptionText();
+ if (i >= RSG_EXCLUDES_KOKIRI_FOREST && i <= RSG_EXCLUDES_GANONS_CASTLE) {
+ auto locationOption = static_cast(option);
+ settingsStr += option->GetOptionText(ctx->GetLocationOption(locationOption->GetKey()).Get());
+ } else if (i == RSG_TRICKS) {
+ auto trickOption = static_cast(option);
+ settingsStr += option->GetOptionText(ctx->GetTrickOption(trickOption->GetKey()).Get());
+ } else {
+ settingsStr += option->GetOptionText(ctx->GetOption(option->GetKey()).Get());
+ }
}
}
}
@@ -53,9 +63,9 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations,
settingsStr += (char*)gBuildVersion;
}
- uint32_t finalHash = boost::hash_32{}(std::to_string(ctx->GetSettings()->GetSeed()) + settingsStr);
+ uint32_t finalHash = boost::hash_32{}(std::to_string(ctx->GetSeed()) + settingsStr);
Random_Init(finalHash);
- ctx->GetSettings()->SetHash(std::to_string(finalHash));
+ ctx->SetHash(std::to_string(finalHash));
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
@@ -94,12 +104,12 @@ int Playthrough_Repeat(std::set excludedLocations, std::setGetSettings()->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
- repeatedSeed = boost::hash_32{}(ctx->GetSettings()->GetSeedString());
- ctx->GetSettings()->SetSeed(repeatedSeed % 0xFFFFFFFF);
+ ctx->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
+ repeatedSeed = boost::hash_32{}(ctx->GetSeedString());
+ ctx->SetSeed(repeatedSeed % 0xFFFFFFFF);
SPDLOG_DEBUG("testing seed: %d", repeatedSeed);
ClearProgress();
- Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
+ Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);
SPDLOG_INFO("Seeds Generated: {}", i + 1);
}
diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
index b778efccf..edaf8aa5d 100644
--- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
@@ -156,7 +156,7 @@ int GetPriceFromMax(int max) {
uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSettings) {
auto ctx = Rando::Context::GetInstance();
- switch (ctx->GetOption(priceSettings.main).GetContextOptionIndex()){
+ switch (ctx->GetOption(priceSettings.main).Get()){
case RO_PRICE_VANILLA:
return loc->GetVanillaPrice();
case RO_PRICE_CHEAP_BALANCED:
@@ -172,19 +172,19 @@ uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSet
return 150;
}
case RO_PRICE_FIXED:
- return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).GetContextOptionIndex() * 5;
+ return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).Get() * 5;
case RO_PRICE_RANGE:{
- uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).GetContextOptionIndex() * 5;
- uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).GetContextOptionIndex() * 5;
+ uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).Get() * 5;
+ uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).Get() * 5;
return range1 < range2 ? Random(range1, range2+1) : Random(range2, range1+1);
}
case RO_PRICE_SET_BY_WALLET:{
- bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).GetContextOptionIndex();
- uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).GetContextOptionIndex();
- uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).GetContextOptionIndex();
- uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).GetContextOptionIndex();
- uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).GetContextOptionIndex();
- uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).GetContextOptionIndex() : 0;
+ bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).Get();
+ uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).Get();
+ uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).Get();
+ uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).Get();
+ uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).Get();
+ uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).Get() : 0;
uint16_t totalWeight = noWeight + childWeight + adultWeight + giantWeight + tycoonWeight;
if (totalWeight == 0){ //if no weight, return from sane range
return Random(0, 501);
diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp
index 10c1afb60..a21dacaaf 100644
--- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp
@@ -2,13 +2,14 @@
#include "../dungeon.h"
#include "../static_data.h"
-#include "../context.h"
+#include "../settings.h"
#include "../entrance.h"
#include "random.hpp"
#include "../trial.h"
#include "hints.hpp"
#include "pool_functions.hpp"
#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
+#include "soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
#include
#include
@@ -45,7 +46,7 @@ std::string placementtxt;
void GenerateHash() {
auto ctx = Rando::Context::GetInstance();
- std::string hash = ctx->GetSettings()->GetHash();
+ std::string hash = ctx->GetHash();
// adds leading 0s to the hash string if it has less than 10 digits.
while (hash.length() < 10) {
hash = "0" + hash;
@@ -91,8 +92,8 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
int16_t destinationIndex = -1;
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
int16_t replacementDestinationIndex = -1;
- std::string name = entrance->GetName();
- std::string text = entrance->GetConnectedRegion()->regionName + " from " + entrance->GetReplacement()->GetParentRegion()->regionName;
+ std::string name = GetEntranceData(originalIndex)->source;
+ std::string text = GetEntranceData(replacementIndex)->destination;
// Track the reverse destination, useful for savewarp handling
if (entrance->GetReverse() != nullptr) {
@@ -138,10 +139,10 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
// Writes the settings (without excluded locations, starting inventory and tricks) to the spoilerLog document.
static void WriteSettings() {
auto ctx = Rando::Context::GetInstance();
- std::array options = ctx->GetSettings()->GetAllOptions();
+ std::array options = Rando::Settings::GetInstance()->GetAllOptions();
for (const Rando::Option& option : options) {
if (option.GetName() != ""){
- jsonData["settings"][option.GetName()] = option.GetSelectedOptionText();
+ jsonData["settings"][option.GetName()] = option.GetOptionText(ctx->GetOption(option.GetKey()).Get());
}
}
}
@@ -156,9 +157,9 @@ std::string RemoveLineBreaks(std::string s) {
static void WriteExcludedLocations() {
auto ctx = Rando::Context::GetInstance();
- for (size_t i = 1; i < ctx->GetSettings()->GetExcludeLocationsOptions().size(); i++) {
- for (const auto& location : ctx->GetSettings()->GetExcludeLocationsOptions()[i]) {
- if (location->GetContextOptionIndex() == RO_LOCATION_INCLUDE) {
+ for (size_t i = 1; i < Rando::Settings::GetInstance()->GetExcludeLocationsOptions().size(); i++) {
+ for (const auto& location : Rando::Settings::GetInstance()->GetExcludeLocationsOptions()[i]) {
+ if (ctx->GetOption(location->GetKey()).Get() == RO_LOCATION_INCLUDE) {
continue;
}
@@ -171,11 +172,11 @@ static void WriteExcludedLocations() {
// Writes the starting inventory to the spoiler log, if there is any.
static void WriteStartingInventory() {
auto ctx = Rando::Context::GetInstance();
- const Rando::OptionGroup& optionGroup = ctx->GetSettings()->GetOptionGroup(RSG_STARTING_INVENTORY);
+ const Rando::OptionGroup& optionGroup = Rando::Settings::GetInstance()->GetOptionGroup(RSG_STARTING_INVENTORY);
for (const Rando::OptionGroup* subGroup : optionGroup.GetSubGroups()) {
if (subGroup->GetContainsType() == Rando::OptionGroupType::DEFAULT) {
for (Rando::Option* option : subGroup->GetOptions()) {
- jsonData["settings"][option->GetName()] = option->GetSelectedOptionText();
+ jsonData["settings"][option->GetName()] = option->GetOptionText(ctx->GetOption(option->GetKey()).Get());
}
}
}
@@ -185,8 +186,8 @@ static void WriteStartingInventory() {
static void WriteEnabledTricks() {
auto ctx = Rando::Context::GetInstance();
- for (const auto& setting : ctx->GetSettings()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
- if (setting->GetContextOptionIndex() != RO_GENERIC_ON) {
+ for (const auto& setting : Rando::Settings::GetInstance()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
+ if (ctx->GetOption(setting->GetKey()).IsNot(RO_GENERIC_ON)) {
continue;
}
jsonData["enabledTricks"].push_back(RemoveLineBreaks(setting->GetName()).c_str());
@@ -321,8 +322,8 @@ const char* SpoilerLog_Write() {
jsonData["version"] = (char*) gBuildVersion;
jsonData["git_branch"] = (char*) gGitBranch;
jsonData["git_commit"] = (char*) gGitCommitHash;
- jsonData["seed"] = ctx->GetSettings()->GetSeedString();
- jsonData["finalSeed"] = ctx->GetSettings()->GetSeed();
+ jsonData["seed"] = ctx->GetSeedString();
+ jsonData["finalSeed"] = ctx->GetSeed();
// Write Hash
int index = 0;
diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
index ca80c4b69..c72b5f285 100644
--- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
@@ -112,7 +112,7 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
// }
// AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value());
- AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).GetContextOptionIndex());
+ AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Get());
AddItemToInventory(RG_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY) ? 1 : 0);
AddItemToInventory(RG_EPONAS_SONG, ctx->GetOption(RSK_STARTING_EPONAS_SONG) ? 1 : 0);
AddItemToInventory(RG_SARIAS_SONG, ctx->GetOption(RSK_STARTING_SARIAS_SONG) ? 1 : 0);
@@ -153,21 +153,21 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value());
// AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value());
// AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value());
- AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex());
+ AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get());
- int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() - 2;
+ int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() - 2;
AdditionalHeartContainers = 0;
if (hearts < 0) {
AddItemToInventory(RG_PIECE_OF_HEART, 4);
// Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart
- if (ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 0 || ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 3) {
+ if (ctx->GetOption(RSK_ITEM_POOL).Get() == 0 || ctx->GetOption(RSK_ITEM_POOL).Get() == 3) {
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
AdditionalHeartContainers = 1 - hearts;
} else if (hearts > 0) {
// 16 containers in plentiful, 8 in balanced and 0 in the others
- uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex());
+ uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).Get());
if (hearts <= maxContainers) {
AddItemToInventory(RG_HEART_CONTAINER, hearts);
diff --git a/soh/soh/Enhancements/randomizer/LockOverworldDoors.cpp b/soh/soh/Enhancements/randomizer/LockOverworldDoors.cpp
new file mode 100644
index 000000000..b8b8f4731
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/LockOverworldDoors.cpp
@@ -0,0 +1,154 @@
+#include
+#include "soh/OTRGlobals.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+extern PlayState* gPlayState;
+#include "macros.h"
+#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
+}
+
+#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
+
+using SceneDoorParamsPair = std::pair;
+std::map lookupTable = {
+ {{ SCENE_MARKET_ENTRANCE_DAY, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_ENTRANCE_NIGHT, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_ENTRANCE_RUINS, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_GUARD_HOUSE, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 4543 }, RAND_INF_MARKET_BAZAAR_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 4753 }, RAND_INF_MARKET_BAZAAR_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 1471 }, RAND_INF_MARKET_POTION_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 1678 }, RAND_INF_MARKET_POTION_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 3519 }, RAND_INF_MASK_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 3728 }, RAND_INF_MASK_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 2495 }, RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 2703 }, RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_SHOOTING_GALLERY, 447 }, RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 5567 }, RAND_INF_BOMBCHU_BOWLING_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 5567 }, RAND_INF_BOMBCHU_BOWLING_UNLOCKED },
+ {{ SCENE_BOMBCHU_BOWLING_ALLEY, 447 }, RAND_INF_BOMBCHU_BOWLING_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 653 }, RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 447 }, RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED },
+ {{ SCENE_TREASURE_BOX_SHOP, 6591 }, RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_DAY, 2689 }, RAND_INF_BOMBCHU_SHOP_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_NIGHT, 2495 }, RAND_INF_BOMBCHU_SHOP_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_DAY, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_NIGHT, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_DOG_LADY_HOUSE, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_DOG_LADY_HOUSE, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_HOUSE, 447 }, RAND_INF_ALLEY_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_DAY, 1665 }, RAND_INF_ALLEY_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_NIGHT, 1471 }, RAND_INF_ALLEY_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 6801 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Adult Night
+ {{ SCENE_KAKARIKO_VILLAGE, 6591 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Adult Day
+ {{ SCENE_KAKARIKO_VILLAGE, 6813 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Child Day
+ {{ SCENE_KAKARIKO_VILLAGE, 6814 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Child Night
+ {{ SCENE_KAKARIKO_VILLAGE, 8871 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Child Day/Night Rear
+ {{ SCENE_KAKARIKO_VILLAGE, 8846 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Adult Night Rear
+ {{ SCENE_KAKARIKO_VILLAGE, 8639 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Adult Day Rear
+ {{ SCENE_KAKARIKO_VILLAGE, 7822 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Adult Night
+ {{ SCENE_KAKARIKO_VILLAGE, 7615 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Child Day/Night and Adult Day
+ {{ SCENE_KAKARIKO_VILLAGE, 2495 }, RAND_INF_BOSS_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_CENTER_GUEST_HOUSE, 447 }, RAND_INF_BOSS_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 3750 }, RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED }, // Child
+ {{ SCENE_KAKARIKO_VILLAGE, 3519 }, RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED }, // Adult
+ {{ SCENE_POTION_SHOP_GRANNY, 447 }, RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 5567 }, RAND_INF_SKULLTULA_HOUSE_UNLOCKED },
+ {{ SCENE_HOUSE_OF_SKULLTULA, 447 }, RAND_INF_SKULLTULA_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 1471 }, RAND_INF_IMPAS_HOUSE_UNLOCKED },
+ {{ SCENE_IMPAS_HOUSE, 447 }, RAND_INF_IMPAS_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 447 }, RAND_INF_WINDMILL_UNLOCKED },
+ {{ SCENE_WINDMILL_AND_DAMPES_GRAVE, 2495 }, RAND_INF_WINDMILL_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 4543 }, RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED }, // Day
+ {{ SCENE_KAKARIKO_VILLAGE, 4751 }, RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED }, // Night
+ {{ SCENE_SHOOTING_GALLERY, 447 }, RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_GRAVEYARD, 645 }, RAND_INF_DAMPES_HUT_UNLOCKED }, // Child Day
+ {{ SCENE_GRAVEYARD, 447 }, RAND_INF_DAMPES_HUT_UNLOCKED }, // Child Evening & Adult
+ {{ SCENE_GRAVEYARD, 774 }, RAND_INF_DAMPES_HUT_UNLOCKED }, // Child Night (After Dampes Tour)
+ {{ SCENE_GRAVEKEEPERS_HUT, 447 }, RAND_INF_DAMPES_HUT_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 2495 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 2473 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 2729 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_BUILDINGS, 1471 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 1471 }, RAND_INF_STABLES_UNLOCKED },
+ {{ SCENE_STABLE, 447 }, RAND_INF_STABLES_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 447 }, RAND_INF_BACK_TOWER_UNLOCKED },
+ {{ SCENE_LON_LON_BUILDINGS, 447 }, RAND_INF_BACK_TOWER_UNLOCKED },
+ {{ SCENE_LAKE_HYLIA, 447 }, RAND_INF_HYLIA_LAB_UNLOCKED },
+ {{ SCENE_LAKESIDE_LABORATORY, 447 }, RAND_INF_HYLIA_LAB_UNLOCKED },
+ {{ SCENE_LAKE_HYLIA, 1471 }, RAND_INF_FISHING_HOLE_UNLOCKED },
+ {{ SCENE_FISHING_POND, 447 }, RAND_INF_FISHING_HOLE_UNLOCKED },
+};
+
+static void OnDoorInit(void* actorRef) {
+ EnDoor* enDoor = static_cast(actorRef);
+ enDoor->randomizerInf = RAND_INF_MAX;
+
+ auto it = lookupTable.find({gPlayState->sceneNum, enDoor->actor.params});
+ if (it != lookupTable.end()) {
+ if (it->second == RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED && gSaveContext.entranceIndex == 0x3B) {
+ // Adult shooting gallery uses same scene and door params as child, so we manually handle it
+ enDoor->randomizerInf = RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED;
+ } else {
+ enDoor->randomizerInf = it->second;
+ }
+ if (!Flags_GetRandomizerInf(enDoor->randomizerInf)) {
+ // We don't want to override checkable doors, we still want those to not be openable even if they have a key
+ if (((enDoor->actor.params >> 7) & 7) != DOOR_CHECKABLE) {
+ enDoor->actor.params = (enDoor->actor.params & ~0x380) | (DOOR_LOCKED << 7);
+ enDoor->actionFunc = EnDoor_SetupType;
+ } else {
+ enDoor->lockTimer = 10;
+ }
+ }
+ }
+}
+
+void RegisterLockOverworldDoors() {
+ bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_LOCK_OVERWORLD_DOORS);
+
+ COND_ID_HOOK(OnActorInit, ACTOR_EN_DOOR, shouldRegister, OnDoorInit);
+
+ COND_VB_SHOULD(VB_CONSUME_SMALL_KEY, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
+ Flags_SetRandomizerInf(enDoor->randomizerInf);
+ *should = false;
+ }
+ });
+
+ COND_VB_SHOULD(VB_NOT_HAVE_SMALL_KEY, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
+ *should = !Flags_GetRandomizerInf((RandomizerInf)(enDoor->randomizerInf + 1));
+ }
+ });
+
+ COND_VB_SHOULD(VB_DOOR_BE_LOCKED, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
+ *should = !Flags_GetRandomizerInf(enDoor->randomizerInf);
+ }
+ });
+
+ // The door actor uses the same param to indicate if a door should be locked or be a scene transition, so it cannot be both. Here we're
+ // overriding the check for scene transition to also check if the door is being unlocked and should be a scene transition.
+ COND_VB_SHOULD(VB_DOOR_PLAY_SCENE_TRANSITION, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (!*should && (
+ enDoor->actor.id == ACTOR_EN_DOOR &&
+ ((enDoor->actor.params >> 7) & 7) == 1 &&
+ enDoor->randomizerInf != RAND_INF_MAX
+ )) {
+ *should = true;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterLockOverworldDoors, { "IS_RANDO" });
diff --git a/soh/soh/Enhancements/randomizer/Plandomizer.cpp b/soh/soh/Enhancements/randomizer/Plandomizer.cpp
index 3fc97eec7..2a086d377 100644
--- a/soh/soh/Enhancements/randomizer/Plandomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/Plandomizer.cpp
@@ -77,7 +77,7 @@ std::unordered_map ocarinaButtonNames = {
{ RG_OCARINA_C_RIGHT_BUTTON, "C-RHT" },
};
-std::map bossSoulMapping = {
+std::map bossSoulColorMapping = {
{ RG_GOHMA_SOUL, { 0.00f, 1.00f, 0.00f, 1.0f } },
{ RG_KING_DODONGO_SOUL, { 1.00f, 0.00f, 0.39f, 1.0f } },
{ RG_BARINADE_SOUL, { 0.20f, 1.00f, 1.00f, 1.0f } },
@@ -339,7 +339,7 @@ ImVec4 plandomizerGetItemColor(Rando::Item randoItem) {
}
if (randoItem.GetRandomizerGet() >= RG_GOHMA_SOUL && randoItem.GetRandomizerGet() <= RG_GANON_SOUL) {
- itemColor = bossSoulMapping.at(randoItem.GetRandomizerGet());
+ itemColor = bossSoulColorMapping.at(randoItem.GetRandomizerGet());
}
return itemColor;
diff --git a/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp b/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp
index e08bfbb92..7bf67b55d 100644
--- a/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp
+++ b/soh/soh/Enhancements/randomizer/ShuffleFreestanding.cpp
@@ -23,7 +23,7 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
Rando::Location* loc = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
uint8_t isDungeon = loc->IsDungeon();
uint8_t freestandingSetting =
- Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).GetContextOptionIndex();
+ Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).Get();
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();
diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp
index f5c7070dd..5b70b424e 100644
--- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp
+++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp
@@ -28,7 +28,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
RandomizerCheck rc = potActor->potIdentity.randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
- uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).GetContextOptionIndex();
+ uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
// Don't pull randomized item if pot isn't randomized or is already checked
if (!IS_RANDO || (potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
@@ -87,7 +87,7 @@ void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va
// Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon
if (id == VB_LOCK_BOSS_DOOR) {
DoorShutter* doorActor = va_arg(args, DoorShutter*);
- uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).GetContextOptionIndex();
+ uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 &&
(shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) {
*should = false;
diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp
index 7b33df771..3e846c4b7 100644
--- a/soh/soh/Enhancements/randomizer/context.cpp
+++ b/soh/soh/Enhancements/randomizer/context.cpp
@@ -28,8 +28,31 @@ Context::Context() {
mDungeons = std::make_shared();
mLogic = std::make_shared();
mTrials = std::make_shared();
- mSettings = std::make_shared();
mFishsanity = std::make_shared();
+ VanillaLogicDefaults = {
+ // RANDOTODO check what this does
+ &mOptions[RSK_LINKS_POCKET],
+ &mOptions[RSK_SHUFFLE_DUNGEON_REWARDS],
+ &mOptions[RSK_SHUFFLE_SONGS],
+ &mOptions[RSK_SHOPSANITY],
+ &mOptions[RSK_SHOPSANITY_COUNT],
+ &mOptions[RSK_SHOPSANITY_PRICES],
+ &mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
+ &mOptions[RSK_FISHSANITY],
+ &mOptions[RSK_FISHSANITY_POND_COUNT],
+ &mOptions[RSK_FISHSANITY_AGE_SPLIT],
+ &mOptions[RSK_SHUFFLE_SCRUBS],
+ &mOptions[RSK_SHUFFLE_BEEHIVES],
+ &mOptions[RSK_SHUFFLE_COWS],
+ &mOptions[RSK_SHUFFLE_POTS],
+ &mOptions[RSK_SHUFFLE_FREESTANDING],
+ &mOptions[RSK_SHUFFLE_MERCHANTS],
+ &mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES],
+ &mOptions[RSK_SHUFFLE_ADULT_TRADE],
+ &mOptions[RSK_SHUFFLE_100_GS_REWARD],
+ &mOptions[RSK_SHUFFLE_FAIRIES],
+ &mOptions[RSK_GOSSIP_STONE_HINTS],
+ };
}
RandomizerArea Context::GetAreaFromString(std::string str) {
@@ -94,7 +117,7 @@ void Context::PlaceItemInLocation(const RandomizerCheck locKey, const Randomizer
const auto loc = GetItemLocation(locKey);
SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetEnglish() + " placed at " + StaticData::GetLocation(locKey)->GetName() + "\n");
- if (applyEffectImmediately || mSettings->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS) || mSettings->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
+ if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) {
StaticData::RetrieveItem(item).ApplyEffect();
}
@@ -130,17 +153,17 @@ bool Context::IsQuestOfLocationActive(RandomizerCheck rc) {
void Context::GenerateLocationPool() {
allLocations.clear();
- if (mSettings->GetOption(RSK_TRIFORCE_HUNT)) {
+ if (mOptions[RSK_TRIFORCE_HUNT]) {
AddLocation(RC_TRIFORCE_COMPLETED);
}
AddLocations(StaticData::GetOverworldLocations());
- if (mSettings->GetOption(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF)) {
+ if (mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_OFF)) {
AddLocations(mFishsanity->GetFishsanityLocations().first);
}
- if (mSettings->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD) ||
- mSettings->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
+ if (mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OVERWORLD) ||
+ mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_ALL)) {
AddLocations(StaticData::GetOverworldPotLocations());
}
@@ -153,7 +176,17 @@ void Context::AddExcludedOptions() {
AddLocations(dungeon->GetEveryLocation(), &everyPossibleLocation);
}
for (const RandomizerCheck rc : everyPossibleLocation) {
- GetItemLocation(rc)->AddExcludeOption();
+ bool alreadyAdded = false;
+ Location* loc = StaticData::GetLocation(rc);
+ for (Option* location : Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc->GetArea()))
+ {
+ if (location->GetName() == loc->GetExcludedOption()->GetName()) {
+ alreadyAdded = true;
+ }
+ }
+ if (!alreadyAdded) {
+ Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc->GetArea()).push_back(loc->GetExcludedOption());
+ }
}
}
@@ -289,7 +322,7 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
nlohmann::json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
ParseHashIconIndexesJson(spoilerFileJson);
- mSettings->ParseJson(spoilerFileJson);
+ Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
ParseItemLocationsJson(spoilerFileJson);
ParseHintJson(spoilerFileJson);
mEntranceShuffler->ParseJson(spoilerFileJson);
@@ -362,10 +395,6 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
CreateStaticHints();
}
-std::shared_ptr Context::GetSettings() {
- return mSettings;
-}
-
std::shared_ptr Context::GetEntranceShuffler() {
return mEntranceShuffler;
}
@@ -405,12 +434,28 @@ Sprite* Context::GetSeedTexture(const uint8_t index) {
return &gSeedTextures[index];
}
-Option& Context::GetOption(const RandomizerSettingKey key) const {
- return mSettings->GetOption(key);
+OptionValue& Context::GetOption(const RandomizerSettingKey key) {
+ return mOptions[key];
}
-TrickOption& Context::GetTrickOption(const RandomizerTrick key) const {
- return mSettings->GetTrickOption(key);
+OptionValue& Context::GetOption(const RandomizerTrick key) {
+ return mTrickOptions[key];
+}
+
+OptionValue& Context::GetOption(const RandomizerCheck key) {
+ return itemLocationTable[key].GetExcludedOption();
+}
+
+OptionValue& Context::GetTrickOption(const RandomizerTrick key) {
+ return mTrickOptions[key];
+}
+
+OptionValue& Context::GetLocationOption(const RandomizerCheck key) {
+ return itemLocationTable[key].GetExcludedOption();
+}
+
+RandoOptionLACSCondition Context::LACSCondition() const {
+ return mLACSCondition;
}
std::shared_ptr Context::GetKaleido() {
@@ -419,4 +464,28 @@ std::shared_ptr Context::GetKaleido() {
}
return mKaleido;
}
+
+std::string Context::GetHash() const {
+ return mHash;
+}
+
+void Context::SetHash(std::string hash) {
+ mHash = std::move(hash);
+}
+
+const std::string& Context::GetSeedString() const {
+ return mSeedString;
+}
+
+void Context::SetSeedString(std::string seedString) {
+ mSeedString = std::move(seedString);
+}
+
+uint32_t Context::GetSeed() const {
+ return mFinalSeed;
+}
+
+void Context::SetSeed(const uint32_t seed) {
+ mFinalSeed = seed;
+}
} // namespace Rando
diff --git a/soh/soh/Enhancements/randomizer/context.h b/soh/soh/Enhancements/randomizer/context.h
index e2baf9559..0fbb18748 100644
--- a/soh/soh/Enhancements/randomizer/context.h
+++ b/soh/soh/Enhancements/randomizer/context.h
@@ -25,7 +25,6 @@
namespace Rando {
class EntranceShuffler;
class Logic;
-class Settings;
class Dungeons;
class DungeonInfo;
class TrialInfo;
@@ -63,7 +62,24 @@ class Context {
void SetSeedGenerated(bool seedGenerated = true);
bool IsSpoilerLoaded() const;
void SetSpoilerLoaded(bool spoilerLoaded = true);
- std::shared_ptr GetSettings();
+
+ /**
+ * @brief Reset all RandomizerTrick keys.
+ */
+ void ResetTrickOptions();
+
+ /**
+ * @brief Runs before seed generation to ensure all options are compatible with each
+ * other and resolve options that have been set to random (such as random trial count,
+ * or starting age).
+ *
+ * @param excludedLocations Set of locations that should be forced to have junk items.
+ * @param enabledTricks Set of tricks that should be considered logically possible. Tricks
+ * are things that are possible to do in gameplay but are difficult, not intuitive or that
+ * require more extensive game knowledge, i.e. opening invisible chests without the Lens of Truth.
+ */
+ void FinalizeSettings(const std::set& excludedLocations,
+ const std::set& enabledTricks);
std::shared_ptr GetEntranceShuffler();
std::shared_ptr GetDungeons();
std::shared_ptr GetFishsanity();
@@ -74,8 +90,19 @@ class Context {
TrialInfo* GetTrial(size_t key) const;
TrialInfo* GetTrial(TrialKey key) const;
static Sprite* GetSeedTexture(uint8_t index);
- Option& GetOption(RandomizerSettingKey key) const;
- TrickOption& GetTrickOption(RandomizerTrick key) const;
+ OptionValue& GetOption(RandomizerSettingKey key);
+ OptionValue& GetOption(RandomizerTrick key);
+ OptionValue& GetOption(RandomizerCheck key);
+ OptionValue& GetTrickOption(RandomizerTrick key);
+ OptionValue& GetLocationOption(RandomizerCheck key);
+
+ /**
+ * @brief Gets the resolved Light Arrow CutScene check condition.
+ * There is no direct option for this, it is inferred based on the value of a few other options.
+ *
+ * @return RandoOptionLACSCondition
+ */
+ RandoOptionLACSCondition LACSCondition() const;
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
void ParseSpoiler(const char* spoilerFileName);
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
@@ -87,16 +114,61 @@ class Context {
std::vector everyPossibleLocation = {};
std::vector possibleIceTrapModels = {};
std::unordered_map iceTrapModels = {};
+ std::vector VanillaLogicDefaults = {};
std::array hashIconIndexes = {};
bool playthroughBeatable = false;
bool allLocationsReachable = false;
RandomizerArea GetAreaFromString(std::string str);
+ /**
+ * @brief Get the hash for the current seed.
+ *
+ * @return std::string
+ */
+ std::string GetHash() const;
+
+ /**
+ * @brief Get the Seed String
+ *
+ * @return const std::string&
+ */
+ const std::string& GetSeedString() const;
+
+ /**
+ * @brief Set the Seed String
+ *
+ * @param seedString
+ */
+ void SetSeedString(std::string seedString);
+
+ /**
+ * @brief Get the Seed
+ *
+ * @return const uint32_t
+ */
+ uint32_t GetSeed() const;
+
+ /**
+ * @brief Set the Seed
+ *
+ * @param seed
+ */
+ void SetSeed(uint32_t seed);
+
+ /**
+ * @brief Set the Seed Hash for the current seed.
+ *
+ * @param hash
+ */
+ void SetHash(std::string hash);
+
private:
static std::weak_ptr mContext;
std::array hintTable = {};
std::array itemLocationTable = {};
- std::shared_ptr mSettings;
+ std::array mOptions;
+ std::array mTrickOptions;
+ RandoOptionLACSCondition mLACSCondition = RO_LACS_VANILLA;
std::shared_ptr mEntranceShuffler;
std::shared_ptr mDungeons;
std::shared_ptr mLogic;
@@ -105,5 +177,8 @@ class Context {
std::shared_ptr mKaleido;
bool mSeedGenerated = false;
bool mSpoilerLoaded = false;
+ std::string mHash;
+ std::string mSeedString;
+ uint32_t mFinalSeed = 0;
};
} // namespace Rando
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp
index c45719e95..0a89e4dae 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -38,32 +38,45 @@ extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
-const char* SmallBaseCvarValue[10] = {
- CVAR_COSMETIC("Key.ForestSmallBase.Value"),
- CVAR_COSMETIC("Key.FireSmallBase.Value"),
- CVAR_COSMETIC("Key.WaterSmallBase.Value"),
- CVAR_COSMETIC("Key.SpiritSmallBase.Value"),
- CVAR_COSMETIC("Key.ShadowSmallBase.Value"),
- CVAR_COSMETIC("Key.WellSmallBase.Value"),
- CVAR_COSMETIC("Key.GTGSmallBase.Value"),
- CVAR_COSMETIC("Key.FortSmallBase.Value"),
- CVAR_COSMETIC("Key.GanonsSmallBase.Value"),
- CVAR_COSMETIC("Key.ChestGameSmallBase.Value"),
+const char* SmallBodyCvarValue[10] = {
+ CVAR_COSMETIC("Key.ForestSmallBody.Value"),
+ CVAR_COSMETIC("Key.FireSmallBody.Value"),
+ CVAR_COSMETIC("Key.WaterSmallBody.Value"),
+ CVAR_COSMETIC("Key.SpiritSmallBody.Value"),
+ CVAR_COSMETIC("Key.ShadowSmallBody.Value"),
+ CVAR_COSMETIC("Key.WellSmallBody.Value"),
+ CVAR_COSMETIC("Key.GTGSmallBody.Value"),
+ CVAR_COSMETIC("Key.FortSmallBody.Value"),
+ CVAR_COSMETIC("Key.GanonsSmallBody.Value"),
+ CVAR_COSMETIC("Key.ChestGameSmallBody.Value"),
};
const char* SmallEmblemCvarValue[10] = {
- CVAR_COSMETIC("Key.ForestEmblem.Value"),
- CVAR_COSMETIC("Key.FireEmblem.Value"),
- CVAR_COSMETIC("Key.WaterEmblem.Value"),
- CVAR_COSMETIC("Key.SpiritEmblem.Value"),
- CVAR_COSMETIC("Key.ShadowEmblem.Value"),
- CVAR_COSMETIC("Key.WellEmblem.Value"),
- CVAR_COSMETIC("Key.GTGEmblem.Value"),
- CVAR_COSMETIC("Key.FortEmblem.Value"),
- CVAR_COSMETIC("Key.GanonsEmblem.Value"),
+ CVAR_COSMETIC("Key.ForestSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.FireSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.WaterSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.SpiritSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.ShadowSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.WellSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.GTGSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.FortSmallEmblem.Value"),
+ CVAR_COSMETIC("Key.GanonsSmallEmblem.Value"),
CVAR_COSMETIC("Key.ChestGameEmblem.Value"),
};
+Color_RGB8 SmallEmblemDefaultValue[10] = {
+ { 4, 195, 46 }, // Forest
+ { 237, 95, 95 }, // Fire
+ { 85, 180, 223 }, // Water
+ { 222, 158, 47 }, // Spirit
+ { 126, 16, 177 }, // Shadow
+ { 227, 110, 255 }, // Well
+ { 221, 212, 60 }, // GTG
+ { 255, 255, 255 }, // Fortress
+ { 80, 80, 80 }, // Ganons
+ { 255, 255, 255 }, // Chest Game
+};
+
extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry) {
@@ -91,7 +104,7 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
G_MTX_MODELVIEW | G_MTX_LOAD);
Color_RGB8 keyColor = { 255, 255, 255 };
- keyColor = CVarGetColor24(SmallBaseCvarValue[slot], keyColor);
+ keyColor = CVarGetColor24(SmallBodyCvarValue[slot], keyColor);
if (isCustomKeysEnabled) {
gDPSetEnvColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
@@ -99,7 +112,7 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
- Color_RGB8 emblemColor = { 255, 0, 0 };
+ Color_RGB8 emblemColor = SmallEmblemDefaultValue[slot];
emblemColor = CVarGetColor24(SmallEmblemCvarValue[slot], emblemColor);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
@@ -166,12 +179,12 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
s16 slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY;
std::string CvarValue[6] = {
- "gCosmetics.Key.Forest",
- "gCosmetics.Key.Fire",
- "gCosmetics.Key.Water",
- "gCosmetics.Key.Spirit",
- "gCosmetics.Key.Shadow",
- "gCosmetics.Key.Ganons",
+ "gCosmetics.Key.ForestBoss",
+ "gCosmetics.Key.FireBoss",
+ "gCosmetics.Key.WaterBoss",
+ "gCosmetics.Key.SpiritBoss",
+ "gCosmetics.Key.ShadowBoss",
+ "gCosmetics.Key.GanonsBoss",
};
Gfx* CustomdLists[] = {
@@ -192,13 +205,13 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
Color_RGB8 keyColor = { 255, 255, 0 };
//Supposed to use CVAR_COSMETIC but I can't figure out the syntax
- keyColor = CVarGetColor24((CvarValue[slot] + "BossBase.Value").c_str(), keyColor);
+ keyColor = CVarGetColor24((CvarValue[slot] + "Body.Value").c_str(), keyColor);
if (isCustomKeysEnabled){
gDPSetEnvColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gBossKeyCustomDL);
} else {
- if (CVarGetInteger((CvarValue[slot] + "BossBase.Changed").c_str(), false)){
+ if (CVarGetInteger((CvarValue[slot] + "Body.Changed").c_str(), false)){
gDPSetGrayscaleColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
gSPGrayscale(POLY_OPA_DISP++, true);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiBossKeyDL);
@@ -213,15 +226,15 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
- Color_RGB8 emblemColor = { 255, 0, 0 };
- emblemColor = CVarGetColor24((CvarValue[slot] + "Emblem.Value").c_str(), emblemColor);
+ Color_RGB8 gemColor = { 255, 0, 0 };
+ gemColor = CVarGetColor24((CvarValue[slot] + "Gem.Value").c_str(), gemColor);
if (isCustomKeysEnabled){
- gDPSetEnvColor(POLY_XLU_DISP++, emblemColor.r, emblemColor.g, emblemColor.b, 255);
+ gDPSetEnvColor(POLY_XLU_DISP++, gemColor.r, gemColor.g, gemColor.b, 255);
gSPDisplayList(POLY_XLU_DISP++, CustomdLists[slot]);
} else {
- if (CVarGetInteger((CvarValue[slot] + "Emblem.Changed").c_str(), false)){
- gDPSetGrayscaleColor(POLY_XLU_DISP++, emblemColor.r, emblemColor.g, emblemColor.b, 255);
+ if (CVarGetInteger((CvarValue[slot] + "Gem.Changed").c_str(), false)){
+ gDPSetGrayscaleColor(POLY_XLU_DISP++, gemColor.r, gemColor.g, gemColor.b, 255);
gSPGrayscale(POLY_XLU_DISP++, true);
gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBossKeyGemDL);
gSPGrayscale(POLY_XLU_DISP++, false);
@@ -296,7 +309,7 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
Gfx_SetupDL_25Opa(play->state.gfxCtx);
Color_RGB8 keyColor = { 255, 255, 255 };
- keyColor = CVarGetColor24(SmallBaseCvarValue[slot], keyColor);
+ keyColor = CVarGetColor24(SmallBodyCvarValue[slot], keyColor);
if (isCustomKeysEnabled) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
@@ -314,7 +327,7 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
gDPSetEnvColor(POLY_OPA_DISP++, ringColor.r, ringColor.g, ringColor.b, 255);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gKeyringRingDL);
- Color_RGB8 emblemColor = { 255, 0, 0 };
+ Color_RGB8 emblemColor = SmallEmblemDefaultValue[slot];
emblemColor = CVarGetColor24(SmallEmblemCvarValue[slot], emblemColor);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
@@ -933,7 +946,13 @@ extern "C" void DrawGanon(PlayState* play) {
}
extern "C" void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry) {
- s16 slot = getItemEntry->getItemId - RG_GOHMA_SOUL;
+ s16 slot;
+ if (getItemEntry->getItemId != RG_ICE_TRAP) {
+ slot = getItemEntry->getItemId - RG_GOHMA_SOUL;
+ } else {
+ slot = getItemEntry->drawItemId - RG_GOHMA_SOUL;
+ }
+
s16 flameColors[9][3] = {
{ 0, 255, 0 }, // Gohma
{ 255, 0, 100 }, // King Dodongo
@@ -1210,3 +1229,18 @@ extern "C" void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry*
CLOSE_DISPS(play->state.gfxCtx);
}
}
+
+extern "C" void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gHouseKeyDL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h
index 31ac2c1fb..3fc5c86b4 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -25,6 +25,7 @@ void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry);
+void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry);
#define GET_ITEM_MYSTERY \
{ ITEM_NONE_FE, 0, 0, 0, 0, MOD_RANDOMIZER, MOD_RANDOMIZER, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE_FE, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem }
diff --git a/soh/soh/Enhancements/randomizer/dungeon.cpp b/soh/soh/Enhancements/randomizer/dungeon.cpp
index 85afc0d3e..d83bc9251 100644
--- a/soh/soh/Enhancements/randomizer/dungeon.cpp
+++ b/soh/soh/Enhancements/randomizer/dungeon.cpp
@@ -148,8 +148,8 @@ void DungeonInfo::PlaceVanillaSmallKeys() const {
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
std::vector DungeonInfo::GetDungeonLocations() const {
auto locations = masterQuest ? mqLocations : vanillaLocations;
- if (Context::GetInstance()->GetSettings()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
- Context::GetInstance()->GetSettings()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
+ if (Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
+ Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
auto potLocations = masterQuest ? mqPots : vanillaPots;
AddElementsToPool(locations, potLocations);
}
diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp
index 910467e81..81afbf33c 100644
--- a/soh/soh/Enhancements/randomizer/entrance.cpp
+++ b/soh/soh/Enhancements/randomizer/entrance.cpp
@@ -20,15 +20,11 @@ void Entrance::SetCondition(ConditionFn newCondition) {
}
bool Entrance::GetConditionsMet() const {
- auto ctx = Rando::Context::GetInstance();
- if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
- return true;
- } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
- return condition_function();
- } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
- return condition_function();
- }
- return false;
+ auto ctx = Rando::Context::GetInstance();
+ if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
+ return condition_function();
+ }
+ return true;
}
std::string Entrance::to_string() const {
@@ -1322,12 +1318,12 @@ int EntranceShuffler::ShuffleAllEntrances() {
(ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES) ? 1 : 0) +
(ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES) ? 1 : 0);
if (totalMixedPools < 2) {
- ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).SetContextIndex(RO_GENERIC_OFF);
- ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
- ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
- ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
- ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
- ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
+ ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).Set(RO_GENERIC_OFF);
+ ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).Set(RO_GENERIC_OFF);
+ ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).Set(RO_GENERIC_OFF);
+ ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).Set(RO_GENERIC_OFF);
+ ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).Set(RO_GENERIC_OFF);
+ ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).Set(RO_GENERIC_OFF);
}
if (ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS)) {
std::set poolsToMix = {};
diff --git a/soh/soh/Enhancements/randomizer/fishsanity.cpp b/soh/soh/Enhancements/randomizer/fishsanity.cpp
index 71c18727c..2769faf31 100644
--- a/soh/soh/Enhancements/randomizer/fishsanity.cpp
+++ b/soh/soh/Enhancements/randomizer/fishsanity.cpp
@@ -17,7 +17,7 @@ extern PlayState* gPlayState;
#define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity()
-#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
+#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
/**
* @brief Parallel list of pond fish checks for both ages
diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp
index e248eebe0..29a9a969f 100644
--- a/soh/soh/Enhancements/randomizer/hint.cpp
+++ b/soh/soh/Enhancements/randomizer/hint.cpp
@@ -559,23 +559,23 @@ CustomMessage Hint::GetBridgeReqsText() {
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_STONES_HINT].GetHintMessage();
- bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex());
+ bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT].GetHintMessage();
- bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex());
+ bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_REWARDS_HINT].GetHintMessage();
- bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex());
+ bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_DUNGEONS_HINT].GetHintMessage();
- bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex());
+ bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_TOKENS_HINT].GetHintMessage();
- bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex());
+ bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) {
return StaticData::hintTextTable[RHT_BRIDGE_GREG_HINT].GetHintMessage();
@@ -613,23 +613,23 @@ CustomMessage Hint::GetGanonBossKeyText() {
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_STONES_HINT].GetHintMessage();
- ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex());
+ ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_MEDALLIONS_HINT].GetHintMessage();
- ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex());
+ ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_REWARDS_HINT].GetHintMessage();
- ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex());
+ ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_DUNGEONS_HINT].GetHintMessage();
- ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex());
+ ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_TOKENS_HINT].GetHintMessage();
- ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex());
+ ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage();
diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
index d1ba2f9ea..cc9708789 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -69,7 +69,7 @@ extern void EnMk_Wait(EnMk* enMk, PlayState* play);
extern void func_80ABA778(EnNiwLady* enNiwLady, PlayState* play);
}
-#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
+#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
bool LocMatchesQuest(Rando::Location loc) {
if (loc.GetQuest() == RCQUEST_BOTH) {
@@ -273,7 +273,9 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() {
RandomizerCheck rc = randomizerQueuedChecks.front();
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
- GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem());
+ RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem();
+ GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID();
+ GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet);
if (loc->HasObtained()) {
SPDLOG_INFO("RC {} already obtained, skipping", static_cast(rc));
@@ -645,7 +647,7 @@ void RandomizerOnDialogMessageHandler() {
MessageContext *msgCtx = &gPlayState->msgCtx;
Actor *actor = msgCtx->talkActor;
auto ctx = Rando::Context::GetInstance();
- bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF;
+ bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).Get() != RO_GENERIC_OFF;
bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) ||
ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL);
@@ -714,7 +716,7 @@ void RandomizerOnDialogMessageHandler() {
}
break;
case TEXT_SCRUB_RANDOM:
- if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF) {
+ if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).Get() != RO_GENERIC_OFF) {
EnDns* enDns = (EnDns*)actor;
reveal = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf);
}
@@ -2370,6 +2372,8 @@ void RandomizerRegisterHooks() {
static uint32_t shuffleFreestandingOnVanillaBehaviorHook = 0;
GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) {
+ ShipInit::Init("IS_RANDO");
+
randomizerQueuedChecks = std::queue();
randomizerQueuedCheck = RC_UNKNOWN_CHECK;
randomizerQueuedItemEntry = GET_ITEM_NONE;
diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp
index c802747ec..6f0309223 100644
--- a/soh/soh/Enhancements/randomizer/item.cpp
+++ b/soh/soh/Enhancements/randomizer/item.cpp
@@ -383,7 +383,7 @@ bool Item::IsBottleItem() const {
bool Item::IsMajorItem() const {
const auto ctx = Context::GetInstance();
if (type == ITEMTYPE_TOKEN) {
- return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS;
+ return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->LACSCondition() == RO_LACS_TOKENS;
}
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP ||
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 6aee0a775..0b94aab39 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -159,6 +159,54 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE);
+ itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_GUARD_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MARKET_BAZAAR_KEY] = Item(RG_MARKET_BAZAAR_KEY, Text{ "Market Bazaar Key", "", "Schlüssel für den Basar des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_MARKET_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MARKET_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MARKET_POTION_SHOP_KEY] = Item(RG_MARKET_POTION_SHOP_KEY, Text{ "Market Potion Shop Key", "", "Schlüssel für den Magie-Laden des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MARKET_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MARKET_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MASK_SHOP_KEY] = Item(RG_MASK_SHOP_KEY, Text{ "Mask Shop Key", "", "Schlüssel für den Maskenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MASK_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MASK_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MASK_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MARKET_SHOOTING_GALLERY_KEY] = Item(RG_MARKET_SHOOTING_GALLERY_KEY, Text{ "Market Shooting Gallery Key", "", "Schlüssel für die Schießbude des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_MARKET_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MARKET_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BOMBCHU_BOWLING_KEY] = Item(RG_BOMBCHU_BOWLING_KEY, Text{ "Bombchu Bowling Alley Key", "", "Schlüssel für die Minenbowlingbahn" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_BOWLING_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_BOWLING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BOMBCHU_BOWLING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = Item(RG_TREASURE_CHEST_GAME_BUILDING_KEY, Text{ "Treasure Chest Game Building Key", "", "Schlüssel für das Haus des Schatzkisten-Pokers" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,RHT_OVERWORLD_KEY, RG_TREASURE_CHEST_GAME_BUILDING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BOMBCHU_SHOP_KEY] = Item(RG_BOMBCHU_SHOP_KEY, Text{ "Bombchu Shop Key", "", "Schlüssel für den Krabbelminenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_SHOP_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BOMBCHU_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_RICHARDS_HOUSE_KEY] = Item(RG_RICHARDS_HOUSE_KEY, Text{ "Richard's House Key", "", "Schlüssel für das Haus von Richard" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_RICHARDS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_RICHARDS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_RICHARDS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_ALLEY_HOUSE_KEY] = Item(RG_ALLEY_HOUSE_KEY, Text{ "Alley House Key", "", "Schlüssel für das Gäßchenhaus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_ALLEY_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_ALLEY_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_ALLEY_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_KAK_BAZAAR_KEY] = Item(RG_KAK_BAZAAR_KEY, Text{ "Kakariko Bazaar Key", "", "Schlüssel für den Basar von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_KAK_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_KAK_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_KAK_POTION_SHOP_KEY] = Item(RG_KAK_POTION_SHOP_KEY, Text{ "Kakariko Potion Shop Key", "", "Schlüssel für den Magie-Laden von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_KAK_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_KAK_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BOSS_HOUSE_KEY] = Item(RG_BOSS_HOUSE_KEY, Text{ "Boss's House Key", "", "Schlüssel für das Haus des Chefs" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOSS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_BOSS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BOSS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_GRANNYS_POTION_SHOP_KEY] = Item(RG_GRANNYS_POTION_SHOP_KEY, Text{ "Granny's Potion Shop Key", "", "Schlüssel für Asas Hexenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GRANNYS_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_GRANNYS_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_GRANNYS_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_SKULLTULA_HOUSE_KEY] = Item(RG_SKULLTULA_HOUSE_KEY, Text{ "Skulltula House Key", "", "Schlüssel für das Skulltula-Haus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_SKULLTULA_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_SKULLTULA_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_SKULLTULA_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_IMPAS_HOUSE_KEY] = Item(RG_IMPAS_HOUSE_KEY, Text{ "Impa's House Key", "", "Schlüssel für das Haus von Impa" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_IMPAS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_IMPAS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_IMPAS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_WINDMILL_KEY] = Item(RG_WINDMILL_KEY, Text{ "Windmill Key", "", "Schlüssel für die Windmühle" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_WINDMILL_KEY, RHT_OVERWORLD_KEY, RG_WINDMILL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_WINDMILL_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_KAK_SHOOTING_GALLERY_KEY] = Item(RG_KAK_SHOOTING_GALLERY_KEY, Text{ "Kakariko Shooting Gallery Key", "", "Schlüssel für die Schießbude von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_KAK_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_KAK_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_DAMPES_HUT_KEY] = Item(RG_DAMPES_HUT_KEY, Text{ "Dampe's Hut Key", "", "Schlüssel für die Hütte von Boris" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_DAMPES_HUT_KEY, RHT_OVERWORLD_KEY, RG_DAMPES_HUT_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_DAMPES_HUT_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_TALONS_HOUSE_KEY] = Item(RG_TALONS_HOUSE_KEY, Text{ "Talon's House Key", "", "Schlüssel für das Haus von Talon" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TALONS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_TALONS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_TALONS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_STABLES_KEY] = Item(RG_STABLES_KEY, Text{ "Stables Key", "", "Schlüssel für die Ställe" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_STABLES_KEY, RHT_OVERWORLD_KEY, RG_STABLES_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_STABLES_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BACK_TOWER_KEY] = Item(RG_BACK_TOWER_KEY, Text{ "Back Tower Key", "", "Schlüssel für den hinteren Turm" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BACK_TOWER_KEY, RHT_OVERWORLD_KEY, RG_BACK_TOWER_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BACK_TOWER_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_HYLIA_LAB_KEY] = Item(RG_HYLIA_LAB_KEY, Text{ "Hylia Laboratory Key", "", "Schlüssel für das Hylia-Labor" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_HYLIA_LAB_KEY, RHT_OVERWORLD_KEY, RG_HYLIA_LAB_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_HYLIA_LAB_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
// Key Rings
itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp
index 47c1f09f1..00e0366ab 100644
--- a/soh/soh/Enhancements/randomizer/item_location.cpp
+++ b/soh/soh/Enhancements/randomizer/item_location.cpp
@@ -178,34 +178,15 @@ void ItemLocation::SetHidden(const bool hidden_) {
}
bool ItemLocation::IsExcluded() {
- return excludedOption.GetContextOptionIndex();
+ return excludedOption.Is(RO_LOCATION_EXCLUDE);
}
-Option* ItemLocation::GetExcludedOption() {
- return &excludedOption;
+OptionValue& ItemLocation::GetExcludedOption() {
+ return excludedOption;
}
-void ItemLocation::AddExcludeOption() {
- if (const std::string name = StaticData::GetLocation(rc)->GetName(); name.length() < 23) {
- excludedOption = Option::Bool(name, {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
- } else {
- const size_t lastSpace = name.rfind(' ', 23);
- std::string settingText = name;
- settingText.replace(lastSpace, 1, "\n ");
-
- excludedOption = Option::Bool(settingText, {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
- }
- // RANDOTODO: this without string compares and loops
- bool alreadyAdded = false;
- const Location* loc = StaticData::GetLocation(rc);
- for (Option* location : Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea())) {
- if (location->GetName() == excludedOption.GetName()) {
- alreadyAdded = true;
- }
- }
- if (!alreadyAdded) {
- Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea()).push_back(&excludedOption);
- }
+void ItemLocation::SetExcludedOption(uint8_t val) {
+ excludedOption.Set(val);
}
bool ItemLocation::IsVisible() const {
diff --git a/soh/soh/Enhancements/randomizer/item_location.h b/soh/soh/Enhancements/randomizer/item_location.h
index 4ec8b8b9e..142ac1c0b 100644
--- a/soh/soh/Enhancements/randomizer/item_location.h
+++ b/soh/soh/Enhancements/randomizer/item_location.h
@@ -3,7 +3,7 @@
#include "randomizerTypes.h"
#include "3drando/text.hpp"
#include "static_data.h"
-#include "settings.h"
+#include "option.h"
namespace Rando {
class ItemLocation {
@@ -46,8 +46,8 @@ class ItemLocation {
void AddHintedBy(RandomizerHint hintKey);
bool IsHidden() const;
bool IsExcluded();
- void AddExcludeOption();
- Option* GetExcludedOption();
+ OptionValue& GetExcludedOption();
+ void SetExcludedOption(uint8_t val);
void SetHidden(bool hidden_);
bool IsVisible() const;
void SetVisible(bool visibleInImGui_);
@@ -65,7 +65,7 @@ class ItemLocation {
bool addedToPool = false;
RandomizerGet placedItem = RG_NONE;
RandomizerGet delayedItem = RG_NONE;
- Option excludedOption = Option::Bool(StaticData::GetLocation(rc)->GetName(), {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
+ OptionValue excludedOption = OptionValue(RO_LOCATION_INCLUDE);
uint16_t price = 0;
RandomizerRegion parentRegion = RR_NONE;
std::set areas = {};
diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp
index 20dc211a8..f5c78884b 100644
--- a/soh/soh/Enhancements/randomizer/location.cpp
+++ b/soh/soh/Enhancements/randomizer/location.cpp
@@ -2,6 +2,7 @@
#include "static_data.h"
#include
#include
+#include "option.h"
RandomizerCheck Rando::Location::GetRandomizerCheck() const {
return rc;
@@ -86,6 +87,10 @@ int16_t Rando::Location::GetVanillaPrice() const {
return vanillaPrice;
}
+Rando::Option* Rando::Location::GetExcludedOption() {
+ return &excludedOption;
+}
+
RandomizerCheckArea GetAreaFromScene(uint8_t scene) {
switch (scene) {
case SCENE_LINKS_HOUSE:
diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h
index 9de741dbf..bd96c3ae1 100644
--- a/soh/soh/Enhancements/randomizer/location.h
+++ b/soh/soh/Enhancements/randomizer/location.h
@@ -10,6 +10,7 @@
#include "z64actor_enum.h"
#include "z64scene.h"
#include "../../util.h"
+#include "option.h"
namespace Rando {
class SpoilerCollectionCheck {
@@ -59,7 +60,17 @@ class Location {
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), actorId(actorId_),
scene(scene_), actorParams(actorParams_), shortName(std::move(shortName_)),
spoilerName(std::move(spoilerName_)), hintKey(hintKey_), vanillaItem(vanillaItem_),
- isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {}
+ isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {
+ if (spoilerName.length() < 23) {
+ excludedOption = LocationOption(rc, spoilerName);
+ } else {
+ const size_t lastSpace = spoilerName.rfind(' ', 23);
+ std::string settingText = spoilerName;
+ settingText.replace(lastSpace, 1, "\n ");
+
+ excludedOption = LocationOption(rc, spoilerName);
+ }
+ }
Location(const RandomizerCheck rc_, const RandomizerCheckQuest quest_, const RandomizerCheckType checkType_, const RandomizerCheckArea area_, const ActorID actorId_,
const SceneID scene_, const int32_t actorParams_, std::string shortName_, const RandomizerHintTextKey hintKey_, const RandomizerGet vanillaItem_,
@@ -67,7 +78,17 @@ class Location {
const int vanillaPrice_ = 0)
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), actorId(actorId_), scene(scene_), actorParams(actorParams_), shortName(shortName_),
spoilerName(SpoilerNameFromShortName(shortName_, area_)), hintKey(hintKey_), vanillaItem(vanillaItem_), isVanillaCompletion(isVanillaCompletion_),
- collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {}
+ collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {
+ if (spoilerName.length() < 23) {
+ excludedOption = LocationOption(rc, spoilerName);
+ } else {
+ const size_t lastSpace = spoilerName.rfind(' ', 23);
+ std::string settingText = spoilerName;
+ settingText.replace(lastSpace, 1, "\n ");
+
+ excludedOption = LocationOption(rc, spoilerName);
+ }
+ }
static std::string SpoilerNameFromShortName(std::string shortName, RandomizerCheckArea area) {
if (area < 0 || area >= RCAREA_INVALID) {
@@ -96,10 +117,13 @@ class Location {
const HintText& GetHint() const;
RandomizerGet GetVanillaItem() const;
int16_t GetVanillaPrice() const;
+ Option* GetExcludedOption();
- static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
- std::string&& shortName_, std::string&& spoilerName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
- SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), bool isVanillaCompletion_ = false, uint16_t vanillaPrice_ = 0);
+ static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
+ ActorID actorId_, SceneID scene_, int32_t actorParams_, std::string&& shortName_,
+ std::string&& spoilerName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
+ SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
+ bool isVanillaCompletion_ = false, uint16_t vanillaPrice_ = 0);
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
@@ -205,5 +229,6 @@ class Location {
SpoilerCollectionCheck collectionCheck;
int16_t vanillaPrice;
bool isHintable = false;
+ Option excludedOption;
};
} // namespace Rando
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp
index 64f0b23d5..a45e27cd0 100644
--- a/soh/soh/Enhancements/randomizer/location_access.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access.cpp
@@ -267,7 +267,7 @@ void RegionTable_Init() {
}, {
//Locations
LOCATION(RC_LINKS_POCKET, true),
- LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1;),
+ LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1;),
LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)),
}, {
//Exits
@@ -409,7 +409,7 @@ void ReplaceAllInString(std::string& s, std::string const& toReplace, std::strin
std::string CleanCheckConditionString(std::string condition) {
ReplaceAllInString(condition, "logic->", "");
ReplaceAllInString(condition, "ctx->", "");
- ReplaceAllInString(condition, ".GetContextOptionIndex()", "");
+ ReplaceAllInString(condition, ".Get()", "");
ReplaceAllInString(condition, "GetSaveContext()->", "");
return condition;
}
diff --git a/soh/soh/Enhancements/randomizer/location_access.h b/soh/soh/Enhancements/randomizer/location_access.h
index 3af0a498d..986d08d6a 100644
--- a/soh/soh/Enhancements/randomizer/location_access.h
+++ b/soh/soh/Enhancements/randomizer/location_access.h
@@ -23,14 +23,10 @@ class EventAccess {
bool ConditionsMet() const {
auto ctx = Rando::Context::GetInstance();
- if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
- return true;
- } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
- return condition_function();
- } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
+ if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
return condition_function();
}
- return false;
+ return true;
}
bool CheckConditionAtAgeTime(bool& age, bool& time) {
@@ -71,14 +67,10 @@ class LocationAccess {
bool GetConditionsMet() const {
auto ctx = Rando::Context::GetInstance();
- if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
- return true;
- } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
- return condition_function();
- } else if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHED)) {
+ if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS)) {
return condition_function();
}
- return false;
+ return true;
}
bool CheckConditionAtAgeTime(bool& age, bool& time) const;
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp
index d67086371..bd0362598 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp
@@ -71,6 +71,7 @@ void RegionTable_Init_DeathMountainTrail() {
LOCATION(RC_DMT_COW_GROTTO_RUPEE_5, true),
LOCATION(RC_DMT_COW_GROTTO_RUPEE_6, true),
LOCATION(RC_DMT_COW_GROTTO_RED_RUPEE, true),
+ LOCATION(RC_DMT_COW_GROTTO_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)),
}, {
//Exits
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, []{return true;}),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
index d6ded1312..727431b1f 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
@@ -24,7 +24,7 @@ void RegionTable_Init_Graveyard() {
Entrance(RR_GRAVEYARD_COMPOSERS_GRAVE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
Entrance(RR_GRAVEYARD_HEART_PIECE_GRAVE, []{return logic->IsAdult || logic->AtNight;}),
Entrance(RR_GRAVEYARD_DAMPES_GRAVE, []{return logic->IsAdult;}),
- Entrance(RR_GRAVEYARD_DAMPES_HOUSE, []{return logic->IsAdult /*|| logic->AtDampeTime*/;}), //TODO: This needs to be handled in ToD rework
+ Entrance(RR_GRAVEYARD_DAMPES_HOUSE, []{return logic->IsAdult && logic->CanOpenOverworldDoor(RG_DAMPES_HUT_KEY) /*|| logic->AtDampeTime*/;}), //TODO: This needs to be handled in ToD rework
Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, []{return false;}),
});
@@ -63,8 +63,9 @@ void RegionTable_Init_Graveyard() {
areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Region("Graveyard Composers Grave", "Graveyard Composers Grave", {}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()),
- LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()),
+ LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()),
+ LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()),
+ LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
//Exits
Entrance(RR_THE_GRAVEYARD, []{return true;}),
@@ -103,7 +104,7 @@ void RegionTable_Init_Graveyard() {
LOCATION(RC_DAMPE_HINT, logic->IsAdult),
}, {
//Exits
- Entrance(RR_THE_GRAVEYARD, []{return true;}),
+ Entrance(RR_THE_GRAVEYARD, []{return logic->CanOpenOverworldDoor(RG_DAMPES_HUT_KEY);}),
});
areaTable[RR_GRAVEYARD_WARP_PAD_REGION] = Region("Graveyard Warp Pad Region", "Graveyard", {RA_THE_GRAVEYARD}, NO_DAY_NIGHT_CYCLE, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
index 7d22f30a0..8fe55c45f 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
@@ -33,14 +33,14 @@ void RegionTable_Init_Kakariko() {
}, {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
- Entrance(RR_KAK_CARPENTER_BOSS_HOUSE, []{return true;}),
- Entrance(RR_KAK_HOUSE_OF_SKULLTULA, []{return true;}),
- Entrance(RR_KAK_IMPAS_HOUSE, []{return true;}),
- Entrance(RR_KAK_WINDMILL, []{return true;}),
- Entrance(RR_KAK_BAZAAR, []{return logic->IsAdult && logic->AtDay;}),
- Entrance(RR_KAK_SHOOTING_GALLERY, []{return logic->IsAdult && logic->AtDay;}),
+ Entrance(RR_KAK_CARPENTER_BOSS_HOUSE, []{return logic->CanOpenOverworldDoor(RG_BOSS_HOUSE_KEY);}),
+ Entrance(RR_KAK_HOUSE_OF_SKULLTULA, []{return logic->CanOpenOverworldDoor(RG_SKULLTULA_HOUSE_KEY);}),
+ Entrance(RR_KAK_IMPAS_HOUSE, []{return logic->CanOpenOverworldDoor(RG_IMPAS_HOUSE_KEY);}),
+ Entrance(RR_KAK_WINDMILL, []{return logic->CanOpenOverworldDoor(RG_WINDMILL_KEY);}),
+ Entrance(RR_KAK_BAZAAR, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_BAZAAR_KEY);}),
+ Entrance(RR_KAK_SHOOTING_GALLERY, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_SHOOTING_GALLERY_KEY);}),
Entrance(RR_KAK_WELL, []{return logic->IsAdult || logic->DrainWell || logic->CanUse(RG_IRON_BOOTS);}),
- Entrance(RR_KAK_POTION_SHOP_FRONT, []{return logic->AtDay || logic->IsChild;}),
+ Entrance(RR_KAK_POTION_SHOP_FRONT, []{return (logic->AtDay || logic->IsChild) && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
Entrance(RR_KAK_REDEAD_GROTTO, []{return logic->CanOpenBombGrotto();}),
Entrance(RR_KAK_IMPAS_LEDGE, []{return (logic->IsChild && logic->AtDay) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION));}),
Entrance(RR_KAK_WATCHTOWER, []{return logic->IsAdult || logic->AtDay || logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer());}),
@@ -95,8 +95,8 @@ void RegionTable_Init_Kakariko() {
//Exits
Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
Entrance(RR_KAK_OPEN_GROTTO, []{return true;}),
- Entrance(RR_KAK_ODD_POTION_BUILDING, []{return logic->IsAdult;}),
- Entrance(RR_KAK_POTION_SHOP_BACK, []{return logic->IsAdult && logic->AtDay;}),
+ Entrance(RR_KAK_ODD_POTION_BUILDING, []{return logic->IsAdult && logic->CanOpenOverworldDoor(RG_GRANNYS_POTION_SHOP_KEY);}),
+ Entrance(RR_KAK_POTION_SHOP_BACK, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
});
areaTable[RR_KAK_CARPENTER_BOSS_HOUSE] = Region("Kak Carpenter Boss House", "Kak Carpenter Boss House", {}, NO_DAY_NIGHT_CYCLE, {
@@ -104,7 +104,7 @@ void RegionTable_Init_Kakariko() {
EventAccess(&logic->WakeUpAdultTalon, []{return logic->IsAdult && logic->CanUse(RG_POCKET_EGG);}),
}, {}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_BOSS_HOUSE_KEY);}),
});
areaTable[RR_KAK_HOUSE_OF_SKULLTULA] = Region("Kak House of Skulltula", "Kak House of Skulltula", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -117,7 +117,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_100_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 100),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_SKULLTULA_HOUSE_KEY);}),
});
areaTable[RR_KAK_IMPAS_HOUSE] = Region("Kak Impas House", "Kak Impas House", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -125,7 +125,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_IMPAS_HOUSE_COW, logic->CanUse(RG_EPONAS_SONG)),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_IMPAS_HOUSE_KEY);}),
});
areaTable[RR_KAK_IMPAS_HOUSE_BACK] = Region("Kak Impas House Back", "Kak Impas House", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -146,7 +146,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_SONG_FROM_WINDMILL, logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA)),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_WINDMILL_KEY);}),
});
areaTable[RR_KAK_BAZAAR] = Region("Kak Bazaar", "Kak Bazaar", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -169,7 +169,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_SHOOTING_GALLERY_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_KAK_SHOOTING_GALLERY_KEY);}),
});
areaTable[RR_KAK_POTION_SHOP_FRONT] = Region("Kak Potion Shop Front", "Kak Potion Shop", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -203,7 +203,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && (logic->CanUse(RG_ODD_MUSHROOM) || logic->TradeQuestStep(RG_ODD_MUSHROOM))),
}, {
// Exits
- Entrance(RR_KAK_BACKYARD, []{return true;}),
+ Entrance(RR_KAK_BACKYARD, []{return logic->CanOpenOverworldDoor(RG_GRANNYS_POTION_SHOP_KEY);}),
});
areaTable[RR_KAK_REDEAD_GROTTO] = Region("Kak Redead Grotto", "Kak Redead Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
index 148acad13..8833441e9 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
@@ -44,7 +44,7 @@ void RegionTable_Init_LakeHylia() {
Entrance(RR_ZORAS_DOMAIN, []{return logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS));}),
Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild;}),
Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->WaterTempleClear) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA)));}),
- Entrance(RR_LH_LAB, []{return true;}),
+ Entrance(RR_LH_LAB, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}),
Entrance(RR_WATER_TEMPLE_ENTRYWAY, []{return logic->CanUse(RG_HOOKSHOT) && ((logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LH_WATER_HOOKSHOT) && logic->HasItem(RG_GOLDEN_SCALE))) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_GOLDEN_SCALE)));}),
Entrance(RR_LH_GROTTO, []{return true;}),
});
@@ -52,7 +52,7 @@ void RegionTable_Init_LakeHylia() {
areaTable[RR_LH_FISHING_ISLAND] = Region("LH Fishing Island", "Lake Hylia", {RA_LAKE_HYLIA}, DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_LAKE_HYLIA, []{return logic->HasItem(RG_BRONZE_SCALE);}),
- Entrance(RR_LH_FISHING_POND, []{return true;}),
+ Entrance(RR_LH_FISHING_POND, []{return logic->CanOpenOverworldDoor(RG_FISHING_HOLE_KEY);}),
});
areaTable[RR_LH_OWL_FLIGHT] = Region("LH Owl Flight", "Lake Hylia", {RA_LAKE_HYLIA}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@@ -70,7 +70,7 @@ void RegionTable_Init_LakeHylia() {
LOCATION(RC_LH_LAB_RIGHT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)),
}, {
//Exits
- Entrance(RR_LAKE_HYLIA, []{return true;}),
+ Entrance(RR_LAKE_HYLIA, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}),
});
// TODO: should some of these helpers be done via events instead?
@@ -115,7 +115,7 @@ void RegionTable_Init_LakeHylia() {
LOCATION(RC_FISHING_POLE_HINT, true),
}, {
//Exits
- Entrance(RR_LH_FISHING_ISLAND, []{return true;}),
+ Entrance(RR_LH_FISHING_ISLAND, []{return logic->CanOpenOverworldDoor(RG_FISHING_HOLE_KEY);}),
});
areaTable[RR_LH_GROTTO] = Region("LH Grotto", "LH Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
index df73b78d9..fa1d7451e 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
@@ -25,9 +25,9 @@ void RegionTable_Init_LonLonRanch() {
}, {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
- Entrance(RR_LLR_TALONS_HOUSE, []{return true;}),
- Entrance(RR_LLR_STABLES, []{return true;}),
- Entrance(RR_LLR_TOWER, []{return true;}),
+ Entrance(RR_LLR_TALONS_HOUSE, []{return logic->CanOpenOverworldDoor(RG_TALONS_HOUSE_KEY);}),
+ Entrance(RR_LLR_STABLES, []{return logic->CanOpenOverworldDoor(RG_STABLES_KEY);}),
+ Entrance(RR_LLR_TOWER, []{return logic->CanOpenOverworldDoor(RG_BACK_TOWER_KEY);}),
Entrance(RR_LLR_GROTTO, []{return logic->IsChild;}),
});
@@ -39,7 +39,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_TALONS_HOUSE_POT_3, logic->CanBreakPots()),
}, {
//Exits
- Entrance(RR_LON_LON_RANCH, []{return true;}),
+ Entrance(RR_LON_LON_RANCH, []{return logic->CanOpenOverworldDoor(RG_TALONS_HOUSE_KEY);}),
});
areaTable[RR_LLR_STABLES] = Region("LLR Stables", "LLR Stables", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -48,7 +48,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_STABLES_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)),
}, {
//Exits
- Entrance(RR_LON_LON_RANCH, []{return true;}),
+ Entrance(RR_LON_LON_RANCH, []{return logic->CanOpenOverworldDoor(RG_STABLES_KEY);}),
});
areaTable[RR_LLR_TOWER] = Region("LLR Tower", "LLR Tower", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -58,7 +58,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_TOWER_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)),
}, {
//Exits
- Entrance(RR_LON_LON_RANCH, []{return true;}),
+ Entrance(RR_LON_LON_RANCH, []{return logic->CanOpenOverworldDoor(RG_BACK_TOWER_KEY);}),
});
areaTable[RR_LLR_GROTTO] = Region("LLR Grotto", "LLR Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
index 6d38b05bd..17aaff639 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
@@ -105,9 +105,10 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_LW_SCRUBS_GROTTO] = Region("LW Scrubs Grotto", "LW Scrubs Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku()),
- LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
- LOCATION(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
//Exits
Entrance(RR_LW_BEYOND_MIDO, []{return true;}),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
index 384485730..e0ef67aa5 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
@@ -8,7 +8,7 @@ void RegionTable_Init_Market() {
//Exits
Entrance(RR_HYRULE_FIELD, []{return logic->IsAdult || logic->AtDay;}),
Entrance(RR_THE_MARKET, []{return true;}),
- Entrance(RR_MARKET_GUARD_HOUSE, []{return true;}),
+ Entrance(RR_MARKET_GUARD_HOUSE, []{return logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
});
areaTable[RR_THE_MARKET] = Region("Market", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@@ -16,21 +16,21 @@ void RegionTable_Init_Market() {
Entrance(RR_MARKET_ENTRANCE, []{return true;}),
Entrance(RR_TOT_ENTRANCE, []{return true;}),
Entrance(RR_CASTLE_GROUNDS, []{return true;}),
- Entrance(RR_MARKET_BAZAAR, []{return logic->IsChild && logic->AtDay;}),
- Entrance(RR_MARKET_MASK_SHOP, []{return logic->IsChild && logic->AtDay;}),
- Entrance(RR_MARKET_SHOOTING_GALLERY, []{return logic->IsChild && logic->AtDay;}),
- Entrance(RR_MARKET_BOMBCHU_BOWLING, []{return logic->IsChild;}),
- Entrance(RR_MARKET_TREASURE_CHEST_GAME, []{return logic->IsChild && logic->AtNight;}),
- Entrance(RR_MARKET_POTION_SHOP, []{return logic->IsChild && logic->AtDay;}),
+ Entrance(RR_MARKET_BAZAAR, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MARKET_BAZAAR_KEY);}),
+ Entrance(RR_MARKET_MASK_SHOP, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MASK_SHOP_KEY);}),
+ Entrance(RR_MARKET_SHOOTING_GALLERY, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MARKET_SHOOTING_GALLERY_KEY);}),
+ Entrance(RR_MARKET_BOMBCHU_BOWLING, []{return logic->IsChild && logic->CanOpenOverworldDoor(RG_BOMBCHU_BOWLING_KEY);}),
+ Entrance(RR_MARKET_TREASURE_CHEST_GAME, []{return logic->IsChild && logic->AtNight && logic->CanOpenOverworldDoor(RG_TREASURE_CHEST_GAME_BUILDING_KEY);}),
+ Entrance(RR_MARKET_POTION_SHOP, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MARKET_POTION_SHOP_KEY);}),
Entrance(RR_MARKET_BACK_ALLEY, []{return logic->IsChild;}),
});
areaTable[RR_MARKET_BACK_ALLEY] = Region("Market Back Alley", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_THE_MARKET, []{return true;}),
- Entrance(RR_MARKET_BOMBCHU_SHOP, []{return logic->AtNight;}),
- Entrance(RR_MARKET_DOG_LADY_HOUSE, []{return true;}),
- Entrance(RR_MARKET_MAN_IN_GREEN_HOUSE, []{return logic->AtNight;}),
+ Entrance(RR_MARKET_BOMBCHU_SHOP, []{return logic->AtNight && logic->CanOpenOverworldDoor(RG_BOMBCHU_SHOP_KEY);}),
+ Entrance(RR_MARKET_DOG_LADY_HOUSE, []{return logic->CanOpenOverworldDoor(RG_RICHARDS_HOUSE_KEY);}),
+ Entrance(RR_MARKET_MAN_IN_GREEN_HOUSE, []{return logic->AtNight && logic->CanOpenOverworldDoor(RG_ALLEY_HOUSE_KEY);}),
});
areaTable[RR_MARKET_GUARD_HOUSE] = Region("Market Guard House", "Market Guard House", {}, NO_DAY_NIGHT_CYCLE, {
@@ -98,7 +98,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MK_GUARD_HOUSE_ADULT_POT_11, logic->IsAdult && logic->CanBreakPots()),
}, {
//Exits
- Entrance(RR_MARKET_ENTRANCE, []{return true;}),
+ Entrance(RR_MARKET_ENTRANCE, []{return logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
});
areaTable[RR_MARKET_BAZAAR] = Region("Market Bazaar", "Market Bazaar", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -133,7 +133,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_SHOOTING_GALLERY_REWARD, logic->IsChild && logic->HasItem(RG_CHILD_WALLET)),
}, {
//Exits
- Entrance(RR_THE_MARKET, []{return true;}),
+ Entrance(RR_THE_MARKET, []{return logic->CanOpenOverworldDoor(RG_MARKET_SHOOTING_GALLERY_KEY);}),
});
areaTable[RR_MARKET_BOMBCHU_BOWLING] = Region("Market Bombchu Bowling", "Market Bombchu Bowling", {}, NO_DAY_NIGHT_CYCLE, {
@@ -145,7 +145,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, logic->CouldPlayBowling && logic->BombchusEnabled()),
}, {
//Exits
- Entrance(RR_THE_MARKET, []{return true;}),
+ Entrance(RR_THE_MARKET, []{return logic->CanOpenOverworldDoor(RG_BOMBCHU_BOWLING_KEY);}),
});
areaTable[RR_MARKET_POTION_SHOP] = Region("Market Potion Shop", "Market Potion Shop", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -179,7 +179,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
}, {
//Exits
- Entrance(RR_THE_MARKET, []{return true;}),
+ Entrance(RR_THE_MARKET, []{return logic->CanOpenOverworldDoor(RG_TREASURE_CHEST_GAME_BUILDING_KEY);}),
});
areaTable[RR_MARKET_BOMBCHU_SHOP] = Region("Market Bombchu Shop", "Market Bombchu Shop", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -202,7 +202,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_LOST_DOG, logic->IsChild && logic->AtNight),
}, {
//Exits
- Entrance(RR_MARKET_BACK_ALLEY, []{return true;}),
+ Entrance(RR_MARKET_BACK_ALLEY, []{return logic->CanOpenOverworldDoor(RG_RICHARDS_HOUSE_KEY);}),
});
areaTable[RR_MARKET_MAN_IN_GREEN_HOUSE] = Region("Market Man in Green House", "Market Man in Green House", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -212,6 +212,6 @@ void RegionTable_Init_Market() {
LOCATION(RC_MK_BACK_ALLEY_HOUSE_POT_3, logic->CanBreakPots()),
}, {
//Exits
- Entrance(RR_MARKET_BACK_ALLEY, []{return true;}),
+ Entrance(RR_MARKET_BACK_ALLEY, []{return logic->CanOpenOverworldDoor(RG_ALLEY_HOUSE_KEY);}),
});
}
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp
index 9e89ea5d1..54c1d8f81 100644
--- a/soh/soh/Enhancements/randomizer/location_list.cpp
+++ b/soh/soh/Enhancements/randomizer/location_list.cpp
@@ -1800,8 +1800,11 @@ void Rando::StaticData::InitLocationTable() { //
locationTable[RC_HF_POND_STORMS_FAIRY] = Location::Fairy(RC_HF_POND_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(0x1000, 5012), "Pond Song of Storms Fairy", "Pond Song of Storms Fairy", RHT_HF_POND_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_POND_STORMS_FAIRY));
locationTable[RC_HF_FENCE_GROTTO_STORMS_FAIRY] = Location::Fairy(RC_HF_FENCE_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -308), "Inside Fence Storms Fairy", "Inside Fence Storms Fairy", RHT_HF_FENCE_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_FENCE_GROTTO_STORMS_FAIRY));
locationTable[RC_DMT_FLAG_SUN_FAIRY] = Location::Fairy(RC_DMT_FLAG_SUN_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_DEATH_MOUNTAIN_TRAIL, TWO_ACTOR_PARAMS(0x1000, 464), "Flag Sun's Song Fairy", "Flag Sun's Song Fairy", RHT_DMT_FLAG_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_FLAG_SUN_FAIRY));
+ locationTable[RC_DMT_COW_GROTTO_STORMS_FAIRY] = Location::Fairy(RC_DMT_COW_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -311), "Cow Grotto Song of Storms Fairy", "Cow Grotto Song of Storms Fairy", RHT_DMT_COW_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_COW_GROTTO_STORMS_FAIRY));
locationTable[RC_LW_SHORTCUT_STORMS_FAIRY] = Location::Fairy(RC_LW_SHORTCUT_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(0x1000, -795), "Shortcuts Song of Storms Fairy", "Shortcuts Song of Storms Fairy", RHT_LW_SHORTCUT_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_SHORTCUT_STORMS_FAIRY));
locationTable[RC_GF_KITCHEN_SUN_FAIRY] = Location::Fairy(RC_GF_KITCHEN_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(0x1000, -621), "Kitchen Sun's Song Fairy", "Kitchen Sun's Song Fairy", RHT_GF_KITCHEN_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_KITCHEN_SUN_FAIRY));
+ locationTable[RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = Location::Fairy(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, 741), "Scrub Grotto Sun's Song Fairy", "Scrub Grotto Sun's Song Fairy", RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY));
+ locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = Location::Fairy(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_ROYAL_FAMILYS_TOMB, TWO_ACTOR_PARAMS(0x1000, 1476), "Composer's Grave Sun's Song Fairy", "Composer's Grave Sun's Song Fairy", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY));
locationTable[RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1896), "After Boulder Room Sun's Song Fairy", "After Boulder Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY));
locationTable[RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "Four Armos Room Sun's Song Fairy", "Four Armos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY));
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index cd65fd006..1ea19d3ad 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -140,6 +140,31 @@ namespace Rando {
case RG_TWINROVA_SOUL:
case RG_GANON_SOUL:
case RG_SKELETON_KEY:
+ // Overworld Keys
+ case RG_GUARD_HOUSE_KEY:
+ case RG_MARKET_BAZAAR_KEY:
+ case RG_MARKET_POTION_SHOP_KEY:
+ case RG_MASK_SHOP_KEY:
+ case RG_MARKET_SHOOTING_GALLERY_KEY:
+ case RG_BOMBCHU_BOWLING_KEY:
+ case RG_TREASURE_CHEST_GAME_BUILDING_KEY:
+ case RG_BOMBCHU_SHOP_KEY:
+ case RG_RICHARDS_HOUSE_KEY:
+ case RG_ALLEY_HOUSE_KEY:
+ case RG_KAK_BAZAAR_KEY:
+ case RG_KAK_POTION_SHOP_KEY:
+ case RG_BOSS_HOUSE_KEY:
+ case RG_GRANNYS_POTION_SHOP_KEY:
+ case RG_SKULLTULA_HOUSE_KEY:
+ case RG_IMPAS_HOUSE_KEY:
+ case RG_WINDMILL_KEY:
+ case RG_KAK_SHOOTING_GALLERY_KEY:
+ case RG_DAMPES_HUT_KEY:
+ case RG_TALONS_HOUSE_KEY:
+ case RG_STABLES_KEY:
+ case RG_BACK_TOWER_KEY:
+ case RG_HYLIA_LAB_KEY:
+ case RG_FISHING_HOLE_KEY:
return CheckRandoInf(RandoGetToRandInf.at(itemName));
// Boss Keys
case RG_EPONA:
@@ -382,6 +407,18 @@ namespace Rando {
}
}
+ bool Logic::CanOpenOverworldDoor(RandomizerGet key) {
+ if (!ctx->GetOption(RSK_LOCK_OVERWORLD_DOORS)) {
+ return true;
+ }
+
+ if (HasItem(RG_SKELETON_KEY)) {
+ return true;
+ }
+
+ return HasItem(key);
+ }
+
uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) {
return 0;
}
@@ -1038,7 +1075,7 @@ namespace Rando {
10 for OHKO.
This is the number of shifts to apply, not a real multiplier
*/
- uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() : 10;
+ uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Get() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Get() : 10;
//(Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) is quarter hearts after DD
//>> Multiplier halves on normal and does nothing on half, meaning we're working with half hearts on normal damage
return ((Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) >> Multiplier) +
@@ -1168,21 +1205,21 @@ namespace Rando {
bool Logic::CanBuildRainbowBridge(){
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA) && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION) && CanUse(RG_LIGHT_ARROWS)) ||
- (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex()) ||
- (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex()) ||
- (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex()) ||
- (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex()) ||
- (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex()) ||
+ (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get()) ||
+ (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get()) ||
+ (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get()) ||
+ (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get()) ||
+ (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && HasItem(RG_GREG_RUPEE));
}
bool Logic::CanTriggerLACS(){
- return (ctx->GetSettings()->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) ||
- (ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex()) ||
- (ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex()) ||
- (ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex()) ||
- (ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex()) ||
- (ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex());
+ return (ctx->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) ||
+ (ctx->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).Get()) ||
+ (ctx->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get()) ||
+ (ctx->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).Get()) ||
+ (ctx->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get()) ||
+ (ctx->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) {
@@ -1293,7 +1330,31 @@ namespace Rando {
{ RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT },
{ RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY },
{ RG_GREG_RUPEE, RAND_INF_GREG_FOUND },
- { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }
+ { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND },
+ { RG_GUARD_HOUSE_KEY, RAND_INF_GUARD_HOUSE_KEY_OBTAINED },
+ { RG_MARKET_BAZAAR_KEY, RAND_INF_MARKET_BAZAAR_KEY_OBTAINED },
+ { RG_MARKET_POTION_SHOP_KEY, RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED },
+ { RG_MASK_SHOP_KEY, RAND_INF_MASK_SHOP_KEY_OBTAINED },
+ { RG_MARKET_SHOOTING_GALLERY_KEY, RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED },
+ { RG_BOMBCHU_BOWLING_KEY, RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED },
+ { RG_TREASURE_CHEST_GAME_BUILDING_KEY, RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED },
+ { RG_BOMBCHU_SHOP_KEY, RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED },
+ { RG_RICHARDS_HOUSE_KEY, RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED },
+ { RG_ALLEY_HOUSE_KEY, RAND_INF_ALLEY_HOUSE_KEY_OBTAINED },
+ { RG_KAK_BAZAAR_KEY, RAND_INF_KAK_BAZAAR_KEY_OBTAINED },
+ { RG_KAK_POTION_SHOP_KEY, RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED },
+ { RG_BOSS_HOUSE_KEY, RAND_INF_BOSS_HOUSE_KEY_OBTAINED },
+ { RG_GRANNYS_POTION_SHOP_KEY, RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED },
+ { RG_SKULLTULA_HOUSE_KEY, RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED },
+ { RG_IMPAS_HOUSE_KEY, RAND_INF_IMPAS_HOUSE_KEY_OBTAINED },
+ { RG_WINDMILL_KEY, RAND_INF_WINDMILL_KEY_OBTAINED },
+ { RG_KAK_SHOOTING_GALLERY_KEY, RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED },
+ { RG_DAMPES_HUT_KEY, RAND_INF_DAMPES_HUT_KEY_OBTAINED },
+ { RG_TALONS_HOUSE_KEY, RAND_INF_TALONS_HOUSE_KEY_OBTAINED },
+ { RG_STABLES_KEY, RAND_INF_STABLES_KEY_OBTAINED },
+ { RG_BACK_TOWER_KEY, RAND_INF_BACK_TOWER_KEY_OBTAINED },
+ { RG_HYLIA_LAB_KEY, RAND_INF_HYLIA_LAB_KEY_OBTAINED },
+ { RG_FISHING_HOLE_KEY, RAND_INF_FISHING_HOLE_KEY_OBTAINED },
};
std::map Logic::RandoGetToDungeonScene = {
@@ -1370,6 +1431,18 @@ namespace Rando {
{ RG_GERUDO_MEMBERSHIP_CARD, QUEST_GERUDO_CARD },
};
+ std::map BottleRandomizerGetToItemID = {
+ { RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED },
+ { RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN },
+ { RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE },
+ { RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY },
+ { RG_BOTTLE_WITH_FISH, ITEM_FISH },
+ { RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE },
+ { RG_BOTTLE_WITH_BUGS, ITEM_BUG },
+ { RG_BOTTLE_WITH_POE, ITEM_POE },
+ { RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE },
+ };
+
uint32_t HookshotLookup[3] = { ITEM_NONE, ITEM_HOOKSHOT, ITEM_LONGSHOT };
uint32_t OcarinaLookup[3] = { ITEM_NONE, ITEM_OCARINA_FAIRY, ITEM_OCARINA_TIME };
@@ -1614,7 +1687,11 @@ namespace Rando {
}
slot++;
}
- mSaveContext->inventory.items[slot] = item.GetGIEntry()->itemId;
+ uint16_t itemId = item.GetGIEntry()->itemId;
+ if (BottleRandomizerGetToItemID.contains(randoGet)) {
+ itemId = BottleRandomizerGetToItemID[randoGet];
+ }
+ mSaveContext->inventory.items[slot] = itemId;
} break;
case RG_RUTOS_LETTER:
SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER, state);
@@ -1635,6 +1712,30 @@ namespace Rando {
case RG_OCARINA_C_RIGHT_BUTTON:
case RG_GREG_RUPEE:
case RG_FISHING_POLE:
+ case RG_GUARD_HOUSE_KEY:
+ case RG_MARKET_BAZAAR_KEY:
+ case RG_MARKET_POTION_SHOP_KEY:
+ case RG_MASK_SHOP_KEY:
+ case RG_MARKET_SHOOTING_GALLERY_KEY:
+ case RG_BOMBCHU_BOWLING_KEY:
+ case RG_TREASURE_CHEST_GAME_BUILDING_KEY:
+ case RG_BOMBCHU_SHOP_KEY:
+ case RG_RICHARDS_HOUSE_KEY:
+ case RG_ALLEY_HOUSE_KEY:
+ case RG_KAK_BAZAAR_KEY:
+ case RG_KAK_POTION_SHOP_KEY:
+ case RG_BOSS_HOUSE_KEY:
+ case RG_GRANNYS_POTION_SHOP_KEY:
+ case RG_SKULLTULA_HOUSE_KEY:
+ case RG_IMPAS_HOUSE_KEY:
+ case RG_WINDMILL_KEY:
+ case RG_KAK_SHOOTING_GALLERY_KEY:
+ case RG_DAMPES_HUT_KEY:
+ case RG_TALONS_HOUSE_KEY:
+ case RG_STABLES_KEY:
+ case RG_BACK_TOWER_KEY:
+ case RG_HYLIA_LAB_KEY:
+ case RG_FISHING_HOLE_KEY:
SetRandoInf(RandoGetToRandInf.at(randoGet), state);
break;
case RG_TRIFORCE_PIECE:
@@ -2116,7 +2217,7 @@ namespace Rando {
//Bottle Count
Bottles = 0;
NumBottles = 0;
- CanEmptyBigPoes = true;
+ CanEmptyBigPoes = false;
//Drops and Bottle Contents Access
NutPot = false;
@@ -2153,7 +2254,7 @@ namespace Rando {
//CanPlantBean = false;
BigPoeKill = false;
- BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() + 1;
+ BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() + 1;
//Bridge Requirements
@@ -2162,7 +2263,7 @@ namespace Rando {
//Other
AtDay = false;
AtNight = false;
- GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
+ GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
//Events
ShowedMidoSwordAndShield = false;
diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h
index 3aff99d67..ea9d51801 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -186,6 +186,7 @@ class Logic {
bool HasProjectile(HasProjectileAge age);
bool HasItem(RandomizerGet itemName);
bool HasBossSoul(RandomizerGet itemName);
+ bool CanOpenOverworldDoor(RandomizerGet itemName);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
bool CanDoGlitch(GlitchType glitch);
diff --git a/soh/soh/Enhancements/randomizer/option.cpp b/soh/soh/Enhancements/randomizer/option.cpp
index d7ff94121..84743cae6 100644
--- a/soh/soh/Enhancements/randomizer/option.cpp
+++ b/soh/soh/Enhancements/randomizer/option.cpp
@@ -5,39 +5,53 @@
#include "soh/UIWidgets.hpp"
namespace Rando {
-Option Option::Bool(std::string name_, std::vector options_, const OptionCategory category_,
- std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
- const bool defaultHidden_, int imFlags_) {
- return {false, std::move(name_), std::move(options_), category_, std::move(cvarName_), std::move(description_),
- widgetType_, defaultOption_, defaultHidden_, imFlags_};
+Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::vector options_,
+ const OptionCategory category_, std::string cvarName_, std::string description_,
+ WidgetType widgetType_, const uint8_t defaultOption_, const bool defaultHidden_, int imFlags_) {
+ return {static_cast(key_), std::move(name_), std::move(options_), category_,
+ std::move(cvarName_), std::move(description_), widgetType_, defaultOption_, defaultHidden_, imFlags_};
}
-Option Option::Bool(std::string name_, std::string cvarName_, std::string description_, const int imFlags_,
- const WidgetType widgetType_, const bool defaultOption_) {
- return Option(false, std::move(name_), {"Off", "On"}, OptionCategory::Setting, std::move(cvarName_),
+Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::string cvarName_, std::string description_,
+ const int imFlags_, const WidgetType widgetType_, const bool defaultOption_) {
+ return Option(key_, std::move(name_), {"Off", "On"}, OptionCategory::Setting, std::move(cvarName_),
std::move(description_), widgetType_, defaultOption_, false, imFlags_);
}
-Option Option::U8(std::string name_, std::vector options_, const OptionCategory category_,
- std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
- const bool defaultHidden_, int imFlags_) {
- return {static_cast(0), std::move(name_), std::move(options_), category_, std::move(cvarName_),
+Option Option::U8(RandomizerSettingKey key_, std::string name_, std::vector options_,
+ const OptionCategory category_, std::string cvarName_, std::string description_,
+ WidgetType widgetType_, const uint8_t defaultOption_, const bool defaultHidden_, int imFlags_) {
+ return {static_cast(key_), std::move(name_), std::move(options_), category_, std::move(cvarName_),
std::move(description_), widgetType_, defaultOption_, defaultHidden_, imFlags_};
}
-Option Option::LogicTrick(std::string name_) {
- return Option(false, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, "",
+Option Option::LogicTrick(RandomizerTrick rt_, std::string name_) {
+ return Option(rt_, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, "",
"", WidgetType::Checkbox, 0, false, IMFLAG_NONE);
}
-Option::operator bool() const {
- return contextSelection != 0;
+OptionValue::OptionValue(uint8_t val) : mVal(val) {}
+
+uint8_t OptionValue::Get() {
+ return mVal;
+}
+
+void OptionValue::Set(uint8_t val) {
+ mVal = val;
+}
+
+OptionValue::operator bool() const {
+ return mVal != 0;
}
size_t Option::GetOptionCount() const {
return options.size();
}
+const RandomizerSettingKey Option::GetKey() const {
+ return static_cast(key);
+}
+
const std::string& Option::GetName() const {
return name;
}
@@ -50,26 +64,14 @@ uint8_t Option::GetMenuOptionIndex() const {
return menuSelection;
}
-uint8_t Option::GetContextOptionIndex() const {
- return contextSelection;
-}
-
-const std::string& Option::GetSelectedOptionText() const {
- return options[contextSelection];
+const std::string& Option::GetOptionText(size_t index) const {
+ return options[index];
}
const std::string& Option::GetCVarName() const {
return cvarName;
}
-void Option::SetVariable() {
- if (std::holds_alternative(var)) {
- var.emplace(menuSelection != 0);
- } else {
- var.emplace(menuSelection);
- }
-}
-
void Option::SaveCVar() const {
if (!cvarName.empty()) {
CVarSetInteger(cvarName.c_str(), GetMenuOptionIndex());
@@ -95,10 +97,10 @@ void Option::SetMenuIndex(size_t idx) {
if (menuSelection > options.size() - 1) {
menuSelection = options.size() - 1;
}
- SetVariable();
}
void Option::SetContextIndex(size_t idx) {
+ // TODO: Set to Context's OptionValue array.
contextSelection = idx;
if (contextSelection > options.size() - 1) {
contextSelection = options.size() - 1;
@@ -178,6 +180,16 @@ void Option::RemoveFlag(const int imFlag_) {
imFlags &= ~imFlag_;
}
+uint8_t Option::GetValueFromText(const std::string text) {
+ if (optionsTextToVar.contains(text)) {
+ return optionsTextToVar[text];
+ } else {
+ SPDLOG_ERROR("Option {} does not have a var named {}.", name, text);
+ assert(false);
+ }
+ return defaultOption;
+}
+
void Option::SetContextIndexFromText(const std::string text) {
if (optionsTextToVar.contains(text)){
SetContextIndex(optionsTextToVar[text]);
@@ -187,21 +199,10 @@ void Option::SetContextIndexFromText(const std::string text) {
}
}
-Option::Option(uint8_t var_, std::string name_, std::vector options_, OptionCategory category_,
+Option::Option(size_t key_, std::string name_, std::vector options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_)
- : var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
- cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_),
- defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) {
- menuSelection = contextSelection = defaultOption;
- hidden = defaultHidden;
- PopulateTextToNum();
- SetFromCVar();
-}
-Option::Option(bool var_, std::string name_, std::vector options_, const OptionCategory category_,
- std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
- const bool defaultHidden_, int imFlags_)
- : var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
+ : key(key_), name(std::move(name_)), options(std::move(options_)), category(category_),
cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_),
defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) {
menuSelection = contextSelection = defaultOption;
@@ -350,13 +351,25 @@ void Option::PopulateTextToNum(){
}
}
-TrickOption::TrickOption(const RandomizerCheckQuest quest_, const RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_) :
- Option(false, name_, {"Disabled", "Enabled"}, OptionCategory::Setting, "",
+LocationOption::LocationOption(RandomizerCheck key_, const std::string& name_) :
+ Option(key_, name_, {"Included", "Excluded"}, OptionCategory::Setting, "", "", WidgetType::Checkbox,
+ RO_LOCATION_INCLUDE, false, IMFLAG_NONE) {}
+
+const RandomizerCheck LocationOption::GetKey() const {
+ return static_cast(key);
+}
+
+TrickOption::TrickOption(RandomizerTrick key_, const RandomizerCheckQuest quest_, const RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_) :
+ Option(key_, name_, {"Disabled", "Enabled"}, OptionCategory::Setting, "",
std::move(description_), WidgetType::Checkbox, 0, false, IMFLAG_NONE),
mQuest(quest_), mArea(area_), mTags(std::move(tags_)) {}
-TrickOption TrickOption::LogicTrick(RandomizerCheckQuest quest_, RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_) {
- return {quest_, area_, std::move(tags_), name_, std::move(description_)};
+TrickOption TrickOption::LogicTrick(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_) {
+ return {key_, quest_, area_, std::move(tags_), name_, std::move(description_)};
+}
+
+const RandomizerTrick TrickOption::GetKey() const {
+ return static_cast(key);
}
RandomizerCheckQuest TrickOption::GetQuest() const {
diff --git a/soh/soh/Enhancements/randomizer/option.h b/soh/soh/Enhancements/randomizer/option.h
index e1e5a3a78..a8ffe3511 100644
--- a/soh/soh/Enhancements/randomizer/option.h
+++ b/soh/soh/Enhancements/randomizer/option.h
@@ -40,6 +40,59 @@ enum class WidgetType {
Slider, /** Compatible with U8s. If constructed with NumOpts, consider using this. Technically can be used for Bool or non-NumOpts options but it would be a bit weird semantically. */
};
+class OptionValue {
+ public:
+ OptionValue() = default;
+ OptionValue(uint8_t value_);
+
+ /**
+ * @brief Returns the value of the OptionValue's mVal
+ *
+ * @return uint8_t
+ */
+ uint8_t Get();
+
+ /**
+ * @brief Set the OptionValue's mVal to the provided val.
+ *
+ * @param val
+ */
+ void Set(uint8_t val);
+
+ /**
+ * @brief Determines if the value/selected index of this Option matches the provided value.
+ *
+ * @param other The value to compare.
+ * @return true
+ * @return false
+ */
+ bool Is(uint32_t other) const {
+ return mVal == other;
+ }
+
+ /**
+ * @brief Determines if the value/selected index of this Option does not match the provided value.
+ *
+ * @param other The value to compare.
+ * @return true
+ * @return false
+ */
+ bool IsNot(uint32_t other) const {
+ return !Is(other);
+ }
+
+ /**
+ * @brief Allows the option to be used as a boolean value directly.
+ *
+ * @return true
+ * @return false
+ */
+ explicit operator bool() const;
+
+ private:
+ uint8_t mVal;
+};
+
/**
* @brief A class describing the state of a single option/setting, such as its name,
* options, current value, whether or not it is interactable in the menu, or the CVar,
@@ -68,7 +121,8 @@ class Option {
* @param imFlags_ (see ImGuiMenuFlags type) flags that can modify how this option is rendered.
* @return Option
*/
- static Option Bool(std::string name_, std::vector options_ = { "Off", "On" },
+ static Option Bool(RandomizerSettingKey key_, std::string name_,
+ std::vector options_ = { "Off", "On" },
OptionCategory category_ = OptionCategory::Setting, std::string cvarName_ = "",
std::string description_ = "", WidgetType widgetType_ = WidgetType::Checkbox,
uint8_t defaultOption_ = 0, bool defaultHidden_ = false, int imFlags_ = IMFLAG_SEPARATOR_BOTTOM);
@@ -79,6 +133,7 @@ class Option {
* existing calls to the other overload of this function. The options vector will be { "Off", "On" }
* when using this overload. If you want your option to have different value names, use the other overload.
*
+ * @param key_ The RandomizerSettingKey of this option.
* @param name_ The name of the option. Appears in the spoiler/patch file.
* @param cvarName_ The name of the CVar this option should correspond with. Set as an empty string to not
* link to any CVar.
@@ -90,13 +145,14 @@ class Option {
* @param defaultOption_ The defaulted selected index for this Option.
* @return Option
*/
- static Option Bool(std::string name_, std::string cvarName_, std::string description_ = "",
- int imFlags_ = IMFLAG_SEPARATOR_BOTTOM, WidgetType widgetType_ = WidgetType::Checkbox,
- bool defaultOption_ = false);
+ static Option Bool(RandomizerSettingKey key_, std::string name_, std::string cvarName_,
+ std::string description_ = "", int imFlags_ = IMFLAG_SEPARATOR_BOTTOM,
+ WidgetType widgetType_ = WidgetType::Checkbox, bool defaultOption_ = false);
/**
* @brief Constructs a U8 Option.
*
+ * @param key_ The RandomizerSettingKey for this option.
* @param name_ The name of this Option. Appears in the spoiler/patch file.
* @param options_ A vector of value names for this Option. The name corresponding to the selected
* index for this option will be printed to the spoiler/patch file.
@@ -114,7 +170,7 @@ class Option {
* @param imFlags_ (see ImGuiMenuFlags type) flags that can modify how this option is rendered.
* @return Option
*/
- static Option U8(std::string name_, std::vector options_,
+ static Option U8(RandomizerSettingKey key_, std::string name_, std::vector options_,
OptionCategory category_ = OptionCategory::Setting, std::string cvarName_ = "",
std::string description_ = "", WidgetType widgetType_ = WidgetType::Combobox,
uint8_t defaultOption_ = 0, bool defaultHidden_ = false, int imFlags_ = IMFLAG_SEPARATOR_BOTTOM);
@@ -125,37 +181,7 @@ class Option {
* @param name_ The name of the trick. Appears in the spoiler/patch file.
* @return Option
*/
- static Option LogicTrick(std::string name_);
-
- /**
- * @brief Determines if the value/selected index of this Option matches the provided value.
- *
- * @param other The value to compare.
- * @return true
- * @return false
- */
- bool Is(uint32_t other) const {
- return contextSelection == other;
- }
-
- /**
- * @brief Determines if the value/selected index of this Option does not match the provided value.
- *
- * @param other The value to compare.
- * @return true
- * @return false
- */
- bool IsNot(uint32_t other) const {
- return !Is(other);
- }
-
- /**
- * @brief Allows the option to be used as a boolean value directly.
- *
- * @return true
- * @return false
- */
- explicit operator bool() const;
+ static Option LogicTrick(RandomizerTrick rt_, std::string name_);
/**
* @brief Get the size of the options array.
@@ -164,6 +190,13 @@ class Option {
*/
size_t GetOptionCount() const;
+ /**
+ * @brief Get the Key Option
+ *
+ * @return const RandomizerSettingKey
+ */
+ const RandomizerSettingKey GetKey() const;
+
/**
* @brief Get the name of the Option.
*
@@ -173,11 +206,12 @@ class Option {
const std::string& GetDescription() const;
/**
- * @brief Get the value name corresponding to the selected index.
- *
- * @return const std::string&
+ * @brief Get the text of the Option value of the selected index.
+ *
+ * @param index
+ * @return const std::string&
*/
- const std::string& GetSelectedOptionText() const;
+ const std::string& GetOptionText(size_t index) const;
/**
* @brief Get the CVar name for this Option.
@@ -193,18 +227,6 @@ class Option {
*/
uint8_t GetMenuOptionIndex() const;
- /**
- * @brief Get the rando context index for this Option.
- *
- * @return uint8_t
- */
- uint8_t GetContextOptionIndex() const;
-
- /**
- * @brief Sets the variable to the currently selected index for this Option.
- */
- void SetVariable();
-
/**
* @brief Sets the CVar corresponding to the property `cvarName` equal to the value
* of the property `selectedValue`.
@@ -306,15 +328,14 @@ class Option {
void SetFlag(int imFlag_);
void RemoveFlag(int imFlag_);
+ uint8_t GetValueFromText(std::string text);
void SetContextIndexFromText(std::string text);
protected:
- Option(uint8_t var_, std::string name_, std::vector options_, OptionCategory category_,
- std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
- bool defaultHidden_, int imFlags_);
- Option(bool var_, std::string name_, std::vector options_, OptionCategory category_,
+ Option(size_t key_, std::string name_, std::vector options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_);
+ size_t key;
private:
bool RenderCheckbox();
@@ -322,7 +343,6 @@ protected:
bool RenderCombobox();
bool RenderSlider();
void PopulateTextToNum();
- std::variant var;
std::string name;
std::vector options;
uint8_t menuSelection = 0;
@@ -342,12 +362,20 @@ protected:
std::unordered_map optionsTextToVar = {};
};
+class LocationOption : public Option {
+public:
+ LocationOption() = default;
+ LocationOption(RandomizerCheck key_, const std::string& name_);
+ const RandomizerCheck GetKey() const;
+};
+
class TrickOption : public Option {
public:
TrickOption() = default;
/**
* @brief A convenience function for constructing the Option for a trick.
*
+ * @param key_ A RandomizerTrick key for this option.
* @param quest_ MQ, Vanilla, or Both.
* @param area_ The area the trick is relevant for.
* @param tags_ The set of RandomizerTrickTags for this trick.
@@ -355,7 +383,9 @@ public:
* @param description_ A brief description of the trick.
* @return Option
*/
- static TrickOption LogicTrick(RandomizerCheckQuest quest_, RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_);
+ static TrickOption LogicTrick(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_);
+
+ const RandomizerTrick GetKey() const;
/**
* @brief Retrieve the quest type this trick is relevant for.
@@ -382,7 +412,7 @@ public:
const std::set& GetTags() const;
private:
- TrickOption(RandomizerCheckQuest quest_, RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_);
+ TrickOption(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set tags_, const std::string& name_, std::string description_);
RandomizerCheckQuest mQuest;
RandomizerArea mArea;
std::set mTags;
diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
index 2e577c51e..8abdd2634 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -41,6 +41,7 @@ void Settings::CreateOptionDescriptions() {
"\n"
"Open - Sleeping Waterfall is always open. "
"Link may always enter Zora's Domain.";
+ mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS] = "Add locks to all wooden overworld doors, requiring specific small keys to open them";
mOptionDescriptions[RSK_STARTING_AGE] =
"Choose which age Link will start as.\n\n"
"Starting as adult means you start with the Master Sword in your inventory.\n"
@@ -697,9 +698,6 @@ void Settings::CreateOptionDescriptions() {
"location is reachable. When disabled, only "
"required items and locations to beat the game "
"will be guaranteed reachable.";
- mOptionDescriptions[RSK_ENABLE_GLITCH_CUTSCENES] =
- "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. "
- "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise.";
mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS] = "Shuffles 8 boss souls (one for each blue warp dungeon). A boss will not appear until you collect its respective soul."
"\n\"On + Ganon\" will also hide Ganon and Ganondorf behind a boss soul.";
}
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index 301498bf8..477c2f0da 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -475,7 +475,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
(CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE);
case RG_DEKU_STICK_1:
case RG_BUY_DEKU_STICK_1:
- return CUR_UPG_VALUE(UPG_STICKS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).GetContextOptionIndex()
+ return CUR_UPG_VALUE(UPG_STICKS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Get()
? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE;
case RG_PROGRESSIVE_NUT_UPGRADE:
return infiniteUpgrades != RO_INF_UPGRADES_OFF ?
@@ -485,7 +485,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
case RG_DEKU_NUTS_10:
case RG_BUY_DEKU_NUTS_5:
case RG_BUY_DEKU_NUTS_10:
- return CUR_UPG_VALUE(UPG_NUTS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).GetContextOptionIndex()
+ return CUR_UPG_VALUE(UPG_NUTS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Get()
? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE;
case RG_PROGRESSIVE_BOMB_BAG:
return infiniteUpgrades != RO_INF_UPGRADES_OFF ?
@@ -1837,7 +1837,7 @@ FishIdentity Randomizer::IdentifyFish(s32 sceneNum, s32 actorParams) {
}
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
- return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetContextOptionIndex();
+ return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get();
}
GetItemEntry Randomizer::GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability) {
@@ -1871,7 +1871,8 @@ void GenerateRandomizerImgui(std::string seed = "") {
CVarSave();
auto ctx = Rando::Context::GetInstance();
//RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings
- ctx->GetSettings()->SetAllFromCVar();
+ Rando::Settings::GetInstance()->SetAllFromCVar();
+ Rando::Settings::GetInstance()->SetAllToContext();
// todo: this efficently when we build out cvar array support
std::set excludedLocations;
@@ -2182,13 +2183,6 @@ void RandomizerSettingsWindow::DrawElement() {
ImGui::SameLine();
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Heads up! This will disable all rando settings except for entrance shuffle and starter items");
}
-
- UIWidgets::PaddedSeparator();
-
- // Enable Glitch-Useful Cutscenes
- if (mSettings->GetOption(RSK_ENABLE_GLITCH_CUTSCENES).RenderImGui()) {
- mNeedsUpdate = true;
- }
ImGui::PopItemWidth();
ImGui::EndTable();
}
@@ -3338,7 +3332,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) {
void Randomizer::CreateCustomMessages() {
// RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED
// with GIMESSAGE(getItemID, itemID, english, german, french).
- const std::array getItemMessages = {{
+ const std::array getItemMessages = {{
GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON,
"You found %gGreg%w!",
"%gGreg%w! Du hast ihn wirklich gefunden!",
@@ -3386,40 +3380,140 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %yThieves Hideout &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für das %yDiebesversteck%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %yDiebesversteck%w!",
"Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"),
GIMESSAGE(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %gForest Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %gWaldtempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gWaldtempel%w!",
"Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"),
GIMESSAGE(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %rFire Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %rFeuertempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %rFeuertempel%w!",
"Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"),
GIMESSAGE(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %bWater Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %bWassertempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %bWassertempel%w!",
"Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"),
GIMESSAGE(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %ySpirit Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %yGeistertempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %yGeistertempel%w!",
"Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"),
GIMESSAGE(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %pShadow Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %pSchattentempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %pSchattentempel%w!",
"Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"),
GIMESSAGE(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %pBottom of the &Well %wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %pGrund des Brunnens%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %pGrund des Brunnens%w!",
"Vous obtenez une %rPetite Clé %w&du %pPuits%w!"),
GIMESSAGE(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %yGerudo Training &Grounds %wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für die %yGerudo-Trainingsarena%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %yGerudo-Trainingsarena%w!",
"Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"),
GIMESSAGE(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %rGanon's Castle &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für %rGanons Schloß%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für %rGanons Schloß%w!",
"Vous obtenez une %rPetite Clé %w&du %rChâteau de Ganon%w!"),
+ GIMESSAGE(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gGuard House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus der Wachen%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison des Gardes%w!"),
+ GIMESSAGE(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMarket Bazaar%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar des Marktes%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMarché%w!"),
+ GIMESSAGE(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMarket Potion Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden des Marktes%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMarché%w!"),
+ GIMESSAGE(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMask Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gMaskenladen%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Masques%w!"),
+ GIMESSAGE(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMarket Shooting Gallery%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude des Marktes%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gStand de Tir%w!"),
+ GIMESSAGE(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBombchu Bowling Alley%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gMinenbowlingbahn%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gBowling Bombchu%w!"),
+ GIMESSAGE(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gTreasure Chest Game Building%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Schatzkisten-Pokers%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gJeu de la Chasse au Trésor%w!"),
+ GIMESSAGE(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBombchu Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gKrabbelminenladen%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Bombchu%w!"),
+ GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gRichard's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de Richard%w!"),
+ GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gRichard's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de Richard%w!"),
+ GIMESSAGE(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&the %gAlley House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus in der Gasse%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de la Ruelle%w!"),
+ GIMESSAGE(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gKakariko Bazaar%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar von Kakariko%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMarché de Cocorico%w!"),
+ GIMESSAGE(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gKakariko Potion Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden von Kakariko%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Potions de Cocorico%w!"),
+ GIMESSAGE(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBoss's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Chefs%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison du Boss%w!"),
+ GIMESSAGE(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gGranny's Potion Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für %gAsas Hexenladen%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Potions de Grand-mère%w!"),
+ GIMESSAGE(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gSkulltula House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gSkulltula-Haus%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison des Skulltulas%w!"),
+ GIMESSAGE(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gImpa's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Impa%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison d'Impa%w!"),
+ GIMESSAGE(RG_WINDMILL_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gWindmill%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gWindmühle%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMoulin à Vent%w!"),
+ GIMESSAGE(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gKakariko Shooting Gallery%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude von Kakariko%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gStand de Tir de Cocorico%w!"),
+ GIMESSAGE(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gDampe's Hut%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gHütte von Boris%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gChalet de Dampe%w!"),
+ GIMESSAGE(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gTalon's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Talon%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de Talon%w!"),
+ GIMESSAGE(RG_STABLES_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gStables%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gStälle%w!",
+ "Vous obtenez une %rPetite Clé %w&des %gÉcuries%w!"),
+ GIMESSAGE(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBack Tower%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %ghinteren Turm%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gTour Arrière%w!"),
+ GIMESSAGE(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gHylia Laboratory%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHylia-Labor%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gLaboratoire d'Hylia%w!"),
+ GIMESSAGE(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gFishing Hole%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gFischweiher%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gTrou de Pêche%w!"),
GIMESSAGE(RG_GERUDO_FORTRESS_KEY_RING, ITEM_KEY_SMALL,
"You found a %yThieves Hideout &%wKeyring!",
@@ -3694,10 +3788,10 @@ class ExtendedVanillaTableInvalidItemIdException: public std::exception {
};
void RandomizerSettingsWindow::InitElement() {
- mSettings = Rando::Context::GetInstance()->GetSettings();
+ mSettings = Rando::Settings::GetInstance();
Randomizer::CreateCustomMessages();
seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char));
- Rando::Context::GetInstance()->GetSettings()->UpdateOptionProperties();
+ mSettings->UpdateOptionProperties();
}
// Gameplay stat tracking: Update time the item was acquired
@@ -3953,6 +4047,9 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
return Return_Item_Entry(giEntry, RG_NONE);
+ } else if (item >= RG_GUARD_HOUSE_KEY && item <= RG_FISHING_HOLE_KEY) {
+ Flags_SetRandomizerInf((RandomizerInf)((int)RAND_INF_GUARD_HOUSE_UNLOCKED + ((item - RG_GUARD_HOUSE_KEY) * 2) + 1));
+ return Return_Item_Entry(giEntry, RG_NONE);
}
switch (item) {
diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h
index d7edb01df..66128d50f 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -148,6 +148,30 @@ typedef enum {
LOGIC_GANONS_CASTLE_KEYS,
LOGIC_TREASURE_GAME_KEYS,
LOGIC_SKELETON_KEY,
+ LOGIC_GUARD_HOUSE_KEY,
+ LOGIC_MARKET_BAZAAR_KEY,
+ LOGIC_MARKET_POTION_SHOP_KEY,
+ LOGIC_MASK_SHOP_KEY,
+ LOGIC_MARKET_SHOOTING_GALLERY_KEY,
+ LOGIC_BOMBCHU_BOWLING_KEY,
+ LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,
+ LOGIC_BOMBCHU_SHOP_KEY,
+ LOGIC_RICHARDS_HOUSE_KEY,
+ LOGIC_ALLEY_HOUSE_KEY,
+ LOGIC_KAK_BAZAAR_KEY,
+ LOGIC_KAK_POTION_SHOP_KEY,
+ LOGIC_BOSS_HOUSE_KEY,
+ LOGIC_GRANNYS_POTION_SHOP_KEY,
+ LOGIC_SKULLTULA_HOUSE_KEY,
+ LOGIC_IMPAS_HOUSE_KEY,
+ LOGIC_WINDMILL_KEY,
+ LOGIC_KAK_SHOOTING_GALLERY_KEY,
+ LOGIC_DAMPES_HUT_KEY,
+ LOGIC_TALONS_HOUSE_KEY,
+ LOGIC_STABLES_KEY,
+ LOGIC_BACK_TOWER_KEY,
+ LOGIC_HYLIA_LAB_KEY,
+ LOGIC_FISHING_HOLE_KEY,
LOGIC_KOKIRI_EMERALD,
LOGIC_GORON_RUBY,
LOGIC_ZORA_SAPPHIRE,
@@ -2799,8 +2823,11 @@ typedef enum {
RC_HF_POND_STORMS_FAIRY,
RC_HF_FENCE_GROTTO_STORMS_FAIRY,
RC_DMT_FLAG_SUN_FAIRY,
+ RC_DMT_COW_GROTTO_STORMS_FAIRY,
RC_LW_SHORTCUT_STORMS_FAIRY,
RC_GF_KITCHEN_SUN_FAIRY,
+ RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY,
+ RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY,
RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY,
RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY,
RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY,
@@ -3341,6 +3368,30 @@ typedef enum {
RG_HOOKSHOT,
RG_LONGSHOT,
RG_SCARECROW,
+ RG_GUARD_HOUSE_KEY,
+ RG_MARKET_BAZAAR_KEY,
+ RG_MARKET_POTION_SHOP_KEY,
+ RG_MASK_SHOP_KEY,
+ RG_MARKET_SHOOTING_GALLERY_KEY,
+ RG_BOMBCHU_BOWLING_KEY,
+ RG_TREASURE_CHEST_GAME_BUILDING_KEY,
+ RG_BOMBCHU_SHOP_KEY,
+ RG_RICHARDS_HOUSE_KEY,
+ RG_ALLEY_HOUSE_KEY,
+ RG_KAK_BAZAAR_KEY,
+ RG_KAK_POTION_SHOP_KEY,
+ RG_BOSS_HOUSE_KEY,
+ RG_GRANNYS_POTION_SHOP_KEY,
+ RG_SKULLTULA_HOUSE_KEY,
+ RG_IMPAS_HOUSE_KEY,
+ RG_WINDMILL_KEY,
+ RG_KAK_SHOOTING_GALLERY_KEY,
+ RG_DAMPES_HUT_KEY,
+ RG_TALONS_HOUSE_KEY,
+ RG_STABLES_KEY,
+ RG_BACK_TOWER_KEY,
+ RG_HYLIA_LAB_KEY,
+ RG_FISHING_HOLE_KEY,
// Logic Only
RG_DISTANT_SCARECROW,
RG_STICKS,
@@ -3431,6 +3482,7 @@ typedef enum {
RHT_CAN_BE_FOUND_AT,
RHT_HOARDS,
// Junk
+ RHT_JUNK01,
RHT_JUNK02,
RHT_JUNK03,
RHT_JUNK04,
@@ -3501,141 +3553,6 @@ typedef enum {
RHT_JUNK69,
RHT_JUNK70,
RHT_JUNK71,
- RHT_JUNK72,
- RHT_JUNK73,
- RHT_JUNK74,
- RHT_JUNK75,
- RHT_JUNK76,
- RHT_JUNK77,
- RHT_JUNK78,
- RHT_JUNK79,
- RHT_JUNK80,
- RHT_JUNK81,
- RHT_JUNK_WTC_1,
- RHT_JUNK_WTC_2,
- RHT_JUNK_WTC_3,
- RHT_JUNK_WTC_4,
- RHT_JUNK_WTC_5,
- RHT_JUNK_WTC_6,
- RHT_JUNK_WTC_7,
- RHT_JUNK_WTC_8,
- RHT_JUNK_WTC_9,
- RHT_JUNK_WTC_10,
- RHT_JUNK_WTC_11,
- RHT_JUNK_WTC_12,
- RHT_JUNK_SEI_1,
- RHT_JUNK_SEI_2,
- RHT_JUNK_SEI_3,
- RHT_JUNK_SEI_4,
- RHT_JUNK_SEI_5,
- RHT_JUNK_SEI_6,
- RHT_JUNK_SEI_7,
- RHT_JUNK_SEI_8,
- RHT_JUNK_SEI_9,
- RHT_JUNK_SEI_10,
- RHT_JUNK_SEI_11,
- RHT_JUNK_SEI_12,
- RHT_JUNK_SEI_13,
- RHT_JUNK_SEI_14,
- RHT_JUNK_SEI_15,
- RHT_JUNK_SEI_16,
- RHT_JUNK_SEI_17,
- RHT_JUNK_SEI_18,
- RHT_JUNK_SEI_19,
- RHT_JUNK_SEI_20,
- RHT_JUNK_SEI_21,
- RHT_JUNK_SEI_22,
- RHT_JUNK_SEI_23,
- RHT_JUNK_SEI_24,
- RHT_JUNK_SEI_25,
- RHT_JUNK_SEI_26,
- RHT_JUNK_SEI_27,
- RHT_JUNK_SEI_28,
- RHT_JUNK_SEI_29,
- RHT_JUNK_OTR_MEANS_1,
- RHT_JUNK_OTR_MEANS_2,
- RHT_JUNK_OTR_MEANS_3,
- RHT_JUNK_OTR_MEANS_4,
- RHT_JUNK_OTR_MEANS_5,
- RHT_JUNK_OTR_MEANS_6,
- RHT_JUNK_OTR_MEANS_7,
- RHT_JUNK_OTR_MEANS_8,
- RHT_JUNK_OTR_MEANS_9,
- RHT_JUNK_OTR_MEANS_10,
- RHT_JUNK_OTR_MEANS_11,
- RHT_JUNK_OTR_MEANS_12,
- RHT_JUNK_OTR_MEANS_13,
- RHT_JUNK_OTR_MEANS_14,
- RHT_JUNK_OTR_MEANS_15,
- RHT_JUNK_OTR_MEANS_16,
- RHT_JUNK_OTR_MEANS_17,
- RHT_JUNK_OTR_MEANS_18,
- RHT_JUNK_OTR_MEANS_19,
- RHT_JUNK_OTR_MEANS_20,
- RHT_JUNK_OTR_MEANS_21,
- RHT_JUNK_OTR_MEANS_22,
- RHT_JUNK_OTR_MEANS_23,
- RHT_JUNK_OTR_MEANS_24,
- RHT_JUNK_OTR_MEANS_25,
- RHT_JUNK_OTR_MEANS_26,
- RHT_JUNK_OTR_MEANS_27,
- RHT_JUNK_OTR_MEANS_28,
- RHT_JUNK_OTR_MEANS_29,
- RHT_JUNK_OTR_MEANS_30,
- RHT_JUNK_MISC_1,
- RHT_JUNK_MISC_2,
- RHT_JUNK_MISC_3,
- RHT_JUNK_MISC_4,
- RHT_JUNK_MISC_5,
- RHT_JUNK_MISC_6,
- RHT_JUNK_MISC_7,
- RHT_JUNK_MISC_8,
- RHT_JUNK_MISC_9,
- RHT_JUNK_MISC_10,
- RHT_JUNK_MISC_11,
- RHT_JUNK_MISC_12,
- RHT_JUNK_MISC_13,
- RHT_JUNK_MISC_14,
- RHT_JUNK_MISC_15,
- RHT_JUNK_MISC_16,
- RHT_JUNK_MISC_17,
- RHT_JUNK_SG_1,
- RHT_JUNK_SG_2,
- RHT_JUNK_SG_3,
- RHT_JUNK_SG_4,
- RHT_JUNK_SG_5,
- RHT_JUNK_SG_6,
- RHT_JUNK_SG_7,
- RHT_JUNK_SG_8,
- RHT_JUNK_CREW_1,
- RHT_JUNK_CREW_2,
- RHT_JUNK_CREW_3,
- RHT_JUNK_CREW_4,
- RHT_JUNK_CREW_5,
- RHT_JUNK_CREW_6,
- RHT_JUNK_CREW_7,
- RHT_JUNK_CREW_8,
- RHT_JUNK_CREW_9,
- RHT_JUNK_CREW_10,
- RHT_JUNK_CREW_11,
- RHT_JUNK_CREW_12,
- RHT_JUNK_CREW_13,
- RHT_JUNK_CREW_14,
- RHT_JUNK_CREW_15,
- RHT_JUNK_CREW_16,
- RHT_JUNK_CREW_17,
- RHT_JUNK_CREW_18,
- RHT_JUNK_CREW_19,
- RHT_JUNK_CREW_20,
- RHT_JUNK_CREW_21,
- RHT_JUNK_CREW_22,
- RHT_JUNK_CREW_23,
- RHT_JUNK_CREW_24,
- RHT_JUNK_CREW_25,
- RHT_JUNK_CREW_26,
- RHT_JUNK_CREW_27,
- RHT_JUNK_CREW_28,
- RHT_JUNK_CREW_29,
// Locations
RHT_LINKS_POCKET,
RHT_QUEEN_GOHMA,
@@ -4614,6 +4531,7 @@ typedef enum {
RHT_FISHING_POLE,
RHT_SKELETON_KEY,
RHT_EPONA,
+ RHT_OVERWORLD_KEY,
RHT_HINT_MYSTERIOUS,
RHT_MYSTERIOUS_ITEM,
RHT_MYSTERIOUS_ITEM_CAPITAL,
@@ -4989,8 +4907,11 @@ typedef enum {
RHT_HF_POND_STORMS_FAIRY,
RHT_HF_FENCE_GROTTO_STORMS_FAIRY,
RHT_DMT_FLAG_SUN_FAIRY,
+ RHT_DMT_COW_GROTTO_STORMS_FAIRY,
RHT_LW_SHORTCUT_STORMS_FAIRY,
RHT_GF_KITCHEN_SUN_FAIRY,
+ RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY,
+ RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY,
RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY,
RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY,
RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY,
@@ -5214,7 +5135,6 @@ typedef enum {
RSK_SKIP_EPONA_RACE,
RSK_COMPLETE_MASK_QUEST,
RSK_SKIP_SCARECROWS_SONG,
- RSK_ENABLE_GLITCH_CUTSCENES,
RSK_SKULLS_SUNS_SONG,
RSK_SHUFFLE_ADULT_TRADE,
RSK_SHUFFLE_MERCHANTS,
@@ -5300,6 +5220,7 @@ typedef enum {
RSK_SHUFFLE_DEKU_NUT_BAG,
RSK_SHUFFLE_FREESTANDING,
RSK_SHUFFLE_FAIRIES,
+ RSK_LOCK_OVERWORLD_DOORS,
RSK_MAX
} RandomizerSettingKey;
@@ -5657,7 +5578,6 @@ typedef enum {
// Logic (glitchless/no logic)
typedef enum {
RO_LOGIC_GLITCHLESS,
- RO_LOGIC_GLITCHED,
RO_LOGIC_NO_LOGIC,
RO_LOGIC_VANILLA,
} RandoOptionLogic;
diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
index 02b5c1f9b..b6ef5752c 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
@@ -490,7 +490,7 @@ void CheckTrackerLoadGame(int32_t fileNum) {
}
}
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
- uint8_t startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
+ uint8_t startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
RandomizerCheckArea startingArea;
switch (startingAge) {
case RO_AGE_CHILD:
diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp
index 2da598c74..0d7b1a731 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.cpp
@@ -87,297 +87,297 @@ const EntranceData entranceData[] = {
{ ENTR_HYRULE_FIELD_OWL_DROP, -1, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Owl Flight", "Hyrule Field Owl Drop", ENTRANCE_GROUP_ONE_WAY, ENTRANCE_GROUP_ONE_WAY, ENTRANCE_TYPE_ONE_WAY},
// Kokiri Forest
- { ENTR_LOST_WOODS_BRIDGE_EAST_EXIT, ENTR_KOKIRI_FOREST_LOWER_EXIT, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "Kokiri Forest Lower Exit", "Lost Woods Bridge East Exit", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTR_LOST_WOODS_SOUTH_EXIT, ENTR_KOKIRI_FOREST_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "Kokiri Forest Upper Exit", "Lost Woods South Exit", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTR_LINKS_HOUSE_1, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Link's House", "Link's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_MIDOS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Mido's House", "Mido's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_SARIAS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Saria's House", "Saria's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_TWINS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside House of Twins", "House of Twins", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_KNOW_IT_ALL_BROS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Know-It-All House", "Know-It-All House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_KOKIRI_SHOP_0, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Shop", "KF Shop", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Storms Grotto Exit", "KF Storms Grotto", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTR_DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Oustide Deku Tree", "Deku Tree Entrance", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE, ENTR_LINKS_HOUSE_1, SINGLE_SCENE_INFO(SCENE_LINKS_HOUSE), "Link's House", "KF Outside Link's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
- { ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_MIDOS_HOUSE), "Mido's House", "KF Outside Mido's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
- { ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_SARIAS_HOUSE), "Saria's House", "KF Outside Saria's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
- { ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE, ENTR_TWINS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_TWINS_HOUSE), "House of Twins", "KF Outside House of Twins", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
- { ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_KNOW_IT_ALL_BROS_HOUSE), "Know-It-All House", "KF Outside Know-It-All House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
- { ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, ENTR_KOKIRI_SHOP_0, SINGLE_SCENE_INFO(SCENE_KOKIRI_SHOP), "KF Shop", "KF Outside Shop", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
- { ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "KF Storms Grotto", "KF Storms Grotto Exit", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest"},
- { ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, ENTR_DEKU_TREE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Entrance", "KF Oustide Deku Tree", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""},
- { ENTR_DEKU_TREE_BOSS_ENTRANCE, ENTR_DEKU_TREE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Boss Door", "Gohma", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_DEKU_TREE_BOSS_DOOR, ENTR_DEKU_TREE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Boss Door", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Blue Warp", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
+ { ENTR_LOST_WOODS_BRIDGE_EAST_EXIT, ENTR_KOKIRI_FOREST_LOWER_EXIT, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "Kokiri Forest Lower Exit", "Lost Woods Bridge East Exit", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTR_LOST_WOODS_SOUTH_EXIT, ENTR_KOKIRI_FOREST_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "Kokiri Forest Upper Exit", "Lost Woods South Exit", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTR_LINKS_HOUSE_1, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Link's House Entry", "Link's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_MIDOS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Mido's House Entry", "Mido's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_SARIAS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Saria's House Entry", "Saria's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_TWINS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF House of Twins Entry", "House of Twins", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_KNOW_IT_ALL_BROS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Know-It-All House Entry", "Know-It-All House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_KOKIRI_SHOP_0, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Shop Entry", "Kokiri Shop", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Storms Grotto Entry", "KF Storms Grotto", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTR_DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Deku Tree", "Deku Tree Entrance", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE, ENTR_LINKS_HOUSE_1, SINGLE_SCENE_INFO(SCENE_LINKS_HOUSE), "Link's House", "KF Link's House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_MIDOS_HOUSE), "Mido's House", "KF Mido's House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_SARIAS_HOUSE), "Saria's House", "KF Saria's House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE, ENTR_TWINS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_TWINS_HOUSE), "House of Twins", "KF House of Twins Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_KNOW_IT_ALL_BROS_HOUSE), "Know-It-All House", "KF Know-It-All House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, ENTR_KOKIRI_SHOP_0, SINGLE_SCENE_INFO(SCENE_KOKIRI_SHOP), "Kokiri Shop", "KF Shop Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "KF Storms Grotto", "KF Storms Grotto Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, ENTR_DEKU_TREE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Entrance", "KF Outside Deku Tree", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""},
+ { ENTR_DEKU_TREE_BOSS_ENTRANCE, ENTR_DEKU_TREE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Boss Door", "Gohma", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_DEKU_TREE_BOSS_DOOR, ENTR_DEKU_TREE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Boss Door", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma Blue Warp", "Deku Tree Blue Warp", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Lost Woods
- { ENTR_KOKIRI_FOREST_LOWER_EXIT, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge East Exit", "Kokiri Forest Lower Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTR_HYRULE_FIELD_WOODED_EXIT, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge West Exit", "Hyrule Field Wooded Path", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lw,hf"},
- { ENTR_KOKIRI_FOREST_UPPER_EXIT, ENTR_LOST_WOODS_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW South Exit", "KF Upper Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTR_GORON_CITY_TUNNEL_SHORTCUT, ENTR_LOST_WOODS_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Tunnel Shortcut", "GC Tunnel Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "lw,gc"},
- { ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Underwater Shortcut", "ZR Underwater Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, ENTR_LOST_WOODS_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Exit", "SFM South Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Tunnel Grotto", "LW Near Shortcuts Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Exit Grotto", "LW Scrubs Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Meadow Grotto", "Deku Theater", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage", 1},
- { ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "LW Near Shortcuts Grotto", "LW Tunnel Grotto Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), {{ SCENE_GROTTOS, 0x07 }}, "LW Scrubs Grotto", "LW North Grotto Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), {{ SCENE_GROTTOS, 0x0C }}, "Deku Theater", "LW Meadow Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage"},
+ { ENTR_KOKIRI_FOREST_LOWER_EXIT, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge East Exit", "Kokiri Forest Lower Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTR_HYRULE_FIELD_WOODED_EXIT, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge West Exit", "Hyrule Field Wooded Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lw,hf"},
+ { ENTR_KOKIRI_FOREST_UPPER_EXIT, ENTR_LOST_WOODS_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods South Exit", "Kokiri Forest Upper Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTR_GORON_CITY_TUNNEL_SHORTCUT, ENTR_LOST_WOODS_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Tunnel Shortcut", "Goron City Tunnel Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "lw,gc"},
+ { ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Underwater Shortcut", "Zora's River Underwater Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, ENTR_LOST_WOODS_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods North Exit", "Sacred Forest Meadow South Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Shortcuts Grotto Entry", "LW Tunnel Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Grotto Entry", "LW Scrubs Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Meadow Grotto Entry", "Deku Theater", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage", 1},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "LW Tunnel Grotto", "LW Shortcuts Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), {{ SCENE_GROTTOS, 0x07 }}, "LW Scrubs Grotto", "LW North Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), {{ SCENE_GROTTOS, 0x0C }}, "Deku Theater", "LW Meadow Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage"},
// Sacred Forest Meadow
- { ENTR_LOST_WOODS_NORTH_EXIT, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM South Exit", "LW North Exit", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Outside Wolfos Grotto", "SFM Wolfos Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Outside Fairy Grotto", "SFM Fairy Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Outside Storms Grotto", "SFM Storms Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
- { ENTR_FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Outside Forest Temple", "Forest Temple Entrance", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), {{ SCENE_GROTTOS, 0x08 }}, "SFM Wolfos Grotto", "SFM Outside Wolfos Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
- { ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "SFM Fairy Grotto", "SFM Outside Fairy Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
- { ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "SFM Storms Grotto", "SFM Outside Storms Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs"},
- { ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, ENTR_FOREST_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Entrance", "SFM Outside Forest Temple", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
- { ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_FOREST_TEMPLE_BOSS_DOOR, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Blue Warp", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
+ { ENTR_LOST_WOODS_NORTH_EXIT, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "Sacred Forest Meadow South Exit", "Lost Woods North Exit", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Wolfos Grotto Entry", "SFM Wolfos Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Fairy Grotto Entry", "SFM Fairy Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Storms Grotto Entry", "SFM Storms Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTR_FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "Sacred Forest Meadow Outside Forest Temple", "Forest Temple Entrance", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), {{ SCENE_GROTTOS, 0x08 }}, "SFM Wolfos Grotto", "SFM Wolfos Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "SFM Fairy Grotto", "SFM Fairy Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "SFM Storms Grotto", "SFM Storms Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs"},
+ { ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, ENTR_FOREST_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Entrance", "Sacred Forest Meadow Outside Forest Temple", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
+ { ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_FOREST_TEMPLE_BOSS_DOOR, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon Blue Warp", "Forest Temple Blue Warp", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Kakariko Village
- { ENTR_HYRULE_FIELD_STAIRS_EXIT, ENTR_KAKARIKO_VILLAGE_FRONT_GATE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Front Gate", "Hyrule Field Stairs Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_GRAVEYARD_ENTRANCE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Southeast Exit", "Graveyard Entrance", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT, ENTR_KAKARIKO_VILLAGE_GUARD_GATE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Guard Gate Exit", "Death Mountain Trail Bottom Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Boss House", "Carpenter Boss House", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_HOUSE_OF_SKULLTULA_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Skulltula House", "House of Skulltula", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_IMPAS_HOUSE_FRONT, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Impa's House Front", "Impa's House Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_IMPAS_HOUSE_BACK, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Impa's House Back", "Impa's House Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "cow", 1},
- { ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Windmill", "Windmill", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_SHOOTING_GALLERY_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Shooting Gallery", "Kak Shooting Gallery", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "adult", 1},
- { ENTR_POTION_SHOP_GRANNY_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Granny's Potion Shop", "Granny's Potion Shop", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_BAZAAR_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Bazaar", "Kak Bazaar", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "shop", 1},
- { ENTR_POTION_SHOP_KAKARIKO_FRONT, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Potion Shop Front", "Kak Potion Shop Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_POTION_SHOP_KAKARIKO_BACK, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside Potion Shop Back", "Kak Potion Shop Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Open Grotto Exit", "Kak Open Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET), SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Redead Grotto Exit", "Kak Redead Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside BotW", "Bottom of the Well Entrance", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw", 1},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0, SINGLE_SCENE_INFO(SCENE_KAKARIKO_CENTER_GUEST_HOUSE), "Carpenter Boss House", "Kak Outside Boss House", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE, ENTR_HOUSE_OF_SKULLTULA_0, SINGLE_SCENE_INFO(SCENE_HOUSE_OF_SKULLTULA), "House of Skulltula", "Kak Outside Skulltula House", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT, ENTR_IMPAS_HOUSE_FRONT, SINGLE_SCENE_INFO(SCENE_IMPAS_HOUSE), "Impa's House Front", "Kak Outside Impa's House Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK, SINGLE_SCENE_INFO(SCENE_IMPAS_HOUSE), "Impa's House Back", "Kak Outside Impa's House Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "cow"},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL, SINGLE_SCENE_INFO(SCENE_WINDMILL_AND_DAMPES_GRAVE), "Windmill", "Kak Outside Windmill", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0, {{ SCENE_SHOOTING_GALLERY, 0x00 }}, "Kak Shooting Gallery", "Kak Outside Shooting Gallery", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY, ENTR_POTION_SHOP_GRANNY_0, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_GRANNY), "Granny's Potion Shop", "Kak Outside Granny's Potion Shop", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR, ENTR_BAZAAR_0, {{ SCENE_BAZAAR, 0x00 }}, "Kak Bazaar", "Kak Outside Bazaar", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "shop"},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_KAKARIKO), "Kak Potion Shop Front", "Kak Outside Potion Shop Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_KAKARIKO), "Kak Potion Shop Back", "Kak Outside Potion Shop Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
- { ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "Kak Open Grotto", "Kak Open Grotto Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET), {{ SCENE_GROTTOS, 0x03 }}, "Kak Redead Grotto", "Kak Redead Grotto Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
- { ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, SINGLE_SCENE_INFO(SCENE_BOTTOM_OF_THE_WELL), "Bottom of the Well Entrance", "Kak Outside BotW", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw"},
+ { ENTR_HYRULE_FIELD_STAIRS_EXIT, ENTR_KAKARIKO_VILLAGE_FRONT_GATE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Front Gate", "Hyrule Field Stairs Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_GRAVEYARD_ENTRANCE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Southeast Exit", "Graveyard Entrance", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT, ENTR_KAKARIKO_VILLAGE_GUARD_GATE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Guard Gate Exit", "Death Mountain Trail Bottom Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Boss House Entry", "Carpenter Boss House", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_HOUSE_OF_SKULLTULA_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Skulltula House Entry", "House of Skulltula", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_IMPAS_HOUSE_FRONT, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Impa's House Front Entry", "Impa's House Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_IMPAS_HOUSE_BACK, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Impa's House Back Entry", "Impa's House Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "cow", 1},
+ { ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Windmill Entry", "Windmill", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_SHOOTING_GALLERY_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Shooting Gallery Entry", "Kak Shooting Gallery", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "adult", 1},
+ { ENTR_POTION_SHOP_GRANNY_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Granny's Potion Shop Entry", "Granny's Potion Shop", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_BAZAAR_0, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Bazaar Entry", "Kak Bazaar", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "shop", 1},
+ { ENTR_POTION_SHOP_KAKARIKO_FRONT, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Potion Shop Front Entry", "Kak Potion Shop Front", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_POTION_SHOP_KAKARIKO_BACK, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Potion Shop Back Entry", "Kak Potion Shop Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Open Grotto Entry", "Kak Open Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET), SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Center Grotto Entry", "Kak Redead Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Outside the Well", "Bottom of the Well Entrance", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw", 1},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0, SINGLE_SCENE_INFO(SCENE_KAKARIKO_CENTER_GUEST_HOUSE), "Carpenter Boss House", "Kak Boss House Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE, ENTR_HOUSE_OF_SKULLTULA_0, SINGLE_SCENE_INFO(SCENE_HOUSE_OF_SKULLTULA), "House of Skulltula", "Kak Skulltula House Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT, ENTR_IMPAS_HOUSE_FRONT, SINGLE_SCENE_INFO(SCENE_IMPAS_HOUSE), "Impa's House Front", "Kak Impa's House Front Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK, SINGLE_SCENE_INFO(SCENE_IMPAS_HOUSE), "Impa's House Back", "Kak Impa's House Back Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "cow"},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL, SINGLE_SCENE_INFO(SCENE_WINDMILL_AND_DAMPES_GRAVE), "Windmill", "Kak Windmill Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0, {{ SCENE_SHOOTING_GALLERY, 0x00 }}, "Kak Shooting Gallery", "Kak Shooting Gallery Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY, ENTR_POTION_SHOP_GRANNY_0, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_GRANNY), "Granny's Potion Shop", "Kak Granny's Potion Shop Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR, ENTR_BAZAAR_0, {{ SCENE_BAZAAR, 0x00 }}, "Kak Bazaar", "Kak Bazaar Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "shop"},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_KAKARIKO), "Kak Potion Shop Front", "Kak Potion Shop Front Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_KAKARIKO), "Kak Potion Shop Back", "Kak Potion Shop Back Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "Kak Open Grotto", "Kak Open Grotto Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET), {{ SCENE_GROTTOS, 0x03 }}, "Kak Redead Grotto", "Kak Center Grotto Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, SINGLE_SCENE_INFO(SCENE_BOTTOM_OF_THE_WELL), "Bottom of the Well Entrance", "Kakariko Outside the Well", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw"},
// The Graveyard
- { ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT, ENTR_GRAVEYARD_ENTRANCE, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "Graveyard Entrance", "Kakariko Southeast Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_GRAVEKEEPERS_HUT_0, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Outside Dampe's Hut", "Dampe's Hut", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Near-Hut Grave Exit", "Shield Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTR_REDEAD_GRAVE_0, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Near-Tomb Grave Exit", "Heart Piece Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTR_ROYAL_FAMILYS_TOMB_0, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Royal Family's Tomb Exit", "Royal Family's Tomb", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Near-Ledge Grave Exit", "Dampe's Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "race", 1},
- { ENTR_SHADOW_TEMPLE_ENTRANCE, ENTR_GRAVEYARD_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "Graveyard Outside Temple", "Shadow Temple Entrance", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT, ENTR_GRAVEKEEPERS_HUT_0, SINGLE_SCENE_INFO(SCENE_GRAVEKEEPERS_HUT), "Dampe's Hut", "GY Outside Dampe's Hut", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_INTERIOR},
- { ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0, SINGLE_SCENE_INFO(SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN), "Shield Grave", "GY Near-Hut Grave Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
- { ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT, ENTR_REDEAD_GRAVE_0, SINGLE_SCENE_INFO(SCENE_REDEAD_GRAVE), "Heart Piece Grave", "GY Near-Tomb Grave Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
- { ENTR_GRAVEYARD_ROYAL_TOMB_EXIT, ENTR_ROYAL_FAMILYS_TOMB_0, SINGLE_SCENE_INFO(SCENE_ROYAL_FAMILYS_TOMB), "Royal Family's Tomb", "GY Royal Family's Tomb Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
- { ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE, SINGLE_SCENE_INFO(SCENE_WINDMILL_AND_DAMPES_GRAVE), "Dampe's Grave", "GY Near-Ledge Grave Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "race"},
- { ENTR_GRAVEYARD_OUTSIDE_TEMPLE, ENTR_SHADOW_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Entrance", "Graveyard Outside Temple", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON},
- { ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, ENTR_SHADOW_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Boss Door", "Bongo-Bongo", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_SHADOW_TEMPLE_BOSS_DOOR, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Boss Door", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Blue Warp", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
+ { ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT, ENTR_GRAVEYARD_ENTRANCE, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "Graveyard Entrance", "Kakariko Southeast Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_GRAVEKEEPERS_HUT_0, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Dampe's Hut Entry", "Dampe's Hut", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Near-Hut Grave Entry", "Shield Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTR_REDEAD_GRAVE_0, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Near-Tomb Grave Entry", "Heart Piece Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTR_ROYAL_FAMILYS_TOMB_0, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Royal Family's Tomb Entry", "Royal Family's Tomb", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "GY Near-Ledge Grave Entry", "Dampe's Grave", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "race", 1},
+ { ENTR_SHADOW_TEMPLE_ENTRANCE, ENTR_GRAVEYARD_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "Graveyard Outside Temple", "Shadow Temple Entrance", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT, ENTR_GRAVEKEEPERS_HUT_0, SINGLE_SCENE_INFO(SCENE_GRAVEKEEPERS_HUT), "Dampe's Hut", "GY Dampe's Hut Entry", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0, SINGLE_SCENE_INFO(SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN), "Shield Grave", "GY Near-Hut Grave Entry", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
+ { ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT, ENTR_REDEAD_GRAVE_0, SINGLE_SCENE_INFO(SCENE_REDEAD_GRAVE), "Heart Piece Grave", "GY Near-Tomb Grave Entry", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
+ { ENTR_GRAVEYARD_ROYAL_TOMB_EXIT, ENTR_ROYAL_FAMILYS_TOMB_0, SINGLE_SCENE_INFO(SCENE_ROYAL_FAMILYS_TOMB), "Royal Family's Tomb", "GY Royal Family's Tomb Entry", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO},
+ { ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE, SINGLE_SCENE_INFO(SCENE_WINDMILL_AND_DAMPES_GRAVE), "Dampe's Grave", "GY Near-Ledge Grave Entry", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_GROTTO, "race"},
+ { ENTR_GRAVEYARD_OUTSIDE_TEMPLE, ENTR_SHADOW_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Entrance", "Graveyard Outside Temple", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON},
+ { ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, ENTR_SHADOW_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Boss Door", "Bongo-Bongo", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_SHADOW_TEMPLE_BOSS_DOOR, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Boss Door", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo Blue Warp", "Shadow Temple Blue Warp", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Death Mountain Trail
- { ENTR_GORON_CITY_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Middle Exit", "Goron City Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
- { ENTR_KAKARIKO_VILLAGE_GUARD_GATE, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Bottom Exit", "Kakariko Guard Gate Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Top Exit", "Death Mountain Crater Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Great Fairy Exit", "DMT Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Rock Circle Grotto Exit", "DMT Storms Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Boulder Grotto Exit", "DMT Cow Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTR_DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Outside Dodongo's Cavern", "Dodongo's Cavern Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
- { ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x00 }}, "DMT Great Fairy Fountain", "DMT Great Fairy Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR},
- { ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMT Storms Grotto", "DMT Rock Circle Grotto Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), {{ SCENE_GROTTOS, 0x0D }}, "DMT Cow Grotto", "DMT Boulder Grotto Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO},
- { ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, ENTR_DODONGOS_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Entrance", "DMT Outside Dodongo's Cavern", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
- { ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, ENTR_DODONGOS_CAVERN_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
- { ENTR_DODONGOS_CAVERN_BOSS_DOOR, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
- { ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_ONE_WAY, "dc,bw", 1},
+ { ENTR_GORON_CITY_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Middle Exit", "Goron City Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
+ { ENTR_KAKARIKO_VILLAGE_GUARD_GATE, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Bottom Exit", "Kakariko Guard Gate Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Top Exit", "Death Mountain Crater Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Great Fairy Entry", "DMT Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Rock Circle Grotto Entry", "DMT Storms Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Boulder Grotto Entry", "DMT Cow Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTR_DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Outside Dodongo's Cavern", "Dodongo's Cavern Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
+ { ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x00 }}, "DMT Great Fairy Fountain", "DMT Great Fairy Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMT Storms Grotto", "DMT Rock Circle Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), {{ SCENE_GROTTOS, 0x0D }}, "DMT Cow Grotto", "DMT Boulder Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO},
+ { ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, ENTR_DODONGOS_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Entrance", "Death Mountain Trail Outside Dodongo's Cavern", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
+ { ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, ENTR_DODONGOS_CAVERN_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
+ { ENTR_DODONGOS_CAVERN_BOSS_DOOR, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
+ { ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo Blue Warp", "Dodongo's Cavern Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_ONE_WAY, "dc,bw", 1},
// Death Mountain Crater
- { ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Bridge Exit", "Goron City Darunia's Room Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
+ { ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Bridge Exit", "Goron City Darunia's Room Backdoor", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Upper Exit", "Death Mountain Trail Top Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Great Fairy Exit", "DMC Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Upper Grotto Exit", "DMC Upper Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Hammer Grotto Exit", "DMC Hammer Scrubs Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Great Fairy Entry", "DMC Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Upper Grotto Entry", "DMC Upper Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Hammer Grotto Entry", "DMC Scrubs Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Outside Temple", "Fire Temple Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x01 }}, "DMC Great Fairy Fountain", "DMC Great Fairy Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR},
- { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMC Upper Grotto", "DMC Upper Grotto Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "DMC Hammer Grotto", "DMC Hammer Grotto Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"},
+ { ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x01 }}, "DMC Great Fairy Fountain", "DMC Great Fairy Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMC Upper Grotto", "DMC Upper Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "DMC Scrubs Grotto", "DMC Hammer Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, ENTR_FIRE_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Entrance", "Death Mountain Crater Outside Temple", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON},
{ ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, ENTR_FIRE_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Boss Door", "Volvagia", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_FIRE_TEMPLE_BOSS_DOOR, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
+ { ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia Blue Warp", "Fire Temple Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Goron City
- { ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, ENTR_GORON_CITY_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Upper Exit", "Death Mountain Trail Middle Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"},
- { ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Darunia's Room Exit", "Death Mountain Crater Bridge Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD, "gc"},
- { ENTR_LOST_WOODS_TUNNEL_SHORTCUT, ENTR_GORON_CITY_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Tunnel Shortcut", "LW Tunnel Shortcut", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "gc,lw"},
- { ENTR_GORON_SHOP_0, ENTR_GORON_CITY_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Outside Shop", "Goron Shop", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Lava Grotto Exit", "Goron City Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1},
- { ENTR_GORON_CITY_OUTSIDE_SHOP, ENTR_GORON_SHOP_0, SINGLE_SCENE_INFO(SCENE_GORON_SHOP), "Goron Shop", "GC Outside Shop", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "Goron City Grotto", "GC Lava Grotto Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"},
+ { ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, ENTR_GORON_CITY_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Upper Exit", "Death Mountain Trail Middle Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"},
+ { ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Darunia's Room Backdoor", "Death Mountain Crater Bridge Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD, "gc"},
+ { ENTR_LOST_WOODS_TUNNEL_SHORTCUT, ENTR_GORON_CITY_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Tunnel Shortcut", "Lost Woods Tunnel Shortcut", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "gc,lw"},
+ { ENTR_GORON_SHOP_0, ENTR_GORON_CITY_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Shop Entry", "Goron Shop", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Lava Grotto Entry", "GC Scrubs Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1},
+ { ENTR_GORON_CITY_OUTSIDE_SHOP, ENTR_GORON_SHOP_0, SINGLE_SCENE_INFO(SCENE_GORON_SHOP), "Goron Shop", "GC Shop Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "GC Scrubs Grotto", "GC Lava Grotto Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"},
// Zora's River
- { ENTR_HYRULE_FIELD_RIVER_EXIT, ENTR_ZORAS_RIVER_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River West Exit", "Hyrule Field River Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Underwater Shortcut", "LW Underwater Shortcut", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
- { ENTR_ZORAS_DOMAIN_ENTRANCE, ENTR_ZORAS_RIVER_WATERFALL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Waterfall Exit", "Zora's Domain Entrance", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
- { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Rock Circle Grotto Exit", "ZR Storms Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Boulder Grotto Exit", "ZR Fairy Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Open Grotto Exit", "ZR Open Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "ZR Storms Grotto", "ZR Rock Circle Grotto Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZR Fairy Grotto", "ZR Raised Boulder Grotto Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO},
- { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "ZR Open Grotto", "ZR Raised Open Grotto Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTR_HYRULE_FIELD_RIVER_EXIT, ENTR_ZORAS_RIVER_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Lower Exit", "Hyrule Field River Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Underwater Shortcut", "Lost Woods Underwater Shortcut", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
+ { ENTR_ZORAS_DOMAIN_ENTRANCE, ENTR_ZORAS_RIVER_WATERFALL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Waterfall Exit", "Zora's Domain Entrance", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Rock Circle Grotto Entry", "ZR Storms Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Boulder Grotto Entry", "ZR Fairy Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Open Grotto Entry", "ZR Open Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "ZR Storms Grotto", "ZR Rock Circle Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZR Fairy Grotto", "ZR Raised Boulder Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "ZR Open Grotto", "ZR Raised Open Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest"},
// Zora's Domain
- { ENTR_ZORAS_RIVER_WATERFALL_EXIT, ENTR_ZORAS_DOMAIN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Entrance", "Zora's River Waterfall Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Underwater Shortcut", "LH Underwater Shortcut", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
- { ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain King Zora Exit", "Zora's Fountain Tunnel Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_ZORA_SHOP_0, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Outside Shop", "Zora Shop", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Island Grotto Exit", "ZD Storms Grotto", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy", 1},
- { ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, ENTR_ZORA_SHOP_0, SINGLE_SCENE_INFO(SCENE_ZORA_SHOP), "Zora Shop", "ZD Outside Shop", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR},
- { ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZD Storms Grotto", "ZD Island Grotto Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy"},
+ { ENTR_ZORAS_RIVER_WATERFALL_EXIT, ENTR_ZORAS_DOMAIN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Entrance", "Zora's River Waterfall Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Underwater Shortcut", "Lake Hylia Underwater Shortcut", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
+ { ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Behind King Zora", "Zora's Fountain Tunnel Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_ZORA_SHOP_0, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Shop Entry", "Zora Shop", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Island Grotto Entry", "ZD Storms Grotto", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy", 1},
+ { ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, ENTR_ZORA_SHOP_0, SINGLE_SCENE_INFO(SCENE_ZORA_SHOP), "Zora Shop", "ZD Shop Entry", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZD Storms Grotto", "ZD Island Grotto Entry", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy"},
// Zora's Fountain
- { ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "Zora's Fountain Tunnel Exit", "Zora's Domain King Zora Exit", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "ZF Outside Great Fairy", "ZF Great Fairy Fountain", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_JABU_JABU_ENTRANCE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "ZF Outside Jabu Jabu", "Jabu Jabu's Belly Entrance", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_ICE_CAVERN_ENTRANCE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "ZF Outside Ice Cavern", "Ice Cavern Entrance", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x00 }}, "ZF Great Fairy Fountain", "ZF Outside Great Fairy", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_INTERIOR},
- { ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, ENTR_JABU_JABU_ENTRANCE, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Entrance", "ZF Outside Jabu Jabu", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
- { ENTR_JABU_JABU_BOSS_ENTRANCE, ENTR_JABU_JABU_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Boss Door", "Barinade", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_JABU_JABU_BOSS_DOOR, ENTR_JABU_JABU_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Boss Door", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Blue Warp", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
- { ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN, ENTR_ICE_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ICE_CAVERN), "Ice Cavern Entrance", "ZF Outside Ice Cavern", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
+ { ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "Zora's Fountain Tunnel Exit", "Zora's Domain Behind King Zora", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "ZF Great Fairy Entry", "ZF Great Fairy Fountain", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_JABU_JABU_ENTRANCE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "Zora's Fountain Outside Jabu Jabu", "Jabu Jabu's Belly Entrance", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_ICE_CAVERN_ENTRANCE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "Zora's Fountain Outside Ice Cavern", "Ice Cavern Entrance", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x00 }}, "ZF Great Fairy Fountain", "ZF Great Fairy Entry", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, ENTR_JABU_JABU_ENTRANCE, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Entrance", "Zora's Fountain Outside Jabu Jabu", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
+ { ENTR_JABU_JABU_BOSS_ENTRANCE, ENTR_JABU_JABU_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Boss Door", "Barinade", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_JABU_JABU_BOSS_DOOR, ENTR_JABU_JABU_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Boss Door", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
+ { ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade Blue Warp", "Jabu Jabu's Belly Blue Warp", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
+ { ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN, ENTR_ICE_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ICE_CAVERN), "Ice Cavern Entrance", "Zora's Fountain Outside Ice Cavern", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
// Hyrule Field
- { ENTR_LOST_WOODS_BRIDGE_WEST_EXIT, ENTR_HYRULE_FIELD_WOODED_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Wooded Exit", "Lost Woods Bridge West Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "hf,lw"},
- { ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Drawbridge Exit", "Market Entrance South Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_LON_LON_RANCH_ENTRANCE, ENTR_HYRULE_FIELD_CENTER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Center Exit", "Lon Lon Ranch Entrance", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_OVERWORLD, "hf,llr"},
- { ENTR_KAKARIKO_VILLAGE_FRONT_GATE, ENTR_HYRULE_FIELD_STAIRS_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Stairs Exit", "Kakariko Front Gate", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_ZORAS_RIVER_WEST_EXIT, ENTR_HYRULE_FIELD_RIVER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field River Exit", "Zora's River West Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_LAKE_HYLIA_NORTH_EXIT, ENTR_HYRULE_FIELD_FENCE_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Fence Exit", "Lake Hylia North Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "hf,lh"},
- { ENTR_GERUDO_VALLEY_EAST_EXIT, ENTR_HYRULE_FIELD_ROCKY_PATH, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Rocky Path", "Gerudo Valley East Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Near Market Boulder Grotto Exit", "HF Near Market Boulder Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Near Stairs Tree Grotto Exit", "HF Near Stairs Tree Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Northwest Tree Grotto Exit", "HF Tektite Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "water", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Northwest Boulder Grotto Exit", "HF Fairy Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF West Rock Circle Grotto Exit", "HF Cow Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF South Open Grotto Exit", "HF Open Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Fenced Grotto Exit", "HF Fenced Scrub Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Southeast Boulder Grotto Exit", "HF Southeast Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Near Market Boulder Grotto", "HF Near Market Boulder Grotto Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET), {{ SCENE_GROTTOS, 0x01 }}, "HF Near Kak Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET), {{ SCENE_GROTTOS, 0x0B }}, "HF Tektite Grotto", "HF Northwest Tree Grotto Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "water"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "HF Fairy Grotto", "HF Northwest Boulder Grotto Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET), {{ SCENE_GROTTOS, 0x05 }}, "HF Cow Grotto", "Hyrule Field", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Open Grotto", "HF South Open Grotto Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), {{ SCENE_GROTTOS, 0x02 }}, "HF Fenced Scrub Grotto", "HF Fenced Grotto Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "srubs"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Southeast Grotto", "HF Southeast Boulder Grotto Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTR_LOST_WOODS_BRIDGE_WEST_EXIT, ENTR_HYRULE_FIELD_WOODED_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Wooded Exit", "Lost Woods Bridge West Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "hf,lw"},
+ { ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Drawbridge Exit", "Market Entrance South Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_LON_LON_RANCH_ENTRANCE, ENTR_HYRULE_FIELD_CENTER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Center Exit", "Lon Lon Ranch Entrance", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_OVERWORLD, "hf,llr"},
+ { ENTR_KAKARIKO_VILLAGE_FRONT_GATE, ENTR_HYRULE_FIELD_STAIRS_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Stairs Exit", "Kakariko Front Gate", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_ZORAS_RIVER_WEST_EXIT, ENTR_HYRULE_FIELD_RIVER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field River Exit", "Zora's River Lower Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_LAKE_HYLIA_NORTH_EXIT, ENTR_HYRULE_FIELD_FENCE_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Fence Exit", "Lake Hylia North Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "hf,lh"},
+ { ENTR_GERUDO_VALLEY_EAST_EXIT, ENTR_HYRULE_FIELD_ROCKY_PATH, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Rocky Path", "Gerudo Valley East Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Near Market Boulder Grotto Entry", "HF Near Market Boulder Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Near Stairs Tree Grotto Entry", "HF Near Stairs Tree Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Northwest Tree Grotto Entry", "HF Tektite Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "water", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Northwest Boulder Grotto Entry", "HF Fairy Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF West Rock Circle Grotto Entry", "HF Cow Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF South Open Grotto Entry", "HF Open Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Fenced Grotto Entry", "HF Fenced Scrub Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Southeast Boulder Grotto Entry", "HF Southeast Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Near Market Boulder Grotto", "HF Near Market Boulder Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET), {{ SCENE_GROTTOS, 0x01 }}, "HF Near Stairs Tree Grotto", "HF Near Stairs Tree Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "spider"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET), {{ SCENE_GROTTOS, 0x0B }}, "HF Tektite Grotto", "HF Northwest Tree Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "water"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "HF Fairy Grotto", "HF Northwest Boulder Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET), {{ SCENE_GROTTOS, 0x05 }}, "HF Cow Grotto", "HF West Rock Circle Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "webbed"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Open Grotto", "HF South Open Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET), {{ SCENE_GROTTOS, 0x02 }}, "HF Fenced Scrub Grotto", "HF Fenced Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "srubs"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "HF Southeast Grotto", "HF Southeast Boulder Grotto Entry", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest"},
// Lon Lon Ranch
- { ENTR_HYRULE_FIELD_CENTER_EXIT, ENTR_LON_LON_RANCH_ENTRANCE, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "Lon Lon Ranch Entrance", "Hyrule Field Center Exit", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_LON_LON_BUILDINGS_TALONS_HOUSE, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Outside Talon's House", "Talon's House", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "llr", 1},
- { ENTR_STABLE_0, ENTR_LON_LON_RANCH_OUTSIDE_STABLES, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Outside Stables", "LLR Stables", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow", 1},
- { ENTR_LON_LON_BUILDINGS_TOWER, ENTR_LON_LON_RANCH_OUTSIDE_TOWER, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Outside Tower", "LLR Tower", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET), SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Grotto Exit", "LLR Scrubs Grotto", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
- { ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE, {{ SCENE_LON_LON_BUILDINGS, 0x00 }}, "Talon's House", "LLR Outside Talon's House", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "llr"},
- { ENTR_LON_LON_RANCH_OUTSIDE_STABLES, ENTR_STABLE_0, SINGLE_SCENE_INFO(SCENE_STABLE), "LLR Stables", "LLR Outside Stables", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow"},
- { ENTR_LON_LON_RANCH_OUTSIDE_TOWER, ENTR_LON_LON_BUILDINGS_TOWER, {{ SCENE_LON_LON_BUILDINGS, 0x01 }}, "LLR Tower", "Lon Lon Ranch", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LLR Scrubs Grotto", "LLR Grotto Exit", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs"},
+ { ENTR_HYRULE_FIELD_CENTER_EXIT, ENTR_LON_LON_RANCH_ENTRANCE, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "Lon Lon Ranch Entrance", "Hyrule Field Center Exit", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_LON_LON_BUILDINGS_TALONS_HOUSE, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Talon's House Entry", "Talon's House", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "llr", 1},
+ { ENTR_STABLE_0, ENTR_LON_LON_RANCH_OUTSIDE_STABLES, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Stables Entry", "LLR Stables", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow", 1},
+ { ENTR_LON_LON_BUILDINGS_TOWER, ENTR_LON_LON_RANCH_OUTSIDE_TOWER, SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Tower Entry", "LLR Tower", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET), SINGLE_SCENE_INFO(SCENE_LON_LON_RANCH), "LLR Grotto Entry", "LLR Scrubs Grotto", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE, {{ SCENE_LON_LON_BUILDINGS, 0x00 }}, "Talon's House", "LLR Talon's House Entry", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "llr"},
+ { ENTR_LON_LON_RANCH_OUTSIDE_STABLES, ENTR_STABLE_0, SINGLE_SCENE_INFO(SCENE_STABLE), "LLR Stables", "LLR Stables Entry", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow"},
+ { ENTR_LON_LON_RANCH_OUTSIDE_TOWER, ENTR_LON_LON_BUILDINGS_TOWER, {{ SCENE_LON_LON_BUILDINGS, 0x01 }}, "LLR Tower", "LLR Tower Entry", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_INTERIOR, "cow"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LLR Scrubs Grotto", "LLR Grotto Entry", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs"},
// Lake Hylia
- { ENTR_HYRULE_FIELD_FENCE_EXIT, ENTR_LAKE_HYLIA_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia North Exit", "Hyrule Field Fenced Exit", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lh"},
- { ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Underwater Shortcut", "ZD Underwater Shortcut", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD, "lh"},
- { ENTR_LAKESIDE_LABORATORY_0, ENTR_LAKE_HYLIA_OUTSIDE_LAB, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Outside Lab", "LH Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
- { ENTR_FISHING_POND_0, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Outside Fishing Pond", "Fishing Pond", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Grave Grotto Exit", "LH Grotto", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
- { ENTR_WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia Outside Temple", "Water Temple Entrance", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
- { ENTR_LAKE_HYLIA_OUTSIDE_LAB, ENTR_LAKESIDE_LABORATORY_0, SINGLE_SCENE_INFO(SCENE_LAKESIDE_LABORATORY), "LH Lab", "LH Outside Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
- { ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, ENTR_FISHING_POND_0, SINGLE_SCENE_INFO(SCENE_FISHING_POND), "Fishing Pond", "LH Outside Fishing Pond", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LH Grotto", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "lh,scrubs"},
- { ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, ENTR_WATER_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Entrance", "Lake Hylia Outside Temple", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
- { ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
- { ENTR_WATER_TEMPLE_BOSS_DOOR, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
- { ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Blue Warp", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_ONE_WAY, "lh,bw", 1},
+ { ENTR_HYRULE_FIELD_FENCE_EXIT, ENTR_LAKE_HYLIA_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia North Exit", "Hyrule Field Fence Exit", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lh"},
+ { ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia Underwater Shortcut", "Zora's Domain Underwater Shortcut", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD, "lh"},
+ { ENTR_LAKESIDE_LABORATORY_0, ENTR_LAKE_HYLIA_OUTSIDE_LAB, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Lab Entry", "LH Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
+ { ENTR_FISHING_POND_0, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Fishing Pond Entry", "Fishing Pond", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Grave Grotto Entry", "LH Grotto", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTR_WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia Outside Temple", "Water Temple Entrance", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
+ { ENTR_LAKE_HYLIA_OUTSIDE_LAB, ENTR_LAKESIDE_LABORATORY_0, SINGLE_SCENE_INFO(SCENE_LAKESIDE_LABORATORY), "LH Lab", "LH Lab Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
+ { ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, ENTR_FISHING_POND_0, SINGLE_SCENE_INFO(SCENE_FISHING_POND), "Fishing Pond", "LH Fishing Pond Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LH Grotto", "LH Grave Grotto Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "lh,scrubs"},
+ { ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, ENTR_WATER_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Entrance", "Lake Hylia Outside Temple", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
+ { ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
+ { ENTR_WATER_TEMPLE_BOSS_DOOR, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
+ { ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha Blue Warp", "Water Temple Blue Warp", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_ONE_WAY, "lh,bw", 1},
// Gerudo Area
{ ENTR_HYRULE_FIELD_ROCKY_PATH, ENTR_GERUDO_VALLEY_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "Gerudo Valley East Exit", "Hyrule Field Rocky Path", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_GERUDOS_FORTRESS_EAST_EXIT, ENTR_GERUDO_VALLEY_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "Gerudo Valley West Exit", "Gerudo Fortress East Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ ENTR_LAKE_HYLIA_RIVER_EXIT, -1, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "Gerudo Valley River Exit", "Lake Hylia River Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
- { ENTR_CARPENTERS_TENT_0, ENTR_GERUDO_VALLEY_OUTSIDE_TENT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Outside Carpenters' Tent", "Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Silver Rock Grotto Exit", "GV Octorok Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Behind Tent Grotto Exit", "GV Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
+ { ENTR_CARPENTERS_TENT_0, ENTR_GERUDO_VALLEY_OUTSIDE_TENT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Carpenters' Tent Entry", "Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Silver Rock Grotto Entry", "GV Octorok Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Behind Tent Grotto Entry", "GV Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_GERUDO_VALLEY_WEST_EXIT, ENTR_GERUDOS_FORTRESS_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "Gerudo Fortress East Exit", "Gerudo Valley West Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
- { ENTR_HAUNTED_WASTELAND_EAST_EXIT, ENTR_GERUDOS_FORTRESS_GATE_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "Gerudo Fortress Gate Exit", "Haunted Wasteland", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
- { ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "GF Outside Storms Grotto", "GF Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress", 1},
+ { ENTR_HAUNTED_WASTELAND_EAST_EXIT, ENTR_GERUDOS_FORTRESS_GATE_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "Gerudo Fortress Gate Exit", "Haunted Wasteland East Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "GF Storms Grotto Entry", "GF Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress", 1},
{ ENTR_GERUDO_TRAINING_GROUND_ENTRANCE, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "GF Outside Training Ground", "Gerudo Training Ground Entrance", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_DUNGEON, "gerudo fortress,gtg", 1},
- { ENTR_GERUDO_VALLEY_OUTSIDE_TENT, ENTR_CARPENTERS_TENT_0, SINGLE_SCENE_INFO(SCENE_CARPENTERS_TENT), "Carpenters' Tent", "GV Outside Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR},
- { ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET), {{ SCENE_GROTTOS, 0x06 }}, "GV Octorok Grotto", "GV Silver Rock Grotto Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO},
- { ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "GV Storms Grotto", "GV Behind Tent Grotto Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "GF Storms Grotto", "GF Storms Grotto Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress"},
+ { ENTR_GERUDO_VALLEY_OUTSIDE_TENT, ENTR_CARPENTERS_TENT_0, SINGLE_SCENE_INFO(SCENE_CARPENTERS_TENT), "Carpenters' Tent", "GV Carpenters' Tent Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET), {{ SCENE_GROTTOS, 0x06 }}, "GV Octorok Grotto", "GV Silver Rock Grotto Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "GV Storms Grotto", "GV Behind Tent Grotto Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "GF Storms Grotto", "GF Storms Grotto Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress"},
{ ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE, SINGLE_SCENE_INFO(SCENE_GERUDO_TRAINING_GROUND), "Gerudo Training Ground Entrance", "GF Outside Training Ground", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_DUNGEON, "gerudo fortress,gtg"},
// The Wasteland
- { ENTR_GERUDOS_FORTRESS_GATE_EXIT, ENTR_HAUNTED_WASTELAND_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_HAUNTED_WASTELAND), "Haunted Wasteland East Exit", "GF Gate Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hw,gerudo fortress"},
+ { ENTR_GERUDOS_FORTRESS_GATE_EXIT, ENTR_HAUNTED_WASTELAND_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_HAUNTED_WASTELAND), "Haunted Wasteland East Exit", "Gerudo Fortress Gate Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hw,gerudo fortress"},
{ ENTR_DESERT_COLOSSUS_EAST_EXIT, ENTR_HAUNTED_WASTELAND_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_HAUNTED_WASTELAND), "Haunted Wasteland West Exit", "Desert Colossus East Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "dc,hw"},
{ ENTR_HAUNTED_WASTELAND_WEST_EXIT, ENTR_DESERT_COLOSSUS_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Desert Colossus East Exit", "Haunted Wasteland West Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "dc,hw"},
- { ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Colossus Great Fairy Exit", "Colossus Great Fairy Fountain", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET), SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Colossus Grotto Exit", "Colossus Grotto", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_GROTTO, "dc,scrubs", 1},
+ { ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Colossus Great Fairy Entry", "Colossus Great Fairy Fountain", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET), SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Colossus Grotto Entry", "Colossus Grotto", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_GROTTO, "dc,scrubs", 1},
{ ENTR_SPIRIT_TEMPLE_ENTRANCE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Colossus Outside Temple", "Spirit Temple Entrance", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc", 1},
- { ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x02 }}, "Colossus Great Fairy Fountain", "Colossus Great Fairy Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc"},
- { ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "Colossus Grotto", "Colossus Grotto Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_GROTTO, "dc,scrubs"},
+ { ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x02 }}, "Colossus Great Fairy Fountain", "Colossus Great Fairy Entry", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc"},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "Colossus Grotto", "Colossus Grotto Entry", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_GROTTO, "dc,scrubs"},
{ ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_SPIRIT_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Entrance", "Colossus Outside Temple", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc"},
{ ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, ENTR_SPIRIT_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Boss Door", "Twinrova", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_SPIRIT_TEMPLE_BOSS_DOOR, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Boss Door", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
- { ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Blue Warp", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
+ { ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova Blue Warp", "Spirit Temple Blue Warp", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Market
- { ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance South Exit", "Hyrule Field Drawbridge Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
- { ENTR_MARKET_SOUTH_EXIT, ENTR_MARKET_ENTRANCE_NORTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance North Exit", "Market South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_MARKET_GUARD_HOUSE_0, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance Outside Guard House", "Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe", 1},
- { ENTR_MARKET_ENTRANCE_NORTH_EXIT, ENTR_MARKET_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market South Exit", "Market Entrance North Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_CASTLE_GROUNDS_SOUTH_EXIT, ENTR_MARKET_DAY_CASTLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Castle Exit", "Castle Grounds South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
- { ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, ENTR_MARKET_DAY_TEMPLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Temple Exit", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
- { ENTR_SHOOTING_GALLERY_1, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Shooting Gallery", "MK Shooting Gallery", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "child", 1},
- { ENTR_BOMBCHU_BOWLING_ALLEY_0, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Bombchu Bowling", "Bombchu Bowling", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_TREASURE_BOX_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Treasure Chest Game", "Treasure Chest Game", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Man-in-Green House", "Man-in-Green's House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_HAPPY_MASK_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Mask Shop", "Mask Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_BAZAAR_1, ENTR_MARKET_DAY_OUTSIDE_BAZAAR, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Bazaar", "MK Bazaar", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop", 1},
- { ENTR_POTION_SHOP_MARKET_0, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Potion Shop", "MK Potion Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_BOMBCHU_SHOP_1, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Outside Bombchu Shop", "Bombchu Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0, {{ SCENE_MARKET_GUARD_HOUSE }}, "Guard House", "MK Entrance Outside Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe"},
- { ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1, {{ SCENE_SHOOTING_GALLERY, 0x01 }}, "MK Shooting Gallery", "MK Outside Shooting Gallery", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0, SINGLE_SCENE_INFO(SCENE_BOMBCHU_BOWLING_ALLEY), "Bombchu Bowling", "MK Outside Bombchu Bowling", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, ENTR_TREASURE_BOX_SHOP_0, SINGLE_SCENE_INFO(SCENE_TREASURE_BOX_SHOP), "Treasure Chest Game", "MK Outside Treasure Chest Game", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, SINGLE_SCENE_INFO(SCENE_BACK_ALLEY_HOUSE), "Man-in-Green's House", "MK Outside Man-in-Green House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0, SINGLE_SCENE_INFO(SCENE_HAPPY_MASK_SHOP), "Mask Shop", "MK Outside Mask Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_MARKET_DAY_OUTSIDE_BAZAAR, ENTR_BAZAAR_1, {{ SCENE_BAZAAR, 0x01 }}, "MK Bazaar", "MK Outside Bazaar", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop"},
- { ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_MARKET), "MK Potion Shop", "MK Outside Potion Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1, SINGLE_SCENE_INFO(SCENE_BOMBCHU_SHOP), "Bombchu Shop", "MK Outside Bombchu Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
- { ENTR_MARKET_DAY_TEMPLE_EXIT, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "MK Temple Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "tot"},
- { ENTR_TEMPLE_OF_TIME_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "Temple of Time Entrance", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot", 1},
- { ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, ENTR_TEMPLE_OF_TIME_ENTRANCE, SINGLE_SCENE_INFO(SCENE_TEMPLE_OF_TIME), "Temple of Time Entrance", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot"},
+ { ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance South Exit", "Hyrule Field Drawbridge Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
+ { ENTR_MARKET_SOUTH_EXIT, ENTR_MARKET_ENTRANCE_NORTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance North Exit", "Market South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_MARKET_GUARD_HOUSE_0, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "MK Entrance Guard House Entry", "Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe", 1},
+ { ENTR_MARKET_ENTRANCE_NORTH_EXIT, ENTR_MARKET_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market South Exit", "Market Entrance North Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_CASTLE_GROUNDS_SOUTH_EXIT, ENTR_MARKET_DAY_CASTLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Castle Exit", "Castle Grounds South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
+ { ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, ENTR_MARKET_DAY_TEMPLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Temple Exit", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
+ { ENTR_SHOOTING_GALLERY_1, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Shooting Gallery Entry", "MK Shooting Gallery", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "child", 1},
+ { ENTR_BOMBCHU_BOWLING_ALLEY_0, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bombchu Bowling Entry", "Bombchu Bowling", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_TREASURE_BOX_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Treasure Chest Game Entry", "Treasure Chest Game", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Man-in-Green House Entry", "Man-in-Green's House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_HAPPY_MASK_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Mask Shop Entry", "Mask Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_BAZAAR_1, ENTR_MARKET_DAY_OUTSIDE_BAZAAR, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bazaar Entry", "MK Bazaar", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop", 1},
+ { ENTR_POTION_SHOP_MARKET_0, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Potion Shop Entry", "MK Potion Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_BOMBCHU_SHOP_1, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bombchu Shop Entry", "Bombchu Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0, {{ SCENE_MARKET_GUARD_HOUSE }}, "Guard House", "MK Entrance Guard House Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe"},
+ { ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1, {{ SCENE_SHOOTING_GALLERY, 0x01 }}, "MK Shooting Gallery", "MK Shooting Gallery Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0, SINGLE_SCENE_INFO(SCENE_BOMBCHU_BOWLING_ALLEY), "Bombchu Bowling", "MK Bombchu Bowling Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, ENTR_TREASURE_BOX_SHOP_0, SINGLE_SCENE_INFO(SCENE_TREASURE_BOX_SHOP), "Treasure Chest Game", "MK Treasure Chest Game Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, SINGLE_SCENE_INFO(SCENE_BACK_ALLEY_HOUSE), "Man-in-Green's House", "MK Man-in-Green House Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0, SINGLE_SCENE_INFO(SCENE_HAPPY_MASK_SHOP), "Mask Shop", "MK Mask Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_MARKET_DAY_OUTSIDE_BAZAAR, ENTR_BAZAAR_1, {{ SCENE_BAZAAR, 0x01 }}, "MK Bazaar", "MK Bazaar Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop"},
+ { ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_MARKET), "MK Potion Shop", "MK Potion Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1, SINGLE_SCENE_INFO(SCENE_BOMBCHU_SHOP), "Bombchu Shop", "MK Bombchu Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
+ { ENTR_MARKET_DAY_TEMPLE_EXIT, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "Market Temple Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "tot"},
+ { ENTR_TEMPLE_OF_TIME_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "Temple of Time Entrance", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot", 1},
+ { ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, ENTR_TEMPLE_OF_TIME_ENTRANCE, SINGLE_SCENE_INFO(SCENE_TEMPLE_OF_TIME), "Temple of Time Entrance", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot"},
// Hyrule Castle
- { ENTR_MARKET_DAY_CASTLE_EXIT, ENTR_CASTLE_GROUNDS_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_HYRULE_CASTLE), SCENE_NO_SPAWN(SCENE_OUTSIDE_GANONS_CASTLE)}, "Castle Grounds South Exit", "Market Castle Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
- { ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Boulder Crawlspace", "HC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "", 1},
- { ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Storms Grotto Exit", "HC Storms Grotto", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable", 1},
- { ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x01 }}, "HC Great Fairy Fountain", "HC Boulder Crawlspace", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR},
- { ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x09 }}, "HC Storms Grotto", "HC Storms Grotto Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable"},
- { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, ENTR_POTION_SHOP_KAKARIKO_1, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Behind Pillar", "OGC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle", 1},
- { ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Rainbow Bridge Exit", "Ganon's Castle", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1},
- { ENTR_POTION_SHOP_KAKARIKO_1, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x02 }}, "OGC Great Fairy Fountain", "OGC Behind Pillar", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"},
- { ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"}
+ { ENTR_MARKET_DAY_CASTLE_EXIT, ENTR_CASTLE_GROUNDS_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_HYRULE_CASTLE), SCENE_NO_SPAWN(SCENE_OUTSIDE_GANONS_CASTLE)}, "Castle Grounds South Exit", "Market Castle Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
+ { ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Boulder Crawlspace", "HC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "", 1},
+ { ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Storms Grotto Entry", "HC Storms Grotto", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable", 1},
+ { ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x01 }}, "HC Great Fairy Fountain", "HC Boulder Crawlspace", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR},
+ { ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x09 }}, "HC Storms Grotto", "HC Storms Grotto Entry", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable"},
+ { ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, ENTR_POTION_SHOP_KAKARIKO_1, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Behind Pillar", "OGC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle", 1},
+ { ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Rainbow Bridge Exit", "Inside Ganon's Castle Entrance", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1},
+ { ENTR_POTION_SHOP_KAKARIKO_1, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x02 }}, "OGC Great Fairy Fountain", "OGC Behind Pillar", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"},
+ { ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"}
};
// Check if Link is in the area and return that scene/entrance for tracking
@@ -442,6 +442,21 @@ const EntranceData* GetEntranceData(s16 index) {
return nullptr;
}
+// Used for verifying the names on both sides of entrance pairs match. Keeping for ease of use for further name changes later
+// TODO: Figure out how to remove the need for duplicate entrance names so this is no longer necessary
+void CheckEntranceNames() {
+ SPDLOG_ERROR("Checking entrance names:");
+ for (size_t i = 0; i < ARRAY_COUNT(entranceData); i++) {
+ auto entrance = &entranceData[i];
+ auto reverse = GetEntranceData(entrance->reverseIndex);
+ if (entrance != nullptr && reverse != nullptr) {
+ if (entrance->source != reverse->destination) {
+ SPDLOG_ERROR("{}({}) -> {}({})", entrance->source, entrance->index, reverse->destination, reverse->reverseIndex);
+ }
+ }
+ }
+}
+
void SortEntranceListByType(EntranceOverride* entranceList, u8 byDest) {
EntranceOverride tempList[ENTRANCE_OVERRIDES_MAX_COUNT] = { 0 };
diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h
index c66c06fab..e43acf57c 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -1249,9 +1249,12 @@ typedef enum {
RAND_INF_LH_ISLAND_SUN_FAIRY,
RAND_INF_HF_POND_STORMS_FAIRY,
RAND_INF_DMT_FLAG_SUN_FAIRY,
+ RAND_INF_DMT_COW_GROTTO_STORMS_FAIRY,
RAND_INF_HF_FENCE_GROTTO_STORMS_FAIRY,
RAND_INF_LW_SHORTCUT_STORMS_FAIRY,
RAND_INF_GF_KITCHEN_SUN_FAIRY,
+ RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY,
+ RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY,
RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY,
RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY,
RAND_INF_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY,
@@ -1272,6 +1275,56 @@ typedef enum {
RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY,
RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY,
RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY,
+
+ RAND_INF_GUARD_HOUSE_UNLOCKED,
+ RAND_INF_GUARD_HOUSE_KEY_OBTAINED,
+ RAND_INF_MARKET_BAZAAR_UNLOCKED,
+ RAND_INF_MARKET_BAZAAR_KEY_OBTAINED,
+ RAND_INF_MARKET_POTION_SHOP_UNLOCKED,
+ RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED,
+ RAND_INF_MASK_SHOP_UNLOCKED,
+ RAND_INF_MASK_SHOP_KEY_OBTAINED,
+ RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED,
+ RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED,
+ RAND_INF_BOMBCHU_BOWLING_UNLOCKED,
+ RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED,
+ RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED,
+ RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED,
+ RAND_INF_BOMBCHU_SHOP_UNLOCKED,
+ RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED,
+ RAND_INF_RICHARDS_HOUSE_UNLOCKED,
+ RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED,
+ RAND_INF_ALLEY_HOUSE_UNLOCKED,
+ RAND_INF_ALLEY_HOUSE_KEY_OBTAINED,
+ RAND_INF_KAK_BAZAAR_UNLOCKED,
+ RAND_INF_KAK_BAZAAR_KEY_OBTAINED,
+ RAND_INF_KAK_POTION_SHOP_UNLOCKED,
+ RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED,
+ RAND_INF_BOSS_HOUSE_UNLOCKED,
+ RAND_INF_BOSS_HOUSE_KEY_OBTAINED,
+ RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED,
+ RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED,
+ RAND_INF_SKULLTULA_HOUSE_UNLOCKED,
+ RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED,
+ RAND_INF_IMPAS_HOUSE_UNLOCKED,
+ RAND_INF_IMPAS_HOUSE_KEY_OBTAINED,
+ RAND_INF_WINDMILL_UNLOCKED,
+ RAND_INF_WINDMILL_KEY_OBTAINED,
+ RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED,
+ RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED,
+ RAND_INF_DAMPES_HUT_UNLOCKED,
+ RAND_INF_DAMPES_HUT_KEY_OBTAINED,
+ RAND_INF_TALONS_HOUSE_UNLOCKED,
+ RAND_INF_TALONS_HOUSE_KEY_OBTAINED,
+ RAND_INF_STABLES_UNLOCKED,
+ RAND_INF_STABLES_KEY_OBTAINED,
+ RAND_INF_BACK_TOWER_UNLOCKED,
+ RAND_INF_BACK_TOWER_KEY_OBTAINED,
+ RAND_INF_HYLIA_LAB_UNLOCKED,
+ RAND_INF_HYLIA_LAB_KEY_OBTAINED,
+ RAND_INF_FISHING_HOLE_UNLOCKED,
+ RAND_INF_FISHING_HOLE_KEY_OBTAINED,
+
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX,
diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
index 2517923fd..0b96c4ab2 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
@@ -90,17 +90,15 @@ std::vector triforcePieces = {
};
std::vector bossSoulItems = {
- //Hack for right now, just gonna draw souls as bottles/big poes.
- //Will replace with other macro once we have a custom texture
- ITEM_TRACKER_ITEM_CUSTOM(RG_GOHMA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_BARINADE_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_PHANTOM_GANON_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_VOLVAGIA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_MORPHA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_BONGO_BONGO_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_TWINROVA_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
- ITEM_TRACKER_ITEM_CUSTOM(RG_GANON_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_GOHMA_SOUL, 0, DrawItem),
+ ITEM_TRACKER_ITEM(RG_KING_DODONGO_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_BARINADE_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_PHANTOM_GANON_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_VOLVAGIA_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_MORPHA_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_BONGO_BONGO_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_TWINROVA_SOUL, 0, DrawItem ),
+ ITEM_TRACKER_ITEM(RG_GANON_SOUL, 0, DrawItem ),
};
std::vector ocarinaButtonItems = {
diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp
index af7abd49e..7e91026b0 100644
--- a/soh/soh/Enhancements/randomizer/savefile.cpp
+++ b/soh/soh/Enhancements/randomizer/savefile.cpp
@@ -272,7 +272,7 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO);
}
- int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
+ int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
switch (startingAge) {
case RO_AGE_ADULT: // Adult
gSaveContext.linkAge = LINK_AGE_ADULT;
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index 2eca18603..2ca325635 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -1,7 +1,6 @@
#include "settings.h"
#include "trial.h"
#include "dungeon.h"
-#include "context.h"
#include "soh/OTRGlobals.h"
@@ -12,6 +11,8 @@
#include "consolevariablebridge.h"
namespace Rando {
+std::shared_ptr Settings::mInstance;
+
std::vector NumOpts(const int min, const int max, const int step = 1, const std::string& textBefore = {}, const std::string& textAfter = {}) {
std::vector options;
options.reserve((max - min) / step + 1);
@@ -102,223 +103,229 @@ void Settings::HandleShopsanityPriceUI(){
Settings::Settings() : mExcludeLocationsOptionsAreas(RCAREA_INVALID) {
}
+#define OPT_U8(rsk, ...) mOptions[rsk] = Option::U8(rsk, __VA_ARGS__)
+#define OPT_BOOL(rsk, ...) mOptions[rsk] = Option::Bool(rsk, __VA_ARGS__)
+#define OPT_TRICK(rsk, ...) mTrickOptions[rsk] = TrickOption::LogicTrick(rsk, __VA_ARGS__)
+
void Settings::CreateOptions() {
CreateOptionDescriptions();
// clang-format off
- mOptions[RSK_FOREST] = Option::U8("Closed Forest", {"On", "Deku Only", "Off"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ClosedForest"), mOptionDescriptions[RSK_FOREST], WidgetType::Combobox, RO_CLOSED_FOREST_ON);
- mOptions[RSK_KAK_GATE] = Option::U8("Kakariko Gate", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("KakarikoGate"), mOptionDescriptions[RSK_KAK_GATE]);
- mOptions[RSK_DOOR_OF_TIME] = Option::U8("Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox);
- mOptions[RSK_ZORAS_FOUNTAIN] = Option::U8("Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]);
- mOptions[RSK_SLEEPING_WATERFALL] = Option::U8("Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]);
- mOptions[RSK_GERUDO_FORTRESS] = Option::U8("Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]);
- mOptions[RSK_RAINBOW_BRIDGE] = Option::U8("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT] = Option::U8("Bridge Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true);
- mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = Option::U8("Bridge Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MedallionCount"), "", WidgetType::Slider, 6, true);
- mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = Option::U8("Bridge Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RewardCount"), "", WidgetType::Slider, 9, true);
- mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = Option::U8("Bridge Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DungeonCount"), "", WidgetType::Slider, 8, true);
- mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = Option::U8("Bridge Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TokenCount"), "", WidgetType::Slider, 100, true);
- mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT] = Option::U8("Bridge Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true);
- mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT] = Option::U8("Bridge Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MedallionCount"), "", WidgetType::Slider, 6, true);
- mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT] = Option::U8("Bridge Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RewardCount"), "", WidgetType::Slider, 9, true);
- mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT] = Option::U8("Bridge Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DungeonCount"), "", WidgetType::Slider, 8, true);
- mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT] = Option::U8("Bridge Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TokenCount"), "", WidgetType::Slider, 100, true);
- mOptions[RSK_BRIDGE_OPTIONS] = Option::U8("Bridge Reward Options", {"Standard Rewards", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), mOptionDescriptions[RSK_BRIDGE_OPTIONS], WidgetType::Combobox, RO_BRIDGE_STANDARD_REWARD, false, IMFLAG_NONE);
- mOptions[RSK_GANONS_TRIALS] = Option::U8("Ganon's Trials", {"Skip", "Set Number", "Random Number"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrial"), mOptionDescriptions[RSK_GANONS_TRIALS], WidgetType::Combobox, RO_GANONS_TRIALS_SET_NUMBER);
- mOptions[RSK_TRIAL_COUNT] = Option::U8("Ganon's Trials Count", {NumOpts(0, 6)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrialCount"), mOptionDescriptions[RSK_TRIAL_COUNT], WidgetType::Slider, 6, true);
- mOptions[RSK_STARTING_AGE] = Option::U8("Starting Age", {"Child", "Adult", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WidgetType::Combobox, RO_AGE_CHILD);
- mOptions[RSK_SELECTED_STARTING_AGE] = Option::U8("Selected Starting Age", {"Child", "Adult"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SelectedStartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WidgetType::Combobox, RO_AGE_CHILD);
- mOptions[RSK_SHUFFLE_ENTRANCES] = Option::Bool("Shuffle Entrances");
- mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES] = Option::U8("Dungeon Entrances", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES], WidgetType::Combobox, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
- mOptions[RSK_SHUFFLE_BOSS_ENTRANCES] = Option::U8("Boss Entrances", {"Off", "Age Restricted", "Full"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), mOptionDescriptions[RSK_SHUFFLE_BOSS_ENTRANCES], WidgetType::Combobox, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
- mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = Option::Bool("Overworld Entrances", CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
- mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES] = Option::U8("Interior Entrances", {"Off", "Simple", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), mOptionDescriptions[RSK_SHUFFLE_INTERIOR_ENTRANCES], WidgetType::Combobox, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
- mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES] = Option::Bool("Grottos Entrances", CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), mOptionDescriptions[RSK_SHUFFLE_GROTTO_ENTRANCES]);
- mOptions[RSK_SHUFFLE_OWL_DROPS] = Option::Bool("Owl Drops", CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), mOptionDescriptions[RSK_SHUFFLE_OWL_DROPS]);
- mOptions[RSK_SHUFFLE_WARP_SONGS] = Option::Bool("Warp Songs", CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), mOptionDescriptions[RSK_SHUFFLE_WARP_SONGS]);
- mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] = Option::Bool("Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
- mOptions[RSK_MIXED_ENTRANCE_POOLS] = Option::Bool("Mixed Entrance Pools", CVAR_RANDOMIZER_SETTING("MixedEntrances"), mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]);
- mOptions[RSK_MIX_DUNGEON_ENTRANCES] = Option::Bool("Mix Dungeons", CVAR_RANDOMIZER_SETTING("MixDungeons"), mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE);
- mOptions[RSK_MIX_BOSS_ENTRANCES] = Option::Bool("Mix Bosses", CVAR_RANDOMIZER_SETTING("MixBosses"), mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE);
- mOptions[RSK_MIX_OVERWORLD_ENTRANCES] = Option::Bool("Mix Overworld", CVAR_RANDOMIZER_SETTING("MixOverworld"), mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES], IMFLAG_NONE);
- mOptions[RSK_MIX_INTERIOR_ENTRANCES] = Option::Bool("Mix Interiors", CVAR_RANDOMIZER_SETTING("MixInteriors"), mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES], IMFLAG_NONE);
- mOptions[RSK_MIX_GROTTO_ENTRANCES] = Option::Bool("Mix Grottos", CVAR_RANDOMIZER_SETTING("MixGrottos"), mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]);
- mOptions[RSK_DECOUPLED_ENTRANCES] = Option::Bool("Decouple Entrances", CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), mOptionDescriptions[RSK_DECOUPLED_ENTRANCES]);
- mOptions[RSK_BOMBCHU_BAG] = Option::Bool("Bombchu Bag", CVAR_RANDOMIZER_SETTING("BombchuBag"), mOptionDescriptions[RSK_BOMBCHU_BAG]);
- mOptions[RSK_ENABLE_BOMBCHU_DROPS] = Option::U8("Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WidgetType::Combobox, RO_AMMO_DROPS_ON);
+ OPT_U8(RSK_FOREST, "Closed Forest", {"On", "Deku Only", "Off"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ClosedForest"), mOptionDescriptions[RSK_FOREST], WidgetType::Combobox, RO_CLOSED_FOREST_ON);
+ OPT_U8(RSK_KAK_GATE, "Kakariko Gate", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("KakarikoGate"), mOptionDescriptions[RSK_KAK_GATE]);
+ OPT_U8(RSK_DOOR_OF_TIME, "Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox);
+ OPT_U8(RSK_ZORAS_FOUNTAIN, "Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]);
+ OPT_U8(RSK_SLEEPING_WATERFALL, "Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]);
+ OPT_BOOL(RSK_LOCK_OVERWORLD_DOORS, "Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]);
+ OPT_U8(RSK_GERUDO_FORTRESS, "Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]);
+ OPT_U8(RSK_RAINBOW_BRIDGE, "Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_RAINBOW_BRIDGE_STONE_COUNT, "Bridge Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT, "Bridge Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MedallionCount"), "", WidgetType::Slider, 6, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_REWARD_COUNT, "Bridge Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RewardCount"), "", WidgetType::Slider, 9, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT, "Bridge Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DungeonCount"), "", WidgetType::Slider, 8, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_TOKEN_COUNT, "Bridge Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TokenCount"), "", WidgetType::Slider, 100, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_STONE_COUNT, "Bridge Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT, "Bridge Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MedallionCount"), "", WidgetType::Slider, 6, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_REWARD_COUNT, "Bridge Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RewardCount"), "", WidgetType::Slider, 9, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT, "Bridge Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DungeonCount"), "", WidgetType::Slider, 8, true);
+ OPT_U8(RSK_RAINBOW_BRIDGE_TOKEN_COUNT, "Bridge Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TokenCount"), "", WidgetType::Slider, 100, true);
+ OPT_U8(RSK_BRIDGE_OPTIONS, "Bridge Reward Options", {"Standard Rewards", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), mOptionDescriptions[RSK_BRIDGE_OPTIONS], WidgetType::Combobox, RO_BRIDGE_STANDARD_REWARD, false, IMFLAG_NONE);
+ OPT_U8(RSK_GANONS_TRIALS, "Ganon's Trials", {"Skip", "Set Number", "Random Number"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrial"), mOptionDescriptions[RSK_GANONS_TRIALS], WidgetType::Combobox, RO_GANONS_TRIALS_SET_NUMBER);
+ OPT_U8(RSK_TRIAL_COUNT, "Ganon's Trials Count", {NumOpts(0, 6)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrialCount"), mOptionDescriptions[RSK_TRIAL_COUNT], WidgetType::Slider, 6, true);
+ OPT_U8(RSK_STARTING_AGE, "Starting Age", {"Child", "Adult", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WidgetType::Combobox, RO_AGE_CHILD);
+ OPT_U8(RSK_SELECTED_STARTING_AGE, "Selected Starting Age", {"Child", "Adult"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SelectedStartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WidgetType::Combobox, RO_AGE_CHILD);
+ OPT_BOOL(RSK_SHUFFLE_ENTRANCES, "Shuffle Entrances");
+ OPT_U8(RSK_SHUFFLE_DUNGEON_ENTRANCES, "Dungeon Entrances", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES], WidgetType::Combobox, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
+ OPT_U8(RSK_SHUFFLE_BOSS_ENTRANCES, "Boss Entrances", {"Off", "Age Restricted", "Full"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), mOptionDescriptions[RSK_SHUFFLE_BOSS_ENTRANCES], WidgetType::Combobox, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
+ OPT_BOOL(RSK_SHUFFLE_OVERWORLD_ENTRANCES, "Overworld Entrances", CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
+ OPT_U8(RSK_SHUFFLE_INTERIOR_ENTRANCES, "Interior Entrances", {"Off", "Simple", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), mOptionDescriptions[RSK_SHUFFLE_INTERIOR_ENTRANCES], WidgetType::Combobox, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
+ OPT_BOOL(RSK_SHUFFLE_GROTTO_ENTRANCES, "Grottos Entrances", CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), mOptionDescriptions[RSK_SHUFFLE_GROTTO_ENTRANCES]);
+ OPT_BOOL(RSK_SHUFFLE_OWL_DROPS, "Owl Drops", CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), mOptionDescriptions[RSK_SHUFFLE_OWL_DROPS]);
+ OPT_BOOL(RSK_SHUFFLE_WARP_SONGS, "Warp Songs", CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), mOptionDescriptions[RSK_SHUFFLE_WARP_SONGS]);
+ OPT_BOOL(RSK_SHUFFLE_OVERWORLD_SPAWNS, "Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
+ OPT_BOOL(RSK_MIXED_ENTRANCE_POOLS, "Mixed Entrance Pools", CVAR_RANDOMIZER_SETTING("MixedEntrances"), mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]);
+ OPT_BOOL(RSK_MIX_DUNGEON_ENTRANCES, "Mix Dungeons", CVAR_RANDOMIZER_SETTING("MixDungeons"), mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE);
+ OPT_BOOL(RSK_MIX_BOSS_ENTRANCES, "Mix Bosses", CVAR_RANDOMIZER_SETTING("MixBosses"), mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE);
+ OPT_BOOL(RSK_MIX_OVERWORLD_ENTRANCES, "Mix Overworld", CVAR_RANDOMIZER_SETTING("MixOverworld"), mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES], IMFLAG_NONE);
+ OPT_BOOL(RSK_MIX_INTERIOR_ENTRANCES, "Mix Interiors", CVAR_RANDOMIZER_SETTING("MixInteriors"), mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES], IMFLAG_NONE);
+ OPT_BOOL(RSK_MIX_GROTTO_ENTRANCES, "Mix Grottos", CVAR_RANDOMIZER_SETTING("MixGrottos"), mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]);
+ OPT_BOOL(RSK_DECOUPLED_ENTRANCES, "Decouple Entrances", CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), mOptionDescriptions[RSK_DECOUPLED_ENTRANCES]);
+ OPT_BOOL(RSK_BOMBCHU_BAG, "Bombchu Bag", CVAR_RANDOMIZER_SETTING("BombchuBag"), mOptionDescriptions[RSK_BOMBCHU_BAG]);
+ OPT_U8(RSK_ENABLE_BOMBCHU_DROPS, "Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WidgetType::Combobox, RO_AMMO_DROPS_ON);
// TODO: AmmoDrops and/or HeartDropRefill, combine with/separate Ammo Drops from Bombchu Drops?
- mOptions[RSK_TRIFORCE_HUNT] = Option::Bool("Triforce Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE);
- mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL] = Option::U8("Triforce Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WidgetType::Slider, 29, false, IMFLAG_NONE);
- mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = Option::U8("Triforce Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WidgetType::Slider, 19);
- mOptions[RSK_MQ_DUNGEON_RANDOM] = Option::U8("MQ Dungeon Setting", {"None", "Set Number", "Random", "Selection Only"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeons"), mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM], WidgetType::Combobox, RO_MQ_DUNGEONS_NONE, true, IMFLAG_NONE);
- mOptions[RSK_MQ_DUNGEON_COUNT] = Option::U8("MQ Dungeon Count", {NumOpts(0, 12)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonCount"), "", WidgetType::Slider, 12, true, IMFLAG_NONE);
- mOptions[RSK_MQ_DUNGEON_SET] = Option::Bool("Set Dungeon Quests", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), mOptionDescriptions[RSK_MQ_DUNGEON_SET], WidgetType::Checkbox, false, false, IMFLAG_NONE);
- mOptions[RSK_MQ_DEKU_TREE] = Option::U8("Deku Tree Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDekuTree"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_DODONGOS_CAVERN] = Option::U8("Dodongo's Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDodongosCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_JABU_JABU] = Option::U8("Jabu-Jabu's Belly Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsJabuJabu"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_FOREST_TEMPLE] = Option::U8("Forest Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsForestTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_FIRE_TEMPLE] = Option::U8("Fire Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsFireTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_WATER_TEMPLE] = Option::U8("Water Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsWaterTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_SPIRIT_TEMPLE] = Option::U8("Spirit Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSpiritTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_SHADOW_TEMPLE] = Option::U8("Shadow Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsShadowTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_BOTTOM_OF_THE_WELL] = Option::U8("Bottom of the Well Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsBottomOfTheWell"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_ICE_CAVERN] = Option::U8("Ice Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_GTG] = Option::U8("Gerudo Training Ground Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MQ_GANONS_CASTLE] = Option::U8("Ganon's Castle Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA);
- mOptions[RSK_SHUFFLE_DUNGEON_REWARDS] = Option::U8("Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
- mOptions[RSK_LINKS_POCKET] = Option::U8("Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD);
- mOptions[RSK_SHUFFLE_SONGS] = Option::U8("Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS);
- mOptions[RSK_SHOPSANITY] = Option::U8("Shop Shuffle", {"Off", "Specific Count", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF);
- mOptions[RSK_SHOPSANITY_COUNT] = Option::U8("Shops Item Count", {NumOpts(0, 7/*8*/)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityCount"), mOptionDescriptions[RSK_SHOPSANITY_COUNT], WidgetType::Slider, 0, false, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES] = Option::U8("Shops Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), mOptionDescriptions[RSK_SHOPSANITY_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE] = Option::U8("Shops Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityFixedPrice"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE], WidgetType::Slider, 10, true);
- mOptions[RSK_SHOPSANITY_PRICES_RANGE_1] = Option::U8("Shops Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPriceRange1"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_1], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_RANGE_2] = Option::U8("Shops Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPriceRange2"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_2], WidgetType::Slider, 100, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT] = Option::U8("Shops No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityNoWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT] = Option::U8("Shops Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityChildWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT] = Option::U8("Shops Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityAdultWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT] = Option::U8("Shops Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityGiantWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT] = Option::U8("Shops Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityTycoonWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] = Option::Bool("Shops Affordable Prices", CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]);
- mOptions[RSK_SHUFFLE_TOKENS] = Option::U8("Token Shuffle", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleTokens"), mOptionDescriptions[RSK_SHUFFLE_TOKENS], WidgetType::Combobox, RO_TOKENSANITY_OFF);
- mOptions[RSK_SHUFFLE_SCRUBS] = Option::U8("Scrubs Shuffle", {"Off", "One-Time Only", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), mOptionDescriptions[RSK_SHUFFLE_SCRUBS], WidgetType::Combobox, RO_SCRUBS_OFF);
- mOptions[RSK_SCRUBS_PRICES] = Option::U8("Scrubs Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPrices"), mOptionDescriptions[RSK_SCRUBS_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE] = Option::U8("Scrubs Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsFixedPrice"), mOptionDescriptions[RSK_SCRUBS_PRICES_FIXED_PRICE], WidgetType::Slider, 10, true);
- mOptions[RSK_SCRUBS_PRICES_RANGE_1] = Option::U8("Scrubs Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPriceRange1"), mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_1], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_RANGE_2] = Option::U8("Scrubs Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPriceRange2"), mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_2], WidgetType::Slider, 100, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT] = Option::U8("Scrubs No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsNoWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT] = Option::U8("Scrubs Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsChildWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT] = Option::U8("Scrubs Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsAdultWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT] = Option::U8("Scrubs Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsGiantWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT] = Option::U8("Scrubs Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsTycoonWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_SCRUBS_PRICES_AFFORDABLE] = Option::Bool("Scrubs Affordable Prices", CVAR_RANDOMIZER_SETTING("ScrubsPricesAffordable"), mOptionDescriptions[RSK_SCRUBS_PRICES_AFFORDABLE]);
- mOptions[RSK_SHUFFLE_BEEHIVES] = Option::Bool("Shuffle Beehives", CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), mOptionDescriptions[RSK_SHUFFLE_BEEHIVES]);
- mOptions[RSK_SHUFFLE_COWS] = Option::Bool("Shuffle Cows", CVAR_RANDOMIZER_SETTING("ShuffleCows"), mOptionDescriptions[RSK_SHUFFLE_COWS]);
- mOptions[RSK_SHUFFLE_KOKIRI_SWORD] = Option::Bool("Shuffle Kokiri Sword", CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), mOptionDescriptions[RSK_SHUFFLE_KOKIRI_SWORD]);
- mOptions[RSK_SHUFFLE_MASTER_SWORD] = Option::Bool("Shuffle Master Sword", CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), mOptionDescriptions[RSK_SHUFFLE_MASTER_SWORD]);
- mOptions[RSK_SHUFFLE_CHILD_WALLET] = Option::Bool("Shuffle Child's Wallet", CVAR_RANDOMIZER_SETTING("ShuffleChildWallet"), mOptionDescriptions[RSK_SHUFFLE_CHILD_WALLET], IMFLAG_NONE);
- mOptions[RSK_INCLUDE_TYCOON_WALLET] = Option::Bool("Include Tycoon Wallet", CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), mOptionDescriptions[RSK_INCLUDE_TYCOON_WALLET]);
- mOptions[RSK_SHUFFLE_OCARINA] = Option::Bool("Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
- mOptions[RSK_SHUFFLE_OCARINA_BUTTONS] = Option::Bool("Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
- mOptions[RSK_SHUFFLE_SWIM] = Option::Bool("Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]);
- mOptions[RSK_SHUFFLE_WEIRD_EGG] = Option::Bool("Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
- mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = Option::Bool("Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
- mOptions[RSK_SHUFFLE_POTS] = Option::U8("Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF);
- mOptions[RSK_SHUFFLE_FISHING_POLE] = Option::Bool("Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]);
- mOptions[RSK_SHUFFLE_MERCHANTS] = Option::U8("Shuffle Merchants", {"Off", "Bean Merchant Only", "All But Beans", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES] = Option::U8("Merchant Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPrices"), mOptionDescriptions[RSK_MERCHANT_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE] = Option::U8("Merchant Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantFixedPrice"), mOptionDescriptions[RSK_MERCHANT_PRICES_FIXED_PRICE], WidgetType::Slider, 10, true);
- mOptions[RSK_MERCHANT_PRICES_RANGE_1] = Option::U8("Merchant Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPriceRange1"), mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_1], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_RANGE_2] = Option::U8("Merchant Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPriceRange2"), mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_2], WidgetType::Slider, 100, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT] = Option::U8("Merchant No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantNoWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT] = Option::U8("Merchant Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantChildWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT] = Option::U8("Merchant Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantAdultWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT] = Option::U8("Merchant Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantGiantWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT] = Option::U8("Merchant Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantTycoonWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
- mOptions[RSK_MERCHANT_PRICES_AFFORDABLE] = Option::Bool("Merchant Affordable Prices", CVAR_RANDOMIZER_SETTING("MerchantPricesAffordable"), mOptionDescriptions[RSK_MERCHANT_PRICES_AFFORDABLE]);
- mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES] = Option::Bool("Shuffle Frog Song Rupees", CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]);
- mOptions[RSK_SHUFFLE_ADULT_TRADE] = Option::Bool("Shuffle Adult Trade", CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), mOptionDescriptions[RSK_SHUFFLE_ADULT_TRADE]);
- mOptions[RSK_SHUFFLE_CHEST_MINIGAME] = Option::U8("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"});
- mOptions[RSK_SHUFFLE_100_GS_REWARD] = Option::Bool("Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox);
- mOptions[RSK_SHUFFLE_DEKU_STICK_BAG] = Option::Bool("Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_SHUFFLE_DEKU_NUT_BAG] = Option::Bool("Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_SHUFFLE_FREESTANDING] = Option::U8("Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WidgetType::Combobox, RO_SHUFFLE_FREESTANDING_OFF);
- mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF);
- mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE);
- mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]);
- mOptions[RSK_SHUFFLE_FAIRIES] = Option::Bool("Shuffle Fairies", CVAR_RANDOMIZER_SETTING("ShuffleFairies"), mOptionDescriptions[RSK_SHUFFLE_FAIRIES]);
- mOptions[RSK_SHUFFLE_MAPANDCOMPASS] = Option::U8("Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
- mOptions[RSK_KEYSANITY] = Option::U8("Small Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
- mOptions[RSK_GERUDO_KEYS] = Option::U8("Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA);
- mOptions[RSK_BOSS_KEYSANITY] = Option::U8("Boss Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BossKeysanity"), mOptionDescriptions[RSK_BOSS_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
- mOptions[RSK_GANONS_BOSS_KEY] = Option::U8("Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "100 GS Reward", "Triforce Hunt"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), mOptionDescriptions[RSK_GANONS_BOSS_KEY], WidgetType::Combobox, RO_GANON_BOSS_KEY_VANILLA);
- mOptions[RSK_LACS_STONE_COUNT] = Option::U8("GCBK Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsStoneCount"), "", WidgetType::Slider, 3, true);
- mOptions[RSK_LACS_MEDALLION_COUNT] = Option::U8("GCBK Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), "", WidgetType::Slider, 6, true);
- mOptions[RSK_LACS_REWARD_COUNT] = Option::U8("GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true);
- mOptions[RSK_LACS_DUNGEON_COUNT] = Option::U8("GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true);
- mOptions[RSK_LACS_TOKEN_COUNT] = Option::U8("GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true);
- mOptions[RSK_LACS_OPTIONS] = Option::U8("GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
- mOptions[RSK_KEYRINGS] = Option::U8("Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF);
- mOptions[RSK_KEYRINGS_RANDOM_COUNT] = Option::U8("Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8);
- mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] = Option::U8("Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_FOREST_TEMPLE] = Option::U8("Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_FIRE_TEMPLE] = Option::U8("Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_WATER_TEMPLE] = Option::U8("Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE] = Option::U8("Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_SHADOW_TEMPLE] = Option::U8("Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL] = Option::U8("Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_GTG] = Option::U8("Gerudo Training Ground Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_KEYRINGS_GANONS_CASTLE] = Option::U8("Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::TristateCheckbox, 0);
- mOptions[RSK_SKIP_CHILD_STEALTH] = Option::Bool("Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
- mOptions[RSK_SKIP_CHILD_ZELDA] = Option::Bool("Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
- mOptions[RSK_SKIP_EPONA_RACE] = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
- mOptions[RSK_SKIP_SCARECROWS_SONG] = Option::Bool("Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
- mOptions[RSK_BIG_POE_COUNT] = Option::U8("Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9);
- mOptions[RSK_CUCCO_COUNT] = Option::U8("Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7);
- mOptions[RSK_COMPLETE_MASK_QUEST] = Option::Bool("Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]);
- mOptions[RSK_ENABLE_GLITCH_CUTSCENES] = Option::Bool("Enable Glitch-Useful Cutscenes", CVAR_RANDOMIZER_SETTING("EnableGlitchCutscenes"), mOptionDescriptions[RSK_ENABLE_GLITCH_CUTSCENES]);
- mOptions[RSK_GOSSIP_STONE_HINTS] = Option::U8("Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE);
- mOptions[RSK_HINT_CLARITY] = Option::U8("Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintClarity"), mOptionDescriptions[RSK_HINT_CLARITY], WidgetType::Combobox, RO_HINT_CLARITY_CLEAR, true, IMFLAG_INDENT);
- mOptions[RSK_HINT_DISTRIBUTION] = Option::U8("Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintDistribution"), mOptionDescriptions[RSK_HINT_DISTRIBUTION], WidgetType::Combobox, RO_HINT_DIST_BALANCED, true, IMFLAG_UNINDENT);
- mOptions[RSK_TOT_ALTAR_HINT] = Option::Bool("ToT Altar Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AltarHint"), mOptionDescriptions[RSK_TOT_ALTAR_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_INDENT);
- mOptions[RSK_GANONDORF_HINT] = Option::Bool("Ganondorf Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanondorfHint"), mOptionDescriptions[RSK_GANONDORF_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE);
- mOptions[RSK_SHEIK_LA_HINT] = Option::Bool("Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SheikLAHint"), mOptionDescriptions[RSK_SHEIK_LA_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE);
- mOptions[RSK_DAMPES_DIARY_HINT] = Option::Bool("Dampe's Diary Hint", CVAR_RANDOMIZER_SETTING("DampeHint"), mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE);
- mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", CVAR_RANDOMIZER_SETTING("GregHint"), mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE);
- mOptions[RSK_LOACH_HINT] = Option::Bool("Hyrule Loach Hint", CVAR_RANDOMIZER_SETTING("LoachHint"), mOptionDescriptions[RSK_LOACH_HINT], IMFLAG_NONE);
- mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE);
- mOptions[RSK_FISHING_POLE_HINT] = Option::Bool("Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE);
- mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE);
- mOptions[RSK_OOT_HINT] = Option::Bool("Ocarina of Time Hint", CVAR_RANDOMIZER_SETTING("OoTHint"), mOptionDescriptions[RSK_OOT_HINT], IMFLAG_NONE);
- mOptions[RSK_BIGGORON_HINT] = Option::Bool("Biggoron's Hint", CVAR_RANDOMIZER_SETTING("BiggoronHint"), mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE);
- mOptions[RSK_BIG_POES_HINT] = Option::Bool("Big Poes Hint", CVAR_RANDOMIZER_SETTING("BigPoesHint"), mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE);
- mOptions[RSK_CHICKENS_HINT] = Option::Bool("Chickens Hint", CVAR_RANDOMIZER_SETTING("ChickensHint"), mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE);
- mOptions[RSK_MALON_HINT] = Option::Bool("Malon Hint", CVAR_RANDOMIZER_SETTING("MalonHint"), mOptionDescriptions[RSK_MALON_HINT], IMFLAG_NONE);
- mOptions[RSK_HBA_HINT] = Option::Bool("Horseback Archery Hint", CVAR_RANDOMIZER_SETTING("HBAHint"), mOptionDescriptions[RSK_HBA_HINT], IMFLAG_NONE);
- mOptions[RSK_WARP_SONG_HINTS] = Option::Bool("Warp Song Hints", CVAR_RANDOMIZER_SETTING("WarpSongText"), mOptionDescriptions[RSK_WARP_SONG_HINTS], IMFLAG_NONE, WidgetType::Checkbox, RO_GENERIC_ON);
- mOptions[RSK_SCRUB_TEXT_HINT] = Option::Bool("Scrub Hint Text", CVAR_RANDOMIZER_SETTING("ScrubText"), mOptionDescriptions[RSK_SCRUB_TEXT_HINT], IMFLAG_NONE);
- mOptions[RSK_MERCHANT_TEXT_HINT] = Option::Bool("Merchant Hint Text", CVAR_RANDOMIZER_SETTING("MerchantText"), mOptionDescriptions[RSK_MERCHANT_TEXT_HINT], IMFLAG_NONE);
- mOptions[RSK_KAK_10_SKULLS_HINT] = Option::Bool("10 GS Hint", CVAR_RANDOMIZER_SETTING("10GSHint"), mOptionDescriptions[RSK_KAK_10_SKULLS_HINT], IMFLAG_NONE);
- mOptions[RSK_KAK_20_SKULLS_HINT] = Option::Bool("20 GS Hint", CVAR_RANDOMIZER_SETTING("20GSHint"), mOptionDescriptions[RSK_KAK_20_SKULLS_HINT], IMFLAG_NONE);
- mOptions[RSK_KAK_30_SKULLS_HINT] = Option::Bool("30 GS Hint", CVAR_RANDOMIZER_SETTING("30GSHint"), mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE);
- mOptions[RSK_KAK_40_SKULLS_HINT] = Option::Bool("40 GS Hint", CVAR_RANDOMIZER_SETTING("40GSHint"), mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE);
- mOptions[RSK_KAK_50_SKULLS_HINT] = Option::Bool("50 GS Hint", CVAR_RANDOMIZER_SETTING("50GSHint"), mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE);
- mOptions[RSK_KAK_100_SKULLS_HINT] = Option::Bool("100 GS Hint", CVAR_RANDOMIZER_SETTING("100GSHint"), mOptionDescriptions[RSK_KAK_100_SKULLS_HINT], IMFLAG_NONE);
- mOptions[RSK_MASK_SHOP_HINT] = Option::Bool("Mask Shop Hint", CVAR_RANDOMIZER_SETTING("MaskShopHint"), mOptionDescriptions[RSK_MASK_SHOP_HINT]);
+ OPT_BOOL(RSK_TRIFORCE_HUNT, "Triforce Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE);
+ OPT_U8(RSK_TRIFORCE_HUNT_PIECES_TOTAL, "Triforce Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WidgetType::Slider, 29, false, IMFLAG_NONE);
+ OPT_U8(RSK_TRIFORCE_HUNT_PIECES_REQUIRED, "Triforce Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WidgetType::Slider, 19);
+ OPT_U8(RSK_MQ_DUNGEON_RANDOM, "MQ Dungeon Setting", {"None", "Set Number", "Random", "Selection Only"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeons"), mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM], WidgetType::Combobox, RO_MQ_DUNGEONS_NONE, true, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_DUNGEON_COUNT, "MQ Dungeon Count", {NumOpts(0, 12)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonCount"), "", WidgetType::Slider, 12, true, IMFLAG_NONE);
+ OPT_BOOL(RSK_MQ_DUNGEON_SET, "Set Dungeon Quests", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), mOptionDescriptions[RSK_MQ_DUNGEON_SET], WidgetType::Checkbox, false, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_DEKU_TREE, "Deku Tree Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDekuTree"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_DODONGOS_CAVERN, "Dodongo's Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDodongosCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_JABU_JABU, "Jabu-Jabu's Belly Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsJabuJabu"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_FOREST_TEMPLE, "Forest Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsForestTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_FIRE_TEMPLE, "Fire Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsFireTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_WATER_TEMPLE, "Water Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsWaterTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_SPIRIT_TEMPLE, "Spirit Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSpiritTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_SHADOW_TEMPLE, "Shadow Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsShadowTemple"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_BOTTOM_OF_THE_WELL, "Bottom of the Well Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsBottomOfTheWell"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_ICE_CAVERN, "Ice Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_GTG, "Gerudo Training Ground Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MQ_GANONS_CASTLE, "Ganon's Castle Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), "", WidgetType::Combobox, RO_MQ_SET_VANILLA);
+ OPT_U8(RSK_SHUFFLE_DUNGEON_REWARDS, "Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
+ OPT_U8(RSK_LINKS_POCKET, "Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD);
+ OPT_U8(RSK_SHUFFLE_SONGS, "Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS);
+ OPT_U8(RSK_SHOPSANITY, "Shop Shuffle", {"Off", "Specific Count", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF);
+ OPT_U8(RSK_SHOPSANITY_COUNT, "Shops Item Count", {NumOpts(0, 7/*8*/)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityCount"), mOptionDescriptions[RSK_SHOPSANITY_COUNT], WidgetType::Slider, 0, false, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES, "Shops Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), mOptionDescriptions[RSK_SHOPSANITY_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_FIXED_PRICE, "Shops Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityFixedPrice"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE], WidgetType::Slider, 10, true);
+ OPT_U8(RSK_SHOPSANITY_PRICES_RANGE_1, "Shops Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPriceRange1"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_1], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_RANGE_2, "Shops Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPriceRange2"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_2], WidgetType::Slider, 100, true, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT, "Shops No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityNoWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT, "Shops Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityChildWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT, "Shops Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityAdultWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT, "Shops Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityGiantWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT, "Shops Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityTycoonWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_BOOL(RSK_SHOPSANITY_PRICES_AFFORDABLE, "Shops Affordable Prices", CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]);
+ OPT_U8(RSK_SHUFFLE_TOKENS, "Token Shuffle", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleTokens"), mOptionDescriptions[RSK_SHUFFLE_TOKENS], WidgetType::Combobox, RO_TOKENSANITY_OFF);
+ OPT_U8(RSK_SHUFFLE_SCRUBS, "Scrubs Shuffle", {"Off", "One-Time Only", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), mOptionDescriptions[RSK_SHUFFLE_SCRUBS], WidgetType::Combobox, RO_SCRUBS_OFF);
+ OPT_U8(RSK_SCRUBS_PRICES, "Scrubs Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPrices"), mOptionDescriptions[RSK_SCRUBS_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_FIXED_PRICE, "Scrubs Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsFixedPrice"), mOptionDescriptions[RSK_SCRUBS_PRICES_FIXED_PRICE], WidgetType::Slider, 10, true);
+ OPT_U8(RSK_SCRUBS_PRICES_RANGE_1, "Scrubs Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPriceRange1"), mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_1], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_RANGE_2, "Scrubs Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPriceRange2"), mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_2], WidgetType::Slider, 100, true, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT, "Scrubs No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsNoWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT, "Scrubs Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsChildWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT, "Scrubs Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsAdultWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT, "Scrubs Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsGiantWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT, "Scrubs Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsTycoonWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_BOOL(RSK_SCRUBS_PRICES_AFFORDABLE, "Scrubs Affordable Prices", CVAR_RANDOMIZER_SETTING("ScrubsPricesAffordable"), mOptionDescriptions[RSK_SCRUBS_PRICES_AFFORDABLE]);
+ OPT_BOOL(RSK_SHUFFLE_BEEHIVES, "Shuffle Beehives", CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), mOptionDescriptions[RSK_SHUFFLE_BEEHIVES]);
+ OPT_BOOL(RSK_SHUFFLE_COWS, "Shuffle Cows", CVAR_RANDOMIZER_SETTING("ShuffleCows"), mOptionDescriptions[RSK_SHUFFLE_COWS]);
+ OPT_BOOL(RSK_SHUFFLE_KOKIRI_SWORD, "Shuffle Kokiri Sword", CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), mOptionDescriptions[RSK_SHUFFLE_KOKIRI_SWORD]);
+ OPT_BOOL(RSK_SHUFFLE_MASTER_SWORD, "Shuffle Master Sword", CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), mOptionDescriptions[RSK_SHUFFLE_MASTER_SWORD]);
+ OPT_BOOL(RSK_SHUFFLE_CHILD_WALLET, "Shuffle Child's Wallet", CVAR_RANDOMIZER_SETTING("ShuffleChildWallet"), mOptionDescriptions[RSK_SHUFFLE_CHILD_WALLET], IMFLAG_NONE);
+ OPT_BOOL(RSK_INCLUDE_TYCOON_WALLET, "Include Tycoon Wallet", CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), mOptionDescriptions[RSK_INCLUDE_TYCOON_WALLET]);
+ OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
+ OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
+ OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]);
+ OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
+ OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
+ OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF);
+ OPT_BOOL(RSK_SHUFFLE_FISHING_POLE, "Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]);
+ OPT_U8(RSK_SHUFFLE_MERCHANTS, "Shuffle Merchants", {"Off", "Bean Merchant Only", "All But Beans", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES, "Merchant Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPrices"), mOptionDescriptions[RSK_MERCHANT_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_FIXED_PRICE, "Merchant Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantFixedPrice"), mOptionDescriptions[RSK_MERCHANT_PRICES_FIXED_PRICE], WidgetType::Slider, 10, true);
+ OPT_U8(RSK_MERCHANT_PRICES_RANGE_1, "Merchant Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPriceRange1"), mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_1], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_RANGE_2, "Merchant Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPriceRange2"), mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_2], WidgetType::Slider, 100, true, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT, "Merchant No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantNoWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT, "Merchant Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantChildWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT, "Merchant Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantAdultWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT, "Merchant Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantGiantWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_U8(RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT, "Merchant Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantTycoonWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT], WidgetType::Slider, 10, true, IMFLAG_NONE);
+ OPT_BOOL(RSK_MERCHANT_PRICES_AFFORDABLE, "Merchant Affordable Prices", CVAR_RANDOMIZER_SETTING("MerchantPricesAffordable"), mOptionDescriptions[RSK_MERCHANT_PRICES_AFFORDABLE]);
+ OPT_BOOL(RSK_SHUFFLE_FROG_SONG_RUPEES, "Shuffle Frog Song Rupees", CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]);
+ OPT_BOOL(RSK_SHUFFLE_ADULT_TRADE, "Shuffle Adult Trade", CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), mOptionDescriptions[RSK_SHUFFLE_ADULT_TRADE]);
+ OPT_U8(RSK_SHUFFLE_CHEST_MINIGAME, "Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"});
+ OPT_BOOL(RSK_SHUFFLE_100_GS_REWARD, "Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
+ OPT_U8(RSK_SHUFFLE_BOSS_SOULS, "Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox);
+ OPT_BOOL(RSK_SHUFFLE_DEKU_STICK_BAG, "Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
+ OPT_BOOL(RSK_SHUFFLE_DEKU_NUT_BAG, "Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
+ OPT_U8(RSK_SHUFFLE_FREESTANDING, "Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WidgetType::Combobox, RO_SHUFFLE_FREESTANDING_OFF);
+ OPT_U8(RSK_FISHSANITY, "Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF);
+ OPT_U8(RSK_FISHSANITY_POND_COUNT, "Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE);
+ OPT_BOOL(RSK_FISHSANITY_AGE_SPLIT, "Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]);
+ OPT_BOOL(RSK_SHUFFLE_FAIRIES, "Shuffle Fairies", CVAR_RANDOMIZER_SETTING("ShuffleFairies"), mOptionDescriptions[RSK_SHUFFLE_FAIRIES]);
+ OPT_U8(RSK_SHUFFLE_MAPANDCOMPASS, "Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
+ OPT_U8(RSK_KEYSANITY, "Small Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
+ OPT_U8(RSK_GERUDO_KEYS, "Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA);
+ OPT_U8(RSK_BOSS_KEYSANITY, "Boss Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BossKeysanity"), mOptionDescriptions[RSK_BOSS_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
+ OPT_U8(RSK_GANONS_BOSS_KEY, "Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "100 GS Reward", "Triforce Hunt"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), mOptionDescriptions[RSK_GANONS_BOSS_KEY], WidgetType::Combobox, RO_GANON_BOSS_KEY_VANILLA);
+ OPT_U8(RSK_LACS_STONE_COUNT, "GCBK Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsStoneCount"), "", WidgetType::Slider, 3, true);
+ OPT_U8(RSK_LACS_MEDALLION_COUNT, "GCBK Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), "", WidgetType::Slider, 6, true);
+ OPT_U8(RSK_LACS_REWARD_COUNT, "GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true);
+ OPT_U8(RSK_LACS_DUNGEON_COUNT, "GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true);
+ OPT_U8(RSK_LACS_TOKEN_COUNT, "GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true);
+ OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
+ OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF);
+ OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8);
+ OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_FOREST_TEMPLE, "Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_FIRE_TEMPLE, "Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_WATER_TEMPLE, "Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_SPIRIT_TEMPLE, "Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_SHADOW_TEMPLE, "Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_BOTTOM_OF_THE_WELL, "Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_GTG, "Gerudo Training Ground Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WidgetType::TristateCheckbox, 0);
+ OPT_U8(RSK_KEYRINGS_GANONS_CASTLE, "Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WidgetType::TristateCheckbox, 0);
+ //Dummied out due to redundancy with TimeSavers.SkipChildStealth until such a time that logic needs to consider child stealth e.g. because it's freestanding checks are added to freestanding shuffle.
+ //To undo this dummying, readd this setting to an OptionGroup so it appears in the UI, then edit the timesaver check hooks to look at this, and the timesaver setting to lock itself as needed.
+ OPT_BOOL(RSK_SKIP_CHILD_STEALTH, "Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
+ OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
+ OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP);
+ OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
+ OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9);
+ OPT_U8(RSK_CUCCO_COUNT, "Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7);
+ OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]);
+ OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE);
+ OPT_U8(RSK_HINT_CLARITY, "Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintClarity"), mOptionDescriptions[RSK_HINT_CLARITY], WidgetType::Combobox, RO_HINT_CLARITY_CLEAR, true, IMFLAG_INDENT);
+ OPT_U8(RSK_HINT_DISTRIBUTION, "Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintDistribution"), mOptionDescriptions[RSK_HINT_DISTRIBUTION], WidgetType::Combobox, RO_HINT_DIST_BALANCED, true, IMFLAG_UNINDENT);
+ OPT_BOOL(RSK_TOT_ALTAR_HINT, "ToT Altar Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AltarHint"), mOptionDescriptions[RSK_TOT_ALTAR_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_INDENT);
+ OPT_BOOL(RSK_GANONDORF_HINT, "Ganondorf Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanondorfHint"), mOptionDescriptions[RSK_GANONDORF_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE);
+ OPT_BOOL(RSK_SHEIK_LA_HINT, "Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SheikLAHint"), mOptionDescriptions[RSK_SHEIK_LA_HINT], WidgetType::Checkbox, RO_GENERIC_ON, false, IMFLAG_NONE);
+ OPT_BOOL(RSK_DAMPES_DIARY_HINT, "Dampe's Diary Hint", CVAR_RANDOMIZER_SETTING("DampeHint"), mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_GREG_HINT, "Greg the Green Rupee Hint", CVAR_RANDOMIZER_SETTING("GregHint"), mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_LOACH_HINT, "Hyrule Loach Hint", CVAR_RANDOMIZER_SETTING("LoachHint"), mOptionDescriptions[RSK_LOACH_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_SARIA_HINT, "Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_FISHING_POLE_HINT, "Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_FROGS_HINT, "Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_OOT_HINT, "Ocarina of Time Hint", CVAR_RANDOMIZER_SETTING("OoTHint"), mOptionDescriptions[RSK_OOT_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_BIGGORON_HINT, "Biggoron's Hint", CVAR_RANDOMIZER_SETTING("BiggoronHint"), mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_BIG_POES_HINT, "Big Poes Hint", CVAR_RANDOMIZER_SETTING("BigPoesHint"), mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_CHICKENS_HINT, "Chickens Hint", CVAR_RANDOMIZER_SETTING("ChickensHint"), mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_MALON_HINT, "Malon Hint", CVAR_RANDOMIZER_SETTING("MalonHint"), mOptionDescriptions[RSK_MALON_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_HBA_HINT, "Horseback Archery Hint", CVAR_RANDOMIZER_SETTING("HBAHint"), mOptionDescriptions[RSK_HBA_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_WARP_SONG_HINTS, "Warp Song Hints", CVAR_RANDOMIZER_SETTING("WarpSongText"), mOptionDescriptions[RSK_WARP_SONG_HINTS], IMFLAG_NONE, WidgetType::Checkbox, RO_GENERIC_ON);
+ OPT_BOOL(RSK_SCRUB_TEXT_HINT, "Scrub Hint Text", CVAR_RANDOMIZER_SETTING("ScrubText"), mOptionDescriptions[RSK_SCRUB_TEXT_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_MERCHANT_TEXT_HINT, "Merchant Hint Text", CVAR_RANDOMIZER_SETTING("MerchantText"), mOptionDescriptions[RSK_MERCHANT_TEXT_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_KAK_10_SKULLS_HINT, "10 GS Hint", CVAR_RANDOMIZER_SETTING("10GSHint"), mOptionDescriptions[RSK_KAK_10_SKULLS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_KAK_20_SKULLS_HINT, "20 GS Hint", CVAR_RANDOMIZER_SETTING("20GSHint"), mOptionDescriptions[RSK_KAK_20_SKULLS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_KAK_30_SKULLS_HINT, "30 GS Hint", CVAR_RANDOMIZER_SETTING("30GSHint"), mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_KAK_40_SKULLS_HINT, "40 GS Hint", CVAR_RANDOMIZER_SETTING("40GSHint"), mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_KAK_50_SKULLS_HINT, "50 GS Hint", CVAR_RANDOMIZER_SETTING("50GSHint"), mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_KAK_100_SKULLS_HINT, "100 GS Hint", CVAR_RANDOMIZER_SETTING("100GSHint"), mOptionDescriptions[RSK_KAK_100_SKULLS_HINT], IMFLAG_NONE);
+ OPT_BOOL(RSK_MASK_SHOP_HINT, "Mask Shop Hint", CVAR_RANDOMIZER_SETTING("MaskShopHint"), mOptionDescriptions[RSK_MASK_SHOP_HINT]);
// TODO: Compasses show rewards/woth, maps show dungeon mode
- mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]);
- mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]);
- mOptions[RSK_INFINITE_UPGRADES] = Option::U8("Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]);
- mOptions[RSK_SKELETON_KEY] = Option::Bool("Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]);
- mOptions[RSK_ITEM_POOL] = Option::U8("Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED);
- mOptions[RSK_ICE_TRAPS] = Option::U8("Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL);
+ OPT_BOOL(RSK_BLUE_FIRE_ARROWS, "Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]);
+ OPT_BOOL(RSK_SUNLIGHT_ARROWS, "Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]);
+ OPT_U8(RSK_INFINITE_UPGRADES, "Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]);
+ OPT_BOOL(RSK_SKELETON_KEY, "Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]);
+ OPT_U8(RSK_ITEM_POOL, "Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED);
+ OPT_U8(RSK_ICE_TRAPS, "Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL);
// TODO: Remove Double Defense, Progressive Goron Sword
- mOptions[RSK_STARTING_OCARINA] = Option::U8("Start with Ocarina", {"Off", "Fairy Ocarina", "Ocarina of Time"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingOcarina"), "", WidgetType::Combobox, RO_STARTING_OCARINA_OFF);
- mOptions[RSK_STARTING_DEKU_SHIELD] = Option::Bool("Start with Deku Shield", CVAR_RANDOMIZER_SETTING("StartingDekuShield"));
- mOptions[RSK_STARTING_KOKIRI_SWORD] = Option::Bool("Start with Kokiri Sword", CVAR_RANDOMIZER_SETTING("StartingKokiriSword"));
- mOptions[RSK_STARTING_MASTER_SWORD] = Option::Bool("Start with Master Sword", CVAR_RANDOMIZER_SETTING("StartingMasterSword"));
- mOptions[RSK_STARTING_STICKS] = Option::Bool("Start with Stick Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSticks"), "", WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_STARTING_NUTS] = Option::Bool("Start with Nut Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingNuts"), "", WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_FULL_WALLETS] = Option::Bool("Full Wallets", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FullWallets"), mOptionDescriptions[RSK_FULL_WALLETS], WidgetType::Checkbox, RO_GENERIC_OFF);
- mOptions[RSK_STARTING_ZELDAS_LULLABY] = Option::Bool("Start with Zelda's Lullaby", CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_EPONAS_SONG] = Option::Bool("Start with Epona's Song", CVAR_RANDOMIZER_SETTING("StartingEponasSong"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_SARIAS_SONG] = Option::Bool("Start with Saria's Song", CVAR_RANDOMIZER_SETTING("StartingSariasSong"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_SUNS_SONG] = Option::Bool("Start with Sun's Song", CVAR_RANDOMIZER_SETTING("StartingSunsSong"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_SONG_OF_TIME] = Option::Bool("Start with Song of Time", CVAR_RANDOMIZER_SETTING("StartingSongOfTime"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_SONG_OF_STORMS] = Option::Bool("Start with Song of Storms", CVAR_RANDOMIZER_SETTING("StartingSongOfStorms"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_MINUET_OF_FOREST] = Option::Bool("Start with Minuet of Forest", CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_BOLERO_OF_FIRE] = Option::Bool("Start with Bolero of Fire", CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_SERENADE_OF_WATER] = Option::Bool("Start with Serenade of Water", CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT] = Option::Bool("Start with Requiem of Spirit", CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW] = Option::Bool("Start with Nocturne of Shadow", CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), "", IMFLAG_NONE);
- mOptions[RSK_STARTING_PRELUDE_OF_LIGHT] = Option::Bool("Start with Prelude of Light", CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight"));
- mOptions[RSK_STARTING_SKULLTULA_TOKEN] = Option::U8("Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), "", WidgetType::Slider);
- mOptions[RSK_STARTING_HEARTS] = Option::U8("Starting Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingHearts"), "", WidgetType::Slider, 2);
+ OPT_U8(RSK_STARTING_OCARINA, "Start with Ocarina", {"Off", "Fairy Ocarina", "Ocarina of Time"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingOcarina"), "", WidgetType::Combobox, RO_STARTING_OCARINA_OFF);
+ OPT_BOOL(RSK_STARTING_DEKU_SHIELD, "Start with Deku Shield", CVAR_RANDOMIZER_SETTING("StartingDekuShield"));
+ OPT_BOOL(RSK_STARTING_KOKIRI_SWORD, "Start with Kokiri Sword", CVAR_RANDOMIZER_SETTING("StartingKokiriSword"));
+ OPT_BOOL(RSK_STARTING_MASTER_SWORD, "Start with Master Sword", CVAR_RANDOMIZER_SETTING("StartingMasterSword"));
+ OPT_BOOL(RSK_STARTING_STICKS, "Start with Stick Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSticks"), "", WidgetType::Checkbox, RO_GENERIC_OFF);
+ OPT_BOOL(RSK_STARTING_NUTS, "Start with Nut Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingNuts"), "", WidgetType::Checkbox, RO_GENERIC_OFF);
+ OPT_BOOL(RSK_FULL_WALLETS, "Full Wallets", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FullWallets"), mOptionDescriptions[RSK_FULL_WALLETS], WidgetType::Checkbox, RO_GENERIC_OFF);
+ OPT_BOOL(RSK_STARTING_ZELDAS_LULLABY, "Start with Zelda's Lullaby", CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_EPONAS_SONG, "Start with Epona's Song", CVAR_RANDOMIZER_SETTING("StartingEponasSong"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_SARIAS_SONG, "Start with Saria's Song", CVAR_RANDOMIZER_SETTING("StartingSariasSong"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_SUNS_SONG, "Start with Sun's Song", CVAR_RANDOMIZER_SETTING("StartingSunsSong"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_SONG_OF_TIME, "Start with Song of Time", CVAR_RANDOMIZER_SETTING("StartingSongOfTime"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_SONG_OF_STORMS, "Start with Song of Storms", CVAR_RANDOMIZER_SETTING("StartingSongOfStorms"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_MINUET_OF_FOREST, "Start with Minuet of Forest", CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_BOLERO_OF_FIRE, "Start with Bolero of Fire", CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_SERENADE_OF_WATER, "Start with Serenade of Water", CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_REQUIEM_OF_SPIRIT, "Start with Requiem of Spirit", CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_NOCTURNE_OF_SHADOW, "Start with Nocturne of Shadow", CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), "", IMFLAG_NONE);
+ OPT_BOOL(RSK_STARTING_PRELUDE_OF_LIGHT, "Start with Prelude of Light", CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight"));
+ OPT_U8(RSK_STARTING_SKULLTULA_TOKEN, "Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), "", WidgetType::Slider);
+ OPT_U8(RSK_STARTING_HEARTS, "Starting Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingHearts"), "", WidgetType::Slider, 2);
// TODO: Remainder of Starting Items
- mOptions[RSK_LOGIC_RULES] = Option::U8("Logic", {"Glitchless", "Glitched", "No Logic", "Vanilla"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS);
- mOptions[RSK_ALL_LOCATIONS_REACHABLE] = Option::Bool("All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON);
- mOptions[RSK_SKULLS_SUNS_SONG] = Option::Bool("Night Skulltula's Expect Sun's Song", CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), mOptionDescriptions[RSK_SKULLS_SUNS_SONG]);
- mOptions[RSK_DAMAGE_MULTIPLIER] = Option::U8("Damage Multiplier", {"x1/2", "x1", "x2", "x4", "x8", "x16", "OHKO"}, OptionCategory::Setting, "", "", WidgetType::Slider, RO_DAMAGE_MULTIPLIER_DEFAULT);
+ OPT_U8(RSK_LOGIC_RULES, "Logic", {"Glitchless", "No Logic", "Vanilla"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WidgetType::Combobox, RO_LOGIC_GLITCHLESS);
+ OPT_BOOL(RSK_ALL_LOCATIONS_REACHABLE, "All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WidgetType::Checkbox, RO_GENERIC_ON);
+ OPT_BOOL(RSK_SKULLS_SUNS_SONG, "Night Skulltula's Expect Sun's Song", CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), mOptionDescriptions[RSK_SKULLS_SUNS_SONG]);
+ OPT_U8(RSK_DAMAGE_MULTIPLIER, "Damage Multiplier", {"x1/2", "x1", "x2", "x4", "x8", "x16", "OHKO"}, OptionCategory::Setting, "", "", WidgetType::Slider, RO_DAMAGE_MULTIPLIER_DEFAULT);
// clang-format on
StaticData::optionNameToEnum = PopulateOptionNameToEnum();
@@ -326,205 +333,205 @@ void Settings::CreateOptions() {
mExcludeLocationsOptionsAreas.reserve(RCAREA_INVALID);
// the following are glitches and are currently disabled
- // mTrickOptions[RT_ACUTE_ANGLE_CLIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Acute angle clip", "Enables locations requiring jumpslash clips through walls which meet at an acute angle.");
- // mTrickOptions[RT_ADVANCED_CLIPS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Advanced clips", "Enables locations requiring clips through walls and objects requiring precise jumps or other tricks.");
- // mTrickOptions[RT_BLANK_A] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Blank A", "Enables locations requiring blank A button; NOTE: this requires the 'Quick Putaway' restoration.");
- // mTrickOptions[RT_DOOM_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Doom Jump", "Enables locations requiring doom jumps.");
- // mTrickOptions[RT_EPG] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "EPG", "Enables locations requiring use of the Entrance Point Glitch.");
- // mTrickOptions[RT_EQUIP_SWAP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Equip Swap", "Enables locations requiring use of equip swap; NOTE: this may expect the 'Allow cursor to be over any slot' enhancement to be turned off.");
- // mTrickOptions[RT_EQUIP_SWAP_EXPECTS_DINS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Equip Swap Require's Din's Fire", "Enables locations requiring use of equip swap once Din's Fire is found.");
- // mTrickOptions[RT_FLAME_STORAGE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Flame Storage", "Enables locations requiring flame storage.");
- // mTrickOptions[RT_GROUND_CLIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Ground Clip", "Enables locations requiring ground clips.");
- // mTrickOptions[RT_GROUND_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Ground Jump", "Enables locations requiring ground jumps.");
- // mTrickOptions[RT_HESS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "HESS", "Enables locations requiring a Hyper Extended Super Slide.");
- // mTrickOptions[RT_HOOKSHOT_CLIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Hookshot Clip", "Enables locations requiring hookshot clips.");
- // mTrickOptions[RT_HOOKSHOT_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Hookshot Jump", "Enables locations requiring hookshot jumps.");
- // mTrickOptions[RT_ISG] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "ISG", "Enables locations requiring use of the infinite sword glitch.");
+ // OPT_TRICK(RT_ACUTE_ANGLE_CLIP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Acute angle clip", "Enables locations requiring jumpslash clips through walls which meet at an acute angle.");
+ // OPT_TRICK(RT_ADVANCED_CLIPS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Advanced clips", "Enables locations requiring clips through walls and objects requiring precise jumps or other tricks.");
+ // OPT_TRICK(RT_BLANK_A, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Blank A", "Enables locations requiring blank A button; NOTE: this requires the 'Quick Putaway' restoration.");
+ // OPT_TRICK(RT_DOOM_JUMP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Doom Jump", "Enables locations requiring doom jumps.");
+ // OPT_TRICK(RT_EPG, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "EPG", "Enables locations requiring use of the Entrance Point Glitch.");
+ // OPT_TRICK(RT_EQUIP_SWAP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Equip Swap", "Enables locations requiring use of equip swap; NOTE: this may expect the 'Allow cursor to be over any slot' enhancement to be turned off.");
+ // OPT_TRICK(RT_EQUIP_SWAP_EXPECTS_DINS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Equip Swap Require's Din's Fire", "Enables locations requiring use of equip swap once Din's Fire is found.");
+ // OPT_TRICK(RT_FLAME_STORAGE, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Flame Storage", "Enables locations requiring flame storage.");
+ // OPT_TRICK(RT_GROUND_CLIP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Ground Clip", "Enables locations requiring ground clips.");
+ // OPT_TRICK(RT_GROUND_JUMP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Ground Jump", "Enables locations requiring ground jumps.");
+ // OPT_TRICK(RT_HESS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "HESS", "Enables locations requiring a Hyper Extended Super Slide.");
+ // OPT_TRICK(RT_HOOKSHOT_CLIP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Hookshot Clip", "Enables locations requiring hookshot clips.");
+ // OPT_TRICK(RT_HOOKSHOT_JUMP, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "Hookshot Jump", "Enables locations requiring hookshot jumps.");
+ // OPT_TRICK(RT_ISG, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL, Tricks::Tag::GLITCH}, "ISG", "Enables locations requiring use of the infinite sword glitch.");
- mTrickOptions[RT_VISIBLE_COLLISION] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Pass Through Visible One-Way Collision", "Allows climbing through the platform to reach Impa's House Back as adult with no items and going through the Kakariko Village Gate as child when coming from the Mountain Trail side.");
- mTrickOptions[RT_GROTTOS_WITHOUT_AGONY] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Hidden Grottos without Stone of Agony", "Allows entering hidden grottos without the Stone of Agony.");
- mTrickOptions[RT_FEWER_TUNIC_REQUIREMENTS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, "Fewer Tunic Requirements", "Allows the following possible without Tunics:\n- Enter Water Temple. The area below the center pillar still requires Zora Tunic. Applies to MQ also.\n- Enter Fire Temple. Volvagia still requires Goron tunic. Applies to MQ also, and includes child access to first floor with dungeon shuffle.");
- mTrickOptions[RT_RUSTED_SWITCHES] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Hammer Rusted Switches Through Walls", "Applies to:\n- Fire Temple Highest Goron Chest.\n- MQ Fire Temple Lizalfos Maze.\n- MQ Spirit Trial.");
- mTrickOptions[RT_FLAMING_CHESTS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, "Flaming Chests", "The chests encircled in flames in Gerudo Training Ground and in Spirit Temple can be opened by running into the flames while Link is invincible after taking damage.");
+ OPT_TRICK(RT_VISIBLE_COLLISION, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Pass Through Visible One-Way Collision", "Allows climbing through the platform to reach Impa's House Back as adult with no items and going through the Kakariko Village Gate as child when coming from the Mountain Trail side.");
+ OPT_TRICK(RT_GROTTOS_WITHOUT_AGONY, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Hidden Grottos without Stone of Agony", "Allows entering hidden grottos without the Stone of Agony.");
+ OPT_TRICK(RT_FEWER_TUNIC_REQUIREMENTS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, "Fewer Tunic Requirements", "Allows the following possible without Tunics:\n- Enter Water Temple. The area below the center pillar still requires Zora Tunic. Applies to MQ also.\n- Enter Fire Temple. Volvagia still requires Goron tunic. Applies to MQ also, and includes child access to first floor with dungeon shuffle.");
+ OPT_TRICK(RT_RUSTED_SWITCHES, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Hammer Rusted Switches Through Walls", "Applies to:\n- Fire Temple Highest Goron Chest.\n- MQ Fire Temple Lizalfos Maze.\n- MQ Spirit Trial.");
+ OPT_TRICK(RT_FLAMING_CHESTS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, "Flaming Chests", "The chests encircled in flames in Gerudo Training Ground and in Spirit Temple can be opened by running into the flames while Link is invincible after taking damage.");
// disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely decoupled from rando
- // mTrickOptions[RT_BUNNY_HOOD_JUMPS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, "Bunny Hood Jumps", "Allows reaching locations using Bunny Hood's extended jumps.");
- mTrickOptions[RT_DAMAGE_BOOST_SIMPLE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL}, "Simple damage boosts", "Allows damage boosts in order to reach further locations. Can be combined with \"Simple hover boosts\" for reaching far distances.");
- mTrickOptions[RT_HOVER_BOOST_SIMPLE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL}, "Simple hover boosts", "Allows equipping of hover boots when link is moving at high speeds to extend distance covered. Can be combined with \"Simple damage boosts\" for greater uses.");
- mTrickOptions[RT_BOMBCHU_BEEHIVES] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Bombchu Beehives", "Allows exploding beehives with bombchus.");
- mTrickOptions[RT_BLUE_FIRE_MUD_WALLS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Break Mud Walls with Blue Fire", "Use Blue Fire to break mud walls.");
- mTrickOptions[RT_KF_ADULT_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_KOKIRI_FOREST, {Tricks::Tag::NOVICE}, "Adult Kokiri Forest GS with Hover Boots", "Can be obtained without Hookshot by using the Hover Boots off of one of the roots.");
- mTrickOptions[RT_LW_BRIDGE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_THE_LOST_WOODS, {Tricks::Tag::EXPERT}, "Jump onto the Lost Woods Bridge as Adult with Nothing", "With very precise movement it's possible for adult to jump onto the bridge without needing Longshot, Hover Boots, or Bean.");
- mTrickOptions[RT_LW_MIDO_BACKFLIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_THE_LOST_WOODS, {Tricks::Tag::NOVICE}, "Backflip over Mido as Adult", "With a specific position and angle, you can backflip over Mido.");
- mTrickOptions[RT_LW_GS_BEAN] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_THE_LOST_WOODS, {Tricks::Tag::INTERMEDIATE}, "Lost Woods Adult GS without Bean", "You can collect the token with a precise Hookshot use, as long as you can kill the Skulltula somehow first. It can be killed using Longshot, Bow, Bombchus or Din's Fire.");
- mTrickOptions[RT_HC_STORMS_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_HYRULE_CASTLE, {Tricks::Tag::INTERMEDIATE}, "Hyrule Castle Storms Grotto GS with Just Boomerang", "With precise throws, the Boomerang alone can kill the Skulltula and collect the token, without first needing to blow up the wall.");
- mTrickOptions[RT_KAK_MAN_ON_ROOF] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::NOVICE}, "Man on Roof without Hookshot", "Can be reached by side-hopping off the watchtower as either age, or by jumping onto the potion shop's roof from the ledge as adult.");
- mTrickOptions[RT_KAK_TOWER_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::INTERMEDIATE}, "Kakariko Tower GS with Jump Slash", "Climb the tower as high as you can without touching the Gold Skulltula, then let go and jump slash immediately. By jump-slashing from as low on the ladder as possible to still hit the Skulltula, this trick can be done without taking fall damage.");
- mTrickOptions[RT_KAK_ADULT_WINDMILL_POH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::NOVICE}, "Windmill PoH as Adult with Nothing", "Can jump up to the spinning platform from below as adult.");
- mTrickOptions[RT_KAK_CHILD_WINDMILL_POH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::EXTREME}, "Windmill PoH as Child with Precise Jump Slash", "Can jump up to the spinning platform from below as child with a precise jumpslash timed with the platforms rotation.");
- mTrickOptions[RT_KAK_ROOFTOP_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::ADVANCED}, "Kakariko Rooftop GS with Hover Boots", "Take the Hover Boots from the entrance to Impa's House over to the rooftop of Skulltula House. From there, a precise Hover Boots backwalk with backflip can be used to get onto a hill above the side of the village. And then from there you can Hover onto Impa's rooftop to kill the Skulltula and backflip into the token.");
- mTrickOptions[RT_GY_POH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_THE_GRAVEYARD, {Tricks::Tag::INTERMEDIATE}, "Graveyard Freestanding PoH with Boomerang", "Using a precise moving setup you can obtain the Piece of Heart by having the Boomerang interact with it along the return path.");
- mTrickOptions[RT_GY_CHILD_DAMPE_RACE_POH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_THE_GRAVEYARD, {Tricks::Tag::NOVICE}, "Second Dampe Race as Child", "It is possible to complete the second dampe race as child in under a minute, but it is a strict time limit.");
- mTrickOptions[RT_GY_SHADOW_FIRE_ARROWS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_THE_GRAVEYARD, {Tricks::Tag::EXPERT}, "Shadow Temple Entry with Fire Arrows", "It is possible to light all of the torches to open the Shadow Temple entrance with just Fire Arrows, but you must be very quick, precise, and strategic with how you take your shots.");
- mTrickOptions[RT_DMT_SOIL_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Soil GS without Destroying Boulder", "Bugs will go into the soft soil even while the boulder is still blocking the entrance. Then, using a precise moving setup you can kill the Gold Skulltula and obtain the token by having the Boomerang interact with it along the return path.");
- mTrickOptions[RT_DMT_BOMBABLE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Chest with Strength", "Child Link can blow up the wall using a nearby bomb flower. You must backwalk with the flower and then quickly throw it toward the wall.");
- mTrickOptions[RT_DMT_HOOKSHOT_LOWER_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Lower Red Rock GS with Hookshot", "After killing the Skulltula, the token can be fished out of the rock without needing to destroy it, by using the Hookshot in the correct way.");
- mTrickOptions[RT_DMT_HOVERS_LOWER_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::ADVANCED}, "Death Mountain Trail Lower Red Rock GS with Hover Boots", "After killing the Skulltula, the token can be collected without needing to destroy the rock by backflipping down onto it with the Hover Boots. First use the Hover Boots to stand on a nearby fence, and go for the Skulltula Token from there.");
- mTrickOptions[RT_DMT_BEAN_LOWER_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::EXPERT}, "Death Mountain Trail Lower Red Rock GS with Magic Bean", "After killing the Skulltula, the token can be collected without needing to destroy the rock by jumping down onto it from the bean plant, midflight, with precise timing and positioning.");
- mTrickOptions[RT_DMT_JS_LOWER_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Lower Red Rock GS with Jump Slash", "After killing the Skulltula, the token can be collected without needing to destroy the rock by jump slashing from a precise angle.");
- mTrickOptions[RT_DMT_CLIMB_HOVERS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::ADVANCED}, "Death Mountain Trail Climb with Hover Boots", "It is possible to use the Hover Boots to bypass needing to destroy the boulders blocking the path to the top of Death Mountain.");
- mTrickOptions[RT_DMT_UPPER_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::NOVICE}, "Death Mountain Trail Upper Red Rock GS without Hammer", "After killing the Skulltula, the token can be collected by backflipping into the rock at the correct angle.");
+ // OPT_TRICK(RT_BUNNY_HOOD_JUMPS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, "Bunny Hood Jumps", "Allows reaching locations using Bunny Hood's extended jumps.");
+ OPT_TRICK(RT_DAMAGE_BOOST_SIMPLE, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL}, "Simple damage boosts", "Allows damage boosts in order to reach further locations. Can be combined with \"Simple hover boosts\" for reaching far distances.");
+ OPT_TRICK(RT_HOVER_BOOST_SIMPLE, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL}, "Simple hover boosts", "Allows equipping of hover boots when link is moving at high speeds to extend distance covered. Can be combined with \"Simple damage boosts\" for greater uses.");
+ OPT_TRICK(RT_BOMBCHU_BEEHIVES, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Bombchu Beehives", "Allows exploding beehives with bombchus.");
+ OPT_TRICK(RT_BLUE_FIRE_MUD_WALLS, RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, "Break Mud Walls with Blue Fire", "Use Blue Fire to break mud walls.");
+ OPT_TRICK(RT_KF_ADULT_GS, RCQUEST_BOTH, RA_KOKIRI_FOREST, {Tricks::Tag::NOVICE}, "Adult Kokiri Forest GS with Hover Boots", "Can be obtained without Hookshot by using the Hover Boots off of one of the roots.");
+ OPT_TRICK(RT_LW_BRIDGE, RCQUEST_BOTH, RA_THE_LOST_WOODS, {Tricks::Tag::EXPERT}, "Jump onto the Lost Woods Bridge as Adult with Nothing", "With very precise movement it's possible for adult to jump onto the bridge without needing Longshot, Hover Boots, or Bean.");
+ OPT_TRICK(RT_LW_MIDO_BACKFLIP, RCQUEST_BOTH, RA_THE_LOST_WOODS, {Tricks::Tag::NOVICE}, "Backflip over Mido as Adult", "With a specific position and angle, you can backflip over Mido.");
+ OPT_TRICK(RT_LW_GS_BEAN, RCQUEST_BOTH, RA_THE_LOST_WOODS, {Tricks::Tag::INTERMEDIATE}, "Lost Woods Adult GS without Bean", "You can collect the token with a precise Hookshot use, as long as you can kill the Skulltula somehow first. It can be killed using Longshot, Bow, Bombchus or Din's Fire.");
+ OPT_TRICK(RT_HC_STORMS_GS, RCQUEST_BOTH, RA_HYRULE_CASTLE, {Tricks::Tag::INTERMEDIATE}, "Hyrule Castle Storms Grotto GS with Just Boomerang", "With precise throws, the Boomerang alone can kill the Skulltula and collect the token, without first needing to blow up the wall.");
+ OPT_TRICK(RT_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::NOVICE}, "Man on Roof without Hookshot", "Can be reached by side-hopping off the watchtower as either age, or by jumping onto the potion shop's roof from the ledge as adult.");
+ OPT_TRICK(RT_KAK_TOWER_GS, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::INTERMEDIATE}, "Kakariko Tower GS with Jump Slash", "Climb the tower as high as you can without touching the Gold Skulltula, then let go and jump slash immediately. By jump-slashing from as low on the ladder as possible to still hit the Skulltula, this trick can be done without taking fall damage.");
+ OPT_TRICK(RT_KAK_ADULT_WINDMILL_POH, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::NOVICE}, "Windmill PoH as Adult with Nothing", "Can jump up to the spinning platform from below as adult.");
+ OPT_TRICK(RT_KAK_CHILD_WINDMILL_POH, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::EXTREME}, "Windmill PoH as Child with Precise Jump Slash", "Can jump up to the spinning platform from below as child with a precise jumpslash timed with the platforms rotation.");
+ OPT_TRICK(RT_KAK_ROOFTOP_GS, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, {Tricks::Tag::ADVANCED}, "Kakariko Rooftop GS with Hover Boots", "Take the Hover Boots from the entrance to Impa's House over to the rooftop of Skulltula House. From there, a precise Hover Boots backwalk with backflip can be used to get onto a hill above the side of the village. And then from there you can Hover onto Impa's rooftop to kill the Skulltula and backflip into the token.");
+ OPT_TRICK(RT_GY_POH, RCQUEST_BOTH, RA_THE_GRAVEYARD, {Tricks::Tag::INTERMEDIATE}, "Graveyard Freestanding PoH with Boomerang", "Using a precise moving setup you can obtain the Piece of Heart by having the Boomerang interact with it along the return path.");
+ OPT_TRICK(RT_GY_CHILD_DAMPE_RACE_POH, RCQUEST_BOTH, RA_THE_GRAVEYARD, {Tricks::Tag::NOVICE}, "Second Dampe Race as Child", "It is possible to complete the second dampe race as child in under a minute, but it is a strict time limit.");
+ OPT_TRICK(RT_GY_SHADOW_FIRE_ARROWS, RCQUEST_BOTH, RA_THE_GRAVEYARD, {Tricks::Tag::EXPERT}, "Shadow Temple Entry with Fire Arrows", "It is possible to light all of the torches to open the Shadow Temple entrance with just Fire Arrows, but you must be very quick, precise, and strategic with how you take your shots.");
+ OPT_TRICK(RT_DMT_SOIL_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Soil GS without Destroying Boulder", "Bugs will go into the soft soil even while the boulder is still blocking the entrance. Then, using a precise moving setup you can kill the Gold Skulltula and obtain the token by having the Boomerang interact with it along the return path.");
+ OPT_TRICK(RT_DMT_BOMBABLE, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Chest with Strength", "Child Link can blow up the wall using a nearby bomb flower. You must backwalk with the flower and then quickly throw it toward the wall.");
+ OPT_TRICK(RT_DMT_HOOKSHOT_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Lower Red Rock GS with Hookshot", "After killing the Skulltula, the token can be fished out of the rock without needing to destroy it, by using the Hookshot in the correct way.");
+ OPT_TRICK(RT_DMT_HOVERS_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::ADVANCED}, "Death Mountain Trail Lower Red Rock GS with Hover Boots", "After killing the Skulltula, the token can be collected without needing to destroy the rock by backflipping down onto it with the Hover Boots. First use the Hover Boots to stand on a nearby fence, and go for the Skulltula Token from there.");
+ OPT_TRICK(RT_DMT_BEAN_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::EXPERT}, "Death Mountain Trail Lower Red Rock GS with Magic Bean", "After killing the Skulltula, the token can be collected without needing to destroy the rock by jumping down onto it from the bean plant, midflight, with precise timing and positioning.");
+ OPT_TRICK(RT_DMT_JS_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Trail Lower Red Rock GS with Jump Slash", "After killing the Skulltula, the token can be collected without needing to destroy the rock by jump slashing from a precise angle.");
+ OPT_TRICK(RT_DMT_CLIMB_HOVERS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::ADVANCED}, "Death Mountain Trail Climb with Hover Boots", "It is possible to use the Hover Boots to bypass needing to destroy the boulders blocking the path to the top of Death Mountain.");
+ OPT_TRICK(RT_DMT_UPPER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::NOVICE}, "Death Mountain Trail Upper Red Rock GS without Hammer", "After killing the Skulltula, the token can be collected by backflipping into the rock at the correct angle.");
// disabled for now, only applies when trade quest is not shuffled so there's a timer (currently not considered in logic)
- // mTrickOptions[RT_DMT_BOLERO_BIGGORON] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Deliver Eye Drops with Bolero of Fire", "Playing a warp song normally causes a trade item to spoil immediately, however, it is possible use Bolero to reach Biggoron and still deliver the Eye Drops before they spoil. If you do not wear the Goron Tunic, the heat timer inside the crater will override the trade item\'s timer. When you exit to Death Mountain Trail you will have one second to show the Eye Drops before they expire. You can get extra time to show the Eye Drops if you warp immediately upon receiving them. If you don't have many hearts, you may have to reset the heat timer by quickly dipping in and out of Darunia\'s chamber or quickly equipping and unequipping the Goron Tunic. This trick does not apply if \"Randomize Warp Song Destinations\" is enabled, or if the settings are such that trade items do not need to be delivered within a time limit.");
- mTrickOptions[RT_GC_POT] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, "Goron City Spinning Pot PoH with Bombchu", "A Bombchu can be used to stop the spinning pot, but it can be quite finicky to get it to work.");
- mTrickOptions[RT_GC_POT_STRENGTH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::INTERMEDIATE}, "Goron City Spinning Pot PoH with Strength", "Allows for stopping the Goron City Spinning Pot using a bomb flower alone, requiring strength in lieu of inventory explosives.");
- mTrickOptions[RT_GC_ROLLING_STRENGTH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::INTERMEDIATE}, "Rolling Goron (Hot Rodder Goron) as Child with Strength", "Use the bombflower on the stairs or near Medigoron. Timing is tight, especially without backwalking.");
- mTrickOptions[RT_GC_LEFTMOST] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, "Goron City Maze Left Chest with Hover Boots", "A precise backwalk starting from on top of the crate and ending with a precisely-timed backflip can reach this chest without needing either the Hammer or Silver Gauntlets.");
- mTrickOptions[RT_GC_GROTTO] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, "Goron City Grotto with Hookshot While Taking Damage", "It is possible to reach the Goron City Grotto by quickly using the Hookshot while in the midst of taking damage from the lava floor.");
- mTrickOptions[RT_GC_LINK_GORON_DINS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::NOVICE}, "Stop Link the Goron with Din\'s Fire", "The timing is quite awkward.");
- mTrickOptions[RT_DMC_HOVER_BEAN_POH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::NOVICE}, "Crater\'s Bean PoH with Hover Boots", "Hover from the base of the bridge near Goron City and walk up the very steep slope.");
- mTrickOptions[RT_DMC_BOLERO_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::EXTREME}, "Death Mountain Crater Jump to Bolero", "As Adult, using a shield to drop a pot while you have the perfect speed and position, the pot can push you that little extra distance you need to jump across the gap in the bridge.");
- mTrickOptions[RT_DMC_BOULDER_JS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::NOVICE}, "Death Mountain Crater Upper to Lower with Hammer", "With the Hammer, you can jump slash the rock twice in the same jump in order to destroy it before you fall into the lava.");
- mTrickOptions[RT_DMC_BOULDER_SKIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Crater Upper to Lower Boulder Skip", "As adult, With careful positioning, you can jump to the ledge where the boulder is, then use repeated ledge grabs to shimmy to a climbable ledge. This trick supersedes \"Death Mountain Crater Upper to Lower with Hammer\".");
- mTrickOptions[RT_ZR_LOWER] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::INTERMEDIATE}, "Zora\'s River Lower Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required.");
- mTrickOptions[RT_ZR_UPPER] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::INTERMEDIATE}, "Zora\'s River Upper Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required.");
- mTrickOptions[RT_ZR_HOVERS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::NOVICE}, "Zora\'s Domain Entry with Hover Boots", "Can hover behind the waterfall as adult.");
- mTrickOptions[RT_ZR_CUCCO] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::NOVICE}, "Zora\'s Domain Entry with Cucco", "You can fly behind the waterfall with a Cucco as child.");
- mTrickOptions[RT_ZD_KING_ZORA_SKIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_DOMAIN, {Tricks::Tag::INTERMEDIATE}, "Skip King Zora as Adult with Nothing", "With a precise jump as adult, it is possible to get on the fence next to King Zora from the front to access Zora's Fountain.");
- mTrickOptions[RT_ZD_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_DOMAIN, {Tricks::Tag::INTERMEDIATE}, "Zora\'s Domain GS with No Additional Items", "A precise jump slash can kill the Skulltula and recoil back onto the top of the frozen waterfall. To kill it, the logic normally guarantees one of Hookshot, Bow, or Magic.");
- mTrickOptions[RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_FOUNTAIN, {Tricks::Tag::NOVICE}, "Zora\'s Fountain Great Fairy Without Explosives", "It's possible to use silver gauntlets to pick up the silver rock and hammer to break the rock below it, allowing you to ledge grab the edge of the hole and get past the breakable wall (hammer can't break the wall itself).");
- mTrickOptions[RT_LH_LAB_WALL_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_LAKE_HYLIA, {Tricks::Tag::NOVICE}, "Lake Hylia Lab Wall GS with Jump Slash", "The jump slash to actually collect the token is somewhat precise.");
- mTrickOptions[RT_LH_LAB_DIVING] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_LAKE_HYLIA, {Tricks::Tag::NOVICE}, "Lake Hylia Lab Dive without Gold Scale", "Remove the Iron Boots in the midst of Hookshotting the underwater crate.");
- mTrickOptions[RT_LH_WATER_HOOKSHOT] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_LAKE_HYLIA, {Tricks::Tag::INTERMEDIATE}, "Water Temple Entry without Iron Boots using Hookshot", "When entering Water Temple using Gold Scale instead of Iron Boots, the Longshot is usually used to be able to hit the switch and open the gate. But, by standing in a particular spot, the switch can be hit with only the reach of the Hookshot.");
- mTrickOptions[RT_GV_CRATE_HOVERS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GERUDO_VALLEY, {Tricks::Tag::INTERMEDIATE}, "Gerudo Valley Crate PoH as Adult with Hover Boots", "From the far side of Gerudo Valley, a precise Hover Boots movement and jump-slash recoil can allow adult to reach the ledge with the crate PoH without needing Longshot. You will take fall damage.");
- mTrickOptions[RT_GF_KITCHEN] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GERUDO_FORTRESS, {Tricks::Tag::NOVICE}, "Thieves\' Hideout \"Kitchen\" with No Additional Items", "Allows passing through the kitchen by avoiding being seen by the guards. The logic normally guarantees Bow or Hookshot to stun them from a distance, or Hover Boots to cross the room without needing to deal with the guards.");
- mTrickOptions[RT_GF_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GERUDO_FORTRESS, {Tricks::Tag::NOVICE}, "Gerudo\'s Fortress Ledge Jumps", "Adult can jump onto the top roof of the fortress without going through the interior of the hideout.");
- mTrickOptions[RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GERUDO_FORTRESS, {Tricks::Tag::NOVICE}, "Gerudo\'s Fortress Warriors with Difficult Weapons", "Warriors can be defeated with slingshot or bombchus.");
+ // OPT_TRICK(RT_DMT_BOLERO_BIGGORON, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, {Tricks::Tag::INTERMEDIATE}, "Deliver Eye Drops with Bolero of Fire", "Playing a warp song normally causes a trade item to spoil immediately, however, it is possible use Bolero to reach Biggoron and still deliver the Eye Drops before they spoil. If you do not wear the Goron Tunic, the heat timer inside the crater will override the trade item\'s timer. When you exit to Death Mountain Trail you will have one second to show the Eye Drops before they expire. You can get extra time to show the Eye Drops if you warp immediately upon receiving them. If you don't have many hearts, you may have to reset the heat timer by quickly dipping in and out of Darunia\'s chamber or quickly equipping and unequipping the Goron Tunic. This trick does not apply if \"Randomize Warp Song Destinations\" is enabled, or if the settings are such that trade items do not need to be delivered within a time limit.");
+ OPT_TRICK(RT_GC_POT, RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, "Goron City Spinning Pot PoH with Bombchu", "A Bombchu can be used to stop the spinning pot, but it can be quite finicky to get it to work.");
+ OPT_TRICK(RT_GC_POT_STRENGTH, RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::INTERMEDIATE}, "Goron City Spinning Pot PoH with Strength", "Allows for stopping the Goron City Spinning Pot using a bomb flower alone, requiring strength in lieu of inventory explosives.");
+ OPT_TRICK(RT_GC_ROLLING_STRENGTH, RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::INTERMEDIATE}, "Rolling Goron (Hot Rodder Goron) as Child with Strength", "Use the bombflower on the stairs or near Medigoron. Timing is tight, especially without backwalking.");
+ OPT_TRICK(RT_GC_LEFTMOST, RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, "Goron City Maze Left Chest with Hover Boots", "A precise backwalk starting from on top of the crate and ending with a precisely-timed backflip can reach this chest without needing either the Hammer or Silver Gauntlets.");
+ OPT_TRICK(RT_GC_GROTTO, RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, "Goron City Grotto with Hookshot While Taking Damage", "It is possible to reach the Goron City Grotto by quickly using the Hookshot while in the midst of taking damage from the lava floor.");
+ OPT_TRICK(RT_GC_LINK_GORON_DINS, RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::NOVICE}, "Stop Link the Goron with Din\'s Fire", "The timing is quite awkward.");
+ OPT_TRICK(RT_DMC_HOVER_BEAN_POH, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::NOVICE}, "Crater\'s Bean PoH with Hover Boots", "Hover from the base of the bridge near Goron City and walk up the very steep slope.");
+ OPT_TRICK(RT_DMC_BOLERO_JUMP, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::EXTREME}, "Death Mountain Crater Jump to Bolero", "As Adult, using a shield to drop a pot while you have the perfect speed and position, the pot can push you that little extra distance you need to jump across the gap in the bridge.");
+ OPT_TRICK(RT_DMC_BOULDER_JS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::NOVICE}, "Death Mountain Crater Upper to Lower with Hammer", "With the Hammer, you can jump slash the rock twice in the same jump in order to destroy it before you fall into the lava.");
+ OPT_TRICK(RT_DMC_BOULDER_SKIP, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::INTERMEDIATE}, "Death Mountain Crater Upper to Lower Boulder Skip", "As adult, With careful positioning, you can jump to the ledge where the boulder is, then use repeated ledge grabs to shimmy to a climbable ledge. This trick supersedes \"Death Mountain Crater Upper to Lower with Hammer\".");
+ OPT_TRICK(RT_ZR_LOWER, RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::INTERMEDIATE}, "Zora\'s River Lower Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required.");
+ OPT_TRICK(RT_ZR_UPPER, RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::INTERMEDIATE}, "Zora\'s River Upper Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required.");
+ OPT_TRICK(RT_ZR_HOVERS, RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::NOVICE}, "Zora\'s Domain Entry with Hover Boots", "Can hover behind the waterfall as adult.");
+ OPT_TRICK(RT_ZR_CUCCO, RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::NOVICE}, "Zora\'s Domain Entry with Cucco", "You can fly behind the waterfall with a Cucco as child.");
+ OPT_TRICK(RT_ZD_KING_ZORA_SKIP, RCQUEST_BOTH, RA_ZORAS_DOMAIN, {Tricks::Tag::INTERMEDIATE}, "Skip King Zora as Adult with Nothing", "With a precise jump as adult, it is possible to get on the fence next to King Zora from the front to access Zora's Fountain.");
+ OPT_TRICK(RT_ZD_GS, RCQUEST_BOTH, RA_ZORAS_DOMAIN, {Tricks::Tag::INTERMEDIATE}, "Zora\'s Domain GS with No Additional Items", "A precise jump slash can kill the Skulltula and recoil back onto the top of the frozen waterfall. To kill it, the logic normally guarantees one of Hookshot, Bow, or Magic.");
+ OPT_TRICK(RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES, RCQUEST_BOTH, RA_ZORAS_FOUNTAIN, {Tricks::Tag::NOVICE}, "Zora\'s Fountain Great Fairy Without Explosives", "It's possible to use silver gauntlets to pick up the silver rock and hammer to break the rock below it, allowing you to ledge grab the edge of the hole and get past the breakable wall (hammer can't break the wall itself).");
+ OPT_TRICK(RT_LH_LAB_WALL_GS, RCQUEST_BOTH, RA_LAKE_HYLIA, {Tricks::Tag::NOVICE}, "Lake Hylia Lab Wall GS with Jump Slash", "The jump slash to actually collect the token is somewhat precise.");
+ OPT_TRICK(RT_LH_LAB_DIVING, RCQUEST_BOTH, RA_LAKE_HYLIA, {Tricks::Tag::NOVICE}, "Lake Hylia Lab Dive without Gold Scale", "Remove the Iron Boots in the midst of Hookshotting the underwater crate.");
+ OPT_TRICK(RT_LH_WATER_HOOKSHOT, RCQUEST_BOTH, RA_LAKE_HYLIA, {Tricks::Tag::INTERMEDIATE}, "Water Temple Entry without Iron Boots using Hookshot", "When entering Water Temple using Gold Scale instead of Iron Boots, the Longshot is usually used to be able to hit the switch and open the gate. But, by standing in a particular spot, the switch can be hit with only the reach of the Hookshot.");
+ OPT_TRICK(RT_GV_CRATE_HOVERS, RCQUEST_BOTH, RA_GERUDO_VALLEY, {Tricks::Tag::INTERMEDIATE}, "Gerudo Valley Crate PoH as Adult with Hover Boots", "From the far side of Gerudo Valley, a precise Hover Boots movement and jump-slash recoil can allow adult to reach the ledge with the crate PoH without needing Longshot. You will take fall damage.");
+ OPT_TRICK(RT_GF_KITCHEN, RCQUEST_BOTH, RA_GERUDO_FORTRESS, {Tricks::Tag::NOVICE}, "Thieves\' Hideout \"Kitchen\" with No Additional Items", "Allows passing through the kitchen by avoiding being seen by the guards. The logic normally guarantees Bow or Hookshot to stun them from a distance, or Hover Boots to cross the room without needing to deal with the guards.");
+ OPT_TRICK(RT_GF_JUMP, RCQUEST_BOTH, RA_GERUDO_FORTRESS, {Tricks::Tag::NOVICE}, "Gerudo\'s Fortress Ledge Jumps", "Adult can jump onto the top roof of the fortress without going through the interior of the hideout.");
+ OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, {Tricks::Tag::NOVICE}, "Gerudo\'s Fortress Warriors with Difficult Weapons", "Warriors can be defeated with slingshot or bombchus.");
// disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely decoupled from rando
- // mTrickOptions[RT_HW_BUNNY_CROSSING] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::NOVICE}, "Wasteland Crossing with Bunny Hood", "You can beat the quicksand by using the increased speed of the Bunny Hood. Note that jumping to the carpet merchant as child typically requires a fairly precise jump slash.");
- mTrickOptions[RT_HW_CROSSING] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::INTERMEDIATE}, "Wasteland Crossing without Hover Boots or Longshot", "You can beat the quicksand by backwalking across it in a specific way. Note that jumping to the carpet merchant as child typically requires a fairly precise jump slash.");
- mTrickOptions[RT_LENS_HW] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::INTERMEDIATE}, "Lensless Wasteland", "By memorizing the path, you can travel through the Wasteland without using the Lens of Truth to see the Poe. The equivalent trick for going in reverse through the Wasteland is \"Reverse Wasteland\".");
- mTrickOptions[RT_HW_REVERSE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::INTERMEDIATE}, "Reverse Wasteland", "By memorizing the path, you can travel through the Wasteland in reverse. Note that jumping to the carpet merchant as child typically requires a fairly precise jump slash. The equivalent trick for going forward through the Wasteland is \"Lensless Wasteland\". To cross the river of sand with no additional items, be sure to also enable \"Wasteland Crossing without Hover Boots or Longshot\". Unless all overworld entrances are randomized, child Link will not be expected to do anything at Gerudo's Fortress.");
- mTrickOptions[RT_COLOSSUS_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DESERT_COLOSSUS, {Tricks::Tag::NOVICE}, "Colossus Hill GS with Hookshot", "Somewhat precise. If you kill enough Leevers you can get enough of a break to take some time to aim more carefully.");
- mTrickOptions[RT_DEKU_BASEMENT_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree Basement Vines GS with Jump Slash", "Can be defeated by doing a precise jump slash.");
- mTrickOptions[RT_DEKU_B1_SKIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEKU_TREE, {Tricks::Tag::INTERMEDIATE}, "Deku Tree Basement without Slingshot", "A precise jump can be used to skip needing to use the Slingshot to go around B1 of the Deku Tree. If used with the \"Closed Forest\" setting, a Slingshot will not be guaranteed to exist somewhere inside the Forest. This trick applies to both Vanilla and Master Quest.");
- mTrickOptions[RT_DEKU_B1_BOW_WEBS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree Basement Web to Gohma with Bow", "All spider web walls in the Deku Tree basement can be burnt as adult with just a bow by shooting through torches. This trick only applies to the circular web leading to Gohma; the two vertical webs are always in logic. Backflip onto the chest near the torch at the bottom of the vine wall. With precise positioning you can shoot through the torch to the right edge of the circular web. This allows completion of adult Deku Tree with no fire source.");
- mTrickOptions[RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree Basement Backflip over Spiked Log", "Allows backflipping over the spiked log in the Deku Tree basement in vanilla. Only relevant if \"Shuffle Swim\" is enabled.");
- mTrickOptions[RT_DEKU_MQ_COMPASS_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree MQ Compass Room GS Boulders with Just Hammer", "Climb to the top of the vines, then let go and jump slash immediately to destroy the boulders using the Hammer, without needing to spawn a Song of Time block.");
- mTrickOptions[RT_DEKU_MQ_LOG] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree MQ Roll Under the Spiked Log", "You can get past the spiked log by rolling to briefly shrink your hitbox. As adult, the timing is a bit more precise.");
- mTrickOptions[RT_DC_SCARECROW_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Scarecrow GS with Armos Statue", "You can jump off an Armos Statue to reach the alcove with the Gold Skulltula. It takes quite a long time to pull the statue the entire way. The jump to the alcove can be a bit picky when done as child.");
- mTrickOptions[RT_DC_VINES_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Vines GS from Below with Longshot", "The vines upon which this Skulltula rests are one-sided collision. You can use the Longshot to get it from below, by shooting it through the vines, bypassing the need to lower the staircase.");
- mTrickOptions[RT_DC_STAIRCASE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Staircase with Bow", "The Bow can be used to knock down the stairs with two well-timed shots.");
- mTrickOptions[RT_DC_SLINGSHOT_SKIP] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::EXPERT}, "Dodongo\'s Cavern Child Slingshot Skips", "With precise platforming, child can cross the platforms while the flame circles are there. When enabling this trick, it's recommended that you also enable the Adult variant: \"Dodongo's Cavern Spike Trap Room Jump without Hover Boots\".");
- mTrickOptions[RT_DC_SCRUB_ROOM] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Two Scrub Room with Strength", "With help from a conveniently-positioned block, Adult can quickly carry a bomb flower over to destroy the mud wall blocking the room with two Deku Scrubs.");
- mTrickOptions[RT_DC_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Spike Trap Room Jump without Hover Boots", "The jump is adult Link only. Applies to both Vanilla and MQ.");
- mTrickOptions[RT_DC_HAMMER_FLOOR] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Smash the Boss Lobby Floor", "The bombable floor before King Dodongo can be destroyed with Hammer if hit in the very center. This is only relevant with Shuffle Boss Entrances or if Dodongo's Cavern is MQ and either variant of \"Dodongo's Cavern MQ Light the Eyes with Strength\" is on.");
- mTrickOptions[RT_DC_MQ_CHILD_BOMBS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DODONGOS_CAVERN, {Tricks::Tag::ADVANCED}, "Dodongo\'s Cavern MQ Early Bomb Bag Area as Child", "With a precise jump slash from above, you can reach the Bomb Bag area as only child without needing a Slingshot. You will take fall damage.");
- mTrickOptions[RT_DC_MQ_CHILD_EYES] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DODONGOS_CAVERN, {Tricks::Tag::EXPERT}, "Dodongo\'s Cavern MQ Light the Eyes with Strength as Child", "If you move very quickly, it is possible to use the bomb flower at the top of the room to light the eyes. To perform this trick as child is significantly more difficult than adult. The player is also expected to complete the DC back area without explosives, including getting past the Armos wall to the switch for the boss door.");
- mTrickOptions[RT_DC_MQ_ADULT_EYES] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DODONGOS_CAVERN, {Tricks::Tag::ADVANCED}, "Dodongo\'s Cavern MQ Light the Eyes with Strength as Adult", "If you move very quickly, it is possible to use the bomb flower at the top of the room to light the eyes.");
- mTrickOptions[RT_JABU_ALCOVE_JUMP_DIVE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_JABU_JABUS_BELLY, {Tricks::Tag::NOVICE}, "Jabu Underwater Alcove as Adult with Jump Dive", "Standing above the underwater tunnel leading to the scrub, jump down and swim through the tunnel. This allows adult to access the alcove with no Scale or Iron Boots. In vanilla Jabu, this alcove has a business scrub. In MQ Jabu, it has the compass chest and a door switch for the main floor.");
- mTrickOptions[RT_JABU_BOSS_HOVER] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, {Tricks::Tag::INTERMEDIATE}, "Jabu Near Boss Room with Hover Boots", "A box for the blue switch can be carried over by backwalking with one while the elevator is at its peak. Alternatively, you can skip transporting a box by quickly rolling from the switch and opening the door before it closes. However, the timing for this is very tight.");
- mTrickOptions[RT_JABU_NEAR_BOSS_RANGED] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_JABU_JABUS_BELLY, {Tricks::Tag::NOVICE}, "Jabu Near Boss Ceiling Switch/GS without Boomerang or Explosives", "Vanilla Jabu: From near the entrance into the room, you can hit the switch that opens the door to the boss room using a precisely-aimed use of the Slingshot, Bow, or Longshot. As well, if you climb to the top of the vines you can stand on the right edge of the platform and shoot around the glass. From this distance, even the Hookshot can reach the switch. This trick is only relevant if \"Shuffle Boss Entrances\" is enabled. MQ Jabu: A Gold Skulltula Token can be collected with the Hookshot or Longshot using the same methods as hitting the switch in vanilla. This MQ trick is not currently relevant in logic.");
- mTrickOptions[RT_JABU_NEAR_BOSS_EXPLOSIVES] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, {Tricks::Tag::INTERMEDIATE}, "Jabu Near Boss Ceiling Switch with Explosives", "You can hit the switch that opens the door to the boss room using a precisely-aimed Bombchu. Also, using the Hover Boots, adult can throw a Bomb at the switch. This trick is only relevant if \"Shuffle Boss Entrances\" is enabled.");
- mTrickOptions[RT_LENS_JABU_MQ] = TrickOption::LogicTrick(RCQUEST_MQ, RA_JABU_JABUS_BELLY, {Tricks::Tag::NOVICE}, "Jabu MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Jabu MQ.");
- mTrickOptions[RT_JABU_MQ_RANG_JUMP] = TrickOption::LogicTrick(RCQUEST_MQ, RA_JABU_JABUS_BELLY, {Tricks::Tag::ADVANCED}, "Jabu MQ Compass Chest with Boomerang", "Boomerang can reach the cow switch to spawn the chest by targeting the cow, jumping off of the ledge where the chest spawns, and throwing the Boomerang in midair.");
- mTrickOptions[RT_JABU_MQ_SOT_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_JABU_JABUS_BELLY, {Tricks::Tag::INTERMEDIATE}, "Jabu MQ Song of Time Block GS with Boomerang", "Allow the Boomerang to return to you through the Song of Time block to grab the token.");
- mTrickOptions[RT_LENS_BOTW] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well without Lens of Truth", "Removes the requirements for the Lens of Truth in Bottom of the Well.");
- mTrickOptions[RT_BOTW_CHILD_DEADHAND] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Child Dead Hand without Kokiri Sword", "Requires 9 sticks or 5 jump slashes.");
- mTrickOptions[RT_BOTW_BASEMENT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well Map Chest with Strength & Sticks", "The chest in the basement can be reached with strength by doing a jump slash with a lit stick to access the bomb flowers.");
- mTrickOptions[RT_BOTW_MQ_PITS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well MQ Jump Over the Pits", "While the pits in Bottom of the Well don't allow you to jump just by running straight at them, you can still get over them by side-hopping or backflipping across. With explosives, this allows you to access the central areas without Zelda's Lullaby. With Zelda's Lullaby, it allows you to access the west inner room without explosives.");
- mTrickOptions[RT_BOTW_MQ_DEADHAND_KEY] = TrickOption::LogicTrick(RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well MQ Dead Hand Freestanding Key with Boomerang", "Boomerang can fish the item out of the rubble without needing explosives to blow it up.");
- mTrickOptions[RT_FOREST_FIRST_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple First Room GS with Difficult-to-Use Weapons", "Allows killing this Skulltula with Sword or Sticks by jump slashing it as you let go from the vines. You can avoid taking fall damage by recoiling onto the tree. Also allows killing it as Child with a Bomb throw. It's much more difficult to use a Bomb as child due to Child Link's shorter height.");
- mTrickOptions[RT_FOREST_OUTDOORS_EAST_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple East Courtyard GS with Boomerang", "Precise Boomerang throws can allow child to kill the Skulltula and collect the token.");
- mTrickOptions[RT_FOREST_VINES] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple East Courtyard Vines with Hookshot", "The vines in Forest Temple leading to where the well drain switch is in the standard form can be barely reached with just the Hookshot. Applies to MQ also.");
- mTrickOptions[RT_FOREST_OUTDOORS_LEDGE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple NE Outdoors Ledge with Hover Boots", "With precise Hover Boots movement you can fall down to this ledge from upper balconies. If done precisely enough, it is not necessary to take fall damage. In MQ, this skips a Longshot requirement. In Vanilla, this can skip a Hookshot requirement in entrance randomizer.");
- mTrickOptions[RT_FOREST_DOORFRAME] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::ADVANCED}, "Forest Temple East Courtyard Door Frame with Hover Boots", "A precise Hover Boots movement from the upper balconies in this courtyard can be used to get on top of the door frame. Applies to both Vanilla and Master Quest. In Vanilla, from on top the door frame you can summon Pierre, allowing you to access the falling ceiling room early. In Master Quest, this allows you to obtain the GS on the door frame as adult without Hookshot or Song of Time.");
- mTrickOptions[RT_FOREST_OUTSIDE_BACKDOOR] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::ADVANCED}, "Forest Temple Outside Backdoor with Jump Slash", "A jump slash recoil can be used to reach the ledge in the block puzzle room that leads to the west courtyard. This skips a potential Hover Boots requirement in vanilla, and it can sometimes apply in MQ as well. This trick can be performed as both ages.");
- mTrickOptions[RT_FOREST_OUTDOORS_HEARTS_BOOMERANG] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple Outside Hearts with Boomerang", "A well aimed boomerang from the water's edge can reach the hearts from ground level. If unable to swim, you can back away from the water while the boomerang is returning so the hearts land on the ground.");
- mTrickOptions[RT_FOREST_MQ_WELL_SWIM] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::ADVANCED}, "Swim Through Forest Temple MQ Well with Hookshot", "Shoot the vines in the well as low and as far to the right as possible, and then immediately swim under the ceiling to the right. This can only be required if Forest Temple is in its Master Quest form.");
- mTrickOptions[RT_FOREST_MQ_BLOCK_PUZZLE] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Skip Forest Temple MQ Block Puzzle with Bombchu", "Send the Bombchu straight up the center of the wall directly to the left upon entering the room.");
+ // OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::NOVICE}, "Wasteland Crossing with Bunny Hood", "You can beat the quicksand by using the increased speed of the Bunny Hood. Note that jumping to the carpet merchant as child typically requires a fairly precise jump slash.");
+ OPT_TRICK(RT_HW_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::INTERMEDIATE}, "Wasteland Crossing without Hover Boots or Longshot", "You can beat the quicksand by backwalking across it in a specific way. Note that jumping to the carpet merchant as child typically requires a fairly precise jump slash.");
+ OPT_TRICK(RT_LENS_HW, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::INTERMEDIATE}, "Lensless Wasteland", "By memorizing the path, you can travel through the Wasteland without using the Lens of Truth to see the Poe. The equivalent trick for going in reverse through the Wasteland is \"Reverse Wasteland\".");
+ OPT_TRICK(RT_HW_REVERSE, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::INTERMEDIATE}, "Reverse Wasteland", "By memorizing the path, you can travel through the Wasteland in reverse. Note that jumping to the carpet merchant as child typically requires a fairly precise jump slash. The equivalent trick for going forward through the Wasteland is \"Lensless Wasteland\". To cross the river of sand with no additional items, be sure to also enable \"Wasteland Crossing without Hover Boots or Longshot\". Unless all overworld entrances are randomized, child Link will not be expected to do anything at Gerudo's Fortress.");
+ OPT_TRICK(RT_COLOSSUS_GS, RCQUEST_BOTH, RA_DESERT_COLOSSUS, {Tricks::Tag::NOVICE}, "Colossus Hill GS with Hookshot", "Somewhat precise. If you kill enough Leevers you can get enough of a break to take some time to aim more carefully.");
+ OPT_TRICK(RT_DEKU_BASEMENT_GS, RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree Basement Vines GS with Jump Slash", "Can be defeated by doing a precise jump slash.");
+ OPT_TRICK(RT_DEKU_B1_SKIP, RCQUEST_BOTH, RA_DEKU_TREE, {Tricks::Tag::INTERMEDIATE}, "Deku Tree Basement without Slingshot", "A precise jump can be used to skip needing to use the Slingshot to go around B1 of the Deku Tree. If used with the \"Closed Forest\" setting, a Slingshot will not be guaranteed to exist somewhere inside the Forest. This trick applies to both Vanilla and Master Quest.");
+ OPT_TRICK(RT_DEKU_B1_BOW_WEBS, RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree Basement Web to Gohma with Bow", "All spider web walls in the Deku Tree basement can be burnt as adult with just a bow by shooting through torches. This trick only applies to the circular web leading to Gohma; the two vertical webs are always in logic. Backflip onto the chest near the torch at the bottom of the vine wall. With precise positioning you can shoot through the torch to the right edge of the circular web. This allows completion of adult Deku Tree with no fire source.");
+ OPT_TRICK(RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG, RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree Basement Backflip over Spiked Log", "Allows backflipping over the spiked log in the Deku Tree basement in vanilla. Only relevant if \"Shuffle Swim\" is enabled.");
+ OPT_TRICK(RT_DEKU_MQ_COMPASS_GS, RCQUEST_MQ, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree MQ Compass Room GS Boulders with Just Hammer", "Climb to the top of the vines, then let go and jump slash immediately to destroy the boulders using the Hammer, without needing to spawn a Song of Time block.");
+ OPT_TRICK(RT_DEKU_MQ_LOG, RCQUEST_MQ, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, "Deku Tree MQ Roll Under the Spiked Log", "You can get past the spiked log by rolling to briefly shrink your hitbox. As adult, the timing is a bit more precise.");
+ OPT_TRICK(RT_DC_SCARECROW_GS, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Scarecrow GS with Armos Statue", "You can jump off an Armos Statue to reach the alcove with the Gold Skulltula. It takes quite a long time to pull the statue the entire way. The jump to the alcove can be a bit picky when done as child.");
+ OPT_TRICK(RT_DC_VINES_GS, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Vines GS from Below with Longshot", "The vines upon which this Skulltula rests are one-sided collision. You can use the Longshot to get it from below, by shooting it through the vines, bypassing the need to lower the staircase.");
+ OPT_TRICK(RT_DC_STAIRCASE, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Staircase with Bow", "The Bow can be used to knock down the stairs with two well-timed shots.");
+ OPT_TRICK(RT_DC_SLINGSHOT_SKIP, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::EXPERT}, "Dodongo\'s Cavern Child Slingshot Skips", "With precise platforming, child can cross the platforms while the flame circles are there. When enabling this trick, it's recommended that you also enable the Adult variant: \"Dodongo's Cavern Spike Trap Room Jump without Hover Boots\".");
+ OPT_TRICK(RT_DC_SCRUB_ROOM, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Two Scrub Room with Strength", "With help from a conveniently-positioned block, Adult can quickly carry a bomb flower over to destroy the mud wall blocking the room with two Deku Scrubs.");
+ OPT_TRICK(RT_DC_JUMP, RCQUEST_BOTH, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Spike Trap Room Jump without Hover Boots", "The jump is adult Link only. Applies to both Vanilla and MQ.");
+ OPT_TRICK(RT_DC_HAMMER_FLOOR, RCQUEST_BOTH, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, "Dodongo\'s Cavern Smash the Boss Lobby Floor", "The bombable floor before King Dodongo can be destroyed with Hammer if hit in the very center. This is only relevant with Shuffle Boss Entrances or if Dodongo's Cavern is MQ and either variant of \"Dodongo's Cavern MQ Light the Eyes with Strength\" is on.");
+ OPT_TRICK(RT_DC_MQ_CHILD_BOMBS, RCQUEST_MQ, RA_DODONGOS_CAVERN, {Tricks::Tag::ADVANCED}, "Dodongo\'s Cavern MQ Early Bomb Bag Area as Child", "With a precise jump slash from above, you can reach the Bomb Bag area as only child without needing a Slingshot. You will take fall damage.");
+ OPT_TRICK(RT_DC_MQ_CHILD_EYES, RCQUEST_MQ, RA_DODONGOS_CAVERN, {Tricks::Tag::EXPERT}, "Dodongo\'s Cavern MQ Light the Eyes with Strength as Child", "If you move very quickly, it is possible to use the bomb flower at the top of the room to light the eyes. To perform this trick as child is significantly more difficult than adult. The player is also expected to complete the DC back area without explosives, including getting past the Armos wall to the switch for the boss door.");
+ OPT_TRICK(RT_DC_MQ_ADULT_EYES, RCQUEST_MQ, RA_DODONGOS_CAVERN, {Tricks::Tag::ADVANCED}, "Dodongo\'s Cavern MQ Light the Eyes with Strength as Adult", "If you move very quickly, it is possible to use the bomb flower at the top of the room to light the eyes.");
+ OPT_TRICK(RT_JABU_ALCOVE_JUMP_DIVE, RCQUEST_BOTH, RA_JABU_JABUS_BELLY, {Tricks::Tag::NOVICE}, "Jabu Underwater Alcove as Adult with Jump Dive", "Standing above the underwater tunnel leading to the scrub, jump down and swim through the tunnel. This allows adult to access the alcove with no Scale or Iron Boots. In vanilla Jabu, this alcove has a business scrub. In MQ Jabu, it has the compass chest and a door switch for the main floor.");
+ OPT_TRICK(RT_JABU_BOSS_HOVER, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, {Tricks::Tag::INTERMEDIATE}, "Jabu Near Boss Room with Hover Boots", "A box for the blue switch can be carried over by backwalking with one while the elevator is at its peak. Alternatively, you can skip transporting a box by quickly rolling from the switch and opening the door before it closes. However, the timing for this is very tight.");
+ OPT_TRICK(RT_JABU_NEAR_BOSS_RANGED, RCQUEST_BOTH, RA_JABU_JABUS_BELLY, {Tricks::Tag::NOVICE}, "Jabu Near Boss Ceiling Switch/GS without Boomerang or Explosives", "Vanilla Jabu: From near the entrance into the room, you can hit the switch that opens the door to the boss room using a precisely-aimed use of the Slingshot, Bow, or Longshot. As well, if you climb to the top of the vines you can stand on the right edge of the platform and shoot around the glass. From this distance, even the Hookshot can reach the switch. This trick is only relevant if \"Shuffle Boss Entrances\" is enabled. MQ Jabu: A Gold Skulltula Token can be collected with the Hookshot or Longshot using the same methods as hitting the switch in vanilla. This MQ trick is not currently relevant in logic.");
+ OPT_TRICK(RT_JABU_NEAR_BOSS_EXPLOSIVES, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, {Tricks::Tag::INTERMEDIATE}, "Jabu Near Boss Ceiling Switch with Explosives", "You can hit the switch that opens the door to the boss room using a precisely-aimed Bombchu. Also, using the Hover Boots, adult can throw a Bomb at the switch. This trick is only relevant if \"Shuffle Boss Entrances\" is enabled.");
+ OPT_TRICK(RT_LENS_JABU_MQ, RCQUEST_MQ, RA_JABU_JABUS_BELLY, {Tricks::Tag::NOVICE}, "Jabu MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Jabu MQ.");
+ OPT_TRICK(RT_JABU_MQ_RANG_JUMP, RCQUEST_MQ, RA_JABU_JABUS_BELLY, {Tricks::Tag::ADVANCED}, "Jabu MQ Compass Chest with Boomerang", "Boomerang can reach the cow switch to spawn the chest by targeting the cow, jumping off of the ledge where the chest spawns, and throwing the Boomerang in midair.");
+ OPT_TRICK(RT_JABU_MQ_SOT_GS, RCQUEST_MQ, RA_JABU_JABUS_BELLY, {Tricks::Tag::INTERMEDIATE}, "Jabu MQ Song of Time Block GS with Boomerang", "Allow the Boomerang to return to you through the Song of Time block to grab the token.");
+ OPT_TRICK(RT_LENS_BOTW, RCQUEST_VANILLA, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well without Lens of Truth", "Removes the requirements for the Lens of Truth in Bottom of the Well.");
+ OPT_TRICK(RT_BOTW_CHILD_DEADHAND, RCQUEST_BOTH, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Child Dead Hand without Kokiri Sword", "Requires 9 sticks or 5 jump slashes.");
+ OPT_TRICK(RT_BOTW_BASEMENT, RCQUEST_VANILLA, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well Map Chest with Strength & Sticks", "The chest in the basement can be reached with strength by doing a jump slash with a lit stick to access the bomb flowers.");
+ OPT_TRICK(RT_BOTW_MQ_PITS, RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well MQ Jump Over the Pits", "While the pits in Bottom of the Well don't allow you to jump just by running straight at them, you can still get over them by side-hopping or backflipping across. With explosives, this allows you to access the central areas without Zelda's Lullaby. With Zelda's Lullaby, it allows you to access the west inner room without explosives.");
+ OPT_TRICK(RT_BOTW_MQ_DEADHAND_KEY, RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, {Tricks::Tag::NOVICE}, "Bottom of the Well MQ Dead Hand Freestanding Key with Boomerang", "Boomerang can fish the item out of the rubble without needing explosives to blow it up.");
+ OPT_TRICK(RT_FOREST_FIRST_GS, RCQUEST_VANILLA, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple First Room GS with Difficult-to-Use Weapons", "Allows killing this Skulltula with Sword or Sticks by jump slashing it as you let go from the vines. You can avoid taking fall damage by recoiling onto the tree. Also allows killing it as Child with a Bomb throw. It's much more difficult to use a Bomb as child due to Child Link's shorter height.");
+ OPT_TRICK(RT_FOREST_OUTDOORS_EAST_GS, RCQUEST_VANILLA, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple East Courtyard GS with Boomerang", "Precise Boomerang throws can allow child to kill the Skulltula and collect the token.");
+ OPT_TRICK(RT_FOREST_VINES, RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple East Courtyard Vines with Hookshot", "The vines in Forest Temple leading to where the well drain switch is in the standard form can be barely reached with just the Hookshot. Applies to MQ also.");
+ OPT_TRICK(RT_FOREST_OUTDOORS_LEDGE, RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple NE Outdoors Ledge with Hover Boots", "With precise Hover Boots movement you can fall down to this ledge from upper balconies. If done precisely enough, it is not necessary to take fall damage. In MQ, this skips a Longshot requirement. In Vanilla, this can skip a Hookshot requirement in entrance randomizer.");
+ OPT_TRICK(RT_FOREST_DOORFRAME, RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::ADVANCED}, "Forest Temple East Courtyard Door Frame with Hover Boots", "A precise Hover Boots movement from the upper balconies in this courtyard can be used to get on top of the door frame. Applies to both Vanilla and Master Quest. In Vanilla, from on top the door frame you can summon Pierre, allowing you to access the falling ceiling room early. In Master Quest, this allows you to obtain the GS on the door frame as adult without Hookshot or Song of Time.");
+ OPT_TRICK(RT_FOREST_OUTSIDE_BACKDOOR, RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::ADVANCED}, "Forest Temple Outside Backdoor with Jump Slash", "A jump slash recoil can be used to reach the ledge in the block puzzle room that leads to the west courtyard. This skips a potential Hover Boots requirement in vanilla, and it can sometimes apply in MQ as well. This trick can be performed as both ages.");
+ OPT_TRICK(RT_FOREST_OUTDOORS_HEARTS_BOOMERANG, RCQUEST_BOTH, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple Outside Hearts with Boomerang", "A well aimed boomerang from the water's edge can reach the hearts from ground level. If unable to swim, you can back away from the water while the boomerang is returning so the hearts land on the ground.");
+ OPT_TRICK(RT_FOREST_MQ_WELL_SWIM, RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::ADVANCED}, "Swim Through Forest Temple MQ Well with Hookshot", "Shoot the vines in the well as low and as far to the right as possible, and then immediately swim under the ceiling to the right. This can only be required if Forest Temple is in its Master Quest form.");
+ OPT_TRICK(RT_FOREST_MQ_BLOCK_PUZZLE, RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Skip Forest Temple MQ Block Puzzle with Bombchu", "Send the Bombchu straight up the center of the wall directly to the left upon entering the room.");
//Child with hovers cannot do this from the lower floor, and most go to the upper floor which needs goron bracelet. Adult can do this with hammer and KSword, But child cannot.
- mTrickOptions[RT_FOREST_MQ_JS_HALLWAY_SWITCH] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple MQ Twisted Hallway Switch with Jump Slash", "The switch to twist the hallway can be hit with a jump slash through the glass block. To get in front of the switch, either use the Hover Boots or hit the shortcut switch at the top of the room and jump from the glass blocks that spawn. Sticks can be used as child, but the Kokiri Sword is too short to reach through the glass.");
- mTrickOptions[RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Forest Temple MQ Twisted Hallway Switch with Hookshot", "There's a very small gap between the glass block and the wall. Through that gap you can hookshot the target on the ceiling.");
- mTrickOptions[RT_FOREST_MQ_RANG_HALLWAY_SWITCH] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Forest Temple MQ Twisted Hallway Switch with Boomerang", "The Boomerang can return to Link through walls, allowing child to hit the hallway switch. This can be used to allow adult to pass through later, or in conjuction with \"Forest Temple Outside Backdoor with Jump Slash\".");
- mTrickOptions[RT_FIRE_BOSS_DOOR_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple Boss Door without Hover Boots or Pillar", "The Fire Temple Boss Door can be reached as adult with a precise jump. You must be touching the side wall of the room so that Link will grab the ledge from farther away than is normally possible.");
+ OPT_TRICK(RT_FOREST_MQ_JS_HALLWAY_SWITCH, RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::NOVICE}, "Forest Temple MQ Twisted Hallway Switch with Jump Slash", "The switch to twist the hallway can be hit with a jump slash through the glass block. To get in front of the switch, either use the Hover Boots or hit the shortcut switch at the top of the room and jump from the glass blocks that spawn. Sticks can be used as child, but the Kokiri Sword is too short to reach through the glass.");
+ OPT_TRICK(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH, RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Forest Temple MQ Twisted Hallway Switch with Hookshot", "There's a very small gap between the glass block and the wall. Through that gap you can hookshot the target on the ceiling.");
+ OPT_TRICK(RT_FOREST_MQ_RANG_HALLWAY_SWITCH, RCQUEST_MQ, RA_FOREST_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Forest Temple MQ Twisted Hallway Switch with Boomerang", "The Boomerang can return to Link through walls, allowing child to hit the hallway switch. This can be used to allow adult to pass through later, or in conjuction with \"Forest Temple Outside Backdoor with Jump Slash\".");
+ OPT_TRICK(RT_FIRE_BOSS_DOOR_JUMP, RCQUEST_BOTH, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple Boss Door without Hover Boots or Pillar", "The Fire Temple Boss Door can be reached as adult with a precise jump. You must be touching the side wall of the room so that Link will grab the ledge from farther away than is normally possible.");
//Is also used in MQ logic, but has no practical effect there as of now
- mTrickOptions[RT_FIRE_SOT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple Song of Time Room GS without Song of Time", "A precise jump can be used to reach this room.");
- mTrickOptions[RT_FIRE_STRENGTH] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple Climb without Strength", "A precise jump can be used to skip pushing the block.");
- mTrickOptions[RT_FIRE_SCARECROW] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::EXPERT}, "Fire Temple East Tower without Scarecrow\'s Song", "Also known as \"Pixelshot\". The Longshot can reach the target on the elevator itself, allowing you to skip needing to spawn the scarecrow.");
- mTrickOptions[RT_FIRE_FLAME_MAZE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple Flame Wall Maze Skip", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. To do it without taking damage is more precise. Allows you to progress without needing either a Small Key or Hover Boots.");
- mTrickOptions[RT_FIRE_MQ_NEAR_BOSS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Chest Near Boss without Breaking Crate", "The hitbox for the torch extends a bit outside of the crate. Shoot a flaming arrow at the side of the crate to light the torch without needing to get over there and break the crate.");
- mTrickOptions[RT_FIRE_MQ_BLOCKED_CHEST] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Big Lava Room Blocked Door without Hookshot", "There is a gap between the hitboxes of the flame wall in the big lava room. If you know where this gap is located, you can jump through it and skip needing to use the Hookshot. To do this without taking damage is more precise.");
- mTrickOptions[RT_FIRE_MQ_BK_CHEST] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Boss Key Chest without Bow", "It is possible to light both of the timed torches to unbar the door to the boss key chest's room with just Din's Fire if you move very quickly between the two torches. It is also possible to unbar the door with just Din's by abusing an oversight in the way the game counts how many torches have been lit.");
- mTrickOptions[RT_FIRE_MQ_CLIMB] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Climb without Fire Source", "You can use the Hover Boots to hover around to the climbable wall, skipping the need to use a fire source and spawn a Hookshot target.");
- mTrickOptions[RT_FIRE_MQ_MAZE_SIDE_ROOM] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Lizalfos Maze Side Room without Box", "You can walk from the blue switch to the door and quickly open the door before the bars reclose. This skips needing to reach the upper sections of the maze to get a box to place on the switch.");
- mTrickOptions[RT_FIRE_MQ_MAZE_HOVERS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Lower to Upper Lizalfos Maze with Hover Boots", "Use the Hover Boots off of a crate to climb to the upper maze without needing to spawn and use the Hookshot targets.");
- mTrickOptions[RT_FIRE_MQ_MAZE_JUMP] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Lower to Upper Lizalfos Maze with Precise Jump", "A precise jump off of a crate can be used to climb to the upper maze without needing to spawn and use the Hookshot targets. This trick supersedes both \"Fire Temple MQ Lower to Upper Lizalfos Maze with Hover Boots\" and \"Fire Temple MQ Lizalfos Maze Side Room without Box\".");
- mTrickOptions[RT_FIRE_MQ_ABOVE_MAZE_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Above Flame Wall Maze GS from Below with Longshot", "The floor of the room that contains this Skulltula is only solid from above. From the maze below, the Longshot can be shot through the ceiling to obtain the token with two fewer small keys than normal.");
- mTrickOptions[RT_FIRE_MQ_FLAME_MAZE] = TrickOption::LogicTrick(RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Flame Wall Maze Skip", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. To do it without taking damage is more precise. Allows you to reach the side room GS without needing Song of Time or Hover Boots. If either of \"Fire Temple MQ Lower to Upper Lizalfos Maze with Hover Boots\" or \"with Precise Jump\" are enabled, this also allows you to progress deeper into the dungeon without Hookshot.");
- mTrickOptions[RT_WATER_LONGSHOT_TORCH] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Torch Longshot", "Stand on the eastern side of the central pillar and longshot the torches on the bottom level. Swim through the corridor and float up to the top level. This allows access to this area and lower water levels without Iron Boots. The majority of the tricks that allow you to skip Iron Boots in the Water Temple are not going to be relevant unless this trick is first enabled.");
- mTrickOptions[RT_WATER_CRACKED_WALL_HOVERS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Cracked Wall with Hover Boots", "With a midair side-hop while wearing the Hover Boots, you can reach the cracked wall without needing to raise the water up to the middle level.");
- mTrickOptions[RT_WATER_CRACKED_WALL] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple Cracked Wall with No Additional Items", "A precise jump slash (among other methods) will get you to the cracked wall without needing the Hover Boots or to raise the water to the middle level. This trick supersedes \"Water Temple Cracked Wall with Hover Boots\".");
- mTrickOptions[RT_WATER_BK_REGION] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple Boss Key Region with Hover Boots", "With precise Hover Boots movement it is possible to reach the boss key chest's region without needing the Longshot. It is not necessary to take damage from the spikes. The Gold Skulltula Token in the following room can also be obtained with just the Hover Boots.");
- mTrickOptions[RT_WATER_NORTH_BASEMENT_LEDGE_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple North Basement Ledge with Precise Jump", "In the northern basement there's a ledge from where, in vanilla Water Temple, boulders roll out into the room. Normally to jump directly to this ledge logically requires the Hover Boots, but with precise jump, it can be done without them. This trick applies to both Vanilla and Master Quest.");
- mTrickOptions[RT_WATER_BK_JUMP_DIVE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Boss Key Jump Dive", "Stand on the very edge of the raised corridor leading from the push block room to the rolling boulder corridor. Face the Gold Skulltula on the waterfall and jump over the boulder corridor floor into the pool of water, swimming right once underwater. This allows access to the boss key room without Iron boots.");
+ OPT_TRICK(RT_FIRE_SOT, RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple Song of Time Room GS without Song of Time", "A precise jump can be used to reach this room.");
+ OPT_TRICK(RT_FIRE_STRENGTH, RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple Climb without Strength", "A precise jump can be used to skip pushing the block.");
+ OPT_TRICK(RT_FIRE_SCARECROW, RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::EXPERT}, "Fire Temple East Tower without Scarecrow\'s Song", "Also known as \"Pixelshot\". The Longshot can reach the target on the elevator itself, allowing you to skip needing to spawn the scarecrow.");
+ OPT_TRICK(RT_FIRE_FLAME_MAZE, RCQUEST_VANILLA, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple Flame Wall Maze Skip", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. To do it without taking damage is more precise. Allows you to progress without needing either a Small Key or Hover Boots.");
+ OPT_TRICK(RT_FIRE_MQ_NEAR_BOSS, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Chest Near Boss without Breaking Crate", "The hitbox for the torch extends a bit outside of the crate. Shoot a flaming arrow at the side of the crate to light the torch without needing to get over there and break the crate.");
+ OPT_TRICK(RT_FIRE_MQ_BLOCKED_CHEST, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Big Lava Room Blocked Door without Hookshot", "There is a gap between the hitboxes of the flame wall in the big lava room. If you know where this gap is located, you can jump through it and skip needing to use the Hookshot. To do this without taking damage is more precise.");
+ OPT_TRICK(RT_FIRE_MQ_BK_CHEST, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Boss Key Chest without Bow", "It is possible to light both of the timed torches to unbar the door to the boss key chest's room with just Din's Fire if you move very quickly between the two torches. It is also possible to unbar the door with just Din's by abusing an oversight in the way the game counts how many torches have been lit.");
+ OPT_TRICK(RT_FIRE_MQ_CLIMB, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Climb without Fire Source", "You can use the Hover Boots to hover around to the climbable wall, skipping the need to use a fire source and spawn a Hookshot target.");
+ OPT_TRICK(RT_FIRE_MQ_MAZE_SIDE_ROOM, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Lizalfos Maze Side Room without Box", "You can walk from the blue switch to the door and quickly open the door before the bars reclose. This skips needing to reach the upper sections of the maze to get a box to place on the switch.");
+ OPT_TRICK(RT_FIRE_MQ_MAZE_HOVERS, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::NOVICE}, "Fire Temple MQ Lower to Upper Lizalfos Maze with Hover Boots", "Use the Hover Boots off of a crate to climb to the upper maze without needing to spawn and use the Hookshot targets.");
+ OPT_TRICK(RT_FIRE_MQ_MAZE_JUMP, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Lower to Upper Lizalfos Maze with Precise Jump", "A precise jump off of a crate can be used to climb to the upper maze without needing to spawn and use the Hookshot targets. This trick supersedes both \"Fire Temple MQ Lower to Upper Lizalfos Maze with Hover Boots\" and \"Fire Temple MQ Lizalfos Maze Side Room without Box\".");
+ OPT_TRICK(RT_FIRE_MQ_ABOVE_MAZE_GS, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Above Flame Wall Maze GS from Below with Longshot", "The floor of the room that contains this Skulltula is only solid from above. From the maze below, the Longshot can be shot through the ceiling to obtain the token with two fewer small keys than normal.");
+ OPT_TRICK(RT_FIRE_MQ_FLAME_MAZE, RCQUEST_MQ, RA_FIRE_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Fire Temple MQ Flame Wall Maze Skip", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. To do it without taking damage is more precise. Allows you to reach the side room GS without needing Song of Time or Hover Boots. If either of \"Fire Temple MQ Lower to Upper Lizalfos Maze with Hover Boots\" or \"with Precise Jump\" are enabled, this also allows you to progress deeper into the dungeon without Hookshot.");
+ OPT_TRICK(RT_WATER_LONGSHOT_TORCH, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Torch Longshot", "Stand on the eastern side of the central pillar and longshot the torches on the bottom level. Swim through the corridor and float up to the top level. This allows access to this area and lower water levels without Iron Boots. The majority of the tricks that allow you to skip Iron Boots in the Water Temple are not going to be relevant unless this trick is first enabled.");
+ OPT_TRICK(RT_WATER_CRACKED_WALL_HOVERS, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Cracked Wall with Hover Boots", "With a midair side-hop while wearing the Hover Boots, you can reach the cracked wall without needing to raise the water up to the middle level.");
+ OPT_TRICK(RT_WATER_CRACKED_WALL, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple Cracked Wall with No Additional Items", "A precise jump slash (among other methods) will get you to the cracked wall without needing the Hover Boots or to raise the water to the middle level. This trick supersedes \"Water Temple Cracked Wall with Hover Boots\".");
+ OPT_TRICK(RT_WATER_BK_REGION, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple Boss Key Region with Hover Boots", "With precise Hover Boots movement it is possible to reach the boss key chest's region without needing the Longshot. It is not necessary to take damage from the spikes. The Gold Skulltula Token in the following room can also be obtained with just the Hover Boots.");
+ OPT_TRICK(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP, RCQUEST_BOTH, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple North Basement Ledge with Precise Jump", "In the northern basement there's a ledge from where, in vanilla Water Temple, boulders roll out into the room. Normally to jump directly to this ledge logically requires the Hover Boots, but with precise jump, it can be done without them. This trick applies to both Vanilla and Master Quest.");
+ OPT_TRICK(RT_WATER_BK_JUMP_DIVE, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Boss Key Jump Dive", "Stand on the very edge of the raised corridor leading from the push block room to the rolling boulder corridor. Face the Gold Skulltula on the waterfall and jump over the boulder corridor floor into the pool of water, swimming right once underwater. This allows access to the boss key room without Iron boots.");
//Also used in MQ logic, but won't be relevent unless a way to enter tower without irons exists (likely a clip + swim)
- mTrickOptions[RT_WATER_FW_CENTRAL_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Central Pillar GS with Farore\'s Wind", "If you set Farore's Wind inside the central pillar and then return to that warp point after raising the water to the highest level, you can obtain this Skulltula Token with Hookshot or Boomerang.");
- mTrickOptions[RT_WATER_IRONS_CENTRAL_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Central Pillar GS with Iron Boots", "After opening the middle water level door into the central pillar, the door will stay unbarred so long as you do not leave the room -- even if you were to raise the water up to the highest level. With the Iron Boots to go through the door after the water has been raised, you can obtain the Skulltula Token with the Hookshot.");
- mTrickOptions[RT_WATER_CENTRAL_BOW] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::ADVANCED}, "Water Temple Central Bow Target without Longshot or Hover Boots", "A very precise Bow shot can hit the eye switch from the floor above. Then, you can jump down into the hallway and make through it before the gate closes. It can also be done as child, using the Slingshot instead of the Bow.");
- mTrickOptions[RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Falling Platform Room GS with Hookshot", "If you stand on the very edge of the platform, this Gold Skulltula can be obtained with only the Hookshot.");
- mTrickOptions[RT_WATER_RANG_FALLING_PLATFORM_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple Falling Platform Room GS with Boomerang", "If you stand on the very edge of the platform, this Gold Skulltula can be obtained with only the Boomerang.");
- mTrickOptions[RT_WATER_RIVER_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple River GS without Iron Boots", "Standing on the exposed ground toward the end of the river, a precise Longshot use can obtain the token. The Longshot cannot normally reach far enough to kill the Skulltula, however. You'll first have to find some other way of killing it.");
- mTrickOptions[RT_WATER_DRAGON_JUMP_DIVE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Dragon Statue Jump Dive", "If you come into the dragon statue room from the serpent river, you can jump down from above and get into the tunnel without needing either Iron Boots or a Scale. This trick applies to both Vanilla and Master Quest. In Vanilla, you must shoot the switch from above with the Bow, and then quickly get through the tunnel before the gate closes.");
- mTrickOptions[RT_WATER_ADULT_DRAGON] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Dragon Statue Switch from Above the Water as Adult", "Normally you need both Hookshot and Iron Boots to hit the switch and swim through the tunnel to get to the chest. But by hitting the switch from dry land, using one of Bombchus, Hookshot, or Bow, it is possible to skip one or both of those requirements. After the gate has been opened, besides just using the Iron Boots, a well-timed dive with at least the Silver Scale could be used to swim through the tunnel. If coming from the serpent river, a jump dive can also be used to get into the tunnel.");
- mTrickOptions[RT_WATER_CHILD_DRAGON] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::ADVANCED}, "Water Temple Dragon Statue Switch from Above the Water as Child", "It is possible for child to hit the switch from dry land using one of Bombchus, Slingshot or Boomerang. Then, to get to the chest, child can dive through the tunnel using at least the Silver Scale. The timing and positioning of this dive needs to be perfect to actually make it under the gate, and it all needs to be done very quickly to be able to get through before the gate closes. Be sure to enable \"Water Temple Dragon Statue Switch from Above the Water as Adult\" for adult's variant of this trick.");
- mTrickOptions[RT_WATER_MQ_CENTRAL_PILLAR] = TrickOption::LogicTrick(RCQUEST_MQ, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple MQ Central Pillar with Fire Arrows", "Slanted torches have misleading hitboxes. Whenever you see a slanted torch jutting out of the wall, you can expect most or all of its hitbox is actually on the other side that wall. This can make slanted torches very finicky to light when using arrows. The torches in the central pillar of MQ Water Temple are a particularly egregious example. Logic normally expects Din's Fire and Song of Time.");
- mTrickOptions[RT_WATER_MQ_LOCKED_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple MQ North Basement GS without Small Key", "There is an invisible Hookshot target that can be used to get over the gate that blocks you from going to this Skulltula early, skipping a small key as well as needing Hovers or Scarecrow to reach the locked door.");
- mTrickOptions[RT_LENS_SHADOW] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Stationary Objects without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple for most areas in the dungeon except for crossing the moving platform in the huge pit room and for fighting Bongo Bongo.");
- mTrickOptions[RT_LENS_SHADOW_PLATFORM] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Invisible Moving Platform without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple to cross the invisible moving platform in the huge pit room in either direction.");
- mTrickOptions[RT_LENS_BONGO] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Bongo Bongo without Lens of Truth", "Bongo Bongo can be defeated without the use of Lens of Truth, as the hands give a pretty good idea of where the eye is.");
- mTrickOptions[RT_SHADOW_UMBRELLA] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::EXPERT}, "Shadow Temple Stone Umbrella Skip", "A very precise Hover Boots movement from off of the lower chest can get you on top of the crushing spikes without needing to pull the block. Applies to both Vanilla and Master Quest.");
- mTrickOptions[RT_SHADOW_UMBRELLA_GS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::EXPERT}, "Shadow Temple Falling Spikes GS with Hover Boots", "After killing the Skulltula, a very precise Hover Boots movement from off of the lower chest can get you on top of the crushing spikes without needing to pull the block. From there, another very precise Hover Boots movement can be used to obtain the token without needing the Hookshot. Applies to both Vanilla and Master Quest. For obtaining the chests in this room with just Hover Boots, be sure to enable \"Shadow Temple Stone Umbrella Skip\".");
- mTrickOptions[RT_SHADOW_FREESTANDING_KEY] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Freestanding Key with Bombchu", "Release the Bombchu with good timing so that it explodes near the bottom of the pot.");
- mTrickOptions[RT_SHADOW_STATUE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple River Statue with Bombchu", "By sending a Bombchu around the edge of the gorge, you can knock down the statue without needing a Bow. Applies in both vanilla and MQ Shadow.");
- mTrickOptions[RT_SHADOW_BONGO] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple Bongo Bongo without projectiles", "Using precise sword slashes, Bongo Bongo can be defeated without using projectiles. This is only relevant in conjunction with Shadow Temple dungeon shortcuts or shuffled boss entrances.");
- mTrickOptions[RT_LENS_SHADOW_MQ] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ Stationary Objects without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple MQ for most areas in the dungeon. See \"Shadow Temple MQ Invisible Moving Platform without Lens of Truth\", \"Shadow Temple MQ Invisible Blades Silver Rupees without Lens of Truth\", \"Shadow Temple MQ 2nd Dead Hand without Lens of Truth\", and \"Shadow Temple Bongo Bongo without Lens of Truth\" for exceptions.");
- mTrickOptions[RT_LENS_SHADOW_MQ_INVISIBLE_BLADES] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ Invisible Blades Silver Rupees without Lens of Truth", "Removes the requirement for the Lens of Truth or Nayru's Love in Shadow Temple MQ for the Invisible Blades room silver rupee collection.");
- mTrickOptions[RT_LENS_SHADOW_MQ_PLATFORM] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ Invisible Moving Platform without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple MQ to cross the invisible moving platform in the huge pit room in either direction.");
- mTrickOptions[RT_LENS_SHADOW_MQ_DEADHAND] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ 2nd Dead Hand without Lens of Truth", "Dead Hand spawns in a random spot within the room. Having Lens removes the hassle of having to comb the room looking for his spawn location.");
- mTrickOptions[RT_SHADOW_MQ_GAP] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Truth Spinner Gap with Longshot", "You can Longshot a torch and jump-slash recoil onto the tongue. It works best if you Longshot the right torch from the left side of the room.");
- mTrickOptions[RT_SHADOW_MQ_INVISIBLE_BLADES] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Invisible Blades without Song of Time", "The Like Like can be used to boost you into the silver rupee or recovery hearts that normally require Song of Time. This cannot be performed on OHKO since the Like Like does not boost you high enough if you die.");
- mTrickOptions[RT_SHADOW_MQ_HUGE_PIT] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Lower Huge Pit without Fire Source", "Normally a frozen eye switch spawns some platforms that you can use to climb down, but there's actually a small piece of ground that you can stand on that you can just jump down to.");
- mTrickOptions[RT_SHADOW_MQ_WINDY_WALKWAY] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Windy Walkway Reverse without Hover Boots", "It is possible to jump from the alcove in the windy hallway to the middle platform. There are two methods: wait out the fan opposite the door and hold forward, or jump to the right to be pushed by the fan there towards the platform ledge. Note that jumps of this distance are inconsistent, but still possible.");
- mTrickOptions[RT_LENS_SPIRIT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple without Lens of Truth", "Removes the requirements for the Lens of Truth in Spirit Temple.");
- mTrickOptions[RT_SPIRIT_CHILD_CHU] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple Child Side Bridge with Bombchu", "A carefully-timed Bombchu can hit the switch.");
- mTrickOptions[RT_SPIRIT_LOBBY_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple Main Room GS with Boomerang", "Standing on the highest part of the arm of the statue, a precise Boomerang throw can kill and obtain this Gold Skulltula. You must throw the Boomerang slightly off to the side so that it curves into the Skulltula, as aiming directly at it will clank off of the wall in front.");
- mTrickOptions[RT_SPIRIT_LOWER_ADULT_SWITCH] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::ADVANCED}, "Spirit Temple Lower Adult Switch with Bombs", "A bomb can be used to hit the switch on the ceiling, but it must be thrown from a particular distance away and with precise timing.");
- mTrickOptions[RT_SPIRIT_LOBBY_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple Main Room Jump from Hands to Upper Ledges", "A precise jump to obtain the following as adult without needing one of Hover Boots, or Hookshot (in vanilla) or Song of Time (in MQ): - Spirit Temple Statue Room Northeast Chest - Spirit Temple GS Lobby - Spirit Temple MQ Central Chamber Top Left Pot (Left) - Spirit Temple MQ Central Chamber Top Left Pot (Right)");
+ OPT_TRICK(RT_WATER_FW_CENTRAL_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Central Pillar GS with Farore\'s Wind", "If you set Farore's Wind inside the central pillar and then return to that warp point after raising the water to the highest level, you can obtain this Skulltula Token with Hookshot or Boomerang.");
+ OPT_TRICK(RT_WATER_IRONS_CENTRAL_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Central Pillar GS with Iron Boots", "After opening the middle water level door into the central pillar, the door will stay unbarred so long as you do not leave the room -- even if you were to raise the water up to the highest level. With the Iron Boots to go through the door after the water has been raised, you can obtain the Skulltula Token with the Hookshot.");
+ OPT_TRICK(RT_WATER_CENTRAL_BOW, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::ADVANCED}, "Water Temple Central Bow Target without Longshot or Hover Boots", "A very precise Bow shot can hit the eye switch from the floor above. Then, you can jump down into the hallway and make through it before the gate closes. It can also be done as child, using the Slingshot instead of the Bow.");
+ OPT_TRICK(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Falling Platform Room GS with Hookshot", "If you stand on the very edge of the platform, this Gold Skulltula can be obtained with only the Hookshot.");
+ OPT_TRICK(RT_WATER_RANG_FALLING_PLATFORM_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple Falling Platform Room GS with Boomerang", "If you stand on the very edge of the platform, this Gold Skulltula can be obtained with only the Boomerang.");
+ OPT_TRICK(RT_WATER_RIVER_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Water Temple River GS without Iron Boots", "Standing on the exposed ground toward the end of the river, a precise Longshot use can obtain the token. The Longshot cannot normally reach far enough to kill the Skulltula, however. You'll first have to find some other way of killing it.");
+ OPT_TRICK(RT_WATER_DRAGON_JUMP_DIVE, RCQUEST_BOTH, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Dragon Statue Jump Dive", "If you come into the dragon statue room from the serpent river, you can jump down from above and get into the tunnel without needing either Iron Boots or a Scale. This trick applies to both Vanilla and Master Quest. In Vanilla, you must shoot the switch from above with the Bow, and then quickly get through the tunnel before the gate closes.");
+ OPT_TRICK(RT_WATER_ADULT_DRAGON, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple Dragon Statue Switch from Above the Water as Adult", "Normally you need both Hookshot and Iron Boots to hit the switch and swim through the tunnel to get to the chest. But by hitting the switch from dry land, using one of Bombchus, Hookshot, or Bow, it is possible to skip one or both of those requirements. After the gate has been opened, besides just using the Iron Boots, a well-timed dive with at least the Silver Scale could be used to swim through the tunnel. If coming from the serpent river, a jump dive can also be used to get into the tunnel.");
+ OPT_TRICK(RT_WATER_CHILD_DRAGON, RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::ADVANCED}, "Water Temple Dragon Statue Switch from Above the Water as Child", "It is possible for child to hit the switch from dry land using one of Bombchus, Slingshot or Boomerang. Then, to get to the chest, child can dive through the tunnel using at least the Silver Scale. The timing and positioning of this dive needs to be perfect to actually make it under the gate, and it all needs to be done very quickly to be able to get through before the gate closes. Be sure to enable \"Water Temple Dragon Statue Switch from Above the Water as Adult\" for adult's variant of this trick.");
+ OPT_TRICK(RT_WATER_MQ_CENTRAL_PILLAR, RCQUEST_MQ, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple MQ Central Pillar with Fire Arrows", "Slanted torches have misleading hitboxes. Whenever you see a slanted torch jutting out of the wall, you can expect most or all of its hitbox is actually on the other side that wall. This can make slanted torches very finicky to light when using arrows. The torches in the central pillar of MQ Water Temple are a particularly egregious example. Logic normally expects Din's Fire and Song of Time.");
+ OPT_TRICK(RT_WATER_MQ_LOCKED_GS, RCQUEST_MQ, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, "Water Temple MQ North Basement GS without Small Key", "There is an invisible Hookshot target that can be used to get over the gate that blocks you from going to this Skulltula early, skipping a small key as well as needing Hovers or Scarecrow to reach the locked door.");
+ OPT_TRICK(RT_LENS_SHADOW, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Stationary Objects without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple for most areas in the dungeon except for crossing the moving platform in the huge pit room and for fighting Bongo Bongo.");
+ OPT_TRICK(RT_LENS_SHADOW_PLATFORM, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Invisible Moving Platform without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple to cross the invisible moving platform in the huge pit room in either direction.");
+ OPT_TRICK(RT_LENS_BONGO, RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Bongo Bongo without Lens of Truth", "Bongo Bongo can be defeated without the use of Lens of Truth, as the hands give a pretty good idea of where the eye is.");
+ OPT_TRICK(RT_SHADOW_UMBRELLA, RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::EXPERT}, "Shadow Temple Stone Umbrella Skip", "A very precise Hover Boots movement from off of the lower chest can get you on top of the crushing spikes without needing to pull the block. Applies to both Vanilla and Master Quest.");
+ OPT_TRICK(RT_SHADOW_UMBRELLA_GS, RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::EXPERT}, "Shadow Temple Falling Spikes GS with Hover Boots", "After killing the Skulltula, a very precise Hover Boots movement from off of the lower chest can get you on top of the crushing spikes without needing to pull the block. From there, another very precise Hover Boots movement can be used to obtain the token without needing the Hookshot. Applies to both Vanilla and Master Quest. For obtaining the chests in this room with just Hover Boots, be sure to enable \"Shadow Temple Stone Umbrella Skip\".");
+ OPT_TRICK(RT_SHADOW_FREESTANDING_KEY, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple Freestanding Key with Bombchu", "Release the Bombchu with good timing so that it explodes near the bottom of the pot.");
+ OPT_TRICK(RT_SHADOW_STATUE, RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple River Statue with Bombchu", "By sending a Bombchu around the edge of the gorge, you can knock down the statue without needing a Bow. Applies in both vanilla and MQ Shadow.");
+ OPT_TRICK(RT_SHADOW_BONGO, RCQUEST_BOTH, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple Bongo Bongo without projectiles", "Using precise sword slashes, Bongo Bongo can be defeated without using projectiles. This is only relevant in conjunction with Shadow Temple dungeon shortcuts or shuffled boss entrances.");
+ OPT_TRICK(RT_LENS_SHADOW_MQ, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ Stationary Objects without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple MQ for most areas in the dungeon. See \"Shadow Temple MQ Invisible Moving Platform without Lens of Truth\", \"Shadow Temple MQ Invisible Blades Silver Rupees without Lens of Truth\", \"Shadow Temple MQ 2nd Dead Hand without Lens of Truth\", and \"Shadow Temple Bongo Bongo without Lens of Truth\" for exceptions.");
+ OPT_TRICK(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ Invisible Blades Silver Rupees without Lens of Truth", "Removes the requirement for the Lens of Truth or Nayru's Love in Shadow Temple MQ for the Invisible Blades room silver rupee collection.");
+ OPT_TRICK(RT_LENS_SHADOW_MQ_PLATFORM, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ Invisible Moving Platform without Lens of Truth", "Removes the requirements for the Lens of Truth in Shadow Temple MQ to cross the invisible moving platform in the huge pit room in either direction.");
+ OPT_TRICK(RT_LENS_SHADOW_MQ_DEADHAND, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::NOVICE}, "Shadow Temple MQ 2nd Dead Hand without Lens of Truth", "Dead Hand spawns in a random spot within the room. Having Lens removes the hassle of having to comb the room looking for his spawn location.");
+ OPT_TRICK(RT_SHADOW_MQ_GAP, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Truth Spinner Gap with Longshot", "You can Longshot a torch and jump-slash recoil onto the tongue. It works best if you Longshot the right torch from the left side of the room.");
+ OPT_TRICK(RT_SHADOW_MQ_INVISIBLE_BLADES, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Invisible Blades without Song of Time", "The Like Like can be used to boost you into the silver rupee or recovery hearts that normally require Song of Time. This cannot be performed on OHKO since the Like Like does not boost you high enough if you die.");
+ OPT_TRICK(RT_SHADOW_MQ_HUGE_PIT, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Lower Huge Pit without Fire Source", "Normally a frozen eye switch spawns some platforms that you can use to climb down, but there's actually a small piece of ground that you can stand on that you can just jump down to.");
+ OPT_TRICK(RT_SHADOW_MQ_WINDY_WALKWAY, RCQUEST_MQ, RA_SHADOW_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Shadow Temple MQ Windy Walkway Reverse without Hover Boots", "It is possible to jump from the alcove in the windy hallway to the middle platform. There are two methods: wait out the fan opposite the door and hold forward, or jump to the right to be pushed by the fan there towards the platform ledge. Note that jumps of this distance are inconsistent, but still possible.");
+ OPT_TRICK(RT_LENS_SPIRIT, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple without Lens of Truth", "Removes the requirements for the Lens of Truth in Spirit Temple.");
+ OPT_TRICK(RT_SPIRIT_CHILD_CHU, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple Child Side Bridge with Bombchu", "A carefully-timed Bombchu can hit the switch.");
+ OPT_TRICK(RT_SPIRIT_LOBBY_GS, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple Main Room GS with Boomerang", "Standing on the highest part of the arm of the statue, a precise Boomerang throw can kill and obtain this Gold Skulltula. You must throw the Boomerang slightly off to the side so that it curves into the Skulltula, as aiming directly at it will clank off of the wall in front.");
+ OPT_TRICK(RT_SPIRIT_LOWER_ADULT_SWITCH, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::ADVANCED}, "Spirit Temple Lower Adult Switch with Bombs", "A bomb can be used to hit the switch on the ceiling, but it must be thrown from a particular distance away and with precise timing.");
+ OPT_TRICK(RT_SPIRIT_LOBBY_JUMP, RCQUEST_BOTH, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple Main Room Jump from Hands to Upper Ledges", "A precise jump to obtain the following as adult without needing one of Hover Boots, or Hookshot (in vanilla) or Song of Time (in MQ): - Spirit Temple Statue Room Northeast Chest - Spirit Temple GS Lobby - Spirit Temple MQ Central Chamber Top Left Pot (Left) - Spirit Temple MQ Central Chamber Top Left Pot (Right)");
// disabled since "Spirit Temple boss shortcuts" (pre-lowers the platform where you break the statues face) isn't a setting in ship
- // mTrickOptions[RT_SPIRIT_PLATFORM_HOOKSHOT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple Main Room Hookshot to Boss Platform", "Precise hookshot aiming at the platform chains can be used to reach the boss platform from the middle landings. Using a jump slash immediately after reaching a chain makes aiming more lenient. Relevant only when Spirit Temple boss shortcuts are on.");
- mTrickOptions[RT_SPIRIT_MAP_CHEST] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple Map Chest with Bow", "To get a line of sight from the upper torch to the map chest torches, you must pull an Armos statue all the way up the stairs.");
- mTrickOptions[RT_SPIRIT_SUN_CHEST] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::ADVANCED}, "Spirit Temple Sun Block Room Chest with Bow", "Using the blocks in the room as platforms you can get lines of sight to all three torches. The timer on the torches is quite short so you must move quickly in order to light all three.");
- mTrickOptions[RT_SPIRIT_WALL] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple Shifting Wall with No Additional Items", "Logic normally guarantees a way of dealing with both the Beamos and the Walltula before climbing the wall.");
- mTrickOptions[RT_LENS_SPIRIT_MQ] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Spirit Temple MQ.");
- mTrickOptions[RT_SPIRIT_MQ_SUN_BLOCK_SOT] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple MQ Sun Block Room as Child without Song of Time", "While adult can easily jump directly to the switch that unbars the door to the sun block room, child Link cannot make the jump without spawning a Song of Time block to jump from. You can skip this by throwing the crate down onto the switch from above, which does unbar the door, however the crate immediately breaks, so you must move quickly to get through the door before it closes back up.");
- mTrickOptions[RT_SPIRIT_MQ_SUN_BLOCK_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple MQ Sun Block Room GS with Boomerang", "Throw the Boomerang in such a way that it curves through the side of the glass block to hit the Gold Skulltula.");
- mTrickOptions[RT_SPIRIT_MQ_LOWER_ADULT] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple MQ Lower Adult without Fire Arrows", "By standing in a precise position it is possible to light two of the torches with a single use of Din\'s Fire. This saves enough time to be able to light all three torches with only Din\'s.");
- mTrickOptions[RT_SPIRIT_MQ_FROZEN_EYE] = TrickOption::LogicTrick(RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple MQ Frozen Eye Switch without Fire", "You can melt the ice by shooting an arrow through a torch. The only way to find a line of sight for this shot is to first spawn a Song of Time block, and then stand on the very edge of it.");
- mTrickOptions[RT_ICE_BLOCK_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_ICE_CAVERN, {Tricks::Tag::INTERMEDIATE}, "Ice Cavern Block Room GS with Hover Boots", "The Hover Boots can be used to get in front of the Skulltula to kill it with a jump slash. Then, the Hover Boots can again be used to obtain the Token, all without Hookshot or Boomerang.");
- mTrickOptions[RT_ICE_MQ_RED_ICE_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_ICE_CAVERN, {Tricks::Tag::INTERMEDIATE}, "Ice Cavern MQ Red Ice GS without Song of Time", "If you side-hop into the perfect position, you can briefly stand on the platform with the red ice just long enough to dump some blue fire.");
- mTrickOptions[RT_ICE_MQ_SCARECROW] = TrickOption::LogicTrick(RCQUEST_MQ, RA_ICE_CAVERN, {Tricks::Tag::INTERMEDIATE}, "Ice Cavern MQ Scarecrow GS with No Additional Items", "As adult a precise jump can be used to reach this alcove.");
- mTrickOptions[RT_LENS_GTG] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Gerudo Training Ground without Lens of Truth", "Removes the requirements for the Lens of Truth in Gerudo Training Ground.");
- mTrickOptions[RT_GTG_WITHOUT_HOOKSHOT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::INTERMEDIATE}, "Gerudo Training Ground Left Side Silver Rupees without Hookshot", "After collecting the rest of the silver rupees in the room, you can reach the final silver rupee on the ceiling by being pulled up into it after getting grabbed by the Wallmaster. Then, you must also reach the exit of the room without the use of the Hookshot. If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. To do so without taking damage is more precise.");
- mTrickOptions[RT_GTG_FAKE_WALL] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Reach Gerudo Training Ground Fake Wall Ledge with Hover Boots", "A precise Hover Boots use from the top of the chest can allow you to grab the ledge without needing the usual requirements. In Master Quest, this always skips a Song of Time requirement. In Vanilla, this skips a Hookshot requirement, but is only relevant if \"Gerudo Training Ground Left Side Silver Rupees without Hookshot\" is enabled.");
- mTrickOptions[RT_LENS_GTG_MQ] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Gerudo Training Ground MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Gerudo Training Ground MQ.");
- mTrickOptions[RT_GTG_MQ_WITH_HOOKSHOT] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Gerudo Training Ground MQ Left Side Silver Rupees with Hookshot", "The highest silver rupee can be obtained by hookshotting the target and then immediately jump slashing toward the rupee.");
- mTrickOptions[RT_GTG_MQ_WIHTOUT_HOOKSHOT] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::INTERMEDIATE}, "Gerudo Training Ground MQ Left Side Silver Rupees without Hookshot", "After collecting the rest of the silver rupees in the room, you can reach the final silver rupee on the ceiling by being pulled up into it after getting grabbed by the Wallmaster. The Wallmaster will not track you to directly underneath the rupee. You should take the last step to be under the rupee after the Wallmaster has begun its attempt to grab you. Also included with this trick is that fact that the switch that unbars the door to the final chest of GTG can be hit without a projectile, using a precise jump slash. This trick supersedes \"Gerudo Training Ground MQ Left Side Silver Rupees with Hookshot\".");
- mTrickOptions[RT_LENS_GANON] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Ganon\'s Castle without Lens of Truth", "Removes the requirements for the Lens of Truth in Ganon's Castle.");
- mTrickOptions[RT_GANON_SPIRIT_TRIAL_HOOKSHOT] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Spirit Trial without Hookshot", "The highest rupee can be obtained as either age by performing a precise jump and a well-timed jumpslash off of an Armos.");
- mTrickOptions[RT_LENS_GANON_MQ] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Ganon\'s Castle MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Ganon's Castle MQ.");
- mTrickOptions[RT_GANON_MQ_FIRE_TRIAL] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::ADVANCED}, "Fire Trial MQ with Hookshot", "It's possible to hook the target at the end of fire trial with just Hookshot, but it requires precise aim and perfect positioning. The main difficulty comes from getting on the very corner of the obelisk without falling into the lava.");
- mTrickOptions[RT_GANON_MQ_SHADOW_TRIAL] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Shadow Trial MQ Torch with Bow", "You can light the torch in this room without a fire source by shooting an arrow through the lit torch at the beginning of the room. Because the room is so dark and the unlit torch is so far away, it can be difficult to aim the shot correctly.");
- mTrickOptions[RT_GANON_MQ_LIGHT_TRIAL] = TrickOption::LogicTrick(RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::INTERMEDIATE}, "Light Trial MQ without Hookshot", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. In this case to do it without taking damage is especially precise.");
+ // OPT_TRICK(RT_SPIRIT_PLATFORM_HOOKSHOT, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple Main Room Hookshot to Boss Platform", "Precise hookshot aiming at the platform chains can be used to reach the boss platform from the middle landings. Using a jump slash immediately after reaching a chain makes aiming more lenient. Relevant only when Spirit Temple boss shortcuts are on.");
+ OPT_TRICK(RT_SPIRIT_MAP_CHEST, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple Map Chest with Bow", "To get a line of sight from the upper torch to the map chest torches, you must pull an Armos statue all the way up the stairs.");
+ OPT_TRICK(RT_SPIRIT_SUN_CHEST, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::ADVANCED}, "Spirit Temple Sun Block Room Chest with Bow", "Using the blocks in the room as platforms you can get lines of sight to all three torches. The timer on the torches is quite short so you must move quickly in order to light all three.");
+ OPT_TRICK(RT_SPIRIT_WALL, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple Shifting Wall with No Additional Items", "Logic normally guarantees a way of dealing with both the Beamos and the Walltula before climbing the wall.");
+ OPT_TRICK(RT_LENS_SPIRIT_MQ, RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Spirit Temple MQ.");
+ OPT_TRICK(RT_SPIRIT_MQ_SUN_BLOCK_SOT, RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple MQ Sun Block Room as Child without Song of Time", "While adult can easily jump directly to the switch that unbars the door to the sun block room, child Link cannot make the jump without spawning a Song of Time block to jump from. You can skip this by throwing the crate down onto the switch from above, which does unbar the door, however the crate immediately breaks, so you must move quickly to get through the door before it closes back up.");
+ OPT_TRICK(RT_SPIRIT_MQ_SUN_BLOCK_GS, RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple MQ Sun Block Room GS with Boomerang", "Throw the Boomerang in such a way that it curves through the side of the glass block to hit the Gold Skulltula.");
+ OPT_TRICK(RT_SPIRIT_MQ_LOWER_ADULT, RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::INTERMEDIATE}, "Spirit Temple MQ Lower Adult without Fire Arrows", "By standing in a precise position it is possible to light two of the torches with a single use of Din\'s Fire. This saves enough time to be able to light all three torches with only Din\'s.");
+ OPT_TRICK(RT_SPIRIT_MQ_FROZEN_EYE, RCQUEST_MQ, RA_SPIRIT_TEMPLE, {Tricks::Tag::NOVICE}, "Spirit Temple MQ Frozen Eye Switch without Fire", "You can melt the ice by shooting an arrow through a torch. The only way to find a line of sight for this shot is to first spawn a Song of Time block, and then stand on the very edge of it.");
+ OPT_TRICK(RT_ICE_BLOCK_GS, RCQUEST_VANILLA, RA_ICE_CAVERN, {Tricks::Tag::INTERMEDIATE}, "Ice Cavern Block Room GS with Hover Boots", "The Hover Boots can be used to get in front of the Skulltula to kill it with a jump slash. Then, the Hover Boots can again be used to obtain the Token, all without Hookshot or Boomerang.");
+ OPT_TRICK(RT_ICE_MQ_RED_ICE_GS, RCQUEST_MQ, RA_ICE_CAVERN, {Tricks::Tag::INTERMEDIATE}, "Ice Cavern MQ Red Ice GS without Song of Time", "If you side-hop into the perfect position, you can briefly stand on the platform with the red ice just long enough to dump some blue fire.");
+ OPT_TRICK(RT_ICE_MQ_SCARECROW, RCQUEST_MQ, RA_ICE_CAVERN, {Tricks::Tag::INTERMEDIATE}, "Ice Cavern MQ Scarecrow GS with No Additional Items", "As adult a precise jump can be used to reach this alcove.");
+ OPT_TRICK(RT_LENS_GTG, RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Gerudo Training Ground without Lens of Truth", "Removes the requirements for the Lens of Truth in Gerudo Training Ground.");
+ OPT_TRICK(RT_GTG_WITHOUT_HOOKSHOT, RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::INTERMEDIATE}, "Gerudo Training Ground Left Side Silver Rupees without Hookshot", "After collecting the rest of the silver rupees in the room, you can reach the final silver rupee on the ceiling by being pulled up into it after getting grabbed by the Wallmaster. Then, you must also reach the exit of the room without the use of the Hookshot. If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. To do so without taking damage is more precise.");
+ OPT_TRICK(RT_GTG_FAKE_WALL, RCQUEST_BOTH, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Reach Gerudo Training Ground Fake Wall Ledge with Hover Boots", "A precise Hover Boots use from the top of the chest can allow you to grab the ledge without needing the usual requirements. In Master Quest, this always skips a Song of Time requirement. In Vanilla, this skips a Hookshot requirement, but is only relevant if \"Gerudo Training Ground Left Side Silver Rupees without Hookshot\" is enabled.");
+ OPT_TRICK(RT_LENS_GTG_MQ, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Gerudo Training Ground MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Gerudo Training Ground MQ.");
+ OPT_TRICK(RT_GTG_MQ_WITH_HOOKSHOT, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::NOVICE}, "Gerudo Training Ground MQ Left Side Silver Rupees with Hookshot", "The highest silver rupee can be obtained by hookshotting the target and then immediately jump slashing toward the rupee.");
+ OPT_TRICK(RT_GTG_MQ_WIHTOUT_HOOKSHOT, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, {Tricks::Tag::INTERMEDIATE}, "Gerudo Training Ground MQ Left Side Silver Rupees without Hookshot", "After collecting the rest of the silver rupees in the room, you can reach the final silver rupee on the ceiling by being pulled up into it after getting grabbed by the Wallmaster. The Wallmaster will not track you to directly underneath the rupee. You should take the last step to be under the rupee after the Wallmaster has begun its attempt to grab you. Also included with this trick is that fact that the switch that unbars the door to the final chest of GTG can be hit without a projectile, using a precise jump slash. This trick supersedes \"Gerudo Training Ground MQ Left Side Silver Rupees with Hookshot\".");
+ OPT_TRICK(RT_LENS_GANON, RCQUEST_VANILLA, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Ganon\'s Castle without Lens of Truth", "Removes the requirements for the Lens of Truth in Ganon's Castle.");
+ OPT_TRICK(RT_GANON_SPIRIT_TRIAL_HOOKSHOT, RCQUEST_VANILLA, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Spirit Trial without Hookshot", "The highest rupee can be obtained as either age by performing a precise jump and a well-timed jumpslash off of an Armos.");
+ OPT_TRICK(RT_LENS_GANON_MQ, RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Ganon\'s Castle MQ without Lens of Truth", "Removes the requirements for the Lens of Truth in Ganon's Castle MQ.");
+ OPT_TRICK(RT_GANON_MQ_FIRE_TRIAL, RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::ADVANCED}, "Fire Trial MQ with Hookshot", "It's possible to hook the target at the end of fire trial with just Hookshot, but it requires precise aim and perfect positioning. The main difficulty comes from getting on the very corner of the obelisk without falling into the lava.");
+ OPT_TRICK(RT_GANON_MQ_SHADOW_TRIAL, RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::NOVICE}, "Shadow Trial MQ Torch with Bow", "You can light the torch in this room without a fire source by shooting an arrow through the lit torch at the beginning of the room. Because the room is so dark and the unlit torch is so far away, it can be difficult to aim the shot correctly.");
+ OPT_TRICK(RT_GANON_MQ_LIGHT_TRIAL, RCQUEST_MQ, RA_GANONS_CASTLE, {Tricks::Tag::INTERMEDIATE}, "Light Trial MQ without Hookshot", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. In this case to do it without taking damage is especially precise.");
mOptionGroups[RSG_LOGIC] = OptionGroup::SubGroup("Logic Options", {
&mOptions[RSK_LOGIC_RULES],
@@ -532,190 +539,18 @@ void Settings::CreateOptions() {
&mOptions[RSK_SKULLS_SUNS_SONG],
});
// TODO: Exclude Locations Menus
- mOptionGroups[RSG_TRICKS] = OptionGroup::SubGroup("Logical Tricks", {
- &mTrickOptions[RT_VISIBLE_COLLISION],
- &mTrickOptions[RT_GROTTOS_WITHOUT_AGONY],
- &mTrickOptions[RT_FEWER_TUNIC_REQUIREMENTS],
- &mTrickOptions[RT_RUSTED_SWITCHES],
- &mTrickOptions[RT_FLAMING_CHESTS],
- &mTrickOptions[RT_BUNNY_HOOD_JUMPS],
- &mTrickOptions[RT_DAMAGE_BOOST_SIMPLE],
- &mTrickOptions[RT_HOVER_BOOST_SIMPLE],
- &mTrickOptions[RT_KF_ADULT_GS],
- &mTrickOptions[RT_LW_BRIDGE],
- &mTrickOptions[RT_LW_MIDO_BACKFLIP],
- &mTrickOptions[RT_LW_GS_BEAN],
- &mTrickOptions[RT_HC_STORMS_GS],
- &mTrickOptions[RT_KAK_MAN_ON_ROOF],
- &mTrickOptions[RT_KAK_TOWER_GS],
- &mTrickOptions[RT_KAK_ADULT_WINDMILL_POH],
- &mTrickOptions[RT_KAK_CHILD_WINDMILL_POH],
- &mTrickOptions[RT_KAK_ROOFTOP_GS],
- &mTrickOptions[RT_GY_POH],
- &mTrickOptions[RT_GY_CHILD_DAMPE_RACE_POH],
- &mTrickOptions[RT_GY_SHADOW_FIRE_ARROWS],
- &mTrickOptions[RT_DMT_SOIL_GS],
- &mTrickOptions[RT_DMT_BOMBABLE],
- &mTrickOptions[RT_DMT_HOOKSHOT_LOWER_GS],
- &mTrickOptions[RT_DMT_HOVERS_LOWER_GS],
- &mTrickOptions[RT_DMT_BEAN_LOWER_GS],
- &mTrickOptions[RT_DMT_JS_LOWER_GS],
- &mTrickOptions[RT_DMT_CLIMB_HOVERS],
- &mTrickOptions[RT_DMT_UPPER_GS],
- &mTrickOptions[RT_DMT_BOLERO_BIGGORON],
- &mTrickOptions[RT_GC_POT],
- &mTrickOptions[RT_GC_POT_STRENGTH],
- &mTrickOptions[RT_GC_ROLLING_STRENGTH],
- &mTrickOptions[RT_GC_LEFTMOST],
- &mTrickOptions[RT_GC_GROTTO],
- &mTrickOptions[RT_GC_LINK_GORON_DINS],
- &mTrickOptions[RT_DMC_HOVER_BEAN_POH],
- &mTrickOptions[RT_DMC_BOLERO_JUMP],
- &mTrickOptions[RT_DMC_BOULDER_JS],
- &mTrickOptions[RT_DMC_BOULDER_SKIP],
- &mTrickOptions[RT_ZR_LOWER],
- &mTrickOptions[RT_ZR_UPPER],
- &mTrickOptions[RT_ZR_HOVERS],
- &mTrickOptions[RT_ZR_CUCCO],
- &mTrickOptions[RT_ZD_KING_ZORA_SKIP],
- &mTrickOptions[RT_ZD_GS],
- &mTrickOptions[RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES],
- &mTrickOptions[RT_LH_LAB_WALL_GS],
- &mTrickOptions[RT_LH_LAB_DIVING],
- &mTrickOptions[RT_LH_WATER_HOOKSHOT],
- &mTrickOptions[RT_GV_CRATE_HOVERS],
- &mTrickOptions[RT_GF_KITCHEN],
- &mTrickOptions[RT_GF_JUMP],
- &mTrickOptions[RT_HW_BUNNY_CROSSING],
- &mTrickOptions[RT_HW_CROSSING],
- &mTrickOptions[RT_LENS_HW],
- &mTrickOptions[RT_HW_REVERSE],
- &mTrickOptions[RT_COLOSSUS_GS],
- &mTrickOptions[RT_DEKU_BASEMENT_GS],
- &mTrickOptions[RT_DEKU_B1_SKIP],
- &mTrickOptions[RT_DEKU_B1_BOW_WEBS],
- &mTrickOptions[RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG],
- &mTrickOptions[RT_DEKU_MQ_COMPASS_GS],
- &mTrickOptions[RT_DEKU_MQ_LOG],
- &mTrickOptions[RT_DC_SCARECROW_GS],
- &mTrickOptions[RT_DC_VINES_GS],
- &mTrickOptions[RT_DC_STAIRCASE],
- &mTrickOptions[RT_DC_SLINGSHOT_SKIP],
- &mTrickOptions[RT_DC_SCRUB_ROOM],
- &mTrickOptions[RT_DC_JUMP],
- &mTrickOptions[RT_DC_HAMMER_FLOOR],
- &mTrickOptions[RT_DC_MQ_CHILD_BOMBS],
- &mTrickOptions[RT_DC_MQ_CHILD_EYES],
- &mTrickOptions[RT_DC_MQ_ADULT_EYES],
- &mTrickOptions[RT_JABU_ALCOVE_JUMP_DIVE],
- &mTrickOptions[RT_JABU_BOSS_HOVER],
- &mTrickOptions[RT_JABU_NEAR_BOSS_RANGED],
- &mTrickOptions[RT_JABU_NEAR_BOSS_EXPLOSIVES],
- &mTrickOptions[RT_LENS_JABU_MQ],
- &mTrickOptions[RT_JABU_MQ_RANG_JUMP],
- &mTrickOptions[RT_JABU_MQ_SOT_GS],
- &mTrickOptions[RT_LENS_BOTW],
- &mTrickOptions[RT_BOTW_CHILD_DEADHAND],
- &mTrickOptions[RT_BOTW_BASEMENT],
- &mTrickOptions[RT_BOTW_MQ_PITS],
- &mTrickOptions[RT_BOTW_MQ_DEADHAND_KEY],
- &mTrickOptions[RT_FOREST_FIRST_GS],
- &mTrickOptions[RT_FOREST_OUTDOORS_EAST_GS],
- &mTrickOptions[RT_FOREST_VINES],
- &mTrickOptions[RT_FOREST_OUTDOORS_LEDGE],
- &mTrickOptions[RT_FOREST_DOORFRAME],
- &mTrickOptions[RT_FOREST_OUTSIDE_BACKDOOR],
- &mTrickOptions[RT_FOREST_OUTDOORS_HEARTS_BOOMERANG],
- &mTrickOptions[RT_FOREST_MQ_WELL_SWIM],
- &mTrickOptions[RT_FOREST_MQ_BLOCK_PUZZLE],
- &mTrickOptions[RT_FOREST_MQ_JS_HALLWAY_SWITCH],
- &mTrickOptions[RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH],
- &mTrickOptions[RT_FOREST_MQ_RANG_HALLWAY_SWITCH],
- &mTrickOptions[RT_FIRE_BOSS_DOOR_JUMP],
- &mTrickOptions[RT_FIRE_SOT],
- &mTrickOptions[RT_FIRE_STRENGTH],
- &mTrickOptions[RT_FIRE_SCARECROW],
- &mTrickOptions[RT_FIRE_FLAME_MAZE],
- &mTrickOptions[RT_FIRE_MQ_NEAR_BOSS],
- &mTrickOptions[RT_FIRE_MQ_BLOCKED_CHEST],
- &mTrickOptions[RT_FIRE_MQ_BK_CHEST],
- &mTrickOptions[RT_FIRE_MQ_CLIMB],
- &mTrickOptions[RT_FIRE_MQ_MAZE_SIDE_ROOM],
- &mTrickOptions[RT_FIRE_MQ_MAZE_HOVERS],
- &mTrickOptions[RT_FIRE_MQ_MAZE_JUMP],
- &mTrickOptions[RT_FIRE_MQ_ABOVE_MAZE_GS],
- &mTrickOptions[RT_FIRE_MQ_FLAME_MAZE],
- &mTrickOptions[RT_WATER_LONGSHOT_TORCH],
- &mTrickOptions[RT_WATER_CRACKED_WALL_HOVERS],
- &mTrickOptions[RT_WATER_CRACKED_WALL],
- &mTrickOptions[RT_WATER_BK_REGION],
- &mTrickOptions[RT_WATER_NORTH_BASEMENT_LEDGE_JUMP],
- &mTrickOptions[RT_WATER_BK_JUMP_DIVE],
- &mTrickOptions[RT_WATER_FW_CENTRAL_GS],
- &mTrickOptions[RT_WATER_IRONS_CENTRAL_GS],
- &mTrickOptions[RT_WATER_CENTRAL_BOW],
- &mTrickOptions[RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS],
- &mTrickOptions[RT_WATER_RANG_FALLING_PLATFORM_GS],
- &mTrickOptions[RT_WATER_RIVER_GS],
- &mTrickOptions[RT_WATER_DRAGON_JUMP_DIVE],
- &mTrickOptions[RT_WATER_ADULT_DRAGON],
- &mTrickOptions[RT_WATER_CHILD_DRAGON],
- &mTrickOptions[RT_WATER_MQ_CENTRAL_PILLAR],
- &mTrickOptions[RT_WATER_MQ_LOCKED_GS],
- &mTrickOptions[RT_LENS_SHADOW],
- &mTrickOptions[RT_LENS_SHADOW_PLATFORM],
- &mTrickOptions[RT_LENS_BONGO],
- &mTrickOptions[RT_SHADOW_UMBRELLA],
- &mTrickOptions[RT_SHADOW_UMBRELLA_GS],
- &mTrickOptions[RT_SHADOW_FREESTANDING_KEY],
- &mTrickOptions[RT_SHADOW_STATUE],
- &mTrickOptions[RT_SHADOW_BONGO],
- &mTrickOptions[RT_LENS_SHADOW_MQ],
- &mTrickOptions[RT_LENS_SHADOW_MQ_INVISIBLE_BLADES],
- &mTrickOptions[RT_LENS_SHADOW_MQ_PLATFORM],
- &mTrickOptions[RT_LENS_SHADOW_MQ_DEADHAND],
- &mTrickOptions[RT_SHADOW_MQ_GAP],
- &mTrickOptions[RT_SHADOW_MQ_INVISIBLE_BLADES],
- &mTrickOptions[RT_SHADOW_MQ_HUGE_PIT],
- &mTrickOptions[RT_SHADOW_MQ_WINDY_WALKWAY],
- &mTrickOptions[RT_LENS_SPIRIT],
- &mTrickOptions[RT_SPIRIT_CHILD_CHU],
- &mTrickOptions[RT_SPIRIT_LOBBY_GS],
- &mTrickOptions[RT_SPIRIT_LOWER_ADULT_SWITCH],
- &mTrickOptions[RT_SPIRIT_LOBBY_JUMP],
- &mTrickOptions[RT_SPIRIT_PLATFORM_HOOKSHOT],
- &mTrickOptions[RT_SPIRIT_MAP_CHEST],
- &mTrickOptions[RT_SPIRIT_SUN_CHEST],
- &mTrickOptions[RT_SPIRIT_WALL],
- &mTrickOptions[RT_LENS_SPIRIT_MQ],
- &mTrickOptions[RT_SPIRIT_MQ_SUN_BLOCK_SOT],
- &mTrickOptions[RT_SPIRIT_MQ_SUN_BLOCK_GS],
- &mTrickOptions[RT_SPIRIT_MQ_LOWER_ADULT],
- &mTrickOptions[RT_SPIRIT_MQ_FROZEN_EYE],
- &mTrickOptions[RT_ICE_BLOCK_GS],
- &mTrickOptions[RT_ICE_MQ_RED_ICE_GS],
- &mTrickOptions[RT_ICE_MQ_SCARECROW],
- &mTrickOptions[RT_LENS_GTG],
- &mTrickOptions[RT_GTG_WITHOUT_HOOKSHOT],
- &mTrickOptions[RT_GTG_FAKE_WALL],
- &mTrickOptions[RT_LENS_GTG_MQ],
- &mTrickOptions[RT_GTG_MQ_WITH_HOOKSHOT],
- &mTrickOptions[RT_GTG_MQ_WIHTOUT_HOOKSHOT],
- &mTrickOptions[RT_LENS_GANON],
- &mTrickOptions[RT_GANON_SPIRIT_TRIAL_HOOKSHOT],
- &mTrickOptions[RT_LENS_GANON_MQ],
- &mTrickOptions[RT_GANON_MQ_FIRE_TRIAL],
- &mTrickOptions[RT_GANON_MQ_SHADOW_TRIAL],
- &mTrickOptions[RT_GANON_MQ_LIGHT_TRIAL],
- });
mTricksByArea.clear();
+ std::vector