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; } } }