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_bombchubag/Hilite_new b/soh/assets/custom/objects/object_bombchubag/Hilite_new
new file mode 100644
index 000000000..5438695fa
Binary files /dev/null and b/soh/assets/custom/objects/object_bombchubag/Hilite_new differ
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL
new file mode 100644
index 000000000..86da33492
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_tri_0 b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_tri_0
new file mode 100644
index 000000000..add13c49f
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_tri_0
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_tri_1 b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_tri_1
new file mode 100644
index 000000000..7430c2a29
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_tri_1
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_vtx_0 b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_vtx_0
new file mode 100644
index 000000000..cddcb70e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_vtx_0
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_vtx_1 b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_vtx_1
new file mode 100644
index 000000000..6f8e0802d
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagBodyDL_vtx_1
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL b/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL
new file mode 100644
index 000000000..b68fbafff
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL_tri_0 b/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL_tri_0
new file mode 100644
index 000000000..c5ccc230f
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL_tri_0
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL_vtx_0 b/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL_vtx_0
new file mode 100644
index 000000000..cdc8798bc
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/gBombchuBagMaskDL_vtx_0
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagBodyDL_f3dlite_bag_body_matte b/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagBodyDL_f3dlite_bag_body_matte
new file mode 100644
index 000000000..4fb4e2029
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagBodyDL_f3dlite_bag_body_matte
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagBodyDL_f3dlite_bag_body_shine b/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagBodyDL_f3dlite_bag_body_shine
new file mode 100644
index 000000000..985d1ad9d
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagBodyDL_f3dlite_bag_body_shine
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagMaskDL_f3dlite_bag_mask b/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagMaskDL_f3dlite_bag_mask
new file mode 100644
index 000000000..4fb4e2029
--- /dev/null
+++ b/soh/assets/custom/objects/object_bombchubag/mat_gBombchuBagMaskDL_f3dlite_bag_mask
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
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 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL
index 6e3cbc204..191d058ec 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL
@@ -1,19 +1,16 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0
index 34ff33a71..643249842 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_0
@@ -1,163 +1,59 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1
index e406505e8..2dd15cd06 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_1
@@ -1,26 +1,14 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2
index d93755356..1ae88a89b 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_2
@@ -1,7 +1,38 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3
index 87fb8da01..38c434f31 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_3
@@ -1,48 +1,42 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4
index 6e436b142..bf4f6d363 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_tri_4
@@ -1,245 +1,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0
index ed4b6e1c0..c42b63538 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_0
@@ -1,173 +1,118 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1
index d2728aae4..c6d656107 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_1
@@ -1,26 +1,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2
index eb0050c03..83377b227 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_2
@@ -1,6 +1,46 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3
index f124650c8..13644a811 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_3
@@ -1,58 +1,62 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4 b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4
index 2bbe7895e..777a37058 100644
--- a/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4
+++ b/soh/assets/custom/objects/object_boss_soul/gGIBossSoulSkullDL_vtx_4
@@ -1,267 +1,46 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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_Gem_eyes b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Gem_eyes
deleted file mode 100644
index 07364ba3a..000000000
--- a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_Gem_eyes
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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_boss_soul/mat_gGIBossSoulSkullDL_skull_horns b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_horns
deleted file mode 100644
index 78d2a531c..000000000
--- a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_horns
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_surface b/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_surface
deleted file mode 100644
index e15a4dce4..000000000
--- a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_surface
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/soh/assets/custom/objects/object_boss_soul/noise_tex b/soh/assets/custom/objects/object_boss_soul/noise_tex
deleted file mode 100644
index aaf4e331f..000000000
Binary files a/soh/assets/custom/objects/object_boss_soul/noise_tex and /dev/null differ
diff --git a/soh/assets/custom/objects/object_boss_soul/noise_tex_copy b/soh/assets/custom/objects/object_boss_soul/noise_tex_copy
deleted file mode 100644
index a6d6cf945..000000000
Binary files a/soh/assets/custom/objects/object_boss_soul/noise_tex_copy and /dev/null differ
diff --git a/soh/assets/custom/objects/object_bosskey/Hilite_Caustics2 b/soh/assets/custom/objects/object_bosskey/Hilite_Caustics2
new file mode 100644
index 000000000..3eae27564
Binary files /dev/null and b/soh/assets/custom/objects/object_bosskey/Hilite_Caustics2 differ
diff --git a/soh/assets/custom/objects/object_bosskey/Hilite_new b/soh/assets/custom/objects/object_bosskey/Hilite_new
new file mode 100644
index 000000000..5438695fa
Binary files /dev/null and b/soh/assets/custom/objects/object_bosskey/Hilite_new differ
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL b/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL
new file mode 100644
index 000000000..606e5e5a8
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL_tri_0
new file mode 100644
index 000000000..55782c315
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL_tri_0
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL_vtx_0
new file mode 100644
index 000000000..1e9285c25
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyCustomDL_vtx_0
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL b/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL
new file mode 100644
index 000000000..5b07f23b0
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL_tri_0
new file mode 100644
index 000000000..66729a5c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL_tri_0
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL_vtx_0
new file mode 100644
index 000000000..72d390049
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconFireTempleDL_vtx_0
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL b/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL
new file mode 100644
index 000000000..ff11c42ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL_tri_0
new file mode 100644
index 000000000..7f516410e
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL_tri_0
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL_vtx_0
new file mode 100644
index 000000000..e04ca5dc1
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconForestTempleDL_vtx_0
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL b/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL
new file mode 100644
index 000000000..770739883
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL_tri_0
new file mode 100644
index 000000000..4e7d534f9
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL_tri_0
@@ -0,0 +1,749 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL_vtx_0
new file mode 100644
index 000000000..64d53ebb3
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconGanonsCastleDL_vtx_0
@@ -0,0 +1,803 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL b/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL
new file mode 100644
index 000000000..52ec0e5f9
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL_tri_0
new file mode 100644
index 000000000..43091fea3
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL_tri_0
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL_vtx_0
new file mode 100644
index 000000000..1619bed17
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconShadowTempleDL_vtx_0
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL b/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL
new file mode 100644
index 000000000..58acaff21
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL_tri_0
new file mode 100644
index 000000000..7a94a5699
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL_tri_0
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL_vtx_0
new file mode 100644
index 000000000..ceebb97ee
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconSpiritTempleDL_vtx_0
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL b/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL
new file mode 100644
index 000000000..edd9984a4
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL_tri_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL_tri_0
new file mode 100644
index 000000000..198e881c2
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL_tri_0
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL_vtx_0 b/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL_vtx_0
new file mode 100644
index 000000000..e3d917797
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/gBossKeyIconWaterTempleDL_vtx_0
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyCustomDL_f3dlite_BossKeyMetal_Custom b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyCustomDL_f3dlite_BossKeyMetal_Custom
new file mode 100644
index 000000000..8c58c67c9
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyCustomDL_f3dlite_BossKeyMetal_Custom
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconFireTempleDL_f3dlite_BossKeyGem_FireTemple b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconFireTempleDL_f3dlite_BossKeyGem_FireTemple
new file mode 100644
index 000000000..c96909c80
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconFireTempleDL_f3dlite_BossKeyGem_FireTemple
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconForestTempleDL_f3dlite_BossKeyGem_ForestTemple b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconForestTempleDL_f3dlite_BossKeyGem_ForestTemple
new file mode 100644
index 000000000..ab328f65b
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconForestTempleDL_f3dlite_BossKeyGem_ForestTemple
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconGanonsCastleDL_f3dlite_BossKeyGem_GanonsCastle b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconGanonsCastleDL_f3dlite_BossKeyGem_GanonsCastle
new file mode 100644
index 000000000..c4c60bef1
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconGanonsCastleDL_f3dlite_BossKeyGem_GanonsCastle
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconShadowTempleDL_f3dlite_BossKeyGem_ShadowTemple b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconShadowTempleDL_f3dlite_BossKeyGem_ShadowTemple
new file mode 100644
index 000000000..301b96815
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconShadowTempleDL_f3dlite_BossKeyGem_ShadowTemple
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconSpiritTempleDL_f3dlite_BossKeyGem_SpiritTemple b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconSpiritTempleDL_f3dlite_BossKeyGem_SpiritTemple
new file mode 100644
index 000000000..f838ce380
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconSpiritTempleDL_f3dlite_BossKeyGem_SpiritTemple
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconWaterTempleDL_f3dlite_BossKeyGem_WaterTemple b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconWaterTempleDL_f3dlite_BossKeyGem_WaterTemple
new file mode 100644
index 000000000..4e6dc67fc
--- /dev/null
+++ b/soh/assets/custom/objects/object_bosskey/mat_gBossKeyIconWaterTempleDL_f3dlite_BossKeyGem_WaterTemple
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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/custom/objects/object_key/Hilite_new b/soh/assets/custom/objects/object_key/Hilite_new
new file mode 100644
index 000000000..5438695fa
Binary files /dev/null and b/soh/assets/custom/objects/object_key/Hilite_new differ
diff --git a/soh/assets/custom/objects/object_key/gSkeletonKeyDL b/soh/assets/custom/objects/object_key/gSkeletonKeyDL
new file mode 100644
index 000000000..0405a3c7c
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSkeletonKeyDL
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSkeletonKeyDL_tri_0 b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_tri_0
new file mode 100644
index 000000000..80e7f1bad
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_tri_0
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSkeletonKeyDL_tri_1 b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_tri_1
new file mode 100644
index 000000000..46e6b22e5
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_tri_1
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSkeletonKeyDL_vtx_0 b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_vtx_0
new file mode 100644
index 000000000..f135e476d
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_vtx_0
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSkeletonKeyDL_vtx_1 b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_vtx_1
new file mode 100644
index 000000000..0f5b2970e
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSkeletonKeyDL_vtx_1
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyCustomDL b/soh/assets/custom/objects/object_key/gSmallKeyCustomDL
new file mode 100644
index 000000000..0ac907844
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyCustomDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyCustomDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyCustomDL_tri_0
new file mode 100644
index 000000000..594962af6
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyCustomDL_tri_0
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyCustomDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyCustomDL_vtx_0
new file mode 100644
index 000000000..9ceebf190
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyCustomDL_vtx_0
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL b/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL
new file mode 100644
index 000000000..c9da256e2
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL_tri_0
new file mode 100644
index 000000000..87c380d5c
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL_tri_0
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL_vtx_0
new file mode 100644
index 000000000..bd7962a42
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconBottomoftheWellDL_vtx_0
@@ -0,0 +1,298 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL b/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL
new file mode 100644
index 000000000..57f2ce5bf
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL_tri_0
new file mode 100644
index 000000000..aa905d45a
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL_tri_0
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL_vtx_0
new file mode 100644
index 000000000..9e167011c
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconFireTempleDL_vtx_0
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL b/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL
new file mode 100644
index 000000000..4bf303073
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL_tri_0
new file mode 100644
index 000000000..5414d43d9
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL_tri_0
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL_vtx_0
new file mode 100644
index 000000000..28f60fbae
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconForestTempleDL_vtx_0
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL b/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL
new file mode 100644
index 000000000..6c1d663d0
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL_tri_0
new file mode 100644
index 000000000..c0eb2f9f7
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL_tri_0
@@ -0,0 +1,749 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL_vtx_0
new file mode 100644
index 000000000..52fd01da3
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGanonsCastleDL_vtx_0
@@ -0,0 +1,803 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL
new file mode 100644
index 000000000..f688a34de
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL_tri_0
new file mode 100644
index 000000000..e1d99f600
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL_tri_0
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL_vtx_0
new file mode 100644
index 000000000..3e17db842
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoFortressDL_vtx_0
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL
new file mode 100644
index 000000000..493d63531
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL_tri_0
new file mode 100644
index 000000000..7d8b684a3
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL_tri_0
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL_vtx_0
new file mode 100644
index 000000000..a4cd37820
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconGerudoTrainingGroundDL_vtx_0
@@ -0,0 +1,430 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL b/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL
new file mode 100644
index 000000000..71426049e
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL_tri_0
new file mode 100644
index 000000000..25ecf0b48
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL_tri_0
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL_vtx_0
new file mode 100644
index 000000000..42a1284ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconShadowTempleDL_vtx_0
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL b/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL
new file mode 100644
index 000000000..5c314fb5a
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL_tri_0
new file mode 100644
index 000000000..fbce62b66
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL_tri_0
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL_vtx_0
new file mode 100644
index 000000000..66a2c5f88
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconSpiritTempleDL_vtx_0
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL b/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL
new file mode 100644
index 000000000..4e27a5d3e
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL_tri_0
new file mode 100644
index 000000000..246bae6a9
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL_tri_0
@@ -0,0 +1,376 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL_vtx_0
new file mode 100644
index 000000000..fd7c81995
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconTreasureChestGameDL_vtx_0
@@ -0,0 +1,406 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL b/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL
new file mode 100644
index 000000000..b2b4f5bfc
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL_tri_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL_tri_0
new file mode 100644
index 000000000..94037d2c9
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL_tri_0
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL_vtx_0 b/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL_vtx_0
new file mode 100644
index 000000000..2ff054194
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/gSmallKeyIconWaterTempleDL_vtx_0
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_black b/soh/assets/custom/objects/object_key/mat_gSkeletonKeyDL_f3dlite_KeyMetal_Skeleton
similarity index 66%
rename from soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_black
rename to soh/assets/custom/objects/object_key/mat_gSkeletonKeyDL_f3dlite_KeyMetal_Skeleton
index 6aee093d9..4062e86db 100644
--- a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_black
+++ b/soh/assets/custom/objects/object_key/mat_gSkeletonKeyDL_f3dlite_KeyMetal_Skeleton
@@ -1,21 +1,20 @@
-
+
-
+
-
+
-
+
-
+
-
diff --git a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_eyes b/soh/assets/custom/objects/object_key/mat_gSkeletonKeyDL_f3dlite_KeyMetal_SkeletonShade
similarity index 55%
rename from soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_eyes
rename to soh/assets/custom/objects/object_key/mat_gSkeletonKeyDL_f3dlite_KeyMetal_SkeletonShade
index c08beb94a..ac5b34610 100644
--- a/soh/assets/custom/objects/object_boss_soul/mat_gGIBossSoulSkullDL_skull_eyes
+++ b/soh/assets/custom/objects/object_key/mat_gSkeletonKeyDL_f3dlite_KeyMetal_SkeletonShade
@@ -1,21 +1,21 @@
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyCustomDL_f3dlite_KeyMetal_Small b/soh/assets/custom/objects/object_key/mat_gSmallKeyCustomDL_f3dlite_KeyMetal_Small
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyCustomDL_f3dlite_KeyMetal_Small
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconBottomoftheWellDL_f3dlite_IconMetal_BottomoftheWell b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconBottomoftheWellDL_f3dlite_IconMetal_BottomoftheWell
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconBottomoftheWellDL_f3dlite_IconMetal_BottomoftheWell
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconFireTempleDL_f3dlite_IconMetal_FireTemple b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconFireTempleDL_f3dlite_IconMetal_FireTemple
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconFireTempleDL_f3dlite_IconMetal_FireTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconForestTempleDL_f3dlite_IconMetal_ForestTemple b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconForestTempleDL_f3dlite_IconMetal_ForestTemple
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconForestTempleDL_f3dlite_IconMetal_ForestTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGanonsCastleDL_f3dlite_IconMetal_GanonsCastle b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGanonsCastleDL_f3dlite_IconMetal_GanonsCastle
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGanonsCastleDL_f3dlite_IconMetal_GanonsCastle
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGerudoTrainingGroundDL_f3dlite_IconMetal_GerudoTrainingGround b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGerudoTrainingGroundDL_f3dlite_IconMetal_GerudoTrainingGround
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconGerudoTrainingGroundDL_f3dlite_IconMetal_GerudoTrainingGround
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconShadowTempleDL_f3dlite_IconMetal_ShadowTemple b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconShadowTempleDL_f3dlite_IconMetal_ShadowTemple
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconShadowTempleDL_f3dlite_IconMetal_ShadowTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconSpiritTempleDL_f3dlite_IconMetal_SpiritTemple b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconSpiritTempleDL_f3dlite_IconMetal_SpiritTemple
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconSpiritTempleDL_f3dlite_IconMetal_SpiritTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconTreasureChestGameDL_f3dlite_IconMetal_TreasureChestGame b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconTreasureChestGameDL_f3dlite_IconMetal_TreasureChestGame
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconTreasureChestGameDL_f3dlite_IconMetal_TreasureChestGame
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_key/mat_gSmallKeyIconWaterTempleDL_f3dlite_IconMetal_WaterTemple b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconWaterTempleDL_f3dlite_IconMetal_WaterTemple
new file mode 100644
index 000000000..57c9001dd
--- /dev/null
+++ b/soh/assets/custom/objects/object_key/mat_gSmallKeyIconWaterTempleDL_f3dlite_IconMetal_WaterTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/Hilite_new b/soh/assets/custom/objects/object_keyring/Hilite_new
new file mode 100644
index 000000000..5438695fa
Binary files /dev/null and b/soh/assets/custom/objects/object_keyring/Hilite_new differ
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL b/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL
new file mode 100644
index 000000000..d00c883c1
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL_tri_0
new file mode 100644
index 000000000..0afe832af
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL_tri_0
@@ -0,0 +1,299 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL_vtx_0
new file mode 100644
index 000000000..58e9ef0ad
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconBottomoftheWellDL_vtx_0
@@ -0,0 +1,360 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL
new file mode 100644
index 000000000..10a581f75
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL_tri_0
new file mode 100644
index 000000000..3848bb958
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL_tri_0
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL_vtx_0
new file mode 100644
index 000000000..a48f4da09
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconFireTempleDL_vtx_0
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL
new file mode 100644
index 000000000..3f5f8e2b3
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL_tri_0
new file mode 100644
index 000000000..d76afc98f
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL_tri_0
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL_vtx_0
new file mode 100644
index 000000000..3d03eb5af
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconForestTempleDL_vtx_0
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL b/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL
new file mode 100644
index 000000000..11c19c09a
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL_tri_0
new file mode 100644
index 000000000..fae636a2e
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL_tri_0
@@ -0,0 +1,807 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL_vtx_0
new file mode 100644
index 000000000..709729262
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGanonsCastleDL_vtx_0
@@ -0,0 +1,865 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL
new file mode 100644
index 000000000..3552eef1b
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL_tri_0
new file mode 100644
index 000000000..791defa81
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL_tri_0
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0
new file mode 100644
index 000000000..1dd0cbb61
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoFortressDL_vtx_0
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL
new file mode 100644
index 000000000..f7bf5e89b
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL_tri_0
new file mode 100644
index 000000000..70e7032ef
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL_tri_0
@@ -0,0 +1,449 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL_vtx_0
new file mode 100644
index 000000000..f255b1e85
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconGerudoTrainingGroundDL_vtx_0
@@ -0,0 +1,495 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL
new file mode 100644
index 000000000..78f6956b6
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL_tri_0
new file mode 100644
index 000000000..e76ad0a59
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL_tri_0
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL_vtx_0
new file mode 100644
index 000000000..068971385
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconShadowTempleDL_vtx_0
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL
new file mode 100644
index 000000000..ac3998c5e
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL_tri_0
new file mode 100644
index 000000000..ed0bbd563
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL_tri_0
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL_vtx_0
new file mode 100644
index 000000000..519fda91b
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconSpiritTempleDL_vtx_0
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL b/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL
new file mode 100644
index 000000000..5dfb7d894
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL_tri_0
new file mode 100644
index 000000000..cba2269e6
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL_tri_0
@@ -0,0 +1,433 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL_vtx_0
new file mode 100644
index 000000000..0bddb8b22
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconTreasureChestGameDL_vtx_0
@@ -0,0 +1,461 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL
new file mode 100644
index 000000000..bcbb38c84
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL_tri_0
new file mode 100644
index 000000000..9eb74a012
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL_tri_0
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL_vtx_0
new file mode 100644
index 000000000..70d0655e2
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringIconWaterTempleDL_vtx_0
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL
new file mode 100644
index 000000000..5db16596e
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL_tri_0
new file mode 100644
index 000000000..d8c702732
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL_tri_0
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL_vtx_0
new file mode 100644
index 000000000..47d6419fc
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellDL_vtx_0
@@ -0,0 +1,301 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL
new file mode 100644
index 000000000..defb5b283
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL_tri_0
new file mode 100644
index 000000000..55f14d8e9
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL_tri_0
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL_vtx_0
new file mode 100644
index 000000000..81ca9693a
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysBottomoftheWellMQDL_vtx_0
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL
new file mode 100644
index 000000000..98ea5b8f4
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL_tri_0
new file mode 100644
index 000000000..a04f98241
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL_tri_0
@@ -0,0 +1,728 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL_vtx_0
new file mode 100644
index 000000000..3b96611f0
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleDL_vtx_0
@@ -0,0 +1,806 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL
new file mode 100644
index 000000000..3d81cd28b
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL_tri_0
new file mode 100644
index 000000000..ca8d79f15
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL_tri_0
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL_vtx_0
new file mode 100644
index 000000000..114ad7219
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysFireTempleMQDL_vtx_0
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL
new file mode 100644
index 000000000..74831c220
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL_tri_0
new file mode 100644
index 000000000..009f5a41d
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL_tri_0
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL_vtx_0
new file mode 100644
index 000000000..114ad7219
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleDL_vtx_0
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL
new file mode 100644
index 000000000..33b2eaa3e
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL_tri_0
new file mode 100644
index 000000000..491d44044
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL_tri_0
@@ -0,0 +1,547 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL_vtx_0
new file mode 100644
index 000000000..5331ba549
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysForestTempleMQDL_vtx_0
@@ -0,0 +1,605 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL
new file mode 100644
index 000000000..693b894b9
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL_tri_0
new file mode 100644
index 000000000..0c059294f
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL_tri_0
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL_vtx_0
new file mode 100644
index 000000000..47d6419fc
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleDL_vtx_0
@@ -0,0 +1,301 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL
new file mode 100644
index 000000000..fe6e93dd6
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL_tri_0
new file mode 100644
index 000000000..eae1fe0fd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL_tri_0
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL_vtx_0
new file mode 100644
index 000000000..81ca9693a
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGanonsCastleMQDL_vtx_0
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL
new file mode 100644
index 000000000..71b8e23e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL_tri_0
new file mode 100644
index 000000000..5aa84af33
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL_tri_0
@@ -0,0 +1,366 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL_vtx_0
new file mode 100644
index 000000000..1005037ee
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoFortressDL_vtx_0
@@ -0,0 +1,404 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL
new file mode 100644
index 000000000..d01877e7b
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL_tri_0
new file mode 100644
index 000000000..fd249043c
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL_tri_0
@@ -0,0 +1,819 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL_vtx_0
new file mode 100644
index 000000000..bc91491ad
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL_vtx_0
@@ -0,0 +1,904 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL
new file mode 100644
index 000000000..cb914449c
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL_tri_0
new file mode 100644
index 000000000..5fb4d5f7e
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL_tri_0
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL_vtx_0
new file mode 100644
index 000000000..47d6419fc
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL_vtx_0
@@ -0,0 +1,301 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL
new file mode 100644
index 000000000..7738f6244
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL_tri_0
new file mode 100644
index 000000000..612359c24
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL_tri_0
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL_vtx_0
new file mode 100644
index 000000000..114ad7219
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleDL_vtx_0
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL
new file mode 100644
index 000000000..d9b35ef41
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL_tri_0
new file mode 100644
index 000000000..d5f911605
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL_tri_0
@@ -0,0 +1,547 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL_vtx_0
new file mode 100644
index 000000000..5331ba549
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysShadowTempleMQDL_vtx_0
@@ -0,0 +1,605 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL
new file mode 100644
index 000000000..f2f531e39
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL_tri_0
new file mode 100644
index 000000000..34e3d25b2
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL_tri_0
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL_vtx_0
new file mode 100644
index 000000000..114ad7219
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleDL_vtx_0
@@ -0,0 +1,502 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL
new file mode 100644
index 000000000..1a6058c23
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL_tri_0
new file mode 100644
index 000000000..a4c7b6c8a
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL_tri_0
@@ -0,0 +1,638 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL_vtx_0
new file mode 100644
index 000000000..b32d9fd51
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysSpiritTempleMQDL_vtx_0
@@ -0,0 +1,703 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL
new file mode 100644
index 000000000..69c9d7a9f
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL_tri_0
new file mode 100644
index 000000000..548ac5731
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL_tri_0
@@ -0,0 +1,366 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL_vtx_0
new file mode 100644
index 000000000..1005037ee
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysTreasureChestGameDL_vtx_0
@@ -0,0 +1,404 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL
new file mode 100644
index 000000000..72868b384
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL_tri_0
new file mode 100644
index 000000000..5ef106903
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL_tri_0
@@ -0,0 +1,547 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL_vtx_0
new file mode 100644
index 000000000..5331ba549
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleDL_vtx_0
@@ -0,0 +1,605 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL
new file mode 100644
index 000000000..1394e1eb9
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL_tri_0
new file mode 100644
index 000000000..e81ea815f
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL_tri_0
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL_vtx_0
new file mode 100644
index 000000000..81ca9693a
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringKeysWaterTempleMQDL_vtx_0
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringRingDL b/soh/assets/custom/objects/object_keyring/gKeyringRingDL
new file mode 100644
index 000000000..8939b439e
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringRingDL
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringRingDL_tri_0 b/soh/assets/custom/objects/object_keyring/gKeyringRingDL_tri_0
new file mode 100644
index 000000000..1e143c948
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringRingDL_tri_0
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/gKeyringRingDL_vtx_0 b/soh/assets/custom/objects/object_keyring/gKeyringRingDL_vtx_0
new file mode 100644
index 000000000..4008f3806
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/gKeyringRingDL_vtx_0
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconBottomoftheWellDL_f3dlite_IconMetal_BottomoftheWell b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconBottomoftheWellDL_f3dlite_IconMetal_BottomoftheWell
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconBottomoftheWellDL_f3dlite_IconMetal_BottomoftheWell
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconFireTempleDL_f3dlite_IconMetal_FireTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconFireTempleDL_f3dlite_IconMetal_FireTemple
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconFireTempleDL_f3dlite_IconMetal_FireTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconForestTempleDL_f3dlite_IconMetal_ForestTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconForestTempleDL_f3dlite_IconMetal_ForestTemple
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconForestTempleDL_f3dlite_IconMetal_ForestTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGanonsCastleDL_f3dlite_IconMetal_GanonsCastle b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGanonsCastleDL_f3dlite_IconMetal_GanonsCastle
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGanonsCastleDL_f3dlite_IconMetal_GanonsCastle
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress
new file mode 100644
index 000000000..b5755b4a8
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGerudoFortressDL_f3dlite_IconMetal_GerudoFortress
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGerudoTrainingGroundDL_f3dlite_IconMetal_GerudoTrainingGround b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGerudoTrainingGroundDL_f3dlite_IconMetal_GerudoTrainingGround
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconGerudoTrainingGroundDL_f3dlite_IconMetal_GerudoTrainingGround
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconShadowTempleDL_f3dlite_IconMetal_ShadowTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconShadowTempleDL_f3dlite_IconMetal_ShadowTemple
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconShadowTempleDL_f3dlite_IconMetal_ShadowTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconSpiritTempleDL_f3dlite_IconMetal_SpiritTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconSpiritTempleDL_f3dlite_IconMetal_SpiritTemple
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconSpiritTempleDL_f3dlite_IconMetal_SpiritTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconTreasureChestGameDL_f3dlite_IconMetal_TreasureChestGame b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconTreasureChestGameDL_f3dlite_IconMetal_TreasureChestGame
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconTreasureChestGameDL_f3dlite_IconMetal_TreasureChestGame
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringIconWaterTempleDL_f3dlite_IconMetal_WaterTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconWaterTempleDL_f3dlite_IconMetal_WaterTemple
new file mode 100644
index 000000000..a76e9f9bd
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringIconWaterTempleDL_f3dlite_IconMetal_WaterTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysBottomoftheWellDL_f3dlite_KeyMetal_BottomoftheWell b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysBottomoftheWellDL_f3dlite_KeyMetal_BottomoftheWell
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysBottomoftheWellDL_f3dlite_KeyMetal_BottomoftheWell
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysBottomoftheWellMQDL_f3dlite_KeyMetal_BottomoftheWell b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysBottomoftheWellMQDL_f3dlite_KeyMetal_BottomoftheWell
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysBottomoftheWellMQDL_f3dlite_KeyMetal_BottomoftheWell
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysFireTempleDL_f3dlite_KeyMetal_FireTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysFireTempleDL_f3dlite_KeyMetal_FireTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysFireTempleDL_f3dlite_KeyMetal_FireTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysFireTempleMQDL_f3dlite_KeyMetal_FireTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysFireTempleMQDL_f3dlite_KeyMetal_FireTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysFireTempleMQDL_f3dlite_KeyMetal_FireTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysForestTempleDL_f3dlite_KeyMetal_ForestTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysForestTempleDL_f3dlite_KeyMetal_ForestTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysForestTempleDL_f3dlite_KeyMetal_ForestTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysForestTempleMQDL_f3dlite_KeyMetal_ForestTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysForestTempleMQDL_f3dlite_KeyMetal_ForestTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysForestTempleMQDL_f3dlite_KeyMetal_ForestTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGanonsCastleDL_f3dlite_KeyMetal_GanonsCastle b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGanonsCastleDL_f3dlite_KeyMetal_GanonsCastle
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGanonsCastleDL_f3dlite_KeyMetal_GanonsCastle
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGanonsCastleMQDL_f3dlite_KeyMetal_GanonsCastle b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGanonsCastleMQDL_f3dlite_KeyMetal_GanonsCastle
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGanonsCastleMQDL_f3dlite_KeyMetal_GanonsCastle
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoFortressDL_f3dlite_KeyMetal_GerudoFortress b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoFortressDL_f3dlite_KeyMetal_GerudoFortress
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoFortressDL_f3dlite_KeyMetal_GerudoFortress
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoTrainingGroundDL_f3dlite_KeyMetal_GerudoTrainingGround b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoTrainingGroundDL_f3dlite_KeyMetal_GerudoTrainingGround
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoTrainingGroundDL_f3dlite_KeyMetal_GerudoTrainingGround
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoTrainingGroundMQDL_f3dlite_KeyMetal_GerudoTrainingGround b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoTrainingGroundMQDL_f3dlite_KeyMetal_GerudoTrainingGround
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysGerudoTrainingGroundMQDL_f3dlite_KeyMetal_GerudoTrainingGround
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysShadowTempleDL_f3dlite_KeyMetal_ShadowTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysShadowTempleDL_f3dlite_KeyMetal_ShadowTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysShadowTempleDL_f3dlite_KeyMetal_ShadowTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysShadowTempleMQDL_f3dlite_KeyMetal_ShadowTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysShadowTempleMQDL_f3dlite_KeyMetal_ShadowTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysShadowTempleMQDL_f3dlite_KeyMetal_ShadowTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysSpiritTempleDL_f3dlite_KeyMetal_SpiritTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysSpiritTempleDL_f3dlite_KeyMetal_SpiritTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysSpiritTempleDL_f3dlite_KeyMetal_SpiritTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysSpiritTempleMQDL_f3dlite_KeyMetal_SpiritTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysSpiritTempleMQDL_f3dlite_KeyMetal_SpiritTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysSpiritTempleMQDL_f3dlite_KeyMetal_SpiritTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysTreasureChestGameDL_f3dlite_KeyMetal_TreasureChestGame b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysTreasureChestGameDL_f3dlite_KeyMetal_TreasureChestGame
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysTreasureChestGameDL_f3dlite_KeyMetal_TreasureChestGame
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysWaterTempleDL_f3dlite_KeyMetal_WaterTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysWaterTempleDL_f3dlite_KeyMetal_WaterTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysWaterTempleDL_f3dlite_KeyMetal_WaterTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysWaterTempleMQDL_f3dlite_KeyMetal_WaterTemple b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysWaterTempleMQDL_f3dlite_KeyMetal_WaterTemple
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringKeysWaterTempleMQDL_f3dlite_KeyMetal_WaterTemple
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_keyring/mat_gKeyringRingDL_f3dlite_KeyRingMetal b/soh/assets/custom/objects/object_keyring/mat_gKeyringRingDL_f3dlite_KeyRingMetal
new file mode 100644
index 000000000..fafddd268
--- /dev/null
+++ b/soh/assets/custom/objects/object_keyring/mat_gKeyringRingDL_f3dlite_KeyRingMetal
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/textures/parameter_static/gBossSoul.rgba32.png b/soh/assets/custom/textures/parameter_static/gBossSoul.rgba32.png
old mode 100755
new mode 100644
index 9fe2ac404..4e60a4995
Binary files a/soh/assets/custom/textures/parameter_static/gBossSoul.rgba32.png and b/soh/assets/custom/textures/parameter_static/gBossSoul.rgba32.png differ
diff --git a/soh/assets/objects/object_shopnuts/object_shopnuts.h b/soh/assets/objects/object_shopnuts/object_shopnuts.h
index f7408c648..a5879943b 100644
--- a/soh/assets/objects/object_shopnuts/object_shopnuts.h
+++ b/soh/assets/objects/object_shopnuts/object_shopnuts.h
@@ -102,8 +102,8 @@ static const ALIGN_ASSET(2) char gBusinessScrubNervousIdleAnim[] = dgBusinessScr
#define dgBusinessScrubAnim_139C "__OTR__objects/object_shopnuts/gBusinessScrubAnim_139C"
static const ALIGN_ASSET(2) char gBusinessScrubAnim_139C[] = dgBusinessScrubAnim_139C;
-#define dgBusinessScrubAnim_4404 "__OTR__objects/object_shopnuts/gBusinessScrubAnim_4404"
-static const ALIGN_ASSET(2) char gBusinessScrubAnim_4404[] = dgBusinessScrubAnim_4404;
+#define dgBusinessScrubLeaveBurrowAnim "__OTR__objects/object_shopnuts/gBusinessScrubLeaveBurrowAnim"
+static const ALIGN_ASSET(2) char gBusinessScrubLeaveBurrowAnim[] = dgBusinessScrubLeaveBurrowAnim;
#define dgBusinessScrubAnim_4574 "__OTR__objects/object_shopnuts/gBusinessScrubAnim_4574"
static const ALIGN_ASSET(2) char gBusinessScrubAnim_4574[] = dgBusinessScrubAnim_4574;
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 894be4106..ace158854 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -83,6 +83,163 @@ static const ALIGN_ASSET(2) char gFishingPoleGiDL[] = dgFishingPoleGiDL;
#define dgMysteryItemDL "__OTR__objects/object_mystery_item/gMysteryItemDL"
static const ALIGN_ASSET(2) char gMysteryItemDL[] = dgMysteryItemDL;
+#define dgBombchuBagBodyDL "__OTR__objects/object_bombchubag/gBombchuBagBodyDL"
+static const ALIGN_ASSET(2) char gBombchuBagBodyDL[] = dgBombchuBagBodyDL;
+
+#define dgBombchuBagMaskDL "__OTR__objects/object_bombchubag/gBombchuBagMaskDL"
+static const ALIGN_ASSET(2) char gBombchuBagMaskDL[] = dgBombchuBagMaskDL;
+
+//boss keys
+#define dgBossKeyCustomDL "__OTR__objects/object_bosskey/gBossKeyCustomDL"
+static const ALIGN_ASSET(2) char gBossKeyCustomDL[] = dgBossKeyCustomDL;
+
+#define dgBossKeyIconForestTempleDL "__OTR__objects/object_bosskey/gBossKeyIconForestTempleDL"
+static const ALIGN_ASSET(2) char gBossKeyIconForestTempleDL[] = dgBossKeyIconForestTempleDL;
+
+#define dgBossKeyIconFireTempleDL "__OTR__objects/object_bosskey/gBossKeyIconFireTempleDL"
+static const ALIGN_ASSET(2) char gBossKeyIconFireTempleDL[] = dgBossKeyIconFireTempleDL;
+
+#define dgBossKeyIconWaterTempleDL "__OTR__objects/object_bosskey/gBossKeyIconWaterTempleDL"
+static const ALIGN_ASSET(2) char gBossKeyIconWaterTempleDL[] = dgBossKeyIconWaterTempleDL;
+
+#define dgBossKeyIconSpiritTempleDL "__OTR__objects/object_bosskey/gBossKeyIconSpiritTempleDL"
+static const ALIGN_ASSET(2) char gBossKeyIconSpiritTempleDL[] = dgBossKeyIconSpiritTempleDL;
+
+#define dgBossKeyIconShadowTempleDL "__OTR__objects/object_bosskey/gBossKeyIconShadowTempleDL"
+static const ALIGN_ASSET(2) char gBossKeyIconShadowTempleDL[] = dgBossKeyIconShadowTempleDL;
+
+#define dgBossKeyIconGanonsCastleDL "__OTR__objects/object_bosskey/gBossKeyIconGanonsCastleDL"
+static const ALIGN_ASSET(2) char gBossKeyIconGanonsCastleDL[] = dgBossKeyIconGanonsCastleDL;
+
+//skeleton key
+#define dgSkeletonKeyDL "__OTR__objects/object_key/gSkeletonKeyDL"
+static const ALIGN_ASSET(2) char gSkeletonKeyDL[] = dgSkeletonKeyDL;
+
+//small keys
+#define dgSmallKeyCustomDL "__OTR__objects/object_key/gSmallKeyCustomDL"
+static const ALIGN_ASSET(2) char gSmallKeyCustomDL[] = dgSmallKeyCustomDL;
+
+#define dgSmallKeyIconForestTempleDL "__OTR__objects/object_key/gSmallKeyIconForestTempleDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconForestTempleDL[] = dgSmallKeyIconForestTempleDL;
+
+#define dgSmallKeyIconFireTempleDL "__OTR__objects/object_key/gSmallKeyIconFireTempleDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconFireTempleDL[] = dgSmallKeyIconFireTempleDL;
+
+#define dgSmallKeyIconWaterTempleDL "__OTR__objects/object_key/gSmallKeyIconWaterTempleDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconWaterTempleDL[] = dgSmallKeyIconWaterTempleDL;
+
+#define dgSmallKeyIconGerudoFortressDL "__OTR__objects/object_key/gSmallKeyIconGerudoFortressDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconGerudoFortressDL[] = dgSmallKeyIconGerudoFortressDL;
+
+#define dgSmallKeyIconGerudoTrainingGroundDL "__OTR__objects/object_key/gSmallKeyIconGerudoTrainingGroundDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconGerudoTrainingGroundDL[] = dgSmallKeyIconGerudoTrainingGroundDL;
+
+#define dgSmallKeyIconSpiritTempleDL "__OTR__objects/object_key/gSmallKeyIconSpiritTempleDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconSpiritTempleDL[] = dgSmallKeyIconSpiritTempleDL;
+
+#define dgSmallKeyIconBottomoftheWellDL "__OTR__objects/object_key/gSmallKeyIconBottomoftheWellDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconBottomoftheWellDL[] = dgSmallKeyIconBottomoftheWellDL;
+
+#define dgSmallKeyIconShadowTempleDL "__OTR__objects/object_key/gSmallKeyIconShadowTempleDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconShadowTempleDL[] = dgSmallKeyIconShadowTempleDL;
+
+#define dgSmallKeyIconGanonsCastleDL "__OTR__objects/object_key/gSmallKeyIconGanonsCastleDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconGanonsCastleDL[] = dgSmallKeyIconGanonsCastleDL;
+
+#define dgSmallKeyIconTreasureChestGameDL "__OTR__objects/object_key/gSmallKeyIconTreasureChestGameDL"
+static const ALIGN_ASSET(2) char gSmallKeyIconTreasureChestGameDL[] = dgSmallKeyIconTreasureChestGameDL;
+
+//keyrings
+#define dgKeyringRingDL "__OTR__objects/object_keyring/gKeyringRingDL"
+static const ALIGN_ASSET(2) char gKeyringRingDL[] = dgKeyringRingDL;
+
+#define dgKeyringIconForestTempleDL "__OTR__objects/object_keyring/gKeyringIconForestTempleDL"
+static const ALIGN_ASSET(2) char gKeyringIconForestTempleDL[] = dgKeyringIconForestTempleDL;
+
+#define dgKeyringIconFireTempleDL "__OTR__objects/object_keyring/gKeyringIconFireTempleDL"
+static const ALIGN_ASSET(2) char gKeyringIconFireTempleDL[] = dgKeyringIconFireTempleDL;
+
+#define dgKeyringIconWaterTempleDL "__OTR__objects/object_keyring/gKeyringIconWaterTempleDL"
+static const ALIGN_ASSET(2) char gKeyringIconWaterTempleDL[] = dgKeyringIconWaterTempleDL;
+
+#define dgKeyringIconGerudoFortressDL "__OTR__objects/object_keyring/gKeyringIconGerudoFortressDL"
+static const ALIGN_ASSET(2) char gKeyringIconGerudoFortressDL[] = dgKeyringIconGerudoFortressDL;
+
+#define dgKeyringIconGerudoTrainingGroundDL "__OTR__objects/object_keyring/gKeyringIconGerudoTrainingGroundDL"
+static const ALIGN_ASSET(2) char gKeyringIconGerudoTrainingGroundDL[] = dgKeyringIconGerudoTrainingGroundDL;
+
+#define dgKeyringIconSpiritTempleDL "__OTR__objects/object_keyring/gKeyringIconSpiritTempleDL"
+static const ALIGN_ASSET(2) char gKeyringIconSpiritTempleDL[] = dgKeyringIconSpiritTempleDL;
+
+#define dgKeyringIconBottomoftheWellDL "__OTR__objects/object_keyring/gKeyringIconBottomoftheWellDL"
+static const ALIGN_ASSET(2) char gKeyringIconBottomoftheWellDL[] = dgKeyringIconBottomoftheWellDL;
+
+#define dgKeyringIconShadowTempleDL "__OTR__objects/object_keyring/gKeyringIconShadowTempleDL"
+static const ALIGN_ASSET(2) char gKeyringIconShadowTempleDL[] = dgKeyringIconShadowTempleDL;
+
+#define dgKeyringIconGanonsCastleDL "__OTR__objects/object_keyring/gKeyringIconGanonsCastleDL"
+static const ALIGN_ASSET(2) char gKeyringIconGanonsCastleDL[] = dgKeyringIconGanonsCastleDL;
+
+#define dgKeyringIconTreasureChestGameDL "__OTR__objects/object_keyring/gKeyringIconTreasureChestGameDL"
+static const ALIGN_ASSET(2) char gKeyringIconTreasureChestGameDL[] = dgKeyringIconTreasureChestGameDL;
+
+#define dgKeyringKeysForestTempleDL "__OTR__objects/object_keyring/gKeyringKeysForestTempleDL"
+static const ALIGN_ASSET(2) char gKeyringKeysForestTempleDL[] = dgKeyringKeysForestTempleDL;
+
+#define dgKeyringKeysFireTempleDL "__OTR__objects/object_keyring/gKeyringKeysFireTempleDL"
+static const ALIGN_ASSET(2) char gKeyringKeysFireTempleDL[] = dgKeyringKeysFireTempleDL;
+
+#define dgKeyringKeysWaterTempleDL "__OTR__objects/object_keyring/gKeyringKeysWaterTempleDL"
+static const ALIGN_ASSET(2) char gKeyringKeysWaterTempleDL[] = dgKeyringKeysWaterTempleDL;
+
+#define dgKeyringKeysGerudoFortressDL "__OTR__objects/object_keyring/gKeyringKeysGerudoFortressDL"
+static const ALIGN_ASSET(2) char gKeyringKeysGerudoFortressDL[] = dgKeyringKeysGerudoFortressDL;
+
+#define dgKeyringKeysGerudoTrainingGroundDL "__OTR__objects/object_keyring/gKeyringKeysGerudoTrainingGroundDL"
+static const ALIGN_ASSET(2) char gKeyringKeysGerudoTrainingGroundDL[] = dgKeyringKeysGerudoTrainingGroundDL;
+
+#define dgKeyringKeysSpiritTempleDL "__OTR__objects/object_keyring/gKeyringKeysSpiritTempleDL"
+static const ALIGN_ASSET(2) char gKeyringKeysSpiritTempleDL[] = dgKeyringKeysSpiritTempleDL;
+
+#define dgKeyringKeysBottomoftheWellDL "__OTR__objects/object_keyring/gKeyringKeysBottomoftheWellDL"
+static const ALIGN_ASSET(2) char gKeyringKeysBottomoftheWellDL[] = dgKeyringKeysBottomoftheWellDL;
+
+#define dgKeyringKeysShadowTempleDL "__OTR__objects/object_keyring/gKeyringKeysShadowTempleDL"
+static const ALIGN_ASSET(2) char gKeyringKeysShadowTempleDL[] = dgKeyringKeysShadowTempleDL;
+
+#define dgKeyringKeysGanonsCastleDL "__OTR__objects/object_keyring/gKeyringKeysGanonsCastleDL"
+static const ALIGN_ASSET(2) char gKeyringKeysGanonsCastleDL[] = dgKeyringKeysGanonsCastleDL;
+
+#define dgKeyringKeysTreasureChestGameDL "__OTR__objects/object_keyring/gKeyringKeysTreasureChestGameDL"
+static const ALIGN_ASSET(2) char gKeyringKeysTreasureChestGameDL[] = dgKeyringKeysTreasureChestGameDL;
+
+#define dgKeyringKeysForestTempleMQDL "__OTR__objects/object_keyring/gKeyringKeysForestTempleMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysForestTempleMQDL[] = dgKeyringKeysForestTempleMQDL;
+
+#define dgKeyringKeysFireTempleMQDL "__OTR__objects/object_keyring/gKeyringKeysFireTempleMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysFireTempleMQDL[] = dgKeyringKeysFireTempleMQDL;
+
+#define dgKeyringKeysWaterTempleMQDL "__OTR__objects/object_keyring/gKeyringKeysWaterTempleMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysWaterTempleMQDL[] = dgKeyringKeysWaterTempleMQDL;
+
+#define dgKeyringKeysGerudoTrainingGroundMQDL "__OTR__objects/object_keyring/gKeyringKeysGerudoTrainingGroundMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysGerudoTrainingGroundMQDL[] = dgKeyringKeysGerudoTrainingGroundMQDL;
+
+#define dgKeyringKeysSpiritTempleMQDL "__OTR__objects/object_keyring/gKeyringKeysSpiritTempleMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysSpiritTempleMQDL[] = dgKeyringKeysSpiritTempleMQDL;
+
+#define dgKeyringKeysBottomoftheWellMQDL "__OTR__objects/object_keyring/gKeyringKeysBottomoftheWellMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysBottomoftheWellMQDL[] = dgKeyringKeysBottomoftheWellMQDL;
+
+#define dgKeyringKeysShadowTempleMQDL "__OTR__objects/object_keyring/gKeyringKeysShadowTempleMQDL"
+static const ALIGN_ASSET(2) char gKeyringKeysShadowTempleMQDL[] = dgKeyringKeysShadowTempleMQDL;
+
+#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;
@@ -181,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/assets/xml/GC_MQ_D/objects/object_shopnuts.xml b/soh/assets/xml/GC_MQ_D/objects/object_shopnuts.xml
index a4e12e38a..7065f8941 100644
--- a/soh/assets/xml/GC_MQ_D/objects/object_shopnuts.xml
+++ b/soh/assets/xml/GC_MQ_D/objects/object_shopnuts.xml
@@ -61,7 +61,7 @@
-
+
diff --git a/soh/assets/xml/GC_MQ_PAL_F/objects/object_shopnuts.xml b/soh/assets/xml/GC_MQ_PAL_F/objects/object_shopnuts.xml
index a4e12e38a..7065f8941 100644
--- a/soh/assets/xml/GC_MQ_PAL_F/objects/object_shopnuts.xml
+++ b/soh/assets/xml/GC_MQ_PAL_F/objects/object_shopnuts.xml
@@ -61,7 +61,7 @@
-
+
diff --git a/soh/assets/xml/GC_NMQ_D/objects/object_shopnuts.xml b/soh/assets/xml/GC_NMQ_D/objects/object_shopnuts.xml
index a4e12e38a..7065f8941 100644
--- a/soh/assets/xml/GC_NMQ_D/objects/object_shopnuts.xml
+++ b/soh/assets/xml/GC_NMQ_D/objects/object_shopnuts.xml
@@ -61,7 +61,7 @@
-
+
diff --git a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_shopnuts.xml b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_shopnuts.xml
index a4e12e38a..7065f8941 100644
--- a/soh/assets/xml/GC_NMQ_PAL_F/objects/object_shopnuts.xml
+++ b/soh/assets/xml/GC_NMQ_PAL_F/objects/object_shopnuts.xml
@@ -61,7 +61,7 @@
-
+
diff --git a/soh/assets/xml/N64_PAL_10/objects/object_shopnuts.xml b/soh/assets/xml/N64_PAL_10/objects/object_shopnuts.xml
index a4e12e38a..7065f8941 100644
--- a/soh/assets/xml/N64_PAL_10/objects/object_shopnuts.xml
+++ b/soh/assets/xml/N64_PAL_10/objects/object_shopnuts.xml
@@ -61,7 +61,7 @@
-
+
diff --git a/soh/assets/xml/N64_PAL_11/objects/object_shopnuts.xml b/soh/assets/xml/N64_PAL_11/objects/object_shopnuts.xml
index a4e12e38a..7065f8941 100644
--- a/soh/assets/xml/N64_PAL_11/objects/object_shopnuts.xml
+++ b/soh/assets/xml/N64_PAL_11/objects/object_shopnuts.xml
@@ -61,7 +61,7 @@
-
+
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/include/z64actor.h b/soh/include/z64actor.h
index 272237d21..6d8fd3ca0 100644
--- a/soh/include/z64actor.h
+++ b/soh/include/z64actor.h
@@ -94,34 +94,120 @@ typedef struct {
/* 0x18 */ Vec3f feetPos[2]; // Update by using `Actor_SetFeetPos` in PostLimbDraw
} ActorShape; // size = 0x30
-#define ACTOR_FLAG_TARGETABLE (1 << 0)
+// Actor is discoverable by the Attention System. This enables Navi to hover over the actor when it is in range.
+// The actor can also be locked onto (as long as `ACTOR_FLAG_LOCK_ON_DISABLED` is not set).
+#define ACTOR_FLAG_ATTENTION_ENABLED (1 << 0)
+
+// Actor is hostile toward the Player. Player has specific "battle" behavior when locked onto hostile actors.
+// Enemy background music will also be played when the player is close enough to a hostile actor.
+// Note: This must be paired with `ACTOR_FLAG_ATTENTION_ENABLED` to have any effect
#define ACTOR_FLAG_HOSTILE (1 << 2)
+
+// Actor is considered "friendly"; Opposite flag of `ACTOR_FLAG_HOSTILE`.
+// Note that this flag doesn't have any effect on either the actor, or Player's behavior.
+// What actually matters is the presence or lack of `ACTOR_FLAG_HOSTILE`.
#define ACTOR_FLAG_FRIENDLY (1 << 3)
-#define ACTOR_FLAG_UPDATE_WHILE_CULLED (1 << 4)
-#define ACTOR_FLAG_DRAW_WHILE_CULLED (1 << 5)
-#define ACTOR_FLAG_ACTIVE (1 << 6)
-#define ACTOR_FLAG_LENS (1 << 7)
-#define ACTOR_FLAG_PLAYER_TALKED_TO (1 << 8)
-#define ACTOR_FLAG_HOOKSHOT_DRAGS (1 << 9)
-#define ACTOR_FLAG_DRAGGED_BY_HOOKSHOT (1 << 10)
-#define ACTOR_FLAG_ENKUSA_CUT (1 << 11)
+
+// Culling of the actor's update process is disabled.
+// In other words, the actor will keep updating even if the actor is outside its own culling volume.
+// See `Actor_CullingCheck` for more information about culling.
+// See `Actor_CullingVolumeTest` for more information on the test used to determine if an actor should be culled.
+#define ACTOR_FLAG_UPDATE_CULLING_DISABLED (1 << 4)
+
+// Culling of the actor's draw process is disabled.
+// In other words, the actor will keep drawing even if the actor is outside its own culling volume.
+// See `Actor_CullingCheck` for more information about culling.
+// See `Actor_CullingVolumeTest` for more information on the test used to determine if an actor should be culled.
+// (The original name for this flag is `NO_CULL_DRAW`, known from the Majora's Mask Debug ROM)
+#define ACTOR_FLAG_DRAW_CULLING_DISABLED (1 << 5)
+
+// Set if the actor is currently within the bounds of its culling volume.
+// In most cases, this flag can be used to determine whether or not an actor is currently culled.
+// However this flag still updates even if `ACTOR_FLAG_UPDATE_CULLING_DISABLED` or `ACTOR_FLAG_DRAW_CULLING_DISABLED`
+// are set. Meaning, the flag can still have a value of "false" even if it is not actually culled.
+// (The original name for this flag is `NO_CULL_FLAG`, known from the Majora's Mask Debug ROM)
+#define ACTOR_FLAG_INSIDE_CULLING_VOLUME (1 << 6)
+
+// hidden or revealed by Lens of Truth (depending on room lensMode)
+#define ACTOR_FLAG_REACT_TO_LENS (1 << 7)
+
+// Signals that player has accepted an offer to talk to an actor
+// Player will retain this flag until the player is finished talking
+// Actor will retain this flag until `Actor_TalkOfferAccepted` is called or manually turned off by the actor
+#define ACTOR_FLAG_TALK (1 << 8)
+
+// When the hookshot attaches to this actor, the actor will be pulled back as the hookshot retracts.
+#define ACTOR_FLAG_HOOKSHOT_PULLS_ACTOR (1 << 9)
+
+// When the hookshot attaches to this actor, Player will be pulled by the hookshot and fly to the actor.
+#define ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER (1 << 10)
+
+// A clump of grass (EN_KUSA) has been destroyed.
+// This flag is used to communicate with the spawner actor (OBJ_MURE).
+#define ACTOR_FLAG_GRASS_DESTROYED (1 << 11)
+
+// Actor will not shake when a quake occurs
#define ACTOR_FLAG_IGNORE_QUAKE (1 << 12)
+
+// The hookshot is currently attached to this actor.
+// The behavior that occurs after attachment is determined by `ACTOR_FLAG_HOOKSHOT_PULLS_ACTOR` and `ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER`.
+// If neither of those flags are set attachment cannot occur, and the hookshot will simply act as a damage source.
+//
+// This flag is also reused to indicate that an actor is attached to the boomerang.
+// This only has an effect for Gold Skulltula Tokens (EN_SI) which has overlapping behavior for hookshot and boomerang.
#define ACTOR_FLAG_HOOKSHOT_ATTACHED (1 << 13)
-#define ACTOR_FLAG_ARROW_DRAGGABLE (1 << 14)
-#define ACTOR_FLAG_DRAGGED_BY_ARROW (1 << 15)
-#define ACTOR_FLAG_WILL_TALK (1 << 16)
-#define ACTOR_FLAG_PILLAR_PICKUP (1 << 17)
-#define ACTOR_FLAG_NAVI_HAS_INFO (1 << 18)
-#define ACTOR_FLAG_SFX_AT_POS (1 << 19)
-#define ACTOR_FLAG_SFX_AT_CENTER (1 << 20)
-#define ACTOR_FLAG_SFX_AT_CENTER2 (1 << 21)
+
+// When hit by an arrow, the actor will be able to attach to the arrow and fly with it in the air
+#define ACTOR_FLAG_CAN_ATTACH_TO_ARROW (1 << 14)
+
+// Actor is currently attached to an arrow and flying with it in the air
+#define ACTOR_FLAG_ATTACHED_TO_ARROW (1 << 15)
+
+// Player automatically accepts a Talk Offer without needing to press the A button.
+// Player still has to meet all conditions to be able to receive a talk offer (for example, being in range).
+#define ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED (1 << 16)
+
+// Actor will be influenced by the pitch (x rot) of Player's left hand when being carried,
+// instead of Player's yaw which is the default actor carry behavior.
+// This flag is helpful for something like the `BG_HEAVY_BLOCK` actor which Player carries underhanded.
+#define ACTOR_FLAG_CARRY_X_ROT_INFLUENCE (1 << 17)
+
+// When locked onto an actor with this flag set, the C-Up button can be used to talk to this actor.
+// A C-Up button labeled "Navi" will appear on the HUD when locked on which indicates the actor can be checked with Navi.
+// With this flag Player talks directly to the actor with C-Up. It is expected that the resulting dialog should appear
+// to be coming from Navi, even though she is not involved at all with this interaction.
+#define ACTOR_FLAG_TALK_WITH_C_UP (1 << 18)
+
+// Flags controlling the use of `Actor.sfx`. Do not use directly.
+#define ACTOR_FLAG_SFX_ACTOR_POS_2 (1 << 19)
+#define ACTOR_AUDIO_FLAG_SFX_CENTERED_1 (1 << 20)
+#define ACTOR_AUDIO_FLAG_SFX_CENTERED_2 (1 << 21)
+
+// ignores point lights but not directional lights (such as environment lights)
#define ACTOR_FLAG_IGNORE_POINTLIGHTS (1 << 22)
-#define ACTOR_FLAG_ALWAYS_THROWN (1 << 23)
-#define ACTOR_FLAG_PLAY_HIT_SFX (1 << 24)
-#define ACTOR_FLAG_NO_FREEZE_OCARINA (1 << 25)
-#define ACTOR_FLAG_CAN_PRESS_SWITCH (1 << 26)
-#define ACTOR_FLAG_NO_LOCKON (1 << 27)
-#define ACTOR_FLAG_SFX_AS_TIMER (1 << 28)
+
+// When Player is carrying this actor, it can only be thrown, not dropped/placed.
+// Typically an actor can only be thrown when moving, but this allows an actor to be thrown when standing still.
+#define ACTOR_FLAG_THROW_ONLY (1 << 23)
+
+// When colliding with Player's body AC collider, a "thump" sound will play indicating his body has been hit
+#define ACTOR_FLAG_SFX_FOR_PLAYER_BODY_HIT (1 << 24)
+
+// Actor can update even if Player is currently using the ocarina.
+// Typically an actor will halt while the ocarina is active (depending on category).
+// This flag allows a given actor to be an exception.
+#define ACTOR_FLAG_UPDATE_DURING_OCARINA (1 << 25)
+
+// Actor can press and hold down switches.
+// See usages of `DynaPolyActor_SetSwitchPressed` and `DynaPolyActor_IsSwitchPressed` for more context on how switches work.
+#define ACTOR_FLAG_CAN_PRESS_SWITCHES (1 << 26)
+
+// Player is not able to lock onto the actor.
+// Navi will still be able to hover over the actor, assuming `ACTOR_FLAG_ATTENTION_ENABLED` is set.
+#define ACTOR_FLAG_LOCK_ON_DISABLED (1 << 27)
+
+// Flag controlling the use of `Actor.sfx`. Do not use directly. See Actor_PlaySfx_FlaggedTimer
+#define ACTOR_FLAG_SFX_TIMER (1 << 28)
typedef struct Actor {
/* 0x000 */ s16 id; // Actor ID
diff --git a/soh/include/z64save.h b/soh/include/z64save.h
index 47a2d18c4..f59271212 100644
--- a/soh/include/z64save.h
+++ b/soh/include/z64save.h
@@ -157,6 +157,42 @@ typedef struct {
char hintText[200];
} HintLocationRando;
+#pragma region SoH
+
+typedef struct ShipRandomizerSaveContextData {
+ u16 adultTradeItems;
+ u8 triforcePiecesCollected;
+} ShipRandomizerSaveContextData;
+
+typedef struct ShipBossRushSaveContextData {
+ u32 isPaused;
+ u8 options[BR_OPTIONS_MAX];
+} ShipBossRushSaveContextData;
+
+typedef union ShipQuestSpecificSaveContextData {
+ ShipRandomizerSaveContextData randomizer;
+ ShipBossRushSaveContextData bossRush;
+} ShipQuestSpecificSaveContextData;
+
+typedef struct ShipQuestSaveContextData {
+ u8 id;
+ ShipQuestSpecificSaveContextData data;
+} ShipQuestSaveContextData;
+
+typedef struct ShipSaveContextData {
+ u16 pendingSale;
+ u16 pendingSaleMod;
+ u8 pendingIceTrapCount;
+ SohStats stats;
+ FaroresWindData backupFW;
+ ShipQuestSaveContextData quest;
+ u8 maskMemory;
+ //TODO: Move non-rando specific flags to a new sohInf and move the remaining randomizerInf to ShipRandomizerSaveContextData
+ u16 randomizerInf[(RAND_INF_MAX + 15) / 16];
+} ShipSaveContextData;
+
+#pragma endregion
+
typedef struct {
/* 0x0000 */ s32 entranceIndex; // start of `save` substruct, originally called "memory"
/* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child (see enum `LinkAge`)
@@ -270,25 +306,7 @@ typedef struct {
/* 0x1420 */ s16 worldMapArea;
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
/* 0x1424 */ s16 healthAccumulator;
- // #region SOH [General]
- // Upstream TODO: Move these to their own struct or name to more obviously specific to SoH
- /* */ u16 pendingSale;
- /* */ u16 pendingSaleMod;
- /* */ uint8_t questId;
- /* */ uint32_t isBossRushPaused;
- /* */ uint8_t bossRushOptions[BR_OPTIONS_MAX];
- /* */ u8 pendingIceTrapCount;
- /* */ SohStats sohStats;
- /* */ FaroresWindData backupFW;
- /* */ u8 maskMemory;
- // #endregion
- // #region SOH [Randomizer]
- // Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer
- /* */ u16 randomizerInf[(RAND_INF_MAX + 15) / 16];
- /* */ u8 mqDungeonCount;
- /* */ u16 adultTradeItems;
- /* */ u8 triforcePiecesCollected;
- // #endregion
+ /* */ ShipSaveContextData ship;
} SaveContext; // size = 0x1428
typedef enum {
@@ -298,10 +316,10 @@ typedef enum {
/* 03 */ QUEST_BOSSRUSH,
} Quest;
-#define IS_VANILLA (gSaveContext.questId == QUEST_NORMAL)
-#define IS_MASTER_QUEST (gSaveContext.questId == QUEST_MASTER)
-#define IS_RANDO (gSaveContext.questId == QUEST_RANDOMIZER)
-#define IS_BOSS_RUSH (gSaveContext.questId == QUEST_BOSSRUSH)
+#define IS_VANILLA (gSaveContext.ship.quest.id == QUEST_NORMAL)
+#define IS_MASTER_QUEST (gSaveContext.ship.quest.id == QUEST_MASTER)
+#define IS_RANDO (gSaveContext.ship.quest.id == QUEST_RANDOMIZER)
+#define IS_BOSS_RUSH (gSaveContext.ship.quest.id == QUEST_BOSSRUSH)
typedef enum {
/* 0x00 */ BTN_ENABLED,
@@ -590,7 +608,7 @@ typedef enum {
#define ITEMGETINF_08 0x08
#define ITEMGETINF_09 0x09
#define ITEMGETINF_0A 0x0A
-#define ITEMGETINF_0B 0x0B
+#define ITEMGETINF_DEKU_SCRUB_HEART_PIECE 0x0B
#define ITEMGETINF_0C 0x0C
#define ITEMGETINF_0D 0x0D
#define ITEMGETINF_0E 0x0E
@@ -760,8 +778,8 @@ typedef enum {
#define INFTABLE_17F 0x17F
#define INFTABLE_190 0x190
#define INFTABLE_191 0x191
-#define INFTABLE_192 0x192
-#define INFTABLE_193 0x193
+#define INFTABLE_BOUGHT_STICK_UPGRADE 0x192
+#define INFTABLE_BOUGHT_NUT_UPGRADE 0x193
#define INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA 0x195
#define INFTABLE_196 0x196
#define INFTABLE_197 0x197
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/ActorDB.cpp b/soh/soh/ActorDB.cpp
index 604d48804..880b2dab9 100644
--- a/soh/soh/ActorDB.cpp
+++ b/soh/soh/ActorDB.cpp
@@ -598,7 +598,7 @@ static ActorDBInit EnPartnerInit = {
"En_Partner",
"Ivan",
ACTORCAT_ITEMACTION,
- (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_DRAGGED_BY_HOOKSHOT | ACTOR_FLAG_CAN_PRESS_SWITCH),
+ (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_HOOKSHOT_PULLS_PLAYER | ACTOR_FLAG_CAN_PRESS_SWITCHES),
OBJECT_GAMEPLAY_KEEP,
sizeof(EnPartner),
(ActorFunc)EnPartner_Init,
diff --git a/soh/soh/Enhancements/Cheats/DekuStick.cpp b/soh/soh/Enhancements/Cheats/DekuStick.cpp
new file mode 100644
index 000000000..8afa0e330
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/DekuStick.cpp
@@ -0,0 +1,27 @@
+#include
+#include "soh/Enhancements/enhancementTypes.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+extern PlayState* gPlayState;
+#include "macros.h"
+}
+
+#define CVAR_DEKU_STICK_NAME CVAR_CHEAT("DekuStick")
+#define CVAR_DEKU_STICK_DEFAULT DEKU_STICK_NORMAL
+#define CVAR_DEKU_STICK_VALUE CVarGetInteger(CVAR_DEKU_STICK_NAME, CVAR_DEKU_STICK_DEFAULT)
+
+void RegisterDekuStickCheats() {
+ COND_VB_SHOULD(VB_DEKU_STICK_BREAK, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
+ COND_VB_SHOULD(VB_DEKU_STICK_BURN_OUT, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
+ COND_VB_SHOULD(VB_DEKU_STICK_BURN_DOWN, CVAR_DEKU_STICK_VALUE != DEKU_STICK_NORMAL, { *should = false; });
+ COND_VB_SHOULD(VB_DEKU_STICK_BE_ON_FIRE, CVAR_DEKU_STICK_VALUE == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, {
+ Player* player = GET_PLAYER(gPlayState);
+ player->unk_860 = 200; // Keeps the stick's flame lit
+ player->unk_85C = 1.0f; // Ensures the stick is the proper length
+ *should = true;
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterDekuStickCheats, { CVAR_DEKU_STICK_NAME });
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/Cheats/EasyISG.cpp b/soh/soh/Enhancements/Cheats/EasyISG.cpp
new file mode 100644
index 000000000..f48788a9d
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/EasyISG.cpp
@@ -0,0 +1,27 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+extern PlayState* gPlayState;
+#include "macros.h"
+}
+
+#define CVAR_EASY_ISG_NAME CVAR_CHEAT("EasyISG")
+#define CVAR_EASY_ISG_DEFAULT 0
+#define CVAR_EASY_ISG_VALUE CVarGetInteger(CVAR_EASY_ISG_NAME, CVAR_EASY_ISG_DEFAULT)
+
+void OnGameFrameUpdateEasyISG() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ Player* player = GET_PLAYER(gPlayState);
+ player->meleeWeaponState = 1;
+}
+
+void RegisterEasyISG() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_EASY_ISG_VALUE, OnGameFrameUpdateEasyISG);
+}
+
+static RegisterShipInitFunc initFunc(RegisterEasyISG, { CVAR_EASY_ISG_NAME });
diff --git a/soh/soh/Enhancements/Cheats/EasyQPA.cpp b/soh/soh/Enhancements/Cheats/EasyQPA.cpp
new file mode 100644
index 000000000..096123cdd
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/EasyQPA.cpp
@@ -0,0 +1,28 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+extern PlayState* gPlayState;
+#include "macros.h"
+}
+
+#define CVAR_EASY_QPA_NAME CVAR_CHEAT("EasyQPA")
+#define CVAR_EASY_QPA_DEFAULT 0
+#define CVAR_EASY_QPA_VALUE CVarGetInteger(CVAR_EASY_QPA_NAME, CVAR_EASY_QPA_DEFAULT)
+
+void OnGameFrameUpdateEasyQPA() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ Player* player = GET_PLAYER(gPlayState);
+ player->meleeWeaponQuads[0].info.toucher.dmgFlags = 0x16171617;
+ player->meleeWeaponQuads[1].info.toucher.dmgFlags = 0x16171617;
+}
+
+void RegisterEasyQPA() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_EASY_QPA_VALUE, OnGameFrameUpdateEasyQPA);
+}
+
+static RegisterShipInitFunc initFunc(RegisterEasyQPA, { CVAR_EASY_QPA_NAME });
diff --git a/soh/soh/Enhancements/Cheats/FreezeTime.cpp b/soh/soh/Enhancements/Cheats/FreezeTime.cpp
new file mode 100644
index 000000000..2296c4fc9
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/FreezeTime.cpp
@@ -0,0 +1,39 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "z64save.h"
+
+extern "C" SaveContext gSaveContext;
+
+#define CVAR_FREEZE_TIME_NAME CVAR_CHEAT("FreezeTime")
+#define CVAR_FREEZE_TIME_DEFAULT 0
+#define CVAR_FREEZE_TIME_VALUE CVarGetInteger(CVAR_FREEZE_TIME_NAME, CVAR_FREEZE_TIME_DEFAULT)
+
+#define CVAR_PREV_TIME_NAME CVAR_GENERAL("PrevTime")
+#define CVAR_PREV_TIME_DEFAULT -1
+#define CVAR_PREV_TIME_VALUE CVarGetInteger(CVAR_PREV_TIME_NAME, CVAR_PREV_TIME_DEFAULT)
+
+void OnGameFrameUpdateFreezeTime() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ if (CVAR_PREV_TIME_VALUE == CVAR_PREV_TIME_DEFAULT) {
+ CVarSetInteger(CVAR_PREV_TIME_NAME, gSaveContext.dayTime);
+ }
+
+ gSaveContext.dayTime = CVAR_PREV_TIME_VALUE;
+}
+
+void RegisterFreezeTime() {
+ static HOOK_ID hookId = 0;
+ GameInteractor::Instance->UnregisterGameHook(hookId);
+ hookId = 0;
+ if (CVAR_FREEZE_TIME_VALUE) {
+ hookId = GameInteractor::Instance->RegisterGameHook(OnGameFrameUpdateFreezeTime);
+ } else {
+ CVarClear(CVAR_PREV_TIME_NAME);
+ }
+}
+
+static RegisterShipInitFunc initFunc(RegisterFreezeTime, { CVAR_FREEZE_TIME_NAME });
diff --git a/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp b/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp
new file mode 100644
index 000000000..b54b330bf
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp
@@ -0,0 +1,35 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "z64save.h"
+
+extern "C" {
+extern SaveContext gSaveContext;
+#include "variables.h"
+#include "macros.h"
+}
+
+#define CVAR_INFINITE_AMMO_NAME CVAR_CHEAT("InfiniteAmmo")
+#define CVAR_INFINITE_AMMO_DEFAULT 0
+#define CVAR_INFINITE_AMMO_VALUE CVarGetInteger(CVAR_INFINITE_AMMO_NAME, CVAR_INFINITE_AMMO_DEFAULT)
+
+void OnGameFrameUpdateInfiniteAmmo() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
+ AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS);
+ AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG);
+ AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER);
+ AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG);
+ if (INV_CONTENT(ITEM_BOMBCHU) != ITEM_NONE) {
+ AMMO(ITEM_BOMBCHU) = 50;
+ }
+}
+
+void RegisterInfiniteAmmo() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_INFINITE_AMMO_VALUE, OnGameFrameUpdateInfiniteAmmo);
+}
+
+static RegisterShipInitFunc initFunc(RegisterInfiniteAmmo, { CVAR_INFINITE_AMMO_NAME });
diff --git a/soh/soh/Enhancements/Cheats/Infinite/Health.cpp b/soh/soh/Enhancements/Cheats/Infinite/Health.cpp
new file mode 100644
index 000000000..d731059e5
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/Infinite/Health.cpp
@@ -0,0 +1,24 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "z64save.h"
+
+extern "C" SaveContext gSaveContext;
+
+#define CVAR_INFINITE_HEALTH_NAME CVAR_CHEAT("InfiniteHealth")
+#define CVAR_INFINITE_HEALTH_DEFAULT 0
+#define CVAR_INFINITE_HEALTH_VALUE CVarGetInteger(CVAR_INFINITE_HEALTH_NAME, CVAR_INFINITE_HEALTH_DEFAULT)
+
+void OnGameFrameUpdateInfiniteHealth() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ gSaveContext.health = gSaveContext.healthCapacity;
+}
+
+void RegisterInfiniteHealth() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_INFINITE_HEALTH_VALUE, OnGameFrameUpdateInfiniteHealth);
+}
+
+static RegisterShipInitFunc initFunc(RegisterInfiniteHealth, { CVAR_INFINITE_HEALTH_NAME });
diff --git a/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp b/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp
new file mode 100644
index 000000000..d078316c9
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp
@@ -0,0 +1,24 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "z64save.h"
+
+extern "C" SaveContext gSaveContext;
+
+#define CVAR_INFINITE_MAGIC_NAME CVAR_CHEAT("InfiniteMagic")
+#define CVAR_INFINITE_MAGIC_DEFAULT 0
+#define CVAR_INFINITE_MAGIC_VALUE CVarGetInteger(CVAR_INFINITE_MAGIC_NAME, CVAR_INFINITE_MAGIC_DEFAULT)
+
+void OnGameFrameUpdateInfiniteMagic() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ gSaveContext.magic = gSaveContext.magicLevel * MAGIC_NORMAL_METER;
+}
+
+void RegisterInfiniteMagic() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_INFINITE_MAGIC_VALUE, OnGameFrameUpdateInfiniteMagic);
+}
+
+static RegisterShipInitFunc initFunc(RegisterInfiniteMagic, { CVAR_INFINITE_MAGIC_NAME });
diff --git a/soh/soh/Enhancements/Cheats/Infinite/Money.cpp b/soh/soh/Enhancements/Cheats/Infinite/Money.cpp
new file mode 100644
index 000000000..292f65065
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/Infinite/Money.cpp
@@ -0,0 +1,32 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "z64save.h"
+#include "variables.h"
+
+extern "C" {
+extern SaveContext gSaveContext;
+extern s32 Flags_GetRandomizerInf(RandomizerInf flag);
+#include "macros.h"
+}
+
+#define CVAR_INFINITE_MONEY_NAME CVAR_CHEAT("InfiniteMoney")
+#define CVAR_INFINITE_MONEY_DEFAULT 0
+#define CVAR_INFINITE_MONEY_VALUE CVarGetInteger(CVAR_INFINITE_MONEY_NAME, CVAR_INFINITE_MONEY_DEFAULT)
+
+void OnGameFrameUpdateInfiniteMoney() {
+ if (
+ !GameInteractor::IsSaveLoaded(true) ||
+ (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))
+ ) {
+ return;
+ }
+
+ gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
+}
+
+void RegisterInfiniteMoney() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_INFINITE_MONEY_VALUE, OnGameFrameUpdateInfiniteMoney);
+}
+
+static RegisterShipInitFunc initFunc(RegisterInfiniteMoney, { CVAR_INFINITE_MONEY_NAME });
diff --git a/soh/soh/Enhancements/Cheats/Infinite/NayrusLove.cpp b/soh/soh/Enhancements/Cheats/Infinite/NayrusLove.cpp
new file mode 100644
index 000000000..0bea9afc9
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/Infinite/NayrusLove.cpp
@@ -0,0 +1,24 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+#include "z64save.h"
+
+extern "C" SaveContext gSaveContext;
+
+#define CVAR_INFINITE_NAYRUS_LOVE_NAME CVAR_CHEAT("InfiniteNayru")
+#define CVAR_INFINITE_NAYRUS_LOVE_DEFAULT 0
+#define CVAR_INFINITE_NAYRUS_LOVE_VALUE CVarGetInteger(CVAR_INFINITE_NAYRUS_LOVE_NAME, CVAR_INFINITE_NAYRUS_LOVE_DEFAULT)
+
+void OnGameFrameUpdateInfiniteNayrusLove() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ gSaveContext.nayrusLoveTimer = 0x44B;
+}
+
+void RegisterInfiniteNayrusLove() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_INFINITE_NAYRUS_LOVE_VALUE, OnGameFrameUpdateInfiniteNayrusLove);
+}
+
+static RegisterShipInitFunc initFunc(RegisterInfiniteNayrusLove, { CVAR_INFINITE_NAYRUS_LOVE_NAME });
diff --git a/soh/soh/Enhancements/Cheats/MoonJump.cpp b/soh/soh/Enhancements/Cheats/MoonJump.cpp
index e741fbb82..fb13c1c7b 100644
--- a/soh/soh/Enhancements/Cheats/MoonJump.cpp
+++ b/soh/soh/Enhancements/Cheats/MoonJump.cpp
@@ -3,11 +3,11 @@
#include "soh/ShipInit.hpp"
extern "C" {
-#include "macros.h"
extern PlayState* gPlayState;
+#include "macros.h"
}
-#define CVAR_MOON_JUMP_NAME "gCheats.MoonJumpOnL"
+#define CVAR_MOON_JUMP_NAME CVAR_CHEAT("MoonJumpOnL")
#define CVAR_MOON_JUMP_DEFAULT 0
#define CVAR_MOON_JUMP_VALUE CVarGetInteger(CVAR_MOON_JUMP_NAME, CVAR_MOON_JUMP_DEFAULT)
diff --git a/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp b/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp
new file mode 100644
index 000000000..0b5aaebbc
--- /dev/null
+++ b/soh/soh/Enhancements/Cheats/UnrestrictedItems.cpp
@@ -0,0 +1,26 @@
+#include
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" PlayState* gPlayState;
+
+#define CVAR_UNRESTRICTED_ITEMS_NAME CVAR_CHEAT("NoRestrictItems")
+#define CVAR_UNRESTRICTED_ITEMS_DEFAULT 0
+#define CVAR_UNRESTRICTED_ITEMS_VALUE CVarGetInteger(CVAR_UNRESTRICTED_ITEMS_NAME, CVAR_UNRESTRICTED_ITEMS_DEFAULT)
+
+void OnGameFrameUpdateUnrestrictedItems() {
+ if (!GameInteractor::IsSaveLoaded(true)) {
+ return;
+ }
+
+ // do not allow the use of sun's song even with the cheat
+ u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
+ memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions));
+ gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup;
+}
+
+void RegisterUnrestrictedItems() {
+ COND_HOOK(OnGameFrameUpdate, CVAR_UNRESTRICTED_ITEMS_VALUE, OnGameFrameUpdateUnrestrictedItems);
+}
+
+static RegisterShipInitFunc initFunc(RegisterUnrestrictedItems, { CVAR_UNRESTRICTED_ITEMS_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..05e03dae1 100644
--- a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp
+++ b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp
@@ -4,7 +4,7 @@
#include "assets/textures/parameter_static/parameter_static.h"
#include "assets/soh_assets.h"
-#include "soh/ImGuiUtils.h"
+#include "soh/SohGui/ImGuiUtils.h"
extern "C" {
#include "macros.h"
@@ -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/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp
index aaaf1b39f..7d676e6f8 100644
--- a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp
+++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp
@@ -85,7 +85,7 @@ void SkipChildRutoInteractions_Register() {
if (enRu1->action == 22) {
enRu1->action = 27;
enRu1->drawConfig = 1;
- enRu1->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY;
+ enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY;
Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f,
Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f);
}
diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp
index d56c8269c..d15bc5f25 100644
--- a/soh/soh/Enhancements/audio/AudioEditor.cpp
+++ b/soh/soh/Enhancements/audio/AudioEditor.cpp
@@ -11,7 +11,7 @@
#include "soh/OTRGlobals.h"
#include "soh/cvar_prefixes.h"
#include
-#include "soh/UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "AudioCollection.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
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/boss-rush/BossRush.cpp b/soh/soh/Enhancements/boss-rush/BossRush.cpp
index d4997cca9..96220f057 100644
--- a/soh/soh/Enhancements/boss-rush/BossRush.cpp
+++ b/soh/soh/Enhancements/boss-rush/BossRush.cpp
@@ -265,10 +265,10 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
gSaveContext.linkAge = LINK_AGE_ADULT;
// Change to Adult Link.
- if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ALL) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ALL) {
BossRush_SetEquipment(LINK_AGE_ADULT);
// Warp to credits.
- } else if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) {
+ } else if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) {
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.nextCutsceneIndex = 0xFFF2;
play->transitionTrigger = TRANS_TRIGGER_START;
@@ -285,14 +285,14 @@ void BossRush_HandleBlueWarp(PlayState* play, f32 warpPosX, f32 warpPosZ) {
void BossRush_HandleBlueWarpHeal(PlayState* play) {
// This function gets called multiple times per blue warp, so only heal when player isn't at max HP.
- if (gSaveContext.bossRushOptions[BR_OPTIONS_HEAL] == BR_CHOICE_HEAL_EVERYBOSS &&
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HEAL] == BR_CHOICE_HEAL_EVERYBOSS &&
gSaveContext.health != gSaveContext.healthCapacity) {
Health_ChangeBy(play, 320);
}
}
void BossRush_HandleCompleteBoss(PlayState* play) {
- gSaveContext.isBossRushPaused = 1;
+ gSaveContext.ship.quest.data.bossRush.isPaused = true;
switch (play->sceneNum) {
case SCENE_DEKU_TREE_BOSS:
Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
@@ -323,16 +323,16 @@ void BossRush_HandleCompleteBoss(PlayState* play) {
}
// Fully heal the player after Ganondorf
- if (gSaveContext.bossRushOptions[BR_OPTIONS_HEAL] == BR_CHOICE_HEAL_EVERYBOSS &&
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HEAL] == BR_CHOICE_HEAL_EVERYBOSS &&
play->sceneNum == SCENE_GANONDORF_BOSS) {
Health_ChangeBy(play, 320);
}
- if ((CheckDungeonCount() == 3 && gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) ||
+ if ((CheckDungeonCount() == 3 && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_CHILD) ||
play->sceneNum == SCENE_GANON_BOSS) {
- gSaveContext.sohStats.playTimer += 2;
- gSaveContext.sohStats.gameComplete = 1;
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_BOSSRUSH_FINISH] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.playTimer += 2;
+ gSaveContext.ship.stats.gameComplete = 1;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_BOSSRUSH_FINISH] = GAMEPLAYSTAT_TOTAL_TIME;
}
}
@@ -344,14 +344,14 @@ void BossRush_InitSave() {
gSaveContext.playerName[i] = brPlayerName[i];
}
- gSaveContext.questId = QUEST_BOSSRUSH;
- gSaveContext.isBossRushPaused = 1;
+ gSaveContext.ship.quest.id = QUEST_BOSSRUSH;
+ gSaveContext.ship.quest.data.bossRush.isPaused = true;
gSaveContext.entranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
gSaveContext.cutsceneIndex = 0x8000;
gSaveContext.isMagicAcquired = 1;
// Set magic
- if (gSaveContext.bossRushOptions[BR_OPTIONS_MAGIC] == BR_CHOICE_MAGIC_SINGLE) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_MAGIC] == BR_CHOICE_MAGIC_SINGLE) {
gSaveContext.magicLevel = 1;
gSaveContext.magic = 48;
} else {
@@ -362,7 +362,7 @@ void BossRush_InitSave() {
// Set health
u16 health = 16;
- switch (gSaveContext.bossRushOptions[BR_OPTIONS_HEARTS]) {
+ switch (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HEARTS]) {
case BR_CHOICE_HEARTS_7:
health *= 7;
break;
@@ -399,8 +399,9 @@ void BossRush_InitSave() {
gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
// Sets all rando flags to false
- for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
- gSaveContext.randomizerInf[i] = 0;
+ // Boss Rush currently uses 2 randomizer flags (RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE & RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)
+ for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.ship.randomizerInf); i++) {
+ gSaveContext.ship.randomizerInf[i] = 0;
}
// Set items
@@ -411,11 +412,11 @@ void BossRush_InitSave() {
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
};
- if (gSaveContext.bossRushOptions[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_LONGSHOT] == BR_CHOICE_LONGSHOT_YES) {
brItems[9] = ITEM_LONGSHOT;
}
- switch (gSaveContext.bossRushOptions[BR_OPTIONS_BOTTLE]) {
+ switch (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOTTLE]) {
case BR_CHOICE_BOTTLE_EMPTY:
brItems[18] = ITEM_BOTTLE;
break;
@@ -435,7 +436,7 @@ void BossRush_InitSave() {
break;
}
- if (gSaveContext.bossRushOptions[BR_OPTIONS_BUNNYHOOD] == BR_CHOICE_BUNNYHOOD_YES) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BUNNYHOOD] == BR_CHOICE_BUNNYHOOD_YES) {
brItems[23] = ITEM_MASK_BUNNY;
}
@@ -446,9 +447,9 @@ void BossRush_InitSave() {
// Set consumable counts
std::array brAmmo = { 5, 5, 10, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- if (gSaveContext.bossRushOptions[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_FULL) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_FULL) {
brAmmo = { 10, 20, 20, 30, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- } else if (gSaveContext.bossRushOptions[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_MAXED) {
+ } else if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_MAXED) {
brAmmo = { 30, 40, 40, 50, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
}
@@ -462,17 +463,17 @@ void BossRush_InitSave() {
gSaveContext.inventory.equipment |= 1 << 4; // Deku Shield
gSaveContext.inventory.equipment |= 1 << 6; // Mirror Shield
gSaveContext.inventory.equipment |= 1 << 9; // Goron Tunic
- if (gSaveContext.bossRushOptions[BR_OPTIONS_BGS] == BR_CHOICE_BGS_YES) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BGS] == BR_CHOICE_BGS_YES) {
gSaveContext.inventory.equipment |= 1 << 2; // Biggoron Sword
gSaveContext.bgsFlag = 1;
}
- if (gSaveContext.bossRushOptions[BR_OPTIONS_HOVERBOOTS] == BR_CHOICE_HOVERBOOTS_YES) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HOVERBOOTS] == BR_CHOICE_HOVERBOOTS_YES) {
gSaveContext.inventory.equipment |= 1 << 14; // Hover Boots
}
// Upgrades
u8 upgradeLevel = 1;
- if (gSaveContext.bossRushOptions[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_MAXED) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_AMMO] == BR_CHOICE_AMMO_MAXED) {
upgradeLevel = 3;
}
Inventory_ChangeUpgrade(UPG_QUIVER, upgradeLevel);
@@ -483,12 +484,12 @@ void BossRush_InitSave() {
Inventory_ChangeUpgrade(UPG_STRENGTH, 1);
// Set flags and Link's age based on chosen settings.
- if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ADULT ||
- gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_ADULT ||
+ gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) {
Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP);
- if (gSaveContext.bossRushOptions[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_BOSSES] == BR_CHOICE_BOSSES_GANONDORF_GANON) {
Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP);
@@ -516,7 +517,7 @@ void BossRush_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
switch (id) {
// Allow not healing before ganon
case VB_GANON_HEAL_BEFORE_FIGHT: {
- if (gSaveContext.bossRushOptions[BR_OPTIONS_HEAL] == BR_CHOICE_HEAL_NEVER) {
+ if (gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HEAL] == BR_CHOICE_HEAL_NEVER) {
*should = false;
}
break;
@@ -669,7 +670,7 @@ void BossRush_OnActorInitHandler(void* actorRef) {
void BossRush_OnSceneInitHandler(s16 sceneNum) {
// Unpause the timer when the scene loaded isn't the Chamber of Sages.
if (sceneNum != SCENE_CHAMBER_OF_THE_SAGES) {
- gSaveContext.isBossRushPaused = 0;
+ gSaveContext.ship.quest.data.bossRush.isPaused = false;
}
}
diff --git a/soh/soh/Enhancements/cheat_hook_handlers.cpp b/soh/soh/Enhancements/cheat_hook_handlers.cpp
deleted file mode 100644
index 20c85d4d4..000000000
--- a/soh/soh/Enhancements/cheat_hook_handlers.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include
-#include "soh/OTRGlobals.h"
-#include "soh/Enhancements/game-interactor/GameInteractor.h"
-#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
-#include "soh/Enhancements/enhancementTypes.h"
-
-extern "C" {
-#include "macros.h"
-#include "variables.h"
-
-extern SaveContext gSaveContext;
-extern PlayState* gPlayState;
-}
-
-void CheatsOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) {
- switch (id) {
- case VB_DEKU_STICK_BREAK: {
- if (CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) {
- *should = false;
- }
- break;
- }
- case VB_DEKU_STICK_BE_ON_FIRE: {
- if (CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) == DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE) {
- Player* player = GET_PLAYER(gPlayState);
- player->unk_860 = 200; // Keeps the stick's flame lit
- player->unk_85C = 1.0f; // Ensures the stick is the proper length
- *should = true;
- }
- break;
- }
- case VB_DEKU_STICK_BURN_OUT: {
- if (CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) {
- *should = false;
- }
- break;
- }
- case VB_DEKU_STICK_BURN_DOWN: {
- if (CVarGetInteger(CVAR_CHEAT("DekuStick"), DEKU_STICK_NORMAL) != DEKU_STICK_NORMAL) {
- *should = false;
- }
- break;
- }
- default:
- break;
- }
-}
-
-static uint32_t onVanillaBehaviorHook = 0;
-void CheatsRegisterHooks() {
- GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) mutable {
-
- GameInteractor::Instance->UnregisterGameHook(onVanillaBehaviorHook);
- onVanillaBehaviorHook = 0;
- onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook(CheatsOnVanillaBehaviorHandler);
-
- });
-}
diff --git a/soh/soh/Enhancements/cheat_hook_handlers.h b/soh/soh/Enhancements/cheat_hook_handlers.h
deleted file mode 100644
index 88a79f285..000000000
--- a/soh/soh/Enhancements/cheat_hook_handlers.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef CHEAT_HOOK_HANDLERS_H
-#define CHEAT_HOOK_HANDLERS_H
-
-void CheatsRegisterHooks();
-
-#endif // CHEAT_HOOK_HANDLERS_H
diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp
index 7d6b37179..5f650a25f 100644
--- a/soh/soh/Enhancements/controls/InputViewer.cpp
+++ b/soh/soh/Enhancements/controls/InputViewer.cpp
@@ -9,7 +9,7 @@
#include
#include
-#include "../../UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
// Text colors
static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp
index 492517738..7e4918799 100644
--- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp
+++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp
@@ -1,7 +1,7 @@
#include "SohInputEditorWindow.h"
#include
#include "soh/OTRGlobals.h"
-#include "../../UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "z64.h"
#include "soh/cvar_prefixes.h"
#ifndef __WIIU__
@@ -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 6274de469..0bdd3d10d 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
@@ -10,7 +10,7 @@
#include
#include
-#include "soh/UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "soh/OTRGlobals.h"
#include "soh/ResourceManagerHelpers.h"
@@ -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,6 +72,9 @@ std::map groupLabels = {
{ COSMETICS_GROUP_SWORDS, "Swords" },
{ COSMETICS_GROUP_GLOVES, "Gloves" },
{ COSMETICS_GROUP_EQUIPMENT, "Equipment" },
+ { 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" },
@@ -118,7 +119,7 @@ Color_RGBA8 ColorRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
/*
So, you would like to add a new cosmetic option? BUCKLE UP
- To preface this, if you have any questions or concerns ping @ProxySaw on discord, if I'm no longer available ask around in the #development-chat
+ To preface this, if you have any questions or concerns ping @ProxySaw on discord, if I'm no longer available ask around in the #soh-development
# Silly Options
Lets get this one out of the way, probably the only thing that will be consistent between silly options is how they are rendered
@@ -252,6 +253,42 @@ 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_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),
COSMETIC_OPTION("HUD.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ColorRGBA8(255, 160, 0, 255), false, true, false),
@@ -294,12 +331,12 @@ static std::map cosmeticOptions = {
#undef MESSAGE_COSMETIC_OPTION
- COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, false),
+ COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, true),
COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 70, 100, 130, 255), false, true, true),
COSMETIC_OPTION("Kaleido.ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 70, 100, 130, 255), false, true, true),
COSMETIC_OPTION("Kaleido.ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, true),
- COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 40, 255), false, true, false),
+ COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 40, 255), false, true, true),
COSMETIC_OPTION("Kaleido.EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 60, 255), false, true, true),
COSMETIC_OPTION("Kaleido.EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 60, 255), false, true, true),
COSMETIC_OPTION("Kaleido.EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, true),
@@ -309,22 +346,22 @@ static std::map cosmeticOptions = {
COSMETIC_OPTION("Kaleido.MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kaleido.MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, true),
- COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 80, 50, 255), false, true, false),
+ COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 80, 50, 255), false, true, true),
COSMETIC_OPTION("Kaleido.QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(120, 120, 70, 255), false, true, true),
COSMETIC_OPTION("Kaleido.QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(120, 120, 70, 255), false, true, true),
COSMETIC_OPTION("Kaleido.QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 80, 50, 255), false, true, true),
- COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, false),
+ COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, true),
COSMETIC_OPTION("Kaleido.MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kaleido.MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true),
COSMETIC_OPTION("Kaleido.MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, true),
- COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 50, 50, 50, 255), false, true, false),
+ COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 50, 50, 50, 255), false, true, true),
COSMETIC_OPTION("Kaleido.SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(110, 110, 110, 255), false, true, true),
COSMETIC_OPTION("Kaleido.SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(110, 110, 110, 255), false, true, true),
COSMETIC_OPTION("Kaleido.SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 50, 50, 50, 255), false, true, true),
- COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 130, 255), true, true, false),
+ COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 130, 255), true, true, true),
COSMETIC_OPTION("Title.FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ColorRGBA8(100, 150, 255, 255), false, true, false),
COSMETIC_OPTION("Title.NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ColorRGBA8( 0, 0, 255, 255), false, true, true),
@@ -1445,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);
}
@@ -1464,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();
}
@@ -1546,66 +1622,6 @@ void ApplySideEffects(CosmeticOption& cosmeticOption) {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack.Level1Primary"), 2.0f);
} else if (cosmeticOption.label == "Level 2 Secondary") {
CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("SpinAttack.Level2Primary"), 2.0f);
- } else if (cosmeticOption.label == "Item Select Color") {
- if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
- ToggleRainbow(cosmeticOptions.at("Kaleido.ItemSelB"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.ItemSelC"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.ItemSelD"), true);
- } else {
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.ItemSelB"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.ItemSelC"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.ItemSelD"), 1.0f);
- }
- } else if (cosmeticOption.label == "Equip Select Color") {
- if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
- ToggleRainbow(cosmeticOptions.at("Kaleido.EquipSelB"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.EquipSelC"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.EquipSelD"), true);
- } else {
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.EquipSelB"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.EquipSelC"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.EquipSelD"), 1.0f);
- }
- } else if (cosmeticOption.label == "Map Dungeon Color") {
- if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
- ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelDunB"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelDunC"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelDunD"), true);
- } else {
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelDunB"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelDunC"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelDunD"), 1.0f);
- }
- } else if (cosmeticOption.label == "Quest Status Color") {
- if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
- ToggleRainbow(cosmeticOptions.at("Kaleido.QuestStatusB"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.QuestStatusC"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.QuestStatusD"), true);
- } else {
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.QuestStatusB"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.QuestStatusC"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.QuestStatusD"), 1.0f);
- }
- } else if (cosmeticOption.label == "Map Color") {
- if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
- ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelectB"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelectC"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.MapSelectD"), true);
- } else {
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelectB"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelectC"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.MapSelectD"), 1.0f);
- }
- } else if (cosmeticOption.label == "Save Color") {
- if (CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
- ToggleRainbow(cosmeticOptions.at("Kaleido.SaveB"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.SaveC"), true);
- ToggleRainbow(cosmeticOptions.at("Kaleido.SaveD"), true);
- } else {
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.SaveB"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.SaveC"), 2.0f);
- CopyMultipliedColor(cosmeticOption, cosmeticOptions.at("Kaleido.SaveD"), 1.0f);
- }
}
}
@@ -1778,6 +1794,7 @@ void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) {
DrawCosmeticRow(cosmeticOption);
}
}
+ UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
}
static const char* colorSchemes[2] = {
@@ -1785,6 +1802,97 @@ static const char* colorSchemes[2] = {
"Gamecube",
};
+void CosmeticsEditorWindow::ApplyDungeonKeyColors() {
+ // Keyring
+ ResetColor(cosmeticOptions.at("Key.KeyringRing"));
+
+ // 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 };
+
+ // 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"));
+
+ // 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() {
ImGui::Text("Color Scheme");
ImGui::SameLine();
@@ -1794,6 +1902,7 @@ void CosmeticsEditorWindow::DrawElement() {
"Some cosmetic options may not apply if you have any mods that provide custom models for the cosmetic option.\n\n"
"For example, if you have custom Link model, then the Link's Hair color option will most likely not apply."
);
+
if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) {
if (ImGui::Button("Lock All Advanced", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) {
for (auto& [id, cosmeticOption] : cosmeticOptions) {
@@ -1882,6 +1991,9 @@ 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);
@@ -1890,7 +2002,29 @@ void CosmeticsEditorWindow::DrawElement() {
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);
@@ -1904,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);
@@ -1918,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();
@@ -1928,9 +2071,11 @@ void CosmeticsEditorWindow::DrawElement() {
ImGui::EndTabItem();
}
- if (ImGui::BeginTabItem("Pause Menu")) {
- DrawCosmeticGroup(COSMETICS_GROUP_KALEIDO);
- ImGui::EndTabItem();
+ if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) {
+ if (ImGui::BeginTabItem("Pause Menu")) {
+ DrawCosmeticGroup(COSMETICS_GROUP_KALEIDO);
+ ImGui::EndTabItem();
+ }
}
if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) {
diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
index 55dba5780..c9a28ef29 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
@@ -9,6 +9,9 @@ typedef enum {
COSMETICS_GROUP_SWORDS,
COSMETICS_GROUP_GLOVES,
COSMETICS_GROUP_EQUIPMENT,
+ COSMETICS_GROUP_KEYRING,
+ COSMETICS_GROUP_SMALL_KEYS,
+ COSMETICS_GROUP_BOSS_KEYS,
COSMETICS_GROUP_CONSUMABLE,
COSMETICS_GROUP_HUD,
COSMETICS_GROUP_KALEIDO,
@@ -62,6 +65,7 @@ class CosmeticsEditorWindow : public Ship::GuiWindow {
void InitElement() override;
void DrawElement() override;
+ 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 76f903eb1..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) {
@@ -470,7 +471,7 @@ static bool FWHandler(std::shared_ptr Console, const std::vector<
break;
case 2: //backup
if (CVarGetInteger(CVAR_ENHANCEMENT("BetterFarore"), 0)) {
- gSaveContext.fw = gSaveContext.backupFW;
+ gSaveContext.fw = gSaveContext.ship.backupFW;
gSaveContext.fw.set = 1;
INFO_MESSAGE("[SOH] Backup FW data copied! Reload scene to take effect.");
return 0;
@@ -1297,6 +1298,9 @@ static constexpr std::array, COSMETICS_GRO
{"swords", COSMETICS_GROUP_SWORDS},
{"gloves", COSMETICS_GROUP_GLOVES},
{"equipment", COSMETICS_GROUP_EQUIPMENT},
+ {"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 7ae34b4a8..589dbaf4a 100644
--- a/soh/soh/Enhancements/debugger/MessageViewer.cpp
+++ b/soh/soh/Enhancements/debugger/MessageViewer.cpp
@@ -1,6 +1,6 @@
#include "MessageViewer.h"
-#include
+#include
#include
#include "../custom-message/CustomMessageManager.h"
@@ -174,15 +174,13 @@ void MessageDebug_StartTextBox(const char* tableId, uint16_t textId, uint8_t lan
PlayState* play = gPlayState;
static int16_t messageStaticIndices[] = { 0, 1, 3, 2 };
const auto player = GET_PLAYER(gPlayState);
- player->actor.flags |= ACTOR_FLAG_PLAYER_TALKED_TO;
+ player->actor.flags |= ACTOR_FLAG_TALK;
MessageContext* msgCtx = &play->msgCtx;
msgCtx->ocarinaAction = 0xFFFF;
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/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp
index c6ac49a74..8aac60954 100644
--- a/soh/soh/Enhancements/debugger/actorViewer.cpp
+++ b/soh/soh/Enhancements/debugger/actorViewer.cpp
@@ -1,6 +1,6 @@
#include "actorViewer.h"
#include "../../util.h"
-#include "../../UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "soh/ActorDB.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/nametag.h"
diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp
index 2cba03f5b..493ffdfdc 100644
--- a/soh/soh/Enhancements/debugger/colViewer.cpp
+++ b/soh/soh/Enhancements/debugger/colViewer.cpp
@@ -1,6 +1,6 @@
#include "colViewer.h"
#include "../../frame_interpolation.h"
-#include "../../UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include
#include
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
index 83fe7f676..962f50bd6 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
@@ -1,8 +1,8 @@
#include "debugSaveEditor.h"
-#include "../../util.h"
-#include "../../ImGuiUtils.h"
-#include "../../OTRGlobals.h"
-#include "../../UIWidgets.hpp"
+#include "soh/util.h"
+#include "soh/SohGui/ImGuiUtils.h"
+#include "soh/OTRGlobals.h"
+#include "soh/SohGui/UIWidgets.hpp"
#include
#include
@@ -314,7 +314,7 @@ void DrawInfoTab() {
UIWidgets::InsertHelpHoverText("Z-Targeting behavior");
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT)) {
- ImGui::InputScalar("Triforce Pieces", ImGuiDataType_U8, &gSaveContext.triforcePiecesCollected);
+ ImGui::InputScalar("Triforce Pieces", ImGuiDataType_U8, &gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected);
UIWidgets::InsertHelpHoverText("Currently obtained Triforce Pieces. For Triforce Hunt.");
}
@@ -416,17 +416,17 @@ void DrawBGSItemFlag(uint8_t itemID) {
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1));
ImGui::SameLine();
int tradeIndex = itemID - ITEM_POCKET_EGG;
- bool hasItem = (gSaveContext.adultTradeItems & (1 << tradeIndex)) != 0;
+ bool hasItem = (gSaveContext.ship.quest.data.randomizer.adultTradeItems & (1 << tradeIndex)) != 0;
bool shouldHaveItem = hasItem;
ImGui::Checkbox(("##adultTradeFlag" + std::to_string(itemID)).c_str(), &shouldHaveItem);
if (hasItem != shouldHaveItem) {
if (shouldHaveItem) {
- gSaveContext.adultTradeItems |= (1 << tradeIndex);
+ gSaveContext.ship.quest.data.randomizer.adultTradeItems |= (1 << tradeIndex);
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_NONE) {
INV_CONTENT(ITEM_TRADE_ADULT) = ITEM_POCKET_EGG + tradeIndex;
}
} else {
- gSaveContext.adultTradeItems &= ~(1 << tradeIndex);
+ gSaveContext.ship.quest.data.randomizer.adultTradeItems &= ~(1 << tradeIndex);
Inventory_ReplaceItem(gPlayState, itemID, Randomizer_GetNextAdultTradeItem());
}
}
@@ -477,7 +477,7 @@ void DrawInventoryTab() {
if (ImGui::Button("##itemNonePicker", ImVec2(32.0f, 32.0f))) {
gSaveContext.inventory.items[selectedIndex] = ITEM_NONE;
if (selectedIndex == SLOT_TRADE_ADULT) {
- gSaveContext.adultTradeItems = 0;
+ gSaveContext.ship.quest.data.randomizer.adultTradeItems = 0;
}
ImGui::CloseCurrentPopup();
}
@@ -517,7 +517,7 @@ void DrawInventoryTab() {
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
selectedIndex == SLOT_TRADE_ADULT &&
slotEntry.id >= ITEM_POCKET_EGG && slotEntry.id <= ITEM_CLAIM_CHECK) {
- gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(slotEntry.id);
+ gSaveContext.ship.quest.data.randomizer.adultTradeItems |= ADULT_TRADE_FLAG(slotEntry.id);
}
ImGui::CloseCurrentPopup();
}
@@ -923,7 +923,7 @@ void DrawFlagsTab() {
DrawFlagTableArray16(flagTable, j, gSaveContext.eventInf[j]);
break;
case RANDOMIZER_INF:
- DrawFlagTableArray16(flagTable, j, gSaveContext.randomizerInf[j]);
+ DrawFlagTableArray16(flagTable, j, gSaveContext.ship.randomizerInf[j]);
break;
}
});
@@ -1305,7 +1305,7 @@ void DrawQuestStatusTab() {
ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[ITEM_KEY_SMALL].name), ImVec2(lineHeight, lineHeight));
ImGui::SameLine();
if (ImGui::InputScalar("##Keys", ImGuiDataType_S8, gSaveContext.inventory.dungeonKeys + dungeonItemsScene)) {
- gSaveContext.sohStats.dungeonKeys[dungeonItemsScene] = gSaveContext.inventory.dungeonKeys[dungeonItemsScene];
+ gSaveContext.ship.stats.dungeonKeys[dungeonItemsScene] = gSaveContext.inventory.dungeonKeys[dungeonItemsScene];
};
} else {
// dungeonItems is size 20 but dungeonKeys is size 19, so there are no keys for the last scene (Barinade's Lair)
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/dlViewer.cpp b/soh/soh/Enhancements/debugger/dlViewer.cpp
index fdfc8be1c..4f4d13bff 100644
--- a/soh/soh/Enhancements/debugger/dlViewer.cpp
+++ b/soh/soh/Enhancements/debugger/dlViewer.cpp
@@ -1,9 +1,9 @@
#include "actorViewer.h"
-#include "../../util.h"
-#include "../../UIWidgets.hpp"
+#include "soh/util.h"
+#include "soh/SohGui/UIWidgets.hpp"
#include "ResourceManager.h"
#include "DisplayList.h"
-#include "../../OTRGlobals.h"
+#include "soh/OTRGlobals.h"
#include
#include
diff --git a/soh/soh/Enhancements/debugger/hookDebugger.cpp b/soh/soh/Enhancements/debugger/hookDebugger.cpp
index 8ee9b3391..782cf4f7a 100644
--- a/soh/soh/Enhancements/debugger/hookDebugger.cpp
+++ b/soh/soh/Enhancements/debugger/hookDebugger.cpp
@@ -1,6 +1,6 @@
#include "hookDebugger.h"
-#include "../game-interactor/GameInteractor.h"
-#include "../../UIWidgets.hpp"
+#include "soh/Enhancements/game-interactor/GameInteractor.h"
+#include "soh/SohGui/UIWidgets.hpp"
#include
#include
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/debugger/valueViewer.cpp b/soh/soh/Enhancements/debugger/valueViewer.cpp
index a58512ea3..088e69713 100644
--- a/soh/soh/Enhancements/debugger/valueViewer.cpp
+++ b/soh/soh/Enhancements/debugger/valueViewer.cpp
@@ -1,5 +1,5 @@
#include "valueViewer.h"
-#include "../../UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "soh/OTRGlobals.h"
extern "C" {
diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp
index 89aab7e00..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.sohStats.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 a6aa85a61..936a4be99 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h
@@ -156,9 +156,9 @@ typedef enum {
// Opt: *EnShopnuts
/* Vanilla Condition:
```
- ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) ||
- ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) ||
- ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))
+ ((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) ||
+ ((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_BOUGHT_STICK_UPGRADE))) ||
+ ((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_BOUGHT_NUT_UPGRADE)))
```
*/
VB_BUSINESS_SCRUB_DESPAWN,
@@ -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
@@ -302,6 +303,15 @@ typedef enum {
// Opt: *EnFr
// Vanilla condition: this->reward == GI_NONE
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 ***/
@@ -379,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,
@@ -633,7 +644,7 @@ struct HookInfo {
#define COND_VB_SHOULD(id, condition, body) \
{ \
static HOOK_ID hookId = 0; \
- GameInteractor::Instance->UnregisterGameHookForID(hookId); \
+ GameInteractor::Instance->UnregisterGameHookForID(hookId); \
hookId = 0; \
if (condition) { \
hookId = REGISTER_VB_SHOULD(id, body); \
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/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp
index bb04e72b8..aa8c72d00 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp
@@ -238,7 +238,12 @@ void GameInteractor::RawAction::SetFlag(int16_t flagType, int16_t flag) {
gSaveContext.eventInf[flag >> 4] |= (1 << (flag & 0xF));
break;
case FlagType::FLAG_RANDOMIZER_INF:
- gSaveContext.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
+ if (!IS_RANDO) {
+ LUSLOG_ERROR("Tried to set randomizerInf flag outside of rando (%d)", flag);
+ assert(false);
+ break;
+ }
+ gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
break;
case FlagType::FLAG_GS_TOKEN:
SET_GS_FLAGS((flag & 0x1F00) >> 8, flag & 0xFF);
@@ -261,7 +266,12 @@ void GameInteractor::RawAction::UnsetFlag(int16_t flagType, int16_t flag) {
gSaveContext.eventInf[flag >> 4] &= ~(1 << (flag & 0xF));
break;
case FlagType::FLAG_RANDOMIZER_INF:
- gSaveContext.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
+ if (!IS_RANDO) {
+ LUSLOG_ERROR("Tried to unset randomizerInf flag outside of rando (%d)", flag);
+ assert(false);
+ break;
+ }
+ gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
break;
}
};
diff --git a/soh/soh/Enhancements/gameplaystats.cpp b/soh/soh/Enhancements/gameplaystats.cpp
index 3f7691741..aff0d0726 100644
--- a/soh/soh/Enhancements/gameplaystats.cpp
+++ b/soh/soh/Enhancements/gameplaystats.cpp
@@ -5,7 +5,7 @@
#include "functions.h"
#include "macros.h"
#include "soh/cvar_prefixes.h"
-#include "../UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "soh/util.h"
#include
@@ -252,7 +252,7 @@ typedef struct {
// Timestamps are an array of structs, each with a name, time, and color
// Names and colors are set up at the bottom of this file
-// Times are stored in gSaveContext.sohStats.itemTimestamp
+// Times are stored in gSaveContext.ship.stats.itemTimestamp
TimestampInfo itemTimestampDisplay[TIMESTAMP_MAX];
TimestampInfo sceneTimestampDisplay[8191];
//std::vector sceneTimestampDisplay;
@@ -287,25 +287,25 @@ extern "C" char* GameplayStats_GetCurrentTime() {
}
void LoadStatsVersion1() {
- SaveManager::Instance->LoadCharArray("buildVersion", gSaveContext.sohStats.buildVersion,
- ARRAY_COUNT(gSaveContext.sohStats.buildVersion));
- SaveManager::Instance->LoadData("buildVersionMajor", gSaveContext.sohStats.buildVersionMajor);
- SaveManager::Instance->LoadData("buildVersionMinor", gSaveContext.sohStats.buildVersionMinor);
- SaveManager::Instance->LoadData("buildVersionPatch", gSaveContext.sohStats.buildVersionPatch);
+ SaveManager::Instance->LoadCharArray("buildVersion", gSaveContext.ship.stats.buildVersion,
+ ARRAY_COUNT(gSaveContext.ship.stats.buildVersion));
+ SaveManager::Instance->LoadData("buildVersionMajor", gSaveContext.ship.stats.buildVersionMajor);
+ SaveManager::Instance->LoadData("buildVersionMinor", gSaveContext.ship.stats.buildVersionMinor);
+ SaveManager::Instance->LoadData("buildVersionPatch", gSaveContext.ship.stats.buildVersionPatch);
- SaveManager::Instance->LoadData("heartPieces", gSaveContext.sohStats.heartPieces);
- SaveManager::Instance->LoadData("heartContainers", gSaveContext.sohStats.heartContainers);
- SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys), [](size_t i) {
- SaveManager::Instance->LoadData("", gSaveContext.sohStats.dungeonKeys[i]);
+ SaveManager::Instance->LoadData("heartPieces", gSaveContext.ship.stats.heartPieces);
+ SaveManager::Instance->LoadData("heartContainers", gSaveContext.ship.stats.heartContainers);
+ SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.ship.stats.dungeonKeys), [](size_t i) {
+ SaveManager::Instance->LoadData("", gSaveContext.ship.stats.dungeonKeys[i]);
});
- SaveManager::Instance->LoadData("rtaTiming", gSaveContext.sohStats.rtaTiming);
- SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.sohStats.fileCreatedAt);
- SaveManager::Instance->LoadData("playTimer", gSaveContext.sohStats.playTimer);
- SaveManager::Instance->LoadData("pauseTimer", gSaveContext.sohStats.pauseTimer);
- SaveManager::Instance->LoadArray("itemTimestamps", ARRAY_COUNT(gSaveContext.sohStats.itemTimestamp), [](size_t i) {
- SaveManager::Instance->LoadData("", gSaveContext.sohStats.itemTimestamp[i]);
+ SaveManager::Instance->LoadData("rtaTiming", gSaveContext.ship.stats.rtaTiming);
+ SaveManager::Instance->LoadData("fileCreatedAt", gSaveContext.ship.stats.fileCreatedAt);
+ SaveManager::Instance->LoadData("playTimer", gSaveContext.ship.stats.playTimer);
+ SaveManager::Instance->LoadData("pauseTimer", gSaveContext.ship.stats.pauseTimer);
+ SaveManager::Instance->LoadArray("itemTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp), [](size_t i) {
+ SaveManager::Instance->LoadData("", gSaveContext.ship.stats.itemTimestamp[i]);
});
- SaveManager::Instance->LoadArray("sceneTimestamps", ARRAY_COUNT(gSaveContext.sohStats.sceneTimestamps), [&](size_t i) {
+ SaveManager::Instance->LoadArray("sceneTimestamps", ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps), [&](size_t i) {
SaveManager::Instance->LoadStruct("", [&]() {
int scene, room, sceneTime, roomTime, isRoom;
SaveManager::Instance->LoadData("scene", scene);
@@ -316,63 +316,63 @@ void LoadStatsVersion1() {
if (scene == 0 && room == 0 && sceneTime == 0 && roomTime == 0 && isRoom == 0) {
return;
}
- gSaveContext.sohStats.sceneTimestamps[i].scene = scene;
- gSaveContext.sohStats.sceneTimestamps[i].room = room;
- gSaveContext.sohStats.sceneTimestamps[i].sceneTime = sceneTime;
- gSaveContext.sohStats.sceneTimestamps[i].roomTime = roomTime;
- gSaveContext.sohStats.sceneTimestamps[i].isRoom = isRoom;
+ gSaveContext.ship.stats.sceneTimestamps[i].scene = scene;
+ gSaveContext.ship.stats.sceneTimestamps[i].room = room;
+ gSaveContext.ship.stats.sceneTimestamps[i].sceneTime = sceneTime;
+ gSaveContext.ship.stats.sceneTimestamps[i].roomTime = roomTime;
+ gSaveContext.ship.stats.sceneTimestamps[i].isRoom = isRoom;
});
});
- SaveManager::Instance->LoadData("tsIdx", gSaveContext.sohStats.tsIdx);
- SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.sohStats.count), [](size_t i) {
- SaveManager::Instance->LoadData("", gSaveContext.sohStats.count[i]);
+ SaveManager::Instance->LoadData("tsIdx", gSaveContext.ship.stats.tsIdx);
+ SaveManager::Instance->LoadArray("counts", ARRAY_COUNT(gSaveContext.ship.stats.count), [](size_t i) {
+ SaveManager::Instance->LoadData("", gSaveContext.ship.stats.count[i]);
});
- SaveManager::Instance->LoadArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.scenesDiscovered), [](size_t i) {
- SaveManager::Instance->LoadData("", gSaveContext.sohStats.scenesDiscovered[i]);
+ SaveManager::Instance->LoadArray("scenesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered), [](size_t i) {
+ SaveManager::Instance->LoadData("", gSaveContext.ship.stats.scenesDiscovered[i]);
});
- SaveManager::Instance->LoadArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.sohStats.entrancesDiscovered), [](size_t i) {
- SaveManager::Instance->LoadData("", gSaveContext.sohStats.entrancesDiscovered[i]);
+ SaveManager::Instance->LoadArray("entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered), [](size_t i) {
+ SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]);
});
}
void SaveStats(SaveContext* saveContext, int sectionID, bool fullSave) {
- SaveManager::Instance->SaveData("buildVersion", saveContext->sohStats.buildVersion);
- SaveManager::Instance->SaveData("buildVersionMajor", saveContext->sohStats.buildVersionMajor);
- SaveManager::Instance->SaveData("buildVersionMinor", saveContext->sohStats.buildVersionMinor);
- SaveManager::Instance->SaveData("buildVersionPatch", saveContext->sohStats.buildVersionPatch);
+ SaveManager::Instance->SaveData("buildVersion", saveContext->ship.stats.buildVersion);
+ SaveManager::Instance->SaveData("buildVersionMajor", saveContext->ship.stats.buildVersionMajor);
+ SaveManager::Instance->SaveData("buildVersionMinor", saveContext->ship.stats.buildVersionMinor);
+ SaveManager::Instance->SaveData("buildVersionPatch", saveContext->ship.stats.buildVersionPatch);
- SaveManager::Instance->SaveData("heartPieces", saveContext->sohStats.heartPieces);
- SaveManager::Instance->SaveData("heartContainers", saveContext->sohStats.heartContainers);
- SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->sohStats.dungeonKeys), [&](size_t i) {
- SaveManager::Instance->SaveData("", saveContext->sohStats.dungeonKeys[i]);
+ SaveManager::Instance->SaveData("heartPieces", saveContext->ship.stats.heartPieces);
+ SaveManager::Instance->SaveData("heartContainers", saveContext->ship.stats.heartContainers);
+ SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->ship.stats.dungeonKeys), [&](size_t i) {
+ SaveManager::Instance->SaveData("", saveContext->ship.stats.dungeonKeys[i]);
});
- SaveManager::Instance->SaveData("rtaTiming", saveContext->sohStats.rtaTiming);
- SaveManager::Instance->SaveData("fileCreatedAt", saveContext->sohStats.fileCreatedAt);
- SaveManager::Instance->SaveData("playTimer", saveContext->sohStats.playTimer);
- SaveManager::Instance->SaveData("pauseTimer", saveContext->sohStats.pauseTimer);
- SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(saveContext->sohStats.itemTimestamp), [&](size_t i) {
- SaveManager::Instance->SaveData("", saveContext->sohStats.itemTimestamp[i]);
+ SaveManager::Instance->SaveData("rtaTiming", saveContext->ship.stats.rtaTiming);
+ SaveManager::Instance->SaveData("fileCreatedAt", saveContext->ship.stats.fileCreatedAt);
+ SaveManager::Instance->SaveData("playTimer", saveContext->ship.stats.playTimer);
+ SaveManager::Instance->SaveData("pauseTimer", saveContext->ship.stats.pauseTimer);
+ SaveManager::Instance->SaveArray("itemTimestamps", ARRAY_COUNT(saveContext->ship.stats.itemTimestamp), [&](size_t i) {
+ SaveManager::Instance->SaveData("", saveContext->ship.stats.itemTimestamp[i]);
});
- SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(saveContext->sohStats.sceneTimestamps), [&](size_t i) {
- if (saveContext->sohStats.sceneTimestamps[i].scene != 254 && saveContext->sohStats.sceneTimestamps[i].room != 254) {
+ SaveManager::Instance->SaveArray("sceneTimestamps", ARRAY_COUNT(saveContext->ship.stats.sceneTimestamps), [&](size_t i) {
+ if (saveContext->ship.stats.sceneTimestamps[i].scene != 254 && saveContext->ship.stats.sceneTimestamps[i].room != 254) {
SaveManager::Instance->SaveStruct("", [&]() {
- SaveManager::Instance->SaveData("scene", saveContext->sohStats.sceneTimestamps[i].scene);
- SaveManager::Instance->SaveData("room", saveContext->sohStats.sceneTimestamps[i].room);
- SaveManager::Instance->SaveData("sceneTime", saveContext->sohStats.sceneTimestamps[i].sceneTime);
- SaveManager::Instance->SaveData("roomTime", saveContext->sohStats.sceneTimestamps[i].roomTime);
- SaveManager::Instance->SaveData("isRoom", saveContext->sohStats.sceneTimestamps[i].isRoom);
+ SaveManager::Instance->SaveData("scene", saveContext->ship.stats.sceneTimestamps[i].scene);
+ SaveManager::Instance->SaveData("room", saveContext->ship.stats.sceneTimestamps[i].room);
+ SaveManager::Instance->SaveData("sceneTime", saveContext->ship.stats.sceneTimestamps[i].sceneTime);
+ SaveManager::Instance->SaveData("roomTime", saveContext->ship.stats.sceneTimestamps[i].roomTime);
+ SaveManager::Instance->SaveData("isRoom", saveContext->ship.stats.sceneTimestamps[i].isRoom);
});
}
});
- SaveManager::Instance->SaveData("tsIdx", saveContext->sohStats.tsIdx);
- SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->sohStats.count), [&](size_t i) {
- SaveManager::Instance->SaveData("", saveContext->sohStats.count[i]);
+ SaveManager::Instance->SaveData("tsIdx", saveContext->ship.stats.tsIdx);
+ SaveManager::Instance->SaveArray("counts", ARRAY_COUNT(saveContext->ship.stats.count), [&](size_t i) {
+ SaveManager::Instance->SaveData("", saveContext->ship.stats.count[i]);
});
- SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->sohStats.scenesDiscovered), [&](size_t i) {
- SaveManager::Instance->SaveData("", saveContext->sohStats.scenesDiscovered[i]);
+ SaveManager::Instance->SaveArray("scenesDiscovered", ARRAY_COUNT(saveContext->ship.stats.scenesDiscovered), [&](size_t i) {
+ SaveManager::Instance->SaveData("", saveContext->ship.stats.scenesDiscovered[i]);
});
- SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->sohStats.entrancesDiscovered), [&](size_t i) {
- SaveManager::Instance->SaveData("", saveContext->sohStats.entrancesDiscovered[i]);
+ SaveManager::Instance->SaveArray("entrancesDiscovered", ARRAY_COUNT(saveContext->ship.stats.entrancesDiscovered), [&](size_t i) {
+ SaveManager::Instance->SaveData("", saveContext->ship.stats.entrancesDiscovered[i]);
});
}
@@ -443,16 +443,16 @@ void DrawGameplayStatsHeader() {
} else {
GameplayStatsRow("Build Version:", (char*)gBuildVersion);
}
- if (gSaveContext.sohStats.rtaTiming) {
- GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.sohStats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
+ if (gSaveContext.ship.stats.rtaTiming) {
+ GameplayStatsRow("Total Time (RTA):", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
} else {
- GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.sohStats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
+ GameplayStatsRow("Total Game Time:", formatTimestampGameplayStat(GAMEPLAYSTAT_TOTAL_TIME), gSaveContext.ship.stats.gameComplete ? COLOR_GREEN : COLOR_WHITE);
}
if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"), 0)) { // !Only display total game time
- GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.sohStats.playTimer / 2), COLOR_GREY);
- GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.sohStats.pauseTimer / 3), COLOR_GREY);
- GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.sohStats.sceneTimer / 2), COLOR_LIGHT_BLUE);
- GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.sohStats.roomTimer / 2), COLOR_LIGHT_BLUE);
+ GameplayStatsRow("Gameplay Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.playTimer / 2), COLOR_GREY);
+ GameplayStatsRow("Pause Menu Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.pauseTimer / 3), COLOR_GREY);
+ GameplayStatsRow("Time in scene:", formatTimestampGameplayStat(gSaveContext.ship.stats.sceneTimer / 2), COLOR_LIGHT_BLUE);
+ GameplayStatsRow("Time in room:", formatTimestampGameplayStat(gSaveContext.ship.stats.roomTimer / 2), COLOR_LIGHT_BLUE);
}
if (gPlayState != NULL && CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo"), 0)) { // && display debug info
GameplayStatsRow("play->sceneNum:", formatHexGameplayStat(gPlayState->sceneNum), COLOR_YELLOW);
@@ -468,7 +468,7 @@ void DrawGameplayStatsTimestampsTab() {
// Set up the array of item timestamps and then sort it chronologically
for (int i = 0; i < TIMESTAMP_MAX; i++) {
strcpy(itemTimestampDisplay[i].name, itemTimestampDisplayName[i]);
- itemTimestampDisplay[i].time = gSaveContext.sohStats.itemTimestamp[i];
+ itemTimestampDisplay[i].time = gSaveContext.ship.stats.itemTimestamp[i];
itemTimestampDisplay[i].color = itemTimestampDisplayColor[i];
}
@@ -497,18 +497,18 @@ void DrawGameplayStatsCountsTab() {
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
// Special case: You must kill 3 mini Floormasters for it count as one defeated Floormaster
- enemiesDefeated += gSaveContext.sohStats.count[i] / 3;
+ enemiesDefeated += gSaveContext.ship.stats.count[i] / 3;
} else {
- enemiesDefeated += gSaveContext.sohStats.count[i];
+ enemiesDefeated += gSaveContext.ship.stats.count[i];
}
}
// Sum of all ammo used
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
- ammoUsed += gSaveContext.sohStats.count[i];
+ ammoUsed += gSaveContext.ship.stats.count[i];
}
// Sum of all button presses
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
- buttonPresses += gSaveContext.sohStats.count[i];
+ buttonPresses += gSaveContext.ship.stats.count[i];
}
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f });
@@ -520,47 +520,47 @@ void DrawGameplayStatsCountsTab() {
if (ImGui::TreeNodeEx("Enemy Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_ENEMIES_DEFEATED_ANUBIS; i <= COUNT_ENEMIES_DEFEATED_WOLFOS; i++) {
if (i == COUNT_ENEMIES_DEFEATED_FLOORMASTER) {
- GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.sohStats.count[i] / 3));
+ GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i] / 3));
} else {
- GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.sohStats.count[i]));
+ GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
}
}
}
}
- GameplayStatsRow("Rupees Collected:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_RUPEES_COLLECTED]));
+ GameplayStatsRow("Rupees Collected:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_RUPEES_COLLECTED]));
UIWidgets::Tooltip("Includes rupees collected with a full wallet.");
- GameplayStatsRow("Rupees Spent:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_RUPEES_SPENT]));
- GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_CHESTS_OPENED]));
+ GameplayStatsRow("Rupees Spent:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_RUPEES_SPENT]));
+ GameplayStatsRow("Chests Opened:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_CHESTS_OPENED]));
GameplayStatsRow("Ammo Used:", formatIntGameplayStat(ammoUsed));
if (ammoUsed > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Ammo Details...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_AMMO_USED_STICK; i <= COUNT_AMMO_USED_BEAN; i++) {
- GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.sohStats.count[i]));
+ GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
}
}
}
- GameplayStatsRow("Damage Taken:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_DAMAGE_TAKEN]));
- GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_SWORD_SWINGS]));
- GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_STEPS]));
+ GameplayStatsRow("Damage Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_DAMAGE_TAKEN]));
+ GameplayStatsRow("Sword Swings:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SWORD_SWINGS]));
+ GameplayStatsRow("Steps Taken:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_STEPS]));
// If using MM Bunny Hood enhancement, show how long it's been equipped (not counting pause time)
- if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
- GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.sohStats.count[COUNT_TIME_BUNNY_HOOD] / 2));
+ if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA || gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] > 0) {
+ GameplayStatsRow("Bunny Hood Time:", formatTimestampGameplayStat(gSaveContext.ship.stats.count[COUNT_TIME_BUNNY_HOOD] / 2));
}
- GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_ROLLS]));
- GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_BONKS]));
- GameplayStatsRow("Sidehops:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_SIDEHOPS]));
- GameplayStatsRow("Backflips:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_BACKFLIPS]));
- GameplayStatsRow("Ice Traps:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_ICE_TRAPS]));
- GameplayStatsRow("Pauses:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_PAUSES]));
- GameplayStatsRow("Pots Smashed:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_POTS_BROKEN]));
- GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.sohStats.count[COUNT_BUSHES_CUT]));
+ GameplayStatsRow("Rolls:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ROLLS]));
+ GameplayStatsRow("Bonks:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BONKS]));
+ GameplayStatsRow("Sidehops:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_SIDEHOPS]));
+ GameplayStatsRow("Backflips:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BACKFLIPS]));
+ GameplayStatsRow("Ice Traps:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_ICE_TRAPS]));
+ GameplayStatsRow("Pauses:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_PAUSES]));
+ GameplayStatsRow("Pots Smashed:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_POTS_BROKEN]));
+ GameplayStatsRow("Bushes Cut:", formatIntGameplayStat(gSaveContext.ship.stats.count[COUNT_BUSHES_CUT]));
GameplayStatsRow("Buttons Pressed:", formatIntGameplayStat(buttonPresses));
if (buttonPresses > 0) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
if (ImGui::TreeNodeEx("Buttons...", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
for (int i = COUNT_BUTTON_PRESSES_A; i <= COUNT_BUTTON_PRESSES_START; i++) {
- GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.sohStats.count[i]));
+ GameplayStatsRow(countMappings[i], formatIntGameplayStat(gSaveContext.ship.stats.count[i]));
}
}
}
@@ -569,25 +569,25 @@ void DrawGameplayStatsCountsTab() {
}
void DrawGameplayStatsBreakdownTab() {
- for (int i = 0; i < gSaveContext.sohStats.tsIdx; i++) {
- std::string sceneName = ResolveSceneID(gSaveContext.sohStats.sceneTimestamps[i].scene, gSaveContext.sohStats.sceneTimestamps[i].room);
+ for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) {
+ std::string sceneName = ResolveSceneID(gSaveContext.ship.stats.sceneTimestamps[i].scene, gSaveContext.ship.stats.sceneTimestamps[i].room);
std::string name;
- if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) && gSaveContext.sohStats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
- name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.sohStats.sceneTimestamps[i].room);
+ if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneTimestamps[i].scene != SCENE_GROTTOS) {
+ name = fmt::format("{:s} Room {:d}", sceneName, gSaveContext.ship.stats.sceneTimestamps[i].room);
} else {
name = sceneName;
}
strcpy(sceneTimestampDisplay[i].name, name.c_str());
- sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) ?
- gSaveContext.sohStats.sceneTimestamps[i].roomTime : gSaveContext.sohStats.sceneTimestamps[i].sceneTime;
+ sceneTimestampDisplay[i].time = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) ?
+ gSaveContext.ship.stats.sceneTimestamps[i].roomTime : gSaveContext.ship.stats.sceneTimestamps[i].sceneTime;
sceneTimestampDisplay[i].color = COLOR_GREY;
- sceneTimestampDisplay[i].isRoom = gSaveContext.sohStats.sceneTimestamps[i].isRoom;
+ sceneTimestampDisplay[i].isRoom = gSaveContext.ship.stats.sceneTimestamps[i].isRoom;
}
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 4.0f, 4.0f });
ImGui::BeginTable("gameplayStatsCounts", 1, ImGuiTableFlags_BordersOuter);
ImGui::TableSetupColumn("stat", ImGuiTableColumnFlags_WidthStretch);
- for (int i = 0; i < gSaveContext.sohStats.tsIdx; i++) {
+ for (int i = 0; i < gSaveContext.ship.stats.tsIdx; i++) {
TimestampInfo tsInfo = sceneTimestampDisplay[i];
bool canShow = !tsInfo.isRoom || CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0);
if (tsInfo.time > 0 && strnlen(tsInfo.name, 40) > 1 && canShow) {
@@ -595,10 +595,10 @@ void DrawGameplayStatsBreakdownTab() {
}
}
std::string toPass;
- if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) && gSaveContext.sohStats.sceneNum != SCENE_GROTTOS) {
- toPass = fmt::format("{:s} Room {:d}", ResolveSceneID(gSaveContext.sohStats.sceneNum, gSaveContext.sohStats.roomNum), gSaveContext.sohStats.roomNum);
+ if (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) && gSaveContext.ship.stats.sceneNum != SCENE_GROTTOS) {
+ toPass = fmt::format("{:s} Room {:d}", ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum), gSaveContext.ship.stats.roomNum);
} else {
- toPass = ResolveSceneID(gSaveContext.sohStats.sceneNum, gSaveContext.sohStats.roomNum);
+ toPass = ResolveSceneID(gSaveContext.ship.stats.sceneNum, gSaveContext.ship.stats.roomNum);
}
GameplayStatsRow(toPass.c_str(), formatTimestampGameplayStat(CURRENT_MODE_TIMER / 2));
ImGui::EndTable();
@@ -611,14 +611,14 @@ void DrawGameplayStatsOptionsTab() {
UIWidgets::PaddedEnhancementCheckbox("Show latest timestamps on top", CVAR_ENHANCEMENT("GameplayStats.ReverseTimestamps"), true, false);
UIWidgets::PaddedEnhancementCheckbox("Room Breakdown", CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), true, false);
ImGui::SameLine();
- UIWidgets::InsertHelpHoverText("Allows a more in-depth perspective of time spent in a certain map.");
+ UIWidgets::InsertHelpHoverText("Allows a more in-depth perspective of time spent in a certain map.");
UIWidgets::PaddedEnhancementCheckbox("RTA Timing on new files", CVAR_ENHANCEMENT("GameplayStats.RTATiming"), true, false);
ImGui::SameLine();
UIWidgets::InsertHelpHoverText(
"Timestamps are relative to starting timestamp rather than in game time, usually necessary for races/speedruns.\n\n"
"Starting timestamp is on first non-c-up input after intro cutscene.\n\n"
"NOTE: THIS NEEDS TO BE SET BEFORE CREATING A FILE TO TAKE EFFECT"
- );
+ );
UIWidgets::PaddedEnhancementCheckbox("Show additional detail timers", CVAR_ENHANCEMENT("GameplayStats.ShowAdditionalTimers"), true, false);
UIWidgets::PaddedEnhancementCheckbox("Show Debug Info", CVAR_ENHANCEMENT("GameplayStats.ShowDebugInfo"));
}
@@ -645,46 +645,46 @@ void GameplayStatsWindow::DrawElement() {
}
ImGui::EndTabBar();
}
-
+
ImGui::Text("Note: Gameplay stats are saved to the current file and will be\nlost if you quit without saving.");
}
void InitStats(bool isDebug) {
- gSaveContext.sohStats.heartPieces = isDebug ? 8 : 0;
- gSaveContext.sohStats.heartContainers = isDebug ? 8 : 0;
- for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.sohStats.dungeonKeys); dungeon++) {
- gSaveContext.sohStats.dungeonKeys[dungeon] = isDebug ? 8 : 0;
+ gSaveContext.ship.stats.heartPieces = isDebug ? 8 : 0;
+ gSaveContext.ship.stats.heartContainers = isDebug ? 8 : 0;
+ for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.ship.stats.dungeonKeys); dungeon++) {
+ gSaveContext.ship.stats.dungeonKeys[dungeon] = isDebug ? 8 : 0;
}
- gSaveContext.sohStats.rtaTiming = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RTATiming"), 0);
- gSaveContext.sohStats.fileCreatedAt = 0;
- gSaveContext.sohStats.playTimer = 0;
- gSaveContext.sohStats.pauseTimer = 0;
- for (int timestamp = 0; timestamp < ARRAY_COUNT(gSaveContext.sohStats.itemTimestamp); timestamp++) {
- gSaveContext.sohStats.itemTimestamp[timestamp] = 0;
+ gSaveContext.ship.stats.rtaTiming = CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RTATiming"), 0);
+ gSaveContext.ship.stats.fileCreatedAt = 0;
+ gSaveContext.ship.stats.playTimer = 0;
+ gSaveContext.ship.stats.pauseTimer = 0;
+ for (int timestamp = 0; timestamp < ARRAY_COUNT(gSaveContext.ship.stats.itemTimestamp); timestamp++) {
+ gSaveContext.ship.stats.itemTimestamp[timestamp] = 0;
}
- for (int timestamp = 0; timestamp < ARRAY_COUNT(gSaveContext.sohStats.sceneTimestamps); timestamp++) {
- gSaveContext.sohStats.sceneTimestamps[timestamp].sceneTime = 0;
- gSaveContext.sohStats.sceneTimestamps[timestamp].roomTime = 0;
- gSaveContext.sohStats.sceneTimestamps[timestamp].scene = 254;
- gSaveContext.sohStats.sceneTimestamps[timestamp].room = 254;
- gSaveContext.sohStats.sceneTimestamps[timestamp].isRoom = 0;
+ for (int timestamp = 0; timestamp < ARRAY_COUNT(gSaveContext.ship.stats.sceneTimestamps); timestamp++) {
+ gSaveContext.ship.stats.sceneTimestamps[timestamp].sceneTime = 0;
+ gSaveContext.ship.stats.sceneTimestamps[timestamp].roomTime = 0;
+ gSaveContext.ship.stats.sceneTimestamps[timestamp].scene = 254;
+ gSaveContext.ship.stats.sceneTimestamps[timestamp].room = 254;
+ gSaveContext.ship.stats.sceneTimestamps[timestamp].isRoom = 0;
}
- gSaveContext.sohStats.tsIdx = 0;
- for (int count = 0; count < ARRAY_COUNT(gSaveContext.sohStats.count); count++) {
- gSaveContext.sohStats.count[count] = 0;
+ gSaveContext.ship.stats.tsIdx = 0;
+ for (int count = 0; count < ARRAY_COUNT(gSaveContext.ship.stats.count); count++) {
+ gSaveContext.ship.stats.count[count] = 0;
}
- gSaveContext.sohStats.gameComplete = false;
- for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.sohStats.scenesDiscovered); scenesIdx++) {
- gSaveContext.sohStats.scenesDiscovered[scenesIdx] = 0;
+ gSaveContext.ship.stats.gameComplete = false;
+ for (int scenesIdx = 0; scenesIdx < ARRAY_COUNT(gSaveContext.ship.stats.scenesDiscovered); scenesIdx++) {
+ gSaveContext.ship.stats.scenesDiscovered[scenesIdx] = 0;
}
- for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.sohStats.entrancesDiscovered); entrancesIdx++) {
- gSaveContext.sohStats.entrancesDiscovered[entrancesIdx] = 0;
+ for (int entrancesIdx = 0; entrancesIdx < ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered); entrancesIdx++) {
+ gSaveContext.ship.stats.entrancesDiscovered[entrancesIdx] = 0;
}
- SohUtils::CopyStringToCharArray(gSaveContext.sohStats.buildVersion, std::string((char*)gBuildVersion),
- ARRAY_COUNT(gSaveContext.sohStats.buildVersion));
- gSaveContext.sohStats.buildVersionMajor = gBuildVersionMajor;
- gSaveContext.sohStats.buildVersionMinor = gBuildVersionMinor;
- gSaveContext.sohStats.buildVersionPatch = gBuildVersionPatch;
+ SohUtils::CopyStringToCharArray(gSaveContext.ship.stats.buildVersion, std::string((char*)gBuildVersion),
+ ARRAY_COUNT(gSaveContext.ship.stats.buildVersion));
+ gSaveContext.ship.stats.buildVersionMajor = gBuildVersionMajor;
+ gSaveContext.ship.stats.buildVersionMinor = gBuildVersionMinor;
+ gSaveContext.ship.stats.buildVersionPatch = gBuildVersionPatch;
}
// Entries listed here will have a timestamp shown in the stat window
diff --git a/soh/soh/Enhancements/gameplaystats.h b/soh/soh/Enhancements/gameplaystats.h
index 9d41f2560..81190c01e 100644
--- a/soh/soh/Enhancements/gameplaystats.h
+++ b/soh/soh/Enhancements/gameplaystats.h
@@ -19,14 +19,17 @@ extern "C" {
// Total gameplay time is tracked in tenths of seconds
// I.E. game time counts frames at 20fps/2, pause time counts frames at 30fps/3
// Frame counts in z_play.c and z_kaleido_scope_call.c
-#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.sohStats.rtaTiming ?\
- (!gSaveContext.sohStats.gameComplete ?\
- (!gSaveContext.sohStats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.sohStats.fileCreatedAt) / 100)) :\
- (gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_GANON])) :\
- (gSaveContext.sohStats.playTimer / 2 + gSaveContext.sohStats.pauseTimer / 3))
+#define GAMEPLAYSTAT_TOTAL_TIME (gSaveContext.ship.stats.rtaTiming ?\
+ (!gSaveContext.ship.stats.gameComplete ?\
+ (!gSaveContext.ship.stats.fileCreatedAt ? 0 : ((GetUnixTimestamp() - gSaveContext.ship.stats.fileCreatedAt) / 100)) :\
+ (gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
+ ? gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] \
+ : gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_TRIFORCE_COMPLETED])) \
+ :\
+ (gSaveContext.ship.stats.playTimer / 2 + gSaveContext.ship.stats.pauseTimer / 3))
#define CURRENT_MODE_TIMER (CVarGetInteger(CVAR_ENHANCEMENT("GameplayStats.RoomBreakdown"), 0) ?\
- gSaveContext.sohStats.roomTimer :\
- gSaveContext.sohStats.sceneTimer)
+ gSaveContext.ship.stats.roomTimer :\
+ gSaveContext.ship.stats.sceneTimer)
void InitStatTracker();
diff --git a/soh/soh/Enhancements/kaleido.cpp b/soh/soh/Enhancements/kaleido.cpp
index 36cf9d0a2..8d578168c 100644
--- a/soh/soh/Enhancements/kaleido.cpp
+++ b/soh/soh/Enhancements/kaleido.cpp
@@ -124,9 +124,9 @@ namespace Rando {
mEntries.push_back(
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.triforcePiecesCollected),
- ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1,
- ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
+ yOffset, reinterpret_cast(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
+ 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 b78368b80..b892a1282 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -15,7 +15,6 @@
#include "soh/Enhancements/nametag.h"
#include "soh/Enhancements/timesaver_hook_handlers.h"
#include "soh/Enhancements/TimeSavers/TimeSavers.h"
-#include "soh/Enhancements/cheat_hook_handlers.h"
#include "soh/Enhancements/randomizer/hook_handlers.h"
#include "objects/object_gi_compass/object_gi_compass.h"
@@ -68,136 +67,6 @@ static const ALIGN_ASSET(2) char tokinoma_room_0DL_007A70[] = dtokinoma_room_0DL
#define dtokinoma_room_0DL_007FD0 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007FD0"
static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL_007FD0;
-void RegisterInfiniteMoney() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
- if (CVarGetInteger(CVAR_CHEAT("InfiniteMoney"), 0) != 0 && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET))) {
- if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) {
- gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
- }
- }
- });
-}
-
-void RegisterInfiniteHealth() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
- if (CVarGetInteger(CVAR_CHEAT("InfiniteHealth"), 0) != 0) {
- if (gSaveContext.health < gSaveContext.healthCapacity) {
- gSaveContext.health = gSaveContext.healthCapacity;
- }
- }
- });
-}
-
-void RegisterInfiniteAmmo() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
- if (CVarGetInteger(CVAR_CHEAT("InfiniteAmmo"), 0) != 0) {
- // Deku Sticks
- if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) {
- AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
- }
-
- // Deku Nuts
- if (AMMO(ITEM_NUT) < CUR_CAPACITY(UPG_NUTS)) {
- AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS);
- }
-
- // Bombs
- if (AMMO(ITEM_BOMB) < CUR_CAPACITY(UPG_BOMB_BAG)) {
- AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG);
- }
-
- // Fairy Bow (Ammo)
- if (AMMO(ITEM_BOW) < CUR_CAPACITY(UPG_QUIVER)) {
- AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER);
- }
-
- // Fairy Slingshot (Ammo)
- if (AMMO(ITEM_SLINGSHOT) < CUR_CAPACITY(UPG_BULLET_BAG)) {
- AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG);
- }
-
- // Bombchus (max: 50, no upgrades)
- if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU && AMMO(ITEM_BOMBCHU) < 50) {
- AMMO(ITEM_BOMBCHU) = 50;
- }
- }
- });
-}
-
-void RegisterInfiniteMagic() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
- if (CVarGetInteger(CVAR_CHEAT("InfiniteMagic"), 0) != 0) {
- if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) {
- gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30;
- }
- }
- });
-}
-
-void RegisterInfiniteNayrusLove() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
- if (CVarGetInteger(CVAR_CHEAT("InfiniteNayru"), 0) != 0) {
- gSaveContext.nayrusLoveTimer = 0x44B;
- }
- });
-}
-
-void RegisterInfiniteISG() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
-
- if (CVarGetInteger(CVAR_CHEAT("EasyISG"), 0) != 0) {
- Player* player = GET_PLAYER(gPlayState);
- player->meleeWeaponState = 1;
- }
- });
-}
-
-//Permanent quick put away (QPA) glitched damage value
-void RegisterEzQPA() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
-
- if (CVarGetInteger(CVAR_CHEAT("EasyQPA"), 0) != 0) {
- Player* player = GET_PLAYER(gPlayState);
- player->meleeWeaponQuads[0].info.toucher.dmgFlags = 0x16171617;
- player->meleeWeaponQuads[1].info.toucher.dmgFlags = 0x16171617;
- }
- });
-}
-
-void RegisterUnrestrictedItems() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (!GameInteractor::IsSaveLoaded(true)) return;
-
- if (CVarGetInteger(CVAR_CHEAT("NoRestrictItems"), 0) != 0) {
- u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
- memset(&gPlayState->interfaceCtx.restrictions, 0, sizeof(gPlayState->interfaceCtx.restrictions));
- gPlayState->interfaceCtx.restrictions.sunsSong = sunsBackup;
- }
- });
-}
-
-void RegisterFreezeTime() {
- GameInteractor::Instance->RegisterGameHook([]() {
- if (CVarGetInteger(CVAR_CHEAT("FreezeTime"), 0) != 0) {
- if (CVarGetInteger(CVAR_GENERAL("PrevTime"), -1) == -1) {
- CVarSetInteger(CVAR_GENERAL("PrevTime"), gSaveContext.dayTime);
- }
-
- int32_t prevTime = CVarGetInteger(CVAR_GENERAL("PrevTime"), gSaveContext.dayTime);
- gSaveContext.dayTime = prevTime;
- } else {
- CVarClear(CVAR_GENERAL("PrevTime"));
- }
- });
-}
-
/// Switches Link's age and respawns him at the last entrance he entered.
void SwitchAge() {
if (gPlayState == NULL) return;
@@ -272,7 +141,7 @@ void AutoSave(GetItemEntry itemEntry) {
// Don't autosave immediately after buying items from shops to prevent getting them for free!
// Don't autosave in the Chamber of Sages since resuming from that map breaks the game
// Don't autosave during the Ganon fight when picking up the Master Sword
- if ((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.pendingSale == ITEM_NONE) &&
+ if ((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.ship.pendingSale == ITEM_NONE) &&
(gPlayState->gameplayFrames > 60 && gSaveContext.cutsceneIndex < 0xFFF0) && (gPlayState->sceneNum != SCENE_GANON_BOSS) && (gPlayState->sceneNum != SCENE_CHAMBER_OF_THE_SAGES)) {
if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_ALL_ITEMS)) && (item != ITEM_NONE)) {
// Autosave for all items
@@ -409,8 +278,8 @@ void UpdatePermanentHeartLossState() {
if (!GameInteractor::IsSaveLoaded()) return;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) {
- uint8_t heartContainers = gSaveContext.sohStats.heartContainers; // each worth 16 health
- uint8_t heartPieces = gSaveContext.sohStats.heartPieces; // each worth 4 health, but only in groups of 4
+ uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health
+ uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4
uint8_t startingHealth = 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3);
@@ -508,7 +377,7 @@ void RegisterDaytimeGoldSkultullas() {
bool IsHyperBossesActive() {
return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) ||
- (IS_BOSS_RUSH && gSaveContext.bossRushOptions[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
+ (IS_BOSS_RUSH && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
}
void UpdateHyperBossesState() {
@@ -666,8 +535,8 @@ 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()
- : gSaveContext.sohStats.fileCreatedAt);
+ uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
+ : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}
@@ -864,60 +733,60 @@ void RegisterEnemyDefeatCounts() {
GameInteractor::Instance->RegisterGameHook([](void* refActor) {
Actor* actor = static_cast(refActor);
if (uniqueEnemyIdToStatCount.contains(actor->id)) {
- gSaveContext.sohStats.count[uniqueEnemyIdToStatCount[actor->id]]++;
+ gSaveContext.ship.stats.count[uniqueEnemyIdToStatCount[actor->id]]++;
} else {
switch (actor->id) {
case ACTOR_EN_BB:
if (actor->params == ENBB_GREEN || actor->params == ENBB_GREEN_BIG) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_GREEN]++;
} else if (actor->params == ENBB_BLUE) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_BLUE]++;
} else if (actor->params == ENBB_WHITE) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_WHITE]++;
} else if (actor->params == ENBB_RED) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_BUBBLE_RED]++;
}
break;
case ACTOR_EN_DEKUBABA:
if (actor->params == DEKUBABA_BIG) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA_BIG]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_DEKU_BABA]++;
}
break;
case ACTOR_EN_ZF:
if (actor->params == ENZF_TYPE_DINOLFOS) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_DINOLFOS]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_DINOLFOS]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LIZALFOS]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LIZALFOS]++;
}
break;
case ACTOR_EN_RD:
if (actor->params >= -1) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_REDEAD]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_REDEAD]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_GIBDO]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_GIBDO]++;
}
break;
case ACTOR_EN_IK:
if (actor->params == 0) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE_NABOORU]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_IRON_KNUCKLE]++;
}
break;
case ACTOR_EN_FIREFLY:
if (actor->params == KEESE_NORMAL_FLY || actor->params == KEESE_NORMAL_PERCH) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_KEESE]++;
} else if (actor->params == KEESE_FIRE_FLY || actor->params == KEESE_FIRE_PERCH) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_KEESE_FIRE]++;
} else if (actor->params == KEESE_ICE_FLY) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_KEESE_ICE]++;
}
break;
@@ -925,80 +794,80 @@ void RegisterEnemyDefeatCounts() {
{
EnReeba* reeba = (EnReeba*)actor;
if (reeba->isBig) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER_BIG]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_LEEVER]++;
}
}
break;
case ACTOR_EN_MB:
if (actor->params == 0) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_MOBLIN_CLUB]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_MOBLIN]++;
}
break;
case ACTOR_EN_PEEHAT:
if (actor->params == PEAHAT_TYPE_LARVA) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_PEAHAT_LARVA]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_PEAHAT]++;
}
break;
-
+
case ACTOR_EN_POH:
if (actor->params == EN_POH_FLAT || actor->params == EN_POH_SHARP) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE_COMPOSER]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE]++;
}
break;
case ACTOR_EN_PO_FIELD:
if (actor->params == EN_PO_FIELD_BIG) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE_BIG]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_POE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_POE]++;
}
break;
case ACTOR_EN_ST:
if (actor->params == 1) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_BIG]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA]++;
}
break;
case ACTOR_EN_SW:
if (((actor->params & 0xE000) >> 0xD) != 0) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLTULA_GOLD]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_SKULLWALLTULA]++;
}
break;
case ACTOR_EN_TP:
if (actor->params == TAILPASARAN_HEAD) { // Only count the head, otherwise each body segment will increment
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_TAILPASARAN]++;
}
break;
case ACTOR_EN_TITE:
if (actor->params == TEKTITE_BLUE) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_BLUE]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_TEKTITE_RED]++;
}
break;
case ACTOR_EN_WF:
if (actor->params == WOLFOS_WHITE) {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_WOLFOS_WHITE]++;
} else {
- gSaveContext.sohStats.count[COUNT_ENEMIES_DEFEATED_WOLFOS]++;
+ gSaveContext.ship.stats.count[COUNT_ENEMIES_DEFEATED_WOLFOS]++;
}
break;
}
@@ -1011,196 +880,40 @@ void RegisterBossDefeatTimestamps() {
Actor* actor = static_cast(refActor);
switch (actor->id) {
case ACTOR_BOSS_DODONGO:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_KING_DODONGO] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_KING_DODONGO] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_FD2:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_VOLVAGIA] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_VOLVAGIA] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_GANON:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_GANONDORF] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANONDORF] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_GANON2:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
- gSaveContext.sohStats.gameComplete = true;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.gameComplete = true;
break;
case ACTOR_BOSS_GANONDROF:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_PHANTOM_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_PHANTOM_GANON] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_GOMA:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_GOHMA] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_GOHMA] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_MO:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_MORPHA] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_MORPHA] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_SST:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_BONGO_BONGO] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_BONGO_BONGO] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_TW:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_TWINROVA] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_TWINROVA] = GAMEPLAYSTAT_TOTAL_TIME;
break;
case ACTOR_BOSS_VA:
- gSaveContext.sohStats.itemTimestamp[TIMESTAMP_DEFEAT_BARINADE] = GAMEPLAYSTAT_TOTAL_TIME;
+ gSaveContext.ship.stats.itemTimestamp[TIMESTAMP_DEFEAT_BARINADE] = GAMEPLAYSTAT_TOTAL_TIME;
break;
}
});
}
-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) {
@@ -1208,10 +921,10 @@ void UpdateHurtContainerModeState(bool newState) {
}
hurtEnabled = newState;
- uint16_t getHeartPieces = gSaveContext.sohStats.heartPieces / 4;
- uint16_t getHeartContainers = gSaveContext.sohStats.heartContainers;
-
- if (hurtEnabled) {
+ uint16_t getHeartPieces = gSaveContext.ship.stats.heartPieces / 4;
+ uint16_t getHeartContainers = gSaveContext.ship.stats.heartContainers;
+
+ if (hurtEnabled) {
gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16);
} else {
gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16);
@@ -1279,7 +992,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
@@ -1491,18 +1204,8 @@ void InitMods() {
BossRush_RegisterHooks();
RandomizerRegisterHooks();
TimeSaverRegisterHooks();
- CheatsRegisterHooks();
TimeSavers_Register();
RegisterTTS();
- RegisterInfiniteMoney();
- RegisterInfiniteHealth();
- RegisterInfiniteAmmo();
- RegisterInfiniteMagic();
- RegisterInfiniteNayrusLove();
- RegisterInfiniteISG();
- RegisterEzQPA();
- RegisterUnrestrictedItems();
- RegisterFreezeTime();
RegisterOcarinaTimeTravel();
RegisterAutoSave();
RegisterDaytimeGoldSkultullas();
@@ -1520,7 +1223,6 @@ void InitMods() {
RegisterDekuNutUpgradeFix();
RegisterEnemyDefeatCounts();
RegisterBossDefeatTimestamps();
- RegisterAltTrapTypes();
RegisterRandomizedEnemySizes();
RegisterOpenAllHours();
RegisterToTMedallions();
diff --git a/soh/soh/Enhancements/nametag.cpp b/soh/soh/Enhancements/nametag.cpp
index c2d72eae0..49b0891fa 100644
--- a/soh/soh/Enhancements/nametag.cpp
+++ b/soh/soh/Enhancements/nametag.cpp
@@ -83,7 +83,7 @@ void DrawNameTag(PlayState* play, const NameTag* nameTag) {
// Prefer the highest between world position and focus position if targetable
float posY = nameTag->actor->world.pos.y;
- if (nameTag->actor->flags & ACTOR_FLAG_TARGETABLE) {
+ if (nameTag->actor->flags & ACTOR_FLAG_ATTENTION_ENABLED) {
posY = std::max(posY, nameTag->actor->focus.pos.y);
}
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..4ba4b62be 100644
--- a/soh/soh/Enhancements/presets.cpp
+++ b/soh/soh/Enhancements/presets.cpp
@@ -3,7 +3,7 @@
#include
#include
#include
-#include "soh/UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include
void clearCvars(std::vector cvarsToClear) {
@@ -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 1bc4550f5..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"),
@@ -397,7 +395,7 @@ const std::vector randomizerCvars = {
CVAR_RANDOMIZER_SETTING("BigPoesHint"),
CVAR_RANDOMIZER_SETTING("BiggoronHint"),
CVAR_RANDOMIZER_SETTING("BlueFireArrows"),
- CVAR_RANDOMIZER_SETTING("BombchusInLogic"),
+ CVAR_RANDOMIZER_SETTING("BombchuBag"),
CVAR_RANDOMIZER_SETTING("BossKeysanity"),
CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"),
CVAR_RANDOMIZER_SETTING("ChickensHint"),
@@ -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),
@@ -1019,7 +1015,7 @@ const std::vector spockRacePresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), 0),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1),
- PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchusInLogic"), 1),
+ PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DampeHint"), 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),
@@ -1103,7 +1098,7 @@ const std::vector spockRaceNoLogicPresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("50GSHint"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), 0),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BlueFireArrows"), 1),
- PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchusInLogic"), 1),
+ PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BossKeysanity"), RO_DUNGEON_ITEM_LOC_ANYWHERE),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1),
@@ -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 248fd960d..234bd6a8e 100644
--- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp
@@ -130,14 +130,14 @@ static bool UpdateToDAccess(Entrance* entrance, Region* connection) {
static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) {
auto ctx = Rando::Context::GetInstance();
// Condition for validating Temple of Time Access
- if (!gals.foundTempleOfTime && ((ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD && RegionTable(RR_TEMPLE_OF_TIME)->Adult()) ||
- (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT && RegionTable(RR_TEMPLE_OF_TIME)->Child()))) {
+ if (!gals.foundTempleOfTime && ((ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) && RegionTable(RR_TEMPLE_OF_TIME)->Adult()) ||
+ (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) && RegionTable(RR_TEMPLE_OF_TIME)->Child()))) {
gals.foundTempleOfTime = true;
}
// Condition for validating a valid starting region
if (!gals.validatedStartingRegion) {
- bool childAccess = ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD || RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child();
- bool adultAccess = ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT || RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult();
+ bool childAccess = ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) || RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Child();
+ bool adultAccess = ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) || RegionTable(RR_TOT_BEYOND_DOOR_OF_TIME)->Adult();
Region* kokiri = RegionTable(RR_KOKIRI_FOREST);
Region* kakariko = RegionTable(RR_KAKARIKO_VILLAGE);
@@ -164,11 +164,11 @@ static void ApplyAllAdvancmentItems(){
static void ValidateSphereZero(GetAccessibleLocationsStruct& gals){
auto ctx = Rando::Context::GetInstance();
// Condition for verifying everything required for sphere 0, expanding search to all locations
- if (logic->CanEmptyBigPoes && gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) {
+ if (logic->CouldEmptyBigPoes && gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) {
// Apply all items that are necessary for checking all location access
ApplyAllAdvancmentItems();
// Reset access as the non-starting age
- if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
for (RandomizerRegion regionKey : gals.regionPool) {
RegionTable(regionKey)->adultDay = false;
RegionTable(regionKey)->adultNight = false;
@@ -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) {
@@ -565,7 +565,7 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce
ctx->allLocationsReachable = false;
if (checkPoeCollectorAccess){
- logic->CanEmptyBigPoes = false;
+ logic->CouldEmptyBigPoes = false;
}
if (checkOtherEntranceAccess){
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 0bf60eb81..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
{
@@ -1512,6 +1523,16 @@ void StaticData::HintTable_Init_Item() {
CustomMessage("a gambler's lockpick", /*german*/"ein Spieler-Dietrich", /*french*/"un crochet à serrure de parieur")});
// /*spanish*/una apertura portentosa del juego de azar
+ hintTextTable[RHT_TREASURE_GAME_KEY_RING] = HintText(CustomMessage("a Chest Game Key Ring"),
+ {
+ CustomMessage("a key ring", /*german*/"ein Schlüsselbund", /*french*/"un trousseau de clés")
+ // /*spanish*/un llavero
+ }, {
+ CustomMessage("a gambler's toolbox for unlocking"),
+ CustomMessage("a gambler's season pass"),
+ CustomMessage("a gambler's jingling ring"),
+ CustomMessage("a gambler's skeleton key")});
+
hintTextTable[RHT_KOKIRI_EMERALD] = HintText(CustomMessage("the Kokiri Emerald", /*german*/"der Kokiri-Smaragd", /*french*/"l'Émeraude Kokiri"),
// /*spanish*/la Esmeralda de los Kokiri
{
@@ -2057,6 +2078,16 @@ void StaticData::HintTable_Init_Item() {
}, {
CustomMessage("a fish-puller", /*german*/"ein Fischzieher", /*french*/"(canne à pêche)")});
// /*spanish*/(caña de pescar)
+
+ hintTextTable[RHT_BOMBCHU_BAG] = HintText(CustomMessage("Bombchu Bag", /*german*/"!!!", /*french*/"!!!"),
+ {
+ CustomMessage("explosives", /*german*/"ein Explosivpaket", /*french*/"un paquet d'explosifs"),
+ // /*spanish*/un montón de explosivos
+ CustomMessage("something that can remove boulders", /*german*/"etwas, das Geröll entfernen kann", /*french*/"une chose qui enlève les rochers")
+ // /*spanish*/algo que pueda quitar rocas
+ }, {
+ CustomMessage("sack of mice", /*german*/"!!!", /*french*/"!!!")});
+
hintTextTable[RHT_SKELETON_KEY] = HintText(CustomMessage("a Skeleton Key", /*german*/ "ein Universalschlüssel", /*french*/ "une Clé Squelette"),
// /*spanish*/una Llave Maestra
{
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 6f908de22..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());
}
@@ -998,7 +998,7 @@ void GenerateItemPool() {
if (/*!ProgressiveGoronSword TODO: Implement Progressive Goron Sword*/true) {
AddItemToMainPool(RG_GIANTS_KNIFE);
}
- if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) {
+ if (ctx->GetOption(RSK_BOMBCHU_BAG)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS);
} else {
AddItemToMainPool(RG_BOMBCHU_10);
@@ -1122,7 +1122,7 @@ void GenerateItemPool() {
AddItemToMainPool(RG_PROGRESSIVE_NUT_UPGRADE);
}
- if (ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) {
+ if (ctx->GetOption(RSK_BOMBCHU_BAG)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5);
} else {
AddItemToMainPool(RG_BOMBCHU_5);
@@ -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 bed532e9b..d78f1ef90 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->GetLocationOption(static_cast(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());
@@ -206,14 +207,19 @@ static void WriteMasterQuestDungeons() {
}
// Writes the required trials to the spoiler log, if there are any.
-static void WriteRequiredTrials() {
- auto ctx = Rando::Context::GetInstance();
- for (const auto& trial : ctx->GetTrials()->GetTrialList()) {
- if (trial->IsRequired()) {
- std::string trialName = trial->GetName().GetForCurrentLanguage(MF_CLEAN);
- jsonData["requiredTrials"].push_back(RemoveLineBreaks(trialName));
- }
+static void WriteChosenOptions() {
+ auto ctx = Rando::Context::GetInstance();
+ for (const auto& trial : ctx->GetTrials()->GetTrialList()) {
+ if (trial->IsRequired()) {
+ std::string trialName = trial->GetName().GetForCurrentLanguage(MF_CLEAN);
+ jsonData["requiredTrials"].push_back(RemoveLineBreaks(trialName));
}
+ }
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT)){
+ jsonData["SelectedStartingAge"] = "Adult";
+ } else {
+ jsonData["SelectedStartingAge"] = "Child";
+ }
}
// Writes the intended playthrough to the spoiler log, separated into spheres.
@@ -316,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;
@@ -331,7 +337,7 @@ const char* SpoilerLog_Write() {
WriteStartingInventory();
WriteEnabledTricks();
WriteMasterQuestDungeons();
- WriteRequiredTrials();
+ WriteChosenOptions();
WritePlaythrough();
ctx->playthroughLocations.clear();
diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
index 4e1afddb7..c72b5f285 100644
--- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
@@ -73,7 +73,7 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_PROGRESSIVE_STICK_UPGRADE, StartingStickCapacity.Value());
// AddItemToInventory(RG_PROGRESSIVE_NUT_UPGRADE, StartingNutCapacity.Value());
// AddItemToInventory(RG_PROGRESSIVE_BOMB_BAG, StartingBombBag.Value());
- // AddItemToInventory((BombchusInLogic ? RG_PROGRESSIVE_BOMBCHUS : RG_BOMBCHU_20), StartingBombchus.Value());
+ // AddItemToInventory((BombchuBag ? RG_PROGRESSIVE_BOMBCHUS : RG_BOMBCHU_20), StartingBombchus.Value());
// AddItemToInventory(RG_PROGRESSIVE_BOW, StartingBow.Value());
// AddItemToInventory(RG_FIRE_ARROWS, StartingFireArrows.Value());
// AddItemToInventory(RG_ICE_ARROWS, StartingIceArrows.Value());
@@ -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..e6c9399b5 100644
--- a/soh/soh/Enhancements/randomizer/Plandomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/Plandomizer.cpp
@@ -1,5 +1,5 @@
#include "Plandomizer.h"
-#include "soh/UIWidgets.hpp"
+#include "soh/SohGui/UIWidgets.hpp"
#include "soh/util.h"
#include
#include "soh/Notification/Notification.h"
@@ -10,7 +10,7 @@
#include
#include "soh/OTRGlobals.h"
-#include "soh/ImGuiUtils.h"
+#include "soh/SohGui/ImGuiUtils.h"
#include "soh/Enhancements/randomizer/logic.h"
#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
#include "soh/Enhancements/randomizer/rando_hash.h"
@@ -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/ShuffleFairies.cpp b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp
index 82db62f2a..f9cd16c4d 100644
--- a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp
+++ b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp
@@ -129,46 +129,42 @@ void ShuffleFairies_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should,
} else if (id == VB_SPAWN_GOSSIP_STONE_FAIRY) {
EnGs* gossipStone = (EnGs*)(actor);
- // If not any of the songs that normally spawn a fairy, mimic vanilla behaviour.
- if (gPlayState->msgCtx.ocarinaMode == OCARINA_MODE_01) {
- Player* player = GET_PLAYER(gPlayState);
- player->stateFlags2 |= PLAYER_STATE2_NEAR_OCARINA_ACTOR;
- return;
- } else if (gPlayState->msgCtx.unk_E3F2 != OCARINA_SONG_LULLABY &&
- gPlayState->msgCtx.unk_E3F2 != OCARINA_SONG_SARIAS &&
- gPlayState->msgCtx.unk_E3F2 != OCARINA_SONG_EPONAS &&
- gPlayState->msgCtx.unk_E3F2 != OCARINA_SONG_SUNS &&
- gPlayState->msgCtx.unk_E3F2 != OCARINA_SONG_TIME &&
- gPlayState->msgCtx.unk_E3F2 != OCARINA_SONG_STORMS &&
- gPlayState->msgCtx.ocarinaMode != OCARINA_MODE_04) {
- return;
- }
+ // Mimic vanilla behaviour, only go into this path if song played is one of the ones normally spawning a fairy.
+ // Otherwise fall back to vanilla behaviour.
+ if (gPlayState->msgCtx.ocarinaMode == OCARINA_MODE_04 &&
+ (gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_LULLABY ||
+ gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_SARIAS ||
+ gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_EPONAS ||
+ gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_SUNS ||
+ gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_TIME ||
+ gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS)) {
- int32_t params = (gPlayState->sceneNum == SCENE_GROTTOS) ? Grotto_CurrentGrotto() : 0;
- // Distinguish storms fairies from the normal song fairies
- if (gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS) {
- params |= 0x1000;
- }
+ int32_t params = (gPlayState->sceneNum == SCENE_GROTTOS) ? Grotto_CurrentGrotto() : 0;
+ // Distinguish storms fairies from the normal song fairies
+ if (gPlayState->msgCtx.unk_E3F2 == OCARINA_SONG_STORMS) {
+ params |= 0x1000;
+ }
- // Combine actor + song params with position to get the right randomizer check
- params = TWO_ACTOR_PARAMS(params, (int32_t)gossipStone->actor.world.pos.z);
+ // Combine actor + song params with position to get the right randomizer check
+ params = TWO_ACTOR_PARAMS(params, (int32_t)gossipStone->actor.world.pos.z);
- // Check if a fairy already exists with the same identity as the stone is trying to spawn.
- // Because the gossip stone code runs several times after playing the song, we need to
- // stop spawning the vanilla fairy as well when these fairies exist, otherwise both
- // the randomized and the vanilla fairy will spawn. When the randomized fairy is already
- // collected, the vanilla code will handle that part automatically.
- FairyIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params);
- if (!ShuffleFairies_FairyExists(fairyIdentity)) {
- if (ShuffleFairies_SpawnFairy(gossipStone->actor.world.pos.x, gossipStone->actor.world.pos.y,
- gossipStone->actor.world.pos.z, params)) {
- Audio_PlayActorSound2(&gossipStone->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY);
- // Set vanilla check for fairy spawned so it doesn't spawn the vanilla fairy afterwards as well.
- gossipStone->unk_19D = 0;
+ // Check if a fairy already exists with the same identity as the stone is trying to spawn.
+ // Because the gossip stone code runs several times after playing the song, we need to
+ // stop spawning the vanilla fairy as well when these fairies exist, otherwise both
+ // the randomized and the vanilla fairy will spawn. When the randomized fairy is already
+ // collected, the vanilla code will handle that part automatically.
+ FairyIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params);
+ if (!ShuffleFairies_FairyExists(fairyIdentity)) {
+ if (ShuffleFairies_SpawnFairy(gossipStone->actor.world.pos.x, gossipStone->actor.world.pos.y,
+ gossipStone->actor.world.pos.z, params)) {
+ Audio_PlayActorSound2(&gossipStone->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY);
+ // Set vanilla check for fairy spawned so it doesn't spawn the vanilla fairy afterwards as well.
+ gossipStone->unk_19D = 0;
+ *should = false;
+ }
+ } else {
*should = false;
}
- } else {
- *should = false;
}
}
}
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/adult_trade_shuffle.c b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c
index c1acc100b..4bf481d2a 100644
--- a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c
+++ b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c
@@ -4,7 +4,7 @@
#include "macros.h"
void Randomizer_ConsumeAdultTradeItem(PlayState* play, u8 itemId) {
- gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(itemId);
+ gSaveContext.ship.quest.data.randomizer.adultTradeItems &= ~ADULT_TRADE_FLAG(itemId);
Inventory_ReplaceItem(play, itemId, Randomizer_GetNextAdultTradeItem());
}
@@ -13,7 +13,7 @@ u8 Randomizer_GetNextAdultTradeItem() {
u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG;
for (int i = 0; i < numTradeItems; i++) {
u8 tradeIndex = (currentTradeItemIndex + i + 1) % numTradeItems;
- if (gSaveContext.adultTradeItems & (1 << tradeIndex)) {
+ if (gSaveContext.ship.quest.data.randomizer.adultTradeItems & (1 << tradeIndex)) {
return ITEM_POCKET_EGG + tradeIndex;
}
}
@@ -25,7 +25,7 @@ u8 Randomizer_GetPrevAdultTradeItem() {
u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG;
for (int i = 0; i < numTradeItems; i++) {
u8 tradeIndex = (currentTradeItemIndex - i - 1 + numTradeItems) % numTradeItems;
- if (gSaveContext.adultTradeItems & (1 << tradeIndex)) {
+ if (gSaveContext.ship.quest.data.randomizer.adultTradeItems & (1 << tradeIndex)) {
return ITEM_POCKET_EGG + tradeIndex;
}
}
diff --git a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h
index 13d905026..f9894cf4e 100644
--- a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h
+++ b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h
@@ -4,7 +4,7 @@
#include
#define ADULT_TRADE_FLAG(itemId) (1 << (itemId - ITEM_POCKET_EGG))
-#define PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(itemID) (gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(itemID))
+#define PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(itemID) (IS_RANDO && gSaveContext.ship.quest.data.randomizer.adultTradeItems & ADULT_TRADE_FLAG(itemID))
void Randomizer_ConsumeAdultTradeItem(PlayState* play, u8 itemId);
u8 Randomizer_GetNextAdultTradeItem();
diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp
index 7b33df771..79a60cc70 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,20 @@ 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::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 +456,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..cc71609eb 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,17 @@ 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& 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 +112,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 +175,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 bd7f92a84..0a89e4dae 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -16,32 +16,84 @@
#include "objects/object_gi_fire/object_gi_fire.h"
#include "objects/object_fish/object_fish.h"
#include "objects/object_toki_objects/object_toki_objects.h"
+#include "objects/object_gi_bomb_2/object_gi_bomb_2.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
+#include "objects/object_goma/object_goma.h"
+#include "objects/object_kingdodongo/object_kingdodongo.h"
+#include "objects/object_bv/object_bv.h"
+#include "objects/object_gnd/object_gnd.h"
+#include "objects/object_fd/object_fd.h"
+#include "objects/object_mo/object_mo.h"
+#include "objects/object_sst/object_sst.h"
+#include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
+#include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h"
+#include "objects/object_tw/object_tw.h"
+#include "objects/object_ganon2/object_ganon2.h"
#include "soh_assets.h"
+#include "dungeon.h"
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
extern "C" {
+extern PlayState* gPlayState;
extern SaveContext gSaveContext;
}
+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.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) {
- s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GERUDO_FORTRESS_SMALL_KEY ?
- Randomizer_GetSettingValue(RSK_GERUDO_KEYS) != RO_GERUDO_KEYS_VANILLA :
- DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY);
- s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MatchKeyColors"), 1);
- s16 color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_SMALL_KEY;
- s16 colors[9][3] = {
- { 4, 195, 46 }, // Forest Temple
- { 237, 95, 95 }, // Fire Temple
- { 85, 180, 223 }, // Water Temple
- { 222, 158, 47 }, // Spirit Temple
- { 126, 16, 177 }, // Shadow Temple
- { 227, 110, 255 }, // Bottom of the Well
- { 221, 212, 60 }, // Gerudo Training Ground
- { 255, 255, 255 }, // Thieves' Hideout
- { 80, 80, 80 } // Ganon's Castle
+ s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 0);
+ int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_SMALL_KEY;
+
+ Gfx* customIconDLs[] = {
+ (Gfx*)gSmallKeyIconForestTempleDL,
+ (Gfx*)gSmallKeyIconFireTempleDL,
+ (Gfx*)gSmallKeyIconWaterTempleDL,
+ (Gfx*)gSmallKeyIconSpiritTempleDL,
+ (Gfx*)gSmallKeyIconShadowTempleDL,
+ (Gfx*)gSmallKeyIconBottomoftheWellDL,
+ (Gfx*)gSmallKeyIconGerudoTrainingGroundDL,
+ (Gfx*)gSmallKeyIconGerudoFortressDL,
+ (Gfx*)gSmallKeyIconGanonsCastleDL,
+ (Gfx*)gSmallKeyIconTreasureChestGameDL,
};
OPEN_DISPS(play->state.gfxCtx);
@@ -51,14 +103,28 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
- if (isColoredKeysEnabled) {
- gDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
+ Color_RGB8 keyColor = { 255, 255, 255 };
+ keyColor = CVarGetColor24(SmallBodyCvarValue[slot], keyColor);
+
+ if (isCustomKeysEnabled) {
+ gDPSetEnvColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gSmallKeyCustomDL);
+
+ Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+
+ Color_RGB8 emblemColor = SmallEmblemDefaultValue[slot];
+ emblemColor = CVarGetColor24(SmallEmblemCvarValue[slot], emblemColor);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ gDPSetEnvColor(POLY_XLU_DISP++, emblemColor.r, emblemColor.g, emblemColor.b, 255);
+
+ gSPDisplayList(POLY_XLU_DISP++, customIconDLs[slot]);
+
+ } else {
+ gDPSetGrayscaleColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
gSPGrayscale(POLY_OPA_DISP++, true);
- }
-
- gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
-
- if (isColoredKeysEnabled) {
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
gSPGrayscale(POLY_OPA_DISP++, false);
}
@@ -109,19 +175,25 @@ extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEnt
}
extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry) {
- s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GANONS_CASTLE_BOSS_KEY ?
- DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY) :
- DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY);
- s8 isColoredKeysEnabled = keysCanBeOutsideDungeon && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MatchKeyColors"), 1);
- s16 color_slot;
- color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY;
- s16 colors[6][3] = {
- { 4, 195, 46 }, // Forest Temple
- { 237, 95, 95 }, // Fire Temple
- { 85, 180, 223 }, // Water Temple
- { 222, 158, 47 }, // Spirit Temple
- { 126, 16, 177 }, // Shadow Temple
- { 210, 0, 0 } // Ganon's Castle
+ s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 1);
+ s16 slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_BOSS_KEY;
+
+ std::string CvarValue[6] = {
+ "gCosmetics.Key.ForestBoss",
+ "gCosmetics.Key.FireBoss",
+ "gCosmetics.Key.WaterBoss",
+ "gCosmetics.Key.SpiritBoss",
+ "gCosmetics.Key.ShadowBoss",
+ "gCosmetics.Key.GanonsBoss",
+ };
+
+ Gfx* CustomdLists[] = {
+ (Gfx*)gBossKeyIconForestTempleDL,
+ (Gfx*)gBossKeyIconFireTempleDL,
+ (Gfx*)gBossKeyIconWaterTempleDL,
+ (Gfx*)gBossKeyIconSpiritTempleDL,
+ (Gfx*)gBossKeyIconShadowTempleDL,
+ (Gfx*)gBossKeyIconGanonsCastleDL,
};
OPEN_DISPS(play->state.gfxCtx);
@@ -131,15 +203,22 @@ extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEnt
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
- if (color_slot == 5 && isColoredKeysEnabled) { // Ganon's Boss Key
- gDPSetGrayscaleColor(POLY_OPA_DISP++, 80, 80, 80, 255);
- gSPGrayscale(POLY_OPA_DISP++, true);
- }
-
- gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiBossKeyDL);
-
- if (color_slot == 5 && isColoredKeysEnabled) { // Ganon's Boss Key
- gSPGrayscale(POLY_OPA_DISP++, false);
+ Color_RGB8 keyColor = { 255, 255, 0 };
+ //Supposed to use CVAR_COSMETIC but I can't figure out the syntax
+ 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] + "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);
+ gSPGrayscale(POLY_OPA_DISP++, false);
+ } else {
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiBossKeyDL);
+ }
}
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
@@ -147,62 +226,140 @@ 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);
- if (isColoredKeysEnabled) {
- gDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
- gSPGrayscale(POLY_XLU_DISP++, true);
- }
-
- gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBossKeyGemDL);
-
- if (isColoredKeysEnabled) {
- gSPGrayscale(POLY_XLU_DISP++, false);
+ Color_RGB8 gemColor = { 255, 0, 0 };
+ gemColor = CVarGetColor24((CvarValue[slot] + "Gem.Value").c_str(), gemColor);
+
+ if (isCustomKeysEnabled){
+ gDPSetEnvColor(POLY_XLU_DISP++, gemColor.r, gemColor.g, gemColor.b, 255);
+ gSPDisplayList(POLY_XLU_DISP++, CustomdLists[slot]);
+ } else {
+ 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);
+ } else {
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBossKeyGemDL);
+ }
}
CLOSE_DISPS(play->state.gfxCtx);
}
extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry) {
- s16 color_slot = getItemEntry->getItemId - RG_FOREST_TEMPLE_KEY_RING;
- s16 colors[9][3] = {
- { 4, 195, 46 }, // Forest Temple
- { 237, 95, 95 }, // Fire Temple
- { 85, 180, 223 }, // Water Temple
- { 222, 158, 47 }, // Spirit Temple
- { 126, 16, 177 }, // Shadow Temple
- { 227, 110, 255 }, // Bottom of the Well
- { 221, 212, 60 }, // Gerudo Training Ground
- { 255, 255, 255 }, // Thieves' Hideout
- { 80, 80, 80 } // Ganon's Castle
+ s8 isCustomKeysEnabled = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("CustomKeyModels"), 0);
+ int slot = getItemEntry->drawItemId - RG_FOREST_TEMPLE_KEY_RING;
+
+ Gfx* CustomIconDLs[] = {
+ (Gfx*)gKeyringIconForestTempleDL,
+ (Gfx*)gKeyringIconFireTempleDL,
+ (Gfx*)gKeyringIconWaterTempleDL,
+ (Gfx*)gKeyringIconSpiritTempleDL,
+ (Gfx*)gKeyringIconShadowTempleDL,
+ (Gfx*)gKeyringIconBottomoftheWellDL,
+ (Gfx*)gKeyringIconGerudoTrainingGroundDL,
+ (Gfx*)gKeyringIconGerudoFortressDL,
+ (Gfx*)gKeyringIconGanonsCastleDL,
+ (Gfx*)gKeyringIconTreasureChestGameDL,
+ };
+
+ Gfx* CustomKeysDLs[] = {
+ (Gfx*)gKeyringKeysForestTempleDL,
+ (Gfx*)gKeyringKeysFireTempleDL,
+ (Gfx*)gKeyringKeysWaterTempleDL,
+ (Gfx*)gKeyringKeysSpiritTempleDL,
+ (Gfx*)gKeyringKeysShadowTempleDL,
+ (Gfx*)gKeyringKeysBottomoftheWellDL,
+ (Gfx*)gKeyringKeysGerudoTrainingGroundDL,
+ (Gfx*)gKeyringKeysGerudoFortressDL,
+ (Gfx*)gKeyringKeysGanonsCastleDL,
+ (Gfx*)gKeyringKeysTreasureChestGameDL,
+ };
+
+ Gfx* CustomKeysMQDLs[] = {
+ (Gfx*)gKeyringKeysForestTempleMQDL,
+ (Gfx*)gKeyringKeysFireTempleMQDL,
+ (Gfx*)gKeyringKeysWaterTempleMQDL,
+ (Gfx*)gKeyringKeysSpiritTempleMQDL,
+ (Gfx*)gKeyringKeysShadowTempleMQDL,
+ (Gfx*)gKeyringKeysBottomoftheWellMQDL,
+ (Gfx*)gKeyringKeysGerudoTrainingGroundMQDL,
+ (Gfx*)gKeyringKeysGerudoFortressDL,
+ (Gfx*)gKeyringKeysGanonsCastleMQDL,
+ (Gfx*)gKeyringKeysTreasureChestGameDL,
+ };
+
+ //RANDOTODO make DungeonInfo static and vanilla accessible to allow all these key model data vars to be stored there.
+ //(Rando::DungeonKey)0 means the keyring is not tied to a dungeon and should not be checked for an MQ variant
+ Rando::DungeonKey SlotToDungeon[10] = {
+ Rando::FOREST_TEMPLE,
+ Rando::FIRE_TEMPLE,
+ Rando::WATER_TEMPLE,
+ Rando::SPIRIT_TEMPLE,
+ Rando::SHADOW_TEMPLE,
+ Rando::BOTTOM_OF_THE_WELL,
+ Rando::GERUDO_TRAINING_GROUND,
+ (Rando::DungeonKey)0, //Gerudo Fortress
+ Rando::GANONS_CASTLE,
+ (Rando::DungeonKey)0, //Treasure Chest Game
};
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Opa(play->state.gfxCtx);
- gDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
- gSPGrayscale(POLY_OPA_DISP++, true);
+ Color_RGB8 keyColor = { 255, 255, 255 };
+ keyColor = CVarGetColor24(SmallBodyCvarValue[slot], keyColor);
- Matrix_Scale(0.5f, 0.5f, 0.5f, MTXMODE_APPLY);
- Matrix_RotateZ(0.8f, MTXMODE_APPLY);
- Matrix_RotateX(-2.16f, MTXMODE_APPLY);
- Matrix_RotateY(-0.56f, MTXMODE_APPLY);
- Matrix_RotateZ(-0.86f, MTXMODE_APPLY);
- Matrix_Translate(28.29f, 0, 0, MTXMODE_APPLY);
- Matrix_Translate(-(3.12f * 2), -(-0.34f * 2), -(17.53f * 2), MTXMODE_APPLY);
- Matrix_RotateX(-(-0.31f * 2), MTXMODE_APPLY);
- Matrix_RotateY(-(0.19f * 2), MTXMODE_APPLY);
- Matrix_RotateZ(-(0.20f * 2), MTXMODE_APPLY);
- for (int i = 0; i < 5; i++) {
+ if (isCustomKeysEnabled) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
- G_MTX_MODELVIEW | G_MTX_LOAD);
- Matrix_Translate(3.12f, -0.34f, 17.53f, MTXMODE_APPLY);
- Matrix_RotateX(-0.31f, MTXMODE_APPLY);
- Matrix_RotateY(0.19f, MTXMODE_APPLY);
- Matrix_RotateZ(0.20f, MTXMODE_APPLY);
- gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
- }
+ G_MTX_MODELVIEW | G_MTX_LOAD);
- gSPGrayscale(POLY_OPA_DISP++, false);
+ gDPSetEnvColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
+ if (SlotToDungeon[slot] != 0 && Rando::Context::GetInstance()->GetDungeon(SlotToDungeon[slot])->IsMQ()){
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)CustomKeysMQDLs[slot]);
+ } else {
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)CustomKeysDLs[slot]);
+ }
+
+ Color_RGB8 ringColor = { 255, 255, 255 };
+ ringColor = CVarGetColor24(CVAR_COSMETIC("Key.KeyringRing.Value"), ringColor);
+ gDPSetEnvColor(POLY_OPA_DISP++, ringColor.r, ringColor.g, ringColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gKeyringRingDL);
+
+ Color_RGB8 emblemColor = SmallEmblemDefaultValue[slot];
+ emblemColor = CVarGetColor24(SmallEmblemCvarValue[slot], emblemColor);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ gDPSetEnvColor(POLY_OPA_DISP++, emblemColor.r, emblemColor.g, emblemColor.b, 255);
+
+ gSPDisplayList(POLY_OPA_DISP++, CustomIconDLs[slot]);
+ } else {
+ gDPSetGrayscaleColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
+ gSPGrayscale(POLY_OPA_DISP++, true);
+ Matrix_Scale(0.5f, 0.5f, 0.5f, MTXMODE_APPLY);
+ Matrix_RotateZ(0.8f, MTXMODE_APPLY);
+ Matrix_RotateX(-2.16f, MTXMODE_APPLY);
+ Matrix_RotateY(-0.56f, MTXMODE_APPLY);
+ Matrix_RotateZ(-0.86f, MTXMODE_APPLY);
+ Matrix_Translate(28.29f, 0, 0, MTXMODE_APPLY);
+ Matrix_Translate(-(3.12f * 2), -(-0.34f * 2), -(17.53f * 2), MTXMODE_APPLY);
+ Matrix_RotateX(-(-0.31f * 2), MTXMODE_APPLY);
+ Matrix_RotateY(-(0.19f * 2), MTXMODE_APPLY);
+ Matrix_RotateZ(-(0.20f * 2), MTXMODE_APPLY);
+ for (int i = 0; i < 5; i++) {
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ Matrix_Translate(3.12f, -0.34f, 17.53f, MTXMODE_APPLY);
+ Matrix_RotateX(-0.31f, MTXMODE_APPLY);
+ Matrix_RotateY(0.19f, MTXMODE_APPLY);
+ Matrix_RotateZ(0.20f, MTXMODE_APPLY);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
+ }
+ gSPGrayscale(POLY_OPA_DISP++, false);
+ }
CLOSE_DISPS(play->state.gfxCtx);
}
@@ -263,7 +420,7 @@ extern "C" void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getIt
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
- uint8_t current = gSaveContext.triforcePiecesCollected;
+ uint8_t current = gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected;
Matrix_Scale(0.035f, 0.035f, 0.035f, MTXMODE_APPLY);
@@ -287,7 +444,7 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
- uint8_t current = gSaveContext.triforcePiecesCollected;
+ uint8_t current = gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected;
uint8_t required = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1;
Matrix_Scale(triforcePieceScale, triforcePieceScale, triforcePieceScale, MTXMODE_APPLY);
@@ -350,8 +507,452 @@ extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItem
CLOSE_DISPS(play->state.gfxCtx);
}
+Gfx* GetEmptyDlist(GraphicsContext* gfxCtx) {
+ Gfx* dListHead;
+ Gfx* dList;
+
+ dList = dListHead = (Gfx*)Graph_Alloc(gfxCtx, sizeof(Gfx) * 1);
+
+ gSPEndDisplayList(dListHead++);
+
+ return dList;
+}
+
+extern "C" s32 OverrideLimbDrawGohma(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 255, 170, 255);
+
+ switch (limbIndex) {
+ case BOSSGOMA_LIMB_EYE:
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 63);
+ break;
+
+ case BOSSGOMA_LIMB_IRIS:
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+ break;
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+ return false;
+}
+
+#define LIMB_COUNT_GOHMA 86
+extern "C" void DrawGohma(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_GOHMA];
+ static Vec3s otherTable[LIMB_COUNT_GOHMA];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_Init(play, &skelAnime, (SkeletonHeader*)&gGohmaSkel, (AnimationHeader*)&gGohmaIdleCrouchedAnim,
+ jointTable, otherTable, LIMB_COUNT_GOHMA);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Translate(0.0f, -20.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.005f, 0.005f, 0.005f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)GetEmptyDlist(play->state.gfxCtx));
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, OverrideLimbDrawGohma, NULL, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+#define LIMB_COUNT_KING_DODONGO 49
+extern "C" void DrawKingDodongo(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_KING_DODONGO];
+ static Vec3s otherTable[LIMB_COUNT_KING_DODONGO];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_Init(play, &skelAnime, (SkeletonHeader*)&object_kingdodongo_Skel_01B310,
+ (AnimationHeader*)&object_kingdodongo_Anim_00F0D8, jointTable, otherTable,
+ LIMB_COUNT_KING_DODONGO);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Translate(0.0f, -20.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.003f, 0.003f, 0.003f, MTXMODE_APPLY);
+
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, NULL, NULL, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+extern "C" s32 OverrideLimbDrawBarinade(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ s16 unk_1AC = play->gameplayFrames * 0xC31;
+ f32 unk_1A0 = 0.0f;
+ f32 unk_1A4 = 0.0f;
+
+ if (limbIndex == 20) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gSPSegment(POLY_OPA_DISP++, 0x08,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 8, 16, 1, 0,
+ (play->gameplayFrames * -2) % 64, 16, 16));
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 200);
+ Matrix_RotateX(-M_PI / 2, MTXMODE_APPLY);
+ } else if ((limbIndex >= 10) && (limbIndex < 20)) {
+ rot->x -= 0x4000;
+ *dList = NULL;
+ } else if (limbIndex == 6) {
+ unk_1A4 = (Math_SinS(unk_1AC) * 0.05f) + 1.0f;
+ Matrix_Scale(unk_1A4, unk_1A4, unk_1A4, MTXMODE_APPLY);
+ } else if (limbIndex == 61) {
+ unk_1A0 = (Math_CosS(unk_1AC) * 0.1f) + 1.0f;
+ Matrix_Scale(unk_1A0, unk_1A0, unk_1A0, MTXMODE_APPLY);
+ } else if (limbIndex == 7) {
+ rot->x -= 0xCCC;
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+ return false;
+}
+
+extern "C" void PostLimbDrawBarinade(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ if (limbIndex == 25) {
+ gSPSegment(POLY_XLU_DISP++, 0x09,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (play->gameplayFrames * 10) % 128, 16, 32, 1,
+ 0, (play->gameplayFrames * 5) % 128, 16, 32));
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gBarinadeDL_008D70);
+ } else if ((limbIndex >= 10) && (limbIndex < 20)) {
+ if (((limbIndex >= 16) || (limbIndex == 10))) {
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gBarinadeDL_008BB8);
+ } else if ((limbIndex >= 11)) {
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gBarinadeDL_008BB8);
+ }
+ } else if ((*dList != NULL) && (limbIndex >= 29) && (limbIndex < 56)) {
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, *dList);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+#define LIMB_COUNT_BARINADE 64
+extern "C" void DrawBarinade(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_BARINADE];
+ static Vec3s otherTable[LIMB_COUNT_BARINADE];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_Init(play, &skelAnime, (SkeletonHeader*)&gBarinadeBodySkel, (AnimationHeader*)&gBarinadeBodyAnim,
+ jointTable, otherTable, LIMB_COUNT_BARINADE);
+
+ // Freeze barniade on the last frame
+ f32 lastFrame = Animation_GetLastFrame((AnimationHeader*)&gBarinadeBodyAnim);
+ Animation_Change(&skelAnime, (AnimationHeader*)&gBarinadeBodyAnim, 1.0f, lastFrame, lastFrame, ANIMMODE_ONCE,
+ 0.0f);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+ Matrix_Translate(0.0f, -25.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.03f, 0.03f, 0.03f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_OPA_DISP++, 0x08,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 8, 16, 1, 0, (play->gameplayFrames * -10) % 16,
+ 16, 16));
+ gSPSegment(POLY_OPA_DISP++, 0x09,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, (play->gameplayFrames * -10) % 32, 16, 0x20, 1, 0,
+ (play->gameplayFrames * -5) % 32, 16, 32));
+
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, OverrideLimbDrawBarinade, PostLimbDrawBarinade, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+#define LIMB_COUNT_PHANTOM_GANON 26
+extern "C" void DrawPhantomGanon(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_PHANTOM_GANON];
+ static Vec3s otherTable[LIMB_COUNT_PHANTOM_GANON];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_Init(play, &skelAnime, (SkeletonHeader*)&gPhantomGanonSkel,
+ (AnimationHeader*)&gPhantomGanonNeutralAnim, jointTable, otherTable, LIMB_COUNT_PHANTOM_GANON);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Translate(0.0f, 10.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.007f, 0.007f, 0.007f, MTXMODE_APPLY);
+
+ // Eye color
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+ gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)GetEmptyDlist(play->state.gfxCtx));
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, NULL, NULL, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+#define LIMB_COUNT_VOLVAGIA 7
+extern "C" void DrawVolvagia(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_VOLVAGIA];
+ static Vec3s otherTable[LIMB_COUNT_VOLVAGIA];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_Init(play, &skelAnime, (SkeletonHeader*)&gVolvagiaHeadSkel,
+ (AnimationHeader*)&gVolvagiaHeadEmergeAnim, jointTable, otherTable, LIMB_COUNT_VOLVAGIA);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Scale(0.007f, 0.007f, 0.007f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_OPA_DISP++, 0x09, (uintptr_t)gVolvagiaEyeOpenTex);
+ gSPSegment(POLY_OPA_DISP++, 0x08,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, play->state.frames * 4, 120, 0x20, 0x20, 1,
+ play->state.frames * 3, play->state.frames * -2, 0x20, 0x20));
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, NULL, NULL, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+extern "C" void DrawMorpha(PlayState* play) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+
+ Matrix_Scale(0.015f, 0.015f, 0.015f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, play->state.frames * 3, play->state.frames * 3, 32,
+ 32, 1, play->state.frames * -3, play->state.frames * -3, 32, 32));
+
+ gSPSegment(POLY_XLU_DISP++, 0x09,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, play->state.frames * 3, 0, 32, 32, 1, 0,
+ play->state.frames * -5, 32, 32));
+
+ Matrix_RotateX(play->state.frames * 0.1f, MTXMODE_APPLY);
+ Matrix_RotateZ(play->state.frames * 0.16f, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, 255);
+
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gMorphaCoreMembraneDL);
+
+ gDPPipeSync(POLY_XLU_DISP++);
+
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 220, 255, 128);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, 255);
+
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gMorphaCoreNucleusDL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+#define LIMB_COUNT_BONGO_BONGO 27
+extern "C" void DrawBongoBongo(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_BONGO_BONGO];
+ static Vec3s otherTable[LIMB_COUNT_BONGO_BONGO];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_InitFlex(play, &skelAnime, (FlexSkeletonHeader*)&gBongoLeftHandSkel,
+ (AnimationHeader*)&gBongoLeftHandIdleAnim, jointTable, otherTable, LIMB_COUNT_BONGO_BONGO);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Translate(0.0f, -25.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)GetEmptyDlist(play->state.gfxCtx));
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x80, 0x80, 255, 255, 255, 255);
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, NULL, NULL, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+extern "C" s32 OverrideLimbDrawKotake(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
+ if (limbIndex == 21) { // Head
+ *dList = (Gfx*)gTwinrovaKotakeHeadDL;
+ }
+
+ return false;
+}
+
+extern "C" void PostLimbDrawKotake(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ if (limbIndex == 21) { // Head
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gTwinrovaKotakeIceHairDL);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+#define LIMB_COUNT_KOTAKE 27
+extern "C" void DrawKotake(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_KOTAKE];
+ static Vec3s otherTable[LIMB_COUNT_KOTAKE];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_InitFlex(play, &skelAnime, (FlexSkeletonHeader*)&gTwinrovaKotakeSkel,
+ (AnimationHeader*)&gTwinrovaKotakeKoumeFlyAnim, jointTable, otherTable, LIMB_COUNT_KOTAKE);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+ Matrix_Translate(0.0f, -10.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_OPA_DISP++, 10, (uintptr_t)gTwinrovaKotakeKoumeEyeOpenTex);
+ gSPSegment(POLY_XLU_DISP++, 10, (uintptr_t)gTwinrovaKotakeKoumeEyeOpenTex);
+ gSPSegment(POLY_XLU_DISP++, 8,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0 & 0x7F, 0 & 0x7F, 0x20, 0x20, 1,
+ play->state.frames & 0x7F, (play->state.frames * -7) & 0xFF, 0x20, 0x40));
+
+ gSPSegment(POLY_XLU_DISP++, 9,
+ (uintptr_t)Gfx_TexScroll(play->state.gfxCtx, 0 & 0x7F, play->state.frames & 0xFF, 0x20, 0x40));
+
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, OverrideLimbDrawKotake, PostLimbDrawKotake, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+extern "C" s32 OverrideLimbDrawGanon(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ if (limbIndex >= 42) { // Tail
+ // Brighten up tail
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+ return false;
+}
+
+#define LIMB_COUNT_GANON 47
+extern "C" void DrawGanon(PlayState* play) {
+ static bool initialized = false;
+ static SkelAnime skelAnime;
+ static Vec3s jointTable[LIMB_COUNT_GANON];
+ static Vec3s otherTable[LIMB_COUNT_GANON];
+ static u32 lastUpdate = 0;
+
+ if (!initialized) {
+ initialized = true;
+ SkelAnime_InitFlex(play, &skelAnime, (FlexSkeletonHeader*)&gGanonSkel, (AnimationHeader*)&gGanonGuardIdleAnim,
+ jointTable, otherTable, LIMB_COUNT_GANON);
+ }
+
+ if (lastUpdate != play->state.frames) {
+ lastUpdate = play->state.frames;
+ SkelAnime_Update(&skelAnime);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Translate(0.0f, -33.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.005f, 0.005f, 0.005f, MTXMODE_APPLY);
+
+ gSPSegment(POLY_OPA_DISP++, 0x08, (uintptr_t)gGanonEyeOpenTex);
+
+ SkelAnime_DrawSkeletonOpa(play, &skelAnime, OverrideLimbDrawGanon, NULL, NULL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
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
@@ -361,42 +962,75 @@ extern "C" void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEn
{ 85, 180, 223 }, // Morpha
{ 126, 16, 177 }, // Bongo Bongo
{ 222, 158, 47 }, // Twinrova
- { 80, 80, 80 }, // Ganon/Dorf
+ { 150, 150, 150 }, // Ganon/Dorf
};
- OPEN_DISPS(play->state.gfxCtx);
+ // Draw the blue fire DL but coloured to the boss soul.
+ OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+ gSPSegment(POLY_XLU_DISP++, 8,
+ (uintptr_t)Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0 * (play->state.frames * 0),
+ 0 * (play->state.frames * 0), 16, 32, 1, 1 * (play->state.frames * 1),
+ -1 * (play->state.frames * 8), 16, 32));
+ Matrix_Push();
+ Matrix_Translate(0.0f, -70.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
+ Matrix_ReplaceRotation(&play->billboardMtxF);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
- if (slot == 8) { // For Ganon only...
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, 255);
- } else {
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255);
- }
- gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gBossSoulSkullDL);
-
- if (slot >= 0) {
- Gfx_SetupDL_25Xlu(play->state.gfxCtx);
- gSPSegment(POLY_XLU_DISP++, 8, (uintptr_t)Gfx_TwoTexScroll(
- play->state.gfxCtx, 0, 0 * (play->state.frames * 0),
- 0 * (play->state.frames * 0), 16, 32, 1, 1 * (play->state.frames * 1),
- -1 * (play->state.frames * 8), 16, 32
- ));
- Matrix_Push();
- Matrix_Translate(0.0f, -70.0f, 0.0f, MTXMODE_APPLY);
- Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
- Matrix_ReplaceRotation(&play->billboardMtxF);
- gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
- G_MTX_MODELVIEW | G_MTX_LOAD);
- gDPSetGrayscaleColor(POLY_XLU_DISP++, flameColors[slot][0], flameColors[slot][1], flameColors[slot][2], 255);
- gSPGrayscale(POLY_XLU_DISP++, true);
- gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBlueFireFlameDL);
- gSPGrayscale(POLY_XLU_DISP++, false);
- Matrix_Pop();
- }
-
+ gDPSetGrayscaleColor(POLY_XLU_DISP++, flameColors[slot][0], flameColors[slot][1], flameColors[slot][2], 255);
+ gSPGrayscale(POLY_XLU_DISP++, true);
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiBlueFireFlameDL);
+ gSPGrayscale(POLY_XLU_DISP++, false);
+ Matrix_Pop();
CLOSE_DISPS(play->state.gfxCtx);
+ // Draw the generic boss soul model
+ if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("SimplerBossSoulModels"), 0)) {
+ OPEN_DISPS(play->state.gfxCtx);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ if (slot == 8) { // For Ganon only...
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 255);
+ } else {
+ gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 255);
+ }
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gBossSoulSkullDL);
+ CLOSE_DISPS(play->state.gfxCtx);
+ // Draw the boss' skeleton
+ } else {
+ switch (slot) {
+ case 0: // Gohma
+ DrawGohma(play);
+ break;
+ case 1: // King Dodongo
+ DrawKingDodongo(play);
+ break;
+ case 2: // Barinade
+ DrawBarinade(play);
+ break;
+ case 3: // Phantom Ganon
+ DrawPhantomGanon(play);
+ break;
+ case 4: // Volvagia
+ DrawVolvagia(play);
+ break;
+ case 5: // Morpha
+ DrawMorpha(play);
+ break;
+ case 6: // Bongo Bongo
+ DrawBongoBongo(play);
+ break;
+ case 7: // Twinrova
+ DrawKotake(play);
+ break;
+ case 8: // Ganon
+ DrawGanon(play);
+ break;
+ default:
+ break;
+ }
+ }
}
extern "C" void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry) {
@@ -545,52 +1179,68 @@ extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getI
CLOSE_DISPS(play->state.gfxCtx);
}
-int skeletonKeyHue = 0;
-
-// Runs every frame to update rainbow hue, taken from CosmeticsEditor.cpp.
-Color_RGBA8 GetSkeletonKeyColor() {
- float rainbowSpeed = 0.6f;
-
- float frequency = 2 * M_PI / (360 * rainbowSpeed);
- Color_RGBA8 color;
- color.r = sin(frequency * skeletonKeyHue + 0) * 127 + 128;
- color.g = sin(frequency * skeletonKeyHue + (2 * M_PI / 3)) * 127 + 128;
- color.b = sin(frequency * skeletonKeyHue + (4 * M_PI / 3)) * 127 + 128;
- color.a = 255;
-
- skeletonKeyHue++;
- if (skeletonKeyHue >= (360 * rainbowSpeed)) skeletonKeyHue = 0;
-
- return color;
-}
-
-int skeletonKeyRotation = 0;
extern "C" void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry) {
OPEN_DISPS(play->state.gfxCtx);
- Color_RGBA8 color = GetSkeletonKeyColor();
-
Gfx_SetupDL_25Opa(play->state.gfxCtx);
- skeletonKeyRotation += 1;
-
- if (skeletonKeyRotation > 40) {
- skeletonKeyRotation -= 80;
- }
-
- Matrix_RotateZ(M_PI / 40 * skeletonKeyRotation, MTXMODE_APPLY);
- Matrix_RotateY(M_PI / 40 * skeletonKeyRotation, MTXMODE_APPLY);
-
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
G_MTX_MODELVIEW | G_MTX_LOAD);
- gDPSetGrayscaleColor(POLY_OPA_DISP++, color.r, color.g, color.b, color.a);
- gSPGrayscale(POLY_OPA_DISP++, true);
-
- gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiSmallKeyDL);
-
- gSPGrayscale(POLY_OPA_DISP++, false);
+ Color_RGB8 keyColor = { 255, 255, 170 };
+ keyColor = CVarGetColor24(CVAR_COSMETIC("Key.Skeleton.Value"), keyColor);
+ gDPSetEnvColor(POLY_OPA_DISP++, keyColor.r, keyColor.g, keyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gSkeletonKeyDL);
CLOSE_DISPS(play->state.gfxCtx);
-}
\ No newline at end of file
+}
+
+extern "C" void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry){
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_26Opa(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+
+ Color_RGB8 maskColor = { 0, 100, 150 };
+ maskColor = CVarGetColor24(CVAR_COSMETIC("Equipment.ChuFace.Value"), maskColor);
+ gDPSetEnvColor(POLY_OPA_DISP++, maskColor.r, maskColor.g, maskColor.b, 255);
+
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gBombchuBagMaskDL);
+
+ Color_RGB8 bodyColor = { 180, 130, 50 };
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.ChuBody.Value"), bodyColor);
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gBombchuBagBodyDL);
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+extern "C" void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry) {
+ if(IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOMBCHU_BAG)){
+ Randomizer_DrawBombchuBag(play, getItemEntry);
+ } else {
+ OPEN_DISPS(play->state.gfxCtx);
+ Gfx_SetupDL_26Opa(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiBombchuDL);
+ 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 538494685..3fc5c86b4 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -23,6 +23,9 @@ void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry);
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 1e28aa2c3..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 {
@@ -536,10 +532,10 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
// The player should be able to get back to ToT after going through time, without having collected any items
// This is important to ensure that the player never loses access to the pedestal after going through time
- if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD && !RegionTable(RR_TEMPLE_OF_TIME)->Adult()) {
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) && !RegionTable(RR_TEMPLE_OF_TIME)->Adult()) {
SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed\n");
return false;
- } else if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_ADULT &&
+ } else if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) &&
!RegionTable(RR_TEMPLE_OF_TIME)->Child()) {
SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed\n");
return false;
@@ -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 f3ff89d70..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
@@ -440,7 +440,7 @@ namespace Rando {
// Reset fish group counter when the group gets culled
if (actor->id == ACTOR_OBJ_MURE && gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && fishGroupCounter > 0 &&
- !(actor->flags & ACTOR_FLAG_UPDATE_WHILE_CULLED) && fs->GetOverworldFishShuffled()) {
+ !(actor->flags & ACTOR_FLAG_UPDATE_CULLING_DISABLED) && fs->GetOverworldFishShuffled()) {
fishGroupCounter = 0;
}
}
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 409fa45d1..e323e810a 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -12,7 +12,7 @@
#include "soh/Enhancements/randomizer/ShuffleFreestanding.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
-#include "soh/ImGuiUtils.h"
+#include "soh/SohGui/ImGuiUtils.h"
#include "soh/Notification/Notification.h"
#include "soh/SaveManager.h"
#include "soh/Enhancements/randomizer/ShuffleFairies.h"
@@ -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,11 +273,14 @@ 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));
} else {
+ iceTrapScale = 0.0f;
randomizerQueuedCheck = rc;
randomizerQueuedItemEntry = getItemEntry;
SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, static_cast(rc));
@@ -405,7 +408,8 @@ void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) {
f32 mtxScale = CVarGetFloat(CVAR_ENHANCEMENT("TimeSavers.SkipGetItemAnimationScale"), 10.0f);
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItemEntry randoItem = enItem00->itemEntry;
- if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) {
+ if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) &&
+ enItem00->actor.params != ITEM00_SOH_GIVE_ITEM_ENTRY) {
randoItem = GET_ITEM_MYSTERY;
}
EnItem00_CustomItemsParticles(&enItem00->actor, play, randoItem);
@@ -643,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);
@@ -712,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);
}
@@ -1010,7 +1014,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
Item_Give(gPlayState, item00->itemEntry.itemId);
} else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) {
if (item00->itemEntry.getItemId == RG_ICE_TRAP) {
- gSaveContext.pendingIceTrapCount++;
+ gSaveContext.ship.pendingIceTrapCount++;
} else {
Randomizer_Item_Give(gPlayState, item00->itemEntry);
}
@@ -1112,14 +1116,14 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
enJs->actor.parent = NULL;
enJs->actor.textId = TEXT_CARPET_SALESMAN_ARMS_DEALER;
enJs->actionFunc = (EnJsActionFunc)func_80A890C0;
- enJs->actor.flags |= ACTOR_FLAG_WILL_TALK;
+ enJs->actor.flags |= ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED;
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN);
*should = true;
}
break;
}
case VB_GIVE_BOMBCHUS_FROM_CARPET_SALESMAN: {
- *should = RAND_GET_OPTION(RSK_BOMBCHUS_IN_LOGIC) == false || INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU;
+ *should = RAND_GET_OPTION(RSK_BOMBCHU_BAG) == false || INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU;
break;
}
case VB_CHECK_RANDO_PRICE_OF_MEDIGORON: {
@@ -1195,7 +1199,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
Flags_SetItemGetInf(ITEMGETINF_30);
granny->actor.textId = 0x504F;
granny->actionFunc = (EnDsActionFunc)EnDs_TalkAfterGiveOddPotion;
- granny->actor.flags &= ~ACTOR_FLAG_PLAYER_TALKED_TO;
+ granny->actor.flags &= ~ACTOR_FLAG_TALK;
*should = false;
break;
}
@@ -1533,7 +1537,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
case VB_BE_ABLE_TO_PLAY_BOMBCHU_BOWLING: {
// Only check for bomb bag when bombchus aren't in logic
// and only check for bombchus when bombchus are in logic
- *should = INV_CONTENT((RAND_GET_OPTION(RSK_BOMBCHUS_IN_LOGIC) ? ITEM_BOMBCHU : ITEM_BOMB)) != ITEM_NONE;
+ *should = INV_CONTENT((RAND_GET_OPTION(RSK_BOMBCHU_BAG) ? ITEM_BOMBCHU : ITEM_BOMB)) != ITEM_NONE;
break;
}
case VB_SHOULD_CHECK_FOR_FISHING_RECORD: {
@@ -1585,7 +1589,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
case VB_TRADE_TIMER_EYEDROPS:{
EnMk* enMk = va_arg(args, EnMk*);
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG);
- enMk->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
+ enMk->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED;
enMk->actionFunc = EnMk_Wait;
enMk->flags |= 1;
*should = false;
@@ -1631,6 +1635,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
}
break;
}
+ case VB_HEALTH_METER_BE_CRITICAL: {
+ if (gSaveContext.health == gSaveContext.healthCapacity) {
+ *should = false;
+ }
+ break;
+ }
case VB_FREEZE_ON_SKULL_TOKEN:
case VB_TRADE_TIMER_ODD_MUSHROOM:
case VB_TRADE_TIMER_FROG:
@@ -2362,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;
@@ -2392,7 +2404,7 @@ void RandomizerRegisterHooks() {
GameInteractor::Instance->UnregisterGameHook(shufflePotsOnActorInitHook);
GameInteractor::Instance->UnregisterGameHook(shufflePotsOnVanillaBehaviorHook);
- GameInteractor::Instance->UnregisterGameHook(shuffleFreestandingOnVanillaBehaviorHook);
+ GameInteractor::Instance->UnregisterGameHook(shuffleFreestandingOnVanillaBehaviorHook);
onFlagSetHook = 0;
onSceneFlagSetHook = 0;
diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp
index 5f94ad6e4..6f0309223 100644
--- a/soh/soh/Enhancements/randomizer/item.cpp
+++ b/soh/soh/Enhancements/randomizer/item.cpp
@@ -340,13 +340,11 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio
break;
case RG_PROGRESSIVE_BOMBCHUS:
if (logic->CurrentInventory(ITEM_BOMBCHU) == ITEM_NONE) {
- actual = RG_BOMBCHU_20;
+ actual = RG_BOMBCHU_BAG;
} else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) {
actual = RG_BOMBCHU_INF;
- } else if (logic->GetAmmo(ITEM_BOMBCHU) < 5) {
- actual = RG_BOMBCHU_10;
} else {
- actual = RG_BOMBCHU_5;
+ actual = RG_BOMBCHU_10;
}
break;
default:
@@ -385,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 ||
@@ -398,7 +396,7 @@ bool Item::IsMajorItem() const {
}
if ((randomizerGet == RG_BOMBCHU_5 || randomizerGet == RG_BOMBCHU_10 || randomizerGet == RG_BOMBCHU_20) &&
- !ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC)) {
+ !ctx->GetOption(RSK_BOMBCHU_BAG)) {
return false;
}
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 2fbcc0ccc..0b94aab39 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -66,7 +66,7 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, true);
itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, true);
itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, true);
- itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true);
+ itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, true);
itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, true);
itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, true);
itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, true);
@@ -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);
@@ -178,6 +226,8 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
+ itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
// Dungeon Rewards
itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
@@ -208,6 +258,7 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_BOMBCHU_5] = Item(RG_BOMBCHU_5, Text{ "Bombchus (5)", "Missiles (5)", "Krabbelminen (5)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, LOGIC_BOMBCHUS, RHT_BOMBCHUS_5, ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBCHU_10] = Item(RG_BOMBCHU_10, Text{ "Bombchus (10)", "Missiles (10)", "Krabbelminen (10)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, LOGIC_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBCHU_20] = Item(RG_BOMBCHU_20, Text{ "Bombchus (20)", "Missiles (20)", "Krabbelminen (20)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, LOGIC_BOMBCHUS, RHT_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
+ itemTable[RG_BOMBCHU_20].SetCustomDrawFunc(Randomizer_DrawBombchuBagInLogic);
itemTable[RG_ARROWS_5] = Item(RG_ARROWS_5, Text{ "Arrows (5)", "Flèches (5)", "Pfeile (5)" }, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, LOGIC_NONE, RHT_ARROWS_5, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_ARROWS_10] = Item(RG_ARROWS_10, Text{ "Arrows (10)", "Flèches (10)", "Pfeile (10)" }, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, LOGIC_NONE, RHT_ARROWS_10, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_ARROWS_30] = Item(RG_ARROWS_30, Text{ "Arrows (30)", "Flèches (30)", "Pfeile (30)" }, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, LOGIC_NONE, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
@@ -288,6 +339,9 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
+ itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
+
itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "Sac de Graines Infinis", "Unendliche Samentasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
@@ -295,6 +349,7 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "Noix Mojo Infinies", "Unendliche Nuß-Kapazität" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "Magie Infinie", "Unendliches Magisches Maß" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "Missiles Teigneux Infinis", "Unendliche Krabbelminen" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
+ itemTable[RG_BOMBCHU_INF].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "Clé Squelette", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
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 7c9cf7e7f..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()->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;
}
@@ -438,13 +438,13 @@ namespace Regions {
}
if (/*Settings::HasNightStart TODO:: Randomize Starting Time*/ false) {
- if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
RegionTable(RR_ROOT)->childNight = true;
} else {
RegionTable(RR_ROOT)->adultNight = true;
}
} else {
- if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
RegionTable(RR_ROOT)->childDay = true;
} else {
RegionTable(RR_ROOT)->adultDay = true;
@@ -465,13 +465,13 @@ namespace Regions {
}
if (/*Settings::HasNightStart TODO:: Randomize Starting Time*/ false) {
- if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
RegionTable(RR_ROOT)->childNight = true;
} else {
RegionTable(RR_ROOT)->adultNight = true;
}
} else {
- if (ctx->GetSettings()->ResolvedStartingAge() == RO_AGE_CHILD) {
+ if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
RegionTable(RR_ROOT)->childDay = true;
} else {
RegionTable(RR_ROOT)->adultDay = true;
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/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp
index 588d32bf1..171542ea3 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp
@@ -49,7 +49,7 @@ void RegionTable_Init_BottomOfTheWell() {
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, true),
LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, true),
LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true),
- //N64 has no extra check here, but I can't get past without dealing with the spider or taking a hit
+ //N64 has no extra check here, but I can't get past without dealing with the spider or taking a hit, they probably assume sticks
LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()),
//Not technically behind a wall, but still logically needs lens due to pits
LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives()),
@@ -111,7 +111,7 @@ void RegionTable_Init_BottomOfTheWell() {
areaTable[RR_BOTTOM_OF_THE_WELL_COFFIN_ROOM] = Region("Bottom of the Well Coffin Room", "Bottom of the Well", {RA_BOTTOM_OF_THE_WELL}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)),
- LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)),
+ LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART, true),
LOCATION(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, logic->HasFireSourceWithTorch() || logic->CanUse(RG_FAIRY_BOW)),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
index eb8be8bb7..189d1c867 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
@@ -60,7 +60,7 @@ void RegionTable_Init_DodongosCavern() {
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_LOBBY, []{return true;}),
- //Shield seems to be in logic to drop a pot on thier head as they hit you to blow up the wall
+ //Shield seems to be in logic to drop a pot on their head as they hit you to blow up the wall
Entrance(RR_DODONGOS_CAVERN_SE_ROOM, []{return Here(RR_DODONGOS_CAVERN_SE_CORRIDOR, []{return logic->BlastOrSmash() || logic->CanAttack() || (logic->TakeDamage() && logic->CanShield());});}),
Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, []{return true;}),
});
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
index 30481922c..8b8b4d465 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
@@ -45,12 +45,12 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))),
- LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))),
+ LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))),
+ LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->HasProjectile(HasProjectileAge::Adult)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->IsChild && logic->HasProjectile(HasProjectileAge::Child))),
LOCATION(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, logic->HasProjectile(HasProjectileAge::Both) || logic->CanUse(RG_DINS_FIRE) ||
(logic->TakeDamage() && (logic->CanJumpslashExceptHammer() || logic->HasProjectile(HasProjectileAge::Child))) ||
(logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasProjectile(HasProjectileAge::Child)) ||
- ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))),
+ ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))),
LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_POT_1, logic->CanBreakPots()),
}, {
//Exits
@@ -72,11 +72,11 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
+ LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
(logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))),
- LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
+ LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
(logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))),
@@ -85,19 +85,19 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) ||
(logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) ||
(logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) &&
- logic->CanUse(RG_BOOMERANG) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))))),
- LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
+ logic->CanUse(RG_BOOMERANG) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))))),
+ LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) &&
ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) ||
(ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_BOOMERANG)) ||
(logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))),
- LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
- LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
+ LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, []{return logic->CanJumpslashExceptHammer() || logic->HasExplosives();}),
@@ -267,7 +267,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, MQSpiritSharedBrokenWallRoom(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanKillEnemy(RE_BEAMOS);})),
//Sunlights only temp spawn this chest, which is unintuitive/a bug.
//chest is only reachable as adult glitchlessly, so we can skip the shared in favour of IsAdult as adult access is always Certain
- LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->IsAdult && logic->HasExplosives() && (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS)) && logic->CanUse(RG_HOOKSHOT)),
+ LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, logic->IsAdult && (logic->HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->CanUse(RG_HOOKSHOT)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}),
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/haunted_wasteland.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp
index 60e616f76..abedcc571 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp
@@ -14,11 +14,11 @@ void RegionTable_Init_HauntedWasteland() {
//Events
EventAccess(&logic->FairyPot, []{return true;}),
EventAccess(&logic->NutPot, []{return true;}),
- EventAccess(&logic->CarpetMerchant, []{return logic->HasItem(RG_ADULT_WALLET) && CanBuyAnother(RC_WASTELAND_BOMBCHU_SALESMAN) && (logic->CanJumpslashExceptHammer() || logic->CanUse(RG_HOVER_BOOTS));}),
+ EventAccess(&logic->CarpetMerchant, []{return logic->HasItem(RG_ADULT_WALLET) && CanBuyAnother(RC_WASTELAND_BOMBCHU_SALESMAN) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS));}),
}, {
//Locations
LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource()),
- LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslashExceptHammer() || logic->CanUse(RG_HOVER_BOOTS)),
+ LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)),
LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang()),
LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()),
LOCATION(RC_WASTELAND_NEAR_GS_POT_2, logic->CanBreakPots()),
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 8a6991301..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,26 +16,27 @@ 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, {
//Events
- EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}),
+ EventAccess(&logic->CouldEmptyBigPoes, []{return logic->IsAdult;}),
+ EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}),
}, {
//Locations
LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && logic->BigPoeKill),
@@ -97,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, {}, {
@@ -132,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, {
@@ -144,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, {}, {
@@ -178,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, {}, {
@@ -201,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, {}, {
@@ -211,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 19ee1c7d0..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));
@@ -1985,7 +1988,7 @@ void Rando::StaticData::InitLocationTable() { //
locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_LEFT_RUPEE] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_LEFT_RUPEE, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-19, -828), "Basement Platform Back Left Rupee", RHT_BOTTOM_OF_THE_WELL_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_LEFT_RUPEE));
locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_MIDDLE_RUPEE] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_MIDDLE_RUPEE, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(47, -805), "Basement Platform Middle Rupee", RHT_BOTTOM_OF_THE_WELL_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_MIDDLE_RUPEE));
locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_RIGHT_RUPEE] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_RIGHT_RUPEE, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(94, -762), "Basement Platform Back Right Rupee", RHT_BOTTOM_OF_THE_WELL_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_BACK_RIGHT_RUPEE));
- locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-85, -710), "Basement Platform Right Rupee", RHT_BOTTOM_OF_THE_WELL_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE));
+ locationTable[RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(85, -710), "Basement Platform Right Rupee", RHT_BOTTOM_OF_THE_WELL_RUPEE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM_RIGHT_RUPEE));
locationTable[RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-1947, -625), "Coffin Room Front Left Heart", RHT_BOTTOM_OF_THE_WELL_HEART, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_COFFIN_ROOM_FRONT_LEFT_HEART));
locationTable[RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART] = Location::Collectable(RC_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART, RCQUEST_VANILLA, RCTYPE_FREESTANDING, ACTOR_EN_ITEM00, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-2144, -859), "Coffin Room Middle Right Heart", RHT_BOTTOM_OF_THE_WELL_HEART, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTTOM_OF_THE_WELL_COFFIN_ROOM_MIDDLE_RIGHT_HEART));
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index 2b92484b3..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;
}
@@ -649,7 +686,7 @@ namespace Rando {
//RANDOTODO Dark link is buggy right now, retest when he is not
return CanJumpslash() || CanUse(RG_FAIRY_BOW);
case RE_ANUBIS:
- //there's a restoration that allows beating them with mirror shield + some way to trigger thier attack
+ //there's a restoration that allows beating them with mirror shield + some way to trigger their attack
return HasFireSource();
case RE_BEAMOS:
return HasExplosives();
@@ -880,13 +917,26 @@ namespace Rando {
uint8_t Logic::BottleCount() {
uint8_t count = 0;
- if (!CanEmptyBigPoes){
- return 0;
- }
- for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) {
- uint8_t item = GetSaveContext()->inventory.items[i];
- if (item != ITEM_NONE && (item != ITEM_LETTER_RUTO || (item == ITEM_LETTER_RUTO && DeliverLetter))) {
- count++;
+ if (CouldEmptyBigPoes){
+ for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) {
+ uint8_t item = GetSaveContext()->inventory.items[i];
+ switch (item) {
+ case ITEM_LETTER_RUTO:
+ if (DeliverLetter) {
+ count++;
+ }
+ break;
+ case ITEM_BIG_POE:
+ if (CanEmptyBigPoes) {
+ count++;
+ }
+ break;
+ case ITEM_NONE:
+ break;
+ default:
+ count++;
+ break;
+ }
}
}
return count;
@@ -951,7 +1001,7 @@ namespace Rando {
}
bool Logic::BombchusEnabled(){
- return ctx->GetOption(RSK_BOMBCHUS_IN_LOGIC) ? CheckInventory(ITEM_BOMBCHU, true) : HasItem(RG_BOMB_BAG);
+ return ctx->GetOption(RSK_BOMBCHU_BAG) ? CheckInventory(ITEM_BOMBCHU, true) : HasItem(RG_BOMB_BAG);
}
// TODO: Implement Ammo Drop Setting in place of bombchu drops
@@ -1025,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) +
@@ -1155,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) {
@@ -1280,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 = {
@@ -1357,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 };
@@ -1601,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);
@@ -1622,10 +1712,34 @@ 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:
- mSaveContext->triforcePiecesCollected += (!state ? -1 : 1);
+ mSaveContext->ship.quest.data.randomizer.triforcePiecesCollected += (!state ? -1 : 1);
break;
case RG_BOMBCHU_5:
case RG_BOMBCHU_10:
@@ -1881,14 +1995,13 @@ namespace Rando {
mSaveContext->sceneFlags[5].swch = 0x40000000;
// SoH specific
- mSaveContext->backupFW = mSaveContext->fw;
- mSaveContext->pendingSale = ITEM_NONE;
- mSaveContext->pendingSaleMod = MOD_NONE;
- mSaveContext->isBossRushPaused = 0;
- mSaveContext->pendingIceTrapCount = 0;
+ mSaveContext->ship.backupFW = mSaveContext->fw;
+ mSaveContext->ship.pendingSale = ITEM_NONE;
+ mSaveContext->ship.pendingSaleMod = MOD_NONE;
+ mSaveContext->ship.pendingIceTrapCount = 0;
// Init with normal quest unless only an MQ rom is provided
- mSaveContext->questId = OTRGlobals::Instance->HasOriginal() ? QUEST_NORMAL : QUEST_MASTER;
+ mSaveContext->ship.quest.id = OTRGlobals::Instance->HasOriginal() ? QUEST_NORMAL : QUEST_MASTER;
//RANDOTODO (ADD ITEMLOCATIONS TO GSAVECONTEXT)
}
@@ -1937,16 +2050,16 @@ namespace Rando {
bool Logic::HasAdultTrade(uint32_t itemID) {
int tradeIndex = itemID - ITEM_POCKET_EGG;
- return mSaveContext->adultTradeItems & (1 << tradeIndex);
+ return mSaveContext->ship.quest.data.randomizer.adultTradeItems & (1 << tradeIndex);
}
void Logic::SetAdultTrade(uint32_t itemID, bool state) {
int tradeIndex = itemID - ITEM_POCKET_EGG;
if (!state) {
- mSaveContext->adultTradeItems &= ~(1 << tradeIndex);
+ mSaveContext->ship.quest.data.randomizer.adultTradeItems &= ~(1 << tradeIndex);
}
else {
- mSaveContext->adultTradeItems |= (1 << tradeIndex);
+ mSaveContext->ship.quest.data.randomizer.adultTradeItems |= (1 << tradeIndex);
}
}
@@ -1981,15 +2094,15 @@ namespace Rando {
}
bool Logic::CheckRandoInf(uint32_t flag) {
- return mSaveContext->randomizerInf[flag >> 4] & (1 << (flag & 0xF));
+ return mSaveContext->ship.randomizerInf[flag >> 4] & (1 << (flag & 0xF));
}
void Logic::SetRandoInf(uint32_t flag, bool state) {
if (!state) {
- mSaveContext->randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
+ mSaveContext->ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF));
}
else {
- mSaveContext->randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
+ mSaveContext->ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
}
}
@@ -2104,7 +2217,7 @@ namespace Rando {
//Bottle Count
Bottles = 0;
NumBottles = 0;
- CanEmptyBigPoes = true;
+ CanEmptyBigPoes = false;
//Drops and Bottle Contents Access
NutPot = false;
@@ -2141,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
@@ -2150,7 +2263,7 @@ namespace Rando {
//Other
AtDay = false;
AtNight = false;
- GetSaveContext()->linkAge = !ctx->GetSettings()->ResolvedStartingAge();
+ 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 ec4b29899..ea9d51801 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -65,7 +65,10 @@ class Logic {
// Bottle Count
uint8_t Bottles = 0;
uint8_t NumBottles = 0;
- bool CanEmptyBigPoes = true;
+ //this event covers if the player can currently empty big poes in logic
+ bool CanEmptyBigPoes = false;
+ //this check covers if the generation has confirmed that it's possible to empty big poes if needed as adult
+ bool CouldEmptyBigPoes = true;
// Drops and Bottle Contents Access
bool NutPot = false;
@@ -183,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..5cf16ac26 100644
--- a/soh/soh/Enhancements/randomizer/option.cpp
+++ b/soh/soh/Enhancements/randomizer/option.cpp
@@ -2,42 +2,56 @@
#include "libultraship/bridge.h"
#include
#include
-#include "soh/UIWidgets.hpp"
+#include "soh/SohGui/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