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 3c3ddcf5a..12ca8c22e 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -137,6 +137,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 214d82711..2ef42f476 100644
--- a/soh/include/z64item.h
+++ b/soh/include/z64item.h
@@ -589,8 +589,8 @@ typedef enum {
/* 0x7A */ GID_SONG_TIME,
/* 0x7B */ GID_SONG_STORM,
/* 0x7C */ GID_TRIFORCE_PIECE,
- /* */ GID_FISHING_POLE,
- /* 0x7C */ GID_MAXIMUM
+ /* 0x7D */ GID_FISHING_POLE,
+ /* 0x7E */ GID_MAXIMUM
} GetItemDrawID;
diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveMidoInKokiriForest.cpp
index 1e4e77d44..09f347e06 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/context.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..0d197361b 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/context.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 09defd088..29d10fb1d 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -2049,6 +2049,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/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp
index f5195c91d..fe64dfb80 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
@@ -2100,6 +2100,8 @@ void StaticData::HintTable_Init_Item() {
{ CustomMessage("a master unlocker", /*german*/ "ein Meisterentsperrer", /*french*/ "un Kit de Déverrouillage") });
// /*spanish*/un desbloqueador maestro
+ hintTextTable[RHT_SPEAK] = HintText(CustomMessage("the ability to speak", /*german*/"!!!", /*french*/"la faculté de parler"));
+
//RANDOTODO if these are ever used for anything other than name, they want abscure and ambiguous hints
hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("an infinite Quiver", /*german*/"der unendliche Köcher", /*french*/"un Carquois Infini"));
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index 3e6588646..4afced29e 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -591,6 +591,15 @@ void GenerateItemPool() {
AddItemToMainPool(RG_PROGRESSIVE_SCALE);
}
+ if (ctx->GetOption(RSK_SHUFFLE_SPEAK)) {
+ AddItemToMainPool(RG_SPEAK_DEKU);
+ AddItemToMainPool(RG_SPEAK_GERUDO);
+ AddItemToMainPool(RG_SPEAK_GORON);
+ AddItemToMainPool(RG_SPEAK_HYLIAN);
+ AddItemToMainPool(RG_SPEAK_KOKIRI);
+ AddItemToMainPool(RG_SPEAK_ZORA);
+ }
+
if (ctx->GetOption(RSK_SHUFFLE_BEEHIVES)) {
// 32 total beehive locations
AddItemToPool(PendingJunkPool, RG_RED_RUPEE, 23);
diff --git a/soh/soh/Enhancements/randomizer/ShuffleSpeak.cpp b/soh/soh/Enhancements/randomizer/ShuffleSpeak.cpp
new file mode 100644
index 000000000..2196a7db9
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/ShuffleSpeak.cpp
@@ -0,0 +1,124 @@
+#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_HINTNUTS:
+ case ACTOR_OBJ_DEKUJR:
+ case ACTOR_EN_KAKASI:
+ case ACTOR_EN_KAKASI2:
+ case ACTOR_EN_KAKASI3:
+ 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_JS:
+ case ACTOR_EN_MA1:
+ 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_OWL:
+ case ACTOR_EN_SSH:
+ case ACTOR_EN_STH:
+ 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:
+ 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_ZORA;
+ 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;
+ }
+ 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 b17718b65..9f40322da 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -1109,6 +1109,56 @@ extern "C" void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getIte
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);
+}
+
extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry) {
Vec3f pos;
OPEN_DISPS(play->state.gfxCtx);
diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h
index 8483a7bf9..c3d222a43 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -21,6 +21,7 @@ void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBronzeScale(PlayState* play, GetItemEntry* getItemEntry);
+void Randomizer_DrawJabbernut(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry);
diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
index 447125ae1..f4eed36d0 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -31,6 +31,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_Go2/z_en_go2.h"
@@ -2115,6 +2116,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);
+ }
+
// In ER, once Link has spawned we know the scene has loaded, so we can sanitize the last known entrance type
if (actor->id == ACTOR_PLAYER && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES)) {
Grotto_SanitizeEntranceType();
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 7f22fe83f..e063fb355 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -349,9 +349,22 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "C-Rechts-Taste der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton);
- itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_NONE, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
+ itemTable[RG_SPEAK_DEKU] = Item(RG_SPEAK_DEKU, Text{ "Deku Jabbernut", "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 Jabbernut", "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 Jabbernut", "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 Jabbernut", "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 Jabbernut", "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 Jabbernut", "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_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
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 1d98e861a..27131f3ea 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/deku_tree.cpp
@@ -406,7 +406,7 @@ void RegionTable_Init_DekuTree() {
EventAccess(&logic->PushedDekuBasementBlock, []{return true;}),
}, {
//Locations
- LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku()),
+ LOCATION(RC_DEKU_TREE_MQ_DEKU_SCRUB, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 d8e64f996..1ba632cb3 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp
@@ -28,7 +28,7 @@ void RegionTable_Init_DodongosCavern() {
}, {
//Locations
LOCATION(RC_DODONGOS_CAVERN_MAP_CHEST, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})),
- LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, (logic->CanStunDeku() || logic->HasItem(RG_GORONS_BRACELET)) && logic->HasItem(RG_SPEAK_DEKU)),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CallGossipFairy()),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE_FAIRY_BIG, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);}) && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_DODONGOS_CAVERN_GOSSIP_STONE, Here(RR_DODONGOS_CAVERN_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);})),
@@ -108,7 +108,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()),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return true;}),
@@ -165,8 +165,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()),
- LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, logic->CanStunDeku()),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return true;}),
@@ -264,8 +264,8 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Region("Dodongos Cavern MQ Lobby", SCENE_DODONGOS_CAVERN, {}, {
//Locations
LOCATION(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)),
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku()),
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
}, {
//Exits
Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, []{return true;}),
@@ -336,7 +336,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER] = Region("Dodongos Cavern MQ Stairs Upper", SCENE_DODONGOS_CAVERN, {}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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()),
@@ -456,7 +456,7 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE] = Region("Dodongos Cavern MQ Lower Right Side", SCENE_DODONGOS_CAVERN, {}, {
//Locations
- LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanStunDeku()),
+ LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_POT_1, logic->CanBreakPots()),
LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_POT_2, logic->CanBreakPots()),
LOCATION(RC_DODONGOS_CAVERN_MQ_RIGHT_SIDE_POT_3, logic->CanBreakPots()),
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 8571ba384..10349e14a 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp
@@ -38,10 +38,10 @@ void RegionTable_Init_GanonsCastle() {
EventAccess(&logic->FreeFairies, []{return true;}),
}, {
//Locations
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, logic->CanStunDeku()),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
LOCATION(RC_GANONS_CASTLE_SCRUBS_FAIRY_1, true),
LOCATION(RC_GANONS_CASTLE_SCRUBS_FAIRY_2, true),
LOCATION(RC_GANONS_CASTLE_SCRUBS_FAIRY_3, true),
@@ -166,11 +166,11 @@ void RegionTable_Init_GanonsCastle() {
EventAccess(&logic->FreeFairies, []{return true;}),
}, {
//Locations
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, logic->CanStunDeku()),
- LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, logic->CanStunDeku()),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 51e80fc0c..5ae926f1d 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp
@@ -28,7 +28,7 @@ void RegionTable_Init_JabuJabusBelly() {
EventAccess(&logic->JabuWestTentacle, []{return logic->JabuRutoIn1F && logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}),
}, {
//Locations
- LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku()),
+ LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
//We can kill the Stingers with ruto
LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->JabuRutoIn1F),
LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->JabuWestTentacle),
@@ -48,7 +48,7 @@ void RegionTable_Init_JabuJabusBelly() {
//contains B1 of hole room (aside from the ledge leading to big octo), 2 octorock room and north water switch room
areaTable[RR_JABU_JABUS_BELLY_B1_NORTH] = Region("Jabu Jabus Belly B1 North", SCENE_JABU_JABU, {
//Events
- EventAccess(&logic->JabuRutoIn1F, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}),
+ EventAccess(&logic->JabuRutoIn1F, []{return (logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE)) && logic->HasItem(RG_SPEAK_ZORA);}),
EventAccess(&logic->FairyPot, []{return logic->CanUse(RG_BOOMERANG) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanKillEnemy(RE_OCTOROK));}),
}, {
//Locations
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 e2a13ecc1..84c91078d 100644
--- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp
@@ -23,7 +23,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
- Entrance(RR_SPIRIT_TEMPLE_CHILD, []{return logic->IsChild;}),
+ Entrance(RR_SPIRIT_TEMPLE_CHILD, []{return logic->IsChild && logic->HasItem(RG_SPEAK_GERUDO);}),
Entrance(RR_SPIRIT_TEMPLE_EARLY_ADULT, []{return logic->CanUse(RG_SILVER_GAUNTLETS);}),
});
@@ -164,7 +164,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
- Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild;}),
+ Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild && logic->HasItem(RG_SPEAK_GERUDO);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, []{return logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5);}),
});
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 b9525386c..6f6d37573 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
@@ -23,7 +23,7 @@ void RegionTable_Init_CastleGrounds() {
EventAccess(&logic->BugRock, []{return true;}),
}, {
//Locations
- LOCATION(RC_HC_MALON_EGG, true),
+ LOCATION(RC_HC_MALON_EGG, logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_HC_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)),
LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()),
LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
@@ -43,8 +43,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_HYRULE_CASTLE_GROUNDS, []{return true;}),
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 be1b2043a..944559c24 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()),
+ LOCATION(RC_DMC_DEKU_SCRUB, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
}, {
//Exits
Entrance(RR_DMC_UPPER_NEARBY, []{return 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()),
- LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku()),
+ LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 dbf218947..f7553384f 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
@@ -47,7 +47,7 @@ void RegionTable_Init_DeathMountainTrail() {
//Exits
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}),
Entrance(RR_DMC_UPPER_LOCAL, []{return true;}),
- Entrance(RR_DMT_OWL_FLIGHT, []{return logic->IsChild;}, false),
+ Entrance(RR_DMT_OWL_FLIGHT, []{return logic->IsChild && logic->HasItem(RG_SPEAK_HYLIAN);}, false),
Entrance(RR_DMT_COW_GROTTO, []{return Here(RR_DEATH_MOUNTAIN_SUMMIT, []{return logic->BlastOrSmash();});}),
Entrance(RR_DMT_GREAT_FAIRY_FOUNTAIN, []{return Here(RR_DEATH_MOUNTAIN_SUMMIT, []{return logic->BlastOrSmash();});}),
});
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 f4b8b01c3..d39d231a1 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/desert_colossus.cpp
@@ -68,8 +68,8 @@ void RegionTable_Init_DesertColossus() {
areaTable[RR_COLOSSUS_GROTTO] = Region("Colossus Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku()),
- LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 17e28d5eb..9f2026228 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
- EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), //needs climb
+ EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_SPEAK_GERUDO);}), //needs climb
}, {
//Locations
LOCATION(RC_GF_OUTSKIRTS_NE_CRATE, (logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD)) && logic->CanBreakCrates()),
@@ -46,7 +46,7 @@ void RegionTable_Init_GerudoFortress() {
areaTable[RR_GF_OUTSIDE_GTG] = Region("GF Outside GTG", SCENE_GERUDOS_FORTRESS, {
//Events
- EventAccess(&logic->GtG_GateOpen, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}),
+ EventAccess(&logic->GtG_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_GERUDO);}),
}, {}, {
//Exits
Entrance(RR_GF_TO_GTG, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}),
@@ -208,8 +208,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->CanUse(RG_EPONA) && 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->CanUse(RG_EPONA) && 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->CanUse(RG_EPONA) && 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->CanUse(RG_EPONA) && 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()),
@@ -233,7 +233,7 @@ void RegionTable_Init_GerudoFortress() {
areaTable[RR_GF_OUTSIDE_GATE] = Region("GF Outside Gate", SCENE_GERUDOS_FORTRESS, {
//Events
- EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}),
+ EventAccess(&logic->GF_GateOpen, []{return logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_SPEAK_GERUDO);}),
}, {}, {
//Exits
Entrance(RR_GF_OUTSKIRTS, []{return logic->GF_GateOpen;}),
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 a9f0299ba..003aaded2 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp
@@ -108,8 +108,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()),
- LOCATION(RC_GV_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_GV_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_GV_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 9d155c3a0..f3c3a57b4 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp
@@ -14,7 +14,7 @@ void RegionTable_Init_GoronCity() {
EventAccess(&logic->GCWoodsWarpOpen, []{return logic->CanDetonateUprightBombFlower() || logic->CanUse(RG_MEGATON_HAMMER) || logic->GoronCityChildFire;}),
EventAccess(&logic->GCDaruniasDoorOpenChild, []{return 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
- EventAccess(&logic->StopGCRollingGoronAsAdult, []{return logic->IsAdult && (logic->HasItem(RG_GORONS_BRACELET) || logic->HasExplosives() || logic->CanUse(RG_FAIRY_BOW) ||
+ EventAccess(&logic->StopGCRollingGoronAsAdult, []{return 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
@@ -22,11 +22,11 @@ void RegionTable_Init_GoronCity() {
LOCATION(RC_GC_MAZE_CENTER_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)),
LOCATION(RC_GC_MAZE_RIGHT_CHEST, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)),
LOCATION(RC_GC_POT_FREESTANDING_POH, logic->IsChild && logic->GoronCityChildFire && (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->StopGCRollingGoronAsAdult),
LOCATION(RC_GC_GS_BOULDER_MAZE, logic->IsChild && logic->BlastOrSmash()),
LOCATION(RC_GC_GS_CENTER_PLATFORM, logic->IsAdult && logic->CanAttack()),
- LOCATION(RC_GC_MEDIGORON, logic->IsAdult && (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET))),
+ LOCATION(RC_GC_MEDIGORON, logic->IsAdult && logic->HasItem(RG_SPEAK_GORON) && (logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET))),
LOCATION(RC_GC_MAZE_GOSSIP_STONE_FAIRY, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->CallGossipFairyExceptSuns()),
LOCATION(RC_GC_MAZE_GOSSIP_STONE_FAIRY_BIG, (logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)) && logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_GC_MAZE_GOSSIP_STONE, logic->BlastOrSmash() || logic->CanUse(RG_SILVER_GAUNTLETS)),
@@ -90,14 +90,14 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_SHOP] = Region("GC Shop", SCENE_GORON_SHOP, {}, {
//Locations
- LOCATION(RC_GC_SHOP_ITEM_1, true),
- LOCATION(RC_GC_SHOP_ITEM_2, true),
- LOCATION(RC_GC_SHOP_ITEM_3, true),
- LOCATION(RC_GC_SHOP_ITEM_4, true),
- LOCATION(RC_GC_SHOP_ITEM_5, true),
- LOCATION(RC_GC_SHOP_ITEM_6, true),
- LOCATION(RC_GC_SHOP_ITEM_7, true),
- LOCATION(RC_GC_SHOP_ITEM_8, true),
+ LOCATION(RC_GC_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_GORON)),
}, {
//Exits
Entrance(RR_GORON_CITY, []{return true;}),
@@ -105,9 +105,9 @@ void RegionTable_Init_GoronCity() {
areaTable[RR_GC_GROTTO] = Region("GC Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_GC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku()),
- LOCATION(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_GC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku()),
+ LOCATION(RC_GC_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_GORON)),
+ LOCATION(RC_GC_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_GORON)),
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 2fce0854f..514ef1e25 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
@@ -10,11 +10,11 @@ void RegionTable_Init_Graveyard() {
EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->BugRock, []{return true;}),
- EventAccess(&logic->BorrowBunnyHood, []{return logic->IsChild && logic->AtDay && logic->BorrowSpookyMask && logic->HasItem(RG_CHILD_WALLET);}),
+ EventAccess(&logic->BorrowBunnyHood, []{return logic->IsChild && logic->AtDay && logic->BorrowSpookyMask && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN);}),
}, {
//Locations
LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || 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() && logic->CanAttack()),
LOCATION(RC_GRAVEYARD_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)),
@@ -92,8 +92,8 @@ void RegionTable_Init_Graveyard() {
EventAccess(&logic->DampesWindmillAccess, []{return logic->IsAdult && logic->CanUse(RG_SONG_OF_TIME);}),
}, {
//Locations
- LOCATION(RC_GRAVEYARD_HOOKSHOT_CHEST, true),
- 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)),
+ LOCATION(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, logic->HasItem(RG_SPEAK_HYLIAN) && (logic->IsAdult || ctx->GetTrickOption(RT_GY_CHILD_DAMPE_RACE_POH))),
LOCATION(RC_GY_DAMPES_GRAVE_POT_1, logic->CanBreakPots()),
LOCATION(RC_GY_DAMPES_GRAVE_POT_2, logic->CanBreakPots()),
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 930ffcb4f..4f2b160f8 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()),
- LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)),
+ LOCATION(RC_WASTELAND_BOMBCHU_SALESMAN, (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)) && logic->HasItem(RG_SPEAK_HYLIAN)),
LOCATION(RC_WASTELAND_GS, logic->HookshotOrBoomerang()),
LOCATION(RC_WASTELAND_NEAR_GS_POT_1, logic->CanBreakPots()),
LOCATION(RC_WASTELAND_NEAR_GS_POT_2, logic->CanBreakPots()),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
index 3d850be58..1c8b5028a 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
EventAccess(&logic->BigPoeKill, []{return logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_EPONA) || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA));}),
- EventAccess(&logic->BorrowRightMasks, []{return logic->IsChild && logic->BorrowBunnyHood && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET);}),
+ EventAccess(&logic->BorrowRightMasks, []{return logic->IsChild && logic->BorrowBunnyHood && 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)),
@@ -119,7 +119,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()),
+ LOCATION(RC_HF_DEKU_SCRUB_GROTTO, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 92bc9aa37..2300d0a59 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
EventAccess(&logic->KakarikoVillageGateOpen, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}),
//Needs wallet to be able to get another mask after selling Keaton
- EventAccess(&logic->BorrowSkullMask, []{return logic->IsChild && logic->CanBorrowMasks && logic->HasItem(RG_CHILD_WALLET);}),
+ EventAccess(&logic->BorrowSkullMask, []{return logic->IsChild && logic->CanBorrowMasks && 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),
- LOCATION(RC_KAK_ANJU_AS_ADULT, logic->IsAdult && logic->AtDay),
+ LOCATION(RC_KAK_ANJU_AS_CHILD, logic->IsChild && logic->AtDay && logic->HasItem(RG_SPEAK_HYLIAN)),
+ 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->WakeUpAdultTalon)),
//Can kill lower kak skulls with pots
LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->CanGetNightTimeGS()),
@@ -108,7 +108,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, []{return true;}),
@@ -138,12 +138,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, []{return true;}),
@@ -180,14 +180,14 @@ void RegionTable_Init_Kakariko() {
areaTable[RR_KAK_BAZAAR] = Region("Kak Bazaar", SCENE_BAZAAR, {}, {
//Locations
- LOCATION(RC_KAK_BAZAAR_ITEM_1, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_2, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_3, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_4, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_5, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_6, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_7, true),
- LOCATION(RC_KAK_BAZAAR_ITEM_8, true),
+ LOCATION(RC_KAK_BAZAAR_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_BAZAAR_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
@@ -195,7 +195,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, []{return true;}),
@@ -203,14 +203,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),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_2, logic->IsAdult),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_3, logic->IsAdult),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_4, logic->IsAdult),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_5, logic->IsAdult),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_6, logic->IsAdult),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_7, logic->IsAdult),
- LOCATION(RC_KAK_POTION_SHOP_ITEM_8, logic->IsAdult),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_1, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_2, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_3, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_4, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_5, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_6, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_7, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_KAK_POTION_SHOP_ITEM_8, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
@@ -229,7 +229,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))),
+ 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, []{return 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 5d8ef11ec..867d8251a 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp
@@ -9,7 +9,7 @@ void RegionTable_Init_KokiriForest() {
//Events
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
- EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}),
+ EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->HasItem(RG_SPEAK_KOKIRI) && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}),
}, {
//Locations
LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild),
@@ -93,7 +93,7 @@ void RegionTable_Init_KokiriForest() {
//Events
EventAccess(&logic->DekuBabaSticks, []{return logic->CanGetDekuBabaSticks();}),
EventAccess(&logic->DekuBabaNuts, []{return logic->CanGetDekuBabaNuts();}),
- EventAccess(&logic->ShowedMidoSwordAndShield, []{return logic->IsChild && logic->CanUse(RG_KOKIRI_SWORD) && logic->CanUse(RG_DEKU_SHIELD);}),
+ EventAccess(&logic->ShowedMidoSwordAndShield, []{return 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()),
@@ -159,14 +159,14 @@ void RegionTable_Init_KokiriForest() {
areaTable[RR_KF_KOKIRI_SHOP] = Region("KF Kokiri Shop", SCENE_KOKIRI_SHOP, {}, {
//Locations
- LOCATION(RC_KF_SHOP_ITEM_1, true),
- LOCATION(RC_KF_SHOP_ITEM_2, true),
- LOCATION(RC_KF_SHOP_ITEM_3, true),
- LOCATION(RC_KF_SHOP_ITEM_4, true),
- LOCATION(RC_KF_SHOP_ITEM_5, true),
- LOCATION(RC_KF_SHOP_ITEM_6, true),
- LOCATION(RC_KF_SHOP_ITEM_7, true),
- LOCATION(RC_KF_SHOP_ITEM_8, true),
+ LOCATION(RC_KF_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_KOKIRI)),
+ LOCATION(RC_KF_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_KOKIRI)),
}, {
//Exits
Entrance(RR_KOKIRI_FOREST, []{return 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 964b781ce..35f83e93d 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
@@ -85,7 +85,7 @@ void RegionTable_Init_LakeHylia() {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
Entrance(RR_LH_FROM_SHORTCUT, []{return true;}),
- Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild;}),
+ Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild && logic->HasItem(RG_SPEAK_HYLIAN);}),
Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->WaterTempleClear) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA)));}),
Entrance(RR_LH_LAB, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}),
Entrance(RR_LH_FROM_WATER_TEMPLE, []{return true;}),
@@ -117,7 +117,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)),
@@ -132,43 +132,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, []{return true;}),
@@ -176,9 +176,9 @@ void RegionTable_Init_LakeHylia() {
areaTable[RR_LH_GROTTO] = Region("LH Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_LH_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku()),
- LOCATION(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_LH_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku()),
+ LOCATION(RC_LH_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_LH_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 c29a5924e..8d227718a 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
- EventAccess(&logic->FreedEpona, []{return (logic->HasItem(RG_CHILD_WALLET) || ctx->GetOption(RSK_SKIP_EPONA_RACE)) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}),
- EventAccess(&logic->LinksCow, []{return logic->HasItem(RG_CHILD_WALLET) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}),
+ EventAccess(&logic->FreedEpona, []{return ((logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)) || ctx->GetOption(RSK_SKIP_EPONA_RACE)) && logic->CanUse(RG_EPONAS_SONG) && logic->IsAdult && logic->AtDay;}),
+ EventAccess(&logic->LinksCow, []{return 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),
@@ -35,7 +35,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()),
@@ -65,9 +65,9 @@ void RegionTable_Init_LonLonRanch() {
areaTable[RR_LLR_GROTTO] = Region("LLR Grotto", SCENE_GROTTOS, {}, {
//Locations
- LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku()),
- LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku()),
- LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku()),
+ LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 6c6bdb536..fb9c75d6c 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp
@@ -15,7 +15,7 @@ void RegionTable_Init_LostWoods() {
EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}),
EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}),
EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}),
- EventAccess(&logic->BorrowSpookyMask, []{return logic->IsChild && logic->BorrowSkullMask && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}),
+ EventAccess(&logic->BorrowSpookyMask, []{return logic->IsChild && logic->BorrowSkullMask && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_KOKIRI);}),
}, {
//Locations
LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)),
@@ -32,7 +32,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()),
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
LOCATION(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, logic->CanSpawnSoilSkull() && 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))),
@@ -68,8 +68,8 @@ void RegionTable_Init_LostWoods() {
EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS);}),
}, {
//Locations
- LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku()),
- LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, logic->IsChild && logic->CanStunDeku()),
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, logic->IsChild && logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
LOCATION(RC_LW_GS_ABOVE_THEATER, logic->IsAdult && ((CanPlantBean(RR_LW_BEYOND_MIDO) && logic->CanAttack()) || (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() && (logic->CanAttack() || (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_OFF) && logic->CanReflectNuts()))),
LOCATION(RC_LW_BOULDER_RUPEE, logic->BlastOrSmash()),
@@ -120,8 +120,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()),
- LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 4f62d437f..239ed4a1f 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
@@ -54,8 +54,8 @@ void RegionTable_Init_Market() {
EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}),
}, {
//Locations
- LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
- LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild),
+ LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && logic->HasItem(RG_SPEAK_HYLIAN) && (logic->BigPoeKill || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())),
+ LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild && logic->CanBreakCrates()),
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_3, logic->IsChild && logic->CanBreakPots()),
@@ -123,14 +123,14 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_BAZAAR] = Region("Market Bazaar", SCENE_BAZAAR, {}, {
//Locations
- LOCATION(RC_MARKET_BAZAAR_ITEM_1, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_2, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_3, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_4, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_5, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_6, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_7, true),
- LOCATION(RC_MARKET_BAZAAR_ITEM_8, true),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BAZAAR_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
Entrance(RR_THE_MARKET, []{return true;}),
@@ -141,11 +141,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
- EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->KakarikoVillageGateOpen;}),
- EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
- EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
- EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
- EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}),
+ EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->KakarikoVillageGateOpen;}),
+ EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanBorrowMasks;}),
+ EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanBorrowMasks;}),
+ EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanBorrowMasks;}),
+ EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->CanBorrowMasks;}),
}, {
//Locations
LOCATION(RC_MASK_SHOP_HINT, true),
@@ -156,7 +156,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, []{return true;}),
@@ -164,7 +164,7 @@ void RegionTable_Init_Market() {
areaTable[RR_MARKET_BOMBCHU_BOWLING] = Region("Market Bombchu Bowling", SCENE_BOMBCHU_BOWLING_ALLEY, {
//Events
- EventAccess(&logic->CouldPlayBowling, []{return (logic->HasItem(RG_CHILD_WALLET));}),
+ EventAccess(&logic->CouldPlayBowling, []{return logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN);}),
}, {
//Locations
LOCATION(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, logic->CouldPlayBowling && logic->BombchusEnabled()),
@@ -176,14 +176,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, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_2, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_3, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_4, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_5, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_6, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_7, true),
- LOCATION(RC_MARKET_POTION_SHOP_ITEM_8, true),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_POTION_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
Entrance(RR_THE_MARKET, []{return true;}),
@@ -191,18 +191,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->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(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
- LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ 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->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(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_KEY_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
+ LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
}, {
//Exits
Entrance(RR_THE_MARKET, []{return true;}),
@@ -210,14 +210,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, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_2, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_3, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_4, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_5, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_6, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_7, true),
- LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_8, true),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_HYLIAN)),
+ LOCATION(RC_MARKET_BOMBCHU_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_HYLIAN)),
}, {
//Exits
Entrance(RR_MARKET_BACK_ALLEY, []{return true;}),
@@ -225,7 +225,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 9d641ac98..7c501258c 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
@@ -65,8 +65,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()),
- LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
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 07efc4326..2314554e6 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, []{return 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 0a70e77e8..2e2eb99cb 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
- EventAccess(&logic->THCouldFree1TorchCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}),
+ EventAccess(&logic->THCouldFree1TorchCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN);}),
EventAccess(&logic->THRescuedAllCarpenters, []{return logic->SmallKeys(RR_GF_OUTSKIRTS, ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) ? 4 : 1) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}),
}, {
//Locations
@@ -26,7 +26,7 @@ void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_DOUBLE_CELL] = Region("Thieves Hideout Double Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EventAccess(&logic->THCouldFreeDoubleCellCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}),
+ EventAccess(&logic->THCouldFreeDoubleCellCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN);}),
EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && logic->SmallKeys(RR_GF_OUTSKIRTS, 4) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}),
}, {
//Locations
@@ -49,7 +49,7 @@ void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_DEAD_END_CELL] = Region("Thieves Hideout Dead End Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EventAccess(&logic->TH_CouldFreeDeadEndCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}),
+ EventAccess(&logic->TH_CouldFreeDeadEndCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN);}),
EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && logic->SmallKeys(RR_GF_OUTSKIRTS, 4) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}),
}, {
//Locations
@@ -63,7 +63,7 @@ void RegionTable_Init_ThievesHideout() {
areaTable[RR_TH_STEEP_SLOPE_CELL] = Region("Thieves Hideout Steep Slope Cell", SCENE_THIEVES_HIDEOUT, {
//Events
- EventAccess(&logic->THCouldRescueSlopeCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR);}),
+ EventAccess(&logic->THCouldRescueSlopeCarpenter, []{return logic->CanKillEnemy(RE_GERUDO_WARRIOR) && logic->HasItem(RG_SPEAK_HYLIAN);}),
EventAccess(&logic->THRescuedAllCarpenters, []{return ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_NORMAL) && logic->SmallKeys(RR_GF_OUTSKIRTS, 4) && logic->THCouldFree1TorchCarpenter && logic->THCouldFreeDoubleCellCarpenter && logic->TH_CouldFreeDeadEndCarpenter && logic->THCouldRescueSlopeCarpenter;}),
}, {
//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 3a626a2f9..bddd3c843 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() {
EventAccess(&logic->DeliverLetter, []{return 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)),
- LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->KingZoraThawed),
+ LOCATION(RC_ZD_KING_ZORA_THAWED, logic->IsAdult && logic->KingZoraThawed && logic->HasItem(RG_SPEAK_ZORA)),
LOCATION(RC_ZD_TRADE_PRESCRIPTION, logic->IsAdult && logic->KingZoraThawed && 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, true),
- LOCATION(RC_ZD_SHOP_ITEM_2, true),
- LOCATION(RC_ZD_SHOP_ITEM_3, true),
- LOCATION(RC_ZD_SHOP_ITEM_4, true),
- LOCATION(RC_ZD_SHOP_ITEM_5, true),
- LOCATION(RC_ZD_SHOP_ITEM_6, true),
- LOCATION(RC_ZD_SHOP_ITEM_7, true),
- LOCATION(RC_ZD_SHOP_ITEM_8, true),
+ LOCATION(RC_ZD_SHOP_ITEM_1, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_2, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_3, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_4, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_5, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_6, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_7, logic->HasItem(RG_SPEAK_ZORA)),
+ LOCATION(RC_ZD_SHOP_ITEM_8, logic->HasItem(RG_SPEAK_ZORA)),
}, {
//Exits
Entrance(RR_ZORAS_DOMAIN, []{return 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 5473ee2ca..9bb318b74 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
@@ -34,7 +34,7 @@ void RegionTable_Init_ZoraRiver() {
EventAccess(&logic->BugShrub, []{return logic->CanCutShrubs();}),
}, {
//Locations
- LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->HasItem(RG_CHILD_WALLET) && logic->IsChild),
+ LOCATION(RC_ZR_MAGIC_BEAN_SALESMAN, logic->IsChild && logic->HasItem(RG_SPEAK_HYLIAN)),
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)),
@@ -121,8 +121,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()),
- LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
+ LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
+ LOCATION(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU)),
LOCATION(RC_ZR_STORMS_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index 3c0c8345e..6b0836f90 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -127,6 +127,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:
@@ -1472,6 +1478,12 @@ std::map Logic::RandoGetToRandInf = {
{ RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT },
{ RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY },
{ RG_GREG_RUPEE, RAND_INF_GREG_FOUND },
+ { RG_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 },
@@ -1837,6 +1849,12 @@ void Logic::ApplyItemEffect(Item& item, bool state) {
case RG_OCARINA_C_LEFT_BUTTON:
case RG_OCARINA_C_RIGHT_BUTTON:
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 50d11d9b2..0fd52ab49 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -251,6 +251,8 @@ void Settings::CreateOptionDescriptions() {
"\n"
"If you enter a water entrance without swim you will be respawned on land to prevent infinite death loops.\n"
"If you void out in Water Temple you will immediately be kicked out to prevent a softlock.";
+ mOptionDescriptions[RSK_SHUFFLE_SPEAK] =
+ "Shuffle ability to speak to NPCs. 6 jabbernuts will be shuffled:\nDeku, Gerudo, Goron, Hylian, Kokiri, Zora";
mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG] = "Shuffles the Weird Egg from Malon in to the item pool. Enabling "
"\"Skip Child Zelda\" disables this feature.\n"
"\n"
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index b8a4820d8..92c160eac 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -5391,7 +5391,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) {
void Randomizer::CreateCustomMessages() {
// RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED
// with GIMESSAGE(getItemID, itemID, english, german, french).
- const std::array getItemMessages = { {
+ const std::array getItemMessages = { {
GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn&wirklich gefunden!",
"Félicitation! Vous avez trouvé %gGreg%w!"),
GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!",
@@ -5715,6 +5715,19 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!",
"Du hast die %rBronzene Schuppe%w&erhalten! Die Fähigkeit zu&Schwimmen ist nun dein!",
"Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"),
+ GIMESSAGE(RG_SPEAK_DEKU, ITEM_NUT, "You got the %rDeku Jabbernut%w!&Use your words!", "!!!",
+ "Vous obtenez la %rNoix Blabla&Mojo%w!&Vous pouvez maintenant communiquer&avec les %gPestes Mojo%w!"),
+ GIMESSAGE(RG_SPEAK_GERUDO, ITEM_NUT, "You got the %rGerudo Jabbernut%w!&Use your words!", "!!!",
+ "Vous obtenez la %rNoix Blabla&Gerudo%w!&Vous pouvez maintenant communiquer&avec les %yGerudos%w!"),
+ GIMESSAGE(RG_SPEAK_GORON, ITEM_NUT, "You got the %rGoron Jabbernut%w!&Use your words!", "!!!",
+ "Vous obtenez la %rNoix Blabla&Goron%w!&Vous pouvez maintenant communiquer&avec les %rGorons%w!"),
+ GIMESSAGE(RG_SPEAK_HYLIAN, ITEM_NUT,
+ "You got the %rHylian Jabbernut%w!&Use your words! You can also speak with owls.", "!!!",
+ "Vous obtenez la %rNoix Blabla&Hylienne%w!&Vous pouvez maintenant communiquer&avec les %cHyliens%w!"),
+ GIMESSAGE(RG_SPEAK_KOKIRI, ITEM_NUT, "You got the %rKokiri Jabbernut%w!&Use your words!", "!!!",
+ "Vous obtenez la %rNoix Blabla&Kokiri%w!&Vous pouvez maintenant communiquer&avec les %gKokiris%w!"),
+ GIMESSAGE(RG_SPEAK_ZORA, ITEM_NUT, "You got the %rZora Jabbernut%w!&Use your words!", "!!!",
+ "Vous obtenez la %rNoix Blabla&Zora%w!&Vous pouvez maintenant communiquer&avec les %bZoras%w!"),
GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!",
"Du hast eine verlorene %rAngelrute%w&gefunden!&Zeit, im Teich&zu angeln!",
"Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"),
@@ -5885,6 +5898,12 @@ extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem);
std::map randomizerGetToRandInf = {
{ RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND },
{ RG_BRONZE_SCALE, RAND_INF_CAN_SWIM },
+ { RG_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 c2b9cbbdd..1db1f3910 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -4008,6 +4008,12 @@ typedef enum {
RG_HINT,
RG_TYCOON_WALLET,
RG_BRONZE_SCALE,
+ RG_SPEAK_DEKU,
+ RG_SPEAK_GERUDO,
+ RG_SPEAK_GORON,
+ RG_SPEAK_HYLIAN,
+ RG_SPEAK_KOKIRI,
+ RG_SPEAK_ZORA,
RG_CHILD_WALLET,
RG_BOMBCHU_BAG,
RG_QUIVER_INF,
@@ -5205,6 +5211,7 @@ typedef enum {
RHT_OCARINA_C_LEFT_BUTTON,
RHT_OCARINA_C_RIGHT_BUTTON,
RHT_BRONZE_SCALE,
+ RHT_SPEAK,
RHT_FISHING_POLE,
RHT_SKELETON_KEY,
RHT_EPONA,
@@ -5773,6 +5780,7 @@ typedef enum {
RSK_SHUFFLE_OCARINA,
RSK_SHUFFLE_OCARINA_BUTTONS,
RSK_SHUFFLE_SWIM,
+ RSK_SHUFFLE_SPEAK,
RSK_STARTING_DEKU_SHIELD,
RSK_STARTING_KOKIRI_SWORD,
RSK_STARTING_MASTER_SWORD,
diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h
index d42e14cb1..ea8e0fd40 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -1001,6 +1001,12 @@ DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE)
DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH)
DEFINE_RAND_INF(RAND_INF_CAN_SWIM)
+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_HAS_WALLET)
diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
index 04bc783d9..6121f2808 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
@@ -120,6 +120,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
@@ -228,6 +234,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" },
@@ -834,6 +845,42 @@ 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 Jabbernut";
+ break;
+
+ case RG_SPEAK_GERUDO:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GERUDO);
+ itemName = "Gerudo Jabbernut";
+ break;
+
+ case RG_SPEAK_GORON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GORON);
+ itemName = "Goron Jabbernut";
+ break;
+
+ case RG_SPEAK_HYLIAN:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN);
+ itemName = "Hylian Jabbernut";
+ break;
+
+ case RG_SPEAK_KOKIRI:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI);
+ itemName = "Kokiri Jabbernut";
+ break;
+
+ case RG_SPEAK_ZORA:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA);
+ itemName = "Zora Jabbernut";
+ break;
+
case RG_OCARINA_A_BUTTON:
actualItemId = item.id;
hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A);
@@ -1011,6 +1058,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];
@@ -1457,8 +1514,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));
}
@@ -1467,11 +1524,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));
}
@@ -1483,8 +1552,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));
}
@@ -1660,6 +1729,13 @@ void ItemTrackerWindow::DrawElement() {
EndFloatingWindows();
}
+ if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Jabbernuts"), SECTION_DISPLAY_HIDDEN) ==
+ SECTION_DISPLAY_SEPARATE) {
+ BeginFloatingWindows("Jabbernut Tracker");
+ DrawItemsInRows(jabbernutItems);
+ EndFloatingWindows();
+ }
+
if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), SECTION_DISPLAY_HIDDEN) ==
SECTION_DISPLAY_SEPARATE) {
BeginFloatingWindows("Ocarina Button Tracker");
@@ -1955,6 +2031,15 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true;
}
+ if (CVarCombobox("Jabbernuts", CVAR_TRACKER_ITEM("DisplayType.Jabbernuts"), displayTypes,
+ ComboboxOptions()
+ .DefaultIndex(SECTION_DISPLAY_HIDDEN)
+ .ComponentAlignment(ComponentAlignments::Right)
+ .LabelPosition(LabelPositions::Far)
+ .Color(THEME_COLOR))) {
+ shouldUpdateVectors = true;
+ }
+
if (CVarCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes,
ComboboxOptions()
.DefaultIndex(SECTION_DISPLAY_HIDDEN)
diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp
index 51101f6fa..2f3017157 100644
--- a/soh/soh/Enhancements/randomizer/savefile.cpp
+++ b/soh/soh/Enhancements/randomizer/savefile.cpp
@@ -241,7 +241,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);
// Go away Ruto (Water Temple first cutscene).
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10);
@@ -258,6 +257,16 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetRandomizerInf(RAND_INF_CAN_SWIM);
}
+ 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_CHILD_WALLET) == RO_GENERIC_OFF) {
Flags_SetRandomizerInf(RAND_INF_HAS_WALLET);
}
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index 5f8c60ac0..af9a63e56 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -212,6 +212,7 @@ void Settings::CreateOptions() {
OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]);
+ OPT_BOOL(RSK_SHUFFLE_SPEAK, "Shuffle Jabbernuts", CVAR_RANDOMIZER_SETTING("ShuffleSpeak"), mOptionDescriptions[RSK_SHUFFLE_SPEAK]);
OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF);
@@ -1241,6 +1242,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_OCARINA],
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
&mOptions[RSK_SHUFFLE_SWIM],
+ &mOptions[RSK_SHUFFLE_SPEAK],
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
&mOptions[RSK_SHUFFLE_FISHING_POLE],
@@ -1519,6 +1521,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_OCARINA],
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
&mOptions[RSK_SHUFFLE_SWIM],
+ &mOptions[RSK_SHUFFLE_SPEAK],
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
&mOptions[RSK_SHUFFLE_MERCHANTS],
diff --git a/soh/soh/SohGui/ImGuiUtils.cpp b/soh/soh/SohGui/ImGuiUtils.cpp
index ab3d8f59c..e1c90d69b 100644
--- a/soh/soh/SohGui/ImGuiUtils.cpp
+++ b/soh/soh/SohGui/ImGuiUtils.cpp
@@ -151,6 +151,15 @@ std::map bossSoulMapping = {
{ RG_GANON_SOUL, { RG_GANON_SOUL, "RG_GANON_SOUL", "RG_GANON_SOUL_Faded", gBossSoulTex } },
};
+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),
@@ -230,6 +239,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 47e651408..88e62008b 100644
--- a/soh/soh/SohGui/SohMenuRandomizer.cpp
+++ b/soh/soh/SohGui/SohMenuRandomizer.cpp
@@ -65,6 +65,17 @@ void SohMenu::AddMenuRandomizer() {
"applies to seeds with maps & compasses shuffled to \"Any Dungeon\", \"Overworld\", or "
"\"Anywhere\".")
.DefaultValue(true));
+ AddWidget(path, "Jabbernut 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, jabbernut 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 3571ca135..65a56b0c9 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -6167,7 +6167,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) &&