diff --git a/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL
new file mode 100644
index 000000000..0e068a1b2
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_tri_0 b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_tri_0
new file mode 100644
index 000000000..39f541204
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_tri_0
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_tri_1 b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_tri_1
new file mode 100644
index 000000000..8b223d8e3
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_tri_1
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_0 b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_0
new file mode 100644
index 000000000..266582a03
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_0
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_1 b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_1
new file mode 100644
index 000000000..dfcc8cc0d
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_1
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_cull b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_cull
new file mode 100644
index 000000000..38adb91be
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/gOcarinaAButtonDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/mat_gOcarinaAButtonDL_f3dlite_ocarina_A_button_edge b/soh/assets/custom/objects/object_ocarina_a_button/mat_gOcarinaAButtonDL_f3dlite_ocarina_A_button_edge
new file mode 100644
index 000000000..45ceb1d42
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/mat_gOcarinaAButtonDL_f3dlite_ocarina_A_button_edge
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/mat_gOcarinaAButtonDL_f3dlite_ocarina_A_button_surface b/soh/assets/custom/objects/object_ocarina_a_button/mat_gOcarinaAButtonDL_f3dlite_ocarina_A_button_surface
new file mode 100644
index 000000000..0ed7292b8
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_a_button/mat_gOcarinaAButtonDL_f3dlite_ocarina_A_button_surface
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_a_button/noise_tex b/soh/assets/custom/objects/object_ocarina_a_button/noise_tex
new file mode 100644
index 000000000..aaf4e331f
Binary files /dev/null and b/soh/assets/custom/objects/object_ocarina_a_button/noise_tex differ
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL
new file mode 100644
index 000000000..0bcb32168
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_tri_0 b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_tri_0
new file mode 100644
index 000000000..825b236e8
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_tri_0
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_tri_1 b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_tri_1
new file mode 100644
index 000000000..8b7f7ff56
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_tri_1
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_0 b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_0
new file mode 100644
index 000000000..f3d8371d4
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_0
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_1 b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_1
new file mode 100644
index 000000000..682f39ebb
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_1
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_cull b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_cull
new file mode 100644
index 000000000..38adb91be
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/mat_gOcarinaCDownButtonDL_f3dlite_ocarina_C_button_edge b/soh/assets/custom/objects/object_ocarina_c_down_button/mat_gOcarinaCDownButtonDL_f3dlite_ocarina_C_button_edge
new file mode 100644
index 000000000..b741478fb
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/mat_gOcarinaCDownButtonDL_f3dlite_ocarina_C_button_edge
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/mat_gOcarinaCDownButtonDL_f3dlite_ocarina_C_button_surface b/soh/assets/custom/objects/object_ocarina_c_down_button/mat_gOcarinaCDownButtonDL_f3dlite_ocarina_C_button_surface
new file mode 100644
index 000000000..9b7410f6f
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_down_button/mat_gOcarinaCDownButtonDL_f3dlite_ocarina_C_button_surface
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_down_button/noise_tex b/soh/assets/custom/objects/object_ocarina_c_down_button/noise_tex
new file mode 100644
index 000000000..aaf4e331f
Binary files /dev/null and b/soh/assets/custom/objects/object_ocarina_c_down_button/noise_tex differ
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL
new file mode 100644
index 000000000..be037cfe2
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_tri_0 b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_tri_0
new file mode 100644
index 000000000..bda98fe0a
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_tri_0
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_tri_1 b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_tri_1
new file mode 100644
index 000000000..937dd564d
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_tri_1
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_0 b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_0
new file mode 100644
index 000000000..e84ec9046
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_0
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_1 b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_1
new file mode 100644
index 000000000..fd2bf7af9
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_1
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_cull b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_cull
new file mode 100644
index 000000000..38adb91be
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/mat_gOcarinaCLeftButtonDL_f3dlite_ocarina_C_button_edge b/soh/assets/custom/objects/object_ocarina_c_left_button/mat_gOcarinaCLeftButtonDL_f3dlite_ocarina_C_button_edge
new file mode 100644
index 000000000..5bef84867
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/mat_gOcarinaCLeftButtonDL_f3dlite_ocarina_C_button_edge
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/mat_gOcarinaCLeftButtonDL_f3dlite_ocarina_C_button_surface b/soh/assets/custom/objects/object_ocarina_c_left_button/mat_gOcarinaCLeftButtonDL_f3dlite_ocarina_C_button_surface
new file mode 100644
index 000000000..2d1b57f5b
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_left_button/mat_gOcarinaCLeftButtonDL_f3dlite_ocarina_C_button_surface
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_left_button/noise_tex b/soh/assets/custom/objects/object_ocarina_c_left_button/noise_tex
new file mode 100644
index 000000000..aaf4e331f
Binary files /dev/null and b/soh/assets/custom/objects/object_ocarina_c_left_button/noise_tex differ
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL
new file mode 100644
index 000000000..9d41daa33
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_tri_0 b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_tri_0
new file mode 100644
index 000000000..f008c7abc
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_tri_0
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_tri_1 b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_tri_1
new file mode 100644
index 000000000..1767f6fe3
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_tri_1
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_0 b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_0
new file mode 100644
index 000000000..f3039179f
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_0
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_1 b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_1
new file mode 100644
index 000000000..1c79e5a86
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_1
@@ -0,0 +1,242 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_cull b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_cull
new file mode 100644
index 000000000..38adb91be
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/mat_gOcarinaCRightButtonDL_f3dlite_ocarina_C_button_edge b/soh/assets/custom/objects/object_ocarina_c_right_button/mat_gOcarinaCRightButtonDL_f3dlite_ocarina_C_button_edge
new file mode 100644
index 000000000..1cb97f9e3
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/mat_gOcarinaCRightButtonDL_f3dlite_ocarina_C_button_edge
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/mat_gOcarinaCRightButtonDL_f3dlite_ocarina_C_button_surface b/soh/assets/custom/objects/object_ocarina_c_right_button/mat_gOcarinaCRightButtonDL_f3dlite_ocarina_C_button_surface
new file mode 100644
index 000000000..70fc9e85d
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_right_button/mat_gOcarinaCRightButtonDL_f3dlite_ocarina_C_button_surface
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_right_button/noise_tex b/soh/assets/custom/objects/object_ocarina_c_right_button/noise_tex
new file mode 100644
index 000000000..aaf4e331f
Binary files /dev/null and b/soh/assets/custom/objects/object_ocarina_c_right_button/noise_tex differ
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL
new file mode 100644
index 000000000..36b1ff7a2
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_tri_0 b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_tri_0
new file mode 100644
index 000000000..f46f7c565
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_tri_0
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_tri_1 b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_tri_1
new file mode 100644
index 000000000..80954ffe2
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_tri_1
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_0 b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_0
new file mode 100644
index 000000000..a35cf324a
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_0
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_1 b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_1
new file mode 100644
index 000000000..09a4018d3
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_1
@@ -0,0 +1,251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_cull b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_cull
new file mode 100644
index 000000000..38adb91be
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/mat_gOcarinaCUpButtonDL_f3dlite_ocarina_C_button_edge b/soh/assets/custom/objects/object_ocarina_c_up_button/mat_gOcarinaCUpButtonDL_f3dlite_ocarina_C_button_edge
new file mode 100644
index 000000000..301ec9fc4
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/mat_gOcarinaCUpButtonDL_f3dlite_ocarina_C_button_edge
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/mat_gOcarinaCUpButtonDL_f3dlite_ocarina_C_button_surface b/soh/assets/custom/objects/object_ocarina_c_up_button/mat_gOcarinaCUpButtonDL_f3dlite_ocarina_C_button_surface
new file mode 100644
index 000000000..a9a701d15
--- /dev/null
+++ b/soh/assets/custom/objects/object_ocarina_c_up_button/mat_gOcarinaCUpButtonDL_f3dlite_ocarina_C_button_surface
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_ocarina_c_up_button/noise_tex b/soh/assets/custom/objects/object_ocarina_c_up_button/noise_tex
new file mode 100644
index 000000000..aaf4e331f
Binary files /dev/null and b/soh/assets/custom/objects/object_ocarina_c_up_button/noise_tex differ
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 16a2f5cd0..8765522b7 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -44,6 +44,21 @@ static const ALIGN_ASSET(2) char gTitleRandomizerSubtitleTex[] = dgTitleRandomiz
#define dgTitleBossRushSubtitleTex "__OTR__objects/object_mag/gTitleBossRushSubtitleTex"
static const ALIGN_ASSET(2) char gTitleBossRushSubtitleTex[] = dgTitleBossRushSubtitleTex;
+#define dgOcarinaAButtonDL "__OTR__objects/object_ocarina_a_button/gOcarinaAButtonDL"
+static const ALIGN_ASSET(2) char gOcarinaAButtonDL[] = dgOcarinaAButtonDL;
+
+#define dgOcarinaCLeftButtonDL "__OTR__objects/object_ocarina_c_left_button/gOcarinaCLeftButtonDL"
+static const ALIGN_ASSET(2) char gOcarinaCLeftButtonDL[] = dgOcarinaCLeftButtonDL;
+
+#define dgOcarinaCRightButtonDL "__OTR__objects/object_ocarina_c_right_button/gOcarinaCRightButtonDL"
+static const ALIGN_ASSET(2) char gOcarinaCRightButtonDL[] = dgOcarinaCRightButtonDL;
+
+#define dgOcarinaCUpButtonDL "__OTR__objects/object_ocarina_c_up_button/gOcarinaCUpButtonDL"
+static const ALIGN_ASSET(2) char gOcarinaCUpButtonDL[] = dgOcarinaCUpButtonDL;
+
+#define dgOcarinaCDownButtonDL "__OTR__objects/object_ocarina_c_down_button/gOcarinaCDownButtonDL"
+static const ALIGN_ASSET(2) char gOcarinaCDownButtonDL[] = dgOcarinaCDownButtonDL;
+
#define dgTriforcePiece0DL "__OTR__objects/object_triforce_piece_0/gTriforcePiece0DL"
static const ALIGN_ASSET(2) char gTriforcePiece0DL[] = dgTriforcePiece0DL;
diff --git a/soh/include/z64save.h b/soh/include/z64save.h
index 7f7189b5f..1e853568a 100644
--- a/soh/include/z64save.h
+++ b/soh/include/z64save.h
@@ -283,7 +283,7 @@ typedef struct {
// #endregion
// #region SOH [Randomizer]
// Upstream TODO: Move these to their own struct or name to more obviously specific to Randomizer
- /* */ u16 randomizerInf[10];
+ /* */ u16 randomizerInf[11];
/* */ u8 mqDungeonCount;
/* */ u16 adultTradeItems;
/* */ u8 triforcePiecesCollected;
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h
index 582b896b0..dec733f3e 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.h
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h
@@ -348,7 +348,7 @@ const std::vector flagTables = {
{ 0x24, "Market Crowd Text Randomizer" },
{ 0x30, "Entered the Market" },
} },
- { "Randomizer Inf Flags", RANDOMIZER_INF, 0x09, {
+ { "Randomizer Inf Flags", RANDOMIZER_INF, 0x0A, {
{ RAND_INF_DUNGEONS_DONE_DEKU_TREE, "DUNGEONS_DONE_DEKU_TREE" },
{ RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN, "DUNGEONS_DONE_DODONGOS_CAVERN" },
{ RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY, "DUNGEONS_DONE_JABU_JABUS_BELLY" },
@@ -516,6 +516,12 @@ const std::vector flagTables = {
{ RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" },
{ RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" },
{ RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" },
+
+ { RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"},
+ { RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" },
+ { RAND_INF_HAS_OCARINA_C_DOWN, "RAND_INF_HAS_OCARINA_C_DOWN" },
+ { RAND_INF_HAS_OCARINA_C_LEFT, "RAND_INF_HAS_OCARINA_C_LEFT"},
+ { RAND_INF_HAS_OCARINA_C_RIGHT, "RAND_INF_HAS_OCARINA_C_RIGHT"},
} },
};
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 0e460a024..8fd0625bc 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
@@ -2047,6 +2047,61 @@ void HintTable_Init_Item() {
Text{"the soul of Ganon", "", ""}}
);
+ hintTable[RHT_OCARINA_A_BUTTON] = HintText::Item({
+ //obscure text
+ Text{"a musical letter", /*french*/"une lettre musicale", /*spanish*/"una letra musical"},
+ }, {
+ //ambiguous text
+ Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"}
+ }, {
+ //clear text
+ Text{"an Ocarina A Button", /*french*/"la Touche A de l'Ocarina", /*spanish*/"un botón A de Ocarina"}}
+ );
+
+ hintTable[RHT_OCARINA_C_UP_BUTTON] = HintText::Item({
+ //obscure text
+ Text{"a high tone", /*french*/"une tonalité élevée", /*spanish*/"un tono alto"},
+ }, {
+ //ambiguous text
+ Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"}
+ }, {
+ //clear text
+ Text{"an Ocarina C Up Button", /*french*/"la Touche C-Haut de l'Ocarina", /*spanish*/"un botón C superior de Ocarina"}}
+ );
+
+ hintTable[RHT_OCARINA_C_DOWN_BUTTON] = HintText::Item({
+ //obscure text
+ Text{"a low tone", /*french*/"une tonalité basse", /*spanish*/"un tono bajo"},
+ }, {
+ //ambiguous text
+ Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"}
+ }, {
+ //clear text
+ Text{"an Ocarina C Down Button", /*french*/"la Touche C-Bas de l'Ocarina", /*spanish*/"un botón C inferior de Ocarina"}}
+ );
+
+ hintTable[RHT_OCARINA_C_LEFT_BUTTON] = HintText::Item({
+ //obscure text
+ Text{"a leftward tone", /*french*/"une tonalité vers la gauche", /*spanish*/"un tono hacia la izquierda"},
+ }, {
+ //ambiguous text
+ Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"}
+ }, {
+ //clear text
+ Text{"an Ocarina C Left Button", /*french*/"la Touche C-Gauche de l'Ocarina", /*spanish*/"un botón C izquierdo de Ocarina"}}
+ );
+
+ hintTable[RHT_OCARINA_C_RIGHT_BUTTON] = HintText::Item({
+ //obscure text
+ Text{"a rightward tone", /*french*/"une tonalité vers la droite", /*spanish*/"un tono hacia la derecha"},
+ }, {
+ //ambiguous text
+ Text{"something melodic", /*french*/"quelque chose de mélodieux", /*spanish*/"algo melódico"}
+ }, {
+ //clear text
+ Text{"an Ocarina C Right Button", /*french*/"la Touche C-Droit de l'Ocarina", /*spanish*/"un botón C derecho de Ocarina"}}
+ );
+
hintTable[RHT_EPONA] = HintText::Item({
//obscure text
Text{"a horse", /*french*/"un fidèle destrier", /*spanish*/"una yegua"},
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index a2d2dbfe6..2248bcd15 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -723,6 +723,21 @@ void GenerateItemPool() {
}
}
+ if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {
+ AddItemToMainPool(RG_OCARINA_A_BUTTON);
+ AddItemToMainPool(RG_OCARINA_C_UP_BUTTON);
+ AddItemToMainPool(RG_OCARINA_C_DOWN_BUTTON);
+ AddItemToMainPool(RG_OCARINA_C_LEFT_BUTTON);
+ AddItemToMainPool(RG_OCARINA_C_RIGHT_BUTTON);
+
+ //TODO: Re-add when custom models work with ice traps
+ //ctx->possibleIceTrapModels.push_back(RG_OCARINA_A_BUTTON);
+ //ctx->possibleIceTrapModels.push_back(RG_OCARINA_C_UP_BUTTON);
+ //ctx->possibleIceTrapModels.push_back(RG_OCARINA_C_DOWN_BUTTON);
+ //ctx->possibleIceTrapModels.push_back(RG_OCARINA_C_LEFT_BUTTON);
+ //ctx->possibleIceTrapModels.push_back(RG_OCARINA_C_RIGHT_BUTTON);
+ }
+
if (ctx->GetOption(RSK_SHUFFLE_COWS)) {
//9 total cow locations
for (uint8_t i = 0; i < 9; i++) {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp
index c4d1ec400..ea1508c29 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp
@@ -261,7 +261,7 @@ void AreaTable_Init() {
//Locations
LocationAccess(RC_LINKS_POCKET, {[]{return true;}}),
LocationAccess(RC_TRIFORCE_COMPLETED, {[]{return CanCompleteTriforce;}}),
- LocationAccess(RC_SARIA_SONG_HINT, {[]{return CanPlay(SariasSong);}}),
+ LocationAccess(RC_SARIA_SONG_HINT, {[]{return CanUse(RG_SARIAS_SONG);}}),
}, {
//Exits
Entrance(RR_ROOT_EXITS, {[]{return true;}})
@@ -271,12 +271,12 @@ void AreaTable_Init() {
//Exits
Entrance(RR_CHILD_SPAWN, {[]{return IsChild;}}),
Entrance(RR_ADULT_SPAWN, {[]{return IsAdult;}}),
- Entrance(RR_MINUET_OF_FOREST_WARP, {[]{return CanPlay(MinuetOfForest);}}),
- Entrance(RR_BOLERO_OF_FIRE_WARP, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;}}),
- Entrance(RR_SERENADE_OF_WATER_WARP, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;}}),
- Entrance(RR_NOCTURNE_OF_SHADOW_WARP, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;}}),
- Entrance(RR_REQUIEM_OF_SPIRIT_WARP, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;}}),
- Entrance(RR_PRELUDE_OF_LIGHT_WARP, {[]{return CanPlay(PreludeOfLight) && CanLeaveForest;}}),
+ Entrance(RR_MINUET_OF_FOREST_WARP, {[]{return CanUse(RG_MINUET_OF_FOREST);}}),
+ Entrance(RR_BOLERO_OF_FIRE_WARP, {[]{return CanUse(RG_BOLERO_OF_FIRE) && CanLeaveForest;}}),
+ Entrance(RR_SERENADE_OF_WATER_WARP, {[]{return CanUse(RG_SERENADE_OF_WATER) && CanLeaveForest;}}),
+ Entrance(RR_NOCTURNE_OF_SHADOW_WARP, {[]{return CanUse(RG_NOCTURNE_OF_SHADOW) && CanLeaveForest;}}),
+ Entrance(RR_REQUIEM_OF_SPIRIT_WARP, {[]{return CanUse(RG_REQUIEM_OF_SPIRIT) && CanLeaveForest;}}),
+ Entrance(RR_PRELUDE_OF_LIGHT_WARP, {[]{return CanUse(RG_PRELUDE_OF_LIGHT) && CanLeaveForest;}}),
});
areaTable[RR_CHILD_SPAWN] = Area("Child Spawn", "", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp
index 39fbc9b35..caed2e6f4 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_bottom_of_the_well.cpp
@@ -34,10 +34,10 @@ void AreaTable_Init_BottomOfTheWell() {
LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}),
- LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)));}}),
- LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
- LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
- LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY) && (KokiriSword || (Sticks && randoCtx->GetTrickOption(RT_BOTW_CHILD_DEADHAND)));}}),
+ LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
+ LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
+ LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH))) || CanUse(RG_DINS_FIRE) || (Sticks && randoCtx->GetTrickOption(RT_BOTW_BASEMENT))) && GoronBracelet);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (randoCtx->GetTrickOption(RT_LENS_BOTW) || CanUse(RG_LENS_OF_TRUTH));}}),
@@ -67,8 +67,8 @@ void AreaTable_Init_BottomOfTheWell() {
}, {
//Exits
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
- Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) && HasExplosives);}}),
- //Trick: CanPlay(ZeldasLullaby) || (LogicBotWMQPits && HasExplosives)
+ Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanUse(RG_ZELDAS_LULLABY) || (randoCtx->GetTrickOption(RT_BOTW_MQ_PITS) && HasExplosives);}}),
+ //Trick: CanUse(RG_ZELDAS_LULLABY) || (LogicBotWMQPits && HasExplosives)
});
areaTable[RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Area("Bottom of the Well MQ Middle", "Bottom of the Well", RA_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp
index 53109e684..fa3ad407c 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_castle_town.cpp
@@ -58,7 +58,7 @@ void AreaTable_Init_CastleTown() {
}, {
//Exits
Entrance(RR_TOT_ENTRANCE, {[]{return true;}}),
- Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}),
+ Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN) || (CanUse(RG_SONG_OF_TIME) && (randoCtx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}),
});
areaTable[RR_TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", RA_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
@@ -112,7 +112,7 @@ void AreaTable_Init_CastleTown() {
areaTable[RR_HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "HC Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_HC_GREAT_FAIRY_REWARD, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Exits
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
@@ -147,7 +147,7 @@ void AreaTable_Init_CastleTown() {
areaTable[RR_OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "OGC Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_OGC_GREAT_FAIRY_REWARD, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Exits
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
@@ -193,7 +193,7 @@ void AreaTable_Init_CastleTown() {
areaTable[RR_MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}),
- EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}),
+ EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (randoCtx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && CanUse(RG_SARIAS_SONG) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}),
}, {}, {
//Exits
Entrance(RR_THE_MARKET, {[]{return true;}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp
index d77ba0b8c..480f40103 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_death_mountain.cpp
@@ -9,7 +9,7 @@ void AreaTable_Init_DeathMountain() {
auto ctx = Rando::Context::GetInstance();
areaTable[RR_DEATH_MOUNTAIN_TRAIL] = Area("Death Mountain", "Death Mountain", RA_DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && CanPlay(SongOfStorms) && (HasExplosives || GoronBracelet));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && CanUse(RG_SONG_OF_STORMS) && (HasExplosives || GoronBracelet));}}),
}, {
//Locations
LocationAccess(RC_DMT_CHEST, {[]{return CanBlastOrSmash || (randoCtx->GetTrickOption(RT_DMT_BOMBABLE) && IsChild && GoronBracelet);}}),
@@ -54,7 +54,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_DMT_COW_GROTTO] = Area("DMT Cow Grotto", "DMT Cow Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);}}),
+ LocationAccess(RC_DMT_COW_GROTTO_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
}, {
//Exits
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
@@ -72,7 +72,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "DMT Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_DMT_GREAT_FAIRY_REWARD, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Exits
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
@@ -85,7 +85,7 @@ void AreaTable_Init_DeathMountain() {
EventAccess(&BugRock, {[]{return BugRock || (CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS));}}),
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(RG_DINS_FIRE));}}),
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(RG_DINS_FIRE) || CanUse(RG_FAIRY_BOW) || GoronBracelet || GoronCityChildFire);}}),
- EventAccess(&GCDaruniasDoorOpenChild, {[]{return GCDaruniasDoorOpenChild || (IsChild && CanPlay(ZeldasLullaby));}}),
+ EventAccess(&GCDaruniasDoorOpenChild, {[]{return GCDaruniasDoorOpenChild || (IsChild && CanUse(RG_ZELDAS_LULLABY));}}),
EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (randoCtx->GetTrickOption(RT_GC_LINK_GORON_DINS) && CanUse(RG_DINS_FIRE))));}}),
}, {
//Locations
@@ -106,9 +106,8 @@ void AreaTable_Init_DeathMountain() {
Entrance(RR_GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}),
Entrance(RR_GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(RG_FAIRY_BOW)));}}),
Entrance(RR_GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && GCDaruniasDoorOpenChild);}}),
- Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && randoCtx->GetTrickOption(RT_GC_GROTTO)));}}),
- });
-
+ Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanUse(RG_SONG_OF_TIME) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && randoCtx->GetTrickOption(RT_GC_GROTTO)));}}),
+ });
areaTable[RR_GC_WOODS_WARP] = Area("GC Woods Warp", "Goron City", RA_GORON_CITY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(RG_DINS_FIRE));}}),
@@ -123,7 +122,7 @@ void AreaTable_Init_DeathMountain() {
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(RG_STICKS));}}),
}, {
//Locations
- LocationAccess(RC_GC_DARUNIAS_JOY, {[]{return IsChild && CanPlay(SariasSong);}}),
+ LocationAccess(RC_GC_DARUNIAS_JOY, {[]{return IsChild && CanUse(RG_SARIAS_SONG);}}),
}, {
//Exits
Entrance(RR_GORON_CITY, {[]{return true;}}),
@@ -133,7 +132,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_GC_GROTTO_PLATFORM] = Area("GC Grotto Platform", "Goron City", RA_GORON_CITY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_GC_GROTTO, {[]{return true;}}),
- Entrance(RR_GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(RG_GORON_TUNIC) || CanUse(RG_NAYRUS_LOVE) || ((IsChild || CanPlay(SongOfTime)) && CanUse(RG_LONGSHOT));}}),
+ Entrance(RR_GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(RG_GORON_TUNIC) || CanUse(RG_NAYRUS_LOVE) || ((IsChild || CanUse(RG_SONG_OF_TIME)) && CanUse(RG_LONGSHOT));}}),
});
areaTable[RR_GC_SHOP] = Area("GC Shop", "GC Shop", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
@@ -220,7 +219,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_DMC_CENTRAL_LOCAL] = Area("DMC Central Local", "Death Mountain Crater", RA_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DMC_CENTRAL_LOCAL) && CanPlay(SongOfStorms));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DMC_CENTRAL_LOCAL) && CanUse(RG_SONG_OF_STORMS));}}),
}, {
//Locations
LocationAccess(RC_DMC_GS_BEAN_PATCH, {[]{return (FireTimer >= 8 || Hearts >= 3) && CanPlantBugs && CanChildAttack;}}),
@@ -234,7 +233,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_DMC_GREAT_FAIRY_REWARD, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Exits
Entrance(RR_DMC_LOWER_LOCAL, {[]{return true;}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp
index 77459619f..5c502cd08 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_deku_tree.cpp
@@ -177,8 +177,8 @@ void AreaTable_Init_DekuTree() {
LocationAccess(RC_DEKU_TREE_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, {[]{return HookshotOrBoomerang &&
Here(RR_DEKU_TREE_MQ_COMPASS_ROOM, []{return HasBombchus ||
- (Bombs && (CanPlay(SongOfTime) || IsAdult)) ||
- (IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));});}}),
+ (Bombs && (CanUse(RG_SONG_OF_TIME) || IsAdult)) ||
+ (IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_DEKU_MQ_COMPASS_GS)));});}}),
}, {
//Exits
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
@@ -196,7 +196,7 @@ void AreaTable_Init_DekuTree() {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, {[]{return CanPlay(SongOfTime);}}),
+ LocationAccess(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, {[]{return CanUse(RG_SONG_OF_TIME);}}),
}, {
//Exits
Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return Here(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, []{return (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) ||
@@ -208,7 +208,7 @@ void AreaTable_Init_DekuTree() {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Area("Deku Tree MQ Basement Back Room", "Deku Tree", RA_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || (CanPlay(SongOfTime) && HookshotOrBoomerang);}}),
+ LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || (CanUse(RG_SONG_OF_TIME) && HookshotOrBoomerang);}}),
LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, {[]{return HasFireSourceWithTorch && HookshotOrBoomerang;}}),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp
index 8730e672b..b17600633 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_dodongos_cavern.cpp
@@ -228,7 +228,7 @@ void AreaTable_Init_DodongosCavern() {
LocationAccess(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, {[]{return CanAdultAttack || CanChildAttack || Nuts;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (randoCtx->GetTrickOption(RT_DC_JUMP) || HoverBoots || Hookshot));}}),
- LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return CanPlay(SongOfTime) && (CanChildAttack || CanAdultAttack);}}),
+ LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return CanUse(RG_SONG_OF_TIME) && (CanChildAttack || CanAdultAttack);}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, {[]{return CanBlastOrSmash;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, {[]{return CanStunDeku;}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp
index 6744ea651..afb1b64be 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_fire_temple.cpp
@@ -96,7 +96,7 @@ void AreaTable_Init_FireTemple() {
//Exits
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 2);}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, {[]{return true;}}),
- Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_FIRE_SOT));}}),
+ Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_FIRE_SOT));}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, {[]{return IsAdult && HasExplosives;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}),
});
@@ -253,11 +253,11 @@ void AreaTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Area("Fire Temple West Central Lower", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && CanUse(RG_MEGATON_HAMMER);});}}),
+ LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_RUSTED_SWITCHES)) && CanUse(RG_MEGATON_HAMMER);});}}),
}, {
//Exits
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}),
- Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return IsAdult && CanPlay(SongOfTime);}}),
+ Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return IsAdult && CanUse(RG_SONG_OF_TIME);}}),
Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return true;}}),
});
@@ -367,13 +367,13 @@ void AreaTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE] = Area("Fire Temple MQ Upper Maze", "Fire Temple", RA_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
- //EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && (((CanPlay(SongOfTime) && CanUse(RG_HOOKSHOT) && HasExplosives) || CanUse(RG_LONGSHOT))));}}),
+ //EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && (((CanUse(RG_SONG_OF_TIME) && CanUse(RG_HOOKSHOT) && HasExplosives) || CanUse(RG_LONGSHOT))));}}),
EventAccess(&FairyPot, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}),
}, {
//Locations
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, {[]{return HasExplosives;}}),
- LocationAccess(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, {[]{return IsAdult && ((CanPlay(SongOfTime) && CanUse(RG_HOOKSHOT) && HasExplosives) || CanUse(RG_LONGSHOT));}}),
+ LocationAccess(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, {[]{return IsAdult && ((CanUse(RG_SONG_OF_TIME) && CanUse(RG_HOOKSHOT) && HasExplosives) || CanUse(RG_LONGSHOT));}}),
}, {
//Exits
Entrance(RR_FIRE_TEMPLE_MQ_UPPER, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3) && IsAdult && ((CanUse(RG_FAIRY_BOW) && CanUse(RG_HOOKSHOT)) || CanUse(RG_FIRE_ARROWS));}}),
@@ -385,8 +385,8 @@ void AreaTable_Init_FireTemple() {
//Trick: (IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze
LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(RG_HOOKSHOT)) || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE)) && SmallKeys(RR_FIRE_TEMPLE, 4);}}),
//Trick: ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4)
- LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}),
- //Trick: CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze
+ LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanUse(RG_SONG_OF_TIME) || HoverBoots || randoCtx->GetTrickOption(RT_FIRE_MQ_FLAME_MAZE);}}),
+ //Trick: CanUse(RG_SONG_OF_TIME) || HoverBoots || LogicFireMQFlameMaze
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, {[]{return HasExplosives;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (randoCtx->GetTrickOption(RT_FIRE_MQ_ABOVE_MAZE_GS) && IsAdult && CanUse(RG_LONGSHOT));}}),
//Trick: (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT))
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp
index 8c5bb0ff6..98022ed82 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_forest_temple.cpp
@@ -47,7 +47,7 @@ void AreaTable_Init_ForestTemple() {
//Exits
Entrance(RR_FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NORTH_CORRIDOR, {[]{return true;}}),
- Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return CanPlay(SongOfTime) || IsChild;}}),
+ Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return CanUse(RG_SONG_OF_TIME) || IsChild;}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}),
Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return SmallKeys(RR_FOREST_TEMPLE, 1, 5);}}),
Entrance(RR_FOREST_TEMPLE_EAST_CORRIDOR, {[]{return false;}}),
@@ -81,7 +81,7 @@ void AreaTable_Init_ForestTemple() {
LocationAccess(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, {[]{return CanUse(RG_LONGSHOT) || Here(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return HookshotOrBoomerang;});}}),
}, {
//Exits
- Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return CanPlay(SongOfTime);}}),
+ Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return CanUse(RG_SONG_OF_TIME);}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return false;}}),
Entrance(RR_FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
@@ -295,7 +295,7 @@ void AreaTable_Init_ForestTemple() {
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
- LocationAccess(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, {[]{return (CanPlay(SongOfTime) || IsChild) && (CanJumpslash || CanUse(RG_DINS_FIRE) || CanUse(RG_STICKS) || CanUse(RG_FAIRY_SLINGSHOT) || KokiriSword);}}),
+ LocationAccess(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, {[]{return (CanUse(RG_SONG_OF_TIME) || IsChild) && (CanJumpslash || CanUse(RG_DINS_FIRE) || CanUse(RG_STICKS) || CanUse(RG_FAIRY_SLINGSHOT) || KokiriSword);}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER);}}),
}, {
//Exits
@@ -344,11 +344,11 @@ void AreaTable_Init_ForestTemple() {
}, {
//Locations
LocationAccess(RC_FOREST_TEMPLE_MQ_WELL_CHEST, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
- LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_FOREST_DOORFRAME))));}}),
+ LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanUse(RG_SONG_OF_TIME) || (CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_FOREST_DOORFRAME))));}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_WELL, {[]{return (IsAdult && ((CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
}, {
//Exits
- Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || CanPlay(SongOfTime));}}),
+ Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_SONG_OF_TIME));}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return IsAdult && CanUse(RG_LONGSHOT);}}),
});
@@ -368,7 +368,7 @@ void AreaTable_Init_ForestTemple() {
}, {
//Exits
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}),
- Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return CanPlay(SongOfTime);}}),
+ Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return CanUse(RG_SONG_OF_TIME);}}),
});
areaTable[RR_FOREST_TEMPLE_MQ_BOW_REGION] = Area("Forest Temple MQ Bow Region", "Forest Temple", RA_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp
index c244dcb89..a89738e4a 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ganons_castle.cpp
@@ -89,7 +89,7 @@ void AreaTable_Init_GanonsCastle() {
EventAccess(&ShadowTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_MEGATON_HAMMER) && ((FireArrows && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH))) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || (DinsFire && (randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH))))));}}),
}, {
//Locations
- LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || CanPlay(SongOfTime) || IsChild;}}),
+ LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_SONG_OF_TIME) || IsChild;}}),
LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_DINS_FIRE)));}}),
}, {});
@@ -115,7 +115,7 @@ void AreaTable_Init_GanonsCastle() {
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return randoCtx->GetTrickOption(RT_LENS_GANON) || CanUse(RG_LENS_OF_TRUTH);}}),
- LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_GANONS_CASTLE, 1);}}),
+ LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY) && SmallKeys(RR_GANONS_CASTLE, 1);}}),
}, {});
}
@@ -171,7 +171,7 @@ void AreaTable_Init_GanonsCastle() {
areaTable[RR_GANONS_CASTLE_MQ_FOREST_TRIAL] = Area("Ganon's Castle MQ Forest Trial", "Ganons Castle", RA_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&ForestTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanPlay(SongOfTime);}}),
+ EventAccess(&ForestTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanUse(RG_SONG_OF_TIME);}}),
}, {
//Locations
LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, {[]{return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT));}}),
@@ -225,7 +225,7 @@ void AreaTable_Init_GanonsCastle() {
//Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ)
}, {
//Locations
- LocationAccess(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, {[]{return (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, {[]{return (CanUse(RG_MASTER_SWORD) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_BIGGORON_SWORD)) && CanUse(RG_ZELDAS_LULLABY);}}),
}, {});
}
}
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp
index 46c5eeae6..fab92a5b6 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_training_grounds.cpp
@@ -60,10 +60,10 @@ void AreaTable_Init_GerudoTrainingGrounds() {
areaTable[RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM] = Area("Gerudo Training Grounds Lava Room", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanPlay(SongOfTime) && IronBoots && WaterTimer >= 24;}}),
+ LocationAccess(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanUse(RG_SONG_OF_TIME) && IronBoots && WaterTimer >= 24;}}),
}, {
//Exits
- Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return CanPlay(SongOfTime) || IsChild;}}),
+ Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return CanUse(RG_SONG_OF_TIME) || IsChild;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return CanUse(RG_LONGSHOT) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT));}}),
});
@@ -164,8 +164,8 @@ void AreaTable_Init_GerudoTrainingGrounds() {
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, {[]{return CanUse(RG_SILVER_GAUNTLETS) && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}),
}, {
//Exits
- Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
- //Trick: IsAdult && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)))
+ Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (randoCtx->GetTrickOption(RT_LENS_GTG_MQ) || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_GTG_FAKE_WALL) && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
+ //Trick: IsAdult && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanUse(RG_SONG_OF_TIME) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)))
});
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS] = Area("Gerudo Training Grounds MQ Back Areas", "Gerudo Training Grounds", RA_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp
index 906169b2d..350cdf703 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_gerudo_valley.cpp
@@ -24,12 +24,12 @@ void AreaTable_Init_GerudoValley() {
areaTable[RR_GV_UPPER_STREAM] = Area("GV Upper Stream", "Gerudo Valley", RA_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_GV_UPPER_STREAM) && CanPlay(SongOfStorms));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_GV_UPPER_STREAM) && CanUse(RG_SONG_OF_STORMS));}}),
}, {
//Locations
LocationAccess(RC_GV_WATERFALL_FREESTANDING_POH, {[]{return true;}}),
LocationAccess(RC_GV_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
- LocationAccess(RC_GV_COW, {[]{return IsChild && CanPlay(EponasSong);}}),
+ LocationAccess(RC_GV_COW, {[]{return IsChild && CanUse(RG_EPONAS_SONG);}}),
LocationAccess(RC_GV_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -165,7 +165,7 @@ void AreaTable_Init_GerudoValley() {
areaTable[RR_DESERT_COLOSSUS] = Area("Desert Colossus", "Desert Colossus", RA_DESERT_COLOSSUS, DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&FairyPond, {[]{return FairyPond || CanPlay(SongOfStorms);}}),
+ EventAccess(&FairyPond, {[]{return FairyPond || CanUse(RG_SONG_OF_STORMS);}}),
EventAccess(&BugRock, {[]{return true;}}),
}, {
//Locations
@@ -192,7 +192,7 @@ void AreaTable_Init_GerudoValley() {
areaTable[RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "Colossus Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Exits
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp
index b43a5c6ae..9259846fb 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_hyrule_field.cpp
@@ -61,7 +61,7 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_HF_COW_GROTTO] = Area("HF Cow Grotto", "HF Cow Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;}}),
- LocationAccess(RC_HF_COW_GROTTO_COW, {[]{return HasFireSource && CanPlay(EponasSong);}}),
+ LocationAccess(RC_HF_COW_GROTTO_COW, {[]{return HasFireSource && CanUse(RG_EPONAS_SONG);}}),
LocationAccess(RC_HF_COW_GROTTO_GOSSIP_STONE, {[]{return HasFireSource;}}),
}, {
//Exits
@@ -104,11 +104,11 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_LAKE_HYLIA] = Area("Lake Hylia", "Lake Hylia", RA_LAKE_HYLIA, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_LAKE_HYLIA) && CanPlay(SongOfStorms));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_LAKE_HYLIA) && CanUse(RG_SONG_OF_STORMS));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(RG_STICKS);}}),
EventAccess(&BugShrub, {[]{return BugShrub || (IsChild && CanCutShrubs);}}),
- EventAccess(&ChildScarecrow, {[]{return ChildScarecrow || (IsChild && Ocarina);}}),
- EventAccess(&AdultScarecrow, {[]{return AdultScarecrow || (IsAdult && Ocarina);}}),
+ EventAccess(&ChildScarecrow, {[]{return ChildScarecrow || (IsChild && Ocarina && OcarinaButtons >= 2);}}),
+ EventAccess(&AdultScarecrow, {[]{return AdultScarecrow || (IsAdult && Ocarina && OcarinaButtons >= 2);}}),
}, {
//Locations
LocationAccess(RC_LH_UNDERWATER_ITEM, {[]{return IsChild && CanDive;}}),
@@ -177,8 +177,8 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_LON_LON_RANCH] = Area("Lon Lon Ranch", "Lon Lon Ranch", RA_LON_LON_RANCH, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&Epona, {[]{return Epona || (CanPlay(EponasSong) && IsAdult && AtDay);}}),
- EventAccess(&LinksCow, {[]{return LinksCow || (CanPlay(EponasSong) && IsAdult && AtDay);}}),
+ EventAccess(&Epona, {[]{return Epona || (CanUse(RG_EPONAS_SONG) && IsAdult && AtDay);}}),
+ EventAccess(&LinksCow, {[]{return LinksCow || (CanUse(RG_EPONAS_SONG) && IsAdult && AtDay);}}),
}, {
//Locations
LocationAccess(RC_SONG_FROM_MALON, {[]{return IsChild && ZeldasLetter && Ocarina && AtDay;}}),
@@ -205,8 +205,8 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_LLR_STABLES] = Area("LLR Stables", "LLR Stables", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);}}),
- LocationAccess(RC_LLR_STABLES_RIGHT_COW, {[]{return CanPlay(EponasSong);}}),
+ LocationAccess(RC_LLR_STABLES_LEFT_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
+ LocationAccess(RC_LLR_STABLES_RIGHT_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
}, {
//Exits
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
@@ -215,8 +215,8 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_LLR_TOWER] = Area("LLR Tower", "LLR Tower", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_LLR_FREESTANDING_POH, {[]{return IsChild;}}),
- LocationAccess(RC_LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);}}),
- LocationAccess(RC_LLR_TOWER_RIGHT_COW, {[]{return CanPlay(EponasSong);}}),
+ LocationAccess(RC_LLR_TOWER_LEFT_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
+ LocationAccess(RC_LLR_TOWER_RIGHT_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
}, {
//Exits
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp
index d3c1629be..60dfee3ba 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_ice_cavern.cpp
@@ -79,8 +79,8 @@ void AreaTable_Init_IceCavern() {
//Locations
LocationAccess(RC_ICE_CAVERN_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_ICE_CAVERN_MQ_FREESTANDING_POH, {[]{return HasExplosives;}}),
- LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_ICE_MQ_RED_ICE_GS);}}),
- //Trick: CanPlay(SongOfTime) || LogicIceMQRedIceGS
+ LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_ICE_MQ_RED_ICE_GS);}}),
+ //Trick: CanUse(RG_SONG_OF_TIME) || LogicIceMQRedIceGS
}, {});
}
}
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp
index 19f52d6bd..64ba1d5bb 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp
@@ -184,8 +184,8 @@ void AreaTable_Init_JabuJabusBelly() {
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}),
- LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && IsChild && CanUse(RG_BOOMERANG));}}),
- //Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG))
+ LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && IsChild && CanUse(RG_BOOMERANG));}}),
+ //Trick: CanUse(RG_SONG_OF_TIME) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG))
}, {
//Exits
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
@@ -208,7 +208,7 @@ void AreaTable_Init_JabuJabusBelly() {
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
- LocationAccess(RC_JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}),
+ LocationAccess(RC_JABU_JABUS_BELLY_MQ_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}),
}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp
index 19c5aa8b0..e56caa1c8 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp
@@ -110,12 +110,12 @@ void AreaTable_Init_Kakariko() {
areaTable[RR_KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "Kak Impas House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);}}),
+ LocationAccess(RC_KAK_IMPAS_HOUSE_COW, {[]{return CanUse(RG_EPONAS_SONG);}}),
}, {});
areaTable[RR_KAK_WINDMILL] = Area("Kak Windmill", "Windmill and Dampes Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));}}),
+ EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanUse(RG_SONG_OF_STORMS));}}),
}, {
//Locations
LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(RG_BOOMERANG) || DampesWindmillAccess || (IsAdult && randoCtx->GetTrickOption(RT_KAK_ADULT_WINDMILL_POH)) || (IsChild && CanJumpslash && randoCtx->GetTrickOption(RT_KAK_CHILD_WINDMILL_POH));}}),
@@ -208,7 +208,7 @@ void AreaTable_Init_Kakariko() {
areaTable[RR_THE_GRAVEYARD] = Area("The Graveyard", "The Graveyard", RA_THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(RG_STICKS) && AtDay);}}),
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_THE_GRAVEYARD) && CanPlay(SongOfStorms));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_THE_GRAVEYARD) && CanUse(RG_SONG_OF_STORMS));}}),
EventAccess(&BugRock, {[]{return true;}}),
}, {
//Locations
@@ -219,7 +219,7 @@ void AreaTable_Init_Kakariko() {
}, {
//Exits
Entrance(RR_GRAVEYARD_SHIELD_GRAVE, {[]{return IsAdult || AtNight;}}),
- Entrance(RR_GRAVEYARD_COMPOSERS_GRAVE, {[]{return CanPlay(ZeldasLullaby);}}),
+ Entrance(RR_GRAVEYARD_COMPOSERS_GRAVE, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
Entrance(RR_GRAVEYARD_HEART_PIECE_GRAVE, {[]{return IsAdult || AtNight;}}),
Entrance(RR_GRAVEYARD_DAMPES_GRAVE, {[]{return IsAdult;}}),
Entrance(RR_GRAVEYARD_DAMPES_HOUSE, {[]{return IsAdult || AtDampeTime;}}), //TODO: This needs to be handled
@@ -238,7 +238,7 @@ void AreaTable_Init_Kakariko() {
areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);}}),
+ LocationAccess(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanUse(RG_SUNS_SONG);}}),
}, {
//Exits
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
@@ -256,7 +256,7 @@ void AreaTable_Init_Kakariko() {
areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "Windmill and Dampes Grave", RA_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return true;}}),
- EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanPlay(SongOfTime));}}),
+ EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanUse(RG_SONG_OF_TIME));}}),
}, {
//Locations
LocationAccess(RC_GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}),
@@ -264,7 +264,7 @@ void AreaTable_Init_Kakariko() {
}, {
//Exits
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
- Entrance(RR_KAK_WINDMILL, {[]{return IsAdult && CanPlay(SongOfTime);}}),
+ Entrance(RR_KAK_WINDMILL, {[]{return IsAdult && CanUse(RG_SONG_OF_TIME);}}),
});
areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp
index 8605d2e4b..f66644061 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_lost_woods.cpp
@@ -8,13 +8,13 @@ using namespace Rando;
void AreaTable_Init_LostWoods() {
areaTable[RR_KOKIRI_FOREST] = Area("Kokiri Forest", "Kokiri Forest", RA_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_KOKIRI_FOREST) && CanPlay(SongOfStorms));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_KOKIRI_FOREST) && CanUse(RG_SONG_OF_STORMS));}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
EventAccess(&ShowedMidoSwordAndShield, {[]{return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield);}}),
}, {
//Locations
LocationAccess(RC_KF_KOKIRI_SWORD_CHEST, {[]{return IsChild;}}),
- LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (/*TODO: HasNightStart ||*/ CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}),
+ LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (/*TODO: HasNightStart ||*/ CanLeaveForest || CanUse(RG_SUNS_SONG)) && CanGetNightTimeGS;}}),
LocationAccess(RC_KF_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (randoCtx->GetTrickOption(RT_KF_ADULT_GS) && CanUse(RG_HOVER_BOOTS))) && CanGetNightTimeGS;}}),
LocationAccess(RC_KF_GOSSIP_STONE, {[]{return true;}}),
@@ -49,7 +49,7 @@ void AreaTable_Init_LostWoods() {
areaTable[RR_KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;}}),
+ LocationAccess(RC_KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanUse(RG_EPONAS_SONG) && LinksCow;}}),
}, {
//Exits
Entrance(RR_KOKIRI_FOREST, {[]{return true;}})
@@ -115,14 +115,22 @@ void AreaTable_Init_LostWoods() {
EventAccess(&OddMushroomAccess, {[]{return OddMushroomAccess || (IsAdult && (CojiroAccess || Cojiro));}}),
EventAccess(&PoachersSawAccess, {[]{return PoachersSawAccess || (IsAdult && OddPoulticeAccess);}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || CanPlay(SongOfStorms);}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || CanUse(RG_SONG_OF_STORMS);}}),
EventAccess(&BugShrub, {[]{return IsChild && CanCutShrubs;}}),
}, {
//Locations
- LocationAccess(RC_LW_SKULL_KID, {[]{return IsChild && CanPlay(SariasSong);}}),
+ LocationAccess(RC_LW_SKULL_KID, {[]{return IsChild && CanUse(RG_SARIAS_SONG);}}),
LocationAccess(RC_LW_TRADE_COJIRO, {[]{return IsAdult && Cojiro;}}),
LocationAccess(RC_LW_TRADE_ODD_POTION, {[]{return IsAdult && OddPoultice && Cojiro;}}),
- LocationAccess(RC_LW_OCARINA_MEMORY_GAME, {[]{return IsChild && Ocarina;}}),
+ //all 5 buttons are logically required for memory game
+ //because the chances of being able to beat it
+ //every time you attempt it are as follows:
+ //0 or 1 button(s) => 0%
+ //2 buttons => 0.15625%
+ //3 buttons => 3.75%
+ //4 buttons => 25.3125%
+ //5 buttons => 100%
+ LocationAccess(RC_LW_OCARINA_MEMORY_GAME, {[]{return IsChild && Ocarina && OcarinaButtons >= 5;}}),
LocationAccess(RC_LW_TARGET_IN_WOODS, {[]{return IsChild && CanUse(RG_FAIRY_SLINGSHOT);}}),
LocationAccess(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, {[]{return CanPlantBugs && CanChildAttack;}}),
@@ -133,7 +141,7 @@ void AreaTable_Init_LostWoods() {
Entrance(RR_GC_WOODS_WARP, {[]{return true;}}),
Entrance(RR_LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || randoCtx->GetTrickOption(RT_LW_BRIDGE))) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT));}}),
Entrance(RR_ZORAS_RIVER, {[]{return CanLeaveForest && (CanDive || CanUse(RG_IRON_BOOTS));}}),
- Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || randoCtx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}}),
+ Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanUse(RG_SARIAS_SONG) || randoCtx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}}),
Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, {[]{return Here(RR_THE_LOST_WOODS, []{return CanBlastOrSmash;});}}),
});
@@ -149,7 +157,7 @@ void AreaTable_Init_LostWoods() {
}, {
//Exits
Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}),
- Entrance(RR_THE_LOST_WOODS, {[]{return IsChild || CanPlay(SariasSong);}}),
+ Entrance(RR_THE_LOST_WOODS, {[]{return IsChild || CanUse(RG_SARIAS_SONG);}}),
Entrance(RR_SFM_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DEKU_THEATER, {[]{return true;}}),
Entrance(RR_LW_SCRUBS_GROTTO, {[]{return Here(RR_LW_BEYOND_MIDO, []{return CanBlastOrSmash;});}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp
index 430525051..d63d4ba5d 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_shadow_temple.cpp
@@ -73,7 +73,7 @@ void AreaTable_Init_ShadowTemple() {
LocationAccess(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return CanUse(RG_LONGSHOT) && SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}),
}, {
//Exits
- Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, {[]{return CanJumpslash && CanPlay(ZeldasLullaby) && SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}),
+ Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, {[]{return CanJumpslash && CanUse(RG_ZELDAS_LULLABY) && SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}),
});
areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
@@ -103,7 +103,7 @@ void AreaTable_Init_ShadowTemple() {
areaTable[RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA] = Area("Shadow Temple MQ Dead Hand Area", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, {[]{return CanJumpslash;}}),
- LocationAccess(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, {[]{return CanJumpslash && CanPlay(SongOfTime) && IsAdult && CanUse(RG_FAIRY_BOW);}}),
+ LocationAccess(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, {[]{return CanJumpslash && CanUse(RG_SONG_OF_TIME) && IsAdult && CanUse(RG_FAIRY_BOW);}}),
}, {});
areaTable[RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS] = Area("Shadow Temple MQ First Beamos", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
@@ -118,10 +118,10 @@ void AreaTable_Init_ShadowTemple() {
areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Area("Shadow Temple MQ Upper Huge Pit", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}),
- //Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
- LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}),
- //Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
+ LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}),
+ //Trick: CanUse(RG_SONG_OF_TIME) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
+ LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && randoCtx->GetOption(RSK_DAMAGE_MULTIPLIER).IsNot(RO_DAMAGE_MULTIPLIER_OHKO));}}),
+ //Trick: CanUse(RG_SONG_OF_TIME) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
}, {
//Exits
Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || randoCtx->GetTrickOption(RT_SHADOW_MQ_HUGE_PIT);}}),
@@ -155,7 +155,7 @@ void AreaTable_Init_ShadowTemple() {
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, {[]{return true;}}),
}, {
//Exits
- Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_SHADOW_TEMPLE, 5);}}),
+ Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return CanUse(RG_ZELDAS_LULLABY) && SmallKeys(RR_SHADOW_TEMPLE, 5);}}),
});
areaTable[RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", RA_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
@@ -164,7 +164,7 @@ void AreaTable_Init_ShadowTemple() {
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus);}}),
}, {
//Exits
- Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(RG_LONGSHOT);}}),
+ Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanUse(RG_SONG_OF_TIME) && IsAdult && CanUse(RG_LONGSHOT);}}),
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || (randoCtx->GetTrickOption(RT_SHADOW_STATUE) && HasBombchus)) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}),
});
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp
index e186b7ffb..a3eca03bb 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_spirit_temple.cpp
@@ -56,11 +56,11 @@ void AreaTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanUse(RG_ZELDAS_LULLABY);}}),
LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus || (Bombs && IsAdult && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH))) && (CanUse(RG_HOVER_BOOTS) || CanJumpslash);}}),
LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}),
LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}),
- LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)));}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanUse(RG_SONG_OF_TIME) && (Bow || Hookshot || HasBombchus || (Bombs && randoCtx->GetTrickOption(RT_SPIRIT_LOWER_ADULT_SWITCH)));}}),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}),
@@ -85,8 +85,8 @@ void AreaTable_Init_SpiritTemple() {
(SmallKeys(RR_SPIRIT_TEMPLE, 3) &&
(CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && Bow)) &&
CanUse(RG_SILVER_GAUNTLETS));}}),
- LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby);}}),
- LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP));}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanUse(RG_ZELDAS_LULLABY);}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanUse(RG_ZELDAS_LULLABY) && (Hookshot || HoverBoots || randoCtx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP));}}),
LocationAccess(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, {[]{return (HasExplosives && Boomerang && Hookshot) ||
(CanUse(RG_BOOMERANG) && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives) ||
(Hookshot && CanUse(RG_SILVER_GAUNTLETS) &&
@@ -124,7 +124,7 @@ void AreaTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS)) || (Bow && Hookshot));}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY) && ((CanTakeDamage && randoCtx->GetTrickOption(RT_FLAMING_CHESTS)) || (Bow && Hookshot));}}),
LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return (MirrorShield && CanAdultAttack) || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS));}}),
}, {
//Exits
@@ -164,8 +164,8 @@ void AreaTable_Init_SpiritTemple() {
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return SmallKeys(RR_SPIRIT_TEMPLE, 7) && Hammer;});}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, {[]{return KokiriSword && HasBombchus && Slingshot && CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, {[]{return KokiriSword || Bombs;}}),
- LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)));})));}}),
- //Trick: HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)))))
+ LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && CanUse(RG_FAIRY_BOW) && CanUse(RG_SONG_OF_TIME)));})));}}),
+ //Trick: HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanUse(RG_SONG_OF_TIME)))))
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 2);}}),
@@ -174,11 +174,11 @@ void AreaTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_ADULT] = Area("Spirit Temple MQ Adult", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
- LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && (CanJumpslash || CanUse(RG_HOVER_BOOTS));}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return CanUse(RG_ZELDAS_LULLABY) && (CanJumpslash || CanUse(RG_HOVER_BOOTS));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5);}}),
- LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime);}}),
- LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanUse(RG_SONG_OF_TIME);}}),
+ LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanUse(RG_SONG_OF_TIME) && (MirrorShield || (randoCtx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS)));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
}, {
@@ -186,24 +186,24 @@ void AreaTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (randoCtx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && CanUse(RG_DINS_FIRE) && Bow));}}),
//Trick: MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow))
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return true;}}),
- Entrance(RR_SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6) && CanPlay(ZeldasLullaby) && Hammer;}}),
- Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}),
+ Entrance(RR_SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6) && CanUse(RG_ZELDAS_LULLABY) && Hammer;}}),
+ Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanUse(RG_SONG_OF_TIME) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH));}}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT) && SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (IsAdult && CanUse(RG_FAIRY_BOW)) || (Bow && Slingshot);}}),
- LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult;}}),
- //Trick: CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult
- LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && Boomerang && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || IsAdult;}}),
- //Trick: (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult
+ LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult;}}),
+ //Trick: CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || IsAdult
+ LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && Boomerang && (CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT))) || IsAdult;}}),
+ //Trick: (LogicSpiritMQSunBlockGS && Boomerang && (CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT)) || IsAdult
}, {
//Exits
- Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)));}}),
- //Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)))
- Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}),
- //Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult)
+ Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanUse(RG_SONG_OF_TIME) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)));}}),
+ //Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanUse(RG_SONG_OF_TIME) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)))
+ Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanUse(RG_SONG_OF_TIME) || randoCtx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanUse(RG_SONG_OF_TIME) && CanJumpslash && (randoCtx->GetTrickOption(RT_LENS_SPIRIT_MQ) || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}),
+ //Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanUse(RG_SONG_OF_TIME) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanUse(RG_SONG_OF_TIME) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult)
});
areaTable[RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Area("Spirit Temple MQ Lower Adult", "Spirit Temple", RA_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp
index 8ba6e23df..fac3affa2 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_water_temple.cpp
@@ -41,7 +41,7 @@ void AreaTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_EAST_LOWER] = Area("Water Temple East Lower", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&WaterTempleLow, {[]{return WaterTempleLow || CanPlay(ZeldasLullaby);}}),
+ EventAccess(&WaterTempleLow, {[]{return WaterTempleLow || CanUse(RG_ZELDAS_LULLABY);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((randoCtx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS) || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
@@ -152,7 +152,7 @@ void AreaTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Area("Water Temple Central Pillar Upper", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&WaterTempleMiddle, {[]{return WaterTempleMiddle || CanPlay(ZeldasLullaby);}}),
+ EventAccess(&WaterTempleMiddle, {[]{return WaterTempleMiddle || CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Locations
LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(RG_LONGSHOT) || (((randoCtx->GetTrickOption(RT_WATER_FW_CENTRAL_GS) && CanUse(RG_FARORES_WIND) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE) || SmallKeys(RR_WATER_TEMPLE, 5))) || (randoCtx->GetTrickOption(RT_WATER_IRONS_CENTRAL_GS) && CanUse(RG_IRON_BOOTS) && ((CanUse(RG_HOOKSHOT) && CanUse(RG_FAIRY_BOW)) || (CanUse(RG_DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}),
@@ -186,7 +186,7 @@ void AreaTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_HIGH_WATER] = Area("Water Temple High Water", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
- EventAccess(&WaterTempleHigh, {[]{return WaterTempleHigh || CanPlay(ZeldasLullaby);}}),
+ EventAccess(&WaterTempleHigh, {[]{return WaterTempleHigh || CanUse(RG_ZELDAS_LULLABY);}}),
}, {}, {
//Exits
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
@@ -227,7 +227,7 @@ void AreaTable_Init_WaterTemple() {
}, {
//Exits
Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, {[]{return true;}}),
- Entrance(RR_WATER_TEMPLE_RIVER, {[]{return IsChild || CanPlay(SongOfTime);}}),
+ Entrance(RR_WATER_TEMPLE_RIVER, {[]{return IsChild || CanUse(RG_SONG_OF_TIME);}}),
});
areaTable[RR_WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
@@ -264,11 +264,11 @@ void AreaTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_WATER_TEMPLE_MQ_MAP_CHEST, {[]{return HasFireSource && IsAdult && CanUse(RG_HOOKSHOT);}}),
- LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((randoCtx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)));}}),
- //Trick: IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)))
+ LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((randoCtx->GetTrickOption(RT_WATER_MQ_CENTRAL_PILLAR) && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanUse(RG_SONG_OF_TIME)));}}),
+ //Trick: IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanUse(RG_SONG_OF_TIME)))
}, {
//Exits
- Entrance(RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, {[]{return CanPlay(ZeldasLullaby);}}),
+ Entrance(RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
});
areaTable[RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS] = Area("Water Temple MQ Lowered Water Levels", "Water Temple", RA_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp
index 8db912cb9..6c9dbead6 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp
@@ -18,19 +18,19 @@ void AreaTable_Init_ZorasDomain() {
areaTable[RR_ZORAS_RIVER] = Area("Zora River", "Zora River", RA_ZORAS_RIVER, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
- EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_ZORAS_RIVER) && CanPlay(SongOfStorms));}}),
+ EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_ZORAS_RIVER) && CanUse(RG_SONG_OF_STORMS));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(RG_STICKS);}}),
EventAccess(&BugShrub, {[]{return BugShrub || CanCutShrubs;}}),
}, {
//Locations
LocationAccess(RC_ZR_MAGIC_BEAN_SALESMAN, {[]{return IsChild;}}),
- LocationAccess(RC_ZR_FROGS_OCARINA_GAME, {[]{return IsChild && CanPlay(ZeldasLullaby) && CanPlay(SariasSong) && CanPlay(SunsSong) && CanPlay(EponasSong) && CanPlay(SongOfTime) && CanPlay(SongOfStorms);}}),
- LocationAccess(RC_ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanPlay(SongOfStorms);}}),
- LocationAccess(RC_ZR_FROGS_ZELDAS_LULLABY, {[]{return IsChild && CanPlay(ZeldasLullaby);}}),
- LocationAccess(RC_ZR_FROGS_EPONAS_SONG, {[]{return IsChild && CanPlay(EponasSong);}}),
- LocationAccess(RC_ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);}}),
- LocationAccess(RC_ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);}}),
- LocationAccess(RC_ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);}}),
+ LocationAccess(RC_ZR_FROGS_OCARINA_GAME, {[]{return IsChild && CanUse(RG_ZELDAS_LULLABY) && CanUse(RG_SARIAS_SONG) && CanUse(RG_SUNS_SONG) && CanUse(RG_EPONAS_SONG) && CanUse(RG_SONG_OF_TIME) && CanUse(RG_SONG_OF_STORMS);}}),
+ LocationAccess(RC_ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanUse(RG_SONG_OF_STORMS);}}),
+ LocationAccess(RC_ZR_FROGS_ZELDAS_LULLABY, {[]{return IsChild && CanUse(RG_ZELDAS_LULLABY);}}),
+ LocationAccess(RC_ZR_FROGS_EPONAS_SONG, {[]{return IsChild && CanUse(RG_EPONAS_SONG);}}),
+ LocationAccess(RC_ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanUse(RG_SARIAS_SONG);}}),
+ LocationAccess(RC_ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanUse(RG_SUNS_SONG);}}),
+ LocationAccess(RC_ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanUse(RG_SONG_OF_TIME);}}),
LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_ZR_LOWER));}}),
LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && randoCtx->GetTrickOption(RT_ZR_UPPER));}}),
LocationAccess(RC_ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}),
@@ -45,7 +45,7 @@ void AreaTable_Init_ZorasDomain() {
Entrance(RR_ZR_FAIRY_GROTTO, {[]{return Here(RR_ZORAS_RIVER, []{return CanBlastOrSmash;});}}),
Entrance(RR_THE_LOST_WOODS, {[]{return CanDive || CanUse(RG_IRON_BOOTS);}}),
Entrance(RR_ZR_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
- Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && randoCtx->GetTrickOption(RT_ZR_CUCCO)) || (IsAdult && CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_ZR_HOVERS));}}),
+ Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanUse(RG_ZELDAS_LULLABY) || (IsChild && randoCtx->GetTrickOption(RT_ZR_CUCCO)) || (IsAdult && CanUse(RG_HOVER_BOOTS) && randoCtx->GetTrickOption(RT_ZR_HOVERS));}}),
});
areaTable[RR_ZR_BEHIND_WATERFALL] = Area("ZR Behind Waterfall", "Zora River", RA_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {}, {
@@ -158,7 +158,7 @@ void AreaTable_Init_ZorasDomain() {
areaTable[RR_ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "ZF Great Fairy Fountain", RA_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
+ LocationAccess(RC_ZF_GREAT_FAIRY_REWARD, {[]{return CanUse(RG_ZELDAS_LULLABY);}}),
}, {
//Exits
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.cpp b/soh/soh/Enhancements/randomizer/3drando/logic.cpp
index 99eb71da3..120c385bf 100644
--- a/soh/soh/Enhancements/randomizer/3drando/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/logic.cpp
@@ -241,6 +241,12 @@ namespace Logic {
bool Fairy = false;
bool BottleWithBigPoe = false;
+ bool OcarinaAButton = false;
+ bool OcarinaCLeftButton = false;
+ bool OcarinaCRightButton = false;
+ bool OcarinaCUpButton = false;
+ bool OcarinaCDownButton = false;
+
bool FoundBombchus = false;
bool CanPlayBowling = false;
bool HasBombchus = false;
@@ -273,6 +279,7 @@ namespace Logic {
bool HookshotOrBoomerang = false;
bool CanGetNightTimeGS = false;
+ uint8_t OcarinaButtons = 0;
uint8_t BaseHearts = 0;
uint8_t Hearts = 0;
uint8_t Multiplier = 0;
@@ -380,10 +387,6 @@ namespace Logic {
bool BuyDekuShieldPast = false;
bool TimeTravelPast = false;
- bool CanPlay(bool song) {
- return Ocarina && song;
- }
-
static bool IsMagicItem(RandomizerGet item) {
return item == RG_DINS_FIRE ||
item == RG_FARORES_WIND ||
@@ -398,35 +401,51 @@ namespace Logic {
}
bool HasItem(RandomizerGet itemName) {
- return (itemName == RG_DINS_FIRE && DinsFire) ||
- (itemName == RG_FARORES_WIND && FaroresWind) ||
- (itemName == RG_NAYRUS_LOVE && NayrusLove) ||
- (itemName == RG_LENS_OF_TRUTH && LensOfTruth) ||
- (itemName == RG_FAIRY_BOW && Bow) ||
- (itemName == RG_MEGATON_HAMMER && Hammer) ||
- (itemName == RG_IRON_BOOTS && IronBoots) ||
- (itemName == RG_HOVER_BOOTS && HoverBoots) ||
- (itemName == RG_HOOKSHOT && Hookshot) ||
- (itemName == RG_LONGSHOT && Longshot) ||
- (itemName == RG_SILVER_GAUNTLETS && SilverGauntlets) ||
- (itemName == RG_GOLDEN_GAUNTLETS && GoldenGauntlets) ||
- (itemName == RG_GORON_TUNIC && GoronTunic) ||
- (itemName == RG_ZORA_TUNIC && ZoraTunic) ||
- (itemName == RG_SCARECROW && Scarecrow) ||
- (itemName == RG_DISTANT_SCARECROW && DistantScarecrow)||
- (itemName == RG_HYLIAN_SHIELD && HylianShield) ||
- (itemName == RG_MIRROR_SHIELD && MirrorShield) ||
- (itemName == RG_MASTER_SWORD && MasterSword) ||
- (itemName == RG_BIGGORON_SWORD && BiggoronSword) ||
- (itemName == RG_FAIRY_SLINGSHOT && Slingshot) ||
- (itemName == RG_BOOMERANG && Boomerang) ||
- (itemName == RG_KOKIRI_SWORD && KokiriSword) ||
- (itemName == RG_STICKS && Sticks) ||
- (itemName == RG_DEKU_SHIELD && DekuShield) ||
- (itemName == RG_FIRE_ARROWS && FireArrows) ||
- (itemName == RG_ICE_ARROWS && IceArrows) ||
- (itemName == RG_LIGHT_ARROWS && LightArrows);
-
+ return (itemName == RG_DINS_FIRE && DinsFire) ||
+ (itemName == RG_FARORES_WIND && FaroresWind) ||
+ (itemName == RG_NAYRUS_LOVE && NayrusLove) ||
+ (itemName == RG_LENS_OF_TRUTH && LensOfTruth) ||
+ (itemName == RG_FAIRY_BOW && Bow) ||
+ (itemName == RG_MEGATON_HAMMER && Hammer) ||
+ (itemName == RG_IRON_BOOTS && IronBoots) ||
+ (itemName == RG_HOVER_BOOTS && HoverBoots) ||
+ (itemName == RG_HOOKSHOT && Hookshot) ||
+ (itemName == RG_LONGSHOT && Longshot) ||
+ (itemName == RG_SILVER_GAUNTLETS && SilverGauntlets) ||
+ (itemName == RG_GOLDEN_GAUNTLETS && GoldenGauntlets) ||
+ (itemName == RG_GORON_TUNIC && GoronTunic) ||
+ (itemName == RG_ZORA_TUNIC && ZoraTunic) ||
+ (itemName == RG_SCARECROW && Scarecrow) ||
+ (itemName == RG_DISTANT_SCARECROW && DistantScarecrow) ||
+ (itemName == RG_HYLIAN_SHIELD && HylianShield) ||
+ (itemName == RG_MIRROR_SHIELD && MirrorShield) ||
+ (itemName == RG_MASTER_SWORD && MasterSword) ||
+ (itemName == RG_BIGGORON_SWORD && BiggoronSword) ||
+ (itemName == RG_FAIRY_SLINGSHOT && Slingshot) ||
+ (itemName == RG_BOOMERANG && Boomerang) ||
+ (itemName == RG_KOKIRI_SWORD && KokiriSword) ||
+ (itemName == RG_STICKS && Sticks) ||
+ (itemName == RG_DEKU_SHIELD && DekuShield) ||
+ (itemName == RG_FIRE_ARROWS && FireArrows) ||
+ (itemName == RG_ICE_ARROWS && IceArrows) ||
+ (itemName == RG_LIGHT_ARROWS && LightArrows) ||
+ (itemName == RG_OCARINA_A_BUTTON && OcarinaAButton) ||
+ (itemName == RG_OCARINA_C_LEFT_BUTTON && OcarinaCLeftButton) ||
+ (itemName == RG_OCARINA_C_RIGHT_BUTTON && OcarinaCRightButton) ||
+ (itemName == RG_OCARINA_C_DOWN_BUTTON && OcarinaCDownButton) ||
+ (itemName == RG_OCARINA_C_UP_BUTTON && OcarinaCUpButton) ||
+ (itemName == RG_ZELDAS_LULLABY && ZeldasLullaby) ||
+ (itemName == RG_EPONAS_SONG && EponasSong) ||
+ (itemName == RG_SARIAS_SONG && SariasSong) ||
+ (itemName == RG_SUNS_SONG && SunsSong) ||
+ (itemName == RG_SONG_OF_TIME && SongOfTime) ||
+ (itemName == RG_SONG_OF_STORMS && SongOfStorms) ||
+ (itemName == RG_MINUET_OF_FOREST && MinuetOfForest) ||
+ (itemName == RG_BOLERO_OF_FIRE && BoleroOfFire) ||
+ (itemName == RG_SERENADE_OF_WATER && SerenadeOfWater) ||
+ (itemName == RG_REQUIEM_OF_SPIRIT && RequiemOfSpirit) ||
+ (itemName == RG_NOCTURNE_OF_SHADOW && NocturneOfShadow) ||
+ (itemName == RG_PRELUDE_OF_LIGHT && PreludeOfLight);
}
//Can the passed in item be used?
@@ -461,6 +480,20 @@ namespace Logic {
case RG_STICKS: return IsChild;// || StickAsAdult;
case RG_DEKU_SHIELD: return IsChild;// || DekuShieldAsAdult;
+ // Songs
+ case RG_ZELDAS_LULLABY: return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton;
+ case RG_EPONAS_SONG: return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton;
+ case RG_SARIAS_SONG: return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCDownButton;
+ case RG_SUNS_SONG: return Ocarina && OcarinaCRightButton && OcarinaCUpButton && OcarinaCDownButton;
+ case RG_SONG_OF_TIME: return Ocarina && OcarinaAButton && OcarinaCRightButton && OcarinaCDownButton;
+ case RG_SONG_OF_STORMS: return Ocarina && OcarinaAButton && OcarinaCUpButton && OcarinaCDownButton;
+ case RG_MINUET_OF_FOREST: return Ocarina && OcarinaAButton && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton;
+ case RG_BOLERO_OF_FIRE: return Ocarina && OcarinaAButton && OcarinaCRightButton && OcarinaCDownButton;
+ case RG_SERENADE_OF_WATER: return Ocarina && OcarinaAButton && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCDownButton;
+ case RG_REQUIEM_OF_SPIRIT: return Ocarina && OcarinaAButton && OcarinaCRightButton && OcarinaCDownButton;
+ case RG_NOCTURNE_OF_SHADOW: return Ocarina && OcarinaAButton && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCDownButton;
+ case RG_PRELUDE_OF_LIGHT: return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton;
+
// Magic items
default: return MagicMeter && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(RG_FAIRY_BOW)));
}
@@ -535,6 +568,11 @@ namespace Logic {
//Updates all logic helpers. Should be called whenever a non-helper is changed
void UpdateHelpers() {
auto ctx = Rando::Context::GetInstance();
+ OcarinaButtons = (OcarinaAButton ? 1 : 0) +
+ (OcarinaCLeftButton ? 1 : 0) +
+ (OcarinaCRightButton ? 1 : 0) +
+ (OcarinaCUpButton ? 1 : 0) +
+ (OcarinaCDownButton ? 1 : 0);
NumBottles = ((NoBottles) ? 0 : (Bottles + ((DeliverLetter) ? 1 : 0)));
HasBottle = NumBottles >= 1;
Slingshot = (ProgressiveBulletBag >= 1) && (BuySeed || AmmoCanDrop);
@@ -553,9 +591,10 @@ namespace Logic {
AdultsWallet = ProgressiveWallet >= 1;
BiggoronSword = BiggoronSword || ProgressiveGiantKnife >= 2;
- ScarecrowSong = ScarecrowSong || ctx->GetOption(RSK_SKIP_SCARECROWS_SONG) || (ChildScarecrow && AdultScarecrow);
- Scarecrow = Hookshot && CanPlay(ScarecrowSong);
- DistantScarecrow = Longshot && CanPlay(ScarecrowSong);
+ //you need at least 2 buttons for scarecrow song
+ ScarecrowSong = ScarecrowSong || (ctx->GetOption(RSK_SKIP_SCARECROWS_SONG) && Ocarina && OcarinaButtons >= 2) || (ChildScarecrow && AdultScarecrow);
+ Scarecrow = Hookshot && ScarecrowSong;
+ DistantScarecrow = Longshot && ScarecrowSong;
//Drop Access
DekuStickDrop = StickPot || DekuBabaSticks;
@@ -607,9 +646,9 @@ namespace Logic {
CanDive = ProgressiveScale >= 1;
CanLeaveForest = ctx->GetOption(RSK_FOREST).IsNot(RO_FOREST_CLOSED) || IsAdult || DekuTreeClear || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES);
CanPlantBugs = IsChild && Bugs;
- CanRideEpona = IsAdult && Epona && CanPlay(EponasSong);
- CanSummonGossipFairy = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime || SunsSong);
- CanSummonGossipFairyWithoutSuns = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime);
+ CanRideEpona = IsAdult && Epona && CanUse(RG_EPONAS_SONG);
+ CanSummonGossipFairyWithoutSuns = CanUse(RG_ZELDAS_LULLABY) || CanUse(RG_EPONAS_SONG) || CanUse(RG_SONG_OF_TIME);
+ CanSummonGossipFairy = CanSummonGossipFairyWithoutSuns || CanUse(RG_SUNS_SONG);
Hearts = BaseHearts + HeartContainer + (PieceOfHeart >> 2);
EffectiveHealth = ((Hearts << (2 + DoubleDefense)) >> Multiplier) + ((Hearts << (2 + DoubleDefense)) % (1 << Multiplier) > 0); //Number of half heart hits to die, ranges from 1 to 160
FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (ctx->GetTrickOption(RT_FEWER_TUNIC_REQUIREMENTS)) ? (Hearts * 8) : 0;
@@ -620,9 +659,9 @@ namespace Logic {
CanTakeDamageTwice = (Fairy && NumBottles >= 2) || ((EffectiveHealth == 2) && (CanUse(RG_NAYRUS_LOVE) || Fairy)) || (EffectiveHealth > 2);
//CanPlantBean = IsChild && (MagicBean || MagicBeanPack);
CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY));
- CanOpenStormGrotto = CanPlay(SongOfStorms) && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY));
+ CanOpenStormGrotto = CanUse(RG_SONG_OF_STORMS) && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY));
HookshotOrBoomerang = CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG);
- CanGetNightTimeGS = (CanPlay(SunsSong) || !ctx->GetOption(RSK_SKULLS_SUNS_SONG));
+ CanGetNightTimeGS = (CanUse(RG_SUNS_SONG) || !ctx->GetOption(RSK_SKULLS_SUNS_SONG));
GuaranteeTradePath = ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetTrickOption(RT_DMT_BOLERO_BIGGORON) || CanBlastOrSmash || StopGCRollingGoronAsAdult;
//GuaranteeHint = (hints == "Mask" && MaskofTruth) || (hints == "Agony") || (hints != "Mask" && hints != "Agony");
@@ -885,6 +924,13 @@ namespace Logic {
GregInBridgeLogic = false;
GregInLacsLogic = false;
+ //Ocarina C Buttons
+ OcarinaAButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1;
+ OcarinaCLeftButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1;
+ OcarinaCRightButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1;
+ OcarinaCUpButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1;
+ OcarinaCDownButton = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true) ? 0 : 1;
+
//Progressive Items
ProgressiveBulletBag = 0;
ProgressiveBombBag = 0;
diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.hpp b/soh/soh/Enhancements/randomizer/3drando/logic.hpp
index 2477f9902..63f7b9fa3 100644
--- a/soh/soh/Enhancements/randomizer/3drando/logic.hpp
+++ b/soh/soh/Enhancements/randomizer/3drando/logic.hpp
@@ -200,6 +200,12 @@ extern uint8_t PieceOfHeart;
extern uint8_t HeartContainer;
extern bool DoubleDefense;
+extern bool OcarinaAButton;
+extern bool OcarinaCLeftButton;
+extern bool OcarinaCRightButton;
+extern bool OcarinaCUpButton;
+extern bool OcarinaCDownButton;
+
/* --- HELPERS --- */
/* These are used to simplify reading the logic, but need to be updated
/ every time a base value is updated. */
@@ -266,6 +272,7 @@ extern bool HookshotOrBoomerang;
extern bool CanGetNightTimeGS;
extern bool BigPoeKill;
+extern uint8_t OcarinaButtons;
extern uint8_t BaseHearts;
extern uint8_t Hearts;
extern uint8_t Multiplier;
@@ -376,7 +383,6 @@ enum class GlitchDifficulty {
};
void UpdateHelpers();
-bool CanPlay(bool song);
bool CanUse(RandomizerGet itemName);
bool HasProjectile(HasProjectileAge age);
bool HasBossSoul(RandomizerGet itemName);
diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
index 973bacaa4..9ca6a25ea 100644
--- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
@@ -740,6 +740,29 @@ void InitTrickNames() {
Text{"Ganon's Ghost", "", ""},
Text{"Pork", "", ""}};
+ trickNameTable[RG_OCARINA_A_BUTTON] = {
+ Text{"Ocarina J Button", "", ""},
+ Text{"Ocarina Ayy Button", "", ""},
+ Text{"Ocarina A Trigger", "", ""} };
+ trickNameTable[RG_OCARINA_C_UP_BUTTON] = {
+ Text{"Ocarina C North Button", "", ""},
+ Text{"Ocarina C App Button", "", ""},
+ Text{"Ocarina Sup Button", "", ""} };
+ trickNameTable[RG_OCARINA_C_DOWN_BUTTON] = {
+ Text{"Ocarina C South Button", "", ""},
+ Text{"Ocarina Z Down Button", "", ""},
+ Text{"Ocarina See Down Button", "", ""},
+ Text{"Ocarina C Dawn Button", "", ""} };
+ trickNameTable[RG_OCARINA_C_LEFT_BUTTON] = {
+ Text{"Ocarina C West Button", "", ""},
+ Text{"Ocarina Sea Left Button", "", ""},
+ Text{"Ocarina C Lift Button", "", ""},
+ Text{"Ocarina Rewind Button", "", ""} };
+ trickNameTable[RG_OCARINA_C_RIGHT_BUTTON] = {
+ Text{"Ocarina C East Button", "", ""},
+ Text{"Ocarina C Wright Button", "", ""},
+ Text{"Overworld C Right Button", "", ""} };
+
/*
//Names for individual upgrades, in case progressive names are replaced
trickNameTable[GI_HOOKSHOT] = {
diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp
index 43f7129ab..1730c7fc7 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -14,6 +14,7 @@
#include "objects/object_toki_objects/object_toki_objects.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
#include "soh_assets.h"
+#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
extern "C" {
extern SaveContext gSaveContext;
@@ -327,3 +328,66 @@ extern "C" void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEn
CLOSE_DISPS(play->state.gfxCtx);
}
+
+extern "C" void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry) {
+ Color_RGB8 aButtonColor = { 80, 150, 255 };
+ if (CVarGetInteger("gCosmetics.Hud_AButton.Changed", 0)) {
+ aButtonColor = CVarGetColor24("gCosmetics.Hud_AButton.Value", aButtonColor);
+ } else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
+ aButtonColor = { 80, 255, 150 };
+ }
+
+ Color_RGB8 cButtonsColor = { 255, 255, 50 };
+ if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) {
+ cButtonsColor = CVarGetColor24("gCosmetics.Hud_CButtons.Value", cButtonsColor);
+ }
+ Color_RGB8 cUpButtonColor = cButtonsColor;
+ if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) {
+ cUpButtonColor = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", cUpButtonColor);
+ }
+ Color_RGB8 cDownButtonColor = cButtonsColor;
+ if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) {
+ cDownButtonColor = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", cDownButtonColor);
+ }
+ Color_RGB8 cLeftButtonColor = cButtonsColor;
+ if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) {
+ cLeftButtonColor = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", cLeftButtonColor);
+ }
+ Color_RGB8 cRightButtonColor = cButtonsColor;
+ if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) {
+ cRightButtonColor = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", cRightButtonColor);
+ }
+
+ s16 slot = getItemEntry->getItemId - RG_OCARINA_A_BUTTON;
+
+ Gfx* dLists[] = {
+ (Gfx*)gOcarinaAButtonDL,
+ (Gfx*)gOcarinaCUpButtonDL,
+ (Gfx*)gOcarinaCDownButtonDL,
+ (Gfx*)gOcarinaCLeftButtonDL,
+ (Gfx*)gOcarinaCRightButtonDL,
+ };
+
+ Color_RGB8 colors[] = {
+ aButtonColor,
+ cUpButtonColor,
+ cDownButtonColor,
+ cLeftButtonColor,
+ cRightButtonColor,
+ };
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
+
+ gDPSetGrayscaleColor(POLY_XLU_DISP++, colors[slot].r, colors[slot].g, colors[slot].b, 255);
+ gSPGrayscale(POLY_XLU_DISP++, true);
+
+ gSPDisplayList(POLY_XLU_DISP++, dLists[slot]);
+
+ gSPGrayscale(POLY_XLU_DISP++, false);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h
index dcf146c28..b2f88e3da 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -17,6 +17,7 @@ void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawMasterSword(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry);
+void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getItemEntry);
#ifdef __cplusplus
};
#endif
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 45151e99c..246e1248c 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -259,6 +259,17 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "", "" }, ITEMTYPE_ITEM, 0xE8, true, &Logic::CanSummonGanon, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
+ itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Botón A de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &Logic::OcarinaAButton, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_OCARINA_A_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton);
+ itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Botón C superior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &Logic::OcarinaCUpButton, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_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_UP_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton);
+ itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Botón C inferior de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &Logic::OcarinaCDownButton, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_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_DOWN_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton);
+ itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Botón C izquierdo de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &Logic::OcarinaCLeftButton, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_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_LEFT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton);
+ itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Botón C derecho de Ocarina" }, ITEMTYPE_ITEM, GI_MAP, true, &Logic::OcarinaCRightButton, 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_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, &Logic::noVariable, RHT_NONE);
itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, &Logic::noVariable, RHT_NONE);
// Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen)
diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
index 22fc33f69..85e5affe8 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -215,6 +215,10 @@ void Settings::CreateOptionDescriptions() {
"Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n"
"\n"
"This will require finding an Ocarina before being able to play songs.";
+ mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS] =
+ "Enabling this shuffles the Ocarina buttons into the item pool.\n"
+ "\n"
+ "This will require finding the buttons before being able to use them in songs.";
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"
@@ -411,7 +415,8 @@ void Settings::CreateOptionDescriptions() {
"Once the happy mask shop is opened, all masks will be available to be borrowed.";
mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] =
"Start with the ability to summon Pierre the scarecrow. Pulling out an ocarina in the usual locations will "
- "automatically summon him.";
+ "automatically summon him.\n"
+ "With \"Shuffle Ocarina Buttons\" enabled, you'll need at least two ocarina buttons to summon him.";
mOptionDescriptions[RSK_ITEM_POOL] = "Sets how many major items appear in the item pool.\n"
"\n"
"Plentiful - Extra major items are added to the pool.\n"
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index b2316d638..3efa3a141 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -822,6 +822,18 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
case RG_LIGHT_MEDALLION:
return !CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE;
+ // Ocarina Buttons
+ case RG_OCARINA_A_BUTTON:
+ return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN;
+ case RG_OCARINA_C_LEFT_BUTTON:
+ return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN;
+ case RG_OCARINA_C_RIGHT_BUTTON:
+ return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN;
+ case RG_OCARINA_C_UP_BUTTON:
+ return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN;
+ case RG_OCARINA_C_DOWN_BUTTON:
+ return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN;
+
case RG_RECOVERY_HEART:
case RG_GREEN_RUPEE:
case RG_GREG_RUPEE:
@@ -1144,6 +1156,19 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem
return GI_HEART_PIECE_WIN;
case RG_TREASURE_GAME_GREEN_RUPEE:
return GI_RUPEE_GREEN_LOSE;
+
+ //Ocarina Buttons
+ case RG_OCARINA_A_BUTTON:
+ return (GetItemID)RG_OCARINA_A_BUTTON;
+ case RG_OCARINA_C_LEFT_BUTTON:
+ return (GetItemID)RG_OCARINA_C_LEFT_BUTTON;
+ case RG_OCARINA_C_RIGHT_BUTTON:
+ return (GetItemID)RG_OCARINA_C_RIGHT_BUTTON;
+ case RG_OCARINA_C_UP_BUTTON:
+ return (GetItemID)RG_OCARINA_C_UP_BUTTON;
+ case RG_OCARINA_C_DOWN_BUTTON:
+ return (GetItemID)RG_OCARINA_C_DOWN_BUTTON;
+
default:
if (!IsItemVanilla(randoGet)) {
return (GetItemID)randoGet;
@@ -3043,7 +3068,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!",
@@ -3289,6 +3314,26 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE_UNTRANSLATED(RG_TWINROVA_SOUL, ITEM_BIG_POE, "You found the soul for %yTwinrova%w!"),
GIMESSAGE_UNTRANSLATED(RG_GANON_SOUL, ITEM_BIG_POE, "You found the soul for %cGanon%w!"),
+ GIMESSAGE(RG_OCARINA_A_BUTTON, ITEM_OCARINA_TIME,
+ "You got the %b\x9f%r button for the&Ocarina%w! You can now use it&while playing songs!",
+ "Der %b\x9f%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
+ "Vous trouvez la %rtouche %b\x9f%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
+ GIMESSAGE(RG_OCARINA_C_LEFT_BUTTON, ITEM_OCARINA_TIME,
+ "You got the %y\xa7%r button for the&Ocarina%w! You can now use it&while playing songs!",
+ "Der %y\xa7%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
+ "Vous trouvez la %rtouche %y\xa7%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
+ GIMESSAGE(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME,
+ "You got the %y\xa8%r button for the&Ocarina%w! You can now use it&while playing songs!",
+ "Der %y\xa8%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
+ "Vous trouvez la %rtouche %y\xa8%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
+ GIMESSAGE(RG_OCARINA_C_UP_BUTTON, ITEM_OCARINA_TIME,
+ "You got the %y\xa5%r button for the&Ocarina%w! You can now use it&while playing songs!",
+ "Der %y\xa5%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
+ "Vous trouvez la %rtouche %y\xa5%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
+ GIMESSAGE(RG_OCARINA_C_DOWN_BUTTON, ITEM_OCARINA_TIME,
+ "You got the %y\xa6%r button for the&Ocarina%w! You can now use it&while playing songs!",
+ "Der %y\xa6%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!",
+ "Vous trouvez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"),
}};
CreateGetItemMessages(&getItemMessages);
CreateRupeeMessages();
diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h
index 14954fe11..95845883f 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -1867,6 +1867,11 @@ typedef enum {
RG_BONGO_BONGO_SOUL,
RG_TWINROVA_SOUL,
RG_GANON_SOUL,
+ RG_OCARINA_A_BUTTON,
+ RG_OCARINA_C_UP_BUTTON,
+ RG_OCARINA_C_DOWN_BUTTON,
+ RG_OCARINA_C_LEFT_BUTTON,
+ RG_OCARINA_C_RIGHT_BUTTON,
RG_HINT,
RG_TYCOON_WALLET,
RG_FAIRY_OCARINA,
@@ -3080,6 +3085,11 @@ typedef enum {
RHT_BONGO_BONGO_SOUL,
RHT_TWINROVA_SOUL,
RHT_GANON_SOUL,
+ RHT_OCARINA_A_BUTTON,
+ RHT_OCARINA_C_UP_BUTTON,
+ RHT_OCARINA_C_DOWN_BUTTON,
+ RHT_OCARINA_C_LEFT_BUTTON,
+ RHT_OCARINA_C_RIGHT_BUTTON,
RHT_EPONA,
// Entrances
RHT_DESERT_COLOSSUS_TO_COLOSSUS_GROTTO,
@@ -3382,6 +3392,7 @@ typedef enum {
RSK_TRIAL_COUNT,
RSK_STARTING_OCARINA,
RSK_SHUFFLE_OCARINA,
+ RSK_SHUFFLE_OCARINA_BUTTONS,
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 472523b7c..39f84ba2a 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -171,6 +171,12 @@ typedef enum {
RAND_INF_TWINROVA_SOUL,
RAND_INF_GANON_SOUL,
+ RAND_INF_HAS_OCARINA_A,
+ RAND_INF_HAS_OCARINA_C_UP,
+ RAND_INF_HAS_OCARINA_C_DOWN,
+ RAND_INF_HAS_OCARINA_C_LEFT,
+ RAND_INF_HAS_OCARINA_C_RIGHT,
+
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX,
diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
index 535e9b4ad..3d4177c59 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
@@ -98,6 +98,16 @@ std::vector bossSoulItems = {
ITEM_TRACKER_ITEM_CUSTOM(RG_GANON_SOUL, ITEM_BIG_POE, ITEM_BOTTLE, 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
+ ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_A_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem ),
+ ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_UP_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem ),
+ ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_DOWN_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem ),
+ ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_LEFT_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem ),
+ ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem ),
+};
+
std::vector itemTrackerDungeonsWithMapsHorizontal = {
{ SCENE_DEKU_TREE, { ITEM_DUNGEON_MAP, ITEM_COMPASS } },
{ SCENE_DODONGOS_CAVERN, { ITEM_DUNGEON_MAP, ITEM_COMPASS } },
@@ -180,6 +190,14 @@ std::map itemTrackerBossShortNames = {
{ RG_GANON_SOUL, "GANON"},
};
+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"},
+};
+
std::vector dungeonItems = {};
std::unordered_map actualItemTrackerItemMap = {
@@ -682,6 +700,32 @@ void DrawItem(ItemTrackerItem item) {
itemName = "Ganon's Soul";
break;
+
+ case RG_OCARINA_A_BUTTON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A);
+ itemName = "Ocarina A Button";
+ break;
+ case RG_OCARINA_C_UP_BUTTON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
+ itemName = "Ocarina C Up Button";
+ break;
+ case RG_OCARINA_C_DOWN_BUTTON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
+ itemName = "Ocarina C Down Button";
+ break;
+ case RG_OCARINA_C_LEFT_BUTTON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT);
+ itemName = "Ocarina C Left Button";
+ break;
+ case RG_OCARINA_C_RIGHT_BUTTON:
+ actualItemId = item.id;
+ hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT);
+ itemName = "Ocarina C Right Button";
+ break;
}
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
@@ -704,6 +748,15 @@ void DrawItem(ItemTrackerItem item) {
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];
+ ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(ocarinaButtonName.c_str()).x / 2), p.y - (iconSize + 13)));
+ ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE);
+ ImGui::Text("%s", ocarinaButtonName.c_str());
+ ImGui::PopStyleColor();
+ }
+
ImGui::EndGroup();
if (itemName == "") {
@@ -1050,6 +1103,17 @@ void UpdateVectors() {
mainWindowItems.insert(mainWindowItems.end(), bossSoulItems.begin(), bossSoulItems.end());
}
+ //If we're adding ocarina buttons to the main window...
+ if (CVarGetInteger("gItemTrackerOcarinaButtonsDisplayType", 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)
+ while (mainWindowItems.size() % 6) {
+ mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
+ }
+
+ //Add ocarina buttons
+ mainWindowItems.insert(mainWindowItems.end(), ocarinaButtonItems.begin(), ocarinaButtonItems.end());
+ }
+
shouldUpdateVectors = false;
}
@@ -1156,6 +1220,12 @@ void ItemTrackerWindow::DrawElement() {
EndFloatingWindows();
}
+ if (CVarGetInteger("gItemTrackerOcarinaButtonsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE) {
+ BeginFloatingWindows("Ocarina Button Tracker");
+ DrawItemsInRows(ocarinaButtonItems);
+ EndFloatingWindows();
+ }
+
if (CVarGetInteger("gItemTrackerNotesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_SEPARATE && CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) {
ImGui::SetNextWindowSize(ImVec2(400,300), ImGuiCond_FirstUseEver);
BeginFloatingWindows("Personal Notes", ImGuiWindowFlags_NoFocusOnAppearing);
@@ -1299,6 +1369,10 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true;
}
+ if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Ocarina Buttons", "gItemTrackerOcarinaButtonsDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) {
+ shouldUpdateVectors = true;
+ }
+
if (CVarGetInteger("gItemTrackerDisplayType", TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_ALWAYS) {
if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Personal notes", "gItemTrackerNotesDisplayType", displayTypes, SECTION_DISPLAY_HIDDEN)) {
shouldUpdateVectors = true;
diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp
index b82c7a0d1..833778348 100644
--- a/soh/soh/Enhancements/randomizer/savefile.cpp
+++ b/soh/soh/Enhancements/randomizer/savefile.cpp
@@ -293,6 +293,14 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple
}
+ if (Randomizer_GetSettingValue(RSK_SHUFFLE_OCARINA_BUTTONS) == RO_GENERIC_OFF) {
+ Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A);
+ Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT);
+ Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT);
+ Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP);
+ Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN);
+ }
+
// Give Link's pocket item
GiveLinksPocketItem();
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index f32c981af..7215415e2 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -103,6 +103,7 @@ void Settings::CreateOptions() {
mOptions[RSK_SHUFFLE_KOKIRI_SWORD] = Option::Bool("Shuffle Kokiri Sword", "gRandomizeShuffleKokiriSword", mOptionDescriptions[RSK_SHUFFLE_KOKIRI_SWORD]);
mOptions[RSK_SHUFFLE_MASTER_SWORD] = Option::Bool("Shuffle Master Sword", "gRandomizeShuffleMasterSword", mOptionDescriptions[RSK_SHUFFLE_MASTER_SWORD]);
mOptions[RSK_SHUFFLE_OCARINA] = Option::Bool("Shuffle Ocarinas", "gRandomizeShuffleOcarinas", mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
+ mOptions[RSK_SHUFFLE_OCARINA_BUTTONS] = Option::Bool("Shuffle Ocarina Buttons", "gRandomizeShuffleOcarinaButtons", mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
mOptions[RSK_SHUFFLE_WEIRD_EGG] = Option::Bool("Shuffle Weird Egg", "gRandomizeShuffleWeirdEgg", mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = Option::Bool("Shuffle Gerudo Membership Card", "gRandomizeShuffleGerudoToken", mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
mOptions[RSK_SHUFFLE_MAGIC_BEANS] = Option::Bool("Shuffle Magic Beans", "gRandomizeShuffleBeans", mOptionDescriptions[RSK_SHUFFLE_MAGIC_BEANS]);
@@ -613,6 +614,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_KOKIRI_SWORD],
&mOptions[RSK_SHUFFLE_MASTER_SWORD],
&mOptions[RSK_SHUFFLE_OCARINA],
+ &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]
}, false, WidgetContainerType::COLUMN);
@@ -813,6 +815,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_COWS],
&mOptions[RSK_SHUFFLE_KOKIRI_SWORD],
&mOptions[RSK_SHUFFLE_OCARINA],
+ &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
&mOptions[RSK_SHUFFLE_MAGIC_BEANS],
@@ -1018,6 +1021,7 @@ void Settings::CreateOptions() {
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
{ "Shuffle Settings:Shuffle Ocarinas", RSK_SHUFFLE_OCARINA },
+ { "Shuffle Settings:Shuffle Ocarina Buttons", RSK_SHUFFLE_OCARINA_BUTTONS },
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
{ "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS },
{ "Shuffle Settings:Shuffle Kokiri Sword", RSK_SHUFFLE_KOKIRI_SWORD },
@@ -2106,6 +2110,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
case RSK_SHUFFLE_FROG_SONG_RUPEES:
case RSK_SHUFFLE_100_GS_REWARD:
case RSK_SHUFFLE_OCARINA:
+ case RSK_SHUFFLE_OCARINA_BUTTONS:
case RSK_STARTING_DEKU_SHIELD:
case RSK_STARTING_KOKIRI_SWORD:
case RSK_STARTING_ZELDAS_LULLABY:
diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c
index f2f72885d..c1528ec88 100644
--- a/soh/src/code/code_800EC960.c
+++ b/soh/src/code/code_800EC960.c
@@ -1626,23 +1626,23 @@ void func_800ED458(s32 arg0) {
}
Audio_OcaUpdateBtnMap(customControls, dpad, rStick);
- if (D_8016BA18 & sOcarinaD4BtnMap) {
+ if (D_8016BA18 & sOcarinaD4BtnMap && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A))) {
osSyncPrintf("Presss NA_KEY_D4 %08x\n", sOcarinaD4BtnMap);
sCurOcarinaBtnVal = 2;
sCurOcarinaBtnIdx = 0;
- } else if (D_8016BA18 & sOcarinaF4BtnMap) {
+ } else if (D_8016BA18 & sOcarinaF4BtnMap && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN))) {
osSyncPrintf("Presss NA_KEY_F4 %08x\n", sOcarinaF4BtnMap);
sCurOcarinaBtnVal = 5;
sCurOcarinaBtnIdx = 1;
- } else if (D_8016BA18 & sOcarinaA4BtnMap) {
+ } else if (D_8016BA18 & sOcarinaA4BtnMap && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT))) {
osSyncPrintf("Presss NA_KEY_A4 %08x\n", sOcarinaA4BtnMap);
sCurOcarinaBtnVal = 9;
sCurOcarinaBtnIdx = 2;
- } else if (D_8016BA18 & sOcarinaB4BtnMap) {
+ } else if (D_8016BA18 & sOcarinaB4BtnMap && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT))) {
osSyncPrintf("Presss NA_KEY_B4 %08x\n", sOcarinaA4BtnMap);
sCurOcarinaBtnVal = 0xB;
sCurOcarinaBtnIdx = 3;
- } else if (D_8016BA18 & sOcarinaD5BtnMap) {
+ } else if (D_8016BA18 & sOcarinaD5BtnMap && (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP))) {
osSyncPrintf("Presss NA_KEY_D5 %08x\n", sOcarinaD5BtnMap);
sCurOcarinaBtnVal = 0xE;
sCurOcarinaBtnIdx = 4;
diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 802abc951..141dbaf6a 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -2664,6 +2664,13 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
return Return_Item_Entry(giEntry, RG_NONE);
}
+ if (item >= RG_OCARINA_A_BUTTON && item <= RG_OCARINA_C_RIGHT_BUTTON) {
+ u8 index = item - RG_OCARINA_A_BUTTON;
+ Flags_SetRandomizerInf(RAND_INF_HAS_OCARINA_A + index);
+
+ return Return_Item_Entry(giEntry, RG_NONE);
+ }
+
temp = gSaveContext.inventory.items[slot];
osSyncPrintf("Item_Register(%d)=%d %d\n", slot, item, temp);
INV_CONTENT(item) = item;
diff --git a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c
index 0a118916b..fe09f4e2b 100644
--- a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c
+++ b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c
@@ -117,7 +117,16 @@ void func_80A90264(EnKakasi2* this, PlayState* play) {
this->unk_194++;
- bool skipScarecrow = play->msgCtx.msgMode == MSGMODE_OCARINA_PLAYING &&
+ int ocarinaButtonCount = 0;
+ for (int i = RAND_INF_HAS_OCARINA_A; i <= RAND_INF_HAS_OCARINA_C_DOWN; i++) {
+ if (Flags_GetRandomizerInf(i)) {
+ ocarinaButtonCount++;
+ }
+ }
+
+ bool hasTwoOcarinaButtons = !IS_RANDO || ocarinaButtonCount >= 2;
+
+ bool skipScarecrow = hasTwoOcarinaButtons && play->msgCtx.msgMode == MSGMODE_OCARINA_PLAYING &&
((CVarGetInteger("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet) ||
(IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG)));
diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c
index 987c004a0..78b5ee32f 100644
--- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c
+++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_collect.c
@@ -12,6 +12,9 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
} else if (CVarGetInteger("gCosmetics.DefaultColorScheme", COLORSCHEME_N64) == COLORSCHEME_GAMECUBE) {
aButtonColor = (Color_RGB8){ 80, 255, 150 };
}
+ if (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A)) {
+ aButtonColor = (Color_RGB8){ 191, 191, 191 };
+ }
Color_RGB8 cButtonsColor = {255, 255, 50};
if (CVarGetInteger("gCosmetics.Hud_CButtons.Changed", 0)) {
@@ -21,18 +24,33 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) {
if (CVarGetInteger("gCosmetics.Hud_CUpButton.Changed", 0)) {
cUpButtonColor = CVarGetColor24("gCosmetics.Hud_CUpButton.Value", cUpButtonColor);
}
+ if (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP)) {
+ cUpButtonColor = (Color_RGB8){ 191, 191, 191 };
+ }
+
Color_RGB8 cDownButtonColor = cButtonsColor;
if (CVarGetInteger("gCosmetics.Hud_CDownButton.Changed", 0)) {
cDownButtonColor = CVarGetColor24("gCosmetics.Hud_CDownButton.Value", cDownButtonColor);
}
+ if (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN)) {
+ cDownButtonColor = (Color_RGB8){ 191, 191, 191 };
+ }
+
Color_RGB8 cLeftButtonColor = cButtonsColor;
if (CVarGetInteger("gCosmetics.Hud_CLeftButton.Changed", 0)) {
cLeftButtonColor = CVarGetColor24("gCosmetics.Hud_CLeftButton.Value", cLeftButtonColor);
}
+ if (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT)) {
+ cLeftButtonColor = (Color_RGB8){ 191, 191, 191 };
+ }
+
Color_RGB8 cRightButtonColor = cButtonsColor;
if (CVarGetInteger("gCosmetics.Hud_CRightButton.Changed", 0)) {
cRightButtonColor = CVarGetColor24("gCosmetics.Hud_CRightButton.Value", cRightButtonColor);
}
+ if (IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT)) {
+ cRightButtonColor = (Color_RGB8){ 191, 191, 191 };
+ }
static s16 D_8082A070[][4] = {
{ 255, 0, 0, 255 },