diff --git a/soh/assets/custom/objects/object_jabbernut/LeafTex b/soh/assets/custom/objects/object_jabbernut/LeafTex
new file mode 100644
index 000000000..8872d9d6e
Binary files /dev/null and b/soh/assets/custom/objects/object_jabbernut/LeafTex differ
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL
new file mode 100644
index 000000000..9fa3e6994
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_0
new file mode 100644
index 000000000..afa1a515b
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_1
new file mode 100644
index 000000000..2816b4b2b
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_2
new file mode 100644
index 000000000..44e9b9eb4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_3
new file mode 100644
index 000000000..ad002de95
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiDekuJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL
new file mode 100644
index 000000000..1d9cf59c7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_0
new file mode 100644
index 000000000..b42a0d2b3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_1
new file mode 100644
index 000000000..687ac7b81
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_2
new file mode 100644
index 000000000..2699f49a2
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_3
new file mode 100644
index 000000000..a3067eb2b
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGerudoJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL
new file mode 100644
index 000000000..c579e8390
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_0
new file mode 100644
index 000000000..eef04e034
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_1
new file mode 100644
index 000000000..e9d18900f
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_2
new file mode 100644
index 000000000..ad2297481
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_3
new file mode 100644
index 000000000..d3d25bf59
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiGoronJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL
new file mode 100644
index 000000000..7481e77cd
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_0
new file mode 100644
index 000000000..98771a392
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_1
new file mode 100644
index 000000000..8bc06c54f
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_2
new file mode 100644
index 000000000..5feb8060d
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_3
new file mode 100644
index 000000000..6171987ed
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiHylianJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL
new file mode 100644
index 000000000..e59d96333
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_0
new file mode 100644
index 000000000..0b52cbb47
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_1
new file mode 100644
index 000000000..036ae2e20
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_2
new file mode 100644
index 000000000..cee24069a
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_3
new file mode 100644
index 000000000..6f8e1dc03
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL
new file mode 100644
index 000000000..b3c308584
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_0
new file mode 100644
index 000000000..bb959e1f2
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_1
new file mode 100644
index 000000000..650ddc218
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_2
new file mode 100644
index 000000000..ad105f64d
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_3
new file mode 100644
index 000000000..2f739e6e1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiKokiriJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL
new file mode 100644
index 000000000..5a31859b5
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_0 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_0
new file mode 100644
index 000000000..52a442cd8
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_0
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_1 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_1
new file mode 100644
index 000000000..cb0e634ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_2 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_2
new file mode 100644
index 000000000..c4a23e265
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_2
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_3 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_3
new file mode 100644
index 000000000..9cfd9fc2f
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_tri_3
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_0 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_0
new file mode 100644
index 000000000..c72717a09
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_0
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_1 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_1
new file mode 100644
index 000000000..91b3a82ce
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_2 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_2
new file mode 100644
index 000000000..b4d3e99c3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_2
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_3 b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_3
new file mode 100644
index 000000000..122fe5ad7
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/gGiZoraJabbernutDL_vtx_3
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiDekuJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGerudoJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiGoronJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiHylianJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiKokiriJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_fruit b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_fruit
new file mode 100644
index 000000000..3c8da9d57
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_fruit
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_fruit_shadow b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_fruit_shadow
new file mode 100644
index 000000000..e4e3c0dd3
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_fruit_shadow
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_leaf b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_leaf
new file mode 100644
index 000000000..bdee796e4
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_leaf
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_stem b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_stem
new file mode 100644
index 000000000..e4f7cfac1
--- /dev/null
+++ b/soh/assets/custom/objects/object_jabbernut/mat_gGiZoraJabbernutDL_f3dlite_stem
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_jabbernut/shadow b/soh/assets/custom/objects/object_jabbernut/shadow
new file mode 100644
index 000000000..667d99efc
Binary files /dev/null and b/soh/assets/custom/objects/object_jabbernut/shadow differ
diff --git a/soh/assets/custom/objects/object_jabbernut/shinyspot b/soh/assets/custom/objects/object_jabbernut/shinyspot
new file mode 100644
index 000000000..40d9bd884
Binary files /dev/null and b/soh/assets/custom/objects/object_jabbernut/shinyspot differ
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 1ed995667..4799b53c0 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -170,6 +170,27 @@ static const ALIGN_ASSET(2) char gRandoCuttableGrassHeartDL[] = dgRandoCuttableG
#define dgRandoCuttableGrassJunkDL "__OTR__objects/gameplay_keep/gRandoCuttableGrassJunkDL"
static const ALIGN_ASSET(2) char gRandoCuttableGrassJunkDL[] = dgRandoCuttableGrassJunkDL;
+#define dgGiJabbernutDL "__OTR__objects/object_jabbernut/gGiJabbernutDL"
+static const ALIGN_ASSET(2) char gGiJabbernutDL[] = dgGiJabbernutDL;
+
+#define dgGiDekuJabbernutDL "__OTR__objects/object_jabbernut/gGiDekuJabbernutDL"
+static const ALIGN_ASSET(2) char gGiDekuJabbernutDL[] = dgGiDekuJabbernutDL;
+
+#define dgGiGerudoJabbernutDL "__OTR__objects/object_jabbernut/gGiGerudoJabbernutDL"
+static const ALIGN_ASSET(2) char gGiGerudoJabbernutDL[] = dgGiGerudoJabbernutDL;
+
+#define dgGiGoronJabbernutDL "__OTR__objects/object_jabbernut/gGiGoronJabbernutDL"
+static const ALIGN_ASSET(2) char gGiGoronJabbernutDL[] = dgGiGoronJabbernutDL;
+
+#define dgGiHylianJabbernutDL "__OTR__objects/object_jabbernut/gGiHylianJabbernutDL"
+static const ALIGN_ASSET(2) char gGiHylianJabbernutDL[] = dgGiHylianJabbernutDL;
+
+#define dgGiKokiriJabbernutDL "__OTR__objects/object_jabbernut/gGiKokiriJabbernutDL"
+static const ALIGN_ASSET(2) char gGiKokiriJabbernutDL[] = dgGiKokiriJabbernutDL;
+
+#define dgGiZoraJabbernutDL "__OTR__objects/object_jabbernut/gGiZoraJabbernutDL"
+static const ALIGN_ASSET(2) char gGiZoraJabbernutDL[] = dgGiZoraJabbernutDL;
+
#define dgFishingPoleGiDL "__OTR__objects/object_gi_fishing_pole/gFishingPoleGiDL"
static const ALIGN_ASSET(2) char gFishingPoleGiDL[] = dgFishingPoleGiDL;
diff --git a/soh/include/z64item.h b/soh/include/z64item.h
index 9bbb8bb30..fb46e7f00 100644
--- a/soh/include/z64item.h
+++ b/soh/include/z64item.h
@@ -593,9 +593,9 @@ typedef enum {
/* 0x7A */ GID_SONG_TIME,
/* 0x7B */ GID_SONG_STORM,
/* 0x7C */ GID_TRIFORCE_PIECE,
- /* 0x7C */ GID_ROCS_FEATHER,
- /* */ GID_FISHING_POLE,
- /* 0x7C */ GID_MAXIMUM
+ /* 0x7D */ GID_ROCS_FEATHER,
+ /* 0x7E */ GID_FISHING_POLE,
+ /* 0x7F */ GID_MAXIMUM
} GetItemDrawID;
diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp
index 1e4e77d44..ed8a81970 100644
--- a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp
+++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp
@@ -1,4 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
+#include "soh/Enhancements/randomizer/SeedContext.h"
#include "soh/ShipInit.hpp"
extern "C" {
@@ -19,7 +20,9 @@ void RegisterMoveMidoInKokiriForest() {
VB_MOVE_MIDO_IN_KOKIRI_FOREST, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), {
if (!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
- (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0) {
+ (CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI) && gSaveContext.cutsceneIndex == 0 &&
+ !(IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SPEAK) &&
+ !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI))) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
*should = true;
}
diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp
index d90391c0f..417c31afb 100644
--- a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp
+++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp
@@ -1,4 +1,5 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
+#include "soh/Enhancements/randomizer/SeedContext.h"
#include "soh/ShipInit.hpp"
extern "C" {
@@ -9,6 +10,10 @@ Actor* func_80AEB124(PlayState* play);
}
void Ru1Init(void* actorRef) {
+ if (IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SPEAK) && !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA)) {
+ return;
+ }
+
EnRu1* enRu1 = static_cast(actorRef);
if (enRu1->action == 22) {
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index 7a260ccd6..f36676f6a 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -2207,6 +2207,14 @@ typedef enum {
// - `*ShotSun`
VB_SPAWN_SONG_FAIRY,
+ // #### `result`
+ // ```c
+ // (talkOfferActor != NULL) || (cUpTalkActor != NULL)
+ // ```
+ // #### `args`
+ // - None
+ VB_SPEAK,
+
// #### `result`
// ```c
// varies, never set should to true
diff --git a/soh/soh/Enhancements/kaleido.cpp b/soh/soh/Enhancements/kaleido.cpp
index e541be5a2..68e78032a 100644
--- a/soh/soh/Enhancements/kaleido.cpp
+++ b/soh/soh/Enhancements/kaleido.cpp
@@ -3,7 +3,6 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "ship/utils/StringHelper.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
-#include "soh/frame_interpolation.h"
#include "soh/ShipInit.hpp"
#include "soh/ShipUtils.h"
@@ -203,6 +202,16 @@ Kaleido::Kaleido() {
32, aButtonColor, FlagType::FLAG_RANDOMIZER_INF,
RAND_INF_CAN_GRAB, "Grab"));
}
+ if (ctx->GetOption(RSK_SHUFFLE_SPEAK)) {
+ int rg = RG_SPEAK_DEKU;
+ for (int i = RAND_INF_CAN_SPEAK_DEKU; i <= RAND_INF_CAN_SPEAK_ZORA; i++, rg++) {
+ std::string speakName = Rando::StaticData::RetrieveItem(static_cast(rg)).GetName().english;
+ StringHelper::ReplaceOriginal(speakName, " Jabber Nut", "");
+ mEntries.push_back(std::make_shared(gItemIconDekuNutTex, G_IM_FMT_RGBA, G_IM_SIZ_32b,
+ 32, 32, Color_RGBA8{ 255, 255, 255, 255 },
+ FlagType::FLAG_RANDOMIZER_INF, i, speakName));
+ }
+ }
if (ctx->GetOption(RSK_SHUFFLE_OPEN_CHEST)) {
mEntries.push_back(std::make_shared(
gMapChestIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, 8, Color_RGBA8{ 255, 255, 255, 255 },
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 4b347417f..5783be19c 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
@@ -2117,10 +2117,11 @@ void StaticData::HintTable_Init_Item() {
{ CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") });
// /*spanish*/un desbloqueador maestro
- //RANDOTODO if these are ever used for anything other than name, they want obscure and ambiguous hints
+ //RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints
hintTextTable[RHT_CLIMB] = HintText(CustomMessage("the ability to climb", /*german*/TODO_TRANSLATE, /*french*/"la capacité de grimper"));
hintTextTable[RHT_CRAWL] = HintText(CustomMessage("the ability to crawl", /*german*/TODO_TRANSLATE, /*french*/"la capacité de ramper"));
hintTextTable[RHT_OPEN_CHEST] = HintText(CustomMessage("the ability to open chests", /*german*/TODO_TRANSLATE, /*french*/TODO_TRANSLATE));
+ hintTextTable[RHT_SPEAK] = HintText(CustomMessage("the ability to speak", /*german*/TODO_TRANSLATE, /*french*/"la faculté de parler"));
hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini"));
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index cfa454be3..e48f30d61 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -415,6 +415,15 @@ void GenerateItemPool() {
AddItemToPool(RG_OPEN_CHEST, 2, 1, 1, 1);
}
+ if (ctx->GetOption(RSK_SHUFFLE_SPEAK)) {
+ AddItemToPool(RG_SPEAK_DEKU, 2, 1, 1, 1);
+ AddItemToPool(RG_SPEAK_GERUDO, 2, 1, 1, 1);
+ AddItemToPool(RG_SPEAK_GORON, 2, 1, 1, 1);
+ AddItemToPool(RG_SPEAK_HYLIAN, 2, 1, 1, 1);
+ AddItemToPool(RG_SPEAK_KOKIRI, 2, 1, 1, 1);
+ AddItemToPool(RG_SPEAK_ZORA, 2, 1, 1, 1);
+ }
+
if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) {
PlaceItemsForType(RCTYPE_BEEHIVE, true, true);
}
diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
index 10b1a6a7d..92684c9a6 100644
--- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
@@ -1260,6 +1260,44 @@ void InitTrickNames() {
Text{ "Gerudo Veil" },
};
+ trickNameTable[RG_SPEAK_DEKU] = {
+ // TODO_TRANSLATE
+ Text{ "Picori Jabber Nut" },
+ Text{ "Kikwi Blabber Nut" },
+ Text{ "Talking Deku Nut" },
+ };
+ trickNameTable[RG_SPEAK_GERUDO] = {
+ // TODO_TRANSLATE
+ Text{ "Gerudo Tuni Nut" },
+ Text{ "Twili Jabber Nut" },
+ Text{ "Zuna Blabber Nut" },
+ };
+ trickNameTable[RG_SPEAK_GORON] = {
+ // TODO_TRANSLATE
+ Text{ "Cobble Jabber Nut" },
+ Text{ "Mogma Blabber Nut" },
+ Text{ "Goron Speak Stone" },
+ };
+ trickNameTable[RG_SPEAK_HYLIAN] = {
+ // TODO_TRANSLATE
+ Text{ "Human Jingle Nut" },
+ Text{ "Sheikah Jabber nut" },
+ Text{ "Lorulean Blabber Nut" },
+ };
+ trickNameTable[RG_SPEAK_KOKIRI] = {
+ // TODO_TRANSLATE
+ Text{ "Korok Blabber Nut" },
+ Text{ "Minish Jabber Nut" },
+ Text{ "Fairy Jingle Nut" },
+ };
+ trickNameTable[RG_SPEAK_ZORA] = {
+ // TODO_TRANSLATE
+ Text{ "Parella Jabber Nut" },
+ Text{ "Fishman Jabber Nut" },
+ Text{ "Zora Jabu Nut" },
+ Text{ "Rito Jingle Nut" },
+ };
+
trickNameTable[RG_GUARD_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Pot Room Key", "Pot Room Key", "Pot Room Key" },
diff --git a/soh/soh/Enhancements/randomizer/ShuffleSpeak.cpp b/soh/soh/Enhancements/randomizer/ShuffleSpeak.cpp
new file mode 100644
index 000000000..ab299a5c2
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/ShuffleSpeak.cpp
@@ -0,0 +1,138 @@
+#include
+extern "C" {
+extern PlayState* gPlayState;
+#include "variables.h"
+#include "functions.h"
+#include "overlays/actors/ovl_En_Ossan/z_en_ossan.h"
+}
+
+void RegisterShuffleSpeak() {
+ bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_SPEAK).Get();
+
+ COND_VB_SHOULD(VB_SPEAK, shouldRegister, {
+ Actor* talkActor = GET_PLAYER(gPlayState)->talkActor;
+ if (talkActor != NULL && talkActor->category == ACTORCAT_NPC &&
+ !(talkActor->flags & ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED)) {
+ RandomizerInf inf = RAND_INF_MAX;
+ switch (talkActor->id) {
+ case ACTOR_EN_DNS:
+ case ACTOR_EN_DNT_JIJI:
+ case ACTOR_EN_HINTNUTS:
+ case ACTOR_EN_KAKASI:
+ case ACTOR_EN_KAKASI2:
+ case ACTOR_EN_KAKASI3:
+ case ACTOR_OBJ_DEKUJR:
+ inf = RAND_INF_CAN_SPEAK_DEKU;
+ break;
+ case ACTOR_EN_GE1:
+ case ACTOR_EN_GE3:
+ case ACTOR_EN_NB:
+ // skip ACTOR_EN_GE2 to always be able to ask to be thrown in jail
+ inf = RAND_INF_CAN_SPEAK_GERUDO;
+ break;
+ case ACTOR_EN_GO:
+ case ACTOR_EN_GO2:
+ case ACTOR_EN_GM:
+ case ACTOR_EN_DU:
+ inf = RAND_INF_CAN_SPEAK_GORON;
+ break;
+ case ACTOR_EN_ANI:
+ case ACTOR_EN_BOM_BOWL_MAN:
+ case ACTOR_EN_CS:
+ case ACTOR_EN_DAIKU:
+ case ACTOR_EN_DAIKU_KAKARIKO:
+ case ACTOR_EN_DS:
+ case ACTOR_EN_FU:
+ case ACTOR_EN_GB:
+ case ACTOR_EN_GIRLA:
+ case ACTOR_EN_GUEST:
+ case ACTOR_EN_HEISHI1:
+ case ACTOR_EN_HEISHI2:
+ case ACTOR_EN_HEISHI3:
+ case ACTOR_EN_HEISHI4:
+ case ACTOR_EN_HS:
+ case ACTOR_EN_HS2:
+ case ACTOR_EN_HY:
+ case ACTOR_EN_IN:
+ case ACTOR_EN_JS:
+ case ACTOR_EN_MA1:
+ case ACTOR_EN_MA2:
+ case ACTOR_EN_MA3:
+ case ACTOR_EN_MK:
+ case ACTOR_EN_MM:
+ case ACTOR_EN_MM2:
+ case ACTOR_EN_MS:
+ case ACTOR_EN_MU:
+ case ACTOR_EN_NIW_GIRL:
+ case ACTOR_EN_NIW_LADY:
+ case ACTOR_EN_SSH:
+ case ACTOR_EN_STH:
+ case ACTOR_EN_SYATEKI_MAN:
+ case ACTOR_EN_TA:
+ case ACTOR_EN_TAKARA_MAN:
+ case ACTOR_EN_TG:
+ case ACTOR_EN_TK:
+ case ACTOR_EN_PO_RELAY:
+ case ACTOR_EN_TORYO:
+ case ACTOR_EN_XC:
+ case ACTOR_EN_ZL1:
+ case ACTOR_EN_ZL2:
+ case ACTOR_EN_ZL3:
+ case ACTOR_EN_ZL4:
+ case ACTOR_FISHING:
+ inf = RAND_INF_CAN_SPEAK_HYLIAN;
+ break;
+ case ACTOR_EN_KO:
+ case ACTOR_EN_SA:
+ case ACTOR_EN_MD:
+ case ACTOR_EN_SKJ:
+ inf = RAND_INF_CAN_SPEAK_KOKIRI;
+ break;
+ case ACTOR_EN_KZ:
+ case ACTOR_EN_RU1:
+ case ACTOR_EN_RU2:
+ case ACTOR_EN_ZO:
+ inf = RAND_INF_CAN_SPEAK_ZORA;
+ break;
+ case ACTOR_EN_OSSAN:
+ switch (talkActor->params) {
+ case OSSAN_TYPE_KOKIRI:
+ inf = RAND_INF_CAN_SPEAK_KOKIRI;
+ break;
+ case OSSAN_TYPE_KAKARIKO_POTION:
+ case OSSAN_TYPE_BOMBCHUS:
+ case OSSAN_TYPE_MARKET_POTION:
+ case OSSAN_TYPE_BAZAAR:
+ case OSSAN_TYPE_ADULT:
+ case OSSAN_TYPE_TALON:
+ case OSSAN_TYPE_INGO:
+ case OSSAN_TYPE_MASK:
+ inf = RAND_INF_CAN_SPEAK_HYLIAN;
+ break;
+ case OSSAN_TYPE_GORON:
+ inf = RAND_INF_CAN_SPEAK_GORON;
+ break;
+ case OSSAN_TYPE_ZORA:
+ inf = RAND_INF_CAN_SPEAK_ZORA;
+ break;
+ }
+ break;
+ case ACTOR_EN_OWL:
+ if (!Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_DEKU) &&
+ !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GERUDO) &&
+ !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GORON) &&
+ !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN) &&
+ !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI) &&
+ !Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA)) {
+ *should = false;
+ }
+ return;
+ }
+ if (inf != RAND_INF_MAX && !Flags_GetRandomizerInf(inf)) {
+ *should = false;
+ }
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterShuffleSpeak, { "IS_RANDO" });
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp
index cfc4a4705..32cfe801c 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -1189,6 +1189,56 @@ extern "C" void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEn
CLOSE_DISPS(play->state.gfxCtx);
}
+extern "C" void Randomizer_DrawJabberNut(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 bodyColor;
+ if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("GenericJabberNutModel"), 0)) {
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.JabberNut.Value"), Color_RGB8{ 255, 0, 216 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiJabbernutDL);
+ } else {
+ switch (getItemEntry->drawItemId) {
+ case RG_SPEAK_DEKU:
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.DekuJabberNut.Value"), Color_RGB8{ 255, 160, 32 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiDekuJabbernutDL);
+ break;
+ case RG_SPEAK_GERUDO:
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.GerudoJabberNut.Value"), Color_RGB8{ 128, 64, 0 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiGerudoJabbernutDL);
+ break;
+ case RG_SPEAK_GORON:
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.GoronJabberNut.Value"), Color_RGB8{ 255, 32, 0 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiGoronJabbernutDL);
+ break;
+ case RG_SPEAK_HYLIAN:
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.HylianJabberNut.Value"), Color_RGB8{ 255, 255, 0 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiHylianJabbernutDL);
+ break;
+ case RG_SPEAK_KOKIRI:
+ bodyColor =
+ CVarGetColor24(CVAR_COSMETIC("Equipment.KokiriJabberNut.Value"), Color_RGB8{ 128, 216, 48 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiKokiriJabbernutDL);
+ break;
+ case RG_SPEAK_ZORA:
+ bodyColor = CVarGetColor24(CVAR_COSMETIC("Equipment.ZoraJabberNut.Value"), Color_RGB8{ 96, 240, 255 });
+ gDPSetEnvColor(POLY_OPA_DISP++, bodyColor.r, bodyColor.g, bodyColor.b, 255);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiZoraJabbernutDL);
+ break;
+ }
+ }
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
static Gfx* boxLidDL;
static Gfx* boxBodyDL;
extern "C" void EnBox_PostLimbDrawOverride(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h
index ce3a4564d..d674f562f 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -25,6 +25,7 @@ void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawPowerBracelet(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawLadder(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry);
+void Randomizer_DrawJabberNut(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry);
diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
index 5f6d78617..ff14d7c8f 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -30,6 +30,7 @@ extern "C" {
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
+#include "src/overlays/actors/ovl_En_Nb/z_en_nb.h"
#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h"
#include "src/overlays/actors/ovl_En_Kz/z_en_kz.h"
#include "src/overlays/actors/ovl_En_Ms/z_en_ms.h"
@@ -2395,6 +2396,11 @@ void RandomizerOnActorInitHandler(void* actorRef) {
return;
}
+ if (actor->id == ACTOR_EN_NB && (actor->params & 0xFF) == NB_TYPE_CRAWLSPACE &&
+ !RAND_GET_OPTION(RSK_SHUFFLE_SPEAK)) {
+ Actor_Kill(actor);
+ }
+
// Turn MQ switch into toggle
if (actor->id == ACTOR_OBJ_SWITCH && gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL &&
(actor->params & 0x3f07) == 0x303) {
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 7ae9956bb..d2be0ce00 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -366,6 +366,19 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_GERUDO_MASK] = Item(RG_GERUDO_MASK, Text{ "Gerudo Mask", "Masque de Gerudo", TODO_TRANSLATE }, ITEMTYPE_ITEM, RG_GERUDO_MASK, true, LOGIC_NONE, RHT_MASK_GERUDO, RG_GERUDO_MASK, OBJECT_GI_GERUDOMASK, GID_MASK_GERUDO, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_MASK_OF_TRUTH] = Item(RG_MASK_OF_TRUTH, Text{ "Mask of Truth", "Masque de Vérité", TODO_TRANSLATE }, ITEMTYPE_ITEM, RG_MASK_OF_TRUTH, true, LOGIC_NONE, RHT_MASK_TRUTH, RG_MASK_OF_TRUTH, OBJECT_GI_TRUTH_MASK, GID_MASK_TRUTH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_DEKU] = Item(RG_SPEAK_DEKU, Text{ "Deku Jabber Nut", "Noix Blabla Mojo", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_SPEAK, RG_SPEAK_DEKU, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_DEKU].SetCustomDrawFunc(Randomizer_DrawJabberNut);
+ itemTable[RG_SPEAK_GERUDO] = Item(RG_SPEAK_GERUDO, Text{ "Gerudo Jabber Nut", "Noix Blabla Gerudo", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_SPEAK, RG_SPEAK_GERUDO, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_GERUDO].SetCustomDrawFunc(Randomizer_DrawJabberNut);
+ itemTable[RG_SPEAK_GORON] = Item(RG_SPEAK_GORON, Text{ "Goron Jabber Nut", "Noix Blabla Goron", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_SPEAK, RG_SPEAK_GORON, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_GORON].SetCustomDrawFunc(Randomizer_DrawJabberNut);
+ itemTable[RG_SPEAK_HYLIAN] = Item(RG_SPEAK_HYLIAN, Text{ "Hylian Jabber Nut", "Noix Blabla Hylienne", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_SPEAK, RG_SPEAK_HYLIAN, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_HYLIAN].SetCustomDrawFunc(Randomizer_DrawJabberNut);
+ itemTable[RG_SPEAK_KOKIRI] = Item(RG_SPEAK_KOKIRI, Text{ "Kokiri Jabber Nut", "Noix Blabla Kokiri", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_SPEAK, RG_SPEAK_KOKIRI, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_KOKIRI].SetCustomDrawFunc(Randomizer_DrawJabberNut);
+ itemTable[RG_SPEAK_ZORA] = Item(RG_SPEAK_ZORA, Text{ "Zora Jabber Nut", "Noix Blabla Zora", "" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_SPEAK, RG_SPEAK_ZORA, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_SPEAK_ZORA].SetCustomDrawFunc(Randomizer_DrawJabberNut);
+
itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_NONE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "});
itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
itemTable[RG_POWER_BRACELET] = Item(RG_POWER_BRACELET, Text{ "Power Bracelet", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_NONE, RHT_NONE, RG_POWER_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
index a0e4ce66c..18d379d2d 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
@@ -448,7 +448,7 @@ void RegionTable_Init_DekuTree() {
EVENT_ACCESS(LOGIC_DEKU_TREE_B1_BROKE_WEB, logic->HasFireSource()),
}, {
//Locations
- LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_DEKU_TREE_MQ_BASEMENT_UPPER_GRASS_1, logic->CanCutShrubs()),
LOCATION(RC_DEKU_TREE_MQ_BASEMENT_UPPER_GRASS_2, logic->CanCutShrubs()),
LOCATION(RC_DEKU_TREE_MQ_BASEMENT_UPPER_GRASS_3, logic->CanCutShrubs()),
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
index 593ab7d99..6066a0f98 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
@@ -29,7 +29,7 @@ void RegionTable_Init_DodongosCavern() {
}, {
//Locations
LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST);),
- LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, (logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, (logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); }) && logic->CallGossipFairy()),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); }) && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, AnyAgeTime([]{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET); })),
@@ -115,7 +115,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_NEAR_DODONGO_ROOM] = Region("Dodongos Cavern Near Dodongo Room", SCENE_DODONGOS_CAVERN, {}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_DODONGOS_CAVERN_DODONGO_ROOM, true),
@@ -175,8 +175,8 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Region("Dodongos Cavern 2F Side Room", SCENE_DODONGOS_CAVERN, {}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, true),
@@ -289,8 +289,8 @@ void RegionTable_Init_DodongosCavern() {
}, {
//Locations
LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_OPEN_CHEST)),
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_DODONGOS_CAVERN_MQ_BEGINNING, true),
@@ -370,7 +370,7 @@ void RegionTable_Init_DodongosCavern() {
EVENT_ACCESS(LOGIC_DC_MQ_STAIRS_SILVER_RUPEES, logic->HasItem(RG_CLIMB)),
}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_1, logic->CanBreakCrates()),
LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_2, logic->CanBreakCrates()),
LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_3, logic->CanBreakCrates()),
@@ -504,7 +504,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE_SCRUB] = Region("Dodongos Cavern MQ Lower Right Side Scrub", SCENE_DODONGOS_CAVERN, {}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, true),
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
index ff0fa0ee1..63bc50d91 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
@@ -23,7 +23,7 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_MAIN] = Region("Ganon's Castle Main", SCENE_INSIDE_GANONS_CASTLE, {}, {
//Locations
- LOCATION(RC_SHEIK_HINT_GC, true),
+ LOCATION(RC_SHEIK_HINT_GC, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_GANONS_CASTLE_LOBBY, true),
@@ -47,10 +47,10 @@ void RegionTable_Init_GanonsCastle() {
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, true),
}, {
//Locations
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_GANONS_CASTLE_SCRUBS_FAIRY_1, true),
LOCATION(RC_GANONS_CASTLE_SCRUBS_FAIRY_2, true),
LOCATION(RC_GANONS_CASTLE_SCRUBS_FAIRY_3, true),
@@ -346,7 +346,7 @@ void RegionTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_MQ_MAIN] = Region("Ganon's Castle MQ Main", SCENE_INSIDE_GANONS_CASTLE, {}, {
//Locations
- LOCATION(RC_SHEIK_HINT_MQ_GC, true),
+ LOCATION(RC_SHEIK_HINT_MQ_GC, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_GANONS_CASTLE_MQ_LOBBY, true),
@@ -371,11 +371,11 @@ void RegionTable_Init_GanonsCastle() {
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, true),
}, {
//Locations
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_1, true),
LOCATION(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_2, true),
LOCATION(RC_GANONS_CASTLE_MQ_SCRUBS_FAIRY_3, true),
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
index 21af8a3d3..6286eaae5 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
@@ -24,7 +24,7 @@ void RegionTable_Init_JabuJabusBelly() {
areaTable[RR_JABU_JABUS_BELLY_LIFT_ROOM] = Region("Jabu Jabus Belly Lift Room", SCENE_JABU_JABU, {}, {
//Locations
- LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_JABU_JABUS_BELLY_PLATFORM_ROOM_SMALL_CRATE_1, logic->CanBreakSmallCrates()),
LOCATION(RC_JABU_JABUS_BELLY_PLATFORM_ROOM_SMALL_CRATE_2, logic->CanBreakSmallCrates()),
}, {
@@ -77,7 +77,7 @@ void RegionTable_Init_JabuJabusBelly() {
areaTable[RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_NORTH] = Region("Jabu Jabus Belly Water Switch Room North", SCENE_JABU_JABU, {
//Events
- EVENT_ACCESS(LOGIC_JABU_RUTO_IN_1F, (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_POWER_BRACELET)),
+ EVENT_ACCESS(LOGIC_JABU_RUTO_IN_1F, (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET)),
}, {
//Locations
LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
@@ -346,7 +346,7 @@ void RegionTable_Init_JabuJabusBelly() {
//Exits
ENTRANCE(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, logic->HasItem(RG_CLIMB)),
ENTRANCE(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, logic->Get(LOGIC_JABU_WEST_TENTACLE)),
- ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, logic->HasItem(RG_POWER_BRACELET)),
+ ENTRANCE(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET)),
ENTRANCE(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, logic->Get(LOGIC_JABU_NORTH_TENTACLE)),
});
@@ -481,8 +481,8 @@ void RegionTable_Init_JabuJabusBelly() {
// Need Ruto here
areaTable[RR_JABU_JABUS_BELLY_MQ_BIGOCTO] = Region("Jabu Jabus Belly MQ Big Octo", SCENE_JABU_JABU, {}, {}, {
//Exits
- ENTRANCE(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && logic->CanKillEnemy(RE_BIG_OCTO);})),
- ENTRANCE(RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO, AnyAgeTime([]{return logic->HasItem(RG_POWER_BRACELET) && logic->CanKillEnemy(RE_BIG_OCTO);})),
+ ENTRANCE(RR_JABU_JABUS_BELLY_MQ_TO_BIGOCTO, AnyAgeTime([]{return logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET) && logic->CanKillEnemy(RE_BIG_OCTO);})),
+ ENTRANCE(RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO, AnyAgeTime([]{return logic->HasItem(RG_SPEAK_ZORA) && logic->HasItem(RG_POWER_BRACELET) && logic->CanKillEnemy(RE_BIG_OCTO);})),
});
areaTable[RR_JABU_JABUS_BELLY_MQ_ABOVE_BIGOCTO] = Region("Jabu Jabus Belly MQ Above Big Octo", SCENE_JABU_JABU, {}, {
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 d2bc4b9a5..90cd300fc 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
@@ -28,7 +28,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
ENTRANCE(RR_SPIRIT_TEMPLE_ENTRYWAY, true),
- ENTRANCE(RR_SPIRIT_TEMPLE_CHILD_SIDE_HUB, logic->CanUse(RG_CRAWL)),
+ ENTRANCE(RR_SPIRIT_TEMPLE_CHILD_SIDE_HUB, (logic->IsAdult || logic->HasItem(RG_SPEAK_GERUDO) || logic->Get(LOGIC_SPIRIT_NABOORU_KIDNAPPED)) && logic->CanUse(RG_CRAWL)),
ENTRANCE(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, logic->CanUse(RG_SILVER_GAUNTLETS)),
});
@@ -334,7 +334,10 @@ void RegionTable_Init_SpiritTemple() {
ENTRANCE(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, true),
});
- areaTable[RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND] = Region("Spirit Temple Outer Right Hand", SCENE_SPIRIT_TEMPLE, {}, {
+ areaTable[RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND] = Region("Spirit Temple Outer Right Hand", SCENE_SPIRIT_TEMPLE, {
+ //Events
+ EVENT_ACCESS(LOGIC_SPIRIT_NABOORU_KIDNAPPED, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})),
+ }, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})),
}, {
@@ -563,7 +566,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
ENTRANCE(RR_SPIRIT_TEMPLE_ENTRYWAY, true),
- ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHILD_SIDE_HUB, logic->CanUse(RG_CRAWL) /*&& logic->HasSoul(RG_NABOORU_SOUL)*/),
+ ENTRANCE(RR_SPIRIT_TEMPLE_MQ_CHILD_SIDE_HUB, (logic->IsAdult || logic->HasItem(RG_SPEAK_GERUDO) || logic->Get(LOGIC_SPIRIT_NABOORU_KIDNAPPED)) && logic->CanUse(RG_CRAWL) /*&& logic->HasSoul(RG_NABOORU_SOUL)*/),
ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BEHIND_GEYSER, ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && (logic->CanUse(RG_MEGATON_HAMMER) || (logic->CanStandingShield() && (logic->CanUseSword() || logic->CanUse(RG_STICKS))))),
ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCKS_HOLE, logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5)),
});
@@ -814,7 +817,10 @@ void RegionTable_Init_SpiritTemple() {
ENTRANCE(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, true),
});
- areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND] = Region("Spirit Temple MQ Outer Right Hand", SCENE_SPIRIT_TEMPLE, {}, {
+ areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND] = Region("Spirit Temple MQ Outer Right Hand", SCENE_SPIRIT_TEMPLE, {
+ //Events
+ EVENT_ACCESS(LOGIC_SPIRIT_NABOORU_KIDNAPPED, SpiritShared(RR_SPIRIT_TEMPLE_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})),
+ }, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->HasItem(RG_OPEN_CHEST);})),
}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp
index b74deee1d..eee04dabc 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/water_temple.cpp
@@ -250,8 +250,8 @@ void RegionTable_Init_WaterTemple() {
//Events
//Implies CanAvoid(RE_STINGER)
//the full logic for the puzzle, as it is cut down here for optimisation
- //EventAccess(LOGIC_WATER_PUSHED_B1_BLOCK, []{return logic->HasItem(RG_GORONS_BRACELET) && logic->HasExplosives() &&
- // (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS));}),
+ //EVENT_ACCESS(LOGIC_WATER_PUSHED_B1_BLOCK, logic->HasItem(RG_GORONS_BRACELET) && logic->HasExplosives() &&
+ // (logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS))),
}, {
//Locations //we can always get the pots by shooting them from afar and diving for the item...
LOCATION(RC_WATER_TEMPLE_BASEMENT_BLOCK_PUZZLE_POT_1, (logic->CanBreakPots(ED_LONGSHOT, true, true) && logic->HasItem(RG_BRONZE_SCALE)) ||
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
index 68d0bb6f4..2a33f87d7 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
@@ -22,14 +22,14 @@ void RegionTable_Init_CastleGrounds() {
EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->HasItem(RG_POWER_BRACELET)),
}, {
//Locations
- LOCATION(RC_HC_MALON_EGG, true),
+ LOCATION(RC_HC_MALON_EGG, logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_HC_GS_TREE, logic->CanBonkTrees() && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)),
LOCATION(RC_HC_SKULLTULA_TREE, logic->CanBonkTrees()),
}, {
//Exits
ENTRANCE(RR_CASTLE_GROUNDS, true),
ENTRANCE(RR_HC_ABOVE_VINE, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)),
- ENTRANCE(RR_HC_PAST_GATE, logic->HasItem(RG_CHILD_WALLET)),
+ ENTRANCE(RR_HC_PAST_GATE, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
});
areaTable[RR_HC_ABOVE_VINE] = Region("Hyrule Castle Above Vine", SCENE_HYRULE_CASTLE, {
@@ -90,7 +90,8 @@ void RegionTable_Init_CastleGrounds() {
//Exits
ENTRANCE(RR_HC_GATE, true),
ENTRANCE(RR_HC_STORMS_GROTTO, logic->CanOpenStormsGrotto()),
- ENTRANCE(RR_HC_GARDEN, (logic->CanUse(RG_WEIRD_EGG) && logic->HasItem(RG_POWER_BRACELET)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage() && logic->HasExplosives() && logic->CanJumpslash())),
+ ENTRANCE(RR_HC_GARDEN, (logic->CanUse(RG_WEIRD_EGG) && logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_SPEAK_HYLIAN)) ||
+ (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage() && logic->HasExplosives() && logic->CanJumpslash())),
});
areaTable[RR_HC_DRAIN_LEDGE] = Region("Hyrule Castle Drain Ledge", SCENE_HYRULE_CASTLE, {}, {}, {
@@ -101,8 +102,8 @@ void RegionTable_Init_CastleGrounds() {
areaTable[RR_HC_GARDEN] = Region("HC Garden", SCENE_CASTLE_COURTYARD_ZELDA, {}, {
//Locations
- LOCATION(RC_HC_ZELDAS_LETTER, true),
- LOCATION(RC_SONG_FROM_IMPA, true),
+ LOCATION(RC_HC_ZELDAS_LETTER, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_SONG_FROM_IMPA, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_HC_DRAIN_LEDGE, true), // if this ever gets shuffled leaving garden area should come out crawlspace
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp
index 4b272cd2b..f1281e27b 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp
@@ -35,7 +35,7 @@ void RegionTable_Init_DeathMountainCrater() {
areaTable[RR_DMC_LADDER_AREA_NEARBY] = Region("DMC Ladder Region Nearby", SCENE_DEATH_MOUNTAIN_CRATER, {}, {
//Locations
- LOCATION(RC_DMC_DEKU_SCRUB, logic->IsChild && logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DMC_DEKU_SCRUB, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_DMC_UPPER_NEARBY, (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)) && logic->Hearts() >= 3),
@@ -127,9 +127,9 @@ void RegionTable_Init_DeathMountainCrater() {
areaTable[RR_DMC_HAMMER_GROTTO] = Region("DMC Hammer Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_DMC_HAMMER_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
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 86a22ffd6..7cb55cf83 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
@@ -52,17 +52,18 @@ void RegionTable_Init_DeathMountainTrail() {
LOCATION(RC_DMT_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()),
LOCATION(RC_DMT_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_DMT_GOSSIP_STONE, true),
+ LOCATION(RC_BIGGORON_HINT, logic->IsAdult && logic->HasItem(RG_SPEAK_GORON)),
}, {
//Exits
ENTRANCE(RR_DEATH_MOUNTAIN_ROCKFALL, true),
ENTRANCE(RR_DMC_UPPER_LOCAL, true),
- ENTRANCE(RR_DMT_OWL_FLIGHT, logic->IsChild, false),
+ ENTRANCE(RR_DMT_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
ENTRANCE(RR_DMT_GREAT_FAIRY_FOUNTAIN, AnyAgeTime([]{return logic->BlastOrSmash();})),
});
areaTable[RR_DMT_OWL_FLIGHT] = Region("DMT Owl Flight", SCENE_DEATH_MOUNTAIN_TRAIL, {}, {}, {
//Exits
- ENTRANCE(RR_KAK_IMPAS_ROOFTOP, true),
+ ENTRANCE(RR_KAK_IMPAS_ROOFTOP, true, false),
});
areaTable[RR_DMT_COW_GROTTO] = Region("DMT Cow Grotto", SCENE_GROTTOS, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp
index a74a3c52a..a60194dd1 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp
@@ -67,8 +67,8 @@ void RegionTable_Init_DesertColossus() {
areaTable[RR_COLOSSUS_GROTTO] = Region("Colossus Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_COLOSSUS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp
index b8bc5cefa..6f2f2bf31 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp
@@ -9,7 +9,7 @@ void RegionTable_Init_GerudoFortress() {
areaTable[RR_GF_OUTSKIRTS] = Region("Gerudo Fortress Outskirts", SCENE_GERUDOS_FORTRESS, {
//Events
- EVENT_ACCESS(LOGIC_GF_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CLIMB)), // longshot can get up without climb, but jank is hard
+ EVENT_ACCESS(LOGIC_GF_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_SPEAK_GERUDO)), // longshot can get up without climb, but jank is hard
}, {
//Locations
LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()),
@@ -18,7 +18,7 @@ void RegionTable_Init_GerudoFortress() {
//Exits
ENTRANCE(RR_GV_FORTRESS_SIDE, true),
ENTRANCE(RR_TH_1_TORCH_CELL, true),
- ENTRANCE(RR_GF_OUTSIDE_GATE, logic->Get(LOGIC_GF_GATE_OPEN) || (ctx->GetTrickOption(RT_GF_CHILD_SKIP_WASTELAND_GATE) && logic->IsChild)),
+ ENTRANCE(RR_GF_OUTSIDE_GATE, logic->Get(LOGIC_GF_GATE_OPEN) || (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanGroundJump() /* && climb */) && (ctx->GetTrickOption(RT_GF_CHILD_SKIP_WASTELAND_GATE) && logic->IsChild)),
ENTRANCE(RR_GF_NEAR_GROTTO, logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)),
ENTRANCE(RR_GF_OUTSIDE_GTG, logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)),
//You can talk to the guards to get yourself thrown in jail, so long as you have a hookshot to actually end up there
@@ -46,7 +46,7 @@ void RegionTable_Init_GerudoFortress() {
areaTable[RR_GF_OUTSIDE_GTG] = Region("GF Outside GTG", SCENE_GERUDOS_FORTRESS, {
//Events
- EVENT_ACCESS(LOGIC_GTG_GATE_OPEN, (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET))),
+ EVENT_ACCESS(LOGIC_GTG_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_GERUDO)),
}, {}, {
//Exits
ENTRANCE(RR_GF_TO_GTG, logic->Get(LOGIC_GTG_GATE_OPEN) && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES))),
@@ -212,8 +212,8 @@ void RegionTable_Init_GerudoFortress() {
areaTable[RR_GF_HBA_RANGE] = Region("GF HBA Range", SCENE_GERUDOS_FORTRESS, {}, {
//Locations
- LOCATION(RC_GF_HBA_1000_POINTS, logic->IsAdult && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->SummonEpona() && logic->CanUse(RG_FAIRY_BOW) && logic->AtDay),
- LOCATION(RC_GF_HBA_1500_POINTS, logic->IsAdult && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->SummonEpona() && logic->CanUse(RG_FAIRY_BOW) && logic->AtDay),
+ LOCATION(RC_GF_HBA_1000_POINTS, logic->IsAdult && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_GERUDO) && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->SummonEpona() && logic->CanUse(RG_FAIRY_BOW) && logic->AtDay),
+ LOCATION(RC_GF_HBA_1500_POINTS, logic->IsAdult && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_GERUDO) && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->SummonEpona() && logic->CanUse(RG_FAIRY_BOW) && logic->AtDay),
LOCATION(RC_GF_HBA_RANGE_GS, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG) && logic->CanGetNightTimeGS()),
LOCATION(RC_GF_HBA_RANGE_CRATE_1, logic->CanBreakCrates()),
LOCATION(RC_GF_HBA_RANGE_CRATE_2, logic->CanBreakCrates()),
@@ -237,7 +237,7 @@ void RegionTable_Init_GerudoFortress() {
areaTable[RR_GF_OUTSIDE_GATE] = Region("GF Outside Gate", SCENE_GERUDOS_FORTRESS, {
//Events
- EVENT_ACCESS(LOGIC_GF_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD)),
+ EVENT_ACCESS(LOGIC_GF_GATE_OPEN, logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_SPEAK_GERUDO)),
}, {}, {
//Exits
ENTRANCE(RR_GF_OUTSKIRTS, logic->Get(LOGIC_GF_GATE_OPEN)),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp
index dacaabc3a..2c2193f9b 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp
@@ -127,8 +127,8 @@ void RegionTable_Init_GerudoValley() {
areaTable[RR_GV_STORMS_GROTTO] = Region("GV Storms Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_GV_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GV_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GV_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GV_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_GV_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp
index dfef7d4f0..e39dac9e6 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp
@@ -14,15 +14,15 @@ void RegionTable_Init_GoronCity() {
EVENT_ACCESS(LOGIC_GORON_CITY_WOODS_WARP_OPEN, logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || logic->Get(LOGIC_GORON_CITY_CHILD_FIRE)),
EVENT_ACCESS(LOGIC_GORON_CITY_DARUNIAS_DOOR_OPEN_CHILD, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY)),
// bottle animation causes similar complications as stopping goron with Din's Fire, only put in logic when both din's & blue fire tricks enabled
- EVENT_ACCESS(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT, logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) ||
- (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && (logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE)))))),
+ EVENT_ACCESS(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT, logic->IsAdult && logic->HasItem(RG_SPEAK_GORON) && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) ||
+ (ctx->GetTrickOption(RT_GC_LINK_GORON_DINS) && (logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE)))))),
}, {
//Locations
LOCATION(RC_GC_MAZE_LEFT_CHEST, (logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_SILVER_GAUNTLETS) || (ctx->GetTrickOption(RT_GC_LEFTMOST) && logic->HasExplosives() && logic->CanUse(RG_HOVER_BOOTS))) && logic->HasItem(RG_OPEN_CHEST)),
LOCATION(RC_GC_MAZE_CENTER_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)),
LOCATION(RC_GC_MAZE_RIGHT_CHEST, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->HasItem(RG_OPEN_CHEST)),
LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->Get(LOGIC_GORON_CITY_CHILD_FIRE) && (logic->CanUse(RG_BOMB_BAG) || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_POT_STRENGTH)) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_GC_POT)))),
- LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && (logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))),
+ LOCATION(RC_GC_ROLLING_GORON_AS_CHILD, logic->IsChild && logic->HasItem(RG_SPEAK_GORON) && (logic->HasExplosives() || (logic->HasItem(RG_GORONS_BRACELET) && ctx->GetTrickOption(RT_GC_ROLLING_STRENGTH)))),
LOCATION(RC_GC_ROLLING_GORON_AS_ADULT, logic->Get(LOGIC_GORON_CITY_STOP_ROLLING_GORON_AS_ADULT)),
LOCATION(RC_GC_GS_BOULDER_MAZE, logic->IsChild && logic->BlastOrSmash()),
LOCATION(RC_GC_GS_CENTER_PLATFORM, logic->IsAdult && logic->CanAttack()),
@@ -48,10 +48,10 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_MEDIGORON] = Region("GC Medigoron", SCENE_GORON_CITY, {
//Events
- EVENT_ACCESS(LOGIC_MEDIGORON, logic->HasItem(RG_ADULT_WALLET) && GetCheckPrice(RC_GC_MEDIGORON) <= GetWalletCapacity()),
+ EVENT_ACCESS(LOGIC_MEDIGORON, logic->IsAdult && logic->HasItem(RG_ADULT_WALLET) && GetCheckPrice(RC_GC_MEDIGORON) <= GetWalletCapacity() && logic->HasItem(RG_SPEAK_GORON)),
}, {
//Locations
- LOCATION(RC_GC_MEDIGORON, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_MEDIGORON, logic->IsAdult && logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()),
LOCATION(RC_GC_MEDIGORON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_GC_MEDIGORON_GOSSIP_STONE, true),
@@ -93,14 +93,14 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_SHOP] = Region("GC Shop", SCENE_GORON_SHOP, {}, {
//Locations
- LOCATION(RC_GC_SHOP_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_SHOP_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_GORON) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_GORON_CITY, true),
@@ -108,9 +108,9 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_GROTTO] = Region("GC Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_GC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_GC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_GC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_GC_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
index 23c032682..77ac0aa44 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
@@ -9,11 +9,11 @@ void RegionTable_Init_Graveyard() {
//Events
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, (logic->AtDay && logic->CanUse(RG_STICKS)) || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS))),
EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->HasItem(RG_POWER_BRACELET)),
- EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET)),
+ EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Locations
LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))),
- LOCATION(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild && logic->AtNight), //TODO: This needs to change
+ LOCATION(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsChild && logic->AtNight), //TODO: This needs to change
LOCATION(RC_GRAVEYARD_GS_WALL, logic->IsChild && logic->HookshotOrBoomerang() && logic->AtNight && logic->CanGetNightTimeGS()),
LOCATION(RC_GRAVEYARD_GS_BEAN_PATCH, logic->CanSpawnSoilSkull(RG_GRAVEYARD_BEAN_SOUL) && logic->CanAttack()),
LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_GRAVEYARD_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS)),
@@ -87,11 +87,11 @@ void RegionTable_Init_Graveyard() {
areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Region("Graveyard Dampes Grave", SCENE_WINDMILL_AND_DAMPES_GRAVE, {
//Events
- EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanBreakPots()),
+ EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanBreakPots()),
}, {
//Locations
- LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, logic->HasItem(RG_OPEN_CHEST)),
- LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)),
+ LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST)),
+ LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, (logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH)) && logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_GY_DAMPES_GRAVE_POT_1, logic->CanBreakPots()),
LOCATION(RC_GY_DAMPES_GRAVE_POT_2, logic->CanBreakPots()),
LOCATION(RC_GY_DAMPES_GRAVE_POT_3, logic->CanBreakPots()),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp
index d88368fd2..efdbf09eb 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/haunted_wasteland.cpp
@@ -23,7 +23,7 @@ void RegionTable_Init_HauntedWasteland() {
}, {
//Locations
LOCATION(RC_WASTELAND_CHEST, logic->HasFireSource() && logic->HasItem(RG_OPEN_CHEST)),
- LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang() || (logic->IsAdult && ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump() && logic->CanJumpslash())), // need to jumpslash immediately with two handed weapons
LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()),
LOCATION(RC_WASTELAND_NEAR_GS_POT_2, logic->CanBreakPots()),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
index 51ab79445..c3a7eeecc 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
@@ -8,7 +8,7 @@ void RegionTable_Init_HyruleField() {
areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", SCENE_HYRULE_FIELD, {
//Events
EVENT_ACCESS(LOGIC_BIG_POE_KILL, logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->SummonEpona() || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA))),
- EVENT_ACCESS(LOGIC_BORROW_RIGHT_MASKS, logic->IsChild && logic->Get(LOGIC_BORROW_BUNNY_HOOD) && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET)),
+ EVENT_ACCESS(LOGIC_BORROW_RIGHT_MASKS, logic->IsChild && logic->Get(LOGIC_BORROW_BUNNY_HOOD) && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Locations
LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)),
@@ -231,7 +231,7 @@ void RegionTable_Init_HyruleField() {
areaTable[RR_HF_INSIDE_FENCE_GROTTO] = Region("HF Inside Fence Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_HF_DEKU_SCRUB_GROTTO, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_HF_DEKU_SCRUB_GROTTO, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_HF_INSIDE_FENCE_GROTTO_BEEHIVE, logic->CanBreakLowerBeehives()),
LOCATION(RC_HF_FENCE_GROTTO_STORMS_FAIRY, logic->CanUse(RG_SONG_OF_STORMS)),
}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
index 20de2b36a..3e4c92a1d 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
@@ -11,12 +11,12 @@ void RegionTable_Init_Kakariko() {
//Open Gate setting is applied in RR_ROOT
EVENT_ACCESS(LOGIC_KAKARIKO_GATE_OPEN, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER)),
//Needs wallet to be able to get another mask after selling Keaton
- EVENT_ACCESS(LOGIC_BORROW_SKULL_MASK, logic->IsChild && logic->Get(LOGIC_CAN_BORROW_MASKS) && logic->HasItem(RG_CHILD_WALLET)),
+ EVENT_ACCESS(LOGIC_BORROW_SKULL_MASK, logic->IsChild && logic->Get(LOGIC_CAN_BORROW_MASKS) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Locations
LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)),
- LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_POWER_BRACELET) && logic->CanBreakCrates()), // RANDOTODO adjust requirements to cucco settings
- LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay),
+ LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_CLIMB) && logic->HasItem(RG_POWER_BRACELET) && logic->CanBreakCrates() && logic->HasItem(RG_SPEAK_HYLIAN)), // RANDOTODO adjust requirements to cucco settings
+ LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay && logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_KAK_TRADE_POCKET_CUCCO, logic->IsAdult && logic->AtDay && (logic->CanUse(RG_POCKET_EGG) && logic->Get(LOGIC_WAKE_UP_ADULT_TALON))),
//Can kill lower kak skulls with pots
LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->CanGetNightTimeGS() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))),
@@ -109,7 +109,7 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_ROOFTOP] = Region("Kak Rooftop", SCENE_KAKARIKO_VILLAGE, {}, {
//Locations
- LOCATION(RC_KAK_MAN_ON_ROOF, true),
+ LOCATION(RC_KAK_MAN_ON_ROOF, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_KAK_BACKYARD, true),
@@ -139,12 +139,12 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_HOUSE_OF_SKULLTULA] = Region("Kak House of Skulltula", SCENE_HOUSE_OF_SKULLTULA, {}, {
//Locations
- LOCATION(RC_KAK_10_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 10),
- LOCATION(RC_KAK_20_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 20),
- LOCATION(RC_KAK_30_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 30),
- LOCATION(RC_KAK_40_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 40),
- LOCATION(RC_KAK_50_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 50),
- LOCATION(RC_KAK_100_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 100),
+ LOCATION(RC_KAK_10_GOLD_SKULLTULA_REWARD, logic->HasItem(RG_SPEAK_HYLIAN) && logic->GetGSCount() >= 10),
+ LOCATION(RC_KAK_20_GOLD_SKULLTULA_REWARD, logic->HasItem(RG_SPEAK_HYLIAN) && logic->GetGSCount() >= 20),
+ LOCATION(RC_KAK_30_GOLD_SKULLTULA_REWARD, logic->HasItem(RG_SPEAK_HYLIAN) && logic->GetGSCount() >= 30),
+ LOCATION(RC_KAK_40_GOLD_SKULLTULA_REWARD, logic->HasItem(RG_SPEAK_HYLIAN) && logic->GetGSCount() >= 40),
+ LOCATION(RC_KAK_50_GOLD_SKULLTULA_REWARD, logic->HasItem(RG_SPEAK_HYLIAN) && logic->GetGSCount() >= 50),
+ LOCATION(RC_KAK_100_GOLD_SKULLTULA_REWARD, logic->HasItem(RG_SPEAK_HYLIAN) && logic->GetGSCount() >= 100),
}, {
//Exits
ENTRANCE(RR_KAKARIKO_VILLAGE, true),
@@ -190,14 +190,14 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_BAZAAR] = Region("Kak Bazaar", SCENE_BAZAAR, {}, {
//Locations
- LOCATION(RC_KAK_BAZAAR_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_BAZAAR_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_BAZAAR_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_KAKARIKO_VILLAGE, true),
@@ -205,7 +205,7 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_SHOOTING_GALLERY] = Region("Kak Shooting Gallery", SCENE_SHOOTING_GALLERY, {}, {
//Locations
- LOCATION(RC_KAK_SHOOTING_GALLERY_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)),
+ LOCATION(RC_KAK_SHOOTING_GALLERY_REWARD, logic->IsAdult && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanUse(RG_FAIRY_BOW)),
}, {
//Exits
ENTRANCE(RR_KAKARIKO_VILLAGE, true),
@@ -213,14 +213,14 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_POTION_SHOP_FRONT] = Region("Kak Potion Shop Front", SCENE_POTION_SHOP_KAKARIKO, {}, {
//Locations
- LOCATION(RC_KAK_POTION_SHOP_ITEM_1, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_2, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_3, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_4, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_5, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_6, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_7, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_8, logic->IsAdult && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_1, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_2, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_3, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_4, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_5, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_6, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_7, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_8, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_KAKARIKO_VILLAGE, true),
@@ -239,7 +239,7 @@ void RegionTable_Init_Kakariko() {
}, {
//Locations
LOCATION(RC_KAK_TRADE_ODD_MUSHROOM, logic->IsAdult && logic->CanUse(RG_ODD_MUSHROOM)),
- LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && (logic->CanUse(RG_ODD_MUSHROOM) || logic->TradeQuestStep(RG_ODD_MUSHROOM)) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->CanUse(RG_ODD_MUSHROOM) || logic->TradeQuestStep(RG_ODD_MUSHROOM))),
}, {
// Exits
ENTRANCE(RR_KAK_BACKYARD, true),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
index 8b95cae57..049da6a99 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
@@ -8,7 +8,7 @@ void RegionTable_Init_KokiriForest() {
areaTable[RR_KOKIRI_FOREST] = Region("Kokiri Forest", SCENE_KOKIRI_FOREST, {
//Events
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_KOKIRI_FOREST_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS))),
- EVENT_ACCESS(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD)),
+ EVENT_ACCESS(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, logic->IsChild && logic->HasItem(RG_SPEAK_KOKIRI) && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD)),
}, {
//Locations
LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanGetNightTimeGS()),
@@ -100,7 +100,7 @@ void RegionTable_Init_KokiriForest() {
EVENT_ACCESS(LOGIC_STICK_ACCESS, logic->CanGetDekuBabaSticks()),
EVENT_ACCESS(LOGIC_NUT_ACCESS, logic->CanGetDekuBabaNuts()),
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns()),
- EVENT_ACCESS(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD)),
+ EVENT_ACCESS(LOGIC_SHOWED_MIDO_SWORD_AND_SHIELD, logic->IsChild && logic->HasItem(RG_SPEAK_KOKIRI) && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD)),
}, {
//Locations
LOCATION(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()),
@@ -171,14 +171,14 @@ void RegionTable_Init_KokiriForest() {
areaTable[RR_KF_KOKIRI_SHOP] = Region("KF Kokiri Shop", SCENE_KOKIRI_SHOP, {}, {
//Locations
- LOCATION(RC_KF_SHOP_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_KF_SHOP_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_KF_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_KOKIRI) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_KOKIRI_FOREST, true),
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 273239b39..cdd106050 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
@@ -81,13 +81,13 @@ void RegionTable_Init_LakeHylia() {
LOCATION(RC_LH_WARP_PAD_GRASS_2, logic->CanCutShrubs()),
}, {
//Exits
- ENTRANCE(RR_HF_TO_LAKE_HYLIA, true),
- ENTRANCE(RR_LH_FROM_SHORTCUT, true),
- ENTRANCE(RR_LH_OWL_FLIGHT, logic->IsChild),
- ENTRANCE(RR_LH_FISHING_ISLAND, ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->ReachScarecrow() || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)))),
- ENTRANCE(RR_LH_LAB, logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY)),
- ENTRANCE(RR_LH_FROM_WATER_TEMPLE, true),
- ENTRANCE(RR_LH_GROTTO, logic->HasItem(RG_POWER_BRACELET)),
+ ENTRANCE(RR_HF_TO_LAKE_HYLIA, true),
+ ENTRANCE(RR_LH_FROM_SHORTCUT, true),
+ ENTRANCE(RR_LH_OWL_FLIGHT, logic->IsChild && (logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
+ ENTRANCE(RR_LH_FISHING_ISLAND, ((logic->IsChild || logic->Get(LOGIC_WATER_TEMPLE_CLEAR)) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->ReachScarecrow() || CanPlantBean(RR_LAKE_HYLIA, RG_LAKE_HYLIA_BEAN_SOUL)))),
+ ENTRANCE(RR_LH_LAB, logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY)),
+ ENTRANCE(RR_LH_FROM_WATER_TEMPLE, true),
+ ENTRANCE(RR_LH_GROTTO, logic->HasItem(RG_POWER_BRACELET) && (logic->IsAdult || logic->HasItem(RG_SPEAK_DEKU) || logic->HasItem(RG_SPEAK_GERUDO) || logic->HasItem(RG_SPEAK_GORON) || logic->HasItem(RG_SPEAK_HYLIAN) || logic->HasItem(RG_SPEAK_ZORA))),
});
areaTable[RR_LH_FROM_SHORTCUT] = Region("LH From Shortcut", SCENE_LAKE_HYLIA, TIME_DOESNT_PASS, {RA_LAKE_HYLIA}, {}, {}, {
@@ -115,7 +115,7 @@ void RegionTable_Init_LakeHylia() {
areaTable[RR_LH_LAB] = Region("LH Lab", SCENE_LAKESIDE_LABORATORY, {}, {
//Locations
- LOCATION(RC_LH_LAB_DIVE, logic->HasItem(RG_GOLDEN_SCALE) || (ctx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE))),
+ LOCATION(RC_LH_LAB_DIVE, (logic->HasItem(RG_GOLDEN_SCALE) || (ctx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE))) && logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_LH_TRADE_FROG, logic->IsAdult && logic->CanUse(RG_EYEBALL_FROG)),
LOCATION(RC_LH_GS_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->CanBreakCrates()),
LOCATION(RC_LH_LAB_FRONT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)),
@@ -130,43 +130,43 @@ void RegionTable_Init_LakeHylia() {
// TODO: should some of these helpers be done via events instead?
areaTable[RR_LH_FISHING_POND] = Region("LH Fishing Hole", SCENE_FISHING_POND, {}, {
//Locations
- LOCATION(RC_LH_CHILD_FISHING, logic->CanUse(RG_FISHING_POLE) && logic->IsChild),
- LOCATION(RC_LH_CHILD_FISH_1, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_2, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_3, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_4, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_5, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_6, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_7, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_8, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_9, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_10, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_11, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_12, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_13, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_14, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_FISH_15, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_LOACH_1, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_CHILD_LOACH_2, logic->CanUse(RG_FISHING_POLE) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
- LOCATION(RC_LH_ADULT_FISHING, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult),
- LOCATION(RC_LH_ADULT_FISH_1, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_2, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_3, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_4, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_5, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_6, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_7, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_8, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_9, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_10, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_11, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_12, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_13, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_14, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_FISH_15, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_ADULT_LOACH, logic->CanUse(RG_FISHING_POLE) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
- LOCATION(RC_LH_HYRULE_LOACH, logic->CanUse(RG_FISHING_POLE)),
- LOCATION(RC_FISHING_POLE_HINT, true),
+ LOCATION(RC_LH_CHILD_FISHING, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsChild),
+ LOCATION(RC_LH_CHILD_FISH_1, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_2, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_3, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_4, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_5, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_6, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_7, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_8, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_9, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_10, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_11, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_12, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_13, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_14, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_FISH_15, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_LOACH_1, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_CHILD_LOACH_2, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsChild || !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT))),
+ LOCATION(RC_LH_ADULT_FISHING, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult),
+ LOCATION(RC_LH_ADULT_FISH_1, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_2, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_3, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_4, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_5, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_6, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_7, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_8, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_9, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_10, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_11, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_12, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_13, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_14, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_FISH_15, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_ADULT_LOACH, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)),
+ LOCATION(RC_LH_HYRULE_LOACH, logic->CanUse(RG_FISHING_POLE) && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_FISHING_POLE_HINT, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_LH_FISHING_ISLAND, true),
@@ -174,9 +174,9 @@ void RegionTable_Init_LakeHylia() {
areaTable[RR_LH_GROTTO] = Region("LH Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_LH_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_LH_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LH_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LH_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_LH_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
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 b1c4ca380..5b6dd53c4 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
@@ -7,8 +7,8 @@ void RegionTable_Init_LonLonRanch() {
// clang-format off
areaTable[RR_LON_LON_RANCH] = Region("Lon Lon Ranch", SCENE_LON_LON_RANCH, {
//Events
- EVENT_ACCESS(LOGIC_FREED_EPONA, logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay),
- EVENT_ACCESS(LOGIC_LINKS_COW, logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay),
+ EVENT_ACCESS(LOGIC_FREED_EPONA, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay),
+ EVENT_ACCESS(LOGIC_LINKS_COW, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay),
}, {
//Locations
LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_FAIRY_OCARINA) && logic->AtDay),
@@ -36,7 +36,7 @@ void RegionTable_Init_LonLonRanch() {
areaTable[RR_LLR_TALONS_HOUSE] = Region("LLR Talons House", SCENE_LON_LON_BUILDINGS, {}, {
//Locations
- LOCATION(RC_LLR_TALONS_CHICKENS, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild && logic->AtDay && logic->HasItem(RG_ZELDAS_LETTER)),
+ LOCATION(RC_LLR_TALONS_CHICKENS, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->IsChild && logic->AtDay && logic->HasItem(RG_ZELDAS_LETTER)),
LOCATION(RC_LLR_TALONS_HOUSE_POT_1, logic->CanBreakPots()),
LOCATION(RC_LLR_TALONS_HOUSE_POT_2, logic->CanBreakPots()),
LOCATION(RC_LLR_TALONS_HOUSE_POT_3, logic->CanBreakPots()),
@@ -66,9 +66,9 @@ void RegionTable_Init_LonLonRanch() {
areaTable[RR_LLR_GROTTO] = Region("LLR Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_LLR_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
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 b91c39b6d..4d5b015a8 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
@@ -14,7 +14,7 @@ void RegionTable_Init_LostWoods() {
//Events
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairyExceptSuns() || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS))),
EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->IsChild && logic->CanCutShrubs()),
- EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET)),
+ EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_KOKIRI) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Locations
LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)),
@@ -31,7 +31,7 @@ void RegionTable_Init_LostWoods() {
//5 buttons => 100%
LOCATION(RC_LW_OCARINA_MEMORY_GAME, logic->IsChild && logic->HasItem(RG_FAIRY_OCARINA) && logic->OcarinaButtons() >= 5),
LOCATION(RC_LW_TARGET_IN_WOODS, logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)),
- LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, logic->CanSpawnSoilSkull(RG_LOST_WOODS_BRIDGE_BEAN_SOUL) && logic->CanAttack()),
//RANDOTODO handle collecting some of these as you leave the shortcut from the other side
LOCATION(RC_LW_SHORTCUT_RUPEE_1, logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_BOOMERANG))),
@@ -67,8 +67,8 @@ void RegionTable_Init_LostWoods() {
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanUse(RG_STICKS) || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_LOST_WOODS_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS))),
}, {
//Locations
- LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, logic->IsChild && logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_LW_GS_ABOVE_THEATER, logic->IsAdult && ((CanPlantBean(RR_LW_BEYOND_MIDO, RG_LOST_WOODS_BEAN_SOUL) && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)) || (ctx->GetTrickOption(RT_LW_GS_BEAN) && logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_BOMBCHU_5) || logic->CanUse(RG_DINS_FIRE)))) && logic->CanGetNightTimeGS()),
LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, logic->CanSpawnSoilSkull(RG_LOST_WOODS_BEAN_SOUL) && (logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA) || (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && logic->CanReflectNuts()))),
LOCATION(RC_LW_BOULDER_RUPEE, logic->BlastOrSmash()),
@@ -111,7 +111,7 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_DEKU_THEATER] = Region("Deku Theater", SCENE_GROTTOS, {}, {
//Locations
LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->CanUse(RG_SKULL_MASK)),
- LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->CanUse(RG_MASK_OF_TRUTH)),
+ LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->CanUse(RG_MASK_OF_TRUTH) && logic->CanUse(RG_SPEAK_DEKU)),
}, {
//Exits
ENTRANCE(RR_LW_BEYOND_MIDO, true),
@@ -119,8 +119,8 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_LW_SCRUBS_GROTTO] = Region("LW Scrubs Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
index 394a486e5..19ca9a4b3 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
@@ -55,8 +55,8 @@ void RegionTable_Init_Market() {
EVENT_ACCESS(LOGIC_CAN_EMPTY_BIG_POES, logic->IsAdult),
}, {
//Locations
- LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->Get(LOGIC_BIG_POE_KILL) || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
- LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))),
+ LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->Get(LOGIC_BIG_POE_KILL) || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
+ LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild && logic->CanBreakCrates() && (logic->HasItem(RG_POWER_BRACELET) || logic->CanKillEnemy(RE_GOLD_SKULLTULA))),
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_3, logic->IsChild && logic->CanBreakPots()),
@@ -124,14 +124,14 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_BAZAAR] = Region("Market Bazaar", SCENE_BAZAAR, {}, {
//Locations
- LOCATION(RC_MARKET_BAZAAR_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BAZAAR_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_THE_MARKET, true),
@@ -142,11 +142,11 @@ void RegionTable_Init_Market() {
//Currently, mask swap in menu doesn't need access to the mask shop
//If it is forced on/a setting, a copy of these events should be added to root
//it also doesn't need you to open kak gate, but that might be best treated as a bug
- EVENT_ACCESS(LOGIC_CAN_BORROW_MASKS, logic->HasItem(RG_ZELDAS_LETTER) && logic->Get(LOGIC_KAKARIKO_GATE_OPEN)),
- EVENT_ACCESS(LOGIC_BORROW_SKULL_MASK, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
- EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
- EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
- EVENT_ACCESS(LOGIC_BORROW_RIGHT_MASKS, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
+ EVENT_ACCESS(LOGIC_CAN_BORROW_MASKS, logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_KAKARIKO_GATE_OPEN)),
+ EVENT_ACCESS(LOGIC_BORROW_SKULL_MASK, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
+ EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
+ EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
+ EVENT_ACCESS(LOGIC_BORROW_RIGHT_MASKS, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)),
}, {
//Locations
LOCATION(RC_MASK_SHOP_HINT, true),
@@ -157,7 +157,7 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_SHOOTING_GALLERY] = Region("Market Shooting Gallery", SCENE_SHOOTING_GALLERY, {}, {
//Locations
- LOCATION(RC_MARKET_SHOOTING_GALLERY_REWARD, logic->IsChild && logic->HasItem(RG_CHILD_WALLET)),
+ LOCATION(RC_MARKET_SHOOTING_GALLERY_REWARD, logic->IsChild && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_THE_MARKET, true),
@@ -165,7 +165,7 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_BOMBCHU_BOWLING] = Region("Market Bombchu Bowling", SCENE_BOMBCHU_BOWLING_ALLEY, {
//Events
- EVENT_ACCESS(LOGIC_COULD_PLAY_BOWLING, logic->HasItem(RG_CHILD_WALLET)),
+ EVENT_ACCESS(LOGIC_COULD_PLAY_BOWLING, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Locations
LOCATION(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, logic->Get(LOGIC_COULD_PLAY_BOWLING) && logic->BombchusEnabled()),
@@ -177,14 +177,14 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_POTION_SHOP] = Region("Market Potion Shop", SCENE_POTION_SHOP_MARKET, {}, {
//Locations
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_THE_MARKET, true),
@@ -192,18 +192,18 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Region("Market Treasure Chest Game", SCENE_TREASURE_BOX_SHOP, {}, {
//Locations
- LOCATION(RC_GREG_HINT, logic->HasItem(RG_CHILD_WALLET)),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_GREG_HINT, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->HasItem(RG_OPEN_CHEST) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(SCENE_TREASURE_BOX_SHOP, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
}, {
//Exits
ENTRANCE(RR_THE_MARKET, true),
@@ -211,14 +211,14 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_BOMBCHU_SHOP] = Region("Market Bombchu Shop", SCENE_BOMBCHU_SHOP, {}, {
//Locations
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_MARKET_BACK_ALLEY, true),
@@ -226,7 +226,7 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_DOG_LADY_HOUSE] = Region("Market Dog Lady House", SCENE_DOG_LADY_HOUSE, {}, {
//Locations
- LOCATION(RC_MARKET_LOST_DOG, logic->IsChild && logic->AtNight),
+ LOCATION(RC_MARKET_LOST_DOG, logic->IsChild && logic->AtNight && logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_MK_LOST_DOG_HOUSE_CRATE, logic->CanBreakCrates()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp
index 4884c43c0..ce5d08f04 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/sacred_forest_meadow.cpp
@@ -84,8 +84,8 @@ void RegionTable_Init_SacredForestMeadow() {
areaTable[RR_SFM_STORMS_GROTTO] = Region("SFM Storms Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_SFM_STORMS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp
index fed89f77a..8871ee293 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/temple_of_time.cpp
@@ -33,7 +33,7 @@ void RegionTable_Init_TempleOfTime() {
LOCATION(RC_TOT_LIGHT_ARROWS_CUTSCENE, logic->IsAdult && logic->CanTriggerLACS()),
LOCATION(RC_ALTAR_HINT_CHILD, logic->IsChild),
LOCATION(RC_ALTAR_HINT_ADULT, logic->IsAdult),
- LOCATION(RC_TOT_SHEIK_HINT, logic->IsAdult),
+ LOCATION(RC_TOT_SHEIK_HINT, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
ENTRANCE(RR_TOT_ENTRANCE, true),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp
index 7f62dadd7..747354103 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/thieves_hideout.cpp
@@ -8,7 +8,7 @@ using namespace Rando;
void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_1_TORCH_CELL] = Region("Thieves Hideout 1 Torch Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EVENT_ACCESS(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)),
+ EVENT_ACCESS(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN)),
EVENT_ACCESS(LOGIC_TH_RESCUED_ALL_CARPENTERS, logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER)),
}, {
//Locations
@@ -26,7 +26,7 @@ void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_DOUBLE_CELL] = Region("Thieves Hideout Double Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EVENT_ACCESS(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)),
+ EVENT_ACCESS(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN)),
EVENT_ACCESS(LOGIC_TH_RESCUED_ALL_CARPENTERS, logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER)),
}, {
//Locations
@@ -50,7 +50,7 @@ void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_DEAD_END_CELL] = Region("Thieves Hideout Dead End Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EVENT_ACCESS(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)),
+ EVENT_ACCESS(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN)),
EVENT_ACCESS(LOGIC_TH_RESCUED_ALL_CARPENTERS, logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER)),
}, {
//Locations
@@ -64,7 +64,7 @@ void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_STEEP_SLOPE_CELL] = Region("Thieves Hideout Steep Slope Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EVENT_ACCESS(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR)),
+ EVENT_ACCESS(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER, logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN)),
EVENT_ACCESS(LOGIC_TH_RESCUED_ALL_CARPENTERS, logic->SmallKeys(SCENE_THIEVES_HIDEOUT, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->Get(LOGIC_TH_COULD_FREE_1_TORCH_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DOUBLE_CELL_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_DEAD_END_CARPENTER) && logic->Get(LOGIC_TH_COULD_FREE_SLOPE_CARPENTER)),
}, {
//Locations
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp
index 405fef7dc..fe82c7d0c 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_domain.cpp
@@ -15,9 +15,9 @@ void RegionTable_Init_ZorasDomain() {
EVENT_ACCESS(LOGIC_DELIVER_RUTOS_LETTER, logic->CanUse(RG_RUTOS_LETTER) && logic->IsChild && ctx->GetOption(RSK_ZORAS_FOUNTAIN).IsNot(RO_ZF_OPEN)),
}, {
//Locations
- LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->IsChild),
+ LOCATION(RC_ZD_DIVING_MINIGAME, logic->HasItem(RG_BRONZE_SCALE) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_ZORA) && logic->IsChild),
LOCATION(RC_ZD_CHEST, logic->IsChild && logic->CanUse(RG_STICKS) && logic->HasItem(RG_OPEN_CHEST)),
- LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED)),
+ LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->HasItem(RG_SPEAK_ZORA)),
LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->Get(LOGIC_KING_ZORA_THAWED) && logic->CanUse(RG_PRESCRIPTION)),
LOCATION(RC_ZD_GS_FROZEN_WATERFALL, logic->IsAdult && (logic->HookshotOrBoomerang() || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || (logic->CanUse(RG_MAGIC_SINGLE) && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (ctx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()),
LOCATION(RC_ZD_FISH_1, logic->IsChild && logic->HasBottle()),
@@ -64,14 +64,14 @@ void RegionTable_Init_ZorasDomain() {
areaTable[RR_ZD_SHOP] = Region("ZD Shop", SCENE_ZORA_SHOP, {}, {
//Locations
- LOCATION(RC_ZD_SHOP_ITEM_1, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_2, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_3, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_4, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_5, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_6, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_7, GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZD_SHOP_ITEM_8, GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZD_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_ZORA) && GetCheckPrice() <= GetWalletCapacity()),
}, {
//Exits
ENTRANCE(RR_ZORAS_DOMAIN, true),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
index 9064607b4..9c897538d 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
@@ -32,7 +32,7 @@ void RegionTable_Init_ZoraRiver() {
EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CallGossipFairy() || (logic->IsChild && logic->CanUse(RG_STICKS)) || (logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->HasItem(RG_ZORAS_RIVER_BEAN_SOUL) && logic->CanUse(RG_SONG_OF_STORMS))),
}, {
//Locations
- LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->IsChild && GetCheckPrice() <= GetWalletCapacity()/* && CanUse(SPEAK_HYLIAN)*/),
+ LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->IsChild && logic->HasItem(RG_SPEAK_HYLIAN) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_ZR_FROGS_OCARINA_GAME, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_SARIAS_SONG) && logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_ZR_FROGS_IN_THE_RAIN, logic->IsChild && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_ZR_FROGS_ZELDAS_LULLABY, logic->IsChild && logic->CanUse(RG_ZELDAS_LULLABY)),
@@ -145,8 +145,8 @@ void RegionTable_Init_ZoraRiver() {
areaTable[RR_ZR_STORMS_GROTTO] = Region("ZR Storms Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
- LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
+ LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()),
LOCATION(RC_ZR_STORMS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp
index 25f6cbc97..690e9f5c3 100644
--- a/soh/soh/Enhancements/randomizer/location_list.cpp
+++ b/soh/soh/Enhancements/randomizer/location_list.cpp
@@ -991,6 +991,7 @@ void Rando::StaticData::InitLocationTable() {
locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "ToT Adult Altar Hint");
locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT, RCQUEST_BOTH, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint");
locationTable[RC_TOT_SHEIK_HINT] = Location::OtherHint(RC_TOT_SHEIK_HINT, RCQUEST_BOTH, ACTOR_EN_XC, SCENE_TEMPLE_OF_TIME, "Ocarina of Time Hint");
+ locationTable[RC_BIGGORON_HINT] = Location::OtherHint(RC_BIGGORON_HINT, RCQUEST_BOTH, ACTOR_EN_GO2, SCENE_DEATH_MOUNTAIN_TRAIL, "Biggoron Hint");
locationTable[RC_MASK_SHOP_HINT] = Location::OtherHint(RC_MASK_SHOP_HINT, RCQUEST_BOTH, ACTOR_ID_MAX, SCENE_HAPPY_MASK_SHOP, "Mask Shop Hint");
locationTable[RC_TRIFORCE_COMPLETED] = Location::Base(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE);
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index 9935d9f63..6dccaa740 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -150,6 +150,12 @@ bool Logic::HasItem(RandomizerGet itemName) {
case RG_ZELDAS_LETTER:
case RG_WEIRD_EGG:
case RG_GREG_RUPEE:
+ case RG_SPEAK_DEKU:
+ case RG_SPEAK_GERUDO:
+ case RG_SPEAK_GORON:
+ case RG_SPEAK_HYLIAN:
+ case RG_SPEAK_KOKIRI:
+ case RG_SPEAK_ZORA:
// Ocarina Buttons
case RG_OCARINA_A_BUTTON:
case RG_OCARINA_C_LEFT_BUTTON:
@@ -1606,6 +1612,12 @@ std::map Logic::RandoGetToRandInf = {
{ RG_MASK_OF_TRUTH, RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH },
{ RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY },
{ RG_GREG_RUPEE, RAND_INF_GREG_FOUND },
+ { RG_SPEAK_DEKU, RAND_INF_CAN_SPEAK_DEKU },
+ { RG_SPEAK_GERUDO, RAND_INF_CAN_SPEAK_GERUDO },
+ { RG_SPEAK_GORON, RAND_INF_CAN_SPEAK_GORON },
+ { RG_SPEAK_HYLIAN, RAND_INF_CAN_SPEAK_HYLIAN },
+ { RG_SPEAK_KOKIRI, RAND_INF_CAN_SPEAK_KOKIRI },
+ { RG_SPEAK_ZORA, RAND_INF_CAN_SPEAK_ZORA },
{ 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 },
@@ -2004,6 +2016,12 @@ void Logic::ApplyItemEffect(Item& item, bool state) {
case RG_GERUDO_MASK:
case RG_MASK_OF_TRUTH:
case RG_GREG_RUPEE:
+ case RG_SPEAK_DEKU:
+ case RG_SPEAK_GERUDO:
+ case RG_SPEAK_GORON:
+ case RG_SPEAK_HYLIAN:
+ case RG_SPEAK_KOKIRI:
+ case RG_SPEAK_ZORA:
case RG_FISHING_POLE:
case RG_GUARD_HOUSE_KEY:
case RG_MARKET_BAZAAR_KEY:
diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
index f9146bf8b..3eddec7e6 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -262,6 +262,9 @@ void Settings::CreateOptionDescriptions() {
"Shuffle the ability to grab as a progressive upgrade before Goron Bracelet.";
mOptionDescriptions[RSK_SHUFFLE_CLIMB] = "Shuffle the ability to climb ladders into the item pool.";
mOptionDescriptions[RSK_SHUFFLE_CRAWL] = "Shuffles the ability to use crawlspaces into the item pool.";
+ mOptionDescriptions[RSK_SHUFFLE_SPEAK] =
+ "Shuffle ability to speak to NPCs. 6 jabbernuts will be shuffled:\nDeku, Gerudo, Goron, Hylian, Kokiri, "
+ "Zora\nKaepora Gaebora speaks any language.";
mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST] = "Shuffles the ability to open chests into the item pool.";
mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling "
"\"Skip Child Zelda\" disables this feature.\n"
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index affc1c497..1162e64a2 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -127,6 +127,12 @@ std::map randomizerGetToRandInf = {
{ RG_CLIMB, RAND_INF_CAN_CLIMB },
{ RG_CRAWL, RAND_INF_CAN_CRAWL },
{ RG_OPEN_CHEST, RAND_INF_CAN_OPEN_CHEST },
+ { RG_SPEAK_DEKU, RAND_INF_CAN_SPEAK_DEKU },
+ { RG_SPEAK_GERUDO, RAND_INF_CAN_SPEAK_GERUDO },
+ { RG_SPEAK_GORON, RAND_INF_CAN_SPEAK_GORON },
+ { RG_SPEAK_HYLIAN, RAND_INF_CAN_SPEAK_HYLIAN },
+ { RG_SPEAK_KOKIRI, RAND_INF_CAN_SPEAK_KOKIRI },
+ { RG_SPEAK_ZORA, RAND_INF_CAN_SPEAK_ZORA },
{ RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER },
{ RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG },
{ RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG },
diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h
index b2211cad9..0c0c18fb9 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -320,6 +320,7 @@ typedef enum {
LOGIC_SPIRIT_SUN_BLOCK_TORCH,
LOGIC_SPIRIT_BOUNDERS_SILVERS,
LOGIC_SPIRIT_STATUE_SOUTH_DOOR,
+ LOGIC_SPIRIT_NABOORU_KIDNAPPED,
LOGIC_SPIRIT_PLATFORM_LOWERED,
LOGIC_SPIRIT_4F_SWITCH,
LOGIC_SPIRIT_PUSHED_4F_MIRRORS,
@@ -3339,6 +3340,7 @@ typedef enum {
RC_ALTAR_HINT_CHILD,
RC_ALTAR_HINT_ADULT,
RC_FISHING_POLE_HINT,
+ RC_BIGGORON_HINT,
RC_TOT_SHEIK_HINT,
RC_MASK_SHOP_HINT,
RC_DMC_UPPER_GROTTO_FISH,
@@ -4636,6 +4638,12 @@ typedef enum {
RG_CLIMB,
RG_CRAWL,
RG_OPEN_CHEST,
+ RG_SPEAK_DEKU,
+ RG_SPEAK_GERUDO,
+ RG_SPEAK_GORON,
+ RG_SPEAK_HYLIAN,
+ RG_SPEAK_KOKIRI,
+ RG_SPEAK_ZORA,
RG_CHILD_WALLET,
RG_PROGRESSIVE_BOMBCHU_BAG,
RG_QUIVER_INF,
@@ -5851,8 +5859,10 @@ typedef enum {
RHT_MASK_ZORA,
RHT_MASK_GERUDO,
RHT_MASK_TRUTH,
+ RHT_BRONZE_SCALE,
RHT_CLIMB,
RHT_CRAWL,
+ RHT_SPEAK,
RHT_OPEN_CHEST,
RHT_FISHING_POLE,
RHT_SKELETON_KEY,
@@ -6452,6 +6462,7 @@ typedef enum {
RSK_SHUFFLE_GRAB,
RSK_SHUFFLE_CLIMB,
RSK_SHUFFLE_CRAWL,
+ RSK_SHUFFLE_SPEAK,
RSK_SHUFFLE_OPEN_CHEST,
RSK_STARTING_DEKU_SHIELD,
RSK_STARTING_KOKIRI_SWORD,
diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h
index de7b8750c..5ce30b484 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -1142,6 +1142,12 @@ DEFINE_RAND_INF(RAND_INF_CAN_SWIM)
DEFINE_RAND_INF(RAND_INF_CAN_CLIMB)
DEFINE_RAND_INF(RAND_INF_CAN_CRAWL)
DEFINE_RAND_INF(RAND_INF_CAN_GRAB)
+DEFINE_RAND_INF(RAND_INF_CAN_SPEAK_DEKU)
+DEFINE_RAND_INF(RAND_INF_CAN_SPEAK_GERUDO)
+DEFINE_RAND_INF(RAND_INF_CAN_SPEAK_GORON)
+DEFINE_RAND_INF(RAND_INF_CAN_SPEAK_HYLIAN)
+DEFINE_RAND_INF(RAND_INF_CAN_SPEAK_KOKIRI)
+DEFINE_RAND_INF(RAND_INF_CAN_SPEAK_ZORA)
DEFINE_RAND_INF(RAND_INF_CAN_OPEN_CHEST)
DEFINE_RAND_INF(RAND_INF_HAS_WALLET)
diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
index 525e5082c..2edbfede3 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
@@ -57,6 +57,7 @@ static WidgetInfo gregTracking;
static WidgetInfo triforcePieceTracking;
static WidgetInfo beanSoulsTracking;
static WidgetInfo bossSoulsTracking;
+static WidgetInfo jabberNutsTracking;
static WidgetInfo ocarinaButtonTracking;
static WidgetInfo overworldKeysTracking;
static WidgetInfo fishingPoleTracking;
@@ -182,6 +183,12 @@ std::vector bossSoulItems = {
ITEM_TRACKER_ITEM(RG_GANON_SOUL, 0, DrawItem),
};
+std::vector jabbernutItems = {
+ ITEM_TRACKER_ITEM(RG_SPEAK_DEKU, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_GERUDO, 0, DrawItem),
+ ITEM_TRACKER_ITEM(RG_SPEAK_GORON, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_HYLIAN, 0, DrawItem),
+ ITEM_TRACKER_ITEM(RG_SPEAK_KOKIRI, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_ZORA, 0, DrawItem),
+};
+
std::vector ocarinaButtonItems = {
// Hack for right now, just gonna draw ocarina buttons as ocarinas.
// Will replace with other macro once we have a custom texture
@@ -303,6 +310,11 @@ std::map itemTrackerBossShortNames = {
{ RG_BONGO_BONGO_SOUL, "BONGO" }, { RG_TWINROVA_SOUL, "TWIN" }, { RG_GANON_SOUL, "GANON" },
};
+std::map itemTrackerJabberNutShortNames = {
+ { RG_SPEAK_DEKU, "DEKU" }, { RG_SPEAK_GERUDO, "GERUDO" }, { RG_SPEAK_GORON, "GORON" },
+ { RG_SPEAK_HYLIAN, "HYLIAN" }, { RG_SPEAK_KOKIRI, "KOKIRI" }, { RG_SPEAK_ZORA, "ZORA" },
+};
+
std::map itemTrackerOcarinaButtonShortNames = {
{ RG_OCARINA_A_BUTTON, "A" }, { RG_OCARINA_C_UP_BUTTON, "C-U" }, { RG_OCARINA_C_DOWN_BUTTON, "C-D" },
{ RG_OCARINA_C_LEFT_BUTTON, "C-L" }, { RG_OCARINA_C_RIGHT_BUTTON, "C-R" },
@@ -976,6 +988,37 @@ void DrawItem(ItemTrackerItem item) {
itemName = "Ganon's Soul";
break;
+ case RG_SPEAK_DEKU:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_DEKU);
+ itemName = "Deku Jabber Nut";
+ break;
+ case RG_SPEAK_GERUDO:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GERUDO);
+ itemName = "Gerudo Jabber Nut";
+ break;
+ case RG_SPEAK_GORON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GORON);
+ itemName = "Goron Jabber Nut";
+ break;
+ case RG_SPEAK_HYLIAN:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN);
+ itemName = "Hylian Jabber Nut";
+ break;
+ case RG_SPEAK_KOKIRI:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI);
+ itemName = "Kokiri Jabber Nut";
+ break;
+ case RG_SPEAK_ZORA:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA);
+ itemName = "Zora Jabber Nut";
+ break;
+
case RG_OCARINA_A_BUTTON:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A);
@@ -1188,6 +1231,16 @@ void DrawItem(ItemTrackerItem item) {
ImGui::PopStyleColor();
}
+ if (item.id >= RG_SPEAK_DEKU && item.id <= RG_SPEAK_ZORA) {
+ ImVec2 p = ImGui::GetCursorScreenPos();
+ std::string name = itemTrackerJabberNutShortNames[item.id];
+ ImGui::SetCursorScreenPos(
+ ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(name.c_str()).x / 2), p.y - (iconSize + 13)));
+ ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE);
+ ImGui::Text("%s", name.c_str());
+ ImGui::PopStyleColor();
+ }
+
if (item.id >= RG_OCARINA_A_BUTTON && item.id <= RG_OCARINA_C_RIGHT_BUTTON) {
ImVec2 p = ImGui::GetCursorScreenPos();
std::string ocarinaButtonName = itemTrackerOcarinaButtonShortNames[item.id];
@@ -1674,8 +1727,8 @@ void UpdateVectors() {
// If we're adding boss souls to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.BossSouls"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) {
- //...add empty items on the main window to get the souls on their own row. (Too many to sit with Greg/Triforce
- // pieces)
+ //...add empty items on the main window to get the souls on their own row
+ // (Too many to sit with Greg/Triforce pieces)
while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
}
@@ -1684,11 +1737,23 @@ void UpdateVectors() {
mainWindowItems.insert(mainWindowItems.end(), bossSoulItems.begin(), bossSoulItems.end());
}
+ // If we're adding jabbernuts to the main window...
+ if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.JabberNuts"), SECTION_DISPLAY_HIDDEN) ==
+ SECTION_DISPLAY_MAIN_WINDOW) {
+ // there are 6 jabbernuts, perfect for a row
+ while (mainWindowItems.size() % 6) {
+ mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
+ }
+
+ // Add jabbernuts
+ mainWindowItems.insert(mainWindowItems.end(), jabbernutItems.begin(), jabbernutItems.end());
+ }
+
// If we're adding ocarina buttons to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) {
- //...add empty items on the main window to get the buttons on their own row. (Too many to sit with Greg/Triforce
- // pieces/boss souls)
+ //...add empty items on the main window to get the buttons on their own row.
+ // (Too many to sit with Greg/Triforce pieces/boss souls)
while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
}
@@ -1700,8 +1765,8 @@ void UpdateVectors() {
// If we're adding overworld keys to the main window...
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_MAIN_WINDOW) {
- //...add empty items on the main window to get the keys on their own row. (Too many to sit with Greg/Triforce
- // pieces/boss souls/ocarina buttons)
+ //...add empty items on the main window to get the keys on their own row.
+ // (Too many to sit with Greg/Triforce pieces/boss souls/ocarina buttons)
while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
}
@@ -1881,6 +1946,13 @@ void ItemTrackerWindow::DrawElement() {
EndFloatingWindows();
}
+ if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.JabberNuts"), SECTION_DISPLAY_HIDDEN) ==
+ SECTION_DISPLAY_SEPARATE) {
+ BeginFloatingWindows("Jabber Nut Tracker");
+ DrawItemsInRows(jabbernutItems);
+ EndFloatingWindows();
+ }
+
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_SEPARATE) {
BeginFloatingWindows("Ocarina Button Tracker");
@@ -2115,6 +2187,7 @@ void ItemTrackerSettingsWindow::DrawElement() {
SohGui::mSohMenu->MenuDrawItem(triforcePieceTracking, 250, THEME_COLOR);
SohGui::mSohMenu->MenuDrawItem(beanSoulsTracking, 250, THEME_COLOR);
SohGui::mSohMenu->MenuDrawItem(bossSoulsTracking, 250, THEME_COLOR);
+ SohGui::mSohMenu->MenuDrawItem(jabberNutsTracking, 250, THEME_COLOR);
SohGui::mSohMenu->MenuDrawItem(ocarinaButtonTracking, 250, THEME_COLOR);
SohGui::mSohMenu->MenuDrawItem(overworldKeysTracking, 250, THEME_COLOR);
SohGui::mSohMenu->MenuDrawItem(fishingPoleTracking, 250, THEME_COLOR);
@@ -2252,6 +2325,18 @@ void RegisterItemTrackerWidgets() {
;
SohGui::mSohMenu->AddSearchWidget({ bossSoulsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" });
+ jabberNutsTracking = { .name = "Jabber Nuts", .type = WidgetType::WIDGET_CVAR_COMBOBOX };
+ jabberNutsTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.JabberNuts"))
+ .Options(ComboboxOptions()
+ .DefaultIndex(SECTION_DISPLAY_HIDDEN)
+ .ComponentAlignment(ComponentAlignments::Right)
+ .LabelPosition(LabelPositions::Far)
+ .Color(THEME_COLOR)
+ .ComboMap(displayTypes))
+ .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; });
+ ;
+ SohGui::mSohMenu->AddSearchWidget({ jabberNutsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" });
+
triforcePieceCount = { .name = "Triforce Piece Count Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX };
triforcePieceCount.CVar(CVAR_TRACKER_ITEM("TriforcePieceCounts"))
.Options(ComboboxOptions()
diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp
index 665ffedfe..a2522ce5a 100644
--- a/soh/soh/Enhancements/randomizer/savefile.cpp
+++ b/soh/soh/Enhancements/randomizer/savefile.cpp
@@ -256,7 +256,6 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO);
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
- Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE);
if (Randomizer_GetSettingValue(RSK_FOREST) == RO_CLOSED_FOREST_OFF) {
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
@@ -325,6 +324,16 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetRandomizerInf(RAND_INF_CAN_CRAWL);
}
+ if (Randomizer_GetSettingValue(RSK_SHUFFLE_SPEAK) == RO_GENERIC_OFF) {
+ Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE);
+ Flags_SetRandomizerInf(RAND_INF_CAN_SPEAK_DEKU);
+ Flags_SetRandomizerInf(RAND_INF_CAN_SPEAK_GERUDO);
+ Flags_SetRandomizerInf(RAND_INF_CAN_SPEAK_GORON);
+ Flags_SetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN);
+ Flags_SetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI);
+ Flags_SetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA);
+ }
+
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OPEN_CHEST) == RO_GENERIC_OFF) {
Flags_SetRandomizerInf(RAND_INF_CAN_OPEN_CHEST);
}
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index e9faf4fc2..8468bcf20 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -788,6 +788,7 @@ void Settings::CreateOptions() {
OPT_BOOL(RSK_SHUFFLE_CLIMB, "Shuffle Climb", CVAR_RANDOMIZER_SETTING("ShuffleClimb"), mOptionDescriptions[RSK_SHUFFLE_CLIMB]);
OPT_BOOL(RSK_SHUFFLE_CRAWL, "Shuffle Crawl", CVAR_RANDOMIZER_SETTING("ShuffleCrawl"), mOptionDescriptions[RSK_SHUFFLE_CRAWL]);
OPT_BOOL(RSK_SHUFFLE_GRAB, "Shuffle Grab", CVAR_RANDOMIZER_SETTING("ShuffleGrab"), mOptionDescriptions[RSK_SHUFFLE_GRAB]);
+ OPT_BOOL(RSK_SHUFFLE_SPEAK, "Shuffle Jabber Nuts", CVAR_RANDOMIZER_SETTING("ShuffleSpeak"), mOptionDescriptions[RSK_SHUFFLE_SPEAK]);
OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]);
OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
@@ -2400,6 +2401,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_GRAB],
&mOptions[RSK_SHUFFLE_CLIMB],
&mOptions[RSK_SHUFFLE_CRAWL],
+ &mOptions[RSK_SHUFFLE_SPEAK],
&mOptions[RSK_SHUFFLE_OPEN_CHEST],
&mOptions[RSK_SHUFFLE_BEAN_SOULS],
&mOptions[RSK_ROCS_FEATHER],
@@ -2622,6 +2624,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_GRAB],
&mOptions[RSK_SHUFFLE_CLIMB],
&mOptions[RSK_SHUFFLE_CRAWL],
+ &mOptions[RSK_SHUFFLE_SPEAK],
&mOptions[RSK_SHUFFLE_OPEN_CHEST],
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp
index 2de5a2c25..3290165ef 100644
--- a/soh/soh/Enhancements/randomizer/static_data.cpp
+++ b/soh/soh/Enhancements/randomizer/static_data.cpp
@@ -208,9 +208,9 @@ std::unordered_map StaticData::staticHintInfoMap
{RH_MALON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MALON_HINT_TURNING_EVIL, RHT_MALON_HINT_HOW_IS_EPONA, RHT_MALON_HINT_OBSTICLE_COURSE, RHT_MALON_HINT_INGO_TEMPTED}, RSK_MALON_HINT, true, {RC_KF_LINKS_HOUSE_COW})},
{RH_BIG_POES_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIG_POES_HINT}, RSK_BIG_POES_HINT, true, {RC_MARKET_10_BIG_POES})},
{RH_CHICKENS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_CHICKENS_HINT}, RSK_CHICKENS_HINT, true, {RC_KAK_ANJU_AS_CHILD})},
- {RH_BIGGORON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIGGORON_HINT}, RSK_BIGGORON_HINT, true, {RC_DMT_TRADE_CLAIM_CHECK})},
+ {RH_BIGGORON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIGGORON_HINT}, RSK_BIGGORON_HINT, true, {RC_DMT_TRADE_CLAIM_CHECK}, {}, {RC_BIGGORON_HINT})},
{RH_FROGS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_FROGS_HINT}, RSK_FROGS_HINT, true, {RC_ZR_FROGS_OCARINA_GAME})},
- {RH_OOT_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_OOT_HINT}, RSK_OOT_HINT, true, {RC_HF_OCARINA_OF_TIME_ITEM, RC_SONG_FROM_OCARINA_OF_TIME}, {}, {RC_TOT_SHEIK_HINT})},
+ {RH_OOT_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_OOT_HINT}, RSK_OOT_HINT, true, {RC_HF_OCARINA_OF_TIME_ITEM, RC_SONG_FROM_OCARINA_OF_TIME}, {}, {RC_TOT_SHEIK_HINT})},
{RH_MASK_SHOP_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MASK_SHOP_HINT}, RSK_MASK_SHOP_HINT, true, {RC_DEKU_THEATER_SKULL_MASK, RC_DEKU_THEATER_MASK_OF_TRUTH}, {}, {RC_MASK_SHOP_HINT})},
// clang-format on
};
diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp
index aca6f302e..508a5bd1a 100644
--- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp
+++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp
@@ -1,8 +1,8 @@
#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"
+#include "soh/Enhancements/randomizer/SeedContext.h"
extern "C" {
#include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h"
@@ -12,10 +12,8 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h"
#include "src/overlays/actors/ovl_En_Go2/z_en_go2.h"
#include "src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.h"
-#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h"
#include "src/overlays/actors/ovl_En_Ru2/z_en_ru2.h"
-#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h"
#include "src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.h"
@@ -81,12 +79,8 @@ void EnFu_EndTeachSong(EnFu* enFu, PlayState* play) {
void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) {
// todo: figure out a better way to handle toggling so we don't
// need to double check cvars like this
- if (!(IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) {
- EnDntDemo_Judge(enDntDemo, play);
- return;
- }
-
- if (enDntDemo->actor.xzDistToPlayer > 30.0f) {
+ if (!(IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) ||
+ (IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SPEAK)) || enDntDemo->actor.xzDistToPlayer > 30.0f) {
EnDntDemo_Judge(enDntDemo, play);
return;
}
@@ -1147,7 +1141,9 @@ void TimeSaverOnSceneInitHandler(int16_t sceneNum) {
case SCENE_LON_LON_RANCH:
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO) &&
GameInteractor_Should(VB_MALON_RETURN_FROM_CASTLE,
- Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) {
+ Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) &&
+ (!IS_RANDO || !RAND_GET_OPTION(RSK_SHUFFLE_SPEAK) ||
+ Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN))) {
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU);
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
diff --git a/soh/soh/SohGui/ImGuiUtils.cpp b/soh/soh/SohGui/ImGuiUtils.cpp
index eaf63c6ea..3f01e6e55 100644
--- a/soh/soh/SohGui/ImGuiUtils.cpp
+++ b/soh/soh/SohGui/ImGuiUtils.cpp
@@ -157,6 +157,15 @@ std::map actionShuffleMapping = {
{ RG_POWER_BRACELET, { RG_POWER_BRACELET, "RG_POWER_BRACELET", "RG_POWER_BRACELET_Faded", gButtonBackgroundTex } },
};
+std::map jabbernutMapping = {
+ { RG_SPEAK_DEKU, { RG_SPEAK_DEKU, "RG_SPEAK_DEKU", "RG_SPEAK_DEKU_Faded", (char*)gItemIcons[ITEM_NUT] } },
+ { RG_SPEAK_GERUDO, { RG_SPEAK_GERUDO, "RG_SPEAK_GERUDO", "RG_SPEAK_GERUDO_Faded", (char*)gItemIcons[ITEM_NUT] } },
+ { RG_SPEAK_GORON, { RG_SPEAK_GORON, "RG_SPEAK_GORON", "RG_SPEAK_GORON_Faded", (char*)gItemIcons[ITEM_NUT] } },
+ { RG_SPEAK_HYLIAN, { RG_SPEAK_HYLIAN, "RG_SPEAK_HYLIAN", "RG_SPEAK_HYLIAN_Faded", (char*)gItemIcons[ITEM_NUT] } },
+ { RG_SPEAK_KOKIRI, { RG_SPEAK_KOKIRI, "RG_SPEAK_KOKIRI", "RG_SPEAK_KOKIRI_Faded", (char*)gItemIcons[ITEM_NUT] } },
+ { RG_SPEAK_ZORA, { RG_SPEAK_ZORA, "RG_SPEAK_ZORA", "RG_SPEAK_ZORA_Faded", (char*)gItemIcons[ITEM_NUT] } },
+};
+
std::map questMapping = {
QUEST_MAP_ENTRY(QUEST_MEDALLION_FOREST, dgQuestIconMedallionForestTex),
QUEST_MAP_ENTRY(QUEST_MEDALLION_FIRE, dgQuestIconMedallionFireTex),
@@ -239,6 +248,13 @@ void RegisterImGuiItemIcons() {
entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
}
+ for (const auto& entry : jabbernutMapping) {
+ Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath,
+ ImVec4(1, 1, 1, 1));
+ Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(
+ entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
+ }
+
for (const auto& entry : questMapping) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.name, entry.second.texturePath,
ImVec4(1, 1, 1, 1));
diff --git a/soh/soh/SohGui/SohMenuRandomizer.cpp b/soh/soh/SohGui/SohMenuRandomizer.cpp
index 81304533e..347e56b58 100644
--- a/soh/soh/SohGui/SohMenuRandomizer.cpp
+++ b/soh/soh/SohGui/SohMenuRandomizer.cpp
@@ -653,6 +653,17 @@ void SohMenu::AddMenuRandomizer() {
"applies to seeds with maps & compasses shuffled to \"Any Dungeon\", \"Overworld\", or "
"\"Anywhere\".")
.DefaultValue(true));
+ AddWidget(path, "Jabber Nut Colors Match Kind", WIDGET_CVAR_CHECKBOX)
+ .CVar(CVAR_RANDOMIZER_ENHANCEMENT("GenericJabberNutModel"))
+ .PreFunc([](WidgetInfo& info) {
+ info.options->disabled = !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_SPEAK);
+ info.options->disabledTooltip =
+ "This setting is disabled because a savefile is loaded without Shuffle Speak.";
+ })
+ .RaceDisable(false)
+ .Options(CheckboxOptions()
+ .Tooltip("With Shuffle Speak, jabber nut model & color will be generic.")
+ .DefaultValue(true));
AddWidget(path, "Quest Item Fanfares", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_RANDOMIZER_ENHANCEMENT("QuestItemFanfares"))
.RaceDisable(false)
diff --git a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c
index 5acfe5a80..0525f6da9 100644
--- a/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c
+++ b/soh/src/overlays/actors/ovl_En_Nb/z_en_nb.c
@@ -1104,7 +1104,7 @@ void EnNb_LookUp(EnNb* this, PlayState* play) {
}
void EnNb_CrawlspaceSpawnCheck(EnNb* this, PlayState* play) {
- if (!IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA) && LINK_IS_CHILD) {
+ if (!Flags_GetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA) && LINK_IS_CHILD) {
EnNb_UpdatePath(this, play);
// looking into crawlspace
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index 5a027c323..617b76fec 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -6175,7 +6175,7 @@ s32 Player_ActionHandler_Talk(Player* this, PlayState* play) {
}
}
- if ((talkOfferActor != NULL) || (cUpTalkActor != NULL)) {
+ if (GameInteractor_Should(VB_SPEAK, (talkOfferActor != NULL) || (cUpTalkActor != NULL))) {
if ((lockOnActor == NULL) || (lockOnActor == talkOfferActor) || (lockOnActor == cUpTalkActor)) {
if (!(this->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR) ||
((this->heldActor != NULL) &&