diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/eff_unknown_10_i8 b/soh/assets/custom/objects/object_gi_fishing_pole/eff_unknown_10_i8
new file mode 100644
index 000000000..174f53cb7
Binary files /dev/null and b/soh/assets/custom/objects/object_gi_fishing_pole/eff_unknown_10_i8 differ
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/eff_unknown_10_i8_png b/soh/assets/custom/objects/object_gi_fishing_pole/eff_unknown_10_i8_png
new file mode 100644
index 000000000..174f53cb7
Binary files /dev/null and b/soh/assets/custom/objects/object_gi_fishing_pole/eff_unknown_10_i8_png differ
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL
new file mode 100644
index 000000000..49ed9b0e5
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_0 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_0
new file mode 100644
index 000000000..747739cb7
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_0
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_1 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_1
new file mode 100644
index 000000000..6a28afee1
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_1
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_2 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_2
new file mode 100644
index 000000000..0f07ec616
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_2
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_3 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_3
new file mode 100644
index 000000000..b3bccf78a
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_3
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_4 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_4
new file mode 100644
index 000000000..7aa7522e8
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_4
@@ -0,0 +1,341 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_5 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_5
new file mode 100644
index 000000000..e815ce7ed
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_5
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_6 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_6
new file mode 100644
index 000000000..1c9bb3d9e
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_6
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_7 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_7
new file mode 100644
index 000000000..fff6a9fee
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_tri_7
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_0 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_0
new file mode 100644
index 000000000..810b26e0c
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_0
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_1 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_1
new file mode 100644
index 000000000..69b125a3e
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_1
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_2 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_2
new file mode 100644
index 000000000..606a6ab09
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_2
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_3 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_3
new file mode 100644
index 000000000..8d8b43d0f
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_3
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_4 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_4
new file mode 100644
index 000000000..802a69d26
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_4
@@ -0,0 +1,672 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_5 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_5
new file mode 100644
index 000000000..4137d75a2
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_5
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_6 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_6
new file mode 100644
index 000000000..7ce420cfc
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_6
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_7 b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_7
new file mode 100644
index 000000000..381565a0e
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_7
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_cull b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_cull
new file mode 100644
index 000000000..47672f31f
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/gFishingPoleGiDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_black b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_black
new file mode 100644
index 000000000..26808af42
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_black
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_f3dlite_material_006 b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_f3dlite_material_006
new file mode 100644
index 000000000..3db97957e
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_f3dlite_material_006
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_line b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_line
new file mode 100644
index 000000000..d08aa632a
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_line
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_accent_001 b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_accent_001
new file mode 100644
index 000000000..3fff6a270
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_accent_001
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_handle_metal b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_handle_metal
new file mode 100644
index 000000000..9633e2458
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_handle_metal
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_metal_001 b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_metal_001
new file mode 100644
index 000000000..332c12c8d
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_metal_001
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_white b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_white
new file mode 100644
index 000000000..4b12ae0fb
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_reel_white
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_wood b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_wood
new file mode 100644
index 000000000..82b446f53
--- /dev/null
+++ b/soh/assets/custom/objects/object_gi_fishing_pole/mat_gFishingPoleGiDL_wood
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 8765522b7..58fed005f 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -74,6 +74,9 @@ static const ALIGN_ASSET(2) char gTriforcePieceCompletedDL[] = dgTriforcePieceCo
#define dgBossSoulSkullDL "__OTR__objects/object_boss_soul/gGIBossSoulSkullDL"
static const ALIGN_ASSET(2) char gBossSoulSkullDL[] = dgBossSoulSkullDL;
+#define dgFishingPoleGiDL "__OTR__objects/object_gi_fishing_pole/gFishingPoleGiDL"
+static const ALIGN_ASSET(2) char gFishingPoleGiDL[] = dgFishingPoleGiDL;
+
// overlays
#define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx"
static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx;
diff --git a/soh/include/z64item.h b/soh/include/z64item.h
index 1fc919a45..92ce499ba 100644
--- a/soh/include/z64item.h
+++ b/soh/include/z64item.h
@@ -574,6 +574,7 @@ typedef enum {
/* 0x7A */ GID_SONG_TIME,
/* 0x7B */ GID_SONG_STORM,
/* 0x7C */ GID_TRIFORCE_PIECE,
+ /* */ GID_FISHING_POLE,
/* 0x7C */ GID_MAXIMUM
} GetItemDrawID;
diff --git a/soh/include/z64save.h b/soh/include/z64save.h
index 1e853568a..b0839b1d3 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[11];
+ /* */ u16 randomizerInf[14];
/* */ u8 mqDungeonCount;
/* */ u16 adultTradeItems;
/* */ u8 triforcePiecesCollected;
@@ -326,6 +326,18 @@ typedef enum {
/* 0x06 */ HS_DAMPE_RACE
} HighScores;
+// the score value for the fishing minigame also stores many flags.
+#define HS_FISH_LENGTH_CHILD 0x7F // mask for record length of catch as child.
+#define HS_FISH_LENGTH_ADULT 0x7F000000 // mask for record length of catch as adult.
+#define HS_FISH_PLAYED_CHILD 0x100 // set when first talking to owner as child
+#define HS_FISH_PLAYED_ADULT 0x200 // set when first talking to owner as adult
+#define HS_FISH_PRIZE_CHILD 0x400 // won the Piece of Heart
+#define HS_FISH_PRIZE_ADULT 0x800 // won the Golden Scale
+#define HS_FISH_STOLE_HAT 0x1000 // Pond owner is visibly bald as Adult Link.
+#define HS_FISH_CHEAT_CHILD 0x80 // used Sinking Lure as child to catch record fish
+#define HS_FISH_CHEAT_ADULT 0x80000000 // used Sinking Lure as adult to catch record fish
+#define HS_FISH_PLAYED 0x10000 // incremented for every play. controls weather.
+
typedef enum {
/* 0 */ SUNSSONG_INACTIVE,
/* 1 */ SUNSSONG_START, // the suns ocarina effect signals that the song has finished playing
diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h
index d8c66ce7d..64f2de063 100644
--- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h
+++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h
@@ -135,6 +135,8 @@ typedef enum {
TEXT_BEAN_SALESMAN_SET_A_BEAN_TO_C = 0x406A,
TEXT_BEAN_SALESMAN_SOLD_OUT = 0x406B,
TEXT_BEAN_SALESMAN_WANT_TO_PLANT = 0x406C,
+ TEXT_FISHING_POND_START = 0x407B,
+ TEXT_FISHING_POND_START_MET = 0x4093,
TEXT_DAMPES_DIARY = 0x5003,
TEXT_GRANNYS_SHOP = 0x500C,
TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK = 0x5036,
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
index f90ab739c..468a46aca 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
@@ -1123,6 +1123,36 @@ void DrawFlagsTab() {
}
});
}
+
+ // make some buttons to help with fishsanity debugging
+ uint8_t fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
+ if (flagTable.flagTableType == RANDOMIZER_INF &&
+ fsMode != RO_FISHSANITY_OFF && fsMode != RO_FISHSANITY_OVERWORLD) {
+ if (ImGui::Button("Catch All (Child)")) {
+ for (int k = RAND_INF_CHILD_FISH_1; k <= RAND_INF_CHILD_LOACH_2; k++) {
+ Flags_SetRandomizerInf((RandomizerInf)k);
+ }
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Uncatch All (Child)")) {
+ for (int k = RAND_INF_CHILD_FISH_1; k <= RAND_INF_CHILD_LOACH_2; k++) {
+ Flags_UnsetRandomizerInf((RandomizerInf)k);
+ }
+ }
+
+ if (ImGui::Button("Catch All (Adult)")) {
+ for (int k = RAND_INF_ADULT_FISH_1; k <= RAND_INF_ADULT_LOACH; k++) {
+ Flags_SetRandomizerInf((RandomizerInf)k);
+ }
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Uncatch All (Adult)")) {
+ for (int k = RAND_INF_ADULT_FISH_1; k <= RAND_INF_ADULT_LOACH; k++) {
+ Flags_UnsetRandomizerInf((RandomizerInf)k);
+ }
+ }
+ }
+
ImGui::TreePop();
}
}
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h
index dec733f3e..481d6c75d 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, 0x0A, {
+ { "Randomizer Inf Flags", RANDOMIZER_INF, 13, {
{ 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" },
@@ -517,11 +517,54 @@ const std::vector flagTables = {
{ 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"},
+ { RAND_INF_CHILD_FISH_1, "RAND_INF_CHILD_FISH_1" },
+ { RAND_INF_CHILD_FISH_2, "RAND_INF_CHILD_FISH_2" },
+ { RAND_INF_CHILD_FISH_3, "RAND_INF_CHILD_FISH_3" },
+ { RAND_INF_CHILD_FISH_4, "RAND_INF_CHILD_FISH_4" },
+ { RAND_INF_CHILD_FISH_5, "RAND_INF_CHILD_FISH_5" },
+ { RAND_INF_CHILD_FISH_6, "RAND_INF_CHILD_FISH_6" },
+ { RAND_INF_CHILD_FISH_7, "RAND_INF_CHILD_FISH_7" },
+ { RAND_INF_CHILD_FISH_8, "RAND_INF_CHILD_FISH_8" },
+ { RAND_INF_CHILD_FISH_9, "RAND_INF_CHILD_FISH_9" },
+ { RAND_INF_CHILD_FISH_10, "RAND_INF_CHILD_FISH_10" },
+ { RAND_INF_CHILD_FISH_11, "RAND_INF_CHILD_FISH_11" },
+ { RAND_INF_CHILD_FISH_12, "RAND_INF_CHILD_FISH_12" },
+ { RAND_INF_CHILD_FISH_13, "RAND_INF_CHILD_FISH_13" },
+ { RAND_INF_CHILD_FISH_14, "RAND_INF_CHILD_FISH_14" },
+ { RAND_INF_CHILD_FISH_15, "RAND_INF_CHILD_FISH_15" },
+ { RAND_INF_CHILD_LOACH_1, "RAND_INF_CHILD_LOACH_1" },
+ { RAND_INF_CHILD_LOACH_2, "RAND_INF_CHILD_LOACH_2" },
+ { RAND_INF_ADULT_FISH_1, "RAND_INF_ADULT_FISH_1" },
+ { RAND_INF_ADULT_FISH_2, "RAND_INF_ADULT_FISH_2" },
+ { RAND_INF_ADULT_FISH_3, "RAND_INF_ADULT_FISH_3" },
+ { RAND_INF_ADULT_FISH_4, "RAND_INF_ADULT_FISH_4" },
+ { RAND_INF_ADULT_FISH_5, "RAND_INF_ADULT_FISH_5" },
+ { RAND_INF_ADULT_FISH_6, "RAND_INF_ADULT_FISH_6" },
+ { RAND_INF_ADULT_FISH_7, "RAND_INF_ADULT_FISH_7" },
+ { RAND_INF_ADULT_FISH_8, "RAND_INF_ADULT_FISH_8" },
+ { RAND_INF_ADULT_FISH_9, "RAND_INF_ADULT_FISH_9" },
+ { RAND_INF_ADULT_FISH_10, "RAND_INF_ADULT_FISH_10" },
+ { RAND_INF_ADULT_FISH_11, "RAND_INF_ADULT_FISH_11" },
+ { RAND_INF_ADULT_FISH_12, "RAND_INF_ADULT_FISH_12" },
+ { RAND_INF_ADULT_FISH_13, "RAND_INF_ADULT_FISH_13" },
+ { RAND_INF_ADULT_FISH_14, "RAND_INF_ADULT_FISH_14" },
+ { RAND_INF_ADULT_FISH_15, "RAND_INF_ADULT_FISH_15" },
+ { RAND_INF_ADULT_LOACH, "RAND_INF_ADULT_LOACH" },
+ { RAND_INF_GROTTO_FISH_ZR_OPEN_GROTTO, "RAND_INF_GROTTO_FISH_ZR_OPEN_GROTTO" },
+ { RAND_INF_GROTTO_FISH_DMC_UPPER_GROTTO, "RAND_INF_GROTTO_FISH_DMC_UPPER_GROTTO" },
+ { RAND_INF_GROTTO_FISH_DMT_STORMS_GROTTO, "RAND_INF_GROTTO_FISH_DMT_STORMS_GROTTO" },
+ { RAND_INF_GROTTO_FISH_KAK_OPEN_GROTTO, "RAND_INF_GROTTO_FISH_KAK_OPEN_GROTTO" },
+ { RAND_INF_GROTTO_FISH_HF_NEAR_MARKET_GROTTO, "RAND_INF_GROTTO_FISH_HF_NEAR_MARKET_GROTTO" },
+ { RAND_INF_GROTTO_FISH_HF_OPEN_GROTTO, "RAND_INF_GROTTO_FISH_HF_OPEN_GROTTO" },
+ { RAND_INF_GROTTO_FISH_HF_SOUTHEAST_GROTTO, "RAND_INF_GROTTO_FISH_HF_SOUTHEAST_GROTTO" },
+ { RAND_INF_GROTTO_FISH_LW_NEAR_SHORTCUTS_GROTTO, "RAND_INF_GROTTO_FISH_LW_NEAR_SHORTCUTS_GROTTO" },
+ { RAND_INF_GROTTO_FISH_KF_STORMS_GROTTO, "RAND_INF_GROTTO_FISH_KF_STORMS_GROTTO" },
+ { RAND_INF_FISHING_POLE_FOUND, "RAND_INF_FISHING_POLE_FOUND" },
+ { RAND_INF_ZD_FISH_1, "RAND_INF_ZD_FISH_1" },
+ { RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" },
+ { RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" },
+ { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" },
+ { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }
} },
};
diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp
index e6e0aa561..d08a9a575 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -6,6 +6,7 @@
#include "soh/Enhancements/boss-rush/BossRushTypes.h"
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/randomizer/3drando/random.hpp"
+#include "soh/Enhancements/randomizer/fishsanity.h"
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include
#include "soh/Enhancements/nametag.h"
@@ -23,6 +24,7 @@
#include "src/overlays/actors/ovl_En_Tp/z_en_tp.h"
#include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h"
#include "src/overlays/actors/ovl_En_Xc/z_en_xc.h"
+#include "src/overlays//actors/ovl_Fishing/z_fishing.h"
extern "C" {
#include
@@ -1282,6 +1284,156 @@ void RegisterToTMedallions() {
});
}
+void RegisterFishsanity() {
+ static s16 fishGroupCounter = 0;
+
+ // Initialization on load
+ GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) {
+ if (!IS_RANDO) {
+ return;
+ }
+ OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave();
+ });
+
+ // Initialize actors for fishsanity
+ GameInteractor::Instance->RegisterGameHook([](void* refActor) {
+ if (!IS_RANDO) {
+ return;
+ }
+
+ Actor* actor = static_cast(refActor);
+ auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
+ FishIdentity fish;
+
+ if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
+ // Set fish ID for ZD fish
+ if (gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && actor->params == -1) {
+ actor->params ^= fishGroupCounter++;
+ }
+
+ fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
+ // Create effect for uncaught fish
+ if (Rando::Fishsanity::IsFish(&fish) && !Flags_GetRandomizerInf(fish.randomizerInf)) {
+ actor->shape.shadowDraw = Fishsanity_DrawEffShadow;
+ }
+ return;
+ }
+
+ if (actor->id == ACTOR_FISHING && gPlayState->sceneNum == SCENE_FISHING_POND && actor->params >= 100 &&
+ actor->params <= 117 && fs->GetPondFishShuffled()) {
+ // Initialize pond fish for fishsanity
+ // Initialize fishsanity metadata on this actor
+ Fishing* fishActor = static_cast(refActor);
+ fishActor->fishsanityParams = actor->params;
+ fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
+
+ // With every pond fish shuffled, caught fish will not spawn unless all fish have been caught.
+ if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT) > 16 &&
+ !fs->GetPondCleared()) {
+ // Create effect for uncaught fish
+ if (!Flags_GetRandomizerInf(fish.randomizerInf)) {
+ actor->shape.shadowDraw = Fishsanity_DrawEffShadow;
+ }
+ }
+ }
+
+ });
+
+ // Update fishsanity when a fish is caught
+ GameInteractor::Instance->RegisterGameHook([](int16_t flagType, int16_t flag) {
+ if (!IS_RANDO || flagType != FLAG_RANDOMIZER_INF) {
+ return;
+ }
+ RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)flag);
+ FishsanityCheckType fsType = Rando::Fishsanity::GetCheckType(rc);
+ if (fsType == FSC_NONE) {
+ return;
+ }
+
+ // When a pond fish is caught, advance the pond.
+ if (fsType == FSC_POND) {
+ OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond();
+ }
+ });
+
+ // Award fishing pond checks
+ GameInteractor::Instance->RegisterGameHook([]() {
+ if (!IS_RANDO || GameInteractor::IsGameplayPaused() || !gPlayState) {
+ return;
+ }
+
+ Player* player = GET_PLAYER(gPlayState);
+ if (Player_InBlockingCsMode(gPlayState, player)) {
+ return;
+ }
+
+ auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
+ if (!fs->GetPondFishShuffled()) {
+ return;
+ }
+
+ FishIdentity pending = fs->GetPendingFish();
+ if (!Rando::Fishsanity::IsFish(&pending)) { // No fish currently pending
+ return;
+ }
+
+ // Award fish
+ GetItemEntry gi = OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(pending.randomizerCheck, GI_NONE);
+ Flags_SetRandomizerInf(pending.randomizerInf);
+ GiveItemEntryWithoutActor(gPlayState, gi);
+ fs->SetPendingFish(NULL);
+ });
+
+ GameInteractor::Instance->RegisterGameHook([](void* refActor) {
+ if (!IS_RANDO || (gPlayState->sceneNum != SCENE_GROTTOS && gPlayState->sceneNum != SCENE_ZORAS_DOMAIN && gPlayState->sceneNum != SCENE_FISHING_POND)) {
+ return;
+ }
+
+ Actor* actor = static_cast(refActor);
+ auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
+
+ // Detect fish catch
+ if (actor->id == ACTOR_FISHING && fs->GetPondFishShuffled()) {
+ Fishing* fish = static_cast(refActor);
+
+ // State 6 -> Fish caught and hoisted
+ FishIdentity pending = fs->GetPendingFish();
+ if (fish->fishState == 6 && !Rando::Fishsanity::IsFish(&pending)) {
+ pending = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, fish->fishsanityParams);
+ if (!Flags_GetRandomizerInf(pending.randomizerInf)) {
+ fs->SetPendingFish(&pending);
+ // Remove uncaught effect
+ if (actor->shape.shadowDraw != NULL) {
+ actor->shape.shadowDraw = NULL;
+ }
+ }
+ }
+ }
+
+ if (actor->id == ACTOR_EN_FISH && fs->GetOverworldFishShuffled()) {
+ FishIdentity fish = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params);
+ if (Rando::Fishsanity::IsFish(&fish) && Flags_GetRandomizerInf(fish.randomizerInf)) {
+ // Remove uncaught effect
+ if (actor->shape.shadowDraw != NULL) {
+ actor->shape.shadowDraw = NULL;
+ }
+ }
+ }
+
+ // Reset fish group counter when the group gets culled
+ if (actor->id == ACTOR_OBJ_MURE && gPlayState->sceneNum == SCENE_ZORAS_DOMAIN && fishGroupCounter > 0 &&
+ !(actor->flags & ACTOR_FLAG_UPDATE_WHILE_CULLED) && fs->GetOverworldFishShuffled()) {
+ fishGroupCounter = 0;
+ }
+ });
+
+ GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) {
+ if (!IS_RANDO || sceneNum != SCENE_ZORAS_DOMAIN)
+ return;
+ fishGroupCounter = 0;
+ });
+}
+
void InitMods() {
RegisterTTS();
RegisterInfiniteMoney();
@@ -1315,5 +1467,6 @@ void InitMods() {
RegisterBossSouls();
RegisterRandomizedEnemySizes();
RegisterToTMedallions();
+ RegisterFishsanity();
NameTag_RegisterHooks();
}
diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h
index d7efeb4f3..01a7d8024 100644
--- a/soh/soh/Enhancements/presets.h
+++ b/soh/soh/Enhancements/presets.h
@@ -122,6 +122,8 @@ const std::vector enhancementsCvars = {
"gInstantFishing",
"gGuaranteeFishingBite",
"gFishNeverEscape",
+ "gLoachesAlwaysAppear",
+ "gSkipKeepConfirmation",
"gChildMinimumWeightFish",
"gAdultMinimumWeightFish",
"gLowHpAlarm",
@@ -341,6 +343,10 @@ const std::vector randomizerCvars = {
"gRandomizeExcludedLocations",
"gRandomizeForest",
"gRandomizeFullWallets",
+ "gRandomizeFishingPoleHint",
+ "gRandomizeFishsanity",
+ "gRandomizeFishsanityPondCount",
+ "gRandomizeFishsanityAgeSplit",
"gRandomizeGanonTrial",
"gRandomizeGanonTrialCount",
"gRandomizeGerudoFortress",
@@ -382,6 +388,7 @@ const std::vector randomizerCvars = {
"gRandomizeShuffleCows",
"gRandomizeShuffleDungeonReward",
"gRandomizeShuffleDungeonsEntrances",
+ "gRandomizeShuffleFishingPole",
"gRandomizeShuffleFrogSongRupees",
"gRandomizeShuffleGanonBossKey",
"gRandomizeShuffleGerudoToken",
diff --git a/soh/soh/Enhancements/randomizer/3drando/category.hpp b/soh/soh/Enhancements/randomizer/3drando/category.hpp
index f43b3ccba..8916f53df 100644
--- a/soh/soh/Enhancements/randomizer/3drando/category.hpp
+++ b/soh/soh/Enhancements/randomizer/3drando/category.hpp
@@ -9,6 +9,7 @@ enum class Category {
cSong,
cSongDungeonReward,
cCow,
+ cFish,
cShop,
cMerchant,
cVanillaSmallKey,
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
index 6540e18a4..c6269d5de 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
@@ -3127,6 +3127,24 @@ void HintTable_Init() {
"# bei sich haben und Dich neugierig beobachten..."
}});
+ hintTable[RHT_FISHING_POLE_HINT01] = HintText::OtherHint({
+ // obscure text
+ Text{"^If I remember correctly, I lost it somewhere in %r",
+ /*french*/
+ "",
+ /*spanish*/
+ "" }
+ });
+
+ hintTable[RHT_FISHING_POLE_HINT02] = HintText::OtherHint({
+ // obscure text
+ Text{"%w...&Let me know if you find it!",
+ /*french*/
+ "",
+ /*spanish*/
+ "" }
+ });
+
/*--------------------------
| GANON LINE TEXT |
---------------------------*/
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp
index 5e5a003ec..026514441 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp
@@ -1,4 +1,5 @@
#include "../hint_list.hpp"
+#include
void HintTable_Init_Exclude_Overworld() {
hintTable[RHT_KF_KOKIRI_SWORD_CHEST] = HintText::Exclude({
@@ -91,46 +92,91 @@ void HintTable_Init_Exclude_Overworld() {
Text{"a #hole in a field near a drawbridge# holds", /*french*/"la #grotte près d'un pont# contient", /*spanish*/"bajo el #hoyo de una llanura cercano a un puente# yace"},
});
+ hintTable[RHT_HF_NEAR_MARKET_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in a hole in a field near a drawbridge# holds", /*french*/"la #grotte près d'un pont# contient", /*spanish*/"bajo el #hoyo de una llanura cercano a un puente# yace"},
+ });
+
hintTable[RHT_HF_SOUTHEAST_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"a #hole amongst trees in a field# holds", /*french*/"la #grotte près des arbres# contient", /*spanish*/"bajo el #hoyo de una llanura rodeado de árboles# yace"},
});
+
+ hintTable[RHT_HF_SOUTHEAST_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in a hole amongst trees in a field# holds", /*french*/"la #grotte près des arbres# contient", /*spanish*/"bajo el #hoyo de una llanura rodeado de árboles# yace"},
+ });
hintTable[RHT_HF_OPEN_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"an #open hole in a field# holds", /*french*/"la #grotte dans les plaines# contient", /*spanish*/"bajo el #hoyo descubierto de una llanura# yace"},
});
+ hintTable[RHT_HF_OPEN_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in an open hole in a field# holds", /*french*/"la #grotte dans les plaines# contient", /*spanish*/"bajo el #hoyo descubierto de una llanura# yace"},
+ });
+
hintTable[RHT_KAK_OPEN_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"an #open hole in a town# holds", /*french*/"la #grotte dans le village# contient", /*spanish*/"bajo el #hoyo descubierto de un pueblo# yace"},
});
+ hintTable[RHT_KAK_OPEN_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in an open hole in a town# holds", /*french*/"la #grotte dans le village# contient", /*spanish*/"bajo el #hoyo descubierto de un pueblo# yace"},
+ });
+
hintTable[RHT_ZR_OPEN_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"a #hole along a river# holds", /*french*/"la #grotte près du fleuve# contient", /*spanish*/"bajo un #hoyo junto a un rÃo# yace"},
});
+ hintTable[RHT_ZR_OPEN_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in a hole along a river# holds", /*french*/"la #grotte près du fleuve# contient", /*spanish*/"bajo un #hoyo junto a un rÃo# yace"},
+ });
+
hintTable[RHT_KF_STORMS_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"a #hole in a forest village# holds", /*french*/"la #grotte inondée de pluie dans le Village Kokiri# révèle", /*spanish*/"bajo el #hoyo de una tribu del bosque# yace"},
});
+ hintTable[RHT_KF_STORMS_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in a hole in a forest village# holds", /*french*/"la #grotte inondée de pluie dans le Village Kokiri# révèle", /*spanish*/"bajo el #hoyo de una tribu del bosque# yace"},
+ });
+
hintTable[RHT_LW_NEAR_SHORTCUTS_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"a #hole in a wooded maze# holds", /*french*/"la #grotte dans le labyrinthe sylvestre# contient", /*spanish*/"bajo un #hoyo de un laberinto forestal# yace"},
});
+ hintTable[RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in a hole in a wooded maze# holds", /*french*/"la #grotte dans le labyrinthe sylvestre# contient", /*spanish*/"bajo un #hoyo de un laberinto forestal# yace"},
+ });
+
hintTable[RHT_DMT_STORMS_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"#hole flooded with rain on a mountain# holds", /*french*/"la #grotte inondée de pluie sur la montagne# contient", /*spanish*/"bajo un #hoyo de una montaña inundado de lluvia# yace"},
});
+ hintTable[RHT_DMT_STORMS_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"#fish in a hole flooded with rain on a mountain# holds", /*french*/"la #grotte inondée de pluie sur la montagne# contient", /*spanish*/"bajo un #hoyo de una montaña inundado de lluvia# yace"},
+ });
+
hintTable[RHT_DMC_UPPER_GROTTO_CHEST] = HintText::Exclude({
//obscure text
Text{"a #hole in a volcano# holds", /*french*/"la #grotte dans le volcan# contient", /*spanish*/"bajo el #hoyo de un volcán# yace"},
});
+ hintTable[RHT_DMC_UPPER_GROTTO_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"a #fish in a hole in a volcano# holds", /*french*/"la #grotte dans le volcan# contient", /*spanish*/"bajo el #hoyo de un volcán# yace"},
+ });
+
hintTable[RHT_TOT_MASTER_SWORD] = HintText::Exclude({
//obscure text
Text{"a #pedestal in a temple# holds", /*french*/"un #piédestal dans un temple# contient", /*spanish*/"un #pedestal en un templo# sostiene"},
@@ -225,6 +271,27 @@ void HintTable_Init_Exclude_Overworld() {
Text{"#fishing in youth# bestows", /*french*/"#pêcher dans sa jeunesse# promet", /*spanish*/"#pescar en la juventud# conduce a"},
});
+ // TODO: needs french + spanish translation
+ hintTable[RHT_LH_POND_FISH] = HintText::Exclude({
+ //obscure text
+ Text{"#hitting the pond# reveals", /*french*/ "", /*spanish*/ ""},
+ {},
+ //clear text
+ Text{"#the fishing pond's bounty# includes", /*french*/ "", /*spanish*/ ""}
+ });
+
+ // TODO: needs french translation
+ hintTable[RHT_LH_HYRULE_LOACH] = HintText::Exclude(
+ {
+ // obscure text
+ Text{ "#fishing the legend# bestows", /*french*/ "!!!", /*spanish*/ "#pescar a la leyenda# conduce a" },
+ },
+ {},
+ // clear text
+ Text{ "#fishing the hyrule loach# will give you", /*french*/ "!!!",
+ /*spanish*/ "si #pescas a la Locha de Hyrule# encontrarás" });
+
+
hintTable[RHT_LH_ADULT_FISHING] = HintText::Exclude({
//obscure text
Text{"#fishing in maturity# bestows", /*french*/"#pêcher dans sa maturité# promet", /*spanish*/"#pescar en la madurez# conduce a"},
@@ -235,6 +302,12 @@ void HintTable_Init_Exclude_Overworld() {
Text{"a #diving experiment# is rewarded with", /*french*/"l'#expérience de plongée# donne", /*spanish*/"#bucear para un experimento# se premia con"},
});
+ // TODO: needs translation
+ hintTable[RHT_ZD_FISH] = HintText::Exclude({
+ // obscure text
+ Text{"a #fish by a waterfall# hoards", /*french*/"", /*spanish*/""}
+ });
+
hintTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText::Exclude({
//obscure text
Text{"#comforting yourself# provides", /*french*/"se #réconforter soi-même# donne", /*spanish*/"#confrontarte a ti mismo# otorga"},
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 d2c59c01d..be20b95a3 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
@@ -2102,6 +2102,17 @@ void HintTable_Init_Item() {
Text{"an Ocarina C Right Button", /*french*/"la Touche C-Droit de l'Ocarina", /*spanish*/"un botón C derecho de Ocarina"}}
);
+ hintTable[RHT_FISHING_POLE] = HintText::Item({
+ //obscure text
+ Text{"a fish-puller", /*french*/"(canne à pêche)", /*spanish*/"(caña de pescar)"},
+ }, {
+ //ambiguous text
+ Text{"the pond owner's property", /*french*/"(canne à pêche)", /*spanish*/"(caña de pescar)"},
+ },
+ //clear text
+ Text{"a fishing pole", /*french*/"canne à pêche", /*spanish*/"caña de pescar"}
+ );
+
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/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
index aa1112764..c55655de0 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
@@ -1105,6 +1105,7 @@ void CreateAllHints(){
CreateSpecialItemHint(RG_PROGRESSIVE_HOOKSHOT, RH_DAMPES_DIARY, {RC_DAMPE_HINT}, RHT_DAMPE_DIARY01, RHT_DAMPE_DIARY02, (bool)ctx->GetOption(RSK_DAMPES_DIARY_HINT));
CreateSpecialItemHint(RG_GREG_RUPEE, RH_GREG_RUPEE, {RC_GREG_HINT}, RHT_GREG_HINT01, RHT_GREG_HINT02, (bool)ctx->GetOption(RSK_GREG_HINT));
CreateSpecialItemHint(RG_PROGRESSIVE_MAGIC_METER, RH_SARIA, {RC_SARIA_SONG_HINT, RC_SONG_FROM_SARIA}, RHT_SARIA_TEXT01, RHT_SARIA_TEXT02, (bool)ctx->GetOption(RSK_SARIA_HINT));
+ CreateSpecialItemHint(RG_FISHING_POLE, RH_FISHING_POLE, {RC_FISHING_POLE_HINT}, RHT_FISHING_POLE_HINT01, RHT_FISHING_POLE_HINT02, (bool)ctx->GetOption(RSK_FISHING_POLE_HINT));
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ON_HINT)) {
CreateMerchantsHints();
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index c4fad91eb..7acb68949 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -574,6 +574,13 @@ static void PlaceVanillaCowMilk() {
}
}
+static void PlaceVanillaOverworldFish() {
+ auto ctx = Rando::Context::GetInstance();
+ for (auto rc : Rando::StaticData::overworldFishLocations) {
+ ctx->PlaceItemInLocation(rc, RG_FISH, false, true);
+ }
+}
+
static void SetScarceItemPool() {
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHUS, 3);
ReplaceMaxItem(RG_BOMBCHU_5, 1);
@@ -751,6 +758,40 @@ void GenerateItemPool() {
PlaceVanillaCowMilk();
}
+ auto fsMode = ctx->GetOption(RSK_FISHSANITY);
+ if (fsMode.IsNot(RO_FISHSANITY_OFF)) {
+ if (fsMode.Is(RO_FISHSANITY_POND) || fsMode.Is(RO_FISHSANITY_BOTH)) {
+ // 17 max child pond fish
+ uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).GetSelectedOptionIndex();
+ for (uint8_t i = 0; i < pondCt; i++) {
+ AddItemToMainPool(GetJunkItem());
+ }
+
+ if (ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)) {
+ // 16 max adult pond fish, have to reduce to 16 if every fish is enabled
+ if (pondCt > 16)
+ pondCt = 16;
+ for (uint8_t i = 0; i < pondCt; i++) {
+ AddItemToMainPool(GetJunkItem());
+ }
+ }
+ }
+ // 9 grotto fish, 5 zora's domain fish
+ if (fsMode.Is(RO_FISHSANITY_OVERWORLD) || fsMode.Is(RO_FISHSANITY_BOTH)) {
+ for (uint8_t i = 0; i < Rando::StaticData::overworldFishLocations.size(); i++)
+ AddItemToMainPool(GetJunkItem());
+ } else {
+ PlaceVanillaOverworldFish();
+ }
+ } else {
+ PlaceVanillaOverworldFish();
+ }
+
+ if (ctx->GetOption(RSK_SHUFFLE_FISHING_POLE)) {
+ AddItemToMainPool(RG_FISHING_POLE);
+ ctx->possibleIceTrapModels.push_back(RG_FISHING_POLE);
+ }
+
if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) {
AddItemToMainPool(RG_MAGIC_BEAN_PACK);
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
@@ -971,6 +1012,10 @@ void GenerateItemPool() {
AddItemToPool(PendingJunkPool, RG_GERUDO_MEMBERSHIP_CARD);
}
+ if (ctx->GetOption(RSK_SHUFFLE_FISHING_POLE)) {
+ AddItemToPool(PendingJunkPool, RG_FISHING_POLE);
+ }
+
//Plentiful small keys
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) || ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
if (ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->HasKeyRing()) {
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 213b04695..af1400eb9 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
@@ -62,6 +62,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "DMT Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_DMT_STORMS_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -241,6 +242,7 @@ void AreaTable_Init_DeathMountain() {
areaTable[RR_DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "DMC Upper Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_DMC_UPPER_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
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 61dc34ed0..258ffd8d6 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
@@ -33,6 +33,7 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "HF Southeast Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_HF_SOUTHEAST_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_HF_SOUTHEAST_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -42,6 +43,7 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_HF_OPEN_GROTTO] = Area("HF Open Grotto", "HF Open Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_HF_OPEN_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -69,6 +71,7 @@ void AreaTable_Init_HyruleField() {
areaTable[RR_HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "HF Near Market Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_HF_NEAR_MARKET_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_HF_NEAR_MARKET_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -154,10 +157,45 @@ void AreaTable_Init_HyruleField() {
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
+ // TODO: should some of these helpers be done via events instead?
areaTable[RR_LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", RA_NONE, DAY_NIGHT_CYCLE, {}, {
//Locations
- LocationAccess(RC_LH_CHILD_FISHING, {[]{return logic->IsChild;}}),
- LocationAccess(RC_LH_ADULT_FISHING, {[]{return logic->IsAdult;}}),
+ LocationAccess(RC_LH_CHILD_FISHING, {[]{return logic->CanFish && logic->IsChild;}}),
+ LocationAccess(RC_LH_CHILD_FISH_1, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_2, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_3, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_4, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_5, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_6, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_7, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_8, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_9, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_10, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_11, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_12, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_13, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_14, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_FISH_15, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_LOACH_1, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_CHILD_LOACH_2, {[]{return logic->CanGetChildFish;}}),
+ LocationAccess(RC_LH_ADULT_FISHING, {[]{return logic->CanFish && logic->IsAdult;}}),
+ LocationAccess(RC_LH_ADULT_FISH_1, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_2, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_3, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_4, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_5, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_6, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_7, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_8, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_9, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_10, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_11, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_12, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_13, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_14, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_FISH_15, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_LH_ADULT_LOACH, {[]{return logic->CanGetAdultFish;}}),
+ LocationAccess(RC_FISHING_POLE_HINT,{[]{return true;}}),
}, {
//Exits
Entrance(RR_LH_FISHING_ISLAND, {[]{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 14ec97cb6..750767323 100644
--- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp
@@ -197,6 +197,7 @@ void AreaTable_Init_Kakariko() {
areaTable[RR_KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "Kak Open Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_KAK_OPEN_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_KAK_OPEN_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
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 244a3cfd5..5ad1e6d5c 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
@@ -97,6 +97,7 @@ void AreaTable_Init_LostWoods() {
areaTable[RR_KF_STORMS_GROTTO] = Area("KF Storms Grotto", "KF Storms Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_KF_STORMS_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_KF_STORMS_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -164,6 +165,7 @@ void AreaTable_Init_LostWoods() {
areaTable[RR_LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "LW Near Shortcuts Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
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 7e786d4e6..5dade599a 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
@@ -55,6 +55,7 @@ void AreaTable_Init_ZorasDomain() {
areaTable[RR_ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "ZR Open Grotto", RA_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
+ LocationAccess(RC_ZR_OPEN_GROTTO_FISH, {[]{return logic->HasBottle;}}),
LocationAccess(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
@@ -94,6 +95,11 @@ void AreaTable_Init_ZorasDomain() {
LocationAccess(RC_ZD_KING_ZORA_THAWED, {[]{return logic->KingZoraThawed;}}),
LocationAccess(RC_ZD_TRADE_PRESCRIPTION, {[]{return logic->KingZoraThawed && logic->Prescription;}}),
LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return logic->IsAdult && logic->AtNight && (logic->HookshotOrBoomerang || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->Bow || (logic->MagicMeter && (logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))) || (randoCtx->GetTrickOption(RT_ZD_GS) && logic->CanJumpslash)) && logic->CanGetNightTimeGS;}}),
+ LocationAccess(RC_ZD_FISH_1, {[]{return logic->IsChild && logic->HasBottle;}}),
+ LocationAccess(RC_ZD_FISH_2, {[]{return logic->IsChild && logic->HasBottle;}}),
+ LocationAccess(RC_ZD_FISH_3, {[]{return logic->IsChild && logic->HasBottle;}}),
+ LocationAccess(RC_ZD_FISH_4, {[]{return logic->IsChild && logic->HasBottle;}}),
+ LocationAccess(RC_ZD_FISH_5, {[]{return logic->IsChild && logic->HasBottle;}}),
LocationAccess(RC_ZD_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
index 9ca6a25ea..7ac5173c5 100644
--- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp
@@ -10,7 +10,7 @@
std::vector NonShopItems = {};
-static std::array, 0xF0> trickNameTable; // Table of trick names for ice traps
+static std::array, 0xF1> trickNameTable; // Table of trick names for ice traps
bool initTrickNames = false; //Indicates if trick ice trap names have been initialized yet
//Set vanilla shop item locations before potentially shuffling
@@ -739,6 +739,10 @@ void InitTrickNames() {
Text{"Pure Evil", "", ""},
Text{"Ganon's Ghost", "", ""},
Text{"Pork", "", ""}};
+ trickNameTable[RG_FISHING_POLE] = {
+ Text{"Fish Tickler", "Fish Tickler", "Fish Tickler"},
+ Text{"Floating Lure", "Floating Lure", "Floating Lure"},
+ Text{"Fishing Reel", "Fishing Reel", "Fishing Reel"}};
trickNameTable[RG_OCARINA_A_BUTTON] = {
Text{"Ocarina J Button", "", ""},
diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp
index aaf9d2361..8e0dee301 100644
--- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp
@@ -622,6 +622,11 @@ static void WriteHints() {
jsonData["sariaHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_SARIA)->GetHintedLocation())->GetName();
jsonData["sariaRegion"] = ::Hint(ctx->GetHint(RH_SARIA)->GetHintedArea()).GetText().GetEnglish();
}
+ if (ctx->GetOption(RSK_FISHING_POLE_HINT)) {
+ jsonData["fishingPoleText"] = ctx->GetHint(RH_FISHING_POLE)->GetText().GetForLanguage(language);
+ jsonData["fishingPoleHintLoc"] = Rando::StaticData::GetLocation(ctx->GetHint(RH_FISHING_POLE)->GetHintedLocation())->GetName();
+ jsonData["fishingPoleRegion"] = ::Hint(ctx->GetHint(RH_FISHING_POLE)->GetHintedArea()).GetText().GetEnglish();
+ }
if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NONE)) {
return;
diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp
index 8ad3212f8..51fc51941 100644
--- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp
+++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.hpp
@@ -4,6 +4,7 @@
#include
#include
#include
+#include "../randomizerTypes.h"
using RandomizerHash = std::array;
@@ -18,6 +19,7 @@ typedef enum {
SPOILER_CHK_EVENT_CHK_INF,
SPOILER_CHK_INF_TABLE,
SPOILER_CHK_COW,
+ SPOILER_CHK_FISH,
SPOILER_CHK_MINIGAME,
SPOILER_CHK_SCRUB,
SPOILER_CHK_GERUDO_MEMBERSHIP_CARD,
@@ -74,7 +76,7 @@ typedef enum {
} SpoilerItemRevealType;
#define SPOILER_SPHERES_MAX 50
-#define SPOILER_ITEMS_MAX 512
+#define SPOILER_ITEMS_MAX RC_MAX
#define SPOILER_STRING_DATA_SIZE 16384
typedef struct {
diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp
index 602a21c4f..5cf0dc087 100644
--- a/soh/soh/Enhancements/randomizer/context.cpp
+++ b/soh/soh/Enhancements/randomizer/context.cpp
@@ -9,6 +9,7 @@
#include "entrance.h"
#include "settings.h"
#include "rando_hash.h"
+#include "fishsanity.h"
#include
#include
@@ -91,6 +92,7 @@ Context::Context() {
mLogic = std::make_shared();
mTrials = std::make_shared();
mSettings = std::make_shared();
+ mFishsanity = std::make_shared();
for (auto& location : StaticData::GetLocationTable()) {
mSpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck();
}
@@ -204,6 +206,10 @@ void Context::GenerateLocationPool() {
}
AddLocations(StaticData::overworldLocations);
+ if (mSettings->GetOption(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF)) {
+ AddLocations(mFishsanity->GetFishsanityLocations().first);
+ }
+
for (const auto dungeon : mDungeons->GetDungeonList()) {
AddLocations(dungeon->GetDungeonLocations());
}
@@ -477,6 +483,14 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
AddHint(RH_SARIA, Text(sariaText), sariaHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[sariaRegion]);
}
+ // Fishing Pole Hint
+ if(spoilerFileJson.contains("fishingPoleText")) {
+ std::string fishingPoleText = spoilerFileJson["fishingPoleText"].get();
+ std::string fishingPoleRegion = spoilerFileJson["fishingPoleRegion"].get();
+ RandomizerCheck fishingPoleHintLoc = mSpoilerfileCheckNameToEnum[spoilerFileJson["fishingPoleHintLoc"].get()];
+ AddHint(RH_FISHING_POLE, Text(fishingPoleText), fishingPoleHintLoc, HINT_TYPE_STATIC, "Static", mSpoilerfileAreaNameToEnum[fishingPoleRegion]);
+ }
+
// Warp Songs
if (spoilerFileJson.contains("warpMinuetText")) {
std::string warpMinuetText = spoilerFileJson["warpMinuetText"].get(); //RANDOTODO fall back for if location is used
@@ -529,6 +543,10 @@ std::shared_ptr Context::GetDungeons() {
return mDungeons;
}
+std::shared_ptr Context::GetFishsanity() {
+ return mFishsanity;
+}
+
DungeonInfo* Context::GetDungeon(size_t key) const {
return mDungeons->GetDungeon(static_cast(key));
}
diff --git a/soh/soh/Enhancements/randomizer/context.h b/soh/soh/Enhancements/randomizer/context.h
index 247bca68e..cef9e5292 100644
--- a/soh/soh/Enhancements/randomizer/context.h
+++ b/soh/soh/Enhancements/randomizer/context.h
@@ -6,6 +6,7 @@
#include "item_override.h"
#include "3drando/text.hpp"
#include "hint.h"
+#include "fishsanity.h"
#include
#include
@@ -66,6 +67,7 @@ class Context {
std::shared_ptr GetSettings();
std::shared_ptr GetEntranceShuffler();
std::shared_ptr GetDungeons();
+ std::shared_ptr GetFishsanity();
DungeonInfo* GetDungeon(size_t key) const;
std::shared_ptr GetLogic();
void ResetLogic();
@@ -111,6 +113,7 @@ class Context {
std::shared_ptr mDungeons;
std::shared_ptr mLogic;
std::shared_ptr mTrials;
+ std::shared_ptr mFishsanity;
bool mSeedGenerated = false;
bool mSpoilerLoaded = false;
bool mPlandoLoaded = false;
diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp
index a66d6b43d..51841ffcd 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -11,6 +11,7 @@
#include "objects/object_gi_bosskey/object_gi_bosskey.h"
#include "objects/object_gi_hearts/object_gi_hearts.h"
#include "objects/object_gi_fire/object_gi_fire.h"
+#include "objects/object_fish/object_fish.h"
#include "objects/object_toki_objects/object_toki_objects.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
#include "soh_assets.h"
@@ -389,5 +390,54 @@ extern "C" void Randomizer_DrawOcarinaButton(PlayState* play, GetItemEntry* getI
gSPGrayscale(POLY_XLU_DISP++, false);
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry) {
+ Vec3f pos;
+ OPEN_DISPS(play->state.gfxCtx);
+
+ // Draw rod
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Scale(0.2, 0.2, 0.2, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingPoleGiDL);
+
+ // Draw lure
+ Matrix_Push();
+ Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
+ pos = { 0.0f, -25.5f, -4.0f };
+ Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_APPLY);
+ Matrix_RotateZ(-M_PI_2, MTXMODE_APPLY);
+ Matrix_RotateY(-M_PI_2 - 0.2f, MTXMODE_APPLY);
+ Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY);
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureFloatDL);
+
+ // Draw hooks
+ Matrix_RotateY(0.2f, MTXMODE_APPLY);
+ Matrix_Translate(0.0f, 0.0f, -300.0f, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+ Matrix_RotateZ(M_PI_2, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+
+ Matrix_Translate(0.0f, -2200.0f, 700.0f, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+ Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+
+ Matrix_Pop();
+
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 b2f88e3da..59f173b17 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -18,6 +18,7 @@ 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);
+void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry);
#ifdef __cplusplus
};
#endif
diff --git a/soh/soh/Enhancements/randomizer/fishsanity.cpp b/soh/soh/Enhancements/randomizer/fishsanity.cpp
new file mode 100644
index 000000000..48ca2d703
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/fishsanity.cpp
@@ -0,0 +1,412 @@
+#include "3drando/pool_functions.hpp"
+#include "../../OTRGlobals.h"
+#include "fishsanity.h"
+#include "variables.h"
+#include "functions.h"
+#include "macros.h"
+#include
+
+#define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity()
+
+/**
+ * @brief Parallel list of pond fish checks for both ages
+*/
+std::array, 17> Rando::StaticData::randomizerFishingPondFish = {
+ { /* Child Check Adult Check */
+ { RC_LH_CHILD_FISH_1, RC_LH_ADULT_FISH_1 },
+ { RC_LH_CHILD_FISH_2, RC_LH_ADULT_FISH_2 },
+ { RC_LH_CHILD_FISH_3, RC_LH_ADULT_FISH_3 },
+ { RC_LH_CHILD_FISH_4, RC_LH_ADULT_FISH_4 },
+ { RC_LH_CHILD_FISH_5, RC_LH_ADULT_FISH_5 },
+ { RC_LH_CHILD_FISH_6, RC_LH_ADULT_FISH_6 },
+ { RC_LH_CHILD_FISH_7, RC_LH_ADULT_FISH_7 },
+ { RC_LH_CHILD_FISH_8, RC_LH_ADULT_FISH_8 },
+ { RC_LH_CHILD_FISH_9, RC_LH_ADULT_FISH_9 },
+ { RC_LH_CHILD_FISH_10, RC_LH_ADULT_FISH_10 },
+ { RC_LH_CHILD_FISH_11, RC_LH_ADULT_FISH_11 },
+ { RC_LH_CHILD_FISH_12, RC_LH_ADULT_FISH_12 },
+ { RC_LH_CHILD_FISH_13, RC_LH_ADULT_FISH_13 },
+ { RC_LH_CHILD_FISH_14, RC_LH_ADULT_FISH_14 },
+ { RC_LH_CHILD_FISH_15, RC_LH_ADULT_FISH_15 },
+ { RC_LH_CHILD_LOACH_1, RC_LH_ADULT_LOACH },
+ { RC_LH_CHILD_LOACH_2, RC_UNKNOWN_CHECK } }
+};
+
+std::unordered_map Rando::StaticData::randomizerGrottoFishMap = {
+ { 0x2C, RC_KF_STORMS_GROTTO_FISH }, { 0x14, RC_LW_NEAR_SHORTCUTS_GROTTO_FISH },
+ { 0x22, RC_HF_SOUTHEAST_GROTTO_FISH }, { 0x03, RC_HF_OPEN_GROTTO_FISH },
+ { 0x00, RC_HF_NEAR_MARKET_GROTTO_FISH }, { 0x28, RC_KAK_OPEN_GROTTO_FISH },
+ { 0x57, RC_DMT_STORMS_GROTTO_FISH }, { 0x7A, RC_DMC_UPPER_GROTTO_FISH },
+ { 0x29, RC_ZR_OPEN_GROTTO_FISH }
+};
+
+namespace Rando {
+ const FishIdentity Fishsanity::defaultIdentity = { RAND_INF_MAX, RC_UNKNOWN_CHECK };
+ bool Fishsanity::fishsanityHelpersInit = false;
+ std::unordered_map Fishsanity::pondFishAgeMap;
+ std::vector Fishsanity::childPondFish;
+ std::vector Fishsanity::adultPondFish;
+
+ Fishsanity::Fishsanity() {
+ InitializeHelpers();
+ }
+
+ Fishsanity::~Fishsanity() {
+
+ }
+
+ bool Fishsanity::GetFishLocationIncluded(Rando::Location* loc,
+ FishsanityOptionsSource optionsSource) {
+ auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
+
+ if (loc->GetRCType() != RCTYPE_FISH || mode == RO_FISHSANITY_OFF)
+ return false;
+ RandomizerCheck rc = loc->GetRandomizerCheck();
+ // Are pond fish enabled, and is this a pond fish location?
+ if (mode != RO_FISHSANITY_OVERWORLD && numFish > 0 && loc->GetScene() == SCENE_FISHING_POND &&
+ loc->GetActorID() == ACTOR_FISHING) {
+ // Is this a child fish location? If so, is it within the defined number of pond fish checks?
+ if (rc >= RC_LH_CHILD_FISH_1 && rc <= RC_LH_CHILD_LOACH_2 && numFish > (loc->GetActorParams() - 100))
+ return true;
+ // Are adult fish available, and is this an adult fish location? If so, is it within the defined number of pond
+ // fish checks?
+ if (ageSplit && rc >= RC_LH_ADULT_FISH_1 && rc <= RC_LH_ADULT_LOACH && numFish > (loc->GetActorParams() - 100))
+ return true;
+ }
+ // Are overworld fish enabled, and is this an overworld fish location?
+ if (mode != RO_FISHSANITY_POND && (loc->GetScene() == SCENE_GROTTOS || loc->GetScene() == SCENE_ZORAS_DOMAIN)
+ && loc->GetActorID() == ACTOR_EN_FISH && (loc->GetActorParams() == 1 || loc->GetActorParams() < 0)) {
+ return true;
+ }
+ // Must not be an included fish location!
+ return false;
+ }
+
+ std::pair, std::vector>
+ Fishsanity::GetFishingPondLocations(FishsanityOptionsSource optionsSource) {
+ auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
+ std::vector activeFish;
+ std::vector remainingFish;
+
+ // Fishsanity_InitializeHelpers();
+ remainingFish.insert(remainingFish.end(), Rando::StaticData::pondFishLocations.begin(),
+ Rando::StaticData::pondFishLocations.end());
+
+ // No pond fish shuffled
+ if (numFish == 0) {
+ return std::make_pair(activeFish, remainingFish);
+ }
+ // Every pond fish is shuffled, so we can save some time
+ if (numFish > 16) {
+ // Child and adult pond fish are both shuffled, set activeFish to remainingFish and return an empty vector for
+ // inactive fish.
+ if (ageSplit) {
+ return std::make_pair(remainingFish, activeFish);
+ }
+ // Activate all child fish only
+ activeFish = FilterAndEraseFromPool(
+ remainingFish, [](const RandomizerCheck loc) { return pondFishAgeMap[loc] == LINK_AGE_CHILD; });
+ return std::make_pair(activeFish, remainingFish);
+ }
+ // Only some pond fish are shuffled, so we have to only activate the requested number.
+ activeFish.insert(activeFish.end(), childPondFish.begin(), childPondFish.begin() + numFish);
+ // If pond is split, also add the requested number of adult fish.
+ if (ageSplit) {
+ activeFish.insert(activeFish.end(), adultPondFish.begin(),
+ adultPondFish.begin() + std::min(numFish, 16));
+ }
+ // NOTE: This only works because we can assume activeFish is already sorted; changes that break this assumption will
+ // also break this
+ FilterAndEraseFromPool(remainingFish,
+ [&](uint32_t loc) { return std::binary_search(activeFish.begin(), activeFish.end(), loc); });
+
+ return std::make_pair(activeFish, remainingFish);
+ }
+
+ std::pair, std::vector>
+ Fishsanity::GetFishsanityLocations(FishsanityOptionsSource optionsSource) {
+ auto [mode, numFish, ageSplit] = GetOptions(optionsSource);
+ std::vector activeFish;
+ std::vector remainingFish;
+
+ // Add pond fish
+ if (mode == RO_FISHSANITY_POND || mode == RO_FISHSANITY_BOTH) {
+ auto pondLocations = GetFishingPondLocations(optionsSource);
+ activeFish.insert(activeFish.end(), pondLocations.first.begin(), pondLocations.first.end());
+ remainingFish.insert(remainingFish.end(), pondLocations.second.begin(), pondLocations.second.end());
+ }
+
+ // Add overworld fish
+ if (mode == RO_FISHSANITY_OVERWORLD || mode == RO_FISHSANITY_BOTH) {
+ activeFish.insert(activeFish.end(), Rando::StaticData::overworldFishLocations.begin(),
+ Rando::StaticData::overworldFishLocations.end());
+ }
+
+ return std::make_pair(activeFish, remainingFish);
+ }
+
+ FishIdentity Fishsanity::IdentifyPondFish(u8 fishParams) {
+ auto [mode, pondCount, ageSplit] = GetOptions();
+ FishIdentity identity = defaultIdentity;
+
+ if (!GetPondFishShuffled()) {
+ return identity;
+ }
+
+ if (pondCount > 16) {
+ identity = GetPondFish(fishParams, IsAdultPond());
+ } else {
+ identity = LINK_IS_ADULT ? mCurrPondFish.second : mCurrPondFish.first;
+ }
+
+ return identity;
+ }
+
+ FishsanityPondOptions Fishsanity::GetOptions(FishsanityOptionsSource optionsSource) {
+ FishsanityPondOptions options{};
+ switch (optionsSource) {
+ // Used in check tracker
+ case FSO_SOURCE_CVARS:
+ options.mode = CVarGetInteger("gRandomizeFishsanity", RO_FISHSANITY_OFF);
+ options.numFish = CVarGetInteger("gRandomizeFishsanityPondCount", 0);
+ options.ageSplit = CVarGetInteger("gRandomizeFishsanityAgeSplit", 0) == 1;
+ break;
+ case FSO_SOURCE_RANDO:
+ default:
+ options.mode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
+ options.numFish = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT);
+ options.ageSplit = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT);
+ break;
+ }
+ return options;
+ }
+
+ void Fishsanity::UpdateCurrentPondFish() {
+ auto [mode, pondCount, ageSplit] = GetOptions();
+ mCurrPondFish = std::pair();
+ mCurrPondFish.first = defaultIdentity;
+ mCurrPondFish.second = defaultIdentity;
+
+ // Initialize mCurrPondFish if we're shuffling pond fish, but if all fish are shuffled, we don't need to use this.
+ if ((mode == RO_FISHSANITY_BOTH || mode == RO_FISHSANITY_POND) && pondCount < 17) {
+ // find the first inf that isn't set yet for each age
+ // but don't go past the max number
+ std::pair tableEntry;
+ for (s16 i = 0, params = 100; i < pondCount; i++, params++) {
+ tableEntry = Rando::StaticData::randomizerFishingPondFish[i];
+ if (!Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(tableEntry.first)) || i == pondCount - 1) {
+ // Found first child check
+ if (!IsFish(&mCurrPondFish.first)) {
+ mCurrPondFish.first = GetPondFish(params, false);
+ }
+
+ if (!ageSplit && !IsFish(&mCurrPondFish.second)) {
+ mCurrPondFish.second = GetPondFish(params, false);
+ // both ages are resolved! we can quit here
+ break;
+ }
+ }
+
+ if (ageSplit && !IsFish(&mCurrPondFish.second) && tableEntry.second != RC_UNKNOWN_CHECK &&
+ (!Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(tableEntry.second)) || i == pondCount - 1)) {
+ mCurrPondFish.second = mCurrPondFish.second = GetPondFish(params, true);
+ }
+ }
+ }
+ }
+
+ void Fishsanity::InitializeFromSave() {
+ UpdateCurrentPondFish();
+ }
+
+ bool Fishsanity::GetPondFishShuffled() {
+ u8 fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
+ return OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT) > 0 &&
+ (fsMode == RO_FISHSANITY_POND || fsMode == RO_FISHSANITY_BOTH);
+ }
+
+ bool Fishsanity::GetOverworldFishShuffled() {
+ u8 fsMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
+ return fsMode == RO_FISHSANITY_OVERWORLD || fsMode == RO_FISHSANITY_BOTH;
+ }
+
+ bool Fishsanity::IsAdultPond() {
+ return LINK_IS_ADULT && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT);
+ }
+
+ bool Fishsanity::GetPondCleared() {
+ auto [mode, pondCount, ageSplit] = GetOptions();
+ // no fish shuffled, so pond is always cleared :thumbsup:
+ if (pondCount == 0)
+ return true;
+
+ bool adultPond = LINK_IS_ADULT && ageSplit;
+ // if we've collected the final shuffled fish, pond is complete
+ if (pondCount <= 16) {
+ auto tableEntry = Rando::StaticData::randomizerFishingPondFish[pondCount - 1];
+ return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(adultPond ? tableEntry.second : tableEntry.first));
+ }
+
+ // the last two checks actually don't matter because logically they will never be true, but maybe one day they will
+ // if every fish is shuffled, check if we've collected every fish
+ for (auto tableEntry : Rando::StaticData::randomizerFishingPondFish) {
+ RandomizerCheck rc = adultPond ? tableEntry.second : tableEntry.first;
+ // if we haven't collected this fish, then we're not done yet! get back in there, soldier
+ if (rc != RC_UNKNOWN_CHECK && !Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc)))
+ return false;
+ }
+ return true;
+ }
+
+ bool Fishsanity::GetDomainCleared() {
+ for (RandomizerInf i = RAND_INF_ZD_FISH_1; i <= RAND_INF_ZD_FISH_5; i = (RandomizerInf)(i + 1)) {
+ if (!Flags_GetRandomizerInf(i))
+ return false;
+ }
+ return true;
+ }
+
+ void Fishsanity::InitializeHelpers() {
+ if (fishsanityHelpersInit)
+ return;
+
+ for (auto pair : Rando::StaticData::randomizerFishingPondFish) {
+ pondFishAgeMap[pair.first] = LINK_AGE_CHILD;
+ pondFishAgeMap[pair.second] = LINK_AGE_ADULT;
+ childPondFish.push_back(pair.first);
+ adultPondFish.push_back(pair.second);
+ }
+ }
+
+ FishIdentity Fishsanity::GetPondFish(s16 params, bool adultPond) {
+ auto pair = Rando::StaticData::randomizerFishingPondFish[params - 100];
+ RandomizerCheck rc = adultPond ? pair.second : pair.first;
+ return { OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc), rc };
+ }
+
+ FishIdentity Fishsanity::AdvancePond() {
+ auto [mode, pondCount, ageSplit] = GetOptions();
+
+ // No need to update state with full pond shuffle
+ if (pondCount > 16) {
+ return defaultIdentity;
+ }
+
+ UpdateCurrentPondFish();
+
+ return IsAdultPond() ? mCurrPondFish.second : mCurrPondFish.first;
+ }
+
+ FishsanityCheckType Fishsanity::GetCheckType(RandomizerCheck rc) {
+ // Is this a pond fish?
+ if (std::binary_search(Rando::StaticData::pondFishLocations.begin(), Rando::StaticData::pondFishLocations.end(), rc))
+ return FSC_POND;
+
+ // Is this an overworld fish?
+ if (std::binary_search(Rando::StaticData::overworldFishLocations.begin(), Rando::StaticData::overworldFishLocations.end(), rc)) {
+ if (rc < RC_ZD_FISH_1)
+ return FSC_GROTTO;
+ else
+ return FSC_ZD;
+ }
+
+ // Must not be a fishsanity check
+ return FSC_NONE;
+ }
+
+ bool Fishsanity::IsFish(FishIdentity* fish) {
+ if (fish->randomizerCheck == RC_UNKNOWN_CHECK || fish->randomizerInf == RAND_INF_MAX)
+ return false;
+
+ return GetCheckType(fish->randomizerCheck) != FSC_NONE;
+ }
+
+ void Fishsanity::SetPendingFish(FishIdentity* fish) {
+ mPendingFish = fish == NULL ? defaultIdentity : *fish;
+ }
+
+ FishIdentity Fishsanity::GetPendingFish() {
+ return mPendingFish;
+ }
+} // namespace Rando
+
+// C interface
+extern "C" {
+ bool Randomizer_GetPondFishShuffled() {
+ return FSi->GetPondFishShuffled();
+ }
+
+ bool Randomizer_GetOverworldFishShuffled() {
+ return FSi->GetOverworldFishShuffled();
+ }
+
+ bool Randomizer_IsAdultPond() {
+ return FSi->IsAdultPond();
+ }
+
+ void Randomizer_SetPendingFish(FishIdentity* fish) {
+ return FSi->SetPendingFish(fish);
+ }
+
+ void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play) {
+ Vec3f pos, ripplePos;
+ static Vec3f velocity = { 0.0f, 0.0f, 0.0f };
+ static Vec3f accel = { 0.0f, 0.0f, 0.0f };
+ Color_RGBA8 primColor;
+ Color_RGBA8 envColor;
+
+ // Color of the circle for the particles
+ static Color_RGBA8 mainColors[5][4] = {
+ { 240, 154, 137, 200 },
+ { 240, 190, 137, 200 },
+ { 240, 171, 137, 200 },
+ { 240, 141, 146, 200 },
+ { 240, 204, 137, 200 }
+ };
+
+ // Color of the faded flares stretching off the particles
+ static Color_RGBA8 flareColors[5][3] = {
+ { 128, 85, 82, 200 },
+ { 128, 101, 82, 200 },
+ { 128, 93, 82, 200 },
+ { 128, 82, 98, 200 },
+ { 128, 108, 82, 200 }
+ };
+
+ Color_RGBA8_Copy(&primColor, mainColors[ABS(actor->params) % 5]);
+ Color_RGBA8_Copy(&envColor, flareColors[ABS(actor->params) % 5]);
+
+ // Spawn sparkles
+ pos.x = Rand_CenteredFloat(23.0f) + actor->world.pos.x;
+ pos.y = (Rand_Centered() * 12.0f) + actor->world.pos.y;
+ pos.z = Rand_CenteredFloat(23.0f) + actor->world.pos.z;
+ velocity.y = 0.05f;
+ accel.y = 0.025f;
+ Math_Vec3f_Copy(&ripplePos, &pos);
+ ripplePos.y += actor->yDistToWater;
+
+ if (Rand_ZeroOne() < 0.3f) {
+ EffectSsKiraKira_SpawnDispersed(play, &pos, &velocity, &accel, &primColor, &envColor, 1800, 10);
+ }
+
+ if (actor->bgCheckFlags & 0x20 && Rand_ZeroOne() < 0.15f) {
+ EffectSsGRipple_Spawn(play, &ripplePos, 100, 200, 2);
+ }
+ }
+
+ void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGBA16* color, int16_t frameOffset) {
+ OPEN_DISPS(play->state.gfxCtx);
+ gDPSetGrayscaleColor(
+ POLY_OPA_DISP++, color->r, color->g, color->b,
+ // Make color pulse, offset a bit by the actor params
+ ABS(255.0f * Math_CosS((play->gameplayFrames + frameOffset) * 1000)));
+ gSPGrayscale(POLY_OPA_DISP++, true);
+ CLOSE_DISPS(play->state.gfxCtx);
+ }
+
+ void Fishsanity_CloseGreyscaleColor(PlayState* play) {
+ OPEN_DISPS(play->state.gfxCtx);
+ gSPGrayscale(POLY_OPA_DISP++, false);
+ CLOSE_DISPS(play->state.gfxCtx);
+ }
+}
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/fishsanity.h b/soh/soh/Enhancements/randomizer/fishsanity.h
new file mode 100644
index 000000000..fb1281162
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/fishsanity.h
@@ -0,0 +1,210 @@
+#ifndef FISHSANITY_H
+#define FISHSANITY_H
+#pragma once
+
+#include
+#include "randomizerTypes.h"
+
+typedef struct FishsanityPondOptions {
+ u8 mode;
+ u8 numFish;
+ bool ageSplit;
+} FishsanityPondOptions;
+
+typedef enum FishsanityOptionsSource {
+ FSO_SOURCE_RANDO,
+ FSO_SOURCE_CVARS
+};
+
+typedef enum FishsanityCheckType {
+ FSC_NONE,
+ FSC_POND,
+ FSC_GROTTO,
+ FSC_ZD,
+};
+
+#ifdef __cplusplus
+namespace Rando {
+
+/**
+ * @brief Class to provide an interface for and direct Fishsanity features
+*/
+class Fishsanity {
+ public:
+ Fishsanity();
+ ~Fishsanity();
+
+ static const FishIdentity defaultIdentity;
+
+ /**
+ * @brief Gets the type of a fishsanity check
+ * @param rc The RandomizerCheck to categorize
+ * @return The check's fishsanity type, or FSC_NONE
+ */
+ static FishsanityCheckType GetCheckType(RandomizerCheck rc);
+
+ /**
+ * @brief Returns true if the given FishIdentity represents an actual fish
+ * @param fish The fish to check
+ */
+ static bool IsFish(FishIdentity* fish);
+
+ /**
+ * @brief Returns true if the given fish location is active
+ *
+ * @param loc The Location to check
+ * @param optionsSource Optionally declare from which source to pull settings
+ */
+ bool GetFishLocationIncluded(Rando::Location* loc, FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
+
+ /**
+ * @brief Get the active and inactive locations in the fishing pond.
+ *
+ * @param optionsSource Optionally declare from which source to pull settings
+ * @return A pair of vectors, where the fist is all active pond fish checks, and the second is all inactive pond fish checks.
+ */
+ std::pair, std::vector> GetFishingPondLocations(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
+
+ /**
+ * @brief Get all active fishsanity locations, and all inactive fishing pond locations.
+ *
+ * @param optionsSource Optionally declare from which source to pull settings
+ * @return A pair of vectors, where the first is all active fishsanity checks, and the second is all inactive fishsanity checks.
+ */
+ std::pair, std::vector> GetFishsanityLocations(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
+
+ /**
+ * @brief Returns the identity for a caught pond fish given its params.
+ * Not for use externally from rando, use Randomizer::IdentifyFish or Randomizer_IdentifyFish for that
+ *
+ * @param fishParams Actor parameters for the fish to identify
+ */
+ FishIdentity IdentifyPondFish(u8 fishParams);
+
+ /**
+ * @brief Get fishsanity fishing pond options from the requested source
+ */
+ FishsanityPondOptions GetOptions(FishsanityOptionsSource optionsSource = FSO_SOURCE_RANDO);
+
+ /**
+ * @brief Updates current pond fish according to save data
+ */
+ void UpdateCurrentPondFish();
+
+ /**
+ * @brief Initializes internal state from save
+ */
+ void InitializeFromSave();
+
+ /**
+ * @brief Returns true if the fishing pond is shuffled
+ */
+ bool GetPondFishShuffled();
+
+ /**
+ * @brief Returns true if overworld fish are shuffled
+ */
+ bool GetOverworldFishShuffled();
+
+ /**
+ * @brief Returns true if the fishing pond is currently adult (i.e., age split is enabled and Link is adult)
+ */
+ bool IsAdultPond();
+
+ /**
+ * @brief Returns true if all available pond fish checks have been collected for the current age
+ */
+ bool GetPondCleared();
+
+ /**
+ * @brief Returns true if all available Zora's Domain fish checks have been collected
+ */
+ bool GetDomainCleared();
+
+ /**
+ * @brief Advances current fishing pond check; no effect if every fish is shuffled
+ * @return The new FishIdentity for the current pond, or default identity if every fish is shuffled
+ */
+ FishIdentity AdvancePond();
+
+ /**
+ * @brief Set the currently held fish
+ * @param fish Pointer to FishIdentity to copy
+ */
+ void SetPendingFish(FishIdentity* fish);
+
+ /**
+ * @brief Get the currently held fish
+ */
+ FishIdentity GetPendingFish();
+
+ private:
+ /**
+ * @brief Initialize helper statics if they have not been initialized yet
+ */
+ void InitializeHelpers();
+
+ /**
+ * @brief Resolves a pond fish's FishIdentity directly from params & pond age
+ *
+ * @param params Params for Fishing actor
+ * @param adultPond Whether to resolve this fish as an adult check
+ * @return The FishIdentity for the described fish
+ */
+ static FishIdentity GetPondFish(s16 params, bool adultPond);
+
+ /**
+ * @brief Current pond fish when all pond fish are not randomized
+ */
+ std::pair mCurrPondFish;
+
+ /**
+ * @brief Identity of the last-caught fish in the fishing pond minigame awaiting reward
+ */
+ FishIdentity mPendingFish;
+
+ /**
+ * @brief True if fishsanity helpers have been initialized
+ */
+ static bool fishsanityHelpersInit;
+
+ /////////////////////////////////////////////////////////
+ //// Helper data structures derived from static data ////
+ /////////////////////////////////////////////////////////
+
+ /**
+ * @brief Mapping from pond fish check to the age where that check can be collected
+ */
+ static std::unordered_map pondFishAgeMap;
+
+ /**
+ * @brief List of child pond fish checks
+ */
+ static std::vector childPondFish;
+
+ /**
+ * @brief List of adult pond fish checks
+ */
+ static std::vector adultPondFish;
+};
+}
+
+extern "C" {
+#endif
+/// Returns true if pond fish should be shuffled based on fishsanity settings.
+bool Randomizer_GetPondFishShuffled();
+/// Returns true if overworld fish should be shuffled based on fishsanity settings.
+bool Randomizer_GetOverworldFishShuffled();
+/// Returns true if the adult fishing pond should be used for fishsanity.
+bool Randomizer_IsAdultPond();
+/// Sets the pending fish
+void Randomizer_SetPendingFish(FishIdentity* fish);
+/// Custom shadow draw function to add effect to uncollected fish
+void Fishsanity_DrawEffShadow(Actor* actor, Lights* lights, PlayState* play);
+void Fishsanity_OpenGreyscaleColor(PlayState* play, Color_RGBA16* color, int16_t frameOffset);
+void Fishsanity_CloseGreyscaleColor(PlayState* play);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FISHSANITY_H
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 88732e6a2..8374c98d6 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -189,6 +189,7 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herz-Container" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2,true, &logic->HeartContainer, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, &logic->noVariable, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, &logic->noVariable, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
+ itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Pez" }, ITEMTYPE_ITEM, GI_FISH, false, &logic->noVariable, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
// Refills
itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, &logic->noVariable, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, &logic->noVariable, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
@@ -260,6 +261,8 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
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_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Caña de Pescar" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, &logic->FishingPole, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
+ itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI);
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);
diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h
index cd6e88f32..993e8c184 100644
--- a/soh/soh/Enhancements/randomizer/location.h
+++ b/soh/soh/Enhancements/randomizer/location.h
@@ -55,6 +55,10 @@ class SpoilerCollectionCheck {
return SpoilerCollectionCheck(SPOILER_CHK_COW, scene, flag);
}
+ static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) {
+ return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag);
+ }
+
static auto Fishing(const uint8_t bit) {
return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit);
}
diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp
index 2e3122cb8..56861e484 100644
--- a/soh/soh/Enhancements/randomizer/location_list.cpp
+++ b/soh/soh/Enhancements/randomizer/location_list.cpp
@@ -516,7 +516,25 @@ std::vector Rando::StaticData::otherHintLocations = {
RC_GREG_HINT,
RC_SARIA_SONG_HINT,
RC_ALTAR_HINT_CHILD,
- RC_ALTAR_HINT_ADULT
+ RC_ALTAR_HINT_ADULT,
+ RC_FISHING_POLE_HINT
+};
+
+std::vector Rando::StaticData::pondFishLocations = {
+ RC_LH_CHILD_FISH_1, RC_LH_CHILD_FISH_2, RC_LH_CHILD_FISH_3, RC_LH_CHILD_FISH_4, RC_LH_CHILD_FISH_5,
+ RC_LH_CHILD_FISH_6, RC_LH_CHILD_FISH_7, RC_LH_CHILD_FISH_8, RC_LH_CHILD_FISH_9, RC_LH_CHILD_FISH_10,
+ RC_LH_CHILD_FISH_11, RC_LH_CHILD_FISH_12, RC_LH_CHILD_FISH_13, RC_LH_CHILD_FISH_14, RC_LH_CHILD_FISH_15,
+ RC_LH_CHILD_LOACH_1, RC_LH_CHILD_LOACH_2, RC_LH_ADULT_FISH_1, RC_LH_ADULT_FISH_2, RC_LH_ADULT_FISH_3,
+ RC_LH_ADULT_FISH_4, RC_LH_ADULT_FISH_5, RC_LH_ADULT_FISH_6, RC_LH_ADULT_FISH_7, RC_LH_ADULT_FISH_8,
+ RC_LH_ADULT_FISH_9, RC_LH_ADULT_FISH_10, RC_LH_ADULT_FISH_11, RC_LH_ADULT_FISH_12, RC_LH_ADULT_FISH_13,
+ RC_LH_ADULT_FISH_14, RC_LH_ADULT_FISH_15, RC_LH_ADULT_LOACH
+};
+
+std::vector Rando::StaticData::overworldFishLocations = {
+ RC_DMC_UPPER_GROTTO_FISH, RC_DMT_STORMS_GROTTO_FISH, RC_HF_SOUTHEAST_GROTTO_FISH,
+ RC_HF_NEAR_MARKET_GROTTO_FISH, RC_HF_OPEN_GROTTO_FISH, RC_KAK_OPEN_GROTTO_FISH,
+ RC_KF_STORMS_GROTTO_FISH, RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RC_ZR_OPEN_GROTTO_FISH,
+ RC_ZD_FISH_1, RC_ZD_FISH_2, RC_ZD_FISH_3, RC_ZD_FISH_4, RC_ZD_FISH_5
};
typedef enum {
@@ -1372,6 +1390,62 @@ void Rando::StaticData::InitLocationTable() {
locationTable[RC_GC_SHOP_ITEM_7] = Location::Base(RC_GC_SHOP_ITEM_7, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x06, 0x36, "Shop Item 7", "GC Shop Item 7", RHT_GC_SHOP_ITEM_7, RG_BUY_RED_POTION_40, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 6), SpoilerCollectionCheckGroup::GROUP_GORON_CITY);
locationTable[RC_GC_SHOP_ITEM_8] = Location::Base(RC_GC_SHOP_ITEM_8, RCQUEST_BOTH, RCTYPE_SHOP, RCAREA_GORON_CITY, ACTOR_EN_GIRLA, SCENE_GORON_SHOP, 0x07, 0x37, "Shop Item 8", "GC Shop Item 8", RHT_GC_SHOP_ITEM_8, RG_BUY_HEART, { Category::cShop }, SpoilerCollectionCheck::ShopItem(0x2E, 7), SpoilerCollectionCheckGroup::GROUP_GORON_CITY);
+ /* +--------------+
+ | FISHSANITY |
+ +--------------+ */
+
+ // Randomizer Check Randomizer Check Quest Type Area Actor ID Scene ID Params Flags Short Name Spoiler Name Hint Text Key Vanilla Item Categories Spoiler Collection Check Collection Check Group
+ locationTable[RC_LH_CHILD_FISH_1] = Location::Base(RC_LH_CHILD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Child Pond Fish 1", "LH Child Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_2] = Location::Base(RC_LH_CHILD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Child Pond Fish 2", "LH Child Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_3] = Location::Base(RC_LH_CHILD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Child Pond Fish 3", "LH Child Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_4] = Location::Base(RC_LH_CHILD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Child Pond Fish 4", "LH Child Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_5] = Location::Base(RC_LH_CHILD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Child Pond Fish 5", "LH Child Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_6] = Location::Base(RC_LH_CHILD_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Child Pond Fish 6", "LH Child Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_7] = Location::Base(RC_LH_CHILD_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Child Pond Fish 7", "LH Child Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_8] = Location::Base(RC_LH_CHILD_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Child Pond Fish 8", "LH Child Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_9] = Location::Base(RC_LH_CHILD_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Child Pond Fish 9", "LH Child Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_10] = Location::Base(RC_LH_CHILD_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Child Pond Fish 10", "LH Child Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_11] = Location::Base(RC_LH_CHILD_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Child Pond Fish 11", "LH Child Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_12] = Location::Base(RC_LH_CHILD_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Child Pond Fish 12", "LH Child Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_13] = Location::Base(RC_LH_CHILD_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Child Pond Fish 13", "LH Child Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_14] = Location::Base(RC_LH_CHILD_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Child Pond Fish 14", "LH Child Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_FISH_15] = Location::Base(RC_LH_CHILD_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Child Pond Fish 15", "LH Child Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_LOACH_1] = Location::Base(RC_LH_CHILD_LOACH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Child Pond Loach 1", "LH Child Pond Loach 1", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_CHILD_LOACH_2] = Location::Base(RC_LH_CHILD_LOACH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 116, 0x00, "Child Pond Loach 2", "LH Child Pond Loach 2", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_1] = Location::Base(RC_LH_ADULT_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 100, 0x00, "Adult Pond Fish 1", "LH Adult Pond Fish 1", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_2] = Location::Base(RC_LH_ADULT_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 101, 0x00, "Adult Pond Fish 2", "LH Adult Pond Fish 2", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_3] = Location::Base(RC_LH_ADULT_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 102, 0x00, "Adult Pond Fish 3", "LH Adult Pond Fish 3", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_4] = Location::Base(RC_LH_ADULT_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 103, 0x00, "Adult Pond Fish 4", "LH Adult Pond Fish 4", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_5] = Location::Base(RC_LH_ADULT_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 104, 0x00, "Adult Pond Fish 5", "LH Adult Pond Fish 5", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_6] = Location::Base(RC_LH_ADULT_FISH_6, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 105, 0x00, "Adult Pond Fish 6", "LH Adult Pond Fish 6", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_7] = Location::Base(RC_LH_ADULT_FISH_7, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 106, 0x00, "Adult Pond Fish 7", "LH Adult Pond Fish 7", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_8] = Location::Base(RC_LH_ADULT_FISH_8, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 107, 0x00, "Adult Pond Fish 8", "LH Adult Pond Fish 8", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_9] = Location::Base(RC_LH_ADULT_FISH_9, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 108, 0x00, "Adult Pond Fish 9", "LH Adult Pond Fish 9", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_10] = Location::Base(RC_LH_ADULT_FISH_10, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 109, 0x00, "Adult Pond Fish 10", "LH Adult Pond Fish 10", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_11] = Location::Base(RC_LH_ADULT_FISH_11, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 110, 0x00, "Adult Pond Fish 11", "LH Adult Pond Fish 11", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_12] = Location::Base(RC_LH_ADULT_FISH_12, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 111, 0x00, "Adult Pond Fish 12", "LH Adult Pond Fish 12", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_13] = Location::Base(RC_LH_ADULT_FISH_13, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 112, 0x00, "Adult Pond Fish 13", "LH Adult Pond Fish 13", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_14] = Location::Base(RC_LH_ADULT_FISH_14, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 113, 0x00, "Adult Pond Fish 14", "LH Adult Pond Fish 14", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_FISH_15] = Location::Base(RC_LH_ADULT_FISH_15, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 114, 0x00, "Adult Pond Fish 15", "LH Adult Pond Fish 15", RHT_LH_POND_FISH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ locationTable[RC_LH_ADULT_LOACH] = Location::Base(RC_LH_ADULT_LOACH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, 115, 0x00, "Adult Pond Loach", "LH Adult Pond Loach", RHT_LH_HYRULE_LOACH, RG_NONE, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
+ // Grotto fish
+ locationTable[RC_KF_STORMS_GROTTO_FISH] = Location::Base(RC_KF_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KOKIRI_FOREST, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "KF Storms Grotto Fish", RHT_KF_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x2C, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KOKIRI_FOREST);
+ locationTable[RC_LW_NEAR_SHORTCUTS_GROTTO_FISH] = Location::Base(RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_LOST_WOODS, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Shortcuts Grotto Fish", "LW Near Shortcuts Grotto Fish", RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x14, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
+ locationTable[RC_HF_SOUTHEAST_GROTTO_FISH] = Location::Base(RC_HF_SOUTHEAST_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Southeast Grotto Fish", "HF Southeast Grotto Fish", RHT_HF_SOUTHEAST_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x22, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD);
+ locationTable[RC_HF_OPEN_GROTTO_FISH] = Location::Base(RC_HF_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "HF Open Grotto Fish", RHT_HF_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x03, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD);
+ locationTable[RC_HF_NEAR_MARKET_GROTTO_FISH] = Location::Base(RC_HF_NEAR_MARKET_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_HYRULE_FIELD, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Near Market Grotto Fish", "HF Near Market Grotto Fish", RHT_HF_NEAR_MARKET_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x00, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_HYRULE_FIELD);
+ locationTable[RC_KAK_OPEN_GROTTO_FISH] = Location::Base(RC_KAK_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_KAKARIKO_VILLAGE, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "Kak Open Grotto Fish", RHT_KAK_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x28, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
+ locationTable[RC_DMT_STORMS_GROTTO_FISH] = Location::Base(RC_DMT_STORMS_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_TRAIL, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Storms Grotto Fish", "DMT Storms Grotto Fish", RHT_DMT_STORMS_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x57, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN);
+ locationTable[RC_DMC_UPPER_GROTTO_FISH] = Location::Base(RC_DMC_UPPER_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_DEATH_MOUNTAIN_CRATER,ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Upper Grotto Fish", "DMC Upper Grotto Fish", RHT_DMC_UPPER_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x7A, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN);
+ locationTable[RC_ZR_OPEN_GROTTO_FISH] = Location::Base(RC_ZR_OPEN_GROTTO_FISH, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_RIVER, ACTOR_EN_FISH, SCENE_GROTTOS, 1, 0x00, "Open Grotto Fish", "ZR Open Grotto Fish", RHT_ZR_OPEN_GROTTO_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0x29, SCENE_GROTTOS), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER);
+ // Zora's Domain fish
+ locationTable[RC_ZD_FISH_1] = Location::Base(RC_ZD_FISH_1, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 0, 0x00, "Fish 1", "ZD Fish 1", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
+ locationTable[RC_ZD_FISH_2] = Location::Base(RC_ZD_FISH_2, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 1, 0x00, "Fish 2", "ZD Fish 2", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
+ locationTable[RC_ZD_FISH_3] = Location::Base(RC_ZD_FISH_3, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 2, 0x00, "Fish 3", "ZD Fish 3", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
+ locationTable[RC_ZD_FISH_4] = Location::Base(RC_ZD_FISH_4, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 3, 0x00, "Fish 4", "ZD Fish 4", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
+ locationTable[RC_ZD_FISH_5] = Location::Base(RC_ZD_FISH_5, RCQUEST_BOTH, RCTYPE_FISH, RCAREA_ZORAS_DOMAIN, ACTOR_EN_FISH, SCENE_ZORAS_DOMAIN, -1 ^ 4, 0x00, "Fish 5", "ZD Fish 5", RHT_ZD_FISH, RG_FISH, { Category::cFish }, SpoilerCollectionCheck::Fish(0xFF, SCENE_ZORAS_DOMAIN), SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
+
+
// Gossip Stones
// RandomizerCheck Randomizer Check Quest Area Scene Params Flag Short Name Spoiler name Categories
locationTable[RC_DMC_GOSSIP_STONE] = Location::HintStone(RC_DMC_GOSSIP_STONE, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, 14341, 0x05, "Gossip Stone", "DMC Gossip Stone", {});
@@ -1424,6 +1498,7 @@ void Rando::StaticData::InitLocationTable() {
locationTable[RC_SARIA_SONG_HINT] = Location::OtherHint(RC_SARIA_SONG_HINT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_KOKIRI_FOREST, ACTOR_ID_MAX, SCENE_ID_MAX, "Sarias Song Hint", "Magic Hint Via Saria's Song");
locationTable[RC_ALTAR_HINT_CHILD] = Location::OtherHint(RC_ALTAR_HINT_CHILD, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Child Altar Hint", "ToT Child Altar Text");
locationTable[RC_ALTAR_HINT_ADULT] = Location::OtherHint(RC_ALTAR_HINT_ADULT, RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, "Adult Altar Hint", "ToT Adult Altar Text");
+ locationTable[RC_FISHING_POLE_HINT] = Location::OtherHint(RC_FISHING_POLE_HINT,RCQUEST_BOTH, RCTYPE_GOSSIP_STONE, RCAREA_LAKE_HYLIA, ACTOR_FISHING, SCENE_FISHING_POND, "Fishing Pole Hint","Fishing Pole Hint");
locationTable[RC_TRIFORCE_COMPLETED] = Location::Reward(RC_TRIFORCE_COMPLETED, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, 0x00, "Completed Triforce", "Completed Triforce", RHT_NONE, RG_NONE, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP);
// clang-format on
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index da3969511..90e956b0b 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -57,6 +57,7 @@ namespace Rando {
(itemName == RG_OCARINA_C_RIGHT_BUTTON && OcarinaCRightButton) ||
(itemName == RG_OCARINA_C_DOWN_BUTTON && OcarinaCDownButton) ||
(itemName == RG_OCARINA_C_UP_BUTTON && OcarinaCUpButton) ||
+ (itemName == RG_FISHING_POLE && FishingPole) ||
(itemName == RG_ZELDAS_LULLABY && ZeldasLullaby) ||
(itemName == RG_EPONAS_SONG && EponasSong) ||
(itemName == RG_SARIAS_SONG && SariasSong) ||
@@ -150,6 +151,11 @@ namespace Rando {
case RG_PRELUDE_OF_LIGHT:
return Ocarina && OcarinaCLeftButton && OcarinaCRightButton && OcarinaCUpButton;
+ // Misc. Items
+ // TODO: Once child wallet shuffle is added, this will need to be updated to account for the fishing pond entry fee.
+ case RG_FISHING_POLE:
+ return true; // as long as you have enough rubies
+
// Magic items
default:
return MagicMeter && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(RG_FAIRY_BOW)));
@@ -325,6 +331,9 @@ namespace Rando {
CanOpenStormGrotto = CanUse(RG_SONG_OF_STORMS) && (ShardOfAgony || ctx->GetTrickOption(RT_GROTTOS_WITHOUT_AGONY));
HookshotOrBoomerang = CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG);
CanGetNightTimeGS = (CanUse(RG_SUNS_SONG) || !ctx->GetOption(RSK_SKULLS_SUNS_SONG));
+ CanFish = CanUse(RG_FISHING_POLE) || !ctx->GetOption(RSK_SHUFFLE_FISHING_POLE);
+ CanGetChildFish = CanFish && (IsChild || (IsAdult && !ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT)));
+ CanGetAdultFish = CanFish && IsAdult && ctx->GetOption(RSK_FISHSANITY_AGE_SPLIT);
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");
@@ -743,6 +752,10 @@ namespace Rando {
CanOpenStormGrotto = false;
BigPoeKill = false;
HookshotOrBoomerang = false;
+ CanGetChildFish = false;
+ CanGetAdultFish = false;
+ FishingPole = false;
+ CanFish = false;
BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Value() + 1;
Hearts = 0;
diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h
index 38cdda325..dfad1077e 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -295,6 +295,10 @@ class Logic {
bool BigPoeKill = false;
bool HookshotOrBoomerang = false;
bool CanGetNightTimeGS = false;
+ bool FishingPole = false;
+ bool CanGetChildFish = false;
+ bool CanGetAdultFish = false;
+ bool CanFish = false;
uint8_t OcarinaButtons = 0;
uint8_t BaseHearts = 0;
diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
index f618b3212..0fd5c2572 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -233,6 +233,9 @@ void Settings::CreateOptionDescriptions() {
"\n"
"The Gerudo Card is required to enter the Gerudo Training Grounds, opening "
"the gate to Haunted Wasteland and the Horseback Archery minigame.";
+ mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n"
+ "\n"
+ "The fishing pole is required to play the fishing pond minigame.";
mOptionDescriptions[RSK_SHOPSANITY] = "Off - All shop items will be the same as vanilla.\n"
"\n"
"0 Items - Vanilla shop items will be shuffled among different shops.\n"
@@ -250,6 +253,17 @@ void Settings::CreateOptionDescriptions() {
mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] =
"Affordable prices per tier: starter = 10, adult = 105, giant = 205, tycoon = 505\n\n"
"Use this to enable wallet tier locking, but make shop items not as expensive as they could be.";
+ mOptionDescriptions[RSK_FISHSANITY] = "Off - Fish will not be shuffled. No changes will be made to fishing behavior.\n\n"
+ "Shuffle Fishing Pond - The fishing pond's fish will be shuffled. Catching a fish in the fishing pond will grant a reward.\n\n"
+ "Shuffle Overworld Fish - Fish in generic grottos and Zora's Domain will be shuffled. Catching a fish in a bottle will give a reward.\n\n"
+ "Shuffle Both - Both overworld fish and fish in the fishing pond will be shuffled.";
+ mOptionDescriptions[RSK_FISHSANITY_POND_COUNT] = "The number of fish to randomize in the fishing pool.\n\n"
+ "If set to maximum, each fish will have a unique check, including a Hyrule Loach which appears only as child, and "
+ "uncaught fish will be given a visual indicator to distinguish from already-caught fish.\n\n"
+ "Otherwise, any fish caught in the pond will give a reward, until all rewards have been given.";
+ mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT] = "Enabling this will split the fishing pond fish by age, making fishing pond fish grant different rewards as child and adult.\n\n"
+ "If disabled, then the child pond will be shuffled and shared between both ages.\n\n"
+ "Note that, as child, there is a second loach available in the pond!";
mOptionDescriptions[RSK_SHUFFLE_SCRUBS] =
"Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game "
"(PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n"
@@ -485,6 +499,7 @@ void Settings::CreateOptionDescriptions() {
"Talking to the chest game owner after buying a key will tell you the location of Greg the Green Rupee.";
mOptionDescriptions[RSK_SARIA_HINT] = "Talking to Saria either in person or through Saria's Song will tell you the "
"location of a progressive magic meter.";
+ mOptionDescriptions[RSK_FISHING_POLE_HINT] = "Talking to the fishing pond owner without the fishing pole will tell you its location.";
mOptionDescriptions[RSK_FROGS_HINT] = "Standing near the pedestal for the frogs in Zora's River will tell you the "
"reward for the frogs' ocarina game.";
mOptionDescriptions[RSK_BIGGORON_HINT] = "Talking to Biggoron will tell you the item he will give you in exchange for the Claim Check.";
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index aef7291dc..41f937828 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -36,6 +36,7 @@
#include "trial.h"
#include "settings.h"
#include "soh/util.h"
+#include "fishsanity.h"
extern "C" uint32_t ResourceMgr_IsGameMasterQuest();
extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
@@ -464,6 +465,20 @@ void Randomizer::LoadHintMessages() {
"Komm wieder sobald du deinen eigenen&Bogen hast, um einen %rspeziellen Preis%w zu&erhalten!",
"J'aurai %rune autre récompense%w pour toi&lorsque tu auras ton propre arc."));
+ // Fishing pond pole hint
+ CustomMessageManager::Instance->CreateMessage(
+ Randomizer::randoMiscHintsTableID, TEXT_FISHING_POND_START,
+ CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(),
+ ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(),
+ ctx->GetHint(RH_FISHING_POLE)->GetText().GetFrench())
+ );
+ CustomMessageManager::Instance->CreateMessage(
+ Randomizer::randoMiscHintsTableID, TEXT_FISHING_POND_START_MET,
+ CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(),
+ ctx->GetHint(RH_FISHING_POLE)->GetText().GetEnglish(),
+ ctx->GetHint(RH_FISHING_POLE)->GetText().GetFrench())
+ );
+
// Lake Hylia water level system
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN,
CustomMessage("Water level control system.&Keep away!",
@@ -731,6 +746,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
// Bottle Refills
case RG_MILK:
+ case RG_FISH:
case RG_RED_POTION_REFILL:
case RG_GREEN_POTION_REFILL:
case RG_BLUE_POTION_REFILL:
@@ -782,6 +798,8 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
case RG_MAGIC_SINGLE:
case RG_MAGIC_DOUBLE:
return gSaveContext.magicLevel < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE;
+ case RG_FISHING_POLE:
+ return !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE;
// Songs
case RG_ZELDAS_LULLABY:
@@ -1123,6 +1141,7 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem
case RG_BLUE_POTION_REFILL:
case RG_BUY_BLUE_POTION:
return GI_POTION_BLUE;
+ case RG_FISH:
case RG_BUY_FISH:
return GI_FISH;
case RG_BUY_BLUE_FIRE:
@@ -1318,6 +1337,7 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) {
case RG_PIECE_OF_HEART:
case RG_HEART_CONTAINER:
case RG_MILK:
+ case RG_FISH:
case RG_BOMBS_5:
case RG_BOMBS_10:
case RG_BOMBS_20:
@@ -1520,9 +1540,57 @@ std::map rcToRandomizerInf = {
{ RC_LH_ADULT_FISHING, RAND_INF_ADULT_FISHING },
{ RC_MARKET_10_BIG_POES, RAND_INF_10_BIG_POES },
{ RC_KAK_100_GOLD_SKULLTULA_REWARD, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD },
+ { RC_LH_CHILD_FISH_1, RAND_INF_CHILD_FISH_1 },
+ { RC_LH_CHILD_FISH_2, RAND_INF_CHILD_FISH_2 },
+ { RC_LH_CHILD_FISH_3, RAND_INF_CHILD_FISH_3 },
+ { RC_LH_CHILD_FISH_4, RAND_INF_CHILD_FISH_4 },
+ { RC_LH_CHILD_FISH_5, RAND_INF_CHILD_FISH_5 },
+ { RC_LH_CHILD_FISH_6, RAND_INF_CHILD_FISH_6 },
+ { RC_LH_CHILD_FISH_7, RAND_INF_CHILD_FISH_7 },
+ { RC_LH_CHILD_FISH_8, RAND_INF_CHILD_FISH_8 },
+ { RC_LH_CHILD_FISH_9, RAND_INF_CHILD_FISH_9 },
+ { RC_LH_CHILD_FISH_10, RAND_INF_CHILD_FISH_10 },
+ { RC_LH_CHILD_FISH_11, RAND_INF_CHILD_FISH_11 },
+ { RC_LH_CHILD_FISH_12, RAND_INF_CHILD_FISH_12 },
+ { RC_LH_CHILD_FISH_13, RAND_INF_CHILD_FISH_13 },
+ { RC_LH_CHILD_FISH_14, RAND_INF_CHILD_FISH_14 },
+ { RC_LH_CHILD_FISH_15, RAND_INF_CHILD_FISH_15 },
+ { RC_LH_CHILD_LOACH_1, RAND_INF_CHILD_LOACH_1 },
+ { RC_LH_CHILD_LOACH_2, RAND_INF_CHILD_LOACH_2 },
+ { RC_LH_ADULT_FISH_1, RAND_INF_ADULT_FISH_1 },
+ { RC_LH_ADULT_FISH_2, RAND_INF_ADULT_FISH_2 },
+ { RC_LH_ADULT_FISH_3, RAND_INF_ADULT_FISH_3 },
+ { RC_LH_ADULT_FISH_4, RAND_INF_ADULT_FISH_4 },
+ { RC_LH_ADULT_FISH_5, RAND_INF_ADULT_FISH_5 },
+ { RC_LH_ADULT_FISH_6, RAND_INF_ADULT_FISH_6 },
+ { RC_LH_ADULT_FISH_7, RAND_INF_ADULT_FISH_7 },
+ { RC_LH_ADULT_FISH_8, RAND_INF_ADULT_FISH_8 },
+ { RC_LH_ADULT_FISH_9, RAND_INF_ADULT_FISH_9 },
+ { RC_LH_ADULT_FISH_10, RAND_INF_ADULT_FISH_10 },
+ { RC_LH_ADULT_FISH_11, RAND_INF_ADULT_FISH_11 },
+ { RC_LH_ADULT_FISH_12, RAND_INF_ADULT_FISH_12 },
+ { RC_LH_ADULT_FISH_13, RAND_INF_ADULT_FISH_13 },
+ { RC_LH_ADULT_FISH_14, RAND_INF_ADULT_FISH_14 },
+ { RC_LH_ADULT_FISH_15, RAND_INF_ADULT_FISH_15 },
+ { RC_LH_ADULT_LOACH, RAND_INF_ADULT_LOACH },
+ { RC_ZR_OPEN_GROTTO_FISH, RAND_INF_GROTTO_FISH_ZR_OPEN_GROTTO },
+ { RC_DMC_UPPER_GROTTO_FISH, RAND_INF_GROTTO_FISH_DMC_UPPER_GROTTO },
+ { RC_DMT_STORMS_GROTTO_FISH, RAND_INF_GROTTO_FISH_DMT_STORMS_GROTTO },
+ { RC_KAK_OPEN_GROTTO_FISH, RAND_INF_GROTTO_FISH_KAK_OPEN_GROTTO },
+ { RC_HF_NEAR_MARKET_GROTTO_FISH, RAND_INF_GROTTO_FISH_HF_NEAR_MARKET_GROTTO },
+ { RC_HF_OPEN_GROTTO_FISH, RAND_INF_GROTTO_FISH_HF_OPEN_GROTTO },
+ { RC_HF_SOUTHEAST_GROTTO_FISH, RAND_INF_GROTTO_FISH_HF_SOUTHEAST_GROTTO },
+ { RC_LW_NEAR_SHORTCUTS_GROTTO_FISH, RAND_INF_GROTTO_FISH_LW_NEAR_SHORTCUTS_GROTTO },
+ { RC_KF_STORMS_GROTTO_FISH, RAND_INF_GROTTO_FISH_KF_STORMS_GROTTO },
+ { RC_ZD_FISH_1, RAND_INF_ZD_FISH_1 },
+ { RC_ZD_FISH_2, RAND_INF_ZD_FISH_2 },
+ { RC_ZD_FISH_3, RAND_INF_ZD_FISH_3 },
+ { RC_ZD_FISH_4, RAND_INF_ZD_FISH_4 },
+ { RC_ZD_FISH_5, RAND_INF_ZD_FISH_5 },
};
Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) {
+ auto fs = OTRGlobals::Instance->gRandoContext->GetFishsanity();
RandomizerCheck specialRc = RC_UNKNOWN_CHECK;
// TODO: Migrate these special cases into table, or at least document why they are special
switch(sceneNum) {
@@ -1620,6 +1688,15 @@ Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum,
specialRc = RC_DODONGOS_CAVERN_GOSSIP_STONE;
}
break;
+ case SCENE_GROTTOS:
+ // Grotto fish are identified by respawn data
+ if (actorId == ACTOR_EN_FISH && actorParams == 1) {
+ int8_t data = gSaveContext.respawn[RESPAWN_MODE_RETURN].data;
+ if (Rando::StaticData::randomizerGrottoFishMap.contains(data)) {
+ specialRc = Rando::StaticData::randomizerGrottoFishMap[data];
+ }
+ }
+ break;
}
if (specialRc != RC_UNKNOWN_CHECK) {
@@ -1727,6 +1804,27 @@ CowIdentity Randomizer::IdentifyCow(s32 sceneNum, s32 posX, s32 posZ) {
return cowIdentity;
}
+FishIdentity Randomizer::IdentifyFish(s32 sceneNum, s32 actorParams) {
+ struct FishIdentity fishIdentity;
+
+ fishIdentity.randomizerInf = RAND_INF_MAX;
+ fishIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
+
+ // Fishsanity will determine what the identity of the fish should be
+ if (sceneNum == SCENE_FISHING_POND) {
+ return OTRGlobals::Instance->gRandoContext->GetFishsanity()->IdentifyPondFish(actorParams);
+ }
+
+ Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_FISH, sceneNum, actorParams);
+
+ if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
+ fishIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
+ fishIdentity.randomizerCheck = location->GetRandomizerCheck();
+ }
+
+ return fishIdentity;
+}
+
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetSelectedOptionIndex();
}
@@ -2557,6 +2655,32 @@ CustomMessage Randomizer::GetSariaMessage(u16 originalTextId) {
}
}
+CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) {
+ CustomMessage hintMessageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::randoMiscHintsTableID, TEXT_FISHING_POND_START);
+ CustomMessage messageEntry = CustomMessage(
+ "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!",
+ "",
+ ""
+ );
+
+ if (Rando::Context::GetInstance()->GetOption(RSK_FISHING_POLE_HINT)) {
+ messageEntry = messageEntry + hintMessageEntry;
+ }
+
+ // if the fishing pond guy doesnt remember me i will cry :(
+ if (originalTextId == TEXT_FISHING_POND_START_MET) {
+ messageEntry = CustomMessage(
+ "Hey, mister! I remember you!&It's been a long time!^",
+ "",
+ ""
+ ) + messageEntry;
+ }
+
+ messageEntry.Format();
+
+ return messageEntry;
+}
+
CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious) {
auto ctx = Rando::Context::GetInstance();
CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId);
@@ -3055,7 +3179,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!",
@@ -3321,6 +3445,7 @@ void Randomizer::CreateCustomMessages() {
"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!"),
+ GIMESSAGE_UNTRANSLATED(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!"),
}};
CreateGetItemMessages(&getItemMessages);
CreateRupeeMessages();
diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h
index f0e3a3440..23a63a074 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.h
+++ b/soh/soh/Enhancements/randomizer/randomizer.h
@@ -13,6 +13,7 @@
#include
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "../custom-message/CustomMessageTypes.h"
+#include "soh/Enhancements/randomizer/fishsanity.h"
#define MAX_SEED_STRING_SIZE 1024
#define NUM_TRIFORCE_PIECE_MESSAGES 6
@@ -53,6 +54,7 @@ class Randomizer {
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex);
CowIdentity IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);
+ FishIdentity IdentifyFish(s32 sceneNum, s32 actorParams);
GetItemEntry GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability = true);
GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, bool checkObtainability = true);
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);
@@ -62,6 +64,7 @@ class Randomizer {
CustomMessage ReplaceWithItemName(CustomMessage message, std::string&& toReplace, RandomizerCheck hintedCheck);
CustomMessage GetMiscHintMessage(TextIDs textToGet, RandomizerCheck hintedCheck, RandomizerCheck otherCheck = RC_UNKNOWN_CHECK);
CustomMessage GetSariaMessage(u16 originalTextId);
+ CustomMessage GetFishingPondOwnerMessage(u16 originalTextId);
CustomMessage GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false);
RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams);
CustomMessage GetCursedSkullMessage(s16 params, RandomizerCheck hintedCheck);
diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h
index f37952001..2ab5bd745 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -112,6 +112,7 @@ typedef enum {
RCTYPE_BOSS_HEART_OR_OTHER_REWARD, // Boss heart container or lesser dungeon rewards (lens, ice arrow)
RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps)
RCTYPE_OCARINA, // Ocarina locations
+ RCTYPE_FISH,
} RandomizerCheckType;
typedef enum { RCQUEST_VANILLA, RCQUEST_MQ, RCQUEST_BOTH } RandomizerCheckQuest;
@@ -905,7 +906,40 @@ typedef enum {
RC_ZF_GS_HIDDEN_CAVE,
RC_LH_UNDERWATER_ITEM,
RC_LH_CHILD_FISHING,
+ RC_LH_CHILD_FISH_1,
+ RC_LH_CHILD_FISH_2,
+ RC_LH_CHILD_FISH_3,
+ RC_LH_CHILD_FISH_4,
+ RC_LH_CHILD_FISH_5,
+ RC_LH_CHILD_FISH_6,
+ RC_LH_CHILD_FISH_7,
+ RC_LH_CHILD_FISH_8,
+ RC_LH_CHILD_FISH_9,
+ RC_LH_CHILD_FISH_10,
+ RC_LH_CHILD_FISH_11,
+ RC_LH_CHILD_FISH_12,
+ RC_LH_CHILD_FISH_13,
+ RC_LH_CHILD_FISH_14,
+ RC_LH_CHILD_FISH_15,
+ RC_LH_CHILD_LOACH_1,
+ RC_LH_CHILD_LOACH_2,
RC_LH_ADULT_FISHING,
+ RC_LH_ADULT_FISH_1,
+ RC_LH_ADULT_FISH_2,
+ RC_LH_ADULT_FISH_3,
+ RC_LH_ADULT_FISH_4,
+ RC_LH_ADULT_FISH_5,
+ RC_LH_ADULT_FISH_6,
+ RC_LH_ADULT_FISH_7,
+ RC_LH_ADULT_FISH_8,
+ RC_LH_ADULT_FISH_9,
+ RC_LH_ADULT_FISH_10,
+ RC_LH_ADULT_FISH_11,
+ RC_LH_ADULT_FISH_12,
+ RC_LH_ADULT_FISH_13,
+ RC_LH_ADULT_FISH_14,
+ RC_LH_ADULT_FISH_15,
+ RC_LH_ADULT_LOACH,
RC_LH_LAB_DIVE,
RC_LH_TRADE_FROG,
RC_LH_FREESTANDING_POH,
@@ -1401,6 +1435,21 @@ typedef enum {
RC_SARIA_SONG_HINT,
RC_ALTAR_HINT_CHILD,
RC_ALTAR_HINT_ADULT,
+ RC_FISHING_POLE_HINT,
+ RC_DMC_UPPER_GROTTO_FISH,
+ RC_DMT_STORMS_GROTTO_FISH,
+ RC_HF_SOUTHEAST_GROTTO_FISH,
+ RC_HF_NEAR_MARKET_GROTTO_FISH,
+ RC_HF_OPEN_GROTTO_FISH,
+ RC_KAK_OPEN_GROTTO_FISH,
+ RC_KF_STORMS_GROTTO_FISH,
+ RC_LW_NEAR_SHORTCUTS_GROTTO_FISH,
+ RC_ZR_OPEN_GROTTO_FISH,
+ RC_ZD_FISH_1,
+ RC_ZD_FISH_2,
+ RC_ZD_FISH_3,
+ RC_ZD_FISH_4,
+ RC_ZD_FISH_5,
RC_MAX
} RandomizerCheck;
@@ -1807,6 +1856,7 @@ typedef enum {
RG_HEART_CONTAINER,
RG_ICE_TRAP,
RG_MILK,
+ RG_FISH,
RG_BOMBS_5,
RG_BOMBS_10,
RG_BOMBS_20,
@@ -1872,6 +1922,7 @@ typedef enum {
RG_OCARINA_C_DOWN_BUTTON,
RG_OCARINA_C_LEFT_BUTTON,
RG_OCARINA_C_RIGHT_BUTTON,
+ RG_FISHING_POLE,
RG_HINT,
RG_TYCOON_WALLET,
RG_FAIRY_OCARINA,
@@ -1959,6 +2010,7 @@ typedef enum {
RH_ALTAR_CHILD,
RH_ALTAR_ADULT,
RH_SARIA,
+ RH_FISHING_POLE,
RH_SHEIK_LIGHT_ARROWS,
RH_MINUET_WARP_LOC,
RH_BOLERO_WARP_LOC,
@@ -2183,6 +2235,7 @@ typedef enum {
RHT_KF_MIDOS_BOTTOM_RIGHT_CHEST,
RHT_KF_KOKIRI_SWORD_CHEST,
RHT_KF_STORMS_GROTTO_CHEST,
+ RHT_KF_STORMS_GROTTO_FISH,
RHT_KF_LINKS_HOUSE_COW,
RHT_KF_GS_KNOW_IT_ALL_HOUSE,
RHT_KF_GS_BEAN_PATCH,
@@ -2199,6 +2252,7 @@ typedef enum {
RHT_LW_OCARINA_MEMORY_GAME,
RHT_LW_TARGET_IN_WOODS,
RHT_LW_NEAR_SHORTCUTS_GROTTO_CHEST,
+ RHT_LW_NEAR_SHORTCUTS_GROTTO_FISH,
RHT_LW_TRADE_COJIRO,
RHT_DEKU_THEATER_SKULL_MASK,
RHT_DEKU_THEATER_MASK_OF_TRUTH,
@@ -2218,9 +2272,12 @@ typedef enum {
RHT_SFM_GS,
RHT_HF_OCARINA_OF_TIME_ITEM,
RHT_HF_NEAR_MARKET_GROTTO_CHEST,
+ RHT_HF_NEAR_MARKET_GROTTO_FISH,
RHT_HF_TEKTITE_GROTTO_FREESTANDING_POH,
RHT_HF_SOUTHEAST_GROTTO_CHEST,
+ RHT_HF_SOUTHEAST_GROTTO_FISH,
RHT_HF_OPEN_GROTTO_CHEST,
+ RHT_HF_OPEN_GROTTO_FISH,
RHT_HF_DEKU_SCRUB_GROTTO,
RHT_HF_COW_GROTTO_COW,
RHT_HF_GS_COW_GROTTO,
@@ -2288,6 +2345,7 @@ typedef enum {
RHT_KAK_WINDMILL_FREESTANDING_POH,
RHT_KAK_MAN_ON_ROOF,
RHT_KAK_OPEN_GROTTO_CHEST,
+ RHT_KAK_OPEN_GROTTO_FISH,
RHT_KAK_REDEAD_GROTTO_CHEST,
RHT_KAK_SHOOTING_GALLERY_REWARD,
RHT_KAK_TRADE_ODD_MUSHROOM,
@@ -2334,6 +2392,7 @@ typedef enum {
RHT_DMT_FREESTANDING_POH,
RHT_DMT_CHEST,
RHT_DMT_STORMS_GROTTO_CHEST,
+ RHT_DMT_STORMS_GROTTO_FISH,
RHT_DMT_TRADE_BROKEN_SWORD,
RHT_DMT_TRADE_EYEDROPS,
RHT_DMT_TRADE_CLAIM_CHECK,
@@ -2367,6 +2426,7 @@ typedef enum {
RHT_DMC_VOLCANO_FREESTANDING_POH,
RHT_DMC_WALL_FREESTANDING_POH,
RHT_DMC_UPPER_GROTTO_CHEST,
+ RHT_DMC_UPPER_GROTTO_FISH,
RHT_DMC_GREAT_FAIRY_REWARD,
RHT_DMC_DEKU_SCRUB,
RHT_DMC_DEKU_SCRUB_GROTTO_LEFT,
@@ -2376,6 +2436,7 @@ typedef enum {
RHT_DMC_GS_BEAN_PATCH,
RHT_ZR_MAGIC_BEAN_SALESMAN,
RHT_ZR_OPEN_GROTTO_CHEST,
+ RHT_ZR_OPEN_GROTTO_FISH,
RHT_ZR_FROGS_ZELDAS_LULLABY,
RHT_ZR_FROGS_EPONAS_SONG,
RHT_ZR_FROGS_SARIAS_SONG,
@@ -2404,6 +2465,7 @@ typedef enum {
RHT_ZD_SHOP_ITEM_6,
RHT_ZD_SHOP_ITEM_7,
RHT_ZD_SHOP_ITEM_8,
+ RHT_ZD_FISH,
RHT_ZF_GREAT_FAIRY_REWARD,
RHT_ZF_ICEBERG_FREESTANDING_POH,
RHT_ZF_BOTTOM_FREESTANDING_POH,
@@ -2413,6 +2475,8 @@ typedef enum {
RHT_LH_UNDERWATER_ITEM,
RHT_LH_CHILD_FISHING,
RHT_LH_ADULT_FISHING,
+ RHT_LH_POND_FISH,
+ RHT_LH_HYRULE_LOACH,
RHT_LH_LAB_DIVE,
RHT_LH_TRADE_FROG,
RHT_LH_FREESTANDING_POH,
@@ -3094,6 +3158,7 @@ typedef enum {
RHT_OCARINA_C_DOWN_BUTTON,
RHT_OCARINA_C_LEFT_BUTTON,
RHT_OCARINA_C_RIGHT_BUTTON,
+ RHT_FISHING_POLE,
RHT_EPONA,
// Entrances
RHT_DESERT_COLOSSUS_TO_COLOSSUS_GROTTO,
@@ -3284,6 +3349,8 @@ typedef enum {
RHT_WARP_CHOICE,
RHT_FROGS_HINT01,
RHT_FROGS_HINT02,
+ RHT_FISHING_POLE_HINT01,
+ RHT_FISHING_POLE_HINT02,
// Ganon Line
RHT_GANON_LINE01,
RHT_GANON_LINE02,
@@ -3453,6 +3520,7 @@ typedef enum {
RSK_HBA_HINT,
RSK_WARP_SONG_HINTS,
RSK_SCRUB_TEXT_HINT,
+ RSK_FISHING_POLE_HINT,
RSK_HINT_CLARITY,
RSK_HINT_DISTRIBUTION,
RSK_SHUFFLE_MAPANDCOMPASS,
@@ -3538,6 +3606,10 @@ typedef enum {
RSK_TRIFORCE_HUNT_PIECES_TOTAL,
RSK_TRIFORCE_HUNT_PIECES_REQUIRED,
RSK_SHUFFLE_BOSS_SOULS,
+ RSK_FISHSANITY,
+ RSK_FISHSANITY_POND_COUNT,
+ RSK_FISHSANITY_AGE_SPLIT,
+ RSK_SHUFFLE_FISHING_POLE,
RSK_MAX
} RandomizerSettingKey;
@@ -3668,6 +3740,14 @@ typedef enum {
RO_BOSS_SOULS_ON_PLUS_GANON,
} RandoOptionBossSouls;
+//Fishsanity settings (off, pond only, grottos only, both)
+typedef enum {
+ RO_FISHSANITY_OFF,
+ RO_FISHSANITY_POND,
+ RO_FISHSANITY_OVERWORLD,
+ RO_FISHSANITY_BOTH
+} RandoOptionsFishsanity;
+
//Any Dungeon Item (start with, vanilla, own dungeon, any dungeon,
//overworld, anywhere)
typedef enum {
@@ -3918,6 +3998,11 @@ typedef struct CowIdentity {
RandomizerCheck randomizerCheck;
} CowIdentity;
+typedef struct FishIdentity {
+ RandomizerInf randomizerInf;
+ RandomizerCheck randomizerCheck;
+} FishIdentity;
+
typedef enum {
TRACKER_WINDOW_FLOATING,
TRACKER_WINDOW_WINDOW
diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp
index 14335db68..3fa6b82d6 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp
@@ -5,6 +5,7 @@
#include
#include
#include "z64.h"
+#include "fishsanity.h"
std::map rcAreaNames = {
{ RCAREA_KOKIRI_FOREST, "Kokiri Forest" },
@@ -153,6 +154,7 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() {
((CVarGetInteger("gRandomizeShuffleTokens", RO_TOKENSANITY_OFF) == RO_TOKENSANITY_DUNGEONS) &&
RandomizerCheckObjects::AreaIsDungeon(location.GetArea()))) &&
(location.GetRCType() != RCTYPE_COW || CVarGetInteger("gRandomizeShuffleCows", RO_GENERIC_NO)) &&
+ (location.GetRCType() != RCTYPE_FISH || ctx->GetFishsanity()->GetFishLocationIncluded(&location, FSO_SOURCE_CVARS)) &&
(location.GetRCType() != RCTYPE_ADULT_TRADE ||
CVarGetInteger("gRandomizeShuffleAdultTrade", RO_GENERIC_NO)) &&
(location.GetRandomizerCheck() != RC_KF_KOKIRI_SWORD_CHEST ||
diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
index 798b11d97..82c2f98fd 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
@@ -15,6 +15,7 @@
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "z64item.h"
#include "randomizerTypes.h"
+#include "fishsanity.h"
extern "C" {
#include "variables.h"
@@ -76,6 +77,10 @@ bool showLinksPocket;
bool fortressFast;
bool fortressNormal;
+u8 fishsanityMode;
+u8 fishsanityPondCount;
+bool fishsanityAgeSplit;
+
// persistent during gameplay
bool initialized;
bool doAreaScroll;
@@ -119,6 +124,7 @@ RandomizerCheck lastLocationChecked = RC_UNKNOWN_CHECK;
RandomizerCheckArea previousArea = RCAREA_INVALID;
RandomizerCheckArea currentArea = RCAREA_INVALID;
OSContPad* trackerButtonsPressed;
+std::unordered_map checkNameOverrides;
void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0);
bool CompareChecks(RandomizerCheck, RandomizerCheck);
@@ -415,6 +421,7 @@ bool HasItemBeenCollected(RandomizerCheck rc) {
case SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT:
case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM:
case SpoilerCollectionCheckType::SPOILER_CHK_COW:
+ case SpoilerCollectionCheckType::SPOILER_CHK_FISH:
case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB:
case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF:
case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD:
@@ -473,6 +480,14 @@ void CheckTrackerLoadGame(int32_t fileNum) {
if (areaChecksGotten[entry2->GetArea()] != 0 || RandomizerCheckObjects::AreaIsOverworld(entry2->GetArea())) {
areasSpoiled |= (1 << entry2->GetArea());
}
+
+ // Create check name overrides for child pond fish if age split is disabled
+ if (fishsanityMode != RO_FISHSANITY_OFF && fishsanityMode != RO_FISHSANITY_OVERWORLD && entry.GetRCType() == RCTYPE_FISH && entry.GetScene() == SCENE_FISHING_POND &&
+ entry.GetActorParams() != 116 && !fishsanityAgeSplit) {
+ if (entry.GetShortName().starts_with("Child")) {
+ checkNameOverrides[rc] = entry.GetShortName().substr(6);
+ }
+ }
}
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
s8 startingAge = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_AGE);
@@ -736,6 +751,7 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) {
(scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_COW ||
+ scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SCRUB ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD ||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) {
@@ -1161,6 +1177,10 @@ void LoadSettings() {
fortressNormal = true;
break;
}
+
+ fishsanityMode = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY);
+ fishsanityPondCount = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_POND_COUNT);
+ fishsanityAgeSplit = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_FISHSANITY_AGE_SPLIT);
}
bool IsVisibleInCheckTracker(RandomizerCheck rc) {
@@ -1194,6 +1214,7 @@ bool IsVisibleInCheckTracker(RandomizerCheck rc) {
(showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))
) &&
(loc->GetRCType() != RCTYPE_COW || showCows) &&
+ (loc->GetRCType() != RCTYPE_FISH || OTRGlobals::Instance->gRandoContext->GetFishsanity()->GetFishLocationIncluded(loc)) &&
(loc->GetRCType() != RCTYPE_ADULT_TRADE ||
showAdultTrade ||
rc == RC_KAK_ANJU_AS_ADULT || // adult trade checks that are always shuffled
@@ -1375,7 +1396,12 @@ void DrawLocation(RandomizerCheck rc) {
}
//Main Text
- txt = loc->GetShortName();
+ if (checkNameOverrides.contains(loc->GetRandomizerCheck())) {
+ txt = checkNameOverrides[loc->GetRandomizerCheck()];
+ } else {
+ txt = loc->GetShortName();
+ }
+
if (lastLocationChecked == loc->GetRandomizerCheck()) {
txt = "* " + txt;
}
diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h
index 39f84ba2a..8cc8e7fb3 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -156,8 +156,43 @@ typedef enum {
RAND_INF_TOT_MASTER_SWORD,
+
RAND_INF_CHILD_FISHING,
+ RAND_INF_CHILD_FISH_1,
+ RAND_INF_CHILD_FISH_2,
+ RAND_INF_CHILD_FISH_3,
+ RAND_INF_CHILD_FISH_4,
+ RAND_INF_CHILD_FISH_5,
+ RAND_INF_CHILD_FISH_6,
+ RAND_INF_CHILD_FISH_7,
+ RAND_INF_CHILD_FISH_8,
+ RAND_INF_CHILD_FISH_9,
+ RAND_INF_CHILD_FISH_10,
+ RAND_INF_CHILD_FISH_11,
+ RAND_INF_CHILD_FISH_12,
+ RAND_INF_CHILD_FISH_13,
+ RAND_INF_CHILD_FISH_14,
+ RAND_INF_CHILD_FISH_15,
+ RAND_INF_CHILD_LOACH_1,
+ RAND_INF_CHILD_LOACH_2,
RAND_INF_ADULT_FISHING,
+ RAND_INF_ADULT_FISH_1,
+ RAND_INF_ADULT_FISH_2,
+ RAND_INF_ADULT_FISH_3,
+ RAND_INF_ADULT_FISH_4,
+ RAND_INF_ADULT_FISH_5,
+ RAND_INF_ADULT_FISH_6,
+ RAND_INF_ADULT_FISH_7,
+ RAND_INF_ADULT_FISH_8,
+ RAND_INF_ADULT_FISH_9,
+ RAND_INF_ADULT_FISH_10,
+ RAND_INF_ADULT_FISH_11,
+ RAND_INF_ADULT_FISH_12,
+ RAND_INF_ADULT_FISH_13,
+ RAND_INF_ADULT_FISH_14,
+ RAND_INF_ADULT_FISH_15,
+ RAND_INF_ADULT_LOACH,
+
RAND_INF_10_BIG_POES,
RAND_INF_GRANT_GANONS_BOSSKEY,
@@ -177,6 +212,24 @@ typedef enum {
RAND_INF_HAS_OCARINA_C_LEFT,
RAND_INF_HAS_OCARINA_C_RIGHT,
+ RAND_INF_GROTTO_FISH_ZR_OPEN_GROTTO,
+ RAND_INF_GROTTO_FISH_DMC_UPPER_GROTTO,
+ RAND_INF_GROTTO_FISH_DMT_STORMS_GROTTO,
+ RAND_INF_GROTTO_FISH_KAK_OPEN_GROTTO,
+ RAND_INF_GROTTO_FISH_HF_NEAR_MARKET_GROTTO,
+ RAND_INF_GROTTO_FISH_HF_OPEN_GROTTO,
+ RAND_INF_GROTTO_FISH_HF_SOUTHEAST_GROTTO,
+ RAND_INF_GROTTO_FISH_LW_NEAR_SHORTCUTS_GROTTO,
+ RAND_INF_GROTTO_FISH_KF_STORMS_GROTTO,
+
+ RAND_INF_FISHING_POLE_FOUND,
+
+ RAND_INF_ZD_FISH_1,
+ RAND_INF_ZD_FISH_2,
+ RAND_INF_ZD_FISH_3,
+ RAND_INF_ZD_FISH_4,
+ RAND_INF_ZD_FISH_5,
+
// 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 3d4177c59..d0d8873ae 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp
@@ -108,6 +108,10 @@ std::vector ocarinaButtonItems = {
ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem ),
};
+std::vector fishingPoleItems = {
+ ITEM_TRACKER_ITEM(ITEM_FISHING_POLE, 0, DrawItem)
+};
+
std::vector itemTrackerDungeonsWithMapsHorizontal = {
{ SCENE_DEKU_TREE, { ITEM_DUNGEON_MAP, ITEM_COMPASS } },
{ SCENE_DODONGOS_CAVERN, { ITEM_DUNGEON_MAP, ITEM_COMPASS } },
@@ -726,6 +730,11 @@ void DrawItem(ItemTrackerItem item) {
hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT);
itemName = "Ocarina C Right Button";
break;
+ case ITEM_FISHING_POLE:
+ actualItemId = item.id;
+ hasItem = IS_RANDO && Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND);
+ itemName = "Fishing Pole";
+ break;
}
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
@@ -1054,25 +1063,22 @@ void UpdateVectors() {
// and misc isn't on the main window,
// and it doesn't already have greg, add him
if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW &&
- CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW &&
- std::none_of(miscItems.begin(), miscItems.end(), [](ItemTrackerItem item){return item.id == ITEM_RUPEE_GREEN;})) {
-
- miscItems.insert(miscItems.end(), gregItems.begin(), gregItems.end());
+ CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) {
+ if (std::none_of(miscItems.begin(), miscItems.end(), [](ItemTrackerItem item) { return item.id == ITEM_RUPEE_GREEN; }))
+ miscItems.insert(miscItems.end(), gregItems.begin(), gregItems.end());
} else {
- for (auto it = miscItems.begin(); it != miscItems.end();) {
- if (it->id == ITEM_RUPEE_GREEN) {
- miscItems.erase(it);
- } else {
- it++;
- }
- }
+ miscItems.erase(std::remove_if(miscItems.begin(), miscItems.end(), [](ItemTrackerItem i) { return i.id == ITEM_RUPEE_GREEN; }), miscItems.end());
}
+ bool newRowAdded = false;
// if we're adding greg to the main window
if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) {
- // insert empty items until we're on a new row for greg
- while (mainWindowItems.size() % 6) {
- mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
+ if (!newRowAdded) {
+ // insert empty items until we're on a new row for greg
+ while (mainWindowItems.size() % 6) {
+ mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
+ }
+ newRowAdded = true;
}
// add greg
@@ -1082,16 +1088,37 @@ void UpdateVectors() {
// If we're adding triforce pieces to the main window
if (CVarGetInteger("gItemTrackerTriforcePiecesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) {
// If Greg isn't on the main window, add empty items to place the triforce pieces on a new row.
- if (CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) != SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) {
+ if (!newRowAdded) {
while (mainWindowItems.size() % 6) {
mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
}
+ newRowAdded = true;
}
// Add triforce pieces
mainWindowItems.insert(mainWindowItems.end(), triforcePieces.begin(), triforcePieces.end());
}
+ // if misc is separate and fishing pole isn't added, add fishing pole to misc
+ if (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MISC_WINDOW &&
+ CVarGetInteger("gItemTrackerMiscItemsDisplayType", SECTION_DISPLAY_MAIN_WINDOW) != SECTION_DISPLAY_MAIN_WINDOW) {
+ if (std::none_of(miscItems.begin(), miscItems.end(), [](ItemTrackerItem item) { return item.id == ITEM_FISHING_POLE; }))
+ miscItems.insert(miscItems.end(), fishingPoleItems.begin(), fishingPoleItems.end());
+ } else {
+ miscItems.erase(std::remove_if(miscItems.begin(), miscItems.end(), [](ItemTrackerItem i) { return i.id == ITEM_FISHING_POLE; }), miscItems.end());
+ }
+ // add fishing pole to main window
+ if (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) {
+ if (!newRowAdded) {
+ while (mainWindowItems.size() % 6) {
+ mainWindowItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem));
+ }
+ newRowAdded = true;
+ }
+
+ mainWindowItems.insert(mainWindowItems.end(), fishingPoleItems.begin(), fishingPoleItems.end());
+ }
+
//If we're adding boss souls to the main window...
if (CVarGetInteger("gItemTrackerBossSoulsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) {
//...add empty items on the main window to get the souls on their own row. (Too many to sit with Greg/Triforce pieces)
@@ -1138,6 +1165,7 @@ void ItemTrackerWindow::DrawElement() {
(CVarGetInteger("gItemTrackerDungeonItemsDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) ||
(CVarGetInteger("gItemTrackerGregDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) ||
(CVarGetInteger("gItemTrackerTriforcePiecesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW) ||
+ (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_MAIN_WINDOW) ||
(CVarGetInteger("gItemTrackerNotesDisplayType", SECTION_DISPLAY_HIDDEN) == SECTION_DISPLAY_MAIN_WINDOW)
) {
BeginFloatingWindows("Item Tracker##main window");
@@ -1226,6 +1254,12 @@ void ItemTrackerWindow::DrawElement() {
EndFloatingWindows();
}
+ if (CVarGetInteger("gItemTrackerFishingPoleDisplayType", SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) {
+ BeginFloatingWindows("Fishing Pole Tracker");
+ DrawItemsInRows(fishingPoleItems);
+ 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);
@@ -1373,6 +1407,10 @@ void ItemTrackerSettingsWindow::DrawElement() {
shouldUpdateVectors = true;
}
+ if (UIWidgets::LabeledRightAlignedEnhancementCombobox("Fishing Pole", "gItemTrackerFishingPoleDisplayType", extendedDisplayTypes, SECTION_DISPLAY_EXTENDED_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/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index edc8880fa..df886e92a 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -108,6 +108,7 @@ void Settings::CreateOptions() {
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_FISHING_POLE] = Option::Bool("Shuffle Fishing Pole", "gRandomizeShuffleFishingPole", mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]);
mOptions[RSK_SHUFFLE_MAGIC_BEANS] = Option::Bool("Shuffle Magic Beans", "gRandomizeShuffleBeans", mOptionDescriptions[RSK_SHUFFLE_MAGIC_BEANS]);
mOptions[RSK_SHUFFLE_MERCHANTS] = Option::U8("Shuffle Merchants", {"Off", "On (No Hints)", "On (With Hints)"}, OptionCategory::Setting, "gRandomizeShuffleMerchants", mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF);
mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES] = Option::Bool("Shuffle Frog Song Rupees", "gRandomizeShuffleFrogSongRupees", mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]);
@@ -115,6 +116,9 @@ void Settings::CreateOptions() {
mOptions[RSK_SHUFFLE_CHEST_MINIGAME] = Option::U8("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"});
mOptions[RSK_SHUFFLE_100_GS_REWARD] = Option::Bool("Shuffle 100 GS Reward", "gRandomizeShuffle100GSReward", mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
mOptions[RSK_SHUFFLE_BOSS_SOULS] = Option::U8("Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, "gRandomizeShuffleBossSouls", mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox);
+ mOptions[RSK_FISHSANITY] = Option::U8("Fishsanity", {"Off", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, "gRandomizeFishsanity", mOptionDescriptions[RSK_FISHSANITY], WidgetType::Combobox, RO_FISHSANITY_OFF);
+ mOptions[RSK_FISHSANITY_POND_COUNT] = Option::U8("Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, "gRandomizeFishsanityPondCount", mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WidgetType::Slider, 0, true, IMFLAG_NONE);
+ mOptions[RSK_FISHSANITY_AGE_SPLIT] = Option::Bool("Pond Age Split", "gRandomizeFishsanityAgeSplit", mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]);
mOptions[RSK_SHUFFLE_MAPANDCOMPASS] = Option::U8("Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeStartingMapsCompasses", mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
mOptions[RSK_KEYSANITY] = Option::U8("Small Keys", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeKeysanity", mOptionDescriptions[RSK_KEYSANITY], WidgetType::Combobox, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
mOptions[RSK_GERUDO_KEYS] = Option::U8("Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, "gRandomizeGerudoKeys", mOptionDescriptions[RSK_GERUDO_KEYS], WidgetType::Combobox, RO_GERUDO_KEYS_VANILLA);
@@ -154,6 +158,7 @@ void Settings::CreateOptions() {
mOptions[RSK_DAMPES_DIARY_HINT] = Option::Bool("Dampe's Diary Hint", "gRandomizeDampeHint", mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE);
mOptions[RSK_GREG_HINT] = Option::Bool("Greg the Green Rupee Hint", "gRandomizeGregHint", mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE);
mOptions[RSK_SARIA_HINT] = Option::Bool("Saria's Hint", "gRandomizeSariaHint", mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE);
+ mOptions[RSK_FISHING_POLE_HINT] = Option::Bool("Fishing Pole Hint", "gRandomizeFishingPoleHint", mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE);
mOptions[RSK_FROGS_HINT] = Option::Bool("Frog Ocarina Game Hint", "gRandomizeFrogsHint", mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE);
mOptions[RSK_BIGGORON_HINT] = Option::Bool("Biggoron's Hint", "gRandomizeBiggoronHint", mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE);
mOptions[RSK_BIG_POES_HINT] = Option::Bool("Big Poes Hint", "gRandomizeBigPoesHint", mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE);
@@ -645,12 +650,16 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_OCARINA],
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
- &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]
+ &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
+ &mOptions[RSK_SHUFFLE_FISHING_POLE],
}, false, WidgetContainerType::COLUMN);
mOptionGroups[RSG_SHUFFLE_NPCS_IMGUI] = OptionGroup::SubGroup("Shuffle NPCs & Merchants", {
&mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
+ &mOptions[RSK_FISHSANITY],
+ &mOptions[RSK_FISHSANITY_POND_COUNT],
+ &mOptions[RSK_FISHSANITY_AGE_SPLIT],
&mOptions[RSK_SHUFFLE_SCRUBS],
&mOptions[RSK_SHUFFLE_COWS],
&mOptions[RSK_SHUFFLE_MAGIC_BEANS],
@@ -719,6 +728,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_CHICKENS_HINT],
&mOptions[RSK_MALON_HINT],
&mOptions[RSK_HBA_HINT],
+ &mOptions[RSK_FISHING_POLE_HINT],
&mOptions[RSK_WARP_SONG_HINTS],
&mOptions[RSK_SCRUB_TEXT_HINT],
&mOptions[RSK_KAK_10_SKULLS_HINT],
@@ -843,6 +853,10 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
+ &mOptions[RSK_FISHSANITY],
+ &mOptions[RSK_FISHSANITY_POND_COUNT],
+ &mOptions[RSK_FISHSANITY_AGE_SPLIT],
+ &mOptions[RSK_SHUFFLE_FISHING_POLE],
&mOptions[RSK_SHUFFLE_TOKENS],
&mOptions[RSK_SHUFFLE_SCRUBS],
&mOptions[RSK_SHUFFLE_COWS],
@@ -946,6 +960,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_KAK_50_SKULLS_HINT],
&mOptions[RSK_KAK_100_SKULLS_HINT],
&mOptions[RSK_SCRUB_TEXT_HINT],
+ &mOptions[RSK_FISHING_POLE_HINT],
// TODO: Compasses show Reward/WOTH, Maps show Dungeon Mode, Starting Time
&mOptions[RSK_DAMAGE_MULTIPLIER],
&mOptions[RSK_BLUE_FIRE_ARROWS],
@@ -1019,6 +1034,9 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
+ &mOptions[RSK_FISHSANITY],
+ &mOptions[RSK_FISHSANITY_POND_COUNT],
+ &mOptions[RSK_FISHSANITY_AGE_SPLIT],
&mOptions[RSK_SHUFFLE_SCRUBS],
&mOptions[RSK_SHUFFLE_COWS],
&mOptions[RSK_SHUFFLE_MAGIC_BEANS],
@@ -1056,6 +1074,10 @@ void Settings::CreateOptions() {
{ "Shuffle Settings:Shopsanity", RSK_SHOPSANITY },
{ "Shuffle Settings:Shopsanity Prices", RSK_SHOPSANITY_PRICES },
{ "Shuffle Settings:Affordable Prices", RSK_SHOPSANITY_PRICES_AFFORDABLE },
+ { "Shuffle Settings:Fishsanity", RSK_FISHSANITY },
+ { "Shuffle Settings:Pond Fish Count", RSK_FISHSANITY_POND_COUNT },
+ { "Shuffle Settings:Split Pond Fish", RSK_FISHSANITY_AGE_SPLIT },
+ { "Shuffle Settings:Shuffle Fishing Pole", RSK_SHUFFLE_FISHING_POLE },
{ "Shuffle Settings:Scrub Shuffle", RSK_SHUFFLE_SCRUBS },
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
@@ -1147,6 +1169,7 @@ void Settings::CreateOptions() {
{ "Miscellaneous Settings:Big Poes Hint", RSK_BIG_POES_HINT },
{ "Miscellaneous Settings:Warp Song Hints", RSK_WARP_SONG_HINTS },
{ "Miscellaneous Settings:Scrub Hint Text", RSK_SCRUB_TEXT_HINT },
+ { "Miscellaneous Settings:Fishing Pole Hint", RSK_FISHING_POLE_HINT },
{ "Miscellaneous Settings:Hint Distribution", RSK_HINT_DISTRIBUTION },
{ "Miscellaneous Settings:Blue Fire Arrows", RSK_BLUE_FIRE_ARROWS },
{ "Miscellaneous Settings:Sunlight Arrows", RSK_SUNLIGHT_ARROWS },
@@ -1526,6 +1549,25 @@ void Settings::UpdateOptionProperties() {
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide();
break;
}
+ // Hide fishing pond settings if we aren't shuffling the fishing pond
+ switch (CVarGetInteger("gRandomizeFishsanity", RO_FISHSANITY_OFF)) {
+ case RO_FISHSANITY_POND:
+ case RO_FISHSANITY_BOTH:
+ mOptions[RSK_FISHSANITY].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
+ mOptions[RSK_FISHSANITY_POND_COUNT].Unhide();
+ mOptions[RSK_FISHSANITY_AGE_SPLIT].Unhide();
+ break;
+ default:
+ mOptions[RSK_FISHSANITY].AddFlag(IMFLAG_SEPARATOR_BOTTOM);
+ mOptions[RSK_FISHSANITY_POND_COUNT].Hide();
+ mOptions[RSK_FISHSANITY_AGE_SPLIT].Hide();
+ }
+ // Disable fishing pole hint if the fishing pole is not shuffled
+ if (CVarGetInteger("gRandomizeShuffleFishingPole", RO_GENERIC_OFF)) {
+ mOptions[RSK_FISHING_POLE_HINT].Enable();
+ } else {
+ mOptions[RSK_FISHING_POLE_HINT].Disable("This option is disabled since the fishing pole is not shuffled.");
+ }
// Shuffle 100 GS Reward - Force-Enabled if Ganon's Boss Key is on the 100 GS Reward
if (CVarGetInteger("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_VANILLA) == RO_GANON_BOSS_KEY_KAK_TOKENS) {
mOptions[RSK_SHUFFLE_100_GS_REWARD].Disable("This option is force-enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward.\"", UIWidgets::CheckboxGraphics::Checkmark);
@@ -2116,6 +2158,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
case RSK_LACS_TOKEN_COUNT:
case RSK_KEYRINGS_RANDOM_COUNT:
case RSK_CUCCO_COUNT:
+ case RSK_FISHSANITY_POND_COUNT:
case RSK_STARTING_SKULLTULA_TOKEN:
numericValueString = it.value();
mOptions[index].SetSelectedIndex(std::stoi(numericValueString));
@@ -2178,6 +2221,9 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
mOptions[index].SetSelectedIndex(RO_SCRUBS_RANDOM);
}
break;
+ case RSK_SHUFFLE_FISHING_POLE:
+ case RSK_FISHSANITY_AGE_SPLIT:
+ case RSK_FISHING_POLE_HINT:
case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD:
case RSK_SHUFFLE_COWS:
case RSK_SHUFFLE_ADULT_TRADE:
@@ -2290,6 +2336,17 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
mOptions[index].SetSelectedIndex(RO_AMMO_DROPS_OFF);
}
break;
+ case RSK_FISHSANITY:
+ if (it.value() == "Off") {
+ mOptions[index].SetSelectedIndex(RO_FISHSANITY_OFF);
+ } else if (it.value() == "Shuffle Fishing Pond") {
+ mOptions[index].SetSelectedIndex(RO_FISHSANITY_POND);
+ } else if (it.value() == "Shuffle Overworld Fish") {
+ mOptions[index].SetSelectedIndex(RO_FISHSANITY_OVERWORLD);
+ } else if (it.value() == "Shuffle Both") {
+ mOptions[index].SetSelectedIndex(RO_FISHSANITY_BOTH);
+ }
+ break;
case RSK_SHUFFLE_BOSS_SOULS:
if (it.value() == "Off") {
mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_OFF);
diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h
index 9a0000da2..7650b5dc4 100644
--- a/soh/soh/Enhancements/randomizer/static_data.h
+++ b/soh/soh/Enhancements/randomizer/static_data.h
@@ -1,6 +1,7 @@
#pragma once
#include
+#include
#include "randomizerTypes.h"
#include "item.h"
#include "location.h"
@@ -32,6 +33,10 @@ class StaticData {
static std::vector scrubLocations;
static std::vector gossipStoneLocations;
static std::vector otherHintLocations;
+ static std::vector pondFishLocations;
+ static std::vector overworldFishLocations;
+ static std::array, 17> randomizerFishingPondFish;
+ static std::unordered_map randomizerGrottoFishMap;
StaticData();
~StaticData();
};
diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp
index d39d115d9..feae99c47 100644
--- a/soh/soh/OTRGlobals.cpp
+++ b/soh/soh/OTRGlobals.cpp
@@ -2387,6 +2387,9 @@ extern "C" CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ)
return OTRGlobals::Instance->gRandomizer->IdentifyCow(sceneNum, posX, posZ);
}
+extern "C" FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams) {
+ return OTRGlobals::Instance->gRandomizer->IdentifyFish(sceneNum, actorParams);
+}
extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) {
GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, getItemID);
return giEntry;
@@ -2415,6 +2418,10 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityChec
return OTRGlobals::Instance->gRandomizer->GetItemFromKnownCheck(randomizerCheck, ogId, false);
}
+extern "C" RandomizerInf Randomizer_GetRandomizerInfFromCheck(RandomizerCheck randomizerCheck) {
+ return OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(randomizerCheck);
+}
+
extern "C" ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck) {
return OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck);
}
@@ -2614,6 +2621,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice);
} else if (Randomizer_GetSettingValue(RSK_FROGS_HINT) && textId == TEXT_FROGS_UNDERWATER) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetMiscHintMessage(TEXT_FROGS_UNDERWATER, RC_ZR_FROGS_OCARINA_GAME);
+ } else if (Randomizer_GetSettingValue(RSK_FISHING_POLE_HINT) && !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND) &&
+ (textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET)) {
+ messageEntry = OTRGlobals::Instance->gRandomizer->GetFishingPondOwnerMessage(textId);
} else if (Randomizer_GetSettingValue(RSK_SARIA_HINT) &&
(gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && textId == TEXT_SARIA_SFM) || (textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER)) {
messageEntry = OTRGlobals::Instance->gRandomizer->GetSariaMessage(textId);
diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h
index 76600d894..143ec9ef2 100644
--- a/soh/soh/OTRGlobals.h
+++ b/soh/soh/OTRGlobals.h
@@ -156,6 +156,7 @@ RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 acto
ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, u8 slotIndex);
CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);
+FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams);
void Randomizer_ParseSpoiler(const char* fileLoc);
void Randomizer_LoadHintMessages();
void Randomizer_LoadMerchantMessages();
@@ -164,6 +165,7 @@ GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorPar
GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId);
GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
+RandomizerInf Randomizer_GetRandomizerInfFromCheck(RandomizerCheck randomizerCheck);
ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
void Randomizer_GenerateSeed();
uint8_t Randomizer_IsSeedGenerated();
diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp
index 83d648039..991e2df6d 100644
--- a/soh/soh/SaveManager.cpp
+++ b/soh/soh/SaveManager.cpp
@@ -272,6 +272,9 @@ void SaveManager::LoadRandomizerVersion2() {
std::string sariaText;
SaveManager::Instance->LoadData("sariaText", sariaText);
randoContext->AddHint(RH_SARIA, Text(sariaText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
+ std::string fishingPoleText;
+ SaveManager::Instance->LoadData("fishingPoleText", fishingPoleText);
+ randoContext->AddHint(RH_FISHING_POLE, Text(fishingPoleText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static");
std::string warpMinuetText;
SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText);
randoContext->AddHint(RH_MINUET_WARP_LOC, Text(warpMinuetText), RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, "Static", randoContext->GetAreaFromString(warpMinuetText));
diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp
index 81fa63c55..86ecd7322 100644
--- a/soh/soh/SohMenuBar.cpp
+++ b/soh/soh/SohMenuBar.cpp
@@ -871,6 +871,10 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic");
UIWidgets::PaddedEnhancementCheckbox("Fish Never Escape", "gFishNeverEscape", true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("Once a hook has been set, fish will never let go while being reeled in.");
+ UIWidgets::PaddedEnhancementCheckbox("Loaches Always Appear", "gLoachesAlwaysAppear", true, false, disabled, disabledTooltip);
+ UIWidgets::Tooltip("Loaches will always appear in the fishing pond instead of every four visits.");
+ UIWidgets::PaddedEnhancementCheckbox("Skip Keep Confirmation", "gSkipKeepConfirmation", true, false, disabled, disabledTooltip);
+ UIWidgets::Tooltip("The pond owner will not ask to confirm if you want to keep a smaller fish.");
UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 3, 10, "", 10, true, true, false, disabled, disabledTooltip);
UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child");
UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 6, 13, "", 13, true, true, false, disabled, disabledTooltip);
diff --git a/soh/src/code/z_draw.c b/soh/src/code/z_draw.c
index e9ab95398..8dcd847ec 100644
--- a/soh/src/code/z_draw.c
+++ b/soh/src/code/z_draw.c
@@ -76,6 +76,7 @@
#include "objects/object_gi_dekupouch/object_gi_dekupouch.h"
#include "objects/object_gi_rupy/object_gi_rupy.h"
#include "objects/object_gi_sword_1/object_gi_sword_1.h"
+#include "objects/object_fish/object_fish.h"
#include "objects/object_st/object_st.h"
#include "soh_assets.h"
@@ -113,6 +114,7 @@ void GetItem_DrawJewelGoron(PlayState* play, s16 drawId);
void GetItem_DrawJewelZora(PlayState* play, s16 drawId);
void GetItem_DrawGenericMusicNote(PlayState* play, s16 drawId);
void GetItem_DrawTriforcePiece(PlayState* play, s16 drawId);
+void GetItem_DrawFishingPole(PlayState* play, s16 drawId);
typedef struct {
/* 0x00 */ void (*drawFunc)(PlayState*, s16);
@@ -388,7 +390,8 @@ DrawItemTableEntry sDrawItemTable[] = {
{ GetItem_DrawGenericMusicNote, { gGiSongNoteDL } }, //Sun's song
{ GetItem_DrawGenericMusicNote, { gGiSongNoteDL } }, //Song of time
{ GetItem_DrawGenericMusicNote, { gGiSongNoteDL } }, //Song of storms
- { GetItem_DrawTriforcePiece, { gTriforcePiece0DL } } // Triforce Piece
+ { GetItem_DrawTriforcePiece, { gTriforcePiece0DL } }, // Triforce Piece
+ { GetItem_DrawFishingPole, { gFishingPoleGiDL } }, // Fishing Pole
};
/**
@@ -1065,3 +1068,54 @@ void GetItem_DrawTriforcePiece(PlayState* play, s16 drawId) {
CLOSE_DISPS(play->state.gfxCtx);
}
+
+void GetItem_DrawFishingPole(PlayState* play, s16 drawId) {
+ Vec3f pos;
+ OPEN_DISPS(play->state.gfxCtx);
+
+ // Draw rod
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ Matrix_Scale(0.2, 0.2, 0.2, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingPoleGiDL);
+
+ // Draw lure
+ Matrix_Push();
+ Matrix_Scale(5.0f, 5.0f, 5.0f, MTXMODE_APPLY);
+ pos.x = 0.0f;
+ pos.y = -25.5f;
+ pos.z = -4.0f;
+ Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_APPLY);
+ Matrix_RotateZ(M_PI / -2, MTXMODE_APPLY);
+ Matrix_RotateY((M_PI / -2) - 0.2f, MTXMODE_APPLY);
+ Matrix_Scale(0.006f, 0.006f, 0.006f, MTXMODE_APPLY);
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureFloatDL);
+
+ // Draw hooks
+ Matrix_RotateY(0.2f, MTXMODE_APPLY);
+ Matrix_Translate(0.0f, 0.0f, -300.0f, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+ Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+
+ Matrix_Translate(0.0f, -2200.0f, 700.0f, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+ Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gFishingLureHookDL);
+
+ Matrix_Pop();
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
\ No newline at end of file
diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 141dbaf6a..7abc2b151 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -2644,6 +2644,11 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
return Return_Item_Entry(giEntry, RG_NONE);
}
+ if (item == RG_FISHING_POLE) {
+ Flags_SetRandomizerInf(RAND_INF_FISHING_POLE_FOUND);
+ return Return_Item_Entry(giEntry, RG_NONE);
+ }
+
if (item == RG_PROGRESSIVE_BOMBCHUS) {
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
diff --git a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c
index 785d1fbca..e777d993f 100644
--- a/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c
+++ b/soh/src/overlays/actors/ovl_En_Fish/z_en_fish.c
@@ -7,6 +7,7 @@
#include "z_en_fish.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "vt.h"
+#include "soh/Enhancements/randomizer/fishsanity.h"
#define FLAGS 0
@@ -36,6 +37,7 @@ void EnFish_Unique_SwimIdle(EnFish* this, PlayState* play);
static Actor* D_80A17010 = NULL;
static f32 D_80A17014 = 0.0f;
static f32 D_80A17018 = 0.0f;
+static Color_RGBA16 fsPulseColor = { 30, 240, 200 };
static ColliderJntSphElementInit sJntSphElementsInit[1] = {
{
@@ -760,10 +762,31 @@ void EnFish_Update(Actor* thisx, PlayState* play) {
}
}
+// #region SOH [Randomizer]
+s32 EnFish_FishsanityOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
+ void* thisx) {
+ EnFish* this = (EnFish*)thisx;
+ Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, ABS(this->actor.params) * 20);
+ return 0;
+}
+
+void EnFish_FishPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
+ Fishsanity_CloseGreyscaleColor(play);
+}
+// #endregion
+
void EnFish_Draw(Actor* thisx, PlayState* play) {
EnFish* this = (EnFish*)thisx;
Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ // #region SOH [Randomizer]
+ // Modify drawing for uncollected fish, having a shadowDraw implies this is being given uncollected FX
+ if (IS_RANDO && Randomizer_GetOverworldFishShuffled() && this->actor.shape.shadowDraw != NULL) {
+ SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnFish_FishsanityOverrideLimbDraw, EnFish_FishPostLimbDraw, this);
+ Collider_UpdateSpheres(0, &this->collider);
+ return;
+ }
+ // #endregion
SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, NULL, NULL, NULL);
Collider_UpdateSpheres(0, &this->collider);
-}
+}
\ No newline at end of file
diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c
index 3f8de83ba..1dd16e6da 100644
--- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.c
+++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.c
@@ -15,6 +15,8 @@
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
#define WATER_SURFACE_Y(play) play->colCtx.colHeader->waterBoxes->ySurface
+#define IS_FISHSANITY (IS_RANDO && Randomizer_GetPondFishShuffled())
+#define FISHID(params) (Randomizer_IdentifyFish(play->sceneNum, params))
void Fishing_Init(Actor* thisx, PlayState* play);
void Fishing_Destroy(Actor* thisx, PlayState* play);
@@ -24,14 +26,14 @@ void Fishing_DrawFish(Actor* thisx, PlayState* play);
void Fishing_DrawOwner(Actor* thisx, PlayState* play);
void Fishing_Reset(void);
-typedef struct {
- /* 0x00 */ u8 unk_00;
- /* 0x02 */ Vec3s pos;
- /* 0x08 */ u8 unk_08;
- /* 0x0C */ f32 unk_0C;
-} FishingFishInit; // size = 0x10
+bool getShouldSpawnLoaches();
-#define EFFECT_COUNT 130
+typedef struct {
+ /* 0x00 */ u8 isLoach;
+ /* 0x02 */ Vec3s pos;
+ /* 0x08 */ u8 baseLength;
+ /* 0x0C */ f32 perception;
+} FishingFishInit; // size = 0x10
typedef enum {
/* 0x00 */ FS_EFF_NONE,
@@ -45,6 +47,8 @@ typedef enum {
/* 0x08 */ FS_EFF_RAIN_SPLASH
} FishingEffectType;
+#define FISHING_EFFECT_COUNT 130
+
typedef struct {
/* 0x00 */ Vec3f pos;
/* 0x0C */ Vec3f vel;
@@ -53,12 +57,10 @@ typedef struct {
/* 0x25 */ u8 timer;
/* 0x26 */ char unk_26[0x04];
/* 0x2A */ s16 alpha;
- /* 0x2C */ s16 unk_2C;
- /* 0x2E */ s16 unk_2E;
- /* 0x30 */ f32 unk_30;
- /* 0x34 */ f32 unk_34;
- /* 0x38 */ f32 unk_38;
- /* 0x3C */ f32 unk_3C;
+ /* 0x2C */ s16 state;
+ /* 0x2E */ s16 alphaMax;
+ /* 0x30 */ f32 scale;
+ /* 0x34 */ Vec3f rot;
u32 epoch;
} FishingEffect; // size = 0x40
@@ -105,10 +107,10 @@ typedef struct {
/* 0x00 */ u8 type;
/* 0x02 */ s16 timer;
/* 0x04 */ Vec3f pos;
- /* 0x10 */ Vec3f unk_10;
+ /* 0x10 */ Vec3f homePos;
/* 0x1C */ Vec3f projectedPos;
- /* 0x28 */ f32 unk_28;
- /* 0x2C */ f32 unk_2C;
+ /* 0x28 */ f32 velY;
+ /* 0x2C */ f32 scaleX;
/* 0x30 */ f32 unk_30;
/* 0x34 */ f32 unk_34;
/* 0x38 */ f32 unk_38;
@@ -120,6 +122,12 @@ typedef struct {
u32 epoch;
} FishingGroupFish; // size = 0x48
+typedef enum {
+ /* 0x00 */ FS_LURE_STOCK,
+ /* 0x01 */ FS_LURE_UNK, // hinted at with an "== 1"
+ /* 0x02 */ FS_LURE_SINKING
+} FishingLureTypes;
+
#define LINE_SEG_COUNT 200
#define SINKING_LURE_SEG_COUNT 20
@@ -136,42 +144,48 @@ const ActorInit Fishing_InitVars = {
(ActorResetFunc)Fishing_Reset,
};
-static f32 D_80B7A650 = 0.0f;
+static f32 sStormStrength = 0.0f;
-static u8 D_80B7A654 = 0;
+static u8 sStormStrengthTarget = 0;
-static f32 D_80B7A658 = 0.0f;
+static f32 sFishingStormShade = 0.0f;
-static Vec3f D_80B7A65C = { 0.0f, 0.0f, 0.0f };
+static Vec3f sFishingStormSfxPos = { 0.0f, 0.0f, 0.0f };
-static f32 D_80B7A668 = 0.0f;
+static f32 sStormSfxFreqScale = 0.0f;
static u8 sSinkingLureLocation = 0;
/// Weight of caught fish.
-static f32 D_80B7A670 = 0.0f;
+static f32 sFishOnHandLength = 0.0f;
-static u8 D_80B7A674 = true;
+static u8 sIsRodVisible = true;
-static u16 D_80B7A678 = 0;
+static u16 sFishLengthToWeigh = 0;
-static u8 D_80B7A67C = 0;
+static u8 sFishingCaughtTextDelay = 0;
-static s32 D_80B7A680 = 0;
+static s32 sFishingTimePlayed = 0;
-static s16 D_80B7A684 = 0;
+static s16 sOwnerTheftTimer = 0;
-static u8 D_80B7A688 = 0;
-static u8 D_80B7A68C = 0;
-static u8 D_80B7A690 = 0;
+typedef enum {
+ /* 0x00 */ FS_OWNER_BALD,
+ /* 0x01 */ FS_OWNER_CAPPED,
+ /* 0x02 */ FS_OWNER_HAIR
+} FishingOwnerHair;
-static s16 D_80B7A694 = 0;
+static u8 sOwnerHair = FS_OWNER_BALD;
+static u8 sIsOwnersHatHooked = false; // hat is on fishing hook
+static u8 sIsOwnersHatSunk = false; // hat is sinking into pond.
+
+static s16 sRodCastState = 0;
static Vec3f sFishMouthOffset = { 500.0f, 500.0f, 0.0f };
static u8 D_80B7A6A4 = 0;
-static f32 D_80B7A6A8 = 0.0f;
+static f32 sRodBendRotY = 0.0f;
static f32 D_80B7A6AC = 0.0f;
static f32 D_80B7A6B0 = 0.0f;
static f32 D_80B7A6B4 = 0.0f;
@@ -179,12 +193,12 @@ static f32 D_80B7A6B8 = 0.0f;
static f32 D_80B7A6BC = 0.0f;
static f32 D_80B7A6C0 = 0.0f;
-static s16 D_80B7A6C4 = 0;
-static s16 D_80B7A6C8 = 0;
+static s16 sStickAdjXPrev = 0;
+static s16 sStickAdjYPrev = 0;
-static u8 D_80B7A6CC = 0;
-static u8 D_80B7A6D0 = 0;
-static u8 D_80B7A6D4 = 0;
+static u8 sFishingPlayerCinematicState = 0;
+static u8 sFishingCinematicTimer = 0;
+static u8 sSinkingLureFound = false;
static ColliderJntSphElementInit sJntSphElementsInit[12] = {
{
@@ -334,81 +348,81 @@ static ColliderJntSphInit sJntSphInit = {
sJntSphElementsInit,
};
-static f32 D_80B7A898 = 0.0f;
+static f32 sFishGroupVar = 0.0f;
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
-static Vec3f D_80B7A8A8 = { 0.0f, 0.0f, 2000.0f };
+static Vec3f sUnusedVec = { 0.0f, 0.0f, 2000.0f };
static Fishing* sFishingMain;
-static u8 D_80B7E074;
+static u8 sReelLock;
static u8 sLinkAge;
-static u8 D_80B7E076;
-static u8 D_80B7E077;
-static f32 D_80B7E078;
-static u8 D_80B7E07C;
-static u8 D_80B7E07D;
-static u8 D_80B7E07E;
-static s16 D_80B7E080;
-static u8 D_80B7E082;
-static u16 D_80B7E084;
-static u16 D_80B7E086;
-static s8 D_80B7E088;
+static u8 sFishingFoggy;
+static u8 sStormChanceTimer;
+static f32 sFishingRecordLength;
+static u8 sFishOnHandIsLoach;
+static u8 sFishGameNumber; // increments for each purchased play. effects weather
+static u8 sLureCaughtWith;
+static s16 sFishFightTime;
+static u8 sPondOwnerTextIdIndex;
+static u16 sFishesCaught;
+static u16 sFishingCaughtTextId;
+static s8 sLureCameraZoomLevel;
static Vec3f sOwnerHeadPos;
-static Vec3s sEffOwnerHatRot;
-static u8 D_80B7E0A2;
-static s16 D_80B7E0A4;
-static s16 D_80B7E0A6;
+static Vec3s sEffOwnersHatRot;
+static u8 sLureMoveDelay; // a small delay between the lure hitting the water, and being able to reel.
+static s16 sRumbleDelay;
+static s16 sFishingMusicDelay;
static Fishing* sFishingHookedFish;
-static s16 D_80B7E0AC;
-static s16 D_80B7E0AE;
+static s16 sFishingPlayingState;
+static s16 sLureTimer; // AND'd for various effects/checks
static s16 D_80B7E0B0;
static s16 D_80B7E0B2;
-static s16 D_80B7E0B4;
-static u8 D_80B7E0B6;
+static s16 sRodCastTimer; // used for the inital line casting
+static u8 sLureEquipped;
static Vec3f sLurePos;
-static Vec3f D_80B7E0C8;
+static Vec3f sLureDrawPos;
static Vec3f sLureRot;
-static Vec3f D_80B7E0E8;
-static Vec3f D_80B7E0F8;
-static f32 D_80B7E104;
-static f32 D_80B7E108;
-static f32 D_80B7E10C;
-static f32 D_80B7E110;
+static Vec3f sLurePosDelta;
+static Vec3f sLureCastDelta;
+static f32 sLure1Rotate; // lure type 1 is programmed to change this.
+static f32 sLurePosZOffset;
+static f32 sLureRotXTarget;
+static f32 sLureRotXStep;
static s8 D_80B7E114;
-static s16 D_80B7E116;
+static s16 sRodPullback; // holding A+Down to keep the fish on line
static u8 D_80B7E118;
-static f32 D_80B7E11C;
-static u8 D_80B7E120;
-static s16 D_80B7E122;
-static u8 D_80B7E124;
-static Vec3f D_80B7E128;
-static f32 D_80B7E134;
-static f32 D_80B7E138;
-static s16 D_80B7E13C;
-static f32 D_80B7E140;
-static f32 D_80B7E144;
+static f32 sRodReelingSpeed;
+static u8 sWiggleAttraction;
+static s16 sLureBitTimer;
+static u8 sLineHooked;
+static Vec3f sLureLineSegPosDelta;
+static f32 sLureWiggleRotYTarget;
+static f32 sLureWigglePosY;
+static s16 sLureWiggleRotY;
+static f32 sLureWiggleSign; // +/-1.0f
+static f32 sRodLineSpooled; // 200 represents the full spool.
static f32 D_80B7E148;
-static f32 D_80B7E14C;
+static f32 sFishingLineScale;
static s16 D_80B7E150;
-static f32 D_80B7E154;
+static f32 sReelLinePosStep;
static Vec3f sRodTipPos;
static Vec3f sReelLinePos[LINE_SEG_COUNT];
static Vec3f sReelLineRot[LINE_SEG_COUNT];
static Vec3f sReelLineUnk[LINE_SEG_COUNT];
static Vec3f sLureHookRefPos[2];
static f32 sLureHookRotY[2];
-static u8 D_80B7FDA8;
+static u8 sRodHitTimer; // brief timer for bending rod when line is snapped
static Vec3f sSinkingLurePos[SINKING_LURE_SEG_COUNT];
-static s16 D_80B7FEA0;
+static s16 sSinkingLureSegmentIndex;
static f32 sProjectedW;
static Vec3f sCameraEye;
static Vec3f sCameraAt;
-static s16 sCameraId;
-static f32 D_80B7FEC8;
-static f32 D_80B7FECC;
+static s16 sSubCamId;
+static f32 sCatchCamX;
+static f32 sSubCamVelFactor;
static f32 D_80B7FED0;
static Vec3f sSinkingLureBasePos;
-static f32 D_80B7FEE4;
+static f32 sSinkingLureHeldY; // the lure going to its mark when being held up.
static s32 sRandSeed0;
static s32 sRandSeed1;
static s32 sRandSeed2;
@@ -417,8 +431,10 @@ static FishingGroupFish sGroupFishes[GROUP_FISH_COUNT];
static f32 sFishGroupAngle1;
static f32 sFishGroupAngle2;
static f32 sFishGroupAngle3;
-static FishingEffect sFishingEffects[EFFECT_COUNT];
+static FishingEffect sFishingEffects[FISHING_EFFECT_COUNT];
static Vec3f sStreamSoundProjectedPos;
+static s16 sFishOnHandParams;
+static Color_RGBA16 fsPulseColor = { 30, 240, 200 };
void Fishing_SetColliderElement(s32 index, ColliderJntSph* collider, Vec3f* pos, f32 scale) {
collider->elements[index].dim.worldSphere.center.x = pos->x;
@@ -470,7 +486,7 @@ s16 Fishing_SmoothStepToS(s16* pValue, s16 target, s16 scale, s16 step) {
return stepSize;
}
-void Fishing_SpawnRipple(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 arg3, f32 arg4, s16 arg5,
+void Fishing_SpawnRipple(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 scale, f32 rotX, s16 alpha,
s16 countLimit) {
s16 i;
@@ -484,18 +500,18 @@ void Fishing_SpawnRipple(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos,
effect->pos = *pos;
effect->vel = sZeroVec;
effect->accel = sZeroVec;
- effect->unk_30 = arg3 * 0.0025f;
- effect->unk_34 = arg4 * 0.0025f;
+ effect->scale = scale * 0.0025f;
+ effect->rot.x = rotX * 0.0025f;
- if (arg3 > 300.0f) {
+ if (scale > 300.0f) {
effect->alpha = 0;
- effect->unk_2E = arg5;
- effect->unk_2C = 0;
- effect->unk_38 = (effect->unk_34 - effect->unk_30) * 0.05f;
+ effect->alphaMax = alpha;
+ effect->state = 0;
+ effect->rot.y = (effect->rot.x - effect->scale) * 0.05f;
} else {
- effect->alpha = arg5;
- effect->unk_2C = 1;
- effect->unk_38 = (effect->unk_34 - effect->unk_30) * 0.1f;
+ effect->alpha = alpha;
+ effect->state = 1;
+ effect->rot.y = (effect->rot.x - effect->scale) * 0.1f;
}
effect->epoch++;
@@ -522,7 +538,7 @@ void Fishing_SpawnDustSplash(Vec3f* projectedPos, FishingEffect* effect, Vec3f*
effect->vel = *vel;
effect->accel = accel;
effect->alpha = 100 + (s16)Rand_ZeroFloat(100.0f);
- effect->unk_30 = scale;
+ effect->scale = scale;
effect->epoch++;
break;
}
@@ -547,8 +563,8 @@ void Fishing_SpawnWaterDust(Vec3f* projectedPos, FishingEffect* effect, Vec3f* p
effect->accel = accel;
effect->alpha = 255;
effect->timer = (s16)Rand_ZeroFloat(100.0f);
- effect->unk_30 = scale;
- effect->unk_34 = 2.0f * scale;
+ effect->scale = scale;
+ effect->rot.x = 2.0f * scale;
effect->epoch++;
break;
}
@@ -557,7 +573,7 @@ void Fishing_SpawnWaterDust(Vec3f* projectedPos, FishingEffect* effect, Vec3f* p
}
}
-void Fishing_SpawnBubble(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 scale, u8 arg4) {
+void Fishing_SpawnBubble(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 scale, u8 state) {
s16 i;
Vec3f vel = { 0.0f, 1.0f, 0.0f };
@@ -572,8 +588,8 @@ void Fishing_SpawnBubble(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos,
effect->vel = vel;
effect->accel = sZeroVec;
effect->timer = (s16)Rand_ZeroFloat(100.0f);
- effect->unk_30 = scale;
- effect->unk_2C = arg4;
+ effect->scale = scale;
+ effect->state = state;
effect->epoch++;
break;
}
@@ -592,14 +608,14 @@ void Fishing_SpawnRainDrop(FishingEffect* effect, Vec3f* pos, Vec3f* rot) {
effect += 30;
- for (i = 30; i < EFFECT_COUNT; i++) {
+ for (i = 30; i < FISHING_EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_NONE) {
effect->type = FS_EFF_RAIN_DROP;
effect->pos = *pos;
effect->accel = sZeroVec;
- effect->unk_34 = rot->x;
- effect->unk_38 = rot->y;
- effect->unk_3C = rot->z;
+ effect->rot.x = rot->x;
+ effect->rot.y = rot->y;
+ effect->rot.z = rot->z;
Matrix_RotateY(rot->y, MTXMODE_NEW);
Matrix_RotateX(rot->x, MTXMODE_APPLY);
Matrix_MultVec3f(&velSrc, &effect->vel);
@@ -781,7 +797,7 @@ void Fishing_InitPondProps(Fishing* this, PlayState* play) {
if (prop->type == FS_PROP_REED) {
prop->scale = (Fishing_RandZeroOne() * 0.25f) + 0.75f;
prop->reedAngle = Rand_ZeroFloat(2 * M_PI);
- if (sLinkAge == 1) {
+ if (sLinkAge == LINK_AGE_CHILD) {
prop->scale *= 0.6f;
}
prop->drawDistance = 1200.0f;
@@ -794,7 +810,7 @@ void Fishing_InitPondProps(Fishing* this, PlayState* play) {
} else if (prop->type == FS_PROP_LILY_PAD) {
prop->scale = (Fishing_RandZeroOne() * 0.3f) + 0.5f;
prop->rotY = Rand_ZeroFloat(2 * M_PI);
- if (sLinkAge == 1) {
+ if (sLinkAge == LINK_AGE_CHILD) {
if ((i % 4) != 0) {
prop->scale *= 0.6f;
} else {
@@ -836,18 +852,18 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f);
if (KREG(5) != 0) {
- sLinkAge = 1;
+ sLinkAge = LINK_AGE_CHILD;
} else {
sLinkAge = gSaveContext.linkAge;
}
- if (thisx->params < 100) {
- D_80B7E074 = 0;
+ if (thisx->params < EN_FISH_PARAM) {
+ sReelLock = 0;
sFishingMain = this;
Collider_InitJntSph(play, &sFishingMain->collider);
Collider_SetJntSph(play, &sFishingMain->collider, thisx, &sJntSphInit, sFishingMain->colliderElements);
- thisx->params = 1;
+ thisx->params = EN_FISH_OWNER;
SkelAnime_InitFlex(play, &this->skelAnime, &gFishingOwnerSkel, &gFishingOwnerAnim, NULL, NULL, 0);
Animation_MorphToLoop(&this->skelAnime, &gFishingOwnerAnim, 0.0f);
@@ -866,59 +882,59 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
thisx->focus.pos.y += 75.0f;
thisx->flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY;
- if (sLinkAge != 1) {
- if (HIGH_SCORE(HS_FISHING) & 0x1000) {
- D_80B7A688 = 0;
+ if (sLinkAge != LINK_AGE_CHILD) {
+ if (HIGH_SCORE(HS_FISHING) & HS_FISH_STOLE_HAT) {
+ sOwnerHair = FS_OWNER_BALD;
} else {
- D_80B7A688 = 1;
+ sOwnerHair = FS_OWNER_CAPPED;
}
} else {
- D_80B7A688 = 2;
+ sOwnerHair = FS_OWNER_HAIR;
}
- D_80B7A684 = 20;
+ sOwnerTheftTimer = 20;
play->specialEffects = sFishingEffects;
gTimeIncrement = 1;
- D_80B7E0AC = 0;
- D_80B7E0A6 = 10;
+ sFishingPlayingState = 0;
+ sFishingMusicDelay = 10;
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x0100FF);
- if (sLinkAge == 1) {
- if ((HIGH_SCORE(HS_FISHING) & 0x7F) != 0) {
- D_80B7E078 = HIGH_SCORE(HS_FISHING) & 0x7F;
+ if (sLinkAge == LINK_AGE_CHILD) {
+ if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD) != 0) {
+ sFishingRecordLength = HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD;
} else {
- D_80B7E078 = 40.0f;
+ sFishingRecordLength = 40.0f; // 6 lbs
}
} else {
- if ((HIGH_SCORE(HS_FISHING) & 0x7F000000) != 0) {
- D_80B7E078 = (HIGH_SCORE(HS_FISHING) & 0x7F000000) >> 0x18;
+ if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) != 0) {
+ sFishingRecordLength = (HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) >> 0x18;
} else {
- D_80B7E078 = 45.0f;
+ sFishingRecordLength = 45.0f; // 7 lbs
}
}
- D_80B7E07D = (HIGH_SCORE(HS_FISHING) & 0xFF0000) >> 0x10;
- if ((D_80B7E07D & 7) == 7) {
+ sFishGameNumber = (HIGH_SCORE(HS_FISHING) & (HS_FISH_PLAYED * 255)) >> 0x10;
+ if ((sFishGameNumber & 7) == 7) {
play->roomCtx.unk_74[0] = 90;
- D_80B7E076 = 1;
+ sFishingFoggy = 1;
} else {
play->roomCtx.unk_74[0] = 40;
- D_80B7E076 = 0;
+ sFishingFoggy = 0;
}
- if (((D_80B7E07D & 7) == 6) || (KREG(3) != 0)) {
- D_80B7E077 = 100;
+ if (((sFishGameNumber & 7) == 6) || (KREG(3) != 0)) {
+ sStormChanceTimer = 100;
if (KREG(3) != 0) {
KREG(3) = 0;
- HIGH_SCORE(HS_FISHING) &= 0xFF00FFFF;
- HIGH_SCORE(HS_FISHING) |= 0x60000;
+ HIGH_SCORE(HS_FISHING) &= ~(HS_FISH_PLAYED * 255);
+ HIGH_SCORE(HS_FISHING) |= (HS_FISH_PLAYED * 6);
}
} else {
- D_80B7E077 = 0;
+ sStormChanceTimer = 0;
}
- for (i = 0; i < EFFECT_COUNT; i++) {
+ for (i = 0; i < FISHING_EFFECT_COUNT; i++) {
sFishingEffects[i].type = FS_EFF_NONE;
}
@@ -938,17 +954,17 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
fish->type = FS_GROUP_FISH_NORMAL;
if (i <= 20) {
- fish->unk_10.x = fish->pos.x = sinf(sFishGroupAngle1) * 720.0f;
- fish->unk_10.z = fish->pos.z = cosf(sFishGroupAngle1) * 720.0f;
+ fish->homePos.x = fish->pos.x = sinf(sFishGroupAngle1) * 720.0f;
+ fish->homePos.z = fish->pos.z = cosf(sFishGroupAngle1) * 720.0f;
} else if (i <= 40) {
- fish->unk_10.x = fish->pos.x = sinf(sFishGroupAngle2) * 720.0f;
- fish->unk_10.z = fish->pos.z = cosf(sFishGroupAngle2) * 720.0f;
+ fish->homePos.x = fish->pos.x = sinf(sFishGroupAngle2) * 720.0f;
+ fish->homePos.z = fish->pos.z = cosf(sFishGroupAngle2) * 720.0f;
} else {
- fish->unk_10.x = fish->pos.x = sinf(sFishGroupAngle3) * 720.0f;
- fish->unk_10.z = fish->pos.z = cosf(sFishGroupAngle3) * 720.0f;
+ fish->homePos.x = fish->pos.x = sinf(sFishGroupAngle3) * 720.0f;
+ fish->homePos.z = fish->pos.z = cosf(sFishGroupAngle3) * 720.0f;
}
- fish->unk_10.y = fish->pos.y = -35.0f;
+ fish->homePos.y = fish->pos.y = -35.0f;
fish->timer = Rand_ZeroFloat(100.0f);
@@ -956,7 +972,7 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
fish->unk_3E = 0;
fish->unk_40 = 0;
- if (sLinkAge != 1) {
+ if (sLinkAge != LINK_AGE_CHILD) {
if (((i >= 15) && (i < 20)) || ((i >= 35) && (i < 40)) || ((i >= 55) && (i < 60))) {
fish->type = FS_GROUP_FISH_NONE;
}
@@ -968,8 +984,10 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
ENKANBAN_FISHING);
Actor_Spawn(&play->actorCtx, play, ACTOR_FISHING, 0.0f, 0.0f, 0.0f, 0, 0, 0, 200, true);
- if ((KREG(1) == 1) || ((D_80B7E07D & 3) == 3)) {
- if (sLinkAge != 1) {
+ // Loach(es) will spawn every fourth game, or if "Loaches Always Appear" is enabled
+ if (getShouldSpawnLoaches()) {
+ // Fishes 16 and 17 are loaches. Only 16 is spawned as adult; child also spawns 17.
+ if (sLinkAge != LINK_AGE_CHILD) {
fishCount = 16;
} else {
fishCount = 17;
@@ -983,7 +1001,7 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
sFishInits[i].pos.z, 0, Rand_ZeroFloat(0x10000), 0, 100 + i, true);
}
} else {
- if ((thisx->params < 115) || (thisx->params == 200)) {
+ if ((thisx->params < (EN_FISH_PARAM + 15)) || (thisx->params == EN_FISH_AQUARIUM)) {
SkelAnime_InitFlex(play, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, NULL, NULL, 0);
Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f);
} else {
@@ -993,32 +1011,34 @@ void Fishing_Init(Actor* thisx, PlayState* play2) {
SkelAnime_Update(&this->skelAnime);
- if (thisx->params == 200) {
- this->unk_158 = 100;
+ if (thisx->params == EN_FISH_AQUARIUM) {
+ this->fishState = 100;
Actor_ChangeCategory(play, &play->actorCtx, thisx, ACTORCAT_PROP);
thisx->targetMode = 0;
thisx->flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY;
this->lightNode = LightContext_InsertLight(play, &play->lightCtx, &this->lightInfo);
} else {
- this->unk_158 = 10;
- this->unk_15A = 10;
+ this->fishState = 10;
+ this->fishStateNext = 10;
- this->unk_150 = sFishInits[thisx->params - 100].unk_00;
- this->unk_1A8 = sFishInits[thisx->params - 100].unk_0C;
- this->unk_1AC = sFishInits[thisx->params - 100].unk_08;
+ this->isLoach = sFishInits[thisx->params - EN_FISH_PARAM].isLoach;
+ this->perception = sFishInits[thisx->params - EN_FISH_PARAM].perception;
+ this->fishLength = sFishInits[thisx->params - EN_FISH_PARAM].baseLength;
- this->unk_1AC += Rand_ZeroFloat(4.99999f);
+ this->fishLength += Rand_ZeroFloat(4.99999f);
- if ((this->unk_1AC >= 65.0f) && (Rand_ZeroOne() < 0.05f)) {
- this->unk_1AC += Rand_ZeroFloat(7.99999f);
+ // small chance to make big fish even bigger.
+ if ((this->fishLength >= 65.0f) && (Rand_ZeroOne() < 0.05f)) {
+ this->fishLength += Rand_ZeroFloat(7.99999f);
}
if (KREG(6) != 0) {
- this->unk_1AC = KREG(6) + 80.0f;
+ this->fishLength = KREG(6) + 80.0f;
}
- if (sLinkAge == 1) {
- this->unk_1AC *= 0.73f;
+ // "Come back when you get older! The fish will be bigger, too!"
+ if (sLinkAge == LINK_AGE_CHILD) {
+ this->fishLength *= 0.73f;
}
}
}
@@ -1030,9 +1050,9 @@ void Fishing_Destroy(Actor* thisx, PlayState* play2) {
SkelAnime_Free(&this->skelAnime, play);
- if (thisx->params == 200) {
+ if (thisx->params == EN_FISH_AQUARIUM) {
LightContext_RemoveLight(play, &play->lightCtx, this->lightNode);
- } else if (thisx->params == 1) {
+ } else if (thisx->params == EN_FISH_OWNER) {
Collider_DestroyJntSph(play, &this->collider);
}
}
@@ -1041,7 +1061,7 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
f32 rippleY;
s16 i;
- for (i = 0; i < EFFECT_COUNT; i++) {
+ for (i = 0; i < FISHING_EFFECT_COUNT; i++) {
if (effect->type) {
effect->timer++;
effect->pos.x += effect->vel.x;
@@ -1050,14 +1070,14 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
effect->vel.y += effect->accel.y;
if (effect->type == FS_EFF_RIPPLE) {
- Math_ApproachF(&effect->unk_30, effect->unk_34, 0.2f, effect->unk_38);
+ Math_ApproachF(&effect->scale, effect->rot.x, 0.2f, effect->rot.y);
- if (effect->unk_2C == 0) {
+ if (effect->state == 0) {
effect->alpha += 20;
- if (effect->alpha >= effect->unk_2E) {
- effect->alpha = effect->unk_2E;
- effect->unk_2C++;
+ if (effect->alpha >= effect->alphaMax) {
+ effect->alpha = effect->alphaMax;
+ effect->state++;
}
} else {
effect->alpha -= 8;
@@ -1067,7 +1087,7 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
}
}
} else if (effect->type == FS_EFF_WATER_DUST) {
- Math_ApproachF(&effect->unk_30, effect->unk_34, 0.1f, 0.1f);
+ Math_ApproachF(&effect->scale, effect->rot.x, 0.1f, 0.1f);
effect->alpha -= 10;
if (effect->pos.y > (WATER_SURFACE_Y(play) - 5.0f)) {
@@ -1080,7 +1100,7 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
effect->type = FS_EFF_NONE;
}
} else if (effect->type == FS_EFF_BUBBLE) {
- if (effect->unk_2C == 0) {
+ if (effect->state == 0) {
rippleY = WATER_SURFACE_Y(play);
} else {
rippleY = 69.0f;
@@ -1117,14 +1137,14 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
effect->pos.y = WATER_SURFACE_Y(play) + ((sqrtf(sqDistXZ) - 920.0f) * 0.11f);
effect->timer = KREG(17) + 2;
effect->type = FS_EFF_RAIN_SPLASH;
- effect->unk_30 = (KREG(18) + 30) * 0.001f;
+ effect->scale = (KREG(18) + 30) * 0.001f;
} else {
effect->pos.y = WATER_SURFACE_Y(play) + 3.0f;
effect->timer = 0;
if (Rand_ZeroOne() < 0.75f) {
effect->type = FS_EFF_RAIN_RIPPLE;
effect->vel = sZeroVec;
- effect->unk_30 = (KREG(18) + 30) * 0.001f;
+ effect->scale = (KREG(18) + 30) * 0.001f;
} else {
effect->type = FS_EFF_NONE;
}
@@ -1133,7 +1153,7 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
effect->vel = sZeroVec;
}
} else if (effect->type >= FS_EFF_RAIN_RIPPLE) {
- effect->unk_30 += (KREG(18) + 30) * 0.001f;
+ effect->scale += (KREG(18) + 30) * 0.001f;
if (effect->timer >= 6) {
effect->type = FS_EFF_NONE;
@@ -1142,11 +1162,11 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
f32 sqDistXZ;
f32 bottomY;
- effect->unk_30 = 0.010000001f;
+ effect->scale = 10 * .001f;
- Math_ApproachS(&sEffOwnerHatRot.y, 0, 20, 100);
- Math_ApproachS(&sEffOwnerHatRot.x, 0, 20, 100);
- Math_ApproachS(&sEffOwnerHatRot.z, -0x4000, 20, 100);
+ Math_ApproachS(&sEffOwnersHatRot.y, 0, 20, 100);
+ Math_ApproachS(&sEffOwnersHatRot.x, 0, 20, 100);
+ Math_ApproachS(&sEffOwnersHatRot.z, -0x4000, 20, 100);
sqDistXZ = SQ(effect->pos.x) + SQ(effect->pos.z);
bottomY = WATER_SURFACE_Y(play) + ((sqrtf(sqDistXZ) - 920.0f) * 0.147f);
@@ -1161,19 +1181,19 @@ void Fishing_UpdateEffects(FishingEffect* effect, PlayState* play) {
Fishing_SpawnRipple(NULL, play->specialEffects, &pos, 30.0f, 300.0f, 150, 90);
}
- if (effect->unk_2C >= 0) {
- effect->unk_2C++;
+ if (effect->state >= 0) {
+ effect->state++;
}
- if (effect->unk_2C == 30) {
+ if (effect->state == 30) {
Message_StartTextbox(play, 0x40B3, NULL);
}
- if ((effect->unk_2C >= 100) && (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT)) {
+ if ((effect->state >= 100) && (Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT)) {
if (Message_ShouldAdvance(play) || (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE)) {
Message_CloseTextbox(play);
Rupees_ChangeBy(-50);
- effect->unk_2C = -1;
+ effect->state = -1;
}
}
}
@@ -1208,7 +1228,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, effect->alpha);
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
- Matrix_Scale(effect->unk_30, 1.0f, effect->unk_30, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, 1.0f, effect->scale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1234,7 +1254,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
- Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1264,7 +1284,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
- Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1289,7 +1309,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
- Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1302,7 +1322,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
effect = firstEffect + 30;
flag = 0;
- for (i = 30; i < EFFECT_COUNT; i++) {
+ for (i = 30; i < FISHING_EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_RAIN_DROP) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
@@ -1313,9 +1333,9 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
}
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
- Matrix_RotateY(effect->unk_38, MTXMODE_APPLY);
- Matrix_RotateX(effect->unk_34, MTXMODE_APPLY);
- Matrix_RotateZ(effect->unk_3C, MTXMODE_APPLY);
+ Matrix_RotateY(effect->rot.y, MTXMODE_APPLY);
+ Matrix_RotateX(effect->rot.x, MTXMODE_APPLY);
+ Matrix_RotateZ(effect->rot.z, MTXMODE_APPLY);
Matrix_Scale(0.002f, 1.0f, 0.1f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
@@ -1331,7 +1351,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
effect = firstEffect + 30;
flag = 0;
- for (i = 30; i < EFFECT_COUNT; i++) {
+ for (i = 30; i < FISHING_EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_RAIN_RIPPLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
@@ -1342,7 +1362,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
}
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
- Matrix_Scale(effect->unk_30, 1.0f, effect->unk_30, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, 1.0f, effect->scale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1355,7 +1375,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
effect = firstEffect + 30;
flag = 0;
- for (i = 30; i < EFFECT_COUNT; i++) {
+ for (i = 30; i < FISHING_EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_RAIN_SPLASH) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
@@ -1373,7 +1393,7 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
Matrix_RotateY(rotY, MTXMODE_APPLY);
- Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1388,10 +1408,10 @@ void Fishing_DrawEffects(FishingEffect* effect, PlayState* play) {
if (effect->type == FS_EFF_OWNER_HAT) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
- Matrix_RotateY((sEffOwnerHatRot.y * M_PI) / 32768, MTXMODE_APPLY);
- Matrix_RotateX((sEffOwnerHatRot.x * M_PI) / 32768, MTXMODE_APPLY);
- Matrix_RotateZ((sEffOwnerHatRot.z * M_PI) / 32768, MTXMODE_APPLY);
- Matrix_Scale(effect->unk_30, effect->unk_30, effect->unk_30, MTXMODE_APPLY);
+ Matrix_RotateY((sEffOwnersHatRot.y * M_PI) / 32768, MTXMODE_APPLY);
+ Matrix_RotateX((sEffOwnersHatRot.x * M_PI) / 32768, MTXMODE_APPLY);
+ Matrix_RotateZ((sEffOwnersHatRot.z * M_PI) / 32768, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, effect->scale, effect->scale, MTXMODE_APPLY);
Matrix_Translate(-1250.0f, 0.0f, 0.0f, MTXMODE_APPLY);
Matrix_RotateX(M_PI / 2, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
@@ -1427,7 +1447,7 @@ void Fishing_DrawStreamSplash(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
-s32 func_80B6C2EC(Vec3f* vec) {
+s32 Fishing_IsAboveCounter(Vec3f* vec) {
if (((vec->x >= 110.0f) && (vec->x <= 150.0f) && (vec->z <= 1400.0f) && (vec->z >= 1160.0f)) ||
((vec->x >= 110.0f) && (vec->x <= 210.0f) && (vec->z <= 1200.0f) && (vec->z >= 1160.0f))) {
if (vec->y <= 42.0f) {
@@ -1448,14 +1468,14 @@ void Fishing_UpdateLine(PlayState* play, Vec3f* basePos, Vec3f* pos, Vec3f* rot,
f32 ry;
f32 dist;
f32 spD8;
- s16 temp_s2;
+ s16 spooled;
s32 pad;
f32 temp_f20;
Vec3f posSrc = { 0.0f, 0.0f, 0.0f };
Vec3f posStep;
- f32 phi_f18;
- Vec3f spA4;
- Vec3f sp98;
+ f32 lineLength;
+ Vec3f tempPos;
+ Vec3f segPos;
f32 sp94;
f32 sp90;
f32 sp8C;
@@ -1465,36 +1485,36 @@ void Fishing_UpdateLine(PlayState* play, Vec3f* basePos, Vec3f* pos, Vec3f* rot,
f32 phi_f2;
if (D_80B7A6A4 != 0) {
- spA4 = *basePos;
- sp98 = pos[LINE_SEG_COUNT - 1];
+ tempPos = *basePos;
+ segPos = pos[LINE_SEG_COUNT - 1];
- sp94 = sp98.x - spA4.x;
- sp90 = sp98.y - spA4.y;
- sp8C = sp98.z - spA4.z;
+ sp94 = segPos.x - tempPos.x;
+ sp90 = segPos.y - tempPos.y;
+ sp8C = segPos.z - tempPos.z;
- phi_f18 = sqrtf(SQ(sp94) + SQ(sp90) + SQ(sp8C)) * 0.97f;
- if (phi_f18 > 1000.0f) {
- phi_f18 = 1000.0f;
+ lineLength = sqrtf(SQ(sp94) + SQ(sp90) + SQ(sp8C)) * 0.97f;
+ if (lineLength > 1000.0f) {
+ lineLength = 1000.0f;
}
- D_80B7E144 = 200.0f - (phi_f18 * 200.0f * 0.001f);
+ sRodLineSpooled = 200.0f - (lineLength * 200.0f * 0.001f);
}
- temp_s2 = D_80B7E144;
+ spooled = sRodLineSpooled;
posSrc.z = 5.0f;
for (i = 0; i < LINE_SEG_COUNT; i++) {
- if (i <= temp_s2) {
+ if (i <= spooled) {
pos[i] = *basePos;
} else if (D_80B7A6A4 != 0) {
- temp_f20 = (f32)(i - temp_s2) / (f32)(LINE_SEG_COUNT - temp_s2 + 1);
- Math_ApproachF(&pos[i].x, (sp94 * temp_f20) + spA4.x, 1.0f, 20.0f);
- Math_ApproachF(&pos[i].y, (sp90 * temp_f20) + spA4.y, 1.0f, 20.0f);
- Math_ApproachF(&pos[i].z, (sp8C * temp_f20) + spA4.z, 1.0f, 20.0f);
+ temp_f20 = (f32)(i - spooled) / (f32)(LINE_SEG_COUNT - spooled + 1);
+ Math_ApproachF(&pos[i].x, (sp94 * temp_f20) + tempPos.x, 1.0f, 20.0f);
+ Math_ApproachF(&pos[i].y, (sp90 * temp_f20) + tempPos.y, 1.0f, 20.0f);
+ Math_ApproachF(&pos[i].z, (sp8C * temp_f20) + tempPos.z, 1.0f, 20.0f);
}
}
- for (i = temp_s2 + 1, k = 0; i < LINE_SEG_COUNT; i++, k++) {
+ for (i = spooled + 1, k = 0; i < LINE_SEG_COUNT; i++, k++) {
temp_f18 = 2.0f * D_80B7E148;
dx = (pos + i)->x - (pos + i - 1)->x;
@@ -1508,7 +1528,7 @@ void Fishing_UpdateLine(PlayState* play, Vec3f* basePos, Vec3f* pos, Vec3f* rot,
phi_f12 = WATER_SURFACE_Y(play);
}
- if (D_80B7E0B6 == 2) {
+ if (sLureEquipped == FS_LURE_SINKING) {
if (spD8 < phi_f12) {
phi_f12 = ((sqrtf(sqDistXZ) - 920.0f) * 0.147f) + WATER_SURFACE_Y(play);
if (spD8 > phi_f12) {
@@ -1538,7 +1558,7 @@ void Fishing_UpdateLine(PlayState* play, Vec3f* basePos, Vec3f* pos, Vec3f* rot,
}
}
- if (func_80B6C2EC(&pos[i])) {
+ if (Fishing_IsAboveCounter(&pos[i])) {
spD8 = 42.0f;
}
@@ -1572,11 +1592,11 @@ void Fishing_UpdateLinePos(Vec3f* pos) {
f32 dist;
Vec3f posSrc = { 0.0f, 0.0f, 0.0f };
Vec3f posStep;
- s16 min = D_80B7E144;
+ s16 spooled = sRodLineSpooled;
posSrc.z = 5.0f;
- for (i = LINE_SEG_COUNT - 2; i > min; i--) {
+ for (i = LINE_SEG_COUNT - 2; i > spooled; i--) {
dx = (pos + i)->x - (pos + i + 1)->x;
dy = (pos + i)->y - (pos + i + 1)->y;
dz = (pos + i)->z - (pos + i + 1)->z;
@@ -1611,7 +1631,7 @@ void Fishing_DrawLureHook(PlayState* play, Vec3f* pos, Vec3f* refPos, u8 hookInd
Matrix_Push();
- if ((D_80B7A694 == 3) && ((pos->y > WATER_SURFACE_Y(play)) || ((D_80B7A68C != 0) && hookIndex))) {
+ if ((sRodCastState == 3) && ((pos->y > WATER_SURFACE_Y(play)) || (sIsOwnersHatHooked && hookIndex))) {
offsetY = 0.0f;
} else if (pos->y < WATER_SURFACE_Y(play)) {
offsetY = -1.0f;
@@ -1637,7 +1657,7 @@ void Fishing_DrawLureHook(PlayState* play, Vec3f* pos, Vec3f* refPos, u8 hookInd
Matrix_Translate(pos->x, pos->y, pos->z, MTXMODE_NEW);
- if ((player->actor.speedXZ == 0.0f) && (D_80B7E138 == 0.0f)) {
+ if ((player->actor.speedXZ == 0.0f) && (sLureWigglePosY == 0.0f)) {
Math_ApproachF(&sLureHookRotY[hookIndex], ry, 0.1f, 0.3f);
} else {
sLureHookRotY[hookIndex] = ry;
@@ -1658,24 +1678,24 @@ void Fishing_DrawLureHook(PlayState* play, Vec3f* pos, Vec3f* refPos, u8 hookInd
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gFishingLureHookDL);
- if ((hookIndex == 1) && (D_80B7A68C != 0)) {
+ if ((hookIndex == 1) && (sIsOwnersHatHooked)) {
Matrix_Scale(2.0f, 2.0f, 2.0f, MTXMODE_APPLY);
Matrix_Translate(250.0f, 0.0f, -1400.0f, MTXMODE_APPLY);
Matrix_Push();
- if (D_80B7A690 != 0) {
+ if (sIsOwnersHatSunk) {
FishingEffect* effect = play->specialEffects;
MtxF mf;
Matrix_MultVec3f(&sZeroVec, &effect->pos);
Matrix_Get(&mf);
- Matrix_MtxFToYXZRotS(&mf, &sEffOwnerHatRot, 0);
+ Matrix_MtxFToYXZRotS(&mf, &sEffOwnersHatRot, 0);
- D_80B7A690 = 0;
- D_80B7A68C = 0;
+ sIsOwnersHatSunk = false;
+ sIsOwnersHatHooked = false;
effect->type = FS_EFF_OWNER_HAT;
- effect->unk_2C = 0;
+ effect->state = 0;
effect->vel = sZeroVec;
effect->accel = sZeroVec;
}
@@ -1715,7 +1735,7 @@ void Fishing_UpdateSinkingLure(PlayState* play) {
sSinkingLurePos[0] = sLurePos;
- if (D_80B7A6D4 != 0) {
+ if (sSinkingLureFound) {
offsetY = -1.0f;
} else if (sLurePos.y < WATER_SURFACE_Y(play)) {
offsetY = 0.5f;
@@ -1723,7 +1743,7 @@ void Fishing_UpdateSinkingLure(PlayState* play) {
offsetY = -5.0f;
}
- if (D_80B7A694 == 5) {
+ if (sRodCastState == 5) {
Matrix_RotateY(player->actor.shape.rot.y * (M_PI / 32768), MTXMODE_NEW);
sp94.x = 5.0f;
sp94.y = 0.0f;
@@ -1734,7 +1754,7 @@ void Fishing_UpdateSinkingLure(PlayState* play) {
for (i = 1; i < SINKING_LURE_SEG_COUNT; i++) {
Vec3f* pos = sSinkingLurePos;
- if ((i < 10) && (D_80B7A694 == 5)) {
+ if ((i < 10) && (sRodCastState == 5)) {
offsetX = (10 - i) * sp88.x * 0.1f;
offsetZ = (10 - i) * sp88.z * 0.1f;
} else {
@@ -1778,10 +1798,10 @@ void Fishing_DrawSinkingLure(PlayState* play) {
gSPDisplayList(POLY_OPA_DISP++, gFishingSinkingLureSegmentMaterialDL);
for (i = SINKING_LURE_SEG_COUNT - 1; i >= 0; i--) {
- if ((i + D_80B7FEA0) < SINKING_LURE_SEG_COUNT) {
+ if ((i + sSinkingLureSegmentIndex) < SINKING_LURE_SEG_COUNT) {
FrameInterpolation_RecordOpenChild("Fishing Lures 1", i);
Matrix_Translate(sSinkingLurePos[i].x, sSinkingLurePos[i].y, sSinkingLurePos[i].z, MTXMODE_NEW);
- scale = sSinkingLureSizes[i + D_80B7FEA0] * 0.04f;
+ scale = sSinkingLureSizes[i + sSinkingLureSegmentIndex] * 0.04f;
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
Matrix_ReplaceRotation(&play->billboardMtxF);
@@ -1797,10 +1817,10 @@ void Fishing_DrawSinkingLure(PlayState* play) {
gSPDisplayList(POLY_XLU_DISP++, gFishingSinkingLureSegmentMaterialDL);
for (i = SINKING_LURE_SEG_COUNT - 1; i >= 0; i--) {
- if ((i + D_80B7FEA0) < SINKING_LURE_SEG_COUNT) {
+ if ((i + sSinkingLureSegmentIndex) < SINKING_LURE_SEG_COUNT) {
FrameInterpolation_RecordOpenChild("Fishing Lures 2", i);
Matrix_Translate(sSinkingLurePos[i].x, sSinkingLurePos[i].y, sSinkingLurePos[i].z, MTXMODE_NEW);
- scale = sSinkingLureSizes[i + D_80B7FEA0] * 0.04f;
+ scale = sSinkingLureSizes[i + sSinkingLureSegmentIndex] * 0.04f;
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
Matrix_ReplaceRotation(&play->billboardMtxF);
@@ -1820,7 +1840,7 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
Vec3f posStep;
Vec3f hookPos[2];
s16 i;
- s16 spB4 = D_80B7E144;
+ s16 spooled = sRodLineSpooled;
s32 pad;
Player* player = GET_PLAYER(play);
@@ -1829,17 +1849,17 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
Gfx_SetupDL_25Opa(play->state.gfxCtx);
Matrix_Push();
- if (D_80B7A6D4 != 0) {
+ if (sSinkingLureFound) {
Vec3f posTemp = sLurePos;
sLurePos = sSinkingLureBasePos;
Fishing_DrawSinkingLure(play);
sLurePos = posTemp;
}
- if ((D_80B7A694 == 4) || (D_80B7A694 == 5)) {
+ if ((sRodCastState == 4) || (sRodCastState == 5)) {
sLurePos = sFishingHookedFish->fishMouthPos;
- if ((D_80B7A694 == 5) && (D_80B7E0B6 == 2)) {
+ if ((sRodCastState == 5) && (sLureEquipped == FS_LURE_SINKING)) {
Matrix_RotateY(player->actor.shape.rot.y * (M_PI / 32768), MTXMODE_NEW);
posSrc.x = 2.0f;
posSrc.y = 0.0f;
@@ -1848,7 +1868,7 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
sLurePos.x += posStep.x;
sLurePos.z += posStep.z;
}
- } else if (D_80B7A694 == 0) {
+ } else if (sRodCastState == 0) {
sLurePos = sReelLinePos[LINE_SEG_COUNT - 1];
sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI;
@@ -1859,12 +1879,12 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
}
}
- if (D_80B7E0B6 != 2) {
+ if (sLureEquipped != FS_LURE_SINKING) {
Matrix_Translate(sLurePos.x, sLurePos.y, sLurePos.z, MTXMODE_NEW);
- Matrix_RotateY(sLureRot.y + D_80B7E104, MTXMODE_APPLY);
+ Matrix_RotateY(sLureRot.y + sLure1Rotate, MTXMODE_APPLY);
Matrix_RotateX(sLureRot.x, MTXMODE_APPLY);
Matrix_Scale(0.0039999997f, 0.0039999997f, 0.0039999997f, MTXMODE_APPLY);
- Matrix_Translate(0.0f, 0.0f, D_80B7E108, MTXMODE_APPLY);
+ Matrix_Translate(0.0f, 0.0f, sLurePosZOffset, MTXMODE_APPLY);
Matrix_RotateZ(M_PI / 2, MTXMODE_APPLY);
Matrix_RotateY(M_PI / 2, MTXMODE_APPLY);
@@ -1877,7 +1897,7 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
posSrc.x = -850.0f;
posSrc.y = 0.0f;
posSrc.z = 0.0f;
- Matrix_MultVec3f(&posSrc, &D_80B7E0C8);
+ Matrix_MultVec3f(&posSrc, &sLureDrawPos);
posSrc.x = 500.0f;
posSrc.z = -300.0f;
@@ -1895,7 +1915,7 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
gDPSetCombineMode(POLY_XLU_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 55);
- if ((D_80B7A694 == 4) && ((D_80B7E124 != 0) || (D_80B7E0B6 != 2))) {
+ if ((sRodCastState == 4) && ((sLineHooked != 0) || (sLureEquipped != 2))) {
f32 rx;
f32 ry;
f32 dist;
@@ -1916,14 +1936,14 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
Matrix_Translate(sRodTipPos.x, sRodTipPos.y, sRodTipPos.z, MTXMODE_NEW);
Matrix_RotateY(ry, MTXMODE_APPLY);
Matrix_RotateX(rx, MTXMODE_APPLY);
- Matrix_Scale(D_80B7E14C, 1.0f, dist, MTXMODE_APPLY);
+ Matrix_Scale(sFishingLineScale, 1.0f, dist, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingLineModelDL);
} else {
- for (i = spB4; i < LINE_SEG_COUNT - 1; i++) {
- if ((i == LINE_SEG_COUNT - 3) && (D_80B7E0B6 == 0) && (D_80B7A694 == 3)) {
+ for (i = spooled; i < LINE_SEG_COUNT - 1; i++) {
+ if ((i == LINE_SEG_COUNT - 3) && (sLureEquipped == FS_LURE_STOCK) && (sRodCastState == 3)) {
f32 rx;
f32 ry;
f32 dist;
@@ -1931,9 +1951,9 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
f32 dy;
f32 dz;
- dx = D_80B7E0C8.x - (linePos + i)->x;
- dy = D_80B7E0C8.y - (linePos + i)->y;
- dz = D_80B7E0C8.z - (linePos + i)->z;
+ dx = sLureDrawPos.x - (linePos + i)->x;
+ dy = sLureDrawPos.y - (linePos + i)->y;
+ dz = sLureDrawPos.z - (linePos + i)->z;
ry = Math_FAtan2F(dx, dz);
dist = sqrtf(SQ(dx) + SQ(dz));
@@ -1944,7 +1964,7 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
Matrix_Translate((linePos + i)->x, (linePos + i)->y, (linePos + i)->z, MTXMODE_NEW);
Matrix_RotateY(ry, MTXMODE_APPLY);
Matrix_RotateX(rx, MTXMODE_APPLY);
- Matrix_Scale(D_80B7E14C, 1.0f, dist, MTXMODE_APPLY);
+ Matrix_Scale(sFishingLineScale, 1.0f, dist, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1955,7 +1975,7 @@ void Fishing_DrawLureAndLine(PlayState* play, Vec3f* linePos, Vec3f* lineRot) {
Matrix_Translate((linePos + i)->x, (linePos + i)->y, (linePos + i)->z, MTXMODE_NEW);
Matrix_RotateY((lineRot + i)->y, MTXMODE_APPLY);
Matrix_RotateX((lineRot + i)->x, MTXMODE_APPLY);
- Matrix_Scale(D_80B7E14C, 1.0f, 0.005f, MTXMODE_APPLY);
+ Matrix_Scale(sFishingLineScale, 1.0f, 0.005f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -1984,7 +2004,7 @@ static Vec3f sRodTipOffset = { 0.0f, 0.0f, 0.0f };
void Fishing_DrawRod(PlayState* play) {
s16 i;
- f32 spC8;
+ f32 lureXZLen;
f32 spC4;
f32 spC0;
Input* input = &play->state.input[0];
@@ -1993,8 +2013,8 @@ void Fishing_DrawRod(PlayState* play) {
OPEN_DISPS(play->state.gfxCtx);
- if (D_80B7FDA8 != 0) {
- D_80B7FDA8--;
+ if (sRodHitTimer != 0) {
+ sRodHitTimer--;
Math_ApproachF(&D_80B7A6C0, 35.0f, 1.0f, 100.0f);
Math_ApproachF(&D_80B7A6BC, -0.8f, 1.0f, 0.4f);
@@ -2002,8 +2022,8 @@ void Fishing_DrawRod(PlayState* play) {
} else {
s16 target = 0;
- if ((D_80B7A694 == 4) && (D_80B7E124 != 0)) {
- target = Math_SinS(D_80B7E0AE * 25600) * 1500.0f;
+ if ((sRodCastState == 4) && sLineHooked) {
+ target = Math_SinS(sLureTimer * 25600) * 1500.0f;
} else {
Math_ApproachZeroF(&D_80B7A6C0, 0.1f, 10.0f);
Math_ApproachZeroF(&D_80B7A6BC, 1.0f, 0.05f);
@@ -2012,17 +2032,17 @@ void Fishing_DrawRod(PlayState* play) {
Math_ApproachS(&player->actor.shape.rot.x, target, 5, 1000);
}
- if ((D_80B7A694 == 3) || (D_80B7A694 == 4)) {
- if ((input->rel.stick_x == 0) && (D_80B7A6C4 != 0)) {
+ if ((sRodCastState == 3) || (sRodCastState == 4)) {
+ if ((input->rel.stick_x == 0) && (sStickAdjXPrev != 0)) {
D_80B7A6B0 = 0.0f;
}
- if ((input->rel.stick_y == 0) && (D_80B7A6C8 != 0)) {
+ if ((input->rel.stick_y == 0) && (sStickAdjYPrev != 0)) {
D_80B7A6B4 = 0.0f;
}
- spC8 = player->unk_85C;
+ lureXZLen = player->unk_85C;
Math_SmoothStepToF(&player->unk_85C, input->rel.stick_y * 0.02f, 0.3f, 5.0f, 0.0f);
- spC8 = player->unk_85C - spC8;
+ lureXZLen = player->unk_85C - lureXZLen;
spC4 = player->unk_858;
Math_SmoothStepToF(&player->unk_858, input->rel.stick_x * 0.02f * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), 0.3f, 5.0f, 0.0f);
@@ -2041,18 +2061,18 @@ void Fishing_DrawRod(PlayState* play) {
player->unk_85C = -1.0f;
}
- Math_ApproachF(&D_80B7A6A8, spC4 * 70.0f * -0.01f, 1.0f, D_80B7A6B0);
+ Math_ApproachF(&sRodBendRotY, spC4 * 70.0f * -0.01f, 1.0f, D_80B7A6B0);
Math_ApproachF(&D_80B7A6B0, 1.0f, 1.0f, 0.1f);
- Math_ApproachF(&D_80B7A6AC, spC8 * 70.0f * 0.01f, 1.0f, D_80B7A6B4);
+ Math_ApproachF(&D_80B7A6AC, lureXZLen * 70.0f * 0.01f, 1.0f, D_80B7A6B4);
Math_ApproachF(&D_80B7A6B4, 1.0f, 1.0f, 0.1f);
Math_ApproachZeroF(&D_80B7A6B8, 1.0f, 0.05f);
} else {
Math_ApproachZeroF(&player->unk_85C, 1.0f, 0.1f);
Math_ApproachZeroF(&player->unk_858, 1.0f, 0.1f);
- Math_ApproachF(&D_80B7A6AC, (Math_SinS(D_80B7E0AE * 3000) * 0.025f) + -0.03f, 1.0f, 0.05f);
- Math_ApproachZeroF(&D_80B7A6A8, 1.0f, 0.05f);
+ Math_ApproachF(&D_80B7A6AC, (Math_SinS(sLureTimer * 3000) * 0.025f) + -0.03f, 1.0f, 0.05f);
+ Math_ApproachZeroF(&sRodBendRotY, 1.0f, 0.05f);
- if ((D_80B7E0B4 >= 19) && (D_80B7E0B4 <= 24)) {
+ if ((sRodCastTimer > 18) && (sRodCastTimer < 25)) {
Math_ApproachF(&D_80B7A6B8, 0.8f, 1.0f, 0.2f);
} else {
Math_ApproachF(&D_80B7A6B8, 0.0f, 1.0f, 0.4f);
@@ -2067,13 +2087,13 @@ void Fishing_DrawRod(PlayState* play) {
Matrix_Mult(&player->mf_9E0, MTXMODE_NEW);
- if (sLinkAge != 1) {
+ if (sLinkAge != LINK_AGE_CHILD) {
Matrix_Translate(0.0f, 400.0f, 0.0f, MTXMODE_APPLY);
} else {
Matrix_Translate(0.0f, 230.0f, 0.0f, MTXMODE_APPLY);
}
- if (D_80B7A694 == 5) {
+ if (sRodCastState == 5) {
Matrix_RotateY(0.56f * M_PI, MTXMODE_APPLY);
} else {
Matrix_RotateY(0.41f * M_PI, MTXMODE_APPLY);
@@ -2089,7 +2109,7 @@ void Fishing_DrawRod(PlayState* play) {
Matrix_Translate(0.0f, 0.0f, -1300.0f, MTXMODE_APPLY);
for (i = 0; i < 22; i++) {
- Matrix_RotateY(sRodBendRatios[i] * D_80B7A6A8 * 0.5f, MTXMODE_APPLY);
+ Matrix_RotateY(sRodBendRatios[i] * sRodBendRotY * 0.5f, MTXMODE_APPLY);
Matrix_RotateX(sRodBendRatios[i] * spC0 * 0.5f, MTXMODE_APPLY);
Matrix_Push();
@@ -2122,18 +2142,18 @@ void Fishing_DrawRod(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
-static Vec3f D_80B7AF94 = { 0.0f, 0.0f, 0.0f };
+static Vec3f sSoundPos = { 0.0f, 0.0f, 0.0f };
void Fishing_UpdateLure(Fishing* this, PlayState* play) {
f32 spE4;
f32 spE0;
- s16 phi_v0;
+ s16 timer;
s16 spDC;
f32 spD8;
f32 spD4;
f32 spD0;
- f32 phi_f16;
- f32 spC8;
+ f32 lengthCasted;
+ f32 lureXZLen;
s16 i;
Player* player = GET_PLAYER(play);
Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
@@ -2145,12 +2165,12 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
f32 sp7C;
f32 sp78;
f32 phi_f0;
- f32 sp70;
+ f32 wiggle;
Vec3f sp64;
Vec3f sp58;
s32 pad;
- D_80B7E0AE++;
+ sLureTimer++;
if (D_80B7E0B0 != 0) {
D_80B7E0B0--;
@@ -2160,12 +2180,12 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
D_80B7E0B2--;
}
- if (D_80B7E0B4 != 0) {
- D_80B7E0B4--;
+ if (sRodCastTimer != 0) {
+ sRodCastTimer--;
}
- if (D_80B7E122 != 0) {
- D_80B7E122--;
+ if (sLureBitTimer != 0) {
+ sLureBitTimer--;
}
if (D_80B7E150 != 0) {
@@ -2176,33 +2196,34 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
D_80B7A6A4--;
}
- if (D_80B7E0A4 != 0) {
- D_80B7E0A4--;
+ if (sRumbleDelay != 0) {
+ sRumbleDelay--;
}
if (D_80B7E114 != 0) {
D_80B7E114--;
}
- if (D_80B7E0AC == 1) {
- D_80B7E0AC = 2;
- D_80B7E084 = 0;
- D_80B7E082 = 0;
- D_80B7E0B6 = 0;
+ if (sFishingPlayingState == 1) {
+ sFishingPlayingState = 2;
+ sFishesCaught = 0;
+ sPondOwnerTextIdIndex = 0;
+ sLureEquipped = FS_LURE_STOCK;
- if (((sLinkAge == 1) && (HIGH_SCORE(HS_FISHING) & 0x400)) ||
- ((sLinkAge != 1) && (HIGH_SCORE(HS_FISHING) & 0x800))) {
+ // if prize item won as child or adult, set the sinking lure location.
+ if (((sLinkAge == LINK_AGE_CHILD) && (HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_CHILD)) ||
+ ((sLinkAge != LINK_AGE_CHILD) && (HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_ADULT))) {
sSinkingLureLocation = (u8)Rand_ZeroFloat(3.999f) + 1;
}
D_80B7E148 = 520.0f;
- D_80B7E144 = 195.0f;
+ sRodLineSpooled = 195.0f;
- D_80B7A694 = D_80B7E0B6 = D_80B7E0AE = D_80B7E0B0 = D_80B7E0B2 = D_80B7E0B4 = D_80B7E120 = D_80B7E114 =
+ sRodCastState = sLureEquipped = sLureTimer = D_80B7E0B0 = D_80B7E0B2 = sRodCastTimer = sWiggleAttraction = D_80B7E114 =
D_80B7E150 = 0;
- D_80B7E104 = D_80B7E154 = D_80B7E108 = 0.0f;
+ sLure1Rotate = sReelLinePosStep = sLurePosZOffset = 0.0f;
- D_80B7E128 = zeroVec;
+ sLureLineSegPosDelta = zeroVec;
for (i = 0; i < LINE_SEG_COUNT; i++) {
sReelLinePos[i] = zeroVec;
@@ -2211,78 +2232,78 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
}
}
- SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &sLurePos, &D_80B7AF94, &sProjectedW);
+ SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &sLurePos, &sSoundPos, &sProjectedW);
- if (D_80B7A694 == 0) {
- Math_ApproachF(&D_80B7E108, -800.0f, 1.0f, 20.0f);
+ if (sRodCastState == 0) {
+ Math_ApproachF(&sLurePosZOffset, -800.0f, 1.0f, 20.0f);
} else {
- Math_ApproachF(&D_80B7E108, 300.0f, 1.0f, 20.0f);
+ Math_ApproachF(&sLurePosZOffset, 300.0f, 1.0f, 20.0f);
}
- switch (D_80B7A694) {
+ switch (sRodCastState) {
case 0:
- D_80B7FEA0 = 0;
+ sSinkingLureSegmentIndex = 0;
if (KREG(14) != 0) {
KREG(14) = 0;
- D_80B7E0B6 = 2 - D_80B7E0B6;
- if (D_80B7E0B6 != 0) {
- D_80B7E082 = 0;
+ sLureEquipped = FS_LURE_SINKING - sLureEquipped;
+ if (sLureEquipped != FS_LURE_STOCK) {
+ sPondOwnerTextIdIndex = 0;
}
}
- Math_ApproachF(&D_80B7E144, 195.0f, 1.0f, 1.0f);
+ Math_ApproachF(&sRodLineSpooled, 195.0f, 1.0f, 1.0f);
if (player->stateFlags1 & 0x8000000) {
- D_80B7E0B4 = 0;
+ sRodCastTimer = 0;
player->unk_860 = 0;
}
- if (D_80B7E0B4 == 0) {
+ if (sRodCastTimer == 0) {
if ((D_80B7E0B0 == 0) && (player->unk_860 == 1)) {
- D_80B7E0B4 = 37;
+ sRodCastTimer = 37;
Message_CloseTextbox(play);
}
} else {
sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI;
sLureRot.y = sReelLineRot[LINE_SEG_COUNT - 2].y;
- if (D_80B7E0B4 == 18) {
- D_80B7A694 = 1;
+ if (sRodCastTimer == 18) {
+ sRodCastState = 1;
sLurePos = sRodTipPos;
Matrix_RotateY((player->actor.shape.rot.y / 32768.0f) * M_PI, MTXMODE_NEW);
sp90.x = 0.0f;
sp90.y = 0.0f;
sp90.z = 25.0f;
- Matrix_MultVec3f(&sp90, &D_80B7E0E8);
- D_80B7E0E8.y = 15.0f;
- D_80B7E0F8.x = D_80B7E0F8.z = 0.0f;
- D_80B7E0F8.y = -1.0f;
+ Matrix_MultVec3f(&sp90, &sLurePosDelta);
+ sLurePosDelta.y = 15.0f;
+ sLureCastDelta.x = sLureCastDelta.z = 0.0f;
+ sLureCastDelta.y = -1.0f;
D_80B7E148 = 0.0f;
D_80B7E0B2 = 5;
- D_80B7E11C = 0.5f;
+ sRodReelingSpeed = 0.5f;
D_80B7E118 = Rand_ZeroFloat(1.9f);
sFishMouthOffset.y = 500.0f;
- func_80078914(&D_80B7AF94, NA_SE_IT_SWORD_SWING_HARD);
+ func_80078914(&sSoundPos, NA_SE_IT_SWORD_SWING_HARD);
}
}
break;
- case 1:
+ case 1: // casting the line
spE0 = sLurePos.y;
- sLurePos.x += D_80B7E0E8.x;
- sLurePos.y += D_80B7E0E8.y;
- sLurePos.z += D_80B7E0E8.z;
+ sLurePos.x += sLurePosDelta.x;
+ sLurePos.y += sLurePosDelta.y;
+ sLurePos.z += sLurePosDelta.z;
- D_80B7E0E8.x += D_80B7E0F8.x;
- D_80B7E0E8.y += D_80B7E0F8.y;
- D_80B7E0E8.z += D_80B7E0F8.z;
-
- if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (D_80B7A68C != 0)) {
- D_80B7E0E8.x *= 0.9f;
- D_80B7E0E8.z *= 0.9f;
- if (D_80B7A68C == 0) {
+ sLurePosDelta.x += sLureCastDelta.x;
+ sLurePosDelta.y += sLureCastDelta.y;
+ sLurePosDelta.z += sLureCastDelta.z;
+ // air drag by hat or reeling during cast.
+ if (CHECK_BTN_ALL(input->cur.button, BTN_A) || sIsOwnersHatHooked) {
+ sLurePosDelta.x *= 0.9f;
+ sLurePosDelta.z *= 0.9f;
+ if (!sIsOwnersHatHooked) {
func_80078884(NA_SE_IT_FISHING_REEL_HIGH - SFX_FLAG);
}
}
@@ -2299,14 +2320,14 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
sLureRot.y = Math_Atan2F(spD0, spD8) + M_PI;
}
- phi_f16 = sqrtf(SQ(spD8) + SQ(spD4) + SQ(spD0));
- if (phi_f16 > 1000.0f) {
- phi_f16 = 1000.0f;
+ lengthCasted = sqrtf(SQ(spD8) + SQ(spD4) + SQ(spD0));
+ if (lengthCasted > 1000.0f) {
+ lengthCasted = 1000.0f;
}
- D_80B7E144 = 200.0f - (phi_f16 * 200.0f * 0.001f);
+ sRodLineSpooled = 200.0f - (lengthCasted * 200.0f * 0.001f);
- spC8 = SQ(sLurePos.x) + SQ(sLurePos.z);
- if (spC8 > SQ(920.0f)) {
+ lureXZLen = SQ(sLurePos.x) + SQ(sLurePos.z);
+ if (lureXZLen > SQ(920.0f)) {
if ((KREG(56) != 0) || (sLurePos.y > 160.0f) || (sLurePos.x < 80.0f) || (sLurePos.x > 180.0f) ||
(sLurePos.z > 1350.0f) || (sLurePos.z < 1100.0f) || (sLurePos.y < 45.0f)) {
sp80 = this->actor.world.pos;
@@ -2315,50 +2336,50 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
this->actor.world.pos = sp80;
if (this->actor.bgCheckFlags & 0x10) {
- D_80B7E0E8.y = -0.5f;
+ sLurePosDelta.y = -0.5f;
}
if (this->actor.bgCheckFlags & 8) {
- if (D_80B7E0E8.y > 0.0f) {
- D_80B7E0E8.y = 0.0f;
+ if (sLurePosDelta.y > 0.0f) {
+ sLurePosDelta.y = 0.0f;
}
- D_80B7E0E8.x = D_80B7E0E8.z = 0.0f;
+ sLurePosDelta.x = sLurePosDelta.z = 0.0f;
}
} else {
- if (func_80B6C2EC(&sLurePos) != 0) {
- D_80B7A694 = 3;
- D_80B7E154 = 0.0f;
+ if (Fishing_IsAboveCounter(&sLurePos)) {
+ sRodCastState = 3;
+ sReelLinePosStep = 0.0f;
}
}
- spE4 = ((sqrtf(spC8) - 920.0f) * 0.11f) + WATER_SURFACE_Y(play);
+ spE4 = ((sqrtf(lureXZLen) - 920.0f) * 0.11f) + WATER_SURFACE_Y(play);
if (sLurePos.y <= spE4) {
sLurePos.y = spE4;
- D_80B7E0E8.x = D_80B7E0E8.y = D_80B7E0E8.z = 0.0f;
- D_80B7A694 = 3;
- D_80B7E154 = 0.0;
+ sLurePosDelta.x = sLurePosDelta.y = sLurePosDelta.z = 0.0f;
+ sRodCastState = 3;
+ sReelLinePosStep = 0.0;
} else {
Math_ApproachF(&D_80B7E148, 0.0f, 1.0f, 0.05f);
- func_80078914(&D_80B7AF94, NA_SE_EN_FANTOM_FLOAT - SFX_FLAG);
+ func_80078914(&sSoundPos, NA_SE_EN_FANTOM_FLOAT - SFX_FLAG);
}
} else {
spE4 = WATER_SURFACE_Y(play);
if (sLurePos.y <= spE4) {
- D_80B7A694 = 2;
- D_80B7E154 = 0.0f;
- D_80B7E0E8.x = D_80B7E0E8.z = 0.0f;
+ sRodCastState = 2;
+ sReelLinePosStep = 0.0f;
+ sLurePosDelta.x = sLurePosDelta.z = 0.0f;
- if (D_80B7E0B6 == 2) {
- D_80B7E0A2 = 0;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ sLureMoveDelay = 0;
} else {
- D_80B7E0A2 = 10;
+ sLureMoveDelay = 10;
}
if ((sLurePos.y <= spE4) && (spE4 < spE0) && (spE4 == WATER_SURFACE_Y(play))) {
D_80B7E114 = 10;
- func_80078914(&D_80B7AF94, NA_SE_EV_BOMB_DROP_WATER);
- D_80B7E0F8.y = 0.0f;
- D_80B7E0E8.y *= 0.2f;
+ func_80078914(&sSoundPos, NA_SE_EV_BOMB_DROP_WATER);
+ sLureCastDelta.y = 0.0f;
+ sLurePosDelta.y *= 0.2f;
for (i = 0; i < 50; i++) {
sp7C = Rand_ZeroFloat(1.5f) + 0.5f;
@@ -2382,7 +2403,7 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
}
} else {
Math_ApproachZeroF(&D_80B7E148, 1.0f, 0.05f);
- func_80078914(&D_80B7AF94, NA_SE_EN_FANTOM_FLOAT - SFX_FLAG);
+ func_80078914(&sSoundPos, NA_SE_EN_FANTOM_FLOAT - SFX_FLAG);
}
}
@@ -2390,218 +2411,218 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
sReelLinePos[LINE_SEG_COUNT - 1].y = sLurePos.y;
sReelLinePos[LINE_SEG_COUNT - 1].z = sLurePos.z;
- D_80B7E140 = 1.0f;
- D_80B7E10C = 0.5f;
+ sLureWiggleSign = 1.0f;
+ sLureRotXTarget = 0.5f;
break;
case 2:
if (sLurePos.y <= WATER_SURFACE_Y(play)) {
- sLurePos.y += D_80B7E0E8.y;
+ sLurePos.y += sLurePosDelta.y;
- Math_ApproachZeroF(&D_80B7E0E8.y, 1.0f, 1.0f);
+ Math_ApproachZeroF(&sLurePosDelta.y, 1.0f, 1.0f);
- if (D_80B7E0B6 != 2) {
+ if (sLureEquipped != FS_LURE_SINKING) {
Math_ApproachF(&sLurePos.y, WATER_SURFACE_Y(play), 0.5f, 1.0f);
}
}
Math_ApproachF(&D_80B7E148, 2.0f, 1.0f, 0.1f);
- if (D_80B7E0A2 == 0) {
- D_80B7A694 = 3;
+ if (sLureMoveDelay == 0) {
+ sRodCastState = 3;
} else {
- D_80B7E0A2--;
+ sLureMoveDelay--;
}
break;
case 3:
- D_80B7FEA0 = 0;
+ sSinkingLureSegmentIndex = 0;
- if ((D_80B7A68C != 0) && ((SQ(sLurePos.x) + SQ(sLurePos.z)) < SQ(500.0f))) {
- D_80B7A690 = 1;
+ if (sIsOwnersHatHooked && ((SQ(sLurePos.x) + SQ(sLurePos.z)) < SQ(500.0f))) {
+ sIsOwnersHatSunk = true;
}
player->unk_860 = 2;
- if (D_80B7E138 < 3.0f) {
- spD0 = D_80B7E10C * Math_SinS(D_80B7E0AE * 0x1060);
- Math_ApproachF(&sLureRot.x, -M_PI / 6.0f + spD0, 0.3f, D_80B7E110);
- Math_ApproachF(&D_80B7E110, 0.5f, 1.0f, 0.02f);
- Math_ApproachZeroF(&D_80B7E10C, 1.0f, 0.02f);
+ if (sLureWigglePosY < 3.0f) {
+ spD0 = sLureRotXTarget * Math_SinS(sLureTimer * 0x1060);
+ Math_ApproachF(&sLureRot.x, -M_PI / 6.0f + spD0, 0.3f, sLureRotXStep);
+ Math_ApproachF(&sLureRotXStep, 0.5f, 1.0f, 0.02f);
+ Math_ApproachZeroF(&sLureRotXTarget, 1.0f, 0.02f);
} else {
- D_80B7E110 = 0.0f;
+ sLureRotXStep = 0.0f;
}
spDC = 0x4000;
spE4 = WATER_SURFACE_Y(play);
- spC8 = SQ(sLurePos.x) + SQ(sLurePos.z);
- if (spC8 < SQ(920.0f)) {
+ lureXZLen = SQ(sLurePos.x) + SQ(sLurePos.z);
+ if (lureXZLen < SQ(920.0f)) {
if (sLurePos.y <= (spE4 + 4.0f)) {
- sp70 = 0.0f;
+ wiggle = 0.0f;
if (D_80B7E150 == 0) {
if (fabsf(input->rel.stick_x) > 30.0f) {
- sp70 = fabsf((input->rel.stick_x - D_80B7A6C4) * (1.0f / 60.0f));
+ wiggle = fabsf((input->rel.stick_x - sStickAdjXPrev) * (1.0f / 60.0f));
} else if (fabsf(input->rel.stick_y) > 30.0f) {
- sp70 = fabsf((input->rel.stick_y - D_80B7A6C8) * (1.0f / 60.0f));
+ wiggle = fabsf((input->rel.stick_y - sStickAdjYPrev) * (1.0f / 60.0f));
}
}
- if (sp70 > 1.0f) {
- sp70 = 1.0f;
+ if (wiggle > 1.0f) {
+ wiggle = 1.0f;
}
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
- sp70 = 0.5f;
+ wiggle = 0.5f;
}
- if (D_80B7A68C != 0) {
- if (sp70 > 0.3f) {
- sp70 = 0.3f;
+ if (sIsOwnersHatHooked) {
+ if (wiggle > 0.3f) {
+ wiggle = 0.3f;
}
}
- if ((sp70 > 0.2f) && (D_80B7E138 < 4.0f)) {
+ if ((wiggle > 0.2f) && (sLureWigglePosY < 4.0f)) {
D_80B7E150 = 5;
- if (sp70 > 0.8f) {
- D_80B7E120 = 2;
+ if (wiggle > 0.8f) {
+ sWiggleAttraction = 2;
} else {
- D_80B7E120 = 1;
+ sWiggleAttraction = 1;
}
sp90.x = player->actor.world.pos.x - sLurePos.x;
sp90.z = player->actor.world.pos.z - sLurePos.z;
sp90.y = Math_Atan2F(sp90.z, sp90.x);
- D_80B7E134 = (sp70 * D_80B7E140) + sp90.y;
- D_80B7E140 = D_80B7E140 * -1.0f;
- D_80B7E138 = fabsf(sp70) * 6.0f;
+ sLureWiggleRotYTarget = (wiggle * sLureWiggleSign) + sp90.y;
+ sLureWiggleSign *= -1.0f;
+ sLureWigglePosY = fabsf(wiggle) * 6.0f;
sLureRot.x = 0.0f;
- D_80B7E10C = 0.5f;
- D_80B7E144 += (fabsf(sp70) * (7.5f + (KREG(25) * 0.1f)));
+ sLureRotXTarget = 0.5f;
+ sRodLineSpooled += (fabsf(wiggle) * (7.5f + (KREG(25) * 0.1f)));
- func_800F436C(&D_80B7AF94, NA_SE_EV_LURE_MOVE_W, (sp70 * 1.999f * 0.25f) + 0.75f);
+ func_800F436C(&sSoundPos, NA_SE_EV_LURE_MOVE_W, (wiggle * 1.999f * 0.25f) + 0.75f);
- if (D_80B7E0B6 == 2) {
- D_80B7E128.y = 5.0f * sp70;
- sReelLinePos[LINE_SEG_COUNT - 1].y += D_80B7E128.y;
- sLurePos.y += D_80B7E128.y;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ sLureLineSegPosDelta.y = 5.0f * wiggle;
+ sReelLinePos[LINE_SEG_COUNT - 1].y += sLureLineSegPosDelta.y;
+ sLurePos.y += sLureLineSegPosDelta.y;
}
} else if (CHECK_BTN_ALL(input->cur.button, BTN_A)) {
spDC = 0x500;
- D_80B7E134 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
+ sLureWiggleRotYTarget = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
sLureRot.x = 0.0f;
- D_80B7E10C = 0.5f;
- if (D_80B7E0B6 == 2) {
- D_80B7E128.y = 0.2f;
- sReelLinePos[LINE_SEG_COUNT - 1].y += D_80B7E128.y;
- sLurePos.y += D_80B7E128.y;
+ sLureRotXTarget = 0.5f;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ sLureLineSegPosDelta.y = 0.2f;
+ sReelLinePos[LINE_SEG_COUNT - 1].y += sLureLineSegPosDelta.y;
+ sLurePos.y += sLureLineSegPosDelta.y;
}
}
} else {
- if (D_80B7E144 > 150.0f) {
+ if (sRodLineSpooled > 150.0f) {
sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI;
- D_80B7E134 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
- D_80B7E144 += 2.0f;
+ sLureWiggleRotYTarget = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
+ sRodLineSpooled += 2.0f;
}
}
} else {
- spE4 = ((sqrtf(spC8) - 920.0f) * 0.11f) + WATER_SURFACE_Y(play);
+ spE4 = ((sqrtf(lureXZLen) - 920.0f) * 0.11f) + WATER_SURFACE_Y(play);
if (sLurePos.y <= spE4) {
sLurePos.y = spE4;
spDC = 0x500;
- D_80B7E134 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
+ sLureWiggleRotYTarget = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
sLureRot.x = 0.0f;
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
- D_80B7E144 += 6.0f;
- func_80078914(&D_80B7AF94, NA_SE_PL_WALK_SAND);
+ sRodLineSpooled += 6.0f;
+ func_80078914(&sSoundPos, NA_SE_PL_WALK_SAND);
}
} else {
- if (D_80B7E144 > 150.0f) {
+ if (sRodLineSpooled > 150.0f) {
sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI;
- D_80B7E134 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
- D_80B7E144 += 2.0f;
+ sLureWiggleRotYTarget = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI;
+ sRodLineSpooled += 2.0f;
}
}
}
- Math_ApproachZeroF(&D_80B7E138, 1.0f, 0.3f);
- Math_ApproachS(&D_80B7E13C, (D_80B7E134 * 32768.0f) / M_PI, 3, spDC);
+ Math_ApproachZeroF(&sLureWigglePosY, 1.0f, 0.3f);
+ Math_ApproachS(&sLureWiggleRotY, (sLureWiggleRotYTarget * 32768.0f) / M_PI, 3, spDC);
- sLureRot.y = (D_80B7E13C / 32768.0f) * M_PI;
+ sLureRot.y = (sLureWiggleRotY / 32768.0f) * M_PI;
sp90.x = 0.0f;
sp90.y = 0.0f;
- sp90.z = D_80B7E138;
+ sp90.z = sLureWigglePosY;
Matrix_RotateY(sLureRot.y, MTXMODE_NEW);
- if (D_80B7E0B6 == 2) {
+ if (sLureEquipped == FS_LURE_SINKING) {
Matrix_MultVec3f(&sp90, &sp64);
- D_80B7E128.x = sp64.x;
- D_80B7E128.z = sp64.z;
+ sLureLineSegPosDelta.x = sp64.x;
+ sLureLineSegPosDelta.z = sp64.z;
phi_f0 = 10.0f;
} else {
- Matrix_MultVec3f(&sp90, &D_80B7E128);
+ Matrix_MultVec3f(&sp90, &sLureLineSegPosDelta);
phi_f0 = 0.0f;
}
- D_80B7E104 = 0.0f;
+ sLure1Rotate = 0.0f;
- if ((D_80B7E0B6 == 1) && CHECK_BTN_ALL(input->cur.button, BTN_A)) {
- D_80B7E128.y = -2.0f;
+ if ((sLureEquipped == FS_LURE_UNK) && CHECK_BTN_ALL(input->cur.button, BTN_A)) {
+ sLureLineSegPosDelta.y = -2.0f;
- if ((D_80B7E0AE & 1) != 0) {
- D_80B7E104 = 0.5f;
+ if ((sLureTimer & 1) != 0) {
+ sLure1Rotate = 0.5f;
} else {
- D_80B7E104 = -0.5f;
+ sLure1Rotate = -0.5f;
}
} else if (sReelLinePos[LINE_SEG_COUNT - 1].y < (WATER_SURFACE_Y(play) + phi_f0)) {
- if (D_80B7E0B6 == 2) {
+ if (sLureEquipped == FS_LURE_SINKING) {
sp58 = this->actor.world.pos;
this->actor.prevPos = this->actor.world.pos = sLurePos;
Actor_UpdateBgCheckInfo(play, &this->actor, 15.0f, 30.0f, 30.0f, 0x44);
this->actor.world.pos = sp58;
- D_80B7E128.y += -0.5f;
- if (D_80B7E128.y < -1.0f) {
- D_80B7E128.y = -1.0f;
+ sLureLineSegPosDelta.y += -0.5f;
+ if (sLureLineSegPosDelta.y < -1.0f) {
+ sLureLineSegPosDelta.y = -1.0f;
}
if (sLurePos.y < (this->actor.floorHeight + 5.0f)) {
sReelLinePos[LINE_SEG_COUNT - 1].y = sLurePos.y = this->actor.floorHeight + 5.0f;
- D_80B7E128.y = 0.0f;
+ sLureLineSegPosDelta.y = 0.0f;
} else {
- D_80B7E120 = 1;
+ sWiggleAttraction = 1;
}
} else {
- D_80B7E128.y = fabsf(sReelLinePos[LINE_SEG_COUNT - 1].y - WATER_SURFACE_Y(play)) * 0.2f;
- if (D_80B7E128.y > 1.5f) {
- D_80B7E128.y = 1.5f;
+ sLureLineSegPosDelta.y = fabsf(sReelLinePos[LINE_SEG_COUNT - 1].y - WATER_SURFACE_Y(play)) * 0.2f;
+ if (sLureLineSegPosDelta.y > 1.5f) {
+ sLureLineSegPosDelta.y = 1.5f;
}
}
}
- sReelLinePos[LINE_SEG_COUNT - 1].x += D_80B7E128.x;
- sReelLinePos[LINE_SEG_COUNT - 1].y += D_80B7E128.y;
- sReelLinePos[LINE_SEG_COUNT - 1].z += D_80B7E128.z;
+ sReelLinePos[LINE_SEG_COUNT - 1].x += sLureLineSegPosDelta.x;
+ sReelLinePos[LINE_SEG_COUNT - 1].y += sLureLineSegPosDelta.y;
+ sReelLinePos[LINE_SEG_COUNT - 1].z += sLureLineSegPosDelta.z;
if (sReelLinePos[LINE_SEG_COUNT - 1].y > (spE4 + 6.0f)) {
sReelLinePos[LINE_SEG_COUNT - 1].y -= 5.0f;
}
- D_80B7E0E8.x = D_80B7E0E8.y = D_80B7E0E8.z = D_80B7E0F8.y = 0.0f;
+ sLurePosDelta.x = sLurePosDelta.y = sLurePosDelta.z = sLureCastDelta.y = 0.0f;
if (CHECK_BTN_ALL(input->cur.button, BTN_A)) {
if (CHECK_BTN_ALL(input->cur.button, BTN_R)) {
- D_80B7E144 += 1.5f;
+ sRodLineSpooled += 1.5f;
func_80078884(NA_SE_IT_FISHING_REEL_HIGH - SFX_FLAG);
- Math_ApproachF(&D_80B7E154, 1000.0f, 1.0f, 2.0f);
+ Math_ApproachF(&sReelLinePosStep, 1000.0f, 1.0f, 2.0f);
} else {
- D_80B7E144 += D_80B7E11C;
+ sRodLineSpooled += sRodReelingSpeed;
func_80078884(NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG);
- Math_ApproachF(&D_80B7E154, 1000.0f, 1.0f, 0.2f);
+ Math_ApproachF(&sReelLinePosStep, 1000.0f, 1.0f, 0.2f);
}
if (sReelLinePos[LINE_SEG_COUNT - 1].y > (WATER_SURFACE_Y(play) + 4.0f)) {
@@ -2613,32 +2634,32 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
Math_ApproachF(&D_80B7E148, 2.0f, 1.0f, 0.2f);
}
- Math_ApproachF(&sLurePos.x, sReelLinePos[LINE_SEG_COUNT - 1].x, 1.0f, D_80B7E154);
- Math_ApproachF(&sLurePos.y, sReelLinePos[LINE_SEG_COUNT - 1].y, 1.0f, D_80B7E154);
- Math_ApproachF(&sLurePos.z, sReelLinePos[LINE_SEG_COUNT - 1].z, 1.0f, D_80B7E154);
+ Math_ApproachF(&sLurePos.x, sReelLinePos[LINE_SEG_COUNT - 1].x, 1.0f, sReelLinePosStep);
+ Math_ApproachF(&sLurePos.y, sReelLinePos[LINE_SEG_COUNT - 1].y, 1.0f, sReelLinePosStep);
+ Math_ApproachF(&sLurePos.z, sReelLinePos[LINE_SEG_COUNT - 1].z, 1.0f, sReelLinePosStep);
- if (D_80B7E138 > 1.0f) {
- Math_ApproachF(&D_80B7E154, 1000.0f, 1.0f, 1.0f);
+ if (sLureWigglePosY > 1.0f) {
+ Math_ApproachF(&sReelLinePosStep, 1000.0f, 1.0f, 1.0f);
}
- Math_ApproachF(&D_80B7E154, 1000.0f, 1.0f, 0.1f);
+ Math_ApproachF(&sReelLinePosStep, 1000.0f, 1.0f, 0.1f);
- if (D_80B7E144 >= 195.0f) {
- D_80B7E144 = 195.0f;
- D_80B7A694 = 0;
+ if (sRodLineSpooled >= 195.0f) {
+ sRodLineSpooled = 195.0f;
+ sRodCastState = 0;
D_80B7E148 = 520.0f;
- D_80B7A6CC = 3;
+ sFishingPlayerCinematicState = 3;
}
if ((sLurePos.y <= (WATER_SURFACE_Y(play) + 4.0f)) &&
(sLurePos.y >= (WATER_SURFACE_Y(play) - 4.0f))) {
- phi_v0 = 63;
- if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (D_80B7E138 > 1.0f)) {
- phi_v0 = 1;
+ timer = 63;
+ if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (sLureWigglePosY > 1.0f)) {
+ timer = 1;
}
- if ((D_80B7E0AE & phi_v0) == 0) {
+ if ((sLureTimer & timer) == 0) {
spA8 = sLurePos;
spA8.y = WATER_SURFACE_Y(play);
Fishing_SpawnRipple(NULL, play->specialEffects, &spA8, 30.0f, 300.0f, 150, 90);
@@ -2649,20 +2670,20 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
case 4:
if (this->unk_157 != 0) {
this->unk_157--;
- D_80B7E144 += D_80B7E11C;
+ sRodLineSpooled += sRodReelingSpeed;
}
if (CHECK_BTN_ALL(input->cur.button, BTN_A)) {
if ((SQ(sLurePos.x) + SQ(sLurePos.z)) > SQ(920.0f)) {
- D_80B7E144 += (1.0f + (KREG(65) * 0.1f));
+ sRodLineSpooled += (1.0f + (KREG(65) * 0.1f));
} else {
- D_80B7E144 += D_80B7E11C;
+ sRodLineSpooled += sRodReelingSpeed;
}
func_80078884(NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG);
}
- if ((D_80B7E0AE & 0x1F) == 0) {
- if ((D_80B7E124 != 0) || (D_80B7E0B6 != 2)) {
+ if ((sLureTimer & 0x1F) == 0) {
+ if (sLineHooked || (sLureEquipped != FS_LURE_SINKING)) {
D_80B7A6A4 = 5;
}
}
@@ -2671,7 +2692,7 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
break;
case 5:
- D_80B7E14C = 0.0005000001f;
+ sFishingLineScale = 0.0005000001f;
sReelLinePos[LINE_SEG_COUNT - 1].x = sLurePos.x;
sReelLinePos[LINE_SEG_COUNT - 1].y = sLurePos.y;
sReelLinePos[LINE_SEG_COUNT - 1].z = sLurePos.z;
@@ -2680,7 +2701,7 @@ void Fishing_UpdateLure(Fishing* this, PlayState* play) {
}
}
-s32 func_80B70A2C(Fishing* this, PlayState* play, u8 ignorePosCheck) {
+s32 Fishing_SplashBySize(Fishing* this, PlayState* play, u8 ignorePosCheck) {
s16 i;
s16 count;
f32 scale;
@@ -2693,7 +2714,7 @@ s32 func_80B70A2C(Fishing* this, PlayState* play, u8 ignorePosCheck) {
return false;
}
- if (this->unk_1AC >= 40.0f) {
+ if (this->fishLength >= 40.0f) {
count = 40;
scale = 1.2f;
} else {
@@ -2723,12 +2744,12 @@ s32 func_80B70A2C(Fishing* this, PlayState* play, u8 ignorePosCheck) {
Fishing_SpawnRipple(&this->actor.projectedPos, play->specialEffects, &pos, 100.0f, 800.0f, 150, 90);
- this->unk_151 = 30;
+ this->lilyTimer = 30;
return true;
}
-void func_80B70CF0(Fishing* this, PlayState* play) {
+void Fishing_SplashBySize2(Fishing* this, PlayState* play) {
s16 count;
s16 i;
f32 scale;
@@ -2737,7 +2758,7 @@ void func_80B70CF0(Fishing* this, PlayState* play) {
f32 speedXZ;
f32 angle;
- if (this->unk_1AC >= 45.0f) {
+ if (this->fishLength >= 45.0f) {
count = 30;
scale = 0.5f;
} else {
@@ -2764,86 +2785,86 @@ void func_80B70CF0(Fishing* this, PlayState* play) {
}
void func_80B70ED4(Fishing* this, Input* input) {
- Vec3f sp34;
+ Vec3f lineVec;
Vec3f sp28;
- f32 sp24;
+ f32 lineLengthSQ;
- sp34.x = sLurePos.x - this->actor.world.pos.x;
- sp34.y = sLurePos.y - this->actor.world.pos.y;
- sp34.z = sLurePos.z - this->actor.world.pos.z;
+ lineVec.x = sLurePos.x - this->actor.world.pos.x;
+ lineVec.y = sLurePos.y - this->actor.world.pos.y;
+ lineVec.z = sLurePos.z - this->actor.world.pos.z;
- sp24 = SQ(sp34.x) + SQ(sp34.y) + SQ(sp34.z);
+ lineLengthSQ = SQ(lineVec.x) + SQ(lineVec.y) + SQ(lineVec.z);
- if ((D_80B7A694 == 3) && (this->unk_1A2 == 0) && (D_80B7A68C == 0)) {
+ if ((sRodCastState == 3) && (this->unk_1A2 == 0) && (sIsOwnersHatHooked == 0)) {
Matrix_RotateY((-this->actor.shape.rot.y / 32768.0f) * M_PI, MTXMODE_NEW);
- Matrix_MultVec3f(&sp34, &sp28);
+ Matrix_MultVec3f(&lineVec, &sp28);
- if ((sp28.z > 0.0f) || (this->unk_1AC < 40.0f)) {
- if ((this->unk_158 == 7) && (sp24 < SQ(200.0f))) {
- this->unk_158 = 4;
- this->unk_1B4 = sLurePos;
- this->unk_1B0 = 28672.0f;
- this->unk_188 = 5.0f;
+ if ((sp28.z > 0.0f) || (this->fishLength < 40.0f)) {
+ if ((this->fishState == 7) && (lineLengthSQ < SQ(200.0f))) {
+ this->fishState = 4;
+ this->fishTargetPos = sLurePos;
+ this->rotationStep = 28672.0f;
+ this->speedTarget = 5.0f;
} else {
- if ((CHECK_BTN_ALL(input->cur.button, BTN_A) || (D_80B7E138 > 1.0f)) && (sp24 < SQ(120.0f))) {
- this->unk_158 = 2;
+ if ((CHECK_BTN_ALL(input->cur.button, BTN_A) || (sLureWigglePosY > 1.0f)) && (lineLengthSQ < SQ(120.0f))) {
+ this->fishState = 2;
this->unk_15E = 0;
- this->unk_17A[0] = 0;
- this->unk_17A[2] = (s16)Rand_ZeroFloat(100.0f) + 100;
- this->unk_1A8 = sFishInits[this->actor.params - 100].unk_0C;
- this->unk_1B0 = 0.0f;
+ this->timerArray[0] = 0;
+ this->timerArray[2] = (s16)Rand_ZeroFloat(100.0f) + 100;
+ this->perception = sFishInits[this->actor.params - EN_FISH_PARAM].perception;
+ this->rotationStep = 0.0f;
}
- if ((this->unk_17A[1] == 0) && (sp24 < SQ(70.0f))) {
- this->unk_158 = 2;
+ if ((this->timerArray[1] == 0) && (lineLengthSQ < SQ(70.0f))) {
+ this->fishState = 2;
this->unk_15E = 0;
- this->unk_17A[0] = 0;
- this->unk_17A[2] = (s16)Rand_ZeroFloat(100.0f) + 100;
- this->unk_1A8 = sFishInits[this->actor.params - 100].unk_0C;
- this->unk_1B0 = 0.0f;
+ this->timerArray[0] = 0;
+ this->timerArray[2] = (s16)Rand_ZeroFloat(100.0f) + 100;
+ this->perception = sFishInits[this->actor.params - EN_FISH_PARAM].perception;
+ this->rotationStep = 0.0f;
}
}
}
- } else if ((D_80B7A694 == 4) && (D_80B7E124 != 0) && (sp24 < SQ(100.0f)) && (this->unk_158 >= 10)) {
- this->unk_15A = 0;
- this->unk_158 = 1;
+ } else if ((sRodCastState == 4) && sLineHooked && (lineLengthSQ < SQ(100.0f)) && (this->fishState >= 10)) {
+ this->fishStateNext = 0;
+ this->fishState = 1;
this->unk_1A4 = 1000;
this->unk_1A2 = 100;
- this->unk_17A[1] = 50;
+ this->timerArray[1] = 50;
}
- if ((D_80B7E0B6 != 2) && (D_80B7E114 != 0) && (this->unk_1AC > 60.0f) && (sp24 < SQ(30.0f)) &&
- (this->unk_158 >= 10)) {
- this->unk_15A = 0;
- this->unk_158 = 1;
+ if ((sLureEquipped != FS_LURE_SINKING) && (D_80B7E114 != 0) && (this->fishLength > 60.0f) && (lineLengthSQ < SQ(30.0f)) &&
+ (this->fishState >= 10)) {
+ this->fishStateNext = 0;
+ this->fishState = 1;
this->unk_1A4 = 1000;
this->unk_1A2 = 100;
- this->unk_17A[1] = 50;
+ this->timerArray[1] = 50;
}
}
-void func_80B71278(Fishing* this, u8 arg1) {
+void Fishing_FishLeapSfx(Fishing* this, u8 outOfWater) {
s16 sfxId;
- u8 temp;
+ u8 length;
- if (this->unk_150 == 0) {
- temp = this->unk_1AC;
+ if (this->isLoach == 0) {
+ length = this->fishLength;
} else {
- temp = 2.0f * this->unk_1AC;
+ length = 2.0f * this->fishLength;
}
- if (arg1 == 0) {
- if (temp >= 50) {
+ if (outOfWater == false) {
+ if (length >= 50) {
sfxId = NA_SE_EV_DIVE_INTO_WATER;
- } else if (temp >= 40) {
+ } else if (length >= 40) {
sfxId = NA_SE_EV_BOMB_DROP_WATER;
} else {
sfxId = NA_SE_EV_BOMB_DROP_WATER;
}
} else {
- if (temp >= 50) {
+ if (length >= 50) {
sfxId = NA_SE_EV_JUMP_OUT_WATER;
- } else if (temp >= 40) {
+ } else if (length >= 40) {
sfxId = NA_SE_EV_OUT_OF_WATER;
} else {
sfxId = NA_SE_EV_OUT_OF_WATER;
@@ -2854,9 +2875,9 @@ void func_80B71278(Fishing* this, u8 arg1) {
}
void Fishing_HandleAquariumDialog(Fishing* this, PlayState* play) {
- if (sLinkAge == 1) {
- if ((HIGH_SCORE(HS_FISHING) & 0x7F) != 0) {
- if (HIGH_SCORE(HS_FISHING) & 0x80) {
+ if (sLinkAge == LINK_AGE_CHILD) {
+ if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_CHILD) != 0) {
+ if (HIGH_SCORE(HS_FISHING) & HS_FISH_CHEAT_CHILD) {
this->actor.textId = 0x40B1;
} else {
this->actor.textId = 0x4089;
@@ -2865,8 +2886,8 @@ void Fishing_HandleAquariumDialog(Fishing* this, PlayState* play) {
this->actor.textId = 0x40AE;
}
} else {
- if ((HIGH_SCORE(HS_FISHING) & 0x7F000000) != 0) {
- if (HIGH_SCORE(HS_FISHING) & 0x80000000) {
+ if ((HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) != 0) {
+ if (HIGH_SCORE(HS_FISHING) & HS_FISH_CHEAT_ADULT) {
this->actor.textId = 0x40B1;
} else {
this->actor.textId = 0x4089;
@@ -2876,23 +2897,23 @@ void Fishing_HandleAquariumDialog(Fishing* this, PlayState* play) {
}
}
- if (this->unk_1D3 == 0) {
- if (this->unk_1D4 == 0) {
+ if (!this->isAquariumMessage) {
+ if (this->aquariumWaitTimer == 0) {
this->actor.flags |= ACTOR_FLAG_TARGETABLE;
if (Actor_ProcessTalkRequest(&this->actor, play)) {
- D_80B7A678 = D_80B7E078;
- this->unk_1D3 = 1;
+ sFishLengthToWeigh = sFishingRecordLength;
+ this->isAquariumMessage = true;
} else {
func_8002F2F4(&this->actor, play);
}
} else {
- this->unk_1D4--;
+ this->aquariumWaitTimer--;
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
}
} else if (Actor_TextboxIsClosing(&this->actor, play)) {
- this->unk_1D3 = 0;
- this->unk_1D4 = 20;
+ this->isAquariumMessage = false;
+ this->aquariumWaitTimer = 20;
}
}
@@ -2921,27 +2942,36 @@ bool getFishNeverEscape() {
return CVarGetInteger("gCustomizeFishing", 0) && CVarGetInteger("gFishNeverEscape", 0);
}
+bool getShouldSpawnLoaches() {
+ return (CVarGetInteger("gCustomizeFishing", 0) && CVarGetInteger("gLoachesAlwaysAppear", 0))
+ || ((KREG(1) == 1) || ((sFishGameNumber & 3) == 3));
+}
+
+bool getShouldConfirmKeep() {
+ return !CVarGetInteger("gCustomizeFishing", 0) || !CVarGetInteger("gSkipKeepConfirmation", 0);
+}
+
void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
s16 i;
- s16 sp134 = 10;
- f32 sp130;
- f32 sp12C;
- f32 sp128;
- f32 sp124;
+ s16 rotXYScale = 10;
+ f32 distX;
+ f32 distY;
+ f32 distZ;
+ f32 distToTarget;
f32 multiplier;
- f32 sp11C;
- f32 sp118;
- Vec3f sp10C;
- Vec3f sp100;
- s16 spFE;
- s16 spFC;
- s16 spFA;
- s16 phi_v0;
+ f32 chance;
+ f32 playerSpeedMod;
+ Vec3f multiVecSrc;
+ Vec3f targetPosOffset;
+ s16 rotXTarget;
+ s16 rotYTarget;
+ s16 rotZScale;
+ s16 timer;
s16 spF6;
- s16 spF4;
- s16 spF2;
- s16 spF0;
- s16 spEE;
+ s16 rotXScale;
+ s16 rotXStep;
+ s16 rotYScale;
+ s16 rotYStep;
Fishing* this = (Fishing*)thisx;
PlayState* play = play2;
Player* player = GET_PLAYER(play);
@@ -2949,46 +2979,46 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
f32 spD8;
f32 phi_f0;
f32 phi_f2;
- Vec3f spC4;
+ Vec3f bubblePos;
Vec3f spB8;
u8 phi_v0_2;
f32 temp_f0;
f32 temp;
s32 pad;
- f32 spA4;
- u16 spA2;
- u8 phi_a1;
+ f32 rumbleStrength;
+ u16 attempts;
+ u8 rumbleStrength8;
this->actor.uncullZoneForward = 700.0f;
this->actor.uncullZoneScale = 50.0f;
- if (this->unk_150 == 0) {
- sp118 = (player->actor.speedXZ * 0.15f) + 0.25f;
+ if (this->isLoach == 0) {
+ playerSpeedMod = (player->actor.speedXZ * 0.15f) + 0.25f;
} else {
- sp118 = (player->actor.speedXZ * 0.3f) + 0.25f;
+ playerSpeedMod = (player->actor.speedXZ * 0.3f) + 0.25f;
}
- if ((D_80B7E0B0 != 0) || (sCameraId != 0) || ((player->actor.world.pos.z > 1150.0f) && (this->unk_158 != 100))) {
+ if ((D_80B7E0B0 != 0) || (sSubCamId != 0) || ((player->actor.world.pos.z > 1150.0f) && (this->fishState != 100))) {
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
} else {
this->actor.flags |= ACTOR_FLAG_TARGETABLE;
- if (D_80B7A694 != 0) {
+ if (sRodCastState != 0) {
if (D_80B7E0B2 == 0) {
this->actor.focus.pos = sLurePos;
} else if (D_80B7E0B2 == 1) {
- D_80B7A6CC = 1;
+ sFishingPlayerCinematicState = 1;
D_80B7FED0 = 0.0f;
- D_80B7E088 = 2;
+ sLureCameraZoomLevel = 2;
}
}
this->actor.focus.pos = this->actor.world.pos;
}
- this->unk_15C++;
+ this->stateAndTimer++;
for (i = 0; i < 4; i++) {
- if (this->unk_17A[i] != 0) {
- this->unk_17A[i]--;
+ if (this->timerArray[i] != 0) {
+ this->timerArray[i]--;
}
}
@@ -3000,18 +3030,18 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->unk_1A2--;
}
- if (this->unk_1A0 != 0) {
- this->unk_1A0--;
+ if (this->bumpTimer != 0) {
+ this->bumpTimer--;
}
- if (this->unk_151 != 0) {
- this->unk_151--;
+ if (this->lilyTimer != 0) {
+ this->lilyTimer--;
}
- Math_ApproachF(&this->unk_198, this->unk_190, 1.0f, 0.2f);
+ Math_ApproachF(&this->fishLimbRotPhaseStep, this->unk_190, 1.0f, 0.2f);
- if (this->unk_158 == 6) {
- Math_ApproachF(&this->unk_19C, this->unk_194, 0.2f, 200.0f);
+ if (this->fishState == 6) {
+ Math_ApproachF(&this->fishLimbRotPhaseMag, this->unk_194, 0.2f, 200.0f);
} else {
phi_f0 = 1.0f;
phi_f2 = 1.0f;
@@ -3019,62 +3049,62 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
phi_f0 = (KREG(64) * 0.1f) + 1.5f;
phi_f2 = 3.0f;
}
- Math_ApproachF(&this->unk_19C, this->unk_194 * phi_f0, 1.0f, 500.0f * phi_f2);
+ Math_ApproachF(&this->fishLimbRotPhaseMag, this->unk_194 * phi_f0, 1.0f, 500.0f * phi_f2);
}
- Math_ApproachS(&this->unk_170, 0, 5, 0x1F4);
+ Math_ApproachS(&this->fishLimbDRotZDelta, 0, 5, 0x1F4);
- if (this->unk_150 == 0) {
- Actor_SetScale(&this->actor, this->unk_1AC * 15.0f * 0.00001f);
+ if (this->isLoach == 0) {
+ Actor_SetScale(&this->actor, this->fishLength * 15.0f * 0.00001f);
- this->unk_18C += this->unk_198;
+ this->fishLimbRotPhase += this->fishLimbRotPhaseStep;
- temp = cosf(this->unk_18C);
- this->unk_16C = this->unk_16E + (s16)(temp * this->unk_19C);
+ temp = cosf(this->fishLimbRotPhase);
+ this->fishLimb23RotYDelta = this->unk_16E + (s16)(temp * this->fishLimbRotPhaseMag);
- temp = cosf(this->unk_18C + -1.2f);
- this->unk_176 = this->unk_16E + (s16)(temp * this->unk_19C * 1.6f);
+ temp = cosf(this->fishLimbRotPhase + -1.2f);
+ this->fishLimb4RotYDelta = this->unk_16E + (s16)(temp * this->fishLimbRotPhaseMag * 1.6f);
} else {
- Actor_SetScale(&this->actor, this->unk_1AC * 65.0f * 0.000001f);
+ Actor_SetScale(&this->actor, this->fishLength * 65.0f * 0.000001f);
this->actor.scale.x = this->actor.scale.z * 1.1f;
this->actor.scale.y = this->actor.scale.z * 1.1f;
- this->unk_18C += this->unk_198 * 0.8f;
+ this->fishLimbRotPhase += this->fishLimbRotPhaseStep * 0.8f;
for (i = 0; i < 3; i++) {
- temp = cosf(this->unk_18C + (i * 2.1f));
- this->unk_1CC[i] = this->unk_16E + (s16)(temp * this->unk_19C * 2.0f);
+ temp = cosf(this->fishLimbRotPhase + (i * 2.1f));
+ this->loachRotYDelta[i] = this->unk_16E + (s16)(temp * this->fishLimbRotPhaseMag * 2.0f);
}
- temp = cosf(this->unk_18C + 0.4f);
- this->unk_16C = (this->unk_19C * temp * 2.0f) * 0.6f;
+ temp = cosf(this->fishLimbRotPhase + 0.4f);
+ this->fishLimb23RotYDelta = (this->fishLimbRotPhaseMag * temp * 2.0f) * 0.6f;
}
- sp130 = this->unk_1B4.x - this->actor.world.pos.x;
- sp12C = this->unk_1B4.y - this->actor.world.pos.y;
- sp128 = this->unk_1B4.z - this->actor.world.pos.z;
+ distX = this->fishTargetPos.x - this->actor.world.pos.x;
+ distY = this->fishTargetPos.y - this->actor.world.pos.y;
+ distZ = this->fishTargetPos.z - this->actor.world.pos.z;
- spFC = Math_Atan2S(sp128, sp130);
- sp124 = sqrtf(SQ(sp130) + SQ(sp128));
+ rotYTarget = Math_Atan2S(distZ, distX);
+ distToTarget = sqrtf(SQ(distX) + SQ(distZ));
- spFE = Math_Atan2S(sp124, sp12C);
- sp124 = sqrtf(SQ(sp130) + SQ(sp128) + SQ(sp12C));
+ rotXTarget = Math_Atan2S(distToTarget, distY);
+ distToTarget = sqrtf(SQ(distX) + SQ(distZ) + SQ(distY));
- if ((this->unk_1A0 != 0) && (this->unk_158 != 2) && (this->unk_158 != 3) && (this->unk_158 != 4)) {
- if ((this->unk_15C & 0x40) != 0) {
- spFC += 0x4000;
+ if ((this->bumpTimer != 0) && (this->fishState != 2) && (this->fishState != 3) && (this->fishState != 4)) {
+ if ((this->stateAndTimer & 0x40) != 0) {
+ rotYTarget += 0x4000;
} else {
- spFC -= 0x4000;
+ rotYTarget -= 0x4000;
}
- if (((this->unk_15C + 0x20) & 0x40) != 0) {
- spFE += 0x2000;
+ if (((this->stateAndTimer + 0x20) & 0x40) != 0) {
+ rotXTarget += 0x2000;
} else {
- spFE -= 0x2000;
+ rotXTarget -= 0x2000;
}
}
- switch (this->unk_158) {
+ switch (this->fishState) {
case 100:
Fishing_HandleAquariumDialog(this, play);
@@ -3085,107 +3115,107 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
(s16)this->actor.world.pos.y + 20.0f, (s16)this->actor.world.pos.z - 50.0f, 255,
255, 255, 255);
- this->unk_1AC = D_80B7E078;
- sp100.y = (f32)Math_SinS(play->gameplayFrames * 300) * 1;
- sp100.z = (f32)Math_SinS(play->gameplayFrames * 230) * 2;
+ this->fishLength = sFishingRecordLength;
+ targetPosOffset.y = (f32)Math_SinS(play->gameplayFrames * 300) * 1;
+ targetPosOffset.z = (f32)Math_SinS(play->gameplayFrames * 230) * 2;
this->actor.world.pos.x = 130.0f;
- this->actor.world.pos.y = 55.0f + sp100.y;
- this->actor.world.pos.z = 1300.0f + sp100.z;
+ this->actor.world.pos.y = 55.0f + targetPosOffset.y;
+ this->actor.world.pos.z = 1300.0f + targetPosOffset.z;
this->actor.shape.rot.y = -0x8000;
if ((this->actor.projectedPos.z < 200.0f) && (this->actor.projectedPos.z > 0.0f)) {
- spC4.x = Rand_CenteredFloat(5.0f) + 130.0f;
- spC4.y = 40.0f;
- spC4.z = Rand_CenteredFloat(5.0f) + 1280.0f;
- Fishing_SpawnBubble(NULL, play->specialEffects, &spC4, Rand_ZeroFloat(0.02f) + 0.03f, 1);
+ bubblePos.x = Rand_CenteredFloat(5.0f) + 130.0f;
+ bubblePos.y = 40.0f;
+ bubblePos.z = Rand_CenteredFloat(5.0f) + 1280.0f;
+ Fishing_SpawnBubble(NULL, play->specialEffects, &bubblePos, Rand_ZeroFloat(0.02f) + 0.03f, 1);
}
- Math_ApproachS(&this->unk_172, (Math_SinS(this->unk_15C * 0x800) * 2500.0f) + 2500.0f, 2, 0x7D0);
- Math_ApproachS(&this->unk_174, Math_SinS(this->unk_15C * 0xA00) * 1500.0f, 2, 0x7D0);
+ Math_ApproachS(&this->fishLimbEFRotYDelta, (Math_SinS(this->stateAndTimer * 0x800) * 2500.0f) + 2500.0f, 2, 0x7D0);
+ Math_ApproachS(&this->fishLimb89RotYDelta, Math_SinS(this->stateAndTimer * 0xA00) * 1500.0f, 2, 0x7D0);
this->unk_190 = 0.3f;
this->unk_194 = 1000.0f / 3.0f;
return;
case 10:
- this->unk_1B4 = this->actor.home.pos;
+ this->fishTargetPos = this->actor.home.pos;
Math_ApproachF(&this->actor.speedXZ, 2.0f, 1.0f, 0.5f);
- Math_ApproachF(&this->unk_1B0, 4096.0f, 1.0f, 256.0f);
+ Math_ApproachF(&this->rotationStep, 4096.0f, 1.0f, 256.0f);
- if (sp124 < 40.0f) {
- this->unk_158 = 11;
+ if (distToTarget < 40.0f) {
+ this->fishState = 11;
this->unk_190 = 0.4f;
this->unk_194 = 500.0f;
}
func_80B70ED4(this, input);
- if (this->actor.xzDistToPlayer < (250.0f * sp118)) {
- this->unk_15A = this->unk_158 = 0;
+ if (this->actor.xzDistToPlayer < (250.0f * playerSpeedMod)) {
+ this->fishStateNext = this->fishState = 0;
this->unk_1A4 = 1000;
this->unk_1A2 = 200;
- this->unk_17A[1] = 50;
+ this->timerArray[1] = 50;
}
break;
case 11:
- this->unk_1B4 = this->actor.home.pos;
+ this->fishTargetPos = this->actor.home.pos;
Math_ApproachF(&this->actor.speedXZ, 0.0f, 1.0f, 0.05f);
- Math_ApproachF(&this->unk_1B0, 0.0f, 1.0f, 256.0f);
+ Math_ApproachF(&this->rotationStep, 0.0f, 1.0f, 256.0f);
- if (sp124 >= 40.0f) {
- this->unk_158 = 10;
+ if (distToTarget >= 40.0f) {
+ this->fishState = 10;
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
}
func_80B70ED4(this, input);
- if (this->actor.xzDistToPlayer < (250.0f * sp118)) {
- this->unk_15A = this->unk_158 = 0;
+ if (this->actor.xzDistToPlayer < (250.0f * playerSpeedMod)) {
+ this->fishStateNext = this->fishState = 0;
this->unk_1A4 = 1000;
this->unk_1A2 = 200;
- this->unk_17A[1] = 50;
+ this->timerArray[1] = 50;
}
if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) {
if ((gSaveContext.dayTime >= 0xC000) && (gSaveContext.dayTime <= 0xC01B)) {
- this->unk_158 = 7;
- this->unk_17A[3] = (s16)Rand_ZeroFloat(150.0f) + 200;
+ this->fishState = 7;
+ this->timerArray[3] = (s16)Rand_ZeroFloat(150.0f) + 200;
}
if ((gSaveContext.dayTime >= 0x3AAA) && (gSaveContext.dayTime <= 0x3AC5)) {
- this->unk_158 = 7;
- this->unk_17A[3] = (s16)Rand_ZeroFloat(150.0f) + 200;
+ this->fishState = 7;
+ this->timerArray[3] = (s16)Rand_ZeroFloat(150.0f) + 200;
}
}
if (KREG(15) != 0) {
KREG(15) = 0;
- this->unk_158 = 7;
- this->unk_17A[3] = (s16)Rand_ZeroFloat(150.0f) + 2000;
+ this->fishState = 7;
+ this->timerArray[3] = (s16)Rand_ZeroFloat(150.0f) + 2000;
}
break;
case 0:
Math_ApproachF(&this->actor.speedXZ, 1.0f, 1.0f, 0.05f);
- Math_ApproachF(&this->unk_1B0, 0.0f, 1.0f, 256.0f);
+ Math_ApproachF(&this->rotationStep, 0.0f, 1.0f, 256.0f);
- if (this->unk_17A[0] == 0) {
+ if (this->timerArray[0] == 0) {
if (this->unk_1A4 == 0) {
- this->unk_158 = this->unk_15A = 10;
+ this->fishState = this->fishStateNext = 10;
} else {
- this->unk_158 = 1;
- this->unk_17A[0] = (s16)Rand_ZeroFloat(30.0f) + 10;
- this->unk_1B4.x = Rand_CenteredFloat(300.0f);
- this->unk_1B4.y = (WATER_SURFACE_Y(play) - 50.0f) - Rand_ZeroFloat(50.0f);
- this->unk_1B4.z = Rand_CenteredFloat(300.0f);
+ this->fishState = 1;
+ this->timerArray[0] = (s16)Rand_ZeroFloat(30.0f) + 10;
+ this->fishTargetPos.x = Rand_CenteredFloat(300.0f);
+ this->fishTargetPos.y = (WATER_SURFACE_Y(play) - 50.0f) - Rand_ZeroFloat(50.0f);
+ this->fishTargetPos.z = Rand_CenteredFloat(300.0f);
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
}
}
- if (D_80B7E0B6 == 2) {
+ if (sLureEquipped == FS_LURE_SINKING) {
func_80B70ED4(this, input);
} else {
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
@@ -3193,36 +3223,36 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
break;
case 1:
- if (this->unk_150 == 1) {
- this->unk_158 = -1;
+ if (this->isLoach == 1) {
+ this->fishState = -1;
this->unk_1A4 = 20000;
this->unk_1A2 = 20000;
- this->unk_1B4.x = 0.0f;
- this->unk_1B4.y = -140.0f;
- this->unk_1B4.z = 0.0f;
+ this->fishTargetPos.x = 0.0f;
+ this->fishTargetPos.y = -140.0f;
+ this->fishTargetPos.z = 0.0f;
} else {
- Math_ApproachF(&this->unk_1B0, 4096.0f, 1.0f, 256.0f);
+ Math_ApproachF(&this->rotationStep, 4096.0f, 1.0f, 256.0f);
- if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_17A[1] != 0)) {
- Math_ApproachF(&this->unk_1B0, 8192.0f, 1.0f, 768.0f);
+ if ((this->actor.xzDistToPlayer < (250.0f * playerSpeedMod)) || (this->timerArray[1] != 0)) {
+ Math_ApproachF(&this->rotationStep, 8192.0f, 1.0f, 768.0f);
Math_ApproachF(&this->actor.speedXZ, 4.2f, 1.0f, 0.75);
this->unk_190 = 1.2f;
this->unk_194 = 4000.0f;
- this->unk_17A[0] = 20;
+ this->timerArray[0] = 20;
} else {
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
Math_ApproachF(&this->actor.speedXZ, 1.5f, 1.0f, 0.1f);
}
- if ((this->unk_17A[0] == 0) || (sp124 < 50.0f)) {
- this->unk_158 = 0;
- this->unk_17A[0] = (s16)Rand_ZeroFloat(30.0f) + 3;
+ if ((this->timerArray[0] == 0) || (distToTarget < 50.0f)) {
+ this->fishState = 0;
+ this->timerArray[0] = (s16)Rand_ZeroFloat(30.0f) + 3;
this->unk_190 = 1.0f;
this->unk_194 = 500.0f;
}
- if (D_80B7E0B6 == 2) {
+ if (sLureEquipped == FS_LURE_SINKING) {
func_80B70ED4(this, input);
} else {
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
@@ -3230,57 +3260,57 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
}
break;
- case -1:
- Math_ApproachS(&this->unk_166, 0, 0x14, 0x20);
+ case -1: // loach state 1
+ Math_ApproachS(&this->rotationTarget.x, 0, 0x14, 0x20);
- if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_17A[1] != 0)) {
+ if ((this->actor.xzDistToPlayer < (250.0f * playerSpeedMod)) || (this->timerArray[1] != 0)) {
Math_ApproachF(&this->actor.speedXZ, 3.0f, 1.0f, 0.75);
this->unk_190 = 1.0f;
- this->unk_17A[0] = 20;
+ this->timerArray[0] = 20;
this->unk_194 = 4000.0f;
- Math_ApproachF(&this->unk_1B0, 4096.0f, 1.0f, 256.0f);
+ Math_ApproachF(&this->rotationStep, 4096.0f, 1.0f, 256.0f);
if ((play->gameplayFrames % 32) == 0) {
- this->unk_1B4.x = Rand_CenteredFloat(600.0f);
- this->unk_1B4.z = Rand_CenteredFloat(600.0f);
- this->unk_1B4.y = -120.0f;
+ this->fishTargetPos.x = Rand_CenteredFloat(600.0f);
+ this->fishTargetPos.z = Rand_CenteredFloat(600.0f);
+ this->fishTargetPos.y = -120.0f;
}
- } else if (sp124 > 50.0f) {
+ } else if (distToTarget > 50.0f) {
this->unk_190 = 0.8f;
this->unk_194 = 1500.0f;
Math_ApproachF(&this->actor.speedXZ, 1.0f, 1.0f, 0.1f);
- Math_ApproachF(&this->unk_1B0, 2048.0f, 1.0f, 128.0f);
+ Math_ApproachF(&this->rotationStep, 2048.0f, 1.0f, 128.0f);
} else {
this->unk_190 = 0.4f;
this->unk_194 = 500.0f;
Math_ApproachZeroF(&this->actor.speedXZ, 1.0f, 0.02f);
- Math_ApproachF(&this->unk_1B0, 0.0f, 1.0f, 256.0f);
+ Math_ApproachF(&this->rotationStep, 0.0f, 1.0f, 256.0f);
}
if (this->unk_1A4 == 0) {
- this->unk_158 = 10;
- this->unk_15A = 10;
+ this->fishState = 10;
+ this->fishStateNext = 10;
} else if ((KREG(2) != 0) || (((this->unk_1A4 & 0x7FF) == 0) && (this->unk_1A4 < 15000))) {
KREG(2) = 0;
- this->unk_158 = -2;
+ this->fishState = -2;
this->actor.world.rot.x = this->actor.shape.rot.x = 0;
- this->unk_1B4.y = WATER_SURFACE_Y(play) + 10.0f;
- this->unk_1B4.x = Rand_ZeroFloat(50.0f);
- this->unk_1B4.z = Rand_ZeroFloat(50.0f);
+ this->fishTargetPos.y = WATER_SURFACE_Y(play) + 10.0f;
+ this->fishTargetPos.x = Rand_ZeroFloat(50.0f);
+ this->fishTargetPos.z = Rand_ZeroFloat(50.0f);
}
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
break;
case -2:
- if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_17A[1] != 0)) {
- this->unk_158 = -1;
- this->unk_1B4.y = -120.0f;
+ if ((this->actor.xzDistToPlayer < (250.0f * playerSpeedMod)) || (this->timerArray[1] != 0)) {
+ this->fishState = -1;
+ this->fishTargetPos.y = -120.0f;
} else {
this->unk_190 = 0.6f;
this->unk_194 = 1000.0f;
- Math_ApproachS(&this->unk_166, -0x1000, 0x14, 0x100);
+ Math_ApproachS(&this->rotationTarget.x, -0x1000, 0x14, 0x100);
if (this->actor.world.pos.y < (WATER_SURFACE_Y(play) - 20.0f)) {
Math_ApproachF(&this->actor.speedXZ, 0.5f, 1.0f, 0.1f);
@@ -3289,11 +3319,11 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
if ((this->actor.speedXZ == 0.0f) ||
(this->actor.world.pos.y > (WATER_SURFACE_Y(play) - 5.0f))) {
- this->unk_1B4.x = Rand_ZeroFloat(300.0f);
- this->unk_1B4.z = Rand_ZeroFloat(300.0f);
- this->unk_1B4.y = this->actor.floorHeight + 10.0f;
- this->unk_158 = -25;
- this->unk_1B0 = 0.0f;
+ this->fishTargetPos.x = Rand_ZeroFloat(300.0f);
+ this->fishTargetPos.z = Rand_ZeroFloat(300.0f);
+ this->fishTargetPos.y = this->actor.floorHeight + 10.0f;
+ this->fishState = -25;
+ this->rotationStep = 0.0f;
spB8 = this->fishMouthPos;
spB8.y = WATER_SURFACE_Y(play);
@@ -3307,99 +3337,99 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
}
}
- Math_ApproachF(&this->unk_1B0, 2048.0f, 1.0f, 128.0f);
+ Math_ApproachF(&this->rotationStep, 2048.0f, 1.0f, 128.0f);
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
}
break;
case -25:
- if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_17A[1] != 0)) {
- this->unk_158 = -1;
- this->unk_1B4.y = -120.0f;
+ if ((this->actor.xzDistToPlayer < (250.0f * playerSpeedMod)) || (this->timerArray[1] != 0)) {
+ this->fishState = -1;
+ this->fishTargetPos.y = -120.0f;
} else {
- Math_ApproachS(&this->unk_166, 0x1000, 0x14, 0x6A);
+ Math_ApproachS(&this->rotationTarget.x, 0x1000, 0x14, 0x6A);
- if (sp124 > 40.0f) {
+ if (distToTarget > 40.0f) {
this->unk_190 = 0.7f;
this->unk_194 = 1200.0f;
Math_ApproachF(&this->actor.speedXZ, 0.5f, 1.0f, 0.01f);
- Math_ApproachF(&this->unk_1B0, 2048.0f, 1.0f, 128.0f);
+ Math_ApproachF(&this->rotationStep, 2048.0f, 1.0f, 128.0f);
} else {
- this->unk_158 = -1;
+ this->fishState = -1;
}
}
break;
case 2:
if (((this->actor.params + D_80B7E118) & 1) != 0) {
- sp10C.x = 10.0f;
+ multiVecSrc.x = 10.0f;
} else {
- sp10C.x = -10.0f;
+ multiVecSrc.x = -10.0f;
}
- sp10C.y = 0.0f;
- sp10C.z = 0.0f;
+ multiVecSrc.y = 0.0f;
+ multiVecSrc.z = 0.0f;
Matrix_RotateY(sLureRot.y, MTXMODE_NEW);
- Matrix_MultVec3f(&sp10C, &sp100);
+ Matrix_MultVec3f(&multiVecSrc, &targetPosOffset);
- this->unk_1B4.x = sLurePos.x + sp100.x;
- this->unk_1B4.z = sLurePos.z + sp100.z;
+ this->fishTargetPos.x = sLurePos.x + targetPosOffset.x;
+ this->fishTargetPos.z = sLurePos.z + targetPosOffset.z;
- if (D_80B7E0B6 == 2) {
- this->unk_1B4.y = sLurePos.y;
- } else if (this->unk_150 == 0) {
- this->unk_1B4.y = sLurePos.y - 15.0f;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ this->fishTargetPos.y = sLurePos.y;
+ } else if (this->isLoach == 0) {
+ this->fishTargetPos.y = sLurePos.y - 15.0f;
} else {
- this->unk_1B4.y = sLurePos.y - 5.0f;
+ this->fishTargetPos.y = sLurePos.y - 5.0f;
}
- if (this->unk_1B4.y <= this->actor.floorHeight) {
- this->unk_1B4.y = this->actor.floorHeight + 3.0f;
+ if (this->fishTargetPos.y <= this->actor.floorHeight) {
+ this->fishTargetPos.y = this->actor.floorHeight + 3.0f;
}
- if ((D_80B7E0B6 != 2) && (this->unk_1B4.y < this->actor.world.pos.y)) {
- Math_ApproachF(&this->actor.world.pos.y, this->unk_1B4.y, 0.1f,
- (this->actor.world.pos.y - this->unk_1B4.y) * 0.1f);
+ if ((sLureEquipped != FS_LURE_SINKING) && (this->fishTargetPos.y < this->actor.world.pos.y)) {
+ Math_ApproachF(&this->actor.world.pos.y, this->fishTargetPos.y, 0.1f,
+ (this->actor.world.pos.y - this->fishTargetPos.y) * 0.1f);
}
- Math_ApproachF(&this->unk_1B0, 8192.0f, 1.0f, (KREG(16) * 128) + 384.0f);
+ Math_ApproachF(&this->rotationStep, 8192.0f, 1.0f, (KREG(16) * 128) + 384.0f);
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
- this->unk_1A8 += 0.005f;
+ this->perception += 0.005f;
}
- if (D_80B7E120 != 0) {
- if (D_80B7E120 == 1) {
- this->unk_1A8 += 0.01f;
+ if (sWiggleAttraction != 0) {
+ if (sWiggleAttraction == 1) {
+ this->perception += 0.01f;
} else {
- this->unk_1A8 += 0.05f;
+ this->perception += 0.05f;
}
- D_80B7E120 = 0;
+ sWiggleAttraction = 0;
}
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
- this->unk_1A8 += 0.008f;
+ this->perception += 0.008f;
}
- if (sp124 < ((this->unk_1AC * 0.5f) + 20.0f)) {
+ if (distToTarget < ((this->fishLength * 0.5f) + 20.0f)) {
if (this->unk_15E == 0) {
this->unk_190 = 1.0f;
this->unk_194 = 500.0f;
- this->unk_17A[0] = (s16)Rand_ZeroFloat(10.0f) + 2;
+ this->timerArray[0] = (s16)Rand_ZeroFloat(10.0f) + 2;
}
Math_ApproachF(&this->actor.speedXZ, -0.2f, 1.0f, 0.1f);
this->unk_15E = 1;
} else {
if (this->unk_15E != 0) {
this->unk_190 = 1.0f;
- this->unk_1B0 = 0.0f;
+ this->rotationStep = 0.0f;
this->unk_194 = 3000.0f;
}
Math_ApproachF(&this->actor.speedXZ, 3.0f, 1.0f, 0.15f);
this->unk_15E = 0;
}
- if (this->unk_1AC >= 60.0f) {
+ if (this->fishLength >= 60.0f) {
multiplier = 0.3f;
- } else if (this->unk_1AC >= 45.0f) {
+ } else if (this->fishLength >= 45.0f) {
multiplier = 0.6f;
} else {
multiplier = 1.0f;
@@ -3409,202 +3439,203 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
multiplier *= 1.75f;
} else if ((gSaveContext.dayTime >= 0x3555) && (gSaveContext.dayTime <= 0x4AAA)) {
multiplier *= 1.5f;
- } else if (D_80B7E076 != 0) {
+ } else if (sFishingFoggy != 0) {
multiplier *= 1.5f;
- } else if ((u8)D_80B7A650 != 0) {
+ } else if ((u8)sStormStrength != 0) {
multiplier *= 3.0f;
}
- sp11C = 0.03f * multiplier;
- if (D_80B7E0B6 == 2) {
- sp11C *= 5.0f;
+ chance = 0.03f * multiplier;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ chance *= 5.0f;
}
if (getGuaranteeBite() == 1 ||
- ((this->unk_17A[0] == 1) || (Rand_ZeroOne() < sp11C)) &&
- ((Rand_ZeroOne() < (this->unk_1A8 * multiplier)) || ((this->unk_150 + 1) == KREG(69)))) {
- if (this->unk_150 == 0) {
- this->unk_158 = 3;
+ ((this->timerArray[0] == 1) || (Rand_ZeroOne() < chance)) &&
+ ((Rand_ZeroOne() < (this->perception * multiplier)) || ((this->isLoach + 1) == KREG(69)))) {
+ if (this->isLoach == 0) {
+ this->fishState = 3;
this->unk_190 = 1.2f;
this->unk_194 = 5000.0f;
- this->unk_17A[0] = Rand_ZeroFloat(10.0f);
+ this->timerArray[0] = Rand_ZeroFloat(10.0f);
} else {
- this->unk_158 = -3;
+ this->fishState = -3;
this->unk_190 = 1.0f;
this->unk_194 = 3000.0f;
- this->unk_17A[0] = 40;
+ this->timerArray[0] = 40;
}
- if (D_80B7E0B6 == 2) {
- this->unk_188 = Rand_ZeroFloat(1.5f) + 3.0f;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ this->speedTarget = Rand_ZeroFloat(1.5f) + 3.0f;
} else {
- this->unk_188 = Rand_ZeroFloat(1.5f) + 4.5f;
+ this->speedTarget = Rand_ZeroFloat(1.5f) + 4.5f;
}
}
- if ((D_80B7A694 != 3) || (this->unk_17A[2] == 0) ||
+ if ((sRodCastState != 3) || (this->timerArray[2] == 0) ||
(sqrtf(SQ(this->actor.world.pos.x) + SQ(this->actor.world.pos.z)) > 800.0f)) {
- this->unk_158 = this->unk_15A;
- this->unk_17A[1] = (s16)Rand_ZeroFloat(30.0f) + 50;
- this->unk_17A[0] = (s16)Rand_ZeroFloat(10.0f) + 5;
+ this->fishState = this->fishStateNext;
+ this->timerArray[1] = (s16)Rand_ZeroFloat(30.0f) + 50;
+ this->timerArray[0] = (s16)Rand_ZeroFloat(10.0f) + 5;
this->unk_190 = 1.0f;
- this->unk_1B0 = 0.0f;
+ this->rotationStep = 0.0f;
this->unk_194 = 2000.0f;
}
- if (this->actor.xzDistToPlayer < (100.0f * sp118)) {
- this->unk_15A = this->unk_158 = 0;
+ if (this->actor.xzDistToPlayer < (100.0f * playerSpeedMod)) {
+ this->fishStateNext = this->fishState = 0;
this->unk_1A4 = 1000;
this->unk_1A2 = 200;
- this->unk_17A[1] = 50;
+ this->timerArray[1] = 50;
}
break;
case 3:
- this->unk_151 = 6;
- sp134 = 2;
+ this->lilyTimer = 6;
+ rotXYScale = 2;
if ((((s16)player->actor.world.pos.x + D_80B7E118) & 1) != 0) {
- sp10C.x = 30.0f;
+ multiVecSrc.x = 30.0f;
} else {
- sp10C.x = -30.0f;
+ multiVecSrc.x = -30.0f;
}
- sp10C.y = 0.0f;
- sp10C.z = 30.0f;
+ multiVecSrc.y = 0.0f;
+ multiVecSrc.z = 30.0f;
Matrix_RotateY(sLureRot.y, MTXMODE_NEW);
- Matrix_MultVec3f(&sp10C, &sp100);
+ Matrix_MultVec3f(&multiVecSrc, &targetPosOffset);
- this->unk_1B4.x = sLurePos.x + sp100.x;
- this->unk_1B4.z = sLurePos.z + sp100.z;
- this->unk_1B4.y = sLurePos.y - 10.0f;
- this->unk_1B0 = 4096.0f;
- Math_ApproachF(&this->actor.speedXZ, this->unk_188 * 0.8f, 1.0f, 1.0f);
+ this->fishTargetPos.x = sLurePos.x + targetPosOffset.x;
+ this->fishTargetPos.z = sLurePos.z + targetPosOffset.z;
+ this->fishTargetPos.y = sLurePos.y - 10.0f;
+ this->rotationStep = 4096.0f;
+ Math_ApproachF(&this->actor.speedXZ, this->speedTarget * 0.8f, 1.0f, 1.0f);
- if ((D_80B7A694 != 3) || (sLurePos.y > (WATER_SURFACE_Y(play) + 5.0f)) ||
+ if ((sRodCastState != 3) || (sLurePos.y > (WATER_SURFACE_Y(play) + 5.0f)) ||
(sqrtf(SQ(sLurePos.x) + SQ(sLurePos.z)) > 800.0f)) {
- this->unk_158 = this->unk_15A;
- this->unk_17A[0] = 0;
+ this->fishState = this->fishStateNext;
+ this->timerArray[0] = 0;
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
- } else if ((this->unk_17A[0] == 0) || (sp124 < 30.0f)) {
- this->unk_158 = 4;
- this->unk_1B4 = sLurePos;
- this->unk_1B0 = 16384.0f;
+ } else if ((this->timerArray[0] == 0) || (distToTarget < 30.0f)) {
+ this->fishState = 4;
+ this->fishTargetPos = sLurePos;
+ this->rotationStep = 16384.0f;
this->unk_190 = 1.2f;
this->unk_194 = 5000.0f;
- this->unk_17A[0] = 20;
+ this->timerArray[0] = 20;
}
break;
case 4:
- Math_ApproachF(&this->unk_1B0, 16384.0f, 1.0f, 4096.0f);
- Math_ApproachS(&this->unk_170, 0x4E20, 4, 0x1388);
+ Math_ApproachF(&this->rotationStep, 16384.0f, 1.0f, 4096.0f);
+ Math_ApproachS(&this->fishLimbDRotZDelta, 0x4E20, 4, 0x1388);
- this->unk_151 = 50;
- sp134 = 2;
- this->unk_1B4 = sLurePos;
- Math_ApproachF(&this->actor.speedXZ, this->unk_188, 1.0f, 1.0f);
+ this->lilyTimer = 50;
+ rotXYScale = 2;
+ this->fishTargetPos = sLurePos;
+ Math_ApproachF(&this->actor.speedXZ, this->speedTarget, 1.0f, 1.0f);
- if ((D_80B7A694 != 3) || (this->unk_17A[0] == 0) || (sLurePos.y > (WATER_SURFACE_Y(play) + 5.0f)) ||
+ if ((sRodCastState != 3) || (this->timerArray[0] == 0) || (sLurePos.y > (WATER_SURFACE_Y(play) + 5.0f)) ||
(sqrtf(SQ(sLurePos.x) + SQ(sLurePos.z)) > 800.0f)) {
- this->unk_17A[0] = 0;
- this->unk_158 = this->unk_15A;
+ this->timerArray[0] = 0;
+ this->fishState = this->fishStateNext;
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
- } else if (sp124 < 10.0f) {
- if (func_80B70A2C(this, play, false)) {
- func_80B71278(this, 0);
+ } else if (distToTarget < 10.0f) {
+ if (Fishing_SplashBySize(this, play, false)) {
+ Fishing_FishLeapSfx(this, false);
}
- this->unk_158 = 5;
+ this->fishState = 5;
this->unk_190 = 1.2f;
this->unk_194 = 5000.0f;
- this->unk_17A[1] = 150;
- this->unk_17A[0] = 0;
- this->unk_17A[2] = 0;
- this->unk_17A[3] = 120;
+ this->timerArray[1] = 150;
+ this->timerArray[0] = 0;
+ this->timerArray[2] = 0;
+ this->timerArray[3] = 120;
- D_80B7A694 = 4;
+ sRodCastState = 4;
sFishingHookedFish = this;
sFishMouthOffset.y = 500.0f - Rand_ZeroFloat(400.0f);
- if (D_80B7E0B6 == 2) {
- if (this->unk_1AC > 70.0f) {
- phi_v0 = (s16)Rand_ZeroFloat(20.0f) + 10;
- } else if (this->unk_1AC > 60.0f) {
- phi_v0 = (s16)Rand_ZeroFloat(30.0f) + 20;
- } else if (this->unk_1AC > 50.0f) {
- phi_v0 = (s16)Rand_ZeroFloat(30.0f) + 30;
+ // get rumble time based on size and lure used.
+ if (sLureEquipped == FS_LURE_SINKING) {
+ if (this->fishLength > 70.0f) {
+ timer = (s16)Rand_ZeroFloat(20.0f) + 10;
+ } else if (this->fishLength > 60.0f) {
+ timer = (s16)Rand_ZeroFloat(30.0f) + 20;
+ } else if (this->fishLength > 50.0f) {
+ timer = (s16)Rand_ZeroFloat(30.0f) + 30;
} else {
- phi_v0 = (s16)Rand_ZeroFloat(40.0f) + 40;
+ timer = (s16)Rand_ZeroFloat(40.0f) + 40;
}
- D_80B7E122 = phi_v0;
- D_80B7E0A4 = phi_v0;
- func_800A9F6C(0.0f, 60, phi_v0 * 3, 10);
+ sLureBitTimer = timer;
+ sRumbleDelay = timer;
+ func_800A9F6C(0.0f, 60, timer * 3, 10);
} else {
- if (this->unk_1AC > 70.0f) {
- phi_v0 = (s16)Rand_ZeroFloat(5.0f) + 10;
- } else if (this->unk_1AC > 60.0f) {
- phi_v0 = (s16)Rand_ZeroFloat(5.0f) + 15;
- } else if (this->unk_1AC > 50.0f) {
- phi_v0 = (s16)Rand_ZeroFloat(5.0f) + 17;
+ if (this->fishLength > 70.0f) {
+ timer = (s16)Rand_ZeroFloat(5.0f) + 10;
+ } else if (this->fishLength > 60.0f) {
+ timer = (s16)Rand_ZeroFloat(5.0f) + 15;
+ } else if (this->fishLength > 50.0f) {
+ timer = (s16)Rand_ZeroFloat(5.0f) + 17;
} else {
- phi_v0 = (s16)Rand_ZeroFloat(5.0f) + 25;
+ timer = (s16)Rand_ZeroFloat(5.0f) + 25;
}
- D_80B7E122 = phi_v0;
- D_80B7E0A4 = phi_v0;
- func_800A9F6C(0.0f, 180, phi_v0 * 3, 10);
+ sLureBitTimer = timer;
+ sRumbleDelay = timer;
+ func_800A9F6C(0.0f, 180, timer * 3, 10);
}
- D_80B7E124 = 0;
- D_80B7E116 = 100;
- D_80B7E080 = 0;
+ sLineHooked = 0;
+ sRodPullback = 100;
+ sFishFightTime = 0;
}
break;
case -3:
- this->unk_151 = 50;
- this->unk_1B4 = sLurePos;
+ this->lilyTimer = 50;
+ this->fishTargetPos = sLurePos;
Math_ApproachF(&this->actor.speedXZ, 2.0f, 1.0f, 1.0f);
- if ((D_80B7A694 != 3) || (this->unk_17A[0] == 0) || (sLurePos.y > (WATER_SURFACE_Y(play) + 5.0f)) ||
+ if ((sRodCastState != 3) || (this->timerArray[0] == 0) || (sLurePos.y > (WATER_SURFACE_Y(play) + 5.0f)) ||
(sqrtf(SQ(sLurePos.x) + SQ(sLurePos.z)) > 800.0f)) {
- this->unk_17A[0] = 0;
+ this->timerArray[0] = 0;
this->unk_190 = 1.0f;
- this->unk_158 = this->unk_15A;
+ this->fishState = this->fishStateNext;
this->unk_194 = 2000.0f;
- } else if (sp124 < 10.0f) {
+ } else if (distToTarget < 10.0f) {
if (sLurePos.y > (WATER_SURFACE_Y(play) - 10.0f)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_JUMP_OUT_WATER);
func_80078884(NA_SE_PL_CATCH_BOOMERANG);
}
- func_80B70A2C(this, play, false);
- this->unk_158 = 5;
+ Fishing_SplashBySize(this, play, false);
+ this->fishState = 5;
this->unk_190 = 1.2f;
this->unk_194 = 5000.0f;
- this->unk_17A[1] = 150;
- this->unk_17A[0] = 0;
- this->unk_17A[2] = 0;
- this->unk_17A[3] = 120;
+ this->timerArray[1] = 150;
+ this->timerArray[0] = 0;
+ this->timerArray[2] = 0;
+ this->timerArray[3] = 120;
- D_80B7A694 = 4;
+ sRodCastState = 4;
sFishingHookedFish = this;
- if (D_80B7E0B6 == 2) {
- D_80B7E122 = 30;
- D_80B7E0A4 = 100;
+ if (sLureEquipped == FS_LURE_SINKING) {
+ sLureBitTimer = 30;
+ sRumbleDelay = 100;
func_800A9F6C(0.0f, 60, 90, 10);
} else {
- D_80B7E122 = 30;
- D_80B7E0A4 = 40;
+ sLureBitTimer = 30;
+ sRumbleDelay = 40;
func_800A9F6C(0.0f, 180, 90, 10);
}
- D_80B7E124 = 0;
- D_80B7E116 = 100;
- D_80B7E080 = 0;
+ sLineHooked = false;
+ sRodPullback = 100;
+ sFishFightTime = 0;
}
break;
@@ -3612,23 +3643,23 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->actor.uncullZoneForward = 1200.0f;
this->actor.uncullZoneScale = 200.0f;
- D_80B7E080++;
- osSyncPrintf("HIT FISH %dcm\n", (u8)this->unk_1AC);
+ sFishFightTime++;
+ osSyncPrintf("HIT FISH %dcm\n", (u8)this->fishLength);
- Math_ApproachS(&this->unk_170, 0x2AF8, 4, 0xBB8);
+ Math_ApproachS(&this->fishLimbDRotZDelta, 0x2AF8, 4, 0xBB8);
sFishingHookedFish = this;
Math_ApproachS(&player->actor.shape.rot.y, this->actor.yawTowardsPlayer + 0x8000, 5, 0x500);
- if (D_80B7E124 == 0) {
- if ((D_80B7FEA0 < 20) && ((D_80B7E0AE & 3) == 0)) {
- D_80B7FEA0++;
+ if (sLineHooked == 0) {
+ if ((sSinkingLureSegmentIndex < 20) && ((sLureTimer & 3) == 0)) {
+ sSinkingLureSegmentIndex++;
}
}
- if ((D_80B7E122 != 0) && (D_80B7E124 == 0)) {
- if (((input->rel.stick_y < -50) && (D_80B7A6C8 > -40)) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ if ((sLureBitTimer != 0) && (sLineHooked == 0)) { // pull the line to hook it
+ if (((input->rel.stick_y < -50) && (sStickAdjYPrev > -40)) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
if (input->rel.stick_y < -50) {
- temp_f0 = 40.0f - ((this->unk_1AC - 30.0f) * 1.333333f);
+ temp_f0 = 40.0f - ((this->fishLength - 30.0f) * 1.333333f);
if (temp_f0 > 0.0f) {
this->unk_152 = temp_f0;
this->unk_154 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
@@ -3636,106 +3667,106 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
}
}
- this->unk_198 = 1.7f;
- this->unk_19C = 7000.0f;
- D_80B7E124 = 1;
+ this->fishLimbRotPhaseStep = 1.7f;
+ this->fishLimbRotPhaseMag = 7000.0f;
+ sLineHooked = 1;
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_ENEMY | 0x800);
- D_80B7E0A6 = 0;
+ sFishingMusicDelay = 0;
- if (this->unk_150 == 1) {
- spA4 = (this->unk_1AC * 3.0f) + 120.0f;
+ if (this->isLoach == 1) {
+ rumbleStrength = (this->fishLength * 3.0f) + 120.0f;
} else {
- spA4 = (2.0f * this->unk_1AC) + 120.0f;
+ rumbleStrength = (2.0f * this->fishLength) + 120.0f;
}
- if (spA4 > 255.0f) {
- spA4 = 255.0f;
+ if (rumbleStrength > 255.0f) {
+ rumbleStrength = 255.0f;
}
- func_800A9F6C(0.0f, spA4, 120, 5);
- D_80B7E0A4 = 40;
- D_80B7FDA8 = 10;
+ func_800A9F6C(0.0f, rumbleStrength, 120, 5);
+ sRumbleDelay = 40;
+ sRodHitTimer = 10;
func_80078884(NA_SE_IT_FISHING_HIT);
}
}
if (this->actor.world.pos.y < WATER_SURFACE_Y(play)) {
- if (this->unk_17A[1] > 30) {
+ if (this->timerArray[1] > 30) {
phi_v0_2 = 7;
} else {
phi_v0_2 = 0xF;
}
- if (((this->unk_15C & phi_v0_2) == 0) && (Rand_ZeroOne() < 0.75f) && (D_80B7E0A4 == 0)) {
- if (this->unk_1AC >= 70.0f) {
- spA4 = 255.0f;
- } else if (this->unk_1AC >= 60.0f) {
- spA4 = 230.0f;
- } else if (this->unk_1AC >= 50.0f) {
- spA4 = 200.0f;
- } else if (this->unk_1AC >= 40.0f) {
- spA4 = 170.0f;
+ if (((this->stateAndTimer & phi_v0_2) == 0) && (Rand_ZeroOne() < 0.75f) && (sRumbleDelay == 0)) {
+ if (this->fishLength >= 70.0f) {
+ rumbleStrength = 255.0f;
+ } else if (this->fishLength >= 60.0f) {
+ rumbleStrength = 230.0f;
+ } else if (this->fishLength >= 50.0f) {
+ rumbleStrength = 200.0f;
+ } else if (this->fishLength >= 40.0f) {
+ rumbleStrength = 170.0f;
} else {
- spA4 = 140.0f;
+ rumbleStrength = 140.0f;
}
if (phi_v0_2 == 0xF) {
- spA4 *= 3.0f / 4.0f;
+ rumbleStrength *= 3.0f / 4.0f;
}
- func_800A9F6C(0.0f, spA4, (s16)Rand_ZeroFloat(5.0f) + 10, 5);
+ func_800A9F6C(0.0f, rumbleStrength, (s16)Rand_ZeroFloat(5.0f) + 10, 5);
}
- if (this->unk_17A[1] > 30) {
- if (this->unk_17A[0] == 0) {
- sp10C.x = 0.0f;
- sp10C.y = 0.0f;
- sp10C.z = 200.0f;
+ if (this->timerArray[1] > 30) {
+ if (this->timerArray[0] == 0) {
+ multiVecSrc.x = 0.0f;
+ multiVecSrc.y = 0.0f;
+ multiVecSrc.z = 200.0f;
- for (spA2 = 0; spA2 < 100; spA2++) {
+ for (attempts = 0; attempts < 100; attempts++) {
Matrix_RotateY(Rand_CenteredFloat(3.0f * M_PI / 4.0f) +
(((this->actor.yawTowardsPlayer + 0x8000) / 32768.0f) * M_PI),
MTXMODE_NEW);
- Matrix_MultVec3f(&sp10C, &sp100);
+ Matrix_MultVec3f(&multiVecSrc, &targetPosOffset);
- this->unk_1B4.x = this->actor.world.pos.x + sp100.x;
- this->unk_1B4.z = this->actor.world.pos.z + sp100.z;
+ this->fishTargetPos.x = this->actor.world.pos.x + targetPosOffset.x;
+ this->fishTargetPos.z = this->actor.world.pos.z + targetPosOffset.z;
- if ((SQ(this->unk_1B4.x) + SQ(this->unk_1B4.z)) < SQ(750.0f)) {
+ if ((SQ(this->fishTargetPos.x) + SQ(this->fishTargetPos.z)) < SQ(750.0f)) {
break;
}
}
- if ((Rand_ZeroOne() < 0.1f) && (this->unk_17A[3] == 0)) {
- if (this->unk_1AC >= 60.0f) {
- phi_a1 = 255;
- } else if (this->unk_1AC >= 50.0f) {
- phi_a1 = 200;
+ if ((Rand_ZeroOne() < 0.1f) && (this->timerArray[3] == 0)) {
+ if (this->fishLength >= 60.0f) {
+ rumbleStrength8 = 255;
+ } else if (this->fishLength >= 50.0f) {
+ rumbleStrength8 = 200;
} else {
- phi_a1 = 180;
+ rumbleStrength8 = 180;
}
- func_800A9F6C(0.0f, phi_a1, 90, 2);
- this->unk_17A[0] = 20;
- this->unk_17A[1] = 100;
- this->unk_17A[2] = 20;
- this->unk_17A[3] = 100;
- this->unk_1B4.y = 300.0f;
- D_80B7E0A4 = 0x28;
- D_80B7E116 = (s16)Rand_ZeroFloat(30.0f) + 20;
+ func_800A9F6C(0.0f, rumbleStrength8, 90, 2);
+ this->timerArray[0] = 20;
+ this->timerArray[1] = 100;
+ this->timerArray[2] = 20;
+ this->timerArray[3] = 100;
+ this->fishTargetPos.y = 300.0f;
+ sRumbleDelay = 0x28;
+ sRodPullback = (s16)Rand_ZeroFloat(30.0f) + 20;
} else {
- this->unk_17A[0] = (s16)Rand_ZeroFloat(10.0f) + 3;
- this->unk_17A[2] = 0;
- this->unk_1B4.y = -70.0f - Rand_ZeroFloat(150.0f);
+ this->timerArray[0] = (s16)Rand_ZeroFloat(10.0f) + 3;
+ this->timerArray[2] = 0;
+ this->fishTargetPos.y = -70.0f - Rand_ZeroFloat(150.0f);
}
}
- if (this->unk_17A[2] != 0) {
- D_80B7E11C = 0.0f;
+ if (this->timerArray[2] != 0) {
+ sRodReelingSpeed = 0.0f;
this->unk_190 = 1.6f;
this->unk_194 = 6000.0f;
Math_ApproachF(&this->actor.speedXZ, 7.5f, 1.0f, 1.0f);
- Math_ApproachS(&this->unk_170, 0x4E20, 2, 0xFA0);
+ Math_ApproachS(&this->fishLimbDRotZDelta, 0x4E20, 2, 0xFA0);
} else {
- if ((D_80B7E124 == 0) && (D_80B7E0B6 == 2)) {
+ if ((sLineHooked == 0) && (sLureEquipped == FS_LURE_SINKING)) {
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
Math_ApproachF(&this->actor.speedXZ, 3.0f, 1.0f, 0.2f);
@@ -3745,15 +3776,15 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
Math_ApproachF(&this->actor.speedXZ, 5.0f, 1.0f, 0.5f);
}
- if (this->unk_150 == 0) {
- D_80B7E11C = 1.0f - (this->unk_1AC * 0.00899f);
+ if (this->isLoach == 0) {
+ sRodReelingSpeed = 1.0f - (this->fishLength * 0.00899f);
} else {
- D_80B7E11C = 1.0f - (this->unk_1AC * 0.00899f * 1.4f);
+ sRodReelingSpeed = 1.0f - (this->fishLength * 0.00899f * 1.4f);
}
}
} else {
- if (((this->unk_17A[1] & 0xF) == 0) && CHECK_BTN_ALL(input->cur.button, BTN_A) &&
- (!(this->unk_1AC >= 60.0f) || (D_80B7E080 >= 2000))) {
+ if (((this->timerArray[1] & 0xF) == 0) && CHECK_BTN_ALL(input->cur.button, BTN_A) &&
+ (!(this->fishLength >= 60.0f) || (sFishFightTime >= 2000))) {
this->unk_152 = (s16)Rand_ZeroFloat(30.0f) + 15;
this->unk_154 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
}
@@ -3761,57 +3792,57 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->unk_190 = 1.0f;
this->unk_194 = 4500.0f;
- if (this->unk_150 == 0) {
- D_80B7E11C = 1.3f - (this->unk_1AC * 0.00899f);
+ if (this->isLoach == 0) {
+ sRodReelingSpeed = 1.3f - (this->fishLength * 0.00899f);
} else {
- D_80B7E11C = 1.3f - (this->unk_1AC * 0.00899f * 1.4f);
+ sRodReelingSpeed = 1.3f - (this->fishLength * 0.00899f * 1.4f);
}
Math_ApproachF(&this->actor.speedXZ, 2.0f, 1.0f, 0.5f);
- if (this->unk_17A[1] == 0) {
+ if (this->timerArray[1] == 0) {
this->unk_152 = 0;
- if (D_80B7E080 < 2000) {
- this->unk_17A[1] = (s16)Rand_ZeroFloat(50.0f) + 50;
- } else if (D_80B7E080 < 3000) {
- this->unk_17A[1] = (s16)Rand_ZeroFloat(20.0f) + 30;
+ if (sFishFightTime < 2000) {
+ this->timerArray[1] = (s16)Rand_ZeroFloat(50.0f) + 50;
+ } else if (sFishFightTime < 3000) {
+ this->timerArray[1] = (s16)Rand_ZeroFloat(20.0f) + 30;
} else {
- this->unk_17A[1] = (s16)Rand_ZeroFloat(10.0f) + 25;
+ this->timerArray[1] = (s16)Rand_ZeroFloat(10.0f) + 25;
}
}
}
}
- if (D_80B7E074 != 0) {
- D_80B7E11C = 0.0f;
+ if (sReelLock != 0) {
+ sRodReelingSpeed = 0.0f;
}
- if (D_80B7E124 || (D_80B7E0B6 != 2)) {
+ if (sLineHooked || (sLureEquipped != FS_LURE_SINKING)) {
if (this->actor.speedXZ < 3.0f) {
- if ((D_80B7E0AE & 8) != 0) {
- sp100.x = -0.8f;
+ if ((sLureTimer & 8) != 0) {
+ targetPosOffset.x = -0.8f;
} else {
- sp100.x = -0.75f;
+ targetPosOffset.x = -0.75f;
}
} else {
- if ((D_80B7E0AE & 4) != 0) {
- sp100.x = -0.9f;
+ if ((sLureTimer & 4) != 0) {
+ targetPosOffset.x = -0.9f;
} else {
- sp100.x = -0.85f;
+ targetPosOffset.x = -0.85f;
}
}
Math_ApproachF(&D_80B7A6C0, 35.0f, 0.1f, 3.5f);
- Math_ApproachF(&D_80B7A6BC, sp100.x, 0.3f, 0.1f);
+ Math_ApproachF(&D_80B7A6BC, targetPosOffset.x, 0.3f, 0.1f);
}
sReelLinePos[LINE_SEG_COUNT - 1] = this->fishMouthPos;
- sp10C.x = sReelLinePos[LINE_SEG_COUNT - 1].x - sReelLinePos[LINE_SEG_COUNT - 2].x;
- sp10C.y = sReelLinePos[LINE_SEG_COUNT - 1].y - sReelLinePos[LINE_SEG_COUNT - 2].y;
- sp10C.z = sReelLinePos[LINE_SEG_COUNT - 1].z - sReelLinePos[LINE_SEG_COUNT - 2].z;
+ multiVecSrc.x = sReelLinePos[LINE_SEG_COUNT - 1].x - sReelLinePos[LINE_SEG_COUNT - 2].x;
+ multiVecSrc.y = sReelLinePos[LINE_SEG_COUNT - 1].y - sReelLinePos[LINE_SEG_COUNT - 2].y;
+ multiVecSrc.z = sReelLinePos[LINE_SEG_COUNT - 1].z - sReelLinePos[LINE_SEG_COUNT - 2].z;
- if ((SQ(sp10C.x) + SQ(sp10C.y) + SQ(sp10C.z)) > SQ(20.0f)) {
+ if ((SQ(multiVecSrc.x) + SQ(multiVecSrc.y) + SQ(multiVecSrc.z)) > SQ(20.0f)) {
Math_ApproachF(&this->actor.world.pos.x, sReelLinePos[LINE_SEG_COUNT - 2].x, 0.2f,
2.0f * (this->actor.speedXZ * 1.5f));
Math_ApproachF(&this->actor.world.pos.y, sReelLinePos[LINE_SEG_COUNT - 2].y, 0.2f,
@@ -3821,167 +3852,175 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
}
if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (input->rel.stick_y < -30)) {
- if (D_80B7E116 < 100) {
- D_80B7E116++;
+ if (sRodPullback < 100) {
+ sRodPullback++;
}
} else {
- if (D_80B7E116 != 0) {
- D_80B7E116--;
+ if (sRodPullback != 0) {
+ sRodPullback--;
}
}
- if ((D_80B7A694 < 3) || ((D_80B7E074 != 0) && (D_80B7E080 > 50)) || (D_80B7E080 >= 6000) ||
- ((D_80B7E122 == 0) && (D_80B7E124 == 0)) || (D_80B7E116 == 0) ||
- (((D_80B7E0AE & 0x7F) == 0) && (Rand_ZeroOne() < 0.05f) && (D_80B7E0B6 != 2) && (KREG(69) == 0) && (getFishNeverEscape() == 0))) {
- D_80B7A67C = 20;
+ if ((sRodCastState < 3) || ((sReelLock != 0) && (sFishFightTime > 50)) || (sFishFightTime >= 6000) ||
+ ((sLureBitTimer == 0) && (sLineHooked == 0)) || (sRodPullback == 0) ||
+ (((sLureTimer & 0x7F) == 0) && (Rand_ZeroOne() < 0.05f) && (sLureEquipped != FS_LURE_SINKING) && (KREG(69) == 0) && (getFishNeverEscape() == 0))) {
+ sFishingCaughtTextDelay = 20;
- if ((D_80B7E122 == 0) && (D_80B7E124 == 0)) {
- D_80B7E086 = 0x4081;
- if (((sLinkAge == 1) && (HIGH_SCORE(HS_FISHING) & 0x400)) ||
- ((sLinkAge != 1) && (HIGH_SCORE(HS_FISHING) & 0x800))) {
- D_80B7A67C = 0;
+ if ((sLureBitTimer == 0) && (sLineHooked == 0)) {
+ sFishingCaughtTextId = 0x4081;
+ if (((sLinkAge == LINK_AGE_CHILD) && (HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_CHILD)) ||
+ ((sLinkAge != LINK_AGE_CHILD) && (HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_ADULT))) {
+ sFishingCaughtTextDelay = 0;
}
} else {
- D_80B7E086 = 0x4082;
+ sFishingCaughtTextId = 0x4082;
func_800A9F6C(0.0f, 1, 3, 1);
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x0A00FF);
}
- this->unk_158 = this->unk_15A = 0;
+ this->fishState = this->fishStateNext = 0;
this->unk_1A4 = 10000;
this->unk_1A2 = 500;
- this->unk_17A[1] = 50;
- this->unk_17A[0] = 0;
+ this->timerArray[1] = 50;
+ this->timerArray[0] = 0;
this->unk_190 = 1.0f;
this->unk_194 = 3000.0f;
- if (D_80B7A694 == 4) {
- D_80B7A694 = 3;
+ if (sRodCastState == 4) {
+ sRodCastState = 3;
}
- D_80B7E0A6 = 50;
- D_80B7E11C = 0.5f;
+ sFishingMusicDelay = 50;
+ sRodReelingSpeed = 0.5f;
this->unk_152 = 0;
} else if (this->actor.xzDistToPlayer < (KREG(59) + 50.0f) || getInstantFish() == 1) {
- this->unk_158 = 6;
- this->unk_17A[0] = 100;
+ this->fishState = 6;
+ this->timerArray[0] = 100;
player->unk_860 = 3;
func_800A9F6C(0.0f, 1, 3, 1);
- D_80B7E084++;
+ sFishesCaught++;
func_80064520(play, &play->csCtx);
- D_80B7A6CC = 100;
- D_80B7FEC8 = 45.0f;
- D_80B7A694 = 5;
+ sFishingPlayerCinematicState = 100;
+ sCatchCamX = 45.0f;
+ sRodCastState = 5;
this->unk_190 = 1.0f;
this->unk_194 = 500.0f;
- this->unk_19C = 5000.0f;
+ this->fishLimbRotPhaseMag = 5000.0f;
if (this->actor.world.pos.y <= WATER_SURFACE_Y(play)) {
- func_80B71278(this, 1);
- func_80B70A2C(this, play, true);
+ Fishing_FishLeapSfx(this, true);
+ Fishing_SplashBySize(this, play, true);
}
- goto case_6;
+ goto hoistCatch;
}
break;
- case_6:
+ hoistCatch:
case 6:
- Math_ApproachS(&this->unk_170, 0x2AF8, 2, 0xFA0);
- Math_ApproachF(&D_80B7FEC8, 15.0f, 0.05f, 0.75f);
+ Math_ApproachS(&this->fishLimbDRotZDelta, 0x2AF8, 2, 0xFA0);
+ Math_ApproachF(&sCatchCamX, 15.0f, 0.05f, 0.75f);
- sp10C.x = D_80B7FEC8;
- if (sLinkAge != 1) {
- sp10C.y = 30.0f;
- sp10C.z = 55.0f;
+ multiVecSrc.x = sCatchCamX;
+ if (sLinkAge != LINK_AGE_CHILD) {
+ multiVecSrc.y = 30.0f;
+ multiVecSrc.z = 55.0f;
} else {
- sp10C.y = 10.0f;
- sp10C.z = 50.0f;
+ multiVecSrc.y = 10.0f;
+ multiVecSrc.z = 50.0f;
}
Matrix_RotateY((player->actor.shape.rot.y / 32768.0f) * M_PI, MTXMODE_NEW);
- Matrix_MultVec3f(&sp10C, &sCameraEye);
+ Matrix_MultVec3f(&multiVecSrc, &sCameraEye);
sCameraEye.x += player->actor.world.pos.x;
sCameraEye.y += player->actor.world.pos.y;
sCameraEye.z += player->actor.world.pos.z;
sCameraAt = player->actor.world.pos;
- if (sLinkAge != 1) {
+ if (sLinkAge != LINK_AGE_CHILD) {
sCameraAt.y += 40.0f;
} else {
sCameraAt.y += 25.0f;
}
- if (this->unk_17A[0] == 90) {
+ if (this->timerArray[0] == 90) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_HEART_GET | 0x900);
- D_80B7A67C = 40;
+ sFishingCaughtTextDelay = 40;
- if (this->unk_150 == 0) {
- D_80B7A678 = this->unk_1AC;
+ if (this->isLoach == 0) {
+ sFishLengthToWeigh = this->fishLength;
- if (D_80B7A678 >= 75) {
- D_80B7E086 = 0x409F;
- } else if (D_80B7A678 >= 50) {
- D_80B7E086 = 0x4091;
+ if (sFishLengthToWeigh >= 75) {
+ sFishingCaughtTextId = 0x409F;
+ } else if (sFishLengthToWeigh >= 50) {
+ sFishingCaughtTextId = 0x4091;
} else {
- D_80B7E086 = 0x4083;
+ sFishingCaughtTextId = 0x4083;
}
} else {
- D_80B7A678 = 2.0f * this->unk_1AC;
- D_80B7E086 = 0x4099;
+ sFishLengthToWeigh = 2.0f * this->fishLength;
+ sFishingCaughtTextId = 0x4099;
}
- this->unk_1D5 = 0;
+ this->keepState = 0;
}
this->unk_160 = -0x4000;
this->actor.shape.rot.y = player->actor.shape.rot.y + 0x5000;
this->actor.shape.rot.x = this->actor.shape.rot.z = this->unk_162 = this->unk_164 = this->unk_16E = 0;
- sp10C.x = 4.0f;
- sp10C.y = -10.0f;
- sp10C.z = 5.0f;
- Matrix_MultVec3f(&sp10C, &sp100);
+ multiVecSrc.x = 4.0f;
+ multiVecSrc.y = -10.0f;
+ multiVecSrc.z = 5.0f;
+ Matrix_MultVec3f(&multiVecSrc, &targetPosOffset);
if (getInstantFish() == 0) {
- Math_ApproachF(&this->actor.world.pos.x, player->bodyPartsPos[15].x + sp100.x, 1.0f, 6.0f);
- Math_ApproachF(&this->actor.world.pos.y, player->bodyPartsPos[15].y + sp100.y, 1.0f, 6.0f);
- Math_ApproachF(&this->actor.world.pos.z, player->bodyPartsPos[15].z + sp100.z, 1.0f, 6.0f);
+ Math_ApproachF(&this->actor.world.pos.x, player->bodyPartsPos[15].x + targetPosOffset.x, 1.0f, 6.0f);
+ Math_ApproachF(&this->actor.world.pos.y, player->bodyPartsPos[15].y + targetPosOffset.y, 1.0f, 6.0f);
+ Math_ApproachF(&this->actor.world.pos.z, player->bodyPartsPos[15].z + targetPosOffset.z, 1.0f, 6.0f);
} else {
- this->actor.world.pos.x = player->bodyPartsPos[15].x + sp100.x;
- this->actor.world.pos.y = player->bodyPartsPos[15].y + sp100.y;
- this->actor.world.pos.z = player->bodyPartsPos[15].z + sp100.z;
+ this->actor.world.pos.x = player->bodyPartsPos[15].x + targetPosOffset.x;
+ this->actor.world.pos.y = player->bodyPartsPos[15].y + targetPosOffset.y;
+ this->actor.world.pos.z = player->bodyPartsPos[15].z + targetPosOffset.z;
}
- D_80B7E144 = 188.0f;
+ sRodLineSpooled = 188.0f;
- if (this->unk_17A[0] <= 50) {
- switch (this->unk_1D5) {
+ if (this->timerArray[0] <= 50) {
+ switch (this->keepState) {
case 0:
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) ||
(Message_GetState(&play->msgCtx) == TEXT_STATE_NONE)) {
if (Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
if (play->msgCtx.choiceIndex == 0) {
- if (D_80B7A670 == 0.0f) {
- D_80B7A670 = this->unk_1AC;
- D_80B7E07C = this->unk_150;
- D_80B7E07E = D_80B7E0B6;
+ if (sFishOnHandLength == 0.0f) {
+ sFishOnHandLength = this->fishLength;
+ sFishOnHandIsLoach = this->isLoach;
+ sLureCaughtWith = sLureEquipped;
+ if (IS_FISHSANITY) {
+ sFishOnHandParams = this->fishsanityParams;
+ }
Actor_Kill(&this->actor);
- } else if ((this->unk_150 == 0) && (D_80B7E07C == 0) &&
- ((s16)this->unk_1AC < (s16)D_80B7A670)) {
- this->unk_1D5 = 1;
- this->unk_17A[0] = 0x3C;
+ } else if (getShouldConfirmKeep() && (this->isLoach == 0) && (sFishOnHandIsLoach == 0) &&
+ ((s16)this->fishLength < (s16)sFishOnHandLength)) {
+ this->keepState = 1;
+ this->timerArray[0] = 0x3C;
Message_StartTextbox(play, 0x4098, NULL);
} else {
- f32 temp1 = D_80B7A670;
- s16 temp2 = D_80B7E07C;
- D_80B7A670 = this->unk_1AC;
- D_80B7E07C = this->unk_150;
- D_80B7E07E = D_80B7E0B6;
- this->unk_1AC = temp1;
- this->unk_150 = temp2;
+ f32 lengthTemp = sFishOnHandLength;
+ s16 loachTemp = sFishOnHandIsLoach;
+ sFishOnHandLength = this->fishLength;
+ sFishOnHandIsLoach = this->isLoach;
+ sLureCaughtWith = sLureEquipped;
+ this->fishLength = lengthTemp;
+ this->isLoach = loachTemp;
+ if (IS_FISHSANITY) {
+ s16 paramsTemp = sFishOnHandParams;
+ sFishOnHandParams = this->fishsanityParams;
+ this->fishsanityParams = paramsTemp;
+ }
}
}
- if (this->unk_1D5 == 0) {
- D_80B7A694 = 0;
+ if (this->keepState == 0) {
+ sRodCastState = 0;
}
}
}
@@ -3992,32 +4031,37 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
if (Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
if (play->msgCtx.choiceIndex != 0) {
- f32 temp1 = D_80B7A670;
- s16 temp2 = D_80B7E07C;
- D_80B7A670 = this->unk_1AC;
- D_80B7E07E = D_80B7E0B6;
- this->unk_1AC = temp1;
- this->unk_150 = temp2;
+ f32 temp1 = sFishOnHandLength;
+ s16 temp2 = sFishOnHandIsLoach;
+ sFishOnHandLength = this->fishLength;
+ sLureCaughtWith = sLureEquipped;
+ this->fishLength = temp1;
+ this->isLoach = temp2;
+ if (IS_FISHSANITY) {
+ s16 paramsTemp = sFishOnHandParams;
+ sFishOnHandParams = this->fishsanityParams;
+ this->fishsanityParams = paramsTemp;
+ }
}
- D_80B7A694 = 0;
+ sRodCastState = 0;
}
}
break;
}
}
- if (D_80B7A694 == 0) {
+ if (sRodCastState == 0) {
if (this->actor.update != NULL) {
- this->unk_158 = this->unk_15A = 0;
+ this->fishState = this->fishStateNext = 0;
this->unk_1A4 = 10000;
this->unk_1A2 = 500;
- this->unk_17A[1] = 50;
- this->unk_17A[0] = 0;
+ this->timerArray[1] = 50;
+ this->timerArray[0] = 0;
this->unk_190 = 1.0f;
this->unk_194 = 2000.0f;
SkelAnime_Free(&this->skelAnime, play);
- if (this->unk_150 == 0) {
+ if (this->isLoach == 0) {
SkelAnime_InitFlex(play, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, 0, 0, 0);
Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f);
} else {
@@ -4028,81 +4072,81 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
}
D_80B7E148 = 520.0f;
- D_80B7E144 = 195.0f;
+ sRodLineSpooled = 195.0f;
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0xA00FF);
- D_80B7E0A6 = 20;
- D_80B7A6CC = 3;
+ sFishingMusicDelay = 20;
+ sFishingPlayerCinematicState = 3;
}
break;
case 7:
- this->unk_151 = 50;
- sp134 = 5;
- this->unk_1B0 = 12288.0f;
+ this->lilyTimer = 50;
+ rotXYScale = 5;
+ this->rotationStep = 12288.0f;
- if (this->actor.params < 104) {
- this->unk_1B4 = sGroupFishes[this->actor.params - 100].pos;
- D_80B7A898 = 1;
- } else if (this->actor.params < 108) {
- this->unk_1B4 = sGroupFishes[this->actor.params - 100 + 16].pos;
- D_80B7A898 = 2;
+ if (this->actor.params < (EN_FISH_PARAM + 4)) {
+ this->fishTargetPos = sGroupFishes[this->actor.params - EN_FISH_PARAM].pos;
+ sFishGroupVar = 1;
+ } else if (this->actor.params < (EN_FISH_PARAM + 8)) {
+ this->fishTargetPos = sGroupFishes[this->actor.params - EN_FISH_PARAM + 16].pos;
+ sFishGroupVar = 2;
} else {
- this->unk_1B4 = sGroupFishes[this->actor.params - 100 + 32].pos;
- D_80B7A898 = 3;
+ this->fishTargetPos = sGroupFishes[this->actor.params - EN_FISH_PARAM + 32].pos;
+ sFishGroupVar = 3;
}
Math_ApproachF(&this->actor.speedXZ, 5.0f, 1.0f, 1.0f);
- if (sp124 < 20.0f) {
- Math_ApproachS(&this->unk_170, 0x4E20, 2, 0xFA0);
+ if (distToTarget < 20.0f) {
+ Math_ApproachS(&this->fishLimbDRotZDelta, 0x4E20, 2, 0xFA0);
- if ((this->unk_17A[2] == 0) && func_80B70A2C(this, play, false)) {
- func_80B71278(this, Rand_ZeroFloat(1.99f));
- this->unk_17A[2] = (s16)Rand_ZeroFloat(20.0f) + 20;
+ if ((this->timerArray[2] == 0) && Fishing_SplashBySize(this, play, false)) {
+ Fishing_FishLeapSfx(this, Rand_ZeroFloat(1.99f));
+ this->timerArray[2] = (s16)Rand_ZeroFloat(20.0f) + 20;
}
}
- if (this->unk_17A[3] == 0) {
- this->unk_158 = 10;
- this->unk_15A = 10;
+ if (this->timerArray[3] == 0) {
+ this->fishState = 10;
+ this->fishStateNext = 10;
} else {
func_80B70ED4(this, input);
- if (this->actor.xzDistToPlayer < (100.0f * sp118)) {
- this->unk_15A = this->unk_158 = 0;
+ if (this->actor.xzDistToPlayer < (100.0f * playerSpeedMod)) {
+ this->fishStateNext = this->fishState = 0;
this->unk_1A4 = 500;
this->unk_1A2 = 200;
- this->unk_17A[1] = 50;
+ this->timerArray[1] = 50;
}
}
break;
}
- Math_ApproachS(&this->unk_172, (Math_SinS(this->unk_15C * 0x1000) * 5000.0f) + 5000.0f, 2, 0x7D0);
+ Math_ApproachS(&this->fishLimbEFRotYDelta, (Math_SinS(this->stateAndTimer * 0x1000) * 5000.0f) + 5000.0f, 2, 0x7D0);
- if (this->unk_158 != 6) {
+ if (this->fishState != 6) {
if (this->actor.world.pos.y > WATER_SURFACE_Y(play)) {
this->unk_190 = 1.5f;
this->unk_194 = 5000.0f;
Math_ApproachS(&this->unk_16E, 0, 5, 0x7D0);
- spF4 = spF0 = spFA = 3;
- spF2 = spEE = 0x2000;
+ rotXScale = rotYScale = rotZScale = 3;
+ rotXStep = rotYStep = 0x2000;
- this->unk_17A[2] = 0;
+ this->timerArray[2] = 0;
this->unk_184 -= 1.0f;
} else {
Math_ApproachZeroF(&this->unk_184, 1.0f, 2.0f);
- if ((this->unk_158 != -1) && (this->unk_158 != -2) && (this->unk_158 != -25)) {
- this->unk_166 = 0;
+ if ((this->fishState != -1) && (this->fishState != -2) && (this->fishState != -25)) {
+ this->rotationTarget.x = 0;
}
- this->unk_168 = this->unk_16A = 0;
- spF4 = spF0 = spFA = 4;
- spF2 = spEE = 0x2000;
+ this->rotationTarget.y = this->rotationTarget.z = 0;
+ rotXScale = rotYScale = rotZScale = 4;
+ rotXStep = rotYStep = 0x2000;
- spF6 = Fishing_SmoothStepToS(&this->actor.world.rot.y, spFC, sp134, this->unk_1B0) * 3.0f;
- Math_ApproachS(&this->actor.world.rot.x, spFE, sp134, this->unk_1B0 * 0.5f);
+ spF6 = Fishing_SmoothStepToS(&this->actor.world.rot.y, rotYTarget, rotXYScale, this->rotationStep) * 3.0f;
+ Math_ApproachS(&this->actor.world.rot.x, rotXTarget, rotXYScale, this->rotationStep * 0.5f);
if (spF6 > 0x1F40) {
spF6 = 0x1F40;
@@ -4124,25 +4168,25 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->actor.world.pos.y += (this->unk_184 * 1.5f);
if (this->unk_152 != 0) {
- this->unk_168 = this->unk_154;
+ this->rotationTarget.y = this->unk_154;
this->unk_152--;
if (this->unk_156 != 0) {
- spF0 = 5;
- spEE = 0x4000;
+ rotYScale = 5;
+ rotYStep = 0x4000;
} else {
- spF0 = 10;
- spEE = 0x800;
+ rotYScale = 10;
+ rotYStep = 0x800;
}
- this->unk_166 = -0x500 - this->actor.shape.rot.x;
- spF4 = 5;
- spF2 = 0x4000;
+ this->rotationTarget.x = -0x500 - this->actor.shape.rot.x;
+ rotXScale = 5;
+ rotXStep = 0x4000;
} else {
this->unk_156 = 0;
}
- Math_ApproachS(&this->unk_160, this->unk_166, spF4, spF2);
- Math_ApproachS(&this->unk_162, this->unk_168, spF0, spEE);
- Math_ApproachS(&this->unk_164, this->unk_16A, spFA, 0x2000);
+ Math_ApproachS(&this->unk_160, this->rotationTarget.x, rotXScale, rotXStep);
+ Math_ApproachS(&this->unk_162, this->rotationTarget.y, rotYScale, rotYStep);
+ Math_ApproachS(&this->unk_164, this->rotationTarget.z, rotZScale, 0x2000);
if (this->actor.speedXZ <= 0.5f) {
Math_ApproachS(&this->actor.shape.rot.x, 0, 10, this->unk_178);
@@ -4154,38 +4198,38 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->actor.shape.rot.y = this->actor.world.rot.y;
- if ((this->unk_158 != -1) && (this->unk_158 != -2) && (this->unk_158 != -25)) {
+ if ((this->fishState != -1) && (this->fishState != -2) && (this->fishState != -25)) {
if ((this->actor.world.pos.y > WATER_SURFACE_Y(play)) &&
(this->actor.prevPos.y <= WATER_SURFACE_Y(play))) {
- func_80B70A2C(this, play, true);
- func_80B71278(this, 1);
+ Fishing_SplashBySize(this, play, true);
+ Fishing_FishLeapSfx(this, true);
this->unk_184 = this->actor.velocity.y;
this->actor.velocity.y = 0.0f;
- this->unk_16A = Rand_CenteredFloat(32768.0f);
+ this->rotationTarget.z = Rand_CenteredFloat(32768.0f);
} else if ((this->actor.world.pos.y < WATER_SURFACE_Y(play)) &&
(this->actor.prevPos.y >= WATER_SURFACE_Y(play))) {
if (this->unk_184 < -5.0f) {
this->unk_184 = -5.0f;
}
this->actor.world.rot.x = -0xFA0;
- func_80B70A2C(this, play, true);
- this->unk_1D2 = 20;
- func_80B71278(this, 0);
+ Fishing_SplashBySize(this, play, true);
+ this->bubbleTime = 20;
+ Fishing_FishLeapSfx(this, 0);
}
}
if ((this->actor.world.pos.y < WATER_SURFACE_Y(play)) &&
- (this->actor.world.pos.y > (WATER_SURFACE_Y(play) - 10.0f)) && ((this->unk_15C & 1) == 0) &&
+ (this->actor.world.pos.y > (WATER_SURFACE_Y(play) - 10.0f)) && ((this->stateAndTimer & 1) == 0) &&
(this->actor.speedXZ > 0.0f)) {
Vec3f pos = this->actor.world.pos;
pos.y = WATER_SURFACE_Y(play);
Fishing_SpawnRipple(&this->actor.projectedPos, play->specialEffects, &pos, 80.0f, 500.0f, 150, 90);
}
- if ((this->actor.speedXZ > 0.0f) || (this->unk_158 == 5)) {
+ if ((this->actor.speedXZ > 0.0f) || (this->fishState == 5)) {
f32 velocityY = this->actor.velocity.y;
- spD8 = this->unk_1AC * 0.1f;
+ spD8 = this->fishLength * 0.1f;
this->actor.world.pos.y -= spD8;
this->actor.prevPos.y -= spD8;
@@ -4197,7 +4241,7 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->actor.velocity.y = velocityY;
if (this->actor.bgCheckFlags & 8) {
- this->unk_1A0 = 20;
+ this->bumpTimer = 20;
}
if (this->actor.bgCheckFlags & 1) {
@@ -4207,47 +4251,47 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
this->actor.velocity.z = this->actor.world.pos.z * -0.003f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_FISH_LEAP);
- func_80B70CF0(this, play);
+ Fishing_SplashBySize2(this, play);
if (Rand_ZeroOne() < 0.5f) {
- this->unk_16A = 0x4000;
+ this->rotationTarget.z = 0x4000;
} else {
- this->unk_16A = -0x4000;
+ this->rotationTarget.z = -0x4000;
}
if (Rand_ZeroOne() < 0.5f) {
- this->unk_166 = 0;
+ this->rotationTarget.x = 0;
} else {
- this->unk_166 = (s16)Rand_CenteredFloat(32.0f) + 0x8000;
+ this->rotationTarget.x = (s16)Rand_CenteredFloat(32.0f) + 0x8000;
}
- this->unk_168 = (s16)Rand_CenteredFloat(16384.0f);
+ this->rotationTarget.y = (s16)Rand_CenteredFloat(16384.0f);
this->unk_190 = 1.0f;
this->unk_194 = 5000.0f;
- this->unk_19C = 5000.0f;
+ this->fishLimbRotPhaseMag = 5000.0f;
} else {
this->unk_184 = 0.0f;
- if ((this->unk_158 == 5) && ((this->unk_15C & 1) == 0)) {
+ if ((this->fishState == 5) && ((this->stateAndTimer & 1) == 0)) {
Vec3f pos;
pos.x = Rand_CenteredFloat(10.0f) + this->actor.world.pos.x;
pos.z = Rand_CenteredFloat(10.0f) + this->actor.world.pos.z;
pos.y = this->actor.floorHeight + 5.0f;
Fishing_SpawnWaterDust(&this->actor.projectedPos, play->specialEffects, &pos,
- (this->unk_1AC * 0.005f) + 0.15f);
+ (this->fishLength * 0.005f) + 0.15f);
}
}
}
}
}
- if (this->unk_1D2 != 0) {
+ if (this->bubbleTime != 0) {
s16 i;
Vec3f pos;
- f32 range = (this->unk_1AC * 0.075f) + 10.0f;
+ f32 range = (this->fishLength * 0.075f) + 10.0f;
- this->unk_1D2--;
+ this->bubbleTime--;
for (i = 0; i < 2; i++) {
pos.x = Rand_CenteredFloat(range) + this->actor.world.pos.x;
@@ -4261,22 +4305,29 @@ void Fishing_UpdateFish(Actor* thisx, PlayState* play2) {
s32 Fishing_FishOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
void* thisx) {
- Fishing* this = (Fishing*)thisx;
+ Fishing* this = (Fishing*)thisx;
+
+ // #region SOH [Randomizer]
+ // A fish having a shadowDraw implies that it is being given uncollected FX
+ if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
+ Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, (this->actor.params - 100) * 20);
+ }
+ // #endregion
if (limbIndex == 0xD) {
- rot->z -= this->unk_170 - 11000;
+ rot->z -= this->fishLimbDRotZDelta - 11000;
} else if ((limbIndex == 2) || (limbIndex == 3)) {
- rot->y += this->unk_16C;
+ rot->y += this->fishLimb23RotYDelta;
} else if (limbIndex == 4) {
- rot->y += this->unk_176;
+ rot->y += this->fishLimb4RotYDelta;
} else if (limbIndex == 0xE) {
- rot->y -= this->unk_172;
+ rot->y -= this->fishLimbEFRotYDelta;
} else if (limbIndex == 0xF) {
- rot->y += this->unk_172;
+ rot->y += this->fishLimbEFRotYDelta;
} else if (limbIndex == 8) {
- rot->y += this->unk_174;
+ rot->y += this->fishLimb89RotYDelta;
} else if (limbIndex == 9) {
- rot->y -= this->unk_174;
+ rot->y -= this->fishLimb89RotYDelta;
}
return 0;
@@ -4285,6 +4336,13 @@ s32 Fishing_FishOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Ve
void Fishing_FishPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
Fishing* this = (Fishing*)thisx;
+ // #region SOH [Randomizer]
+ // A fish having a shadowDraw implies that it is being given uncollected FX
+ if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
+ Fishsanity_CloseGreyscaleColor(play);
+ }
+ // #endregion
+
if (limbIndex == 0xD) {
Matrix_MultVec3f(&sFishMouthOffset, &this->fishMouthPos);
}
@@ -4294,12 +4352,19 @@ s32 Fishing_LoachOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, V
void* thisx) {
Fishing* this = (Fishing*)thisx;
+ // #region SOH [Randomizer]
+ // A fish having a shadowDraw implies that it is being given uncollected FX
+ if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
+ Fishsanity_OpenGreyscaleColor(play, &fsPulseColor, (this->actor.params - 100) * 20);
+ }
+ // #endregion
+
if (limbIndex == 3) {
- rot->y += this->unk_1CC[0];
+ rot->y += this->loachRotYDelta[0];
} else if (limbIndex == 4) {
- rot->y += this->unk_1CC[1];
+ rot->y += this->loachRotYDelta[1];
} else if (limbIndex == 5) {
- rot->y += this->unk_1CC[2];
+ rot->y += this->loachRotYDelta[2];
}
return 0;
@@ -4309,6 +4374,13 @@ void Fishing_LoachPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3
static Vec3f sLoachMouthOffset = { 500.0f, 500.0f, 0.0f };
Fishing* this = (Fishing*)thisx;
+ // #region SOH [Randomizer]
+ // A fish having a shadowDraw implies that it is being given uncollected FX
+ if (IS_FISHSANITY && this->actor.shape.shadowDraw != NULL) {
+ Fishsanity_CloseGreyscaleColor(play);
+ }
+ // #endregion
+
if (limbIndex == 0xB) {
Matrix_MultVec3f(&sLoachMouthOffset, &this->fishMouthPos);
}
@@ -4325,14 +4397,14 @@ void Fishing_DrawFish(Actor* thisx, PlayState* play) {
Matrix_RotateZ(((this->unk_164 + this->actor.shape.rot.z) / 32768.0f) * M_PI, MTXMODE_APPLY);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
- if (this->unk_150 == 0) {
- Matrix_RotateY((this->unk_16C * (M_PI / 32768)) - (M_PI / 2), MTXMODE_APPLY);
- Matrix_Translate(0.0f, 0.0f, this->unk_16C * 10.0f * 0.01f, MTXMODE_APPLY);
+ if (this->isLoach == 0) {
+ Matrix_RotateY((this->fishLimb23RotYDelta * (M_PI / 32768)) - (M_PI / 2), MTXMODE_APPLY);
+ Matrix_Translate(0.0f, 0.0f, this->fishLimb23RotYDelta * 10.0f * 0.01f, MTXMODE_APPLY);
SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, Fishing_FishOverrideLimbDraw, Fishing_FishPostLimbDraw, this);
} else {
Matrix_Translate(0.0f, 0.0f, 3000.0f, MTXMODE_APPLY);
- Matrix_RotateY(this->unk_16C * (M_PI / 32768), MTXMODE_APPLY);
+ Matrix_RotateY(this->fishLimb23RotYDelta * (M_PI / 32768), MTXMODE_APPLY);
Matrix_Translate(0.0f, 0.0f, -3000.0f, MTXMODE_APPLY);
Matrix_RotateY(-(M_PI / 2), MTXMODE_APPLY);
@@ -4397,7 +4469,7 @@ void Fishing_UpdatePondProps(PlayState* play) {
actor = play->actorCtx.actorLists[ACTORCAT_NPC].head;
while (actor != NULL) {
- if (!((actor->id == ACTOR_FISHING) && (actor->params >= 100))) {
+ if (!((actor->id == ACTOR_FISHING) && (actor->params >= EN_FISH_PARAM))) {
actor = actor->next;
} else {
Fishing_HandleReedContact(prop, &actor->world.pos);
@@ -4411,10 +4483,10 @@ void Fishing_UpdatePondProps(PlayState* play) {
actor = play->actorCtx.actorLists[ACTORCAT_NPC].head;
while (actor != NULL) {
- if (!((actor->id == ACTOR_FISHING) && (actor->params >= 100))) {
+ if (!((actor->id == ACTOR_FISHING) && (actor->params >= EN_FISH_PARAM))) {
actor = actor->next;
} else {
- Fishing_HandleLilyPadContact(prop, &actor->world.pos, ((Fishing*)actor)->unk_151);
+ Fishing_HandleLilyPadContact(prop, &actor->world.pos, ((Fishing*)actor)->lilyTimer);
actor = actor->next;
}
}
@@ -4430,13 +4502,13 @@ void Fishing_UpdatePondProps(PlayState* play) {
prop++;
}
- if (sCameraId == 0) {
+ if (sSubCamId == 0) {
CollisionCheck_SetOC(play, &play->colChkCtx, &sFishingMain->collider.base);
}
}
void Fishing_DrawPondProps(PlayState* play) {
- u8 flag = 0;
+ u8 materialFlag = 0;
FishingProp* prop = &sPondProps[0];
s16 i;
s32 pad;
@@ -4447,9 +4519,9 @@ void Fishing_DrawPondProps(PlayState* play) {
for (i = 0; i < POND_PROP_COUNT; i++) {
if (prop->type == FS_PROP_REED) {
- if (flag == 0) {
+ if (materialFlag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingReedMaterialDL);
- flag++;
+ materialFlag++;
}
if (prop->shouldDraw) {
@@ -4471,12 +4543,12 @@ void Fishing_DrawPondProps(PlayState* play) {
}
prop = &sPondProps[0];
- flag = 0;
+ materialFlag = 0;
for (i = 0; i < POND_PROP_COUNT; i++) {
if (prop->type == FS_PROP_WOOD_POST) {
- if (flag == 0) {
+ if (materialFlag == 0) {
gSPDisplayList(POLY_OPA_DISP++, gFishingWoodPostMaterialDL);
- flag++;
+ materialFlag++;
}
if (prop->shouldDraw) {
@@ -4495,12 +4567,12 @@ void Fishing_DrawPondProps(PlayState* play) {
}
prop = &sPondProps[0];
- flag = 0;
+ materialFlag = 0;
for (i = 0; i < POND_PROP_COUNT; i++) {
if (prop->type == FS_PROP_LILY_PAD) {
- if (flag == 0) {
+ if (materialFlag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingLilyPadMaterialDL);
- flag++;
+ materialFlag++;
}
if (prop->shouldDraw) {
@@ -4522,12 +4594,12 @@ void Fishing_DrawPondProps(PlayState* play) {
}
prop = &sPondProps[0];
- flag = 0;
+ materialFlag = 0;
for (i = 0; i < POND_PROP_COUNT; i++) {
if (prop->type == FS_PROP_ROCK) {
- if (flag == 0) {
+ if (materialFlag == 0) {
gSPDisplayList(POLY_OPA_DISP++, gFishingRockMaterialDL);
- flag++;
+ materialFlag++;
}
if (prop->shouldDraw) {
@@ -4573,7 +4645,7 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
f32 temp1;
f32 temp2;
- if ((D_80B7E114 != 0) || (D_80B7A694 == 4)) {
+ if ((D_80B7E114 != 0) || (sRodCastState == 4)) {
refPos = &sLurePos;
} else {
refPos = &player->actor.world.pos;
@@ -4589,7 +4661,7 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
if ((SQ(temp1) + SQ(temp2)) < SQ(50.0f)) {
sFishGroupAngle1 += 0.3f;
groupContactFlags |= 1;
- } else if (D_80B7A898 != 0.0f) {
+ } else if (sFishGroupVar != 0.0f) {
sFishGroupAngle1 += 0.05f;
basePos[0].y = WATER_SURFACE_Y(play) - 5.0f;
} else {
@@ -4606,7 +4678,7 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
if ((SQ(temp1) + SQ(temp2)) < SQ(50.0f)) {
sFishGroupAngle2 -= 0.3f;
groupContactFlags |= 2;
- } else if (D_80B7A898 != 0.0f) {
+ } else if (sFishGroupVar != 0.0f) {
sFishGroupAngle2 -= 0.05f;
basePos[1].y = WATER_SURFACE_Y(play) - 5.0f;
} else {
@@ -4623,14 +4695,14 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
if ((SQ(temp1) + SQ(temp2)) < SQ(50.0f)) {
sFishGroupAngle3 -= 0.3f;
groupContactFlags |= 4;
- } else if (D_80B7A898 != 0.0f) {
+ } else if (sFishGroupVar != 0.0f) {
sFishGroupAngle3 -= 0.05f;
basePos[2].y = WATER_SURFACE_Y(play) - 5.0f;
} else {
Math_ApproachF(&sFishGroupAngle3, 4.6f, 1.0f, 0.001f);
}
- if (sLinkAge == 1) {
+ if (sLinkAge == LINK_AGE_CHILD) {
spD8 = 0.8f;
} else {
spD8 = 1.0f;
@@ -4659,22 +4731,22 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
groupFlag = 4;
}
- dx = fish->unk_10.x - fish->pos.x;
- dy = fish->unk_10.y - fish->pos.y;
- dz = fish->unk_10.z - fish->pos.z;
+ dx = fish->homePos.x - fish->pos.x;
+ dy = fish->homePos.y - fish->pos.y;
+ dz = fish->homePos.z - fish->pos.z;
spD4 = Math_Atan2S(dz, dx);
dist = sqrtf(SQ(dx) + SQ(dz));
spD6 = Math_Atan2S(dist, dy);
if ((dist < 10.0f) || (((fish->timer % 32) == 0) && (Rand_ZeroOne() > 0.5f))) {
- fish->unk_10.y = basePos[groupIndex].y + Rand_CenteredFloat(10.0f);
+ fish->homePos.y = basePos[groupIndex].y + Rand_CenteredFloat(10.0f);
- if (D_80B7A898 != 0.0f) {
- fish->unk_10.x = basePos[groupIndex].x + Rand_CenteredFloat(200.0f);
- fish->unk_10.z = basePos[groupIndex].z + Rand_CenteredFloat(200.0f);
+ if (sFishGroupVar != 0.0f) {
+ fish->homePos.x = basePos[groupIndex].x + Rand_CenteredFloat(200.0f);
+ fish->homePos.z = basePos[groupIndex].z + Rand_CenteredFloat(200.0f);
} else {
- fish->unk_10.x = basePos[groupIndex].x + Rand_CenteredFloat(100.0f);
- fish->unk_10.z = basePos[groupIndex].z + Rand_CenteredFloat(100.0f);
+ fish->homePos.x = basePos[groupIndex].x + Rand_CenteredFloat(100.0f);
+ fish->homePos.z = basePos[groupIndex].z + Rand_CenteredFloat(100.0f);
}
ripplePos = fish->pos;
@@ -4682,8 +4754,8 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
Fishing_SpawnRipple(&fish->projectedPos, play->specialEffects, &ripplePos, 20.0f,
Rand_ZeroFloat(50.0f) + 100.0f, 150, 90);
- if (fish->unk_28 < 1.5f) {
- fish->unk_28 = 1.5f;
+ if (fish->velY < 1.5f) {
+ fish->velY = 1.5f;
}
fish->unk_34 = 1.5f;
@@ -4704,19 +4776,19 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
if (groupContactFlags & groupFlag) {
fish->unk_38 = 1.0f;
- fish->unk_28 = 6.0f;
+ fish->velY = 6.0f;
fish->unk_34 = 2.0f;
}
- if (D_80B7A898 != 0.0f) {
+ if (sFishGroupVar != 0.0f) {
fish->unk_38 = 1.0f;
- fish->unk_28 = 4.0f;
+ fish->velY = 4.0f;
fish->unk_34 = 2.0f;
}
- Math_ApproachF(&fish->unk_28, 0.75f, 1.0f, 0.05f);
+ Math_ApproachF(&fish->velY, 0.75f, 1.0f, 0.05f);
- temp1 = fish->unk_28 * spD8;
+ temp1 = fish->velY * spD8;
temp2 = Math_CosS(fish->unk_3C) * temp1;
fish->pos.x += temp2 * Math_SinS(fish->unk_3E);
@@ -4727,24 +4799,24 @@ void Fishing_UpdateGroupFishes(PlayState* play) {
Math_ApproachF(&fish->unk_34, 1.0f, 1.0f, 0.1f);
Math_ApproachF(&fish->unk_38, 0.4f, 1.0f, 0.04f);
fish->unk_30 += fish->unk_34;
- fish->unk_2C = (cosf(fish->unk_30) * fish->unk_38) + offset;
+ fish->scaleX = (cosf(fish->unk_30) * fish->unk_38) + offset;
}
}
fish++;
}
- D_80B7A898 = 0.0f;
+ sFishGroupVar = 0.0f;
}
void Fishing_DrawGroupFishes(PlayState* play) {
- u8 flag = 0;
+ u8 materialFlag = 0;
FishingGroupFish* fish = &sGroupFishes[0];
f32 scale;
s16 i;
s32 pad;
- if (sLinkAge == 1) {
+ if (sLinkAge == LINK_AGE_CHILD) {
scale = 0.003325f;
} else {
scale = 0.00475f;
@@ -4754,10 +4826,10 @@ void Fishing_DrawGroupFishes(PlayState* play) {
for (i = 0; i < GROUP_FISH_COUNT; i++) {
if (fish->type != FS_GROUP_FISH_NONE) {
- if (flag == 0) {
+ if (!materialFlag) {
gSPDisplayList(POLY_OPA_DISP++, gFishingGroupFishMaterialDL);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 155, 155, 155, 255);
- flag++;
+ materialFlag++;
}
if (fish->shouldDraw) {
@@ -4765,7 +4837,7 @@ void Fishing_DrawGroupFishes(PlayState* play) {
Matrix_Translate(fish->pos.x, fish->pos.y, fish->pos.z, MTXMODE_NEW);
Matrix_RotateY(((f32)fish->unk_3E * M_PI) / 32768.0f, MTXMODE_APPLY);
Matrix_RotateX((-(f32)fish->unk_3C * M_PI) / 32768.0f, MTXMODE_APPLY);
- Matrix_Scale(fish->unk_2C * scale, scale, scale, MTXMODE_APPLY);
+ Matrix_Scale(fish->scaleX * scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -4779,14 +4851,15 @@ void Fishing_DrawGroupFishes(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
-static u16 D_80B7AFB8[] = { 0x4096, 0x408D, 0x408E, 0x408F, 0x4094, 0x4095 };
+static u16 sPondOwnerTextIds[] = { 0x4096, 0x408D, 0x408E, 0x408F, 0x4094, 0x4095 };
void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
- switch (this->unk_15C) {
+ switch (this->stateAndTimer) {
case 0:
- if (D_80B7E0AC == 0) {
- if (sLinkAge != 1) {
- if ((HIGH_SCORE(HS_FISHING) & 0x100) && !(HIGH_SCORE(HS_FISHING) & 0x200)) {
+ if (sFishingPlayingState == 0) {
+ if (sLinkAge != LINK_AGE_CHILD) {
+ if ((HIGH_SCORE(HS_FISHING) & HS_FISH_PLAYED_CHILD) &&
+ !(HIGH_SCORE(HS_FISHING) & HS_FISH_PLAYED_ADULT)) {
this->actor.textId = 0x4093;
} else {
this->actor.textId = 0x407B;
@@ -4794,22 +4867,22 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
} else {
this->actor.textId = 0x407B;
}
- } else if (D_80B7A68C == 0) {
+ } else if (!sIsOwnersHatHooked) {
this->actor.textId = 0x4084;
} else {
this->actor.textId = 0x4097;
}
if (Actor_ProcessTalkRequest(&this->actor, play)) {
- if (D_80B7E0AC == 0) {
- this->unk_15C = 1;
- if (sLinkAge != 1) {
- HIGH_SCORE(HS_FISHING) |= 0x200;
+ if (sFishingPlayingState == 0) {
+ this->stateAndTimer = 1;
+ if (sLinkAge != LINK_AGE_CHILD) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_PLAYED_ADULT;
} else {
- HIGH_SCORE(HS_FISHING) |= 0x100;
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_PLAYED_CHILD;
}
} else {
- this->unk_15C = 10;
+ this->stateAndTimer = 10;
}
} else {
func_8002F2CC(&this->actor, play, 100.0f);
@@ -4830,17 +4903,21 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
this->actor.textId = 0x407D;
}
Message_ContinueTextbox(play, this->actor.textId);
- this->unk_15C = 2;
+ this->stateAndTimer = 2;
} else {
Message_ContinueTextbox(play, 0x407E);
- this->unk_15C = 3;
+ this->stateAndTimer = 3;
}
break;
case 1:
Message_ContinueTextbox(play, 0x2D);
- this->unk_15C = 3;
+ this->stateAndTimer = 3;
break;
}
+ // Fix for owner getting stuck when the pond is closed (Fishing Pole Shuffle)
+ } else if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE && Message_ShouldAdvance(play)) {
+ Message_CloseTextbox(play);
+ this->stateAndTimer = 0;
}
break;
@@ -4848,17 +4925,17 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
Message_ContinueTextbox(play, 0x407F);
- this->unk_15C = 4;
+ this->stateAndTimer = 4;
}
break;
case 3:
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
- this->unk_15C = 0;
+ this->stateAndTimer = 0;
}
if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) {
- this->unk_15C = 0;
+ this->stateAndTimer = 0;
}
break;
@@ -4868,9 +4945,9 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
switch (play->msgCtx.choiceIndex) {
case 0:
- D_80B7A678 = D_80B7E078;
+ sFishLengthToWeigh = sFishingRecordLength;
Message_ContinueTextbox(play, 0x4080);
- this->unk_15C = 5;
+ this->stateAndTimer = 5;
break;
case 1:
Message_ContinueTextbox(play, 0x407F);
@@ -4885,30 +4962,30 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
play->interfaceCtx.unk_260 = 1;
play->startPlayerFishing(play);
- D_80B7E0AC = 1;
- D_80B7A684 = 20;
- this->unk_15C = 0;
+ sFishingPlayingState = 1;
+ sOwnerTheftTimer = 20;
+ this->stateAndTimer = 0;
if ((HIGH_SCORE(HS_FISHING) & 0xFF0000) < 0xFF0000) {
- HIGH_SCORE(HS_FISHING) += 0x10000;
+ HIGH_SCORE(HS_FISHING) += HS_FISH_PLAYED;
}
}
break;
case 10:
- if (D_80B7A68C != 0) {
+ if (sIsOwnersHatHooked) { // owner asks for hat back
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
switch (play->msgCtx.choiceIndex) {
case 0:
Message_ContinueTextbox(play, 0x40B2);
- D_80B7A688 = 1;
- D_80B7A68C = 0;
- this->unk_15C = 20;
+ sOwnerHair = FS_OWNER_CAPPED;
+ sIsOwnersHatHooked = false;
+ this->stateAndTimer = 20;
break;
case 1:
- this->unk_15C = 0;
+ this->stateAndTimer = 0;
break;
}
}
@@ -4918,77 +4995,77 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
switch (play->msgCtx.choiceIndex) {
case 0:
- if (D_80B7A670 == 0.0f) {
+ if (sFishOnHandLength == 0.0f) {
this->actor.textId = 0x408C;
- this->unk_15C = 20;
- } else if (D_80B7E07C == 0 && !IS_RANDO) {
- D_80B7A678 = D_80B7A670;
- if ((s16)D_80B7E078 < (s16)D_80B7A670) {
- if (D_80B7E07E == 2) {
+ this->stateAndTimer = 20;
+ } else if (sFishOnHandIsLoach == 0 && !IS_RANDO) {
+ sFishLengthToWeigh = sFishOnHandLength;
+ if ((s16)sFishingRecordLength < (s16)sFishOnHandLength) {
+ if (sLureCaughtWith == FS_LURE_SINKING) {
this->actor.textId = 0x40B0;
} else {
this->actor.textId = 0x4086;
}
- this->unk_15C = 11;
+ this->stateAndTimer = 11;
} else {
this->actor.textId = 0x408B;
- this->unk_15C = 20;
+ this->stateAndTimer = 20;
}
} else if (!IS_RANDO) {
this->actor.textId = 0x409B;
- this->unk_15C = 11;
+ this->stateAndTimer = 11;
}
else {
this->actor.textId = 0x4086;
- this->unk_15C = 11;
+ this->stateAndTimer = 11;
}
Message_ContinueTextbox(play, this->actor.textId);
break;
case 1:
- if (D_80B7A680 > 36000) {
- D_80B7A680 = 30000;
+ if (sFishingTimePlayed > 36000) {
+ sFishingTimePlayed = 30000;
Message_ContinueTextbox(play, 0x4088);
} else {
- if (D_80B7E076 == 0) {
- if (D_80B7E082 == 0) {
- D_80B7E082++;
+ if (sFishingFoggy == 0) {
+ if (sPondOwnerTextIdIndex == 0) {
+ sPondOwnerTextIdIndex++;
}
}
- if ((D_80B7E0B6 == 2) && (D_80B7AFB8[D_80B7E082] == 0x408D)) {
+ if ((sLureEquipped == FS_LURE_SINKING) && (sPondOwnerTextIds[sPondOwnerTextIdIndex] == 0x408D)) {
Message_ContinueTextbox(play, 0x40AF);
} else {
- Message_ContinueTextbox(play, D_80B7AFB8[D_80B7E082]);
+ Message_ContinueTextbox(play, sPondOwnerTextIds[sPondOwnerTextIdIndex]);
}
- D_80B7E082++;
+ sPondOwnerTextIdIndex++;
- if (sLinkAge != 1) {
- if (D_80B7E082 >= 6) {
- D_80B7E082 = 0;
+ if (sLinkAge != LINK_AGE_CHILD) {
+ if (sPondOwnerTextIdIndex >= 6) {
+ sPondOwnerTextIdIndex = 0;
}
} else {
- if (D_80B7E082 >= 4) {
- D_80B7E082 = 0;
+ if (sPondOwnerTextIdIndex >= 4) {
+ sPondOwnerTextIdIndex = 0;
}
}
}
- this->unk_15C = 0;
+ this->stateAndTimer = 0;
break;
case 2:
- if (D_80B7E084 == 0) {
+ if (sFishesCaught == 0) {
Message_ContinueTextbox(play, 0x4085);
- } else if (sLinkAge == 1) {
+ } else if (sLinkAge == LINK_AGE_CHILD) {
Message_ContinueTextbox(play, 0x4092);
}
- this->unk_15C = 22;
+ this->stateAndTimer = 22;
break;
}
}
}
break;
- case 11:
+ case 11: // collect prize, update record.
if (((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) ||
(Message_GetState(&play->msgCtx) == TEXT_STATE_NONE)) &&
Message_ShouldAdvance(play)) {
@@ -4997,59 +5074,58 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
Message_CloseTextbox(play);
- if (D_80B7E07C == 0) {
- D_80B7E078 = D_80B7A670;
- D_80B7A670 = 0.0f;
+ if (sFishOnHandIsLoach == 0) {
+ sFishingRecordLength = sFishOnHandLength;
+ sFishOnHandLength = 0.0f;
- if (sLinkAge == 1) {
+ if (sLinkAge == LINK_AGE_CHILD) {
f32 temp;
HIGH_SCORE(HS_FISHING) &= 0xFFFFFF00;
- HIGH_SCORE(HS_FISHING) |= (s32)D_80B7E078 & 0x7F;
+ HIGH_SCORE(HS_FISHING) |= (s32)sFishingRecordLength & HS_FISH_LENGTH_CHILD;
- temp = (HIGH_SCORE(HS_FISHING) & 0x7F000000) >> 0x18;
- if (temp < D_80B7E078) {
+ temp = (HIGH_SCORE(HS_FISHING) & HS_FISH_LENGTH_ADULT) >> 0x18;
+ if (temp < sFishingRecordLength) {
HIGH_SCORE(HS_FISHING) &= 0xFFFFFF;
- HIGH_SCORE(HS_FISHING) |= ((s32)D_80B7E078 & 0x7F) << 0x18;
+ HIGH_SCORE(HS_FISHING) |= ((s32)sFishingRecordLength & HS_FISH_LENGTH_CHILD) << 0x18;
- if (D_80B7E07E == 2) {
- HIGH_SCORE(HS_FISHING) |= 0x80000000;
+ if (sLureCaughtWith == FS_LURE_SINKING) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_CHEAT_ADULT;
}
}
- if (D_80B7E07E == 2) {
- HIGH_SCORE(HS_FISHING) |= 0x80;
- this->unk_15C = 0;
+ if (sLureCaughtWith == FS_LURE_SINKING) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_CHEAT_CHILD;
+ this->stateAndTimer = 0;
break;
}
} else {
HIGH_SCORE(HS_FISHING) &= 0xFFFFFF;
- HIGH_SCORE(HS_FISHING) |= ((s32)D_80B7E078 & 0x7F) << 0x18;
+ HIGH_SCORE(HS_FISHING) |= ((s32)sFishingRecordLength & HS_FISH_LENGTH_CHILD) << 0x18;
- if (D_80B7E07E == 2) {
- HIGH_SCORE(HS_FISHING) |= 0x80000000;
- this->unk_15C = 0;
+ if (sLureCaughtWith == FS_LURE_SINKING) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_CHEAT_ADULT;
+ this->stateAndTimer = 0;
break;
}
}
- if (D_80B7E078 >= 60.0f) {
+ if (sFishingRecordLength >= 60.0f) { // 13 lbs
getItemId = GI_RUPEE_PURPLE;
- } else if (D_80B7E078 >= 50.0f) {
+ } else if (sFishingRecordLength >= 50.0f) { // 9 lbs
getItemId = GI_RUPEE_RED;
- } else if (D_80B7E078 >= 40.0f) {
+ } else if (sFishingRecordLength >= 40.0f) { // 6 lbs
getItemId = GI_RUPEE_BLUE;
} else {
getItemId = GI_RUPEE_GREEN;
}
- if (sLinkAge == 1) {
- if (
- (!IS_RANDO && !(HIGH_SCORE(HS_FISHING) & 0x400)) ||
+ if (sLinkAge == LINK_AGE_CHILD) { // 9 lbs
+ if ((!IS_RANDO && !(HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_CHILD)) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_CHILD_FISHING))
) {
- if (D_80B7E078 >= Fishing_GetMinimumRequiredScore()) {
- HIGH_SCORE(HS_FISHING) |= 0x400;
+ if (sFishingRecordLength >= Fishing_GetMinimumRequiredScore()) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_PRIZE_CHILD;
Flags_SetRandomizerInf(RAND_INF_CHILD_FISHING);
sSinkingLureLocation = (u8)Rand_ZeroFloat(3.999f) + 1;
if (!IS_RANDO) {
@@ -5060,13 +5136,12 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
}
}
}
- } else {
- if (
- (!IS_RANDO && !(HIGH_SCORE(HS_FISHING) & 0x800)) ||
+ } else { // 13 lbs
+ if ((!IS_RANDO && !(HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_ADULT)) ||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_ADULT_FISHING))
) {
- if (D_80B7E078 >= Fishing_GetMinimumRequiredScore()) {
- HIGH_SCORE(HS_FISHING) |= 0x800;
+ if (sFishingRecordLength >= Fishing_GetMinimumRequiredScore()) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_PRIZE_ADULT;
Flags_SetRandomizerInf(RAND_INF_ADULT_FISHING);
sSinkingLureLocation = (u8)Rand_ZeroFloat(3.999f) + 1;
if (!IS_RANDO) {
@@ -5080,7 +5155,7 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
}
} else {
getItemId = GI_RUPEE_PURPLE;
- D_80B7A670 = 0.0f;
+ sFishOnHandLength = 0.0f; // doesn't record loach
}
this->actor.parent = NULL;
@@ -5089,14 +5164,14 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
} else {
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 2000.0f, 1000.0f);
}
- this->unk_15C = 23;
+ this->stateAndTimer = 23;
}
break;
case 20:
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play);
- this->unk_15C = 0;
+ this->stateAndTimer = 0;
}
break;
@@ -5106,15 +5181,15 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
switch (play->msgCtx.choiceIndex) {
case 0:
- this->unk_15C = 0;
+ this->stateAndTimer = 0;
break;
case 1:
- if (D_80B7E084 == 0) {
+ if (sFishesCaught == 0) {
Message_ContinueTextbox(play, 0x4085);
- } else if (sLinkAge == 1) {
+ } else if (sLinkAge == LINK_AGE_CHILD) {
Message_ContinueTextbox(play, 0x4092);
}
- this->unk_15C = 22;
+ this->stateAndTimer = 22;
break;
}
}
@@ -5124,20 +5199,20 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
if (play) {}
if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) {
- this->unk_15C = 0;
- if (D_80B7A68C != 0) {
- D_80B7A688 = 1;
- D_80B7A68C = 0;
+ this->stateAndTimer = 0;
+ if (sIsOwnersHatHooked) {
+ sOwnerHair = FS_OWNER_CAPPED;
+ sIsOwnersHatHooked = false;
}
- D_80B7E0AC = 0;
+ sFishingPlayingState = 0;
play->interfaceCtx.unk_260 = 0;
}
break;
case 23:
- D_80B7A674 = false;
+ sIsRodVisible = false;
if (Actor_HasParent(&this->actor, play)) {
- this->unk_15C = 24;
+ this->stateAndTimer = 24;
} else {
if (!IS_RANDO) {
func_8002F434(&this->actor, play, GI_SCALE_GOLD, 2000.0f, 1000.0f);
@@ -5149,41 +5224,41 @@ void Fishing_HandleOwnerDialog(Fishing* this, PlayState* play) {
break;
case 24:
- D_80B7A674 = false;
+ sIsRodVisible = false;
if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) ||
(IS_RANDO && GET_PLAYER(play)->getItemId == GI_ICE_TRAP)) {
- if (D_80B7E07C == 0) {
- this->unk_15C = 0;
+ if (sFishOnHandIsLoach == 0) {
+ this->stateAndTimer = 0;
} else {
Message_StartTextbox(play, 0x409C, NULL);
- this->unk_15C = 20;
+ this->stateAndTimer = 20;
}
}
break;
}
}
-static s16 D_80B7AFC4[] = { 0, 1, 2, 2, 1 };
+static s16 sOwnerBlinkIndex[] = { 0, 1, 2, 2, 1 };
static Vec3f sStreamSoundPos = { 670.0f, 0.0f, -600.0f };
static Vec3s sSinkingLureLocationPos[] = {
- { -364, -30, -269 },
- { 1129, 3, -855 },
- { -480, 0, -1055 },
- { 553, -48, -508 },
+ { -364, -30, -269 }, // in the pond, log past the lilies.
+ { 1129, 3, -855 }, // rock next to stream
+ { -480, 0, -1055 }, // wall opposite of entrance
+ { 553, -48, -508 }, // tip of log beside 3 posts
};
void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
PlayState* play = play2;
Fishing* this = (Fishing*)thisx;
- Vec3f sp114;
- Vec3f sp108;
- Vec3f spFC;
+ Vec3f multiVecSrc;
+ Vec3f eyeTarget;
+ Vec3f lureDist;
s16 headRotTarget;
s16 playerShadowAlpha;
f32 target;
- f32 camAtFraction;
+ f32 subCamAtMaxVelFrac;
f32 lureDistXZ;
s32 pad;
Player* player = GET_PLAYER(play);
@@ -5210,7 +5285,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
SkelAnime_Update(&this->skelAnime);
- if ((D_80B7A684 != 0) || (Message_GetState(&play->msgCtx) != TEXT_STATE_NONE)) {
+ if ((sOwnerTheftTimer != 0) || (Message_GetState(&play->msgCtx) != TEXT_STATE_NONE)) {
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
} else {
this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_DRAW_WHILE_CULLED;
@@ -5234,67 +5309,70 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
this->unk_162 = 4;
}
- this->unk_160 = D_80B7AFC4[this->unk_162];
+ this->unk_160 = sOwnerBlinkIndex[this->unk_162];
if (this->unk_162 != 0) {
this->unk_162--;
}
- if (D_80B7A684 != 0) {
- D_80B7A684--;
+ if (sOwnerTheftTimer != 0) {
+ sOwnerTheftTimer--;
}
- if ((D_80B7A68C == 0) && (D_80B7E0B6 != 2) && (D_80B7A694 > 0) && (D_80B7A688 == 1) && (D_80B7A684 == 0)) {
+ // steal the owner's hat
+ if (!sIsOwnersHatHooked && (sLureEquipped != FS_LURE_SINKING) && (sRodCastState > 0) &&
+ (sOwnerHair == FS_OWNER_CAPPED) && (sOwnerTheftTimer == 0)) {
f32 dx = sOwnerHeadPos.x - sLurePos.x;
f32 dy = sOwnerHeadPos.y - sLurePos.y;
f32 dz = sOwnerHeadPos.z - sLurePos.z;
if ((sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < 25.0f) || (KREG(77) > 0)) {
KREG(77) = 0;
- D_80B7A688 = 0;
- D_80B7A68C = 1;
+ sOwnerHair = FS_OWNER_BALD;
+ sIsOwnersHatHooked = true;
Message_StartTextbox(play, 0x4087, NULL);
}
}
- if (D_80B7A688 == 0) {
- HIGH_SCORE(HS_FISHING) |= 0x1000;
- } else if (D_80B7A688 == 1) {
- HIGH_SCORE(HS_FISHING) &= ~0x1000;
+ // update hat flag.
+ if (sOwnerHair == FS_OWNER_BALD) {
+ HIGH_SCORE(HS_FISHING) |= HS_FISH_STOLE_HAT;
+ } else if (sOwnerHair == FS_OWNER_CAPPED) {
+ HIGH_SCORE(HS_FISHING) &= ~HS_FISH_STOLE_HAT;
}
if (KREG(77) < 0) {
KREG(77) = 0;
- D_80B7A690 = 1;
+ sIsOwnersHatSunk = true;
}
- if (D_80B7A67C != 0) {
- D_80B7A67C--;
- if (D_80B7A67C == 0) {
- Message_StartTextbox(play, D_80B7E086, NULL);
+ if (sFishingCaughtTextDelay != 0) {
+ sFishingCaughtTextDelay--;
+ if (sFishingCaughtTextDelay == 0) {
+ Message_StartTextbox(play, sFishingCaughtTextId, NULL);
}
}
Fishing_HandleOwnerDialog(this, play);
- D_80B7E14C = 0.0015f;
- D_80B7A680++;
+ sFishingLineScale = 0.0015f;
+ sFishingTimePlayed++;
- if ((D_80B7E0AC != 0) && D_80B7A674) {
+ if ((sFishingPlayingState != 0) && sIsRodVisible) {
Fishing_UpdateLure(this, play);
}
Fishing_UpdateEffects(play->specialEffects, play);
Fishing_UpdatePondProps(play);
Fishing_UpdateGroupFishes(play);
-
- if ((D_80B7E0AC != 0) && (D_80B7A6CC == 0) && (player->actor.world.pos.z > 1360.0f) &&
+ // can't leave with the rod
+ if ((sFishingPlayingState != 0) && (sFishingPlayerCinematicState == 0) && (player->actor.world.pos.z > 1360.0f) &&
(fabsf(player->actor.world.pos.x) < 25.0f)) {
player->actor.world.pos.z = 1360.0f;
player->actor.speedXZ = 0.0f;
- if (D_80B7A6D0 == 0) {
- D_80B7A6CC = 10;
+ if (sFishingCinematicTimer == 0) {
+ sFishingPlayerCinematicState = 10;
}
}
@@ -5303,7 +5381,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
(fabsf(player->actor.world.pos.y - sSinkingLureLocationPos[sSinkingLureLocation - 1].y) < 10.0f) &&
(fabsf(player->actor.world.pos.z - sSinkingLureLocationPos[sSinkingLureLocation - 1].z) < 25.0f)) {
sSinkingLureLocation = 0;
- D_80B7A6CC = 20;
+ sFishingPlayerCinematicState = 20;
func_800A9F6C(0.0f, 150, 10, 10);
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x1400FF);
@@ -5311,87 +5389,87 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
if (KREG(0) != 0) {
KREG(0) = 0;
- D_80B7E0B6 = 0;
- D_80B7A6CC = 20;
+ sLureEquipped = FS_LURE_STOCK;
+ sFishingPlayerCinematicState = 20;
func_800A9F6C(0.0f, 150, 10, 10);
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x1400FF);
}
- if (D_80B7A6D0 != 0) {
- D_80B7A6D0--;
+ if (sFishingCinematicTimer != 0) {
+ sFishingCinematicTimer--;
}
- switch (D_80B7A6CC) {
+ switch (sFishingPlayerCinematicState) {
case 0:
break;
case 1: {
- Camera* camera;
+ Camera* mainCam;
- sCameraId = Play_CreateSubCamera(play);
+ sSubCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
- Play_ChangeCameraStatus(play, sCameraId, CAM_STAT_ACTIVE);
- camera = Play_GetCamera(play, MAIN_CAM);
- sCameraEye.x = camera->eye.x;
- sCameraEye.y = camera->eye.y;
- sCameraEye.z = camera->eye.z;
- sCameraAt.x = camera->at.x;
- sCameraAt.y = camera->at.y;
- sCameraAt.z = camera->at.z;
- D_80B7A6CC = 2;
+ Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE);
+ mainCam = Play_GetCamera(play, MAIN_CAM);
+ sCameraEye.x = mainCam->eye.x;
+ sCameraEye.y = mainCam->eye.y;
+ sCameraEye.z = mainCam->eye.z;
+ sCameraAt.x = mainCam->at.x;
+ sCameraAt.y = mainCam->at.y;
+ sCameraAt.z = mainCam->at.z;
+ sFishingPlayerCinematicState = 2;
Interface_ChangeAlpha(12);
- D_80B7FECC = 0.0f;
+ sSubCamVelFactor = 0.0f;
// fallthrough
}
case 2:
ShrinkWindow_SetVal(0x1B);
- spFC.x = sLurePos.x - player->actor.world.pos.x;
- spFC.z = sLurePos.z - player->actor.world.pos.z;
- lureDistXZ = sqrtf(SQ(spFC.x) + SQ(spFC.z));
- Matrix_RotateY(Math_Atan2F(spFC.z, spFC.x), MTXMODE_NEW);
+ lureDist.x = sLurePos.x - player->actor.world.pos.x;
+ lureDist.z = sLurePos.z - player->actor.world.pos.z;
+ lureDistXZ = sqrtf(SQ(lureDist.x) + SQ(lureDist.z));
+ Matrix_RotateY(Math_Atan2F(lureDist.z, lureDist.x), MTXMODE_NEW);
- sp114.x = 0.0f;
- sp114.y = 0.0f;
- sp114.z = 100.0f;
- Matrix_MultVec3f(&sp114, &spFC);
+ multiVecSrc.x = 0.0f;
+ multiVecSrc.y = 0.0f;
+ multiVecSrc.z = 100.0f;
+ Matrix_MultVec3f(&multiVecSrc, &lureDist);
- if (D_80B7A694 == 1) {
- camAtFraction = 0.2f;
+ if (sRodCastState == 1) {
+ subCamAtMaxVelFrac = 0.2f;
} else {
- camAtFraction = 0.1f;
+ subCamAtMaxVelFrac = 0.1f;
}
- Math_ApproachF(&sCameraAt.x, sLurePos.x, camAtFraction, fabsf(spFC.x) * D_80B7FECC);
- Math_ApproachF(&sCameraAt.y, sLurePos.y, camAtFraction, 50.0f * D_80B7FECC);
- Math_ApproachF(&sCameraAt.z, sLurePos.z, camAtFraction, fabsf(spFC.z) * D_80B7FECC);
+ Math_ApproachF(&sCameraAt.x, sLurePos.x, subCamAtMaxVelFrac, fabsf(lureDist.x) * sSubCamVelFactor);
+ Math_ApproachF(&sCameraAt.y, sLurePos.y, subCamAtMaxVelFrac, 50.0f * sSubCamVelFactor);
+ Math_ApproachF(&sCameraAt.z, sLurePos.z, subCamAtMaxVelFrac, fabsf(lureDist.z) * sSubCamVelFactor);
- sp114.x = 0.0f - D_80B7FED0;
- if (sLinkAge != 1) {
- sp114.y = 80.0f;
+ multiVecSrc.x = 0.0f - D_80B7FED0;
+ if (sLinkAge != LINK_AGE_CHILD) {
+ multiVecSrc.y = 80.0f;
} else {
- sp114.y = 55.0f;
+ multiVecSrc.y = 55.0f;
}
- sp114.z = -80.0f;
+ multiVecSrc.z = -80.0f;
- Matrix_MultVec3f(&sp114, &sp108);
- sp108.x += player->actor.world.pos.x;
- sp108.y += player->actor.world.pos.y;
- sp108.z += player->actor.world.pos.z;
+ Matrix_MultVec3f(&multiVecSrc, &eyeTarget);
+ eyeTarget.x += player->actor.world.pos.x;
+ eyeTarget.y += player->actor.world.pos.y;
+ eyeTarget.z += player->actor.world.pos.z;
Math_ApproachF(&D_80B7FED0, 30.0f, 0.1f, 0.4f);
- if (CHECK_BTN_ALL(input->press.button, BTN_Z)) {
- if ((D_80B7E088 >= 0) && (D_80B7E122 == 0)) {
- D_80B7E088++;
+ if (CHECK_BTN_ALL(input->press.button, BTN_Z)) { // zoom in/out from the lure
+ if ((sLureCameraZoomLevel >= 0) && (sLureBitTimer == 0)) {
+ sLureCameraZoomLevel++;
- if (D_80B7E088 >= 4) {
- D_80B7E088 = 0;
+ if (sLureCameraZoomLevel >= 4) {
+ sLureCameraZoomLevel = 0;
}
- if ((D_80B7E088 == 0) || (D_80B7E088 == 3)) {
+ if ((sLureCameraZoomLevel == 0) || (sLureCameraZoomLevel == 3)) {
func_80078884(NA_SE_SY_CAMERA_ZOOM_DOWN);
} else {
func_80078884(NA_SE_SY_CAMERA_ZOOM_UP);
@@ -5399,56 +5477,56 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
}
}
- if (D_80B7A694 >= 3) {
+ if (sRodCastState >= 3) {
if (lureDistXZ < 110.0f) {
- D_80B7E088 = -1;
- } else if ((lureDistXZ > 300.0f) && (D_80B7E088 < 0)) {
- D_80B7E088 = 0;
+ sLureCameraZoomLevel = -1;
+ } else if ((lureDistXZ > 300.0f) && (sLureCameraZoomLevel < 0)) {
+ sLureCameraZoomLevel = 0;
}
}
- if (D_80B7E088 > 0) {
+ if (sLureCameraZoomLevel > 0) {
f32 dist;
f32 offset;
f32 factor;
- dist = sqrtf(SQ(spFC.x) + SQ(spFC.z)) * 0.001f;
+ dist = sqrtf(SQ(lureDist.x) + SQ(lureDist.z)) * 0.001f;
if (dist > 1.0f) {
dist = 1.0f;
}
- if (D_80B7E088 == 2) {
+ if (sLureCameraZoomLevel == 2) {
offset = 0.3f;
} else {
offset = 0.1f;
}
factor = 0.4f + offset + (dist * 0.4f);
- sp108.x += (sLurePos.x - sp108.x) * factor;
- sp108.y += ((sLurePos.y - sp108.y) * factor) + 20.0f;
- sp108.z += (sLurePos.z - sp108.z) * factor;
- D_80B7E14C = 0.0005000001f;
+ eyeTarget.x += (sLurePos.x - eyeTarget.x) * factor;
+ eyeTarget.y += ((sLurePos.y - eyeTarget.y) * factor) + 20.0f;
+ eyeTarget.z += (sLurePos.z - eyeTarget.z) * factor;
+ sFishingLineScale = 0.0005000001f;
}
- sp114.x = 0.0f;
- sp114.y = 0.0f;
- sp114.z = 100.0f;
- Matrix_MultVec3f(&sp114, &spFC);
+ multiVecSrc.x = 0.0f;
+ multiVecSrc.y = 0.0f;
+ multiVecSrc.z = 100.0f;
+ Matrix_MultVec3f(&multiVecSrc, &lureDist);
- Math_ApproachF(&sCameraEye.x, sp108.x, 0.3f, fabsf(spFC.x) * D_80B7FECC);
- Math_ApproachF(&sCameraEye.y, sp108.y, 0.3f, 20.0f * D_80B7FECC);
- Math_ApproachF(&sCameraEye.z, sp108.z, 0.3f, fabsf(spFC.z) * D_80B7FECC);
+ Math_ApproachF(&sCameraEye.x, eyeTarget.x, 0.3f, fabsf(lureDist.x) * sSubCamVelFactor);
+ Math_ApproachF(&sCameraEye.y, eyeTarget.y, 0.3f, 20.0f * sSubCamVelFactor);
+ Math_ApproachF(&sCameraEye.z, eyeTarget.z, 0.3f, fabsf(lureDist.z) * sSubCamVelFactor);
break;
case 3: {
- Camera* camera = Play_GetCamera(play, MAIN_CAM);
+ Camera* mainCam = Play_GetCamera(play, MAIN_CAM);
- camera->eye = sCameraEye;
- camera->eyeNext = sCameraEye;
- camera->at = sCameraAt;
- func_800C08AC(play, sCameraId, 0);
+ mainCam->eye = sCameraEye;
+ mainCam->eyeNext = sCameraEye;
+ mainCam->at = sCameraAt;
+ func_800C08AC(play, sSubCamId, 0);
func_80064534(play, &play->csCtx);
- D_80B7A6CC = 0;
- sCameraId = 0;
+ sFishingPlayerCinematicState = 0;
+ sSubCamId = 0;
Environment_EnableUnderwaterLights(play, 0);
play->envCtx.adjFogNear = 0;
player->unk_860 = -5;
@@ -5456,23 +5534,23 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
break;
}
- case 10: {
- Camera* camera;
+ case 10: { // owner tells you to return the rod.
+ Camera* mainCam;
func_80064520(play, &play->csCtx);
- sCameraId = Play_CreateSubCamera(play);
+ sSubCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
- Play_ChangeCameraStatus(play, sCameraId, CAM_STAT_ACTIVE);
+ Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE);
func_8002DF54(play, &this->actor, 5);
- camera = Play_GetCamera(play, MAIN_CAM);
- sCameraEye.x = camera->eye.x;
- sCameraEye.y = camera->eye.y;
- sCameraEye.z = camera->eye.z;
- sCameraAt.x = camera->at.x;
- sCameraAt.y = camera->at.y;
- sCameraAt.z = camera->at.z;
+ mainCam = Play_GetCamera(play, MAIN_CAM);
+ sCameraEye.x = mainCam->eye.x;
+ sCameraEye.y = mainCam->eye.y;
+ sCameraEye.z = mainCam->eye.z;
+ sCameraAt.x = mainCam->at.x;
+ sCameraAt.y = mainCam->at.y;
+ sCameraAt.z = mainCam->at.z;
Message_StartTextbox(play, 0x409E, NULL);
- D_80B7A6CC = 11;
+ sFishingPlayerCinematicState = 11;
func_800A9F6C(0.0f, 150, 10, 10);
// fallthrough
}
@@ -5482,124 +5560,124 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
player->actor.speedXZ = 0.0f;
if (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) {
- Camera* camera = Play_GetCamera(play, MAIN_CAM);
+ Camera* mainCam = Play_GetCamera(play, MAIN_CAM);
- camera->eye = sCameraEye;
- camera->eyeNext = sCameraEye;
- camera->at = sCameraAt;
- func_800C08AC(play, sCameraId, 0);
+ mainCam->eye = sCameraEye;
+ mainCam->eyeNext = sCameraEye;
+ mainCam->at = sCameraAt;
+ func_800C08AC(play, sSubCamId, 0);
func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7);
- D_80B7A6CC = 0;
- sCameraId = 0;
- D_80B7A6D0 = 30;
+ sFishingPlayerCinematicState = 0;
+ sSubCamId = 0;
+ sFishingCinematicTimer = 30;
Environment_EnableUnderwaterLights(play, 0);
play->envCtx.adjFogNear = 0;
}
break;
- case 20: {
- Camera* camera;
+ case 20: { // found the sinking lure
+ Camera* mainCam;
func_80064520(play, &play->csCtx);
- sCameraId = Play_CreateSubCamera(play);
+ sSubCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
- Play_ChangeCameraStatus(play, sCameraId, CAM_STAT_ACTIVE);
+ Play_ChangeCameraStatus(play, sSubCamId, CAM_STAT_ACTIVE);
func_8002DF54(play, &this->actor, 5);
- camera = Play_GetCamera(play, MAIN_CAM);
- sCameraEye.x = camera->eye.x;
- sCameraEye.y = camera->eye.y;
- sCameraEye.z = camera->eye.z;
- sCameraAt.x = camera->at.x;
- sCameraAt.y = camera->at.y;
- sCameraAt.z = camera->at.z;
+ mainCam = Play_GetCamera(play, MAIN_CAM);
+ sCameraEye.x = mainCam->eye.x;
+ sCameraEye.y = mainCam->eye.y;
+ sCameraEye.z = mainCam->eye.z;
+ sCameraAt.x = mainCam->at.x;
+ sCameraAt.y = mainCam->at.y;
+ sCameraAt.z = mainCam->at.z;
Message_StartTextbox(play, 0x409A, NULL);
- D_80B7A6CC = 21;
- D_80B7FEC8 = 45.0f;
- D_80B7A6D0 = 10;
+ sFishingPlayerCinematicState = 21;
+ sCatchCamX = 45.0f;
+ sFishingCinematicTimer = 10;
// fallthrough
}
case 21:
- if ((D_80B7A6D0 == 0) && Message_ShouldAdvance(play)) {
- D_80B7A6CC = 22;
- D_80B7A6D0 = 40;
+ if ((sFishingCinematicTimer == 0) && Message_ShouldAdvance(play)) {
+ sFishingPlayerCinematicState = 22;
+ sFishingCinematicTimer = 40;
func_8002DF54(play, &this->actor, 0x1C);
- D_80B7FEE4 = 0.0f;
+ sSinkingLureHeldY = 0.0f;
}
break;
case 22:
- if (D_80B7A6D0 == 30) {
+ if (sFishingCinematicTimer == 30) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_ITEM_GET | 0x900);
}
- D_80B7A6D4 = 1;
+ sSinkingLureFound = 1;
- Math_ApproachF(&D_80B7FEE4, 71.0f, 0.5f, 3.0f);
+ Math_ApproachF(&sSinkingLureHeldY, 71.0f, 0.5f, 3.0f);
Matrix_RotateY((player->actor.shape.rot.y / 32768.0f) * M_PI, MTXMODE_NEW);
- sp114.x = Math_SinS(play->gameplayFrames * 0x1000);
- sp114.y = D_80B7FEE4;
- sp114.z = -5.0f;
- if (sLinkAge == 1) {
- sp114.y -= 20.0f;
+ multiVecSrc.x = Math_SinS(play->gameplayFrames * 0x1000);
+ multiVecSrc.y = sSinkingLureHeldY;
+ multiVecSrc.z = -5.0f;
+ if (sLinkAge == LINK_AGE_CHILD) {
+ multiVecSrc.y -= 20.0f;
}
- Matrix_MultVec3f(&sp114, &sp108);
+ Matrix_MultVec3f(&multiVecSrc, &eyeTarget);
- sSinkingLureBasePos.x = player->actor.world.pos.x + sp108.x;
- sSinkingLureBasePos.y = player->actor.world.pos.y + sp108.y;
- sSinkingLureBasePos.z = player->actor.world.pos.z + sp108.z;
+ sSinkingLureBasePos.x = player->actor.world.pos.x + eyeTarget.x;
+ sSinkingLureBasePos.y = player->actor.world.pos.y + eyeTarget.y;
+ sSinkingLureBasePos.z = player->actor.world.pos.z + eyeTarget.z;
- Math_ApproachF(&D_80B7FEC8, 15.0f, 0.1f, 0.75f);
+ Math_ApproachF(&sCatchCamX, 15.0f, 0.1f, 0.75f);
- sp114.x = D_80B7FEC8 - 15.0f;
+ multiVecSrc.x = sCatchCamX - 15.0f;
- if (sLinkAge != 1) {
- sp114.y = 60.0f;
- sp114.z = -30.0f;
+ if (sLinkAge != LINK_AGE_CHILD) {
+ multiVecSrc.y = 60.0f;
+ multiVecSrc.z = -30.0f;
} else {
- sp114.y = 40.0f;
- sp114.z = -35.0f;
+ multiVecSrc.y = 40.0f;
+ multiVecSrc.z = -35.0f;
}
- Matrix_MultVec3f(&sp114, &sCameraEye);
+ Matrix_MultVec3f(&multiVecSrc, &sCameraEye);
sCameraEye.x += player->actor.world.pos.x;
sCameraEye.y += player->actor.world.pos.y;
sCameraEye.z += player->actor.world.pos.z;
sCameraAt = player->actor.world.pos;
- if (sLinkAge != 1) {
+ if (sLinkAge != LINK_AGE_CHILD) {
sCameraAt.y += 62.0f;
} else {
sCameraAt.y += 40.0f;
}
- if (D_80B7A6D0 == 0) {
+ if (sFishingCinematicTimer == 0) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) ||
(Message_GetState(&play->msgCtx) == TEXT_STATE_NONE)) {
if (Message_ShouldAdvance(play)) {
- Camera* camera = Play_GetCamera(play, MAIN_CAM);
+ Camera* mainCam = Play_GetCamera(play, MAIN_CAM);
Message_CloseTextbox(play);
if (play->msgCtx.choiceIndex == 0) {
- D_80B7E0B6 = 2;
- D_80B7E082 = 0;
+ sLureEquipped = FS_LURE_SINKING;
+ sPondOwnerTextIdIndex = 0;
}
- camera->eye = sCameraEye;
- camera->eyeNext = sCameraEye;
- camera->at = sCameraAt;
- func_800C08AC(play, sCameraId, 0);
+ mainCam->eye = sCameraEye;
+ mainCam->eyeNext = sCameraEye;
+ mainCam->at = sCameraAt;
+ func_800C08AC(play, sSubCamId, 0);
func_80064534(play, &play->csCtx);
func_8002DF54(play, &this->actor, 7);
- D_80B7A6CC = 0;
- sCameraId = 0;
+ sFishingPlayerCinematicState = 0;
+ sSubCamId = 0;
player->unk_860 = -5;
D_80B7E0B0 = 5;
- D_80B7A6D4 = 0;
- D_80B7E0A6 = 20;
+ sSinkingLureFound = false;
+ sFishingMusicDelay = 20;
Environment_EnableUnderwaterLights(play, 0);
play->envCtx.adjFogNear = 0;
}
@@ -5611,13 +5689,13 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
break;
}
- if (sCameraId != 0) {
- Play_CameraSetAtEye(play, sCameraId, &sCameraAt, &sCameraEye);
- Math_ApproachF(&D_80B7FECC, 1.0f, 1.0f, 0.02f);
+ if (sSubCamId != 0) {
+ Play_CameraSetAtEye(play, sSubCamId, &sCameraAt, &sCameraEye);
+ Math_ApproachF(&sSubCamVelFactor, 1.0f, 1.0f, 0.02f);
if (sCameraEye.y <= (WATER_SURFACE_Y(play) + 1.0f)) {
Environment_EnableUnderwaterLights(play, 1);
- if (D_80B7E076 != 0) {
+ if (sFishingFoggy != 0) {
play->envCtx.adjFogNear = -0xB2;
} else {
play->envCtx.adjFogNear = -0x2E;
@@ -5666,15 +5744,15 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
}
if (sREG(15) != 0) {
- if (D_80B7A654 != (sREG(15) - 1)) {
- if (D_80B7A654 == 0) {
+ if (sStormStrengthTarget != (sREG(15) - 1)) {
+ if (sStormStrengthTarget == 0) {
play->envCtx.gloomySkyMode = 1;
} else {
play->envCtx.gloomySkyMode = 2;
}
}
- D_80B7A654 = sREG(15) - 1;
+ sStormStrengthTarget = sREG(15) - 1;
}
if (sREG(14) == 1) {
@@ -5690,55 +5768,55 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
osSyncPrintf("zelda_time %x\n", ((void)0, gSaveContext.dayTime));
osSyncPrintf(VT_RST);
- if (D_80B7E077 >= 2) {
- D_80B7E077--;
+ if (sStormChanceTimer >= 2) {
+ sStormChanceTimer--;
}
- if ((D_80B7E077 == 1) && (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) &&
- ((D_80B7A680 & 0xFFF) == 0xFFF)) {
- D_80B7E077 = 200;
+ if ((sStormChanceTimer == 1) && (Message_GetState(&play->msgCtx) == TEXT_STATE_NONE) &&
+ ((sFishingTimePlayed & 0xFFF) == 0xFFF)) {
+ sStormChanceTimer = 200;
if (Rand_ZeroOne() < 0.5f) {
- D_80B7A654 = (u8)Rand_ZeroFloat(10.0f) + 5;
+ sStormStrengthTarget = (u8)Rand_ZeroFloat(10.0f) + 5;
play->envCtx.gloomySkyMode = 1;
} else {
- D_80B7A654 = 0;
+ sStormStrengthTarget = 0;
play->envCtx.gloomySkyMode = 2;
}
}
- Math_ApproachF(&D_80B7A650, D_80B7A654, 1.0f, 0.05f);
+ Math_ApproachF(&sStormStrength, sStormStrengthTarget, 1.0f, 0.05f);
- if (D_80B7A650 > 0.0f) {
- target = (D_80B7A650 * 0.03f) + 0.8f;
+ if (sStormStrength > 0.0f) {
+ target = (sStormStrength * 0.03f) + 0.8f;
if (target > 1.2f) {
target = 1.2f;
}
- Math_ApproachF(&D_80B7A668, target, 1.0f, 0.01f);
+ Math_ApproachF(&sStormSfxFreqScale, target, 1.0f, 0.01f);
}
- target = (10.0f - D_80B7A650) * 150.1f;
+ target = (10.0f - sStormStrength) * 150.1f;
if (target < 0.0f) {
target = 0.0f;
}
- Math_ApproachF(&D_80B7A65C.z, target, 1.0f, 5.0f);
+ Math_ApproachF(&sFishingStormSfxPos.z, target, 1.0f, 5.0f);
- if (D_80B7A65C.z < 1500.0f) {
- func_800F436C(&D_80B7A65C, NA_SE_EV_RAIN - SFX_FLAG, D_80B7A668);
+ if (sFishingStormSfxPos.z < 1500.0f) {
+ func_800F436C(&sFishingStormSfxPos, NA_SE_EV_RAIN - SFX_FLAG, sStormSfxFreqScale);
}
- if (D_80B7A654 != 0) {
- Math_ApproachF(&D_80B7A658, -200.0f, 1.0f, 2.0f);
+ if (sStormStrengthTarget != 0) {
+ Math_ApproachF(&sFishingStormShade, -200.0f, 1.0f, 2.0f);
} else {
- Math_ApproachZeroF(&D_80B7A658, 1.0f, 2.0f);
+ Math_ApproachZeroF(&sFishingStormShade, 1.0f, 2.0f);
}
play->envCtx.adjLight1Color[0] = play->envCtx.adjLight1Color[1] = play->envCtx.adjLight1Color[2] =
- D_80B7A658;
+ sFishingStormShade;
- if ((u8)D_80B7A650 > 0) {
+ if ((u8)sStormStrength > 0) {
s32 pad;
- Camera* camera = Play_GetCamera(play, MAIN_CAM);
+ Camera* mainCam = Play_GetCamera(play, MAIN_CAM);
s16 i;
s32 pad1;
Vec3f pos;
@@ -5748,9 +5826,9 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
rot.x = M_PI / 2.0f + 0.1f;
rot.y = 1.0f;
- rot.z = (Camera_GetInputDirYaw(camera) * -(M_PI / 32768)) + rot.y;
+ rot.z = (Camera_GetInputDirYaw(mainCam) * -(M_PI / 32768)) + rot.y;
- for (i = 0; i < (u8)D_80B7A650; i++) {
+ for (i = 0; i < (u8)sStormStrength; i++) {
pos.x = Rand_CenteredFloat(700.0f) + play->view.eye.x;
pos.y = (Rand_ZeroFloat(100.0f) + 150.0f) - 170.0f;
pos.z = Rand_CenteredFloat(700.0f) + play->view.eye.z;
@@ -5772,7 +5850,7 @@ void Fishing_UpdateOwner(Actor* thisx, PlayState* play2) {
func_80078914(&sStreamSoundProjectedPos, NA_SE_EV_WATER_WALL - SFX_FLAG);
- gSaveContext.minigameScore = (SQ((f32)D_80B7A678) * 0.0036f) + 0.5f;
+ gSaveContext.minigameScore = (SQ((f32)sFishLengthToWeigh) * 0.0036f) + 0.5f;
if (BREG(26) != 0) {
BREG(26) = 0;
@@ -5798,9 +5876,9 @@ void Fishing_OwnerPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3
OPEN_DISPS(play->state.gfxCtx);
Matrix_MultVec3f(&sZeroVec, &sOwnerHeadPos);
- if (D_80B7A688 == 1) {
+ if (sOwnerHair == FS_OWNER_CAPPED) {
gSPDisplayList(POLY_OPA_DISP++, SEGMENTED_TO_VIRTUAL(gFishingOwnerHatDL));
- } else if (D_80B7A688 == 2) {
+ } else if (sOwnerHair == FS_OWNER_HAIR) {
gSPDisplayList(POLY_OPA_DISP++, SEGMENTED_TO_VIRTUAL(gFishingOwnerHairDL));
}
@@ -5837,17 +5915,17 @@ void Fishing_DrawOwner(Actor* thisx, PlayState* play) {
Fishing_DrawGroupFishes(play);
Fishing_DrawStreamSplash(play);
- if (D_80B7E0A6 != 0) {
- D_80B7E0A6--;
+ if (sFishingMusicDelay != 0) {
+ sFishingMusicDelay--;
- if (D_80B7E0A6 == 0) {
- if (sLinkAge != 1) {
+ if (sFishingMusicDelay == 0) {
+ if (sLinkAge != LINK_AGE_CHILD) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_KAKARIKO_ADULT);
} else {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_KAKARIKO_KID);
}
- if (sLinkAge != 1) {
+ if (sLinkAge != LINK_AGE_CHILD) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_KAKARIKO_ADULT);
} else {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_KAKARIKO_KID);
@@ -5855,17 +5933,17 @@ void Fishing_DrawOwner(Actor* thisx, PlayState* play) {
}
}
- if ((D_80B7E0AC != 0) && D_80B7A674) {
+ if ((sFishingPlayingState != 0) && sIsRodVisible) {
Fishing_DrawRod(play);
Fishing_UpdateLinePos(sReelLinePos);
Fishing_UpdateLine(play, &sRodTipPos, sReelLinePos, sReelLineRot, sReelLineUnk);
Fishing_DrawLureAndLine(play, sReelLinePos, sReelLineRot);
- D_80B7A6C4 = input->rel.stick_x;
- D_80B7A6C8 = input->rel.stick_y;
+ sStickAdjXPrev = input->rel.stick_x;
+ sStickAdjYPrev = input->rel.stick_y;
}
- D_80B7A674 = true;
+ sIsRodVisible = true;
Matrix_Translate(130.0f, 40.0f, 1300.0f, MTXMODE_NEW);
Matrix_Scale(0.08f, 0.12f, 0.14f, MTXMODE_APPLY);
@@ -5878,7 +5956,7 @@ void Fishing_DrawOwner(Actor* thisx, PlayState* play) {
gSPDisplayList(POLY_OPA_DISP++, gFishingAquariumBottomDL);
gSPDisplayList(POLY_XLU_DISP++, gFishingAquariumContainerDL);
- if ((D_80B7E0AC != 0) && (D_80B7E0B6 == 2)) {
+ if ((sFishingPlayingState != 0) && (sLureEquipped == 2)) {
Fishing_DrawSinkingLure(play);
}
@@ -5888,6 +5966,6 @@ void Fishing_DrawOwner(Actor* thisx, PlayState* play) {
void Fishing_Reset(void) {
// Reset static variables for fishing camera and cinematic state to prevent crashing when dying
// or re-entering the scene while the fishing rod was cast
- sCameraId = 0;
- D_80B7A6CC = 0;
+ sSubCamId = 0;
+ sFishingPlayerCinematicState = 0;
}
diff --git a/soh/src/overlays/actors/ovl_Fishing/z_fishing.h b/soh/src/overlays/actors/ovl_Fishing/z_fishing.h
index f83416834..b128c71a5 100644
--- a/soh/src/overlays/actors/ovl_Fishing/z_fishing.h
+++ b/soh/src/overlays/actors/ovl_Fishing/z_fishing.h
@@ -3,61 +3,65 @@
#include
#include "global.h"
+#include "soh/Enhancements/randomizer/fishsanity.h"
struct Fishing;
typedef struct Fishing {
/* 0x0000 */ Actor actor;
/* 0x014C */ char unk_14C[0x004];
- /* 0x0150 */ u8 unk_150;
- /* 0x0151 */ u8 unk_151;
+ /* 0x0150 */ u8 isLoach;
+ /* 0x0151 */ u8 lilyTimer; // if near lily and >0, lily moves. Move more if >20
/* 0x0152 */ u8 unk_152;
/* 0x0154 */ s16 unk_154;
/* 0x0156 */ u8 unk_156;
/* 0x0157 */ u8 unk_157;
- /* 0x0158 */ s16 unk_158;
- /* 0x015A */ s16 unk_15A;
- /* 0x015C */ s16 unk_15C;
+ /* 0x0158 */ s16 fishState; // negative index for loach behavior
+ /* 0x015A */ s16 fishStateNext;
+ /* 0x015C */ s16 stateAndTimer; // fish use as timer that's AND'd, owner as talking state
/* 0x015E */ s16 unk_15E;
- /* 0x0160 */ s16 unk_160;
- /* 0x0162 */ s16 unk_162;
- /* 0x0164 */ s16 unk_164;
- /* 0x0166 */ s16 unk_166;
- /* 0x0168 */ s16 unk_168;
- /* 0x016A */ s16 unk_16A;
- /* 0x016C */ s16 unk_16C;
+ /* 0x0160 */ s16 unk_160; // fish use as rotateX, owner as index of eye texture
+ /* 0x0162 */ s16 unk_162; // fish use as rotateY, owner as index of eye texture
+ /* 0x0164 */ s16 unk_164; // fish use as rotateZ, owner as rotation of head
+ /* 0x0166 */ Vec3s rotationTarget;
+ /* 0x016C */ s16 fishLimb23RotYDelta;
/* 0x016E */ s16 unk_16E;
- /* 0x0170 */ s16 unk_170;
- /* 0x0172 */ s16 unk_172;
- /* 0x0174 */ s16 unk_174;
- /* 0x0176 */ s16 unk_176;
+ /* 0x0170 */ s16 fishLimbDRotZDelta;
+ /* 0x0172 */ s16 fishLimbEFRotYDelta;
+ /* 0x0174 */ s16 fishLimb89RotYDelta;
+ /* 0x0176 */ s16 fishLimb4RotYDelta;
/* 0x0178 */ s16 unk_178;
- /* 0x017A */ s16 unk_17A[4];
+ /* 0x017A */ s16 timerArray[4];
/* 0x0184 */ f32 unk_184;
- /* 0x0188 */ f32 unk_188;
- /* 0x018C */ f32 unk_18C;
- /* 0x0190 */ f32 unk_190;
- /* 0x0194 */ f32 unk_194;
- /* 0x0198 */ f32 unk_198;
- /* 0x019C */ f32 unk_19C;
- /* 0x01A0 */ s16 unk_1A0;
- /* 0x01A2 */ s16 unk_1A2;
- /* 0x01A4 */ s16 unk_1A4;
- /* 0x01A8 */ f32 unk_1A8;
- /* 0x01AC */ f32 unk_1AC;
- /* 0x01B0 */ f32 unk_1B0;
- /* 0x01B4 */ Vec3f unk_1B4;
+ /* 0x0188 */ f32 speedTarget;
+ /* 0x018C */ f32 fishLimbRotPhase;
+ /* 0x0190 */ f32 unk_190; // fishLimbRotPhaseStep target
+ /* 0x0194 */ f32 unk_194; // fishLimbRotPhaseMag target
+ /* 0x0198 */ f32 fishLimbRotPhaseStep;
+ /* 0x019C */ f32 fishLimbRotPhaseMag;
+ /* 0x01A0 */ s16 bumpTimer; // set when hitting a wall.
+ /* 0x01A2 */ s16 unk_1A2; // "scared" timer?
+ /* 0x01A4 */ s16 unk_1A4; // "scared" timer? set at same time as above
+ /* 0x01A8 */ f32 perception; // how easily they are drawn to the lure.
+ /* 0x01AC */ f32 fishLength; // fish are (x^2*.0036+.5) lbs, loach double that.
+ /* 0x01B0 */ f32 rotationStep;
+ /* 0x01B4 */ Vec3f fishTargetPos;
/* 0x01C0 */ Vec3f fishMouthPos;
- /* 0x01CC */ s16 unk_1CC[3];
- /* 0x01D2 */ u8 unk_1D2;
- /* 0x01D3 */ u8 unk_1D3;
- /* 0x01D4 */ u8 unk_1D4;
- /* 0x01D5 */ u8 unk_1D5;
+ /* 0x01CC */ s16 loachRotYDelta[3]; // adds rotation to the loach limb 3-5.
+ /* 0x01D2 */ u8 bubbleTime; // spawn bubbles while >0
+ /* 0x01D3 */ u8 isAquariumMessage;
+ /* 0x01D4 */ u8 aquariumWaitTimer;
+ /* 0x01D5 */ u8 keepState; // case-switch and keeping or releasing a fish
/* 0x01D8 */ SkelAnime skelAnime;
/* 0x021C */ LightNode* lightNode;
/* 0x0220 */ LightInfo lightInfo;
/* 0x0230 */ ColliderJntSph collider;
/* 0x0250 */ ColliderJntSphElement colliderElements[12];
+ /* */ s16 fishsanityParams;
} Fishing; // size = 0x0550
+#define EN_FISH_OWNER 1 // param for owner of pond. default if params<100
+#define EN_FISH_PARAM 100 // param base for fish in pond.
+#define EN_FISH_AQUARIUM 200 // param for record fish in tank.
+
#endif
diff --git a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c
index 2f5cf4ee3..bbe5bd0aa 100644
--- a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c
+++ b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c
@@ -193,7 +193,7 @@ void ObjMure_SpawnActors1(ObjMure* this, PlayState* play) {
this->children[i] = Actor_Spawn(ac, play, sSpawnActorIds[this->type], spawnPos.x, spawnPos.y, spawnPos.z,
actor->world.rot.x, actor->world.rot.y, actor->world.rot.z,
(this->type == 4 && i == 0) ? 1 : sSpawnParams[this->type], true);
- if (this->children[i] != NULL) {
+ if (this->children[i] != NULL && this->children[i]->update != NULL) {
this->childrenStates[i] = OBJMURE_CHILD_STATE_0;
this->children[i]->room = actor->room;
} else {
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index 82a600bee..279aa50e3 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -29,6 +29,7 @@
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/randomizer/randomizer_grotto.h"
+#include "soh/Enhancements/randomizer/fishsanity.h"
#include "soh/frame_interpolation.h"
#include
@@ -13658,14 +13659,41 @@ void func_8084ECA4(Player* this, PlayState* play) {
struct_80854554* sp24;
BottleCatchInfo* catchInfo;
s32 temp;
- s32 i;
+ s32 i, j;
+ FishIdentity fish;
+ GetItemEntry gi = GET_ITEM_NONE;
+ RandomizerCheck rc = RC_UNKNOWN_CHECK;
+ u8 catchId;
- sp24 = &D_80854554[this->unk_850];
func_8083721C(this);
+ // TODO: Rework the bottle rando code in vanilla behavior overhaul
if (LinkAnimation_Update(play, &this->skelAnime)) {
if (this->unk_84F != 0) {
- if (this->unk_850 == 0) {
+ if (IS_RANDO && this->unk_84F < 0) {
+ rc = this->unk_850;
+ // Award rando item; this should only give us GI_NONE if something went wrong during the catch setup
+ gi = Randomizer_GetItemFromKnownCheck(rc, GI_NONE);
+ temp = Randomizer_GetRandomizerInfFromCheck(rc);
+ // Either we can't give an item, we can't tell if we've gotten the check, or we have definitely gotten the check
+ if (gi.getItemId == GI_NONE || temp == RAND_INF_MAX || Flags_GetRandomizerInf(temp)) {
+ this->unk_84F = 0;
+ if (this->interactRangeActor != NULL)
+ this->interactRangeActor->parent = NULL;
+ }
+ // Item get cutscene hasn't played yet
+ else if((this->interactRangeActor == NULL && !(this->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD)) || !Actor_HasParent(this->interactRangeActor, play)) {
+ // Can't guarantee that whatever we "caught" is actually going to still exist
+ if (GiveItemEntryWithoutActor(play, gi)) {
+ // have to set this flag manually to prevent interactRangeActor from being wiped out
+ this->stateFlags1 |= PLAYER_STATE1_ITEM_OVER_HEAD;
+ this->pendingFlag.flagID = temp;
+ this->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
+ Flags_SetRandomizerInf(temp);
+ }
+
+ }
+ } else if (this->unk_850 == 0) {
if (CVarGetInteger("gFastDrops", 0)) {
this->unk_84F = 0;
} else {
@@ -13682,6 +13710,7 @@ void func_8084ECA4(Player* this, PlayState* play) {
}
} else {
if (this->unk_84F == 0) {
+ sp24 = &D_80854554[this->unk_850];
temp = this->skelAnime.curFrame - sp24->unk_08;
if (temp >= 0) {
@@ -13704,11 +13733,38 @@ void func_8084ECA4(Player* this, PlayState* play) {
this->unk_84F = i + 1;
this->unk_850 = 0;
this->interactRangeActor->parent = &this->actor;
- Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction));
- if (!CVarGetInteger("gFastDrops", 0)) {
- this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
- Player_AnimPlayOnceAdjusted(play, this, sp24->unk_04);
- func_80835EA4(play, 4);
+ // TODO: this should probably be refactored a bit, maybe rehome some of this to rando instead
+ if (IS_RANDO) {
+ // Check if fishsanity applies for this actor
+ if (Randomizer_GetOverworldFishShuffled()) {
+ fish = Randomizer_IdentifyFish(play->sceneNum, this->interactRangeActor->params);
+ if (fish.randomizerCheck != RC_UNKNOWN_CHECK && !Flags_GetRandomizerInf(fish.randomizerInf)) {
+ gi = Randomizer_GetItemFromKnownCheck(fish.randomizerCheck, GI_FISH);
+ rc = fish.randomizerCheck;
+ // check if the item is a bottle item anyway
+ catchInfo = NULL;
+ for (j = 0; j < 4; j++) {
+ if (D_80854A04[j].itemId == gi.itemId) {
+ catchInfo = &D_80854A04[j];
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Vanilla behavior/rando gave a bottle item
+ if (!IS_RANDO || catchInfo != NULL) {
+ Player_UpdateBottleHeld(play, this, catchInfo->itemId, ABS(catchInfo->itemAction));
+ if (!CVarGetInteger("gFastDrops", 0)) {
+ this->stateFlags1 |= PLAYER_STATE1_IN_ITEM_CS | PLAYER_STATE1_IN_CUTSCENE;
+ Player_AnimPlayOnceAdjusted(play, this, sp24->unk_04);
+ func_80835EA4(play, 4);
+ }
+ } else if (IS_RANDO && gi.itemId != ITEM_NONE) {
+ // Non-bottle item found from rando, flag for special behavior
+ this->unk_84F = -1;
+ this->unk_850 = rc;
}
}
}