From 44f03064a21fab4265d14b90d2c1bde129c45022 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 25 Nov 2024 16:21:44 -0600 Subject: [PATCH] Migrate enhancements to ShipInit pattern --- mm/2s2h/BenGui/BenMenuBar.cpp | 50 +- mm/2s2h/BenGui/SearchableMenuItems.h | 59 +- mm/2s2h/Enhancements/Cheats/Cheats.h | 13 - mm/2s2h/Enhancements/Cheats/ElegyAnywhere.cpp | 12 +- .../Enhancements/Cheats/HookshotAnywhere.cpp | 14 +- mm/2s2h/Enhancements/Cheats/Infinite.cpp | 44 +- .../Enhancements/Cheats/LongerFlowerGlide.cpp | 10 +- mm/2s2h/Enhancements/Cheats/MoonJump.cpp | 34 +- mm/2s2h/Enhancements/Cheats/TimeStop.cpp | 14 +- .../Cheats/UnbreakableRazorSword.cpp | 12 +- .../Enhancements/Cheats/UnrestrictedItems.cpp | 12 +- mm/2s2h/Enhancements/Dialogue/Dialogue.h | 6 - .../Dialogue/FastBankSelection.cpp | 118 ++-- .../DekuGuardSearchBalls.cpp | 14 +- .../DifficultyOptions/DifficultyOptions.h | 7 - .../DifficultyOptions/DisableTakkuriSteal.cpp | 16 +- mm/2s2h/Enhancements/Enhancements.cpp | 65 --- mm/2s2h/Enhancements/Enhancements.h | 20 +- mm/2s2h/Enhancements/Equipment/Equipment.h | 8 - .../Enhancements/Equipment/InstantRecall.cpp | 24 +- .../Equipment/SkipMagicArrowEquip.cpp | 19 +- .../Equipment/TwoHandedSwordSpinAttack.cpp | 73 ++- .../Fixes/CompletedHeartContainerAudio.cpp | 11 +- .../Fixes/FierceDeityZTargetMovement.cpp | 11 +- mm/2s2h/Enhancements/Fixes/Fixes.h | 7 - mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp | 44 +- mm/2s2h/Enhancements/Graphics/3DSClock.cpp | 533 +++++++++--------- .../Graphics/DisableBlackBars.cpp | 12 +- mm/2s2h/Enhancements/Graphics/Graphics.h | 6 - .../Graphics/HyruleWarriorsStyledLink.cpp | 64 --- mm/2s2h/Enhancements/Graphics/MotionBlur.cpp | 3 +- .../Enhancements/Graphics/TextBasedClock.cpp | 164 +++--- mm/2s2h/Enhancements/Masks/BlastMaskKeg.cpp | 40 +- .../Enhancements/Masks/FastTransformation.cpp | 69 ++- .../Masks/FierceDeityAnywhere.cpp | 15 +- mm/2s2h/Enhancements/Masks/Masks.h | 11 - .../Masks/NoBlastMaskCooldown.cpp | 12 +- .../Enhancements/Masks/PersistentMasks.cpp | 73 ++- .../Minigames/AlwaysWinDoggyRace.cpp | 17 +- mm/2s2h/Enhancements/Minigames/CremiaHugs.cpp | 19 +- .../Minigames/CuccoShackCuccoCount.cpp | 44 +- mm/2s2h/Enhancements/Minigames/Minigames.h | 9 - .../Minigames/SwordsmanSchool.cpp | 44 +- .../Modes/HyruleWarriorsStyledLink.cpp | 51 ++ mm/2s2h/Enhancements/Modes/Modes.h | 6 - .../{Graphics => Modes}/PlayAsKafei.cpp | 24 +- .../Modes/TimeMovesWhenYouMove.cpp | 33 +- mm/2s2h/Enhancements/Player/ClimbSpeed.cpp | 14 +- .../Enhancements/Player/FastFlowerLaunch.cpp | 60 +- .../Player/FierceDeityPutaway.cpp | 24 +- .../Enhancements/Player/InstantPutaway.cpp | 12 +- mm/2s2h/Enhancements/Player/Player.h | 9 - mm/2s2h/Enhancements/Songs/EnableSunsSong.cpp | 12 +- .../Enhancements/Songs/FasterSongPlayback.cpp | 34 +- mm/2s2h/Enhancements/Songs/PauseOwlWarp.cpp | 10 +- .../Enhancements/Songs/SkipScarecrowSong.cpp | 37 +- mm/2s2h/Enhancements/Songs/Songs.h | 6 - mm/2s2h/Enhancements/Songs/ZoraEggCount.cpp | 40 +- 58 files changed, 1011 insertions(+), 1213 deletions(-) delete mode 100644 mm/2s2h/Enhancements/Cheats/Cheats.h delete mode 100644 mm/2s2h/Enhancements/Dialogue/Dialogue.h delete mode 100644 mm/2s2h/Enhancements/DifficultyOptions/DifficultyOptions.h delete mode 100644 mm/2s2h/Enhancements/Equipment/Equipment.h delete mode 100644 mm/2s2h/Enhancements/Fixes/Fixes.h delete mode 100644 mm/2s2h/Enhancements/Graphics/HyruleWarriorsStyledLink.cpp delete mode 100644 mm/2s2h/Enhancements/Masks/Masks.h delete mode 100644 mm/2s2h/Enhancements/Minigames/Minigames.h create mode 100644 mm/2s2h/Enhancements/Modes/HyruleWarriorsStyledLink.cpp delete mode 100644 mm/2s2h/Enhancements/Modes/Modes.h rename mm/2s2h/Enhancements/{Graphics => Modes}/PlayAsKafei.cpp (86%) delete mode 100644 mm/2s2h/Enhancements/Player/Player.h diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index ec9fe7762f..ed0a1e1d00 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -8,6 +8,7 @@ #include #include #include "2s2h/Enhancements/Enhancements.h" +#include "2s2h/Enhancements/Graphics/Graphics.h" #include "2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h" #include "2s2h/DeveloperTools/DeveloperTools.h" #include "HudEditor.h" @@ -649,10 +650,8 @@ void DrawEnhancementsMenu() { "model and texture on the boot logo start screen" }); UIWidgets::CVarCheckbox("Bow Reticle", "gEnhancements.Graphics.BowReticle", { .tooltip = "Gives the bow a reticle when you draw an arrow" }); - if (UIWidgets::CVarCheckbox("3D Item Drops", "gEnhancements.Graphics.3DItemDrops", - { .tooltip = "Makes item drops 3D" })) { - Register3DItemDrops(); - } + UIWidgets::CVarCheckbox("3D Item Drops", "gEnhancements.Graphics.3DItemDrops", + { .tooltip = "Makes item drops 3D" }); UIWidgets::CVarCheckbox( "Disable Black Bar Letterboxes", "gEnhancements.Graphics.DisableBlackBars", { .tooltip = "Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be " @@ -686,11 +685,9 @@ void DrawEnhancementsMenu() { UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere", { .tooltip = "Allow using Fierce Deity's mask outside of boss rooms." }); UIWidgets::CVarCheckbox("No Blast Mask Cooldown", "gEnhancements.Masks.NoBlastMaskCooldown", {}); - if (UIWidgets::CVarCheckbox("Persistent Bunny Hood", "gEnhancements.Masks.PersistentBunnyHood.Enabled", - { .tooltip = "Permanently toggle a speed boost from the bunny hood by pressing " - "'A' on it in the mask menu." })) { - UpdatePersistentMasksState(); - } + UIWidgets::CVarCheckbox("Persistent Bunny Hood", "gEnhancements.Masks.PersistentBunnyHood.Enabled", + { .tooltip = "Permanently toggle a speed boost from the bunny hood by pressing " + "'A' on it in the mask menu." }); ImGui::EndMenu(); } @@ -717,9 +714,7 @@ void DrawEnhancementsMenu() { UIWidgets::CVarCheckbox("Hyrule Warriors Young Link", "gModes.HyruleWarriorsStyledLink", { .tooltip = "When acquired, places the Keaton and Fierce Deity masks on Link " "similarly to how he wears them in Hyrule Warriors" }); - if (UIWidgets::CVarCheckbox("Time Moves When You Move", "gModes.TimeMovesWhenYouMove")) { - RegisterTimeMovesWhenYouMove(); - } + UIWidgets::CVarCheckbox("Time Moves When You Move", "gModes.TimeMovesWhenYouMove"); if (UIWidgets::CVarCheckbox("Mirrored World", "gModes.MirroredWorld.Mode")) { if (CVarGetInteger("gModes.MirroredWorld.Mode", 0)) { CVarSetInteger("gModes.MirroredWorld.State", 1); @@ -734,12 +729,9 @@ void DrawEnhancementsMenu() { if (UIWidgets::BeginMenu("Player")) { UIWidgets::CVarSliderInt("Climb speed", "gEnhancements.Player.ClimbSpeed", 1, 5, 1, { .tooltip = "Increases the speed at which Link climbs vines and ladders." }); - if (UIWidgets::CVarCheckbox("Fast Deku Flower Launch", "gEnhancements.Player.FastFlowerLaunch", - { .tooltip = - "Speeds up the time it takes to be able to get maximum height from " - "launching out of a deku flower" })) { - RegisterFastFlowerLaunch(); - } + UIWidgets::CVarCheckbox("Fast Deku Flower Launch", "gEnhancements.Player.FastFlowerLaunch", + { .tooltip = "Speeds up the time it takes to be able to get maximum height from " + "launching out of a deku flower" }); UIWidgets::CVarCheckbox("Instant Putaway", "gEnhancements.Player.InstantPutaway", { .tooltip = "Allows Link to instantly puts away held item without waiting." }); UIWidgets::CVarCheckbox("Fierce Deity Putaway", "gEnhancements.Player.FierceDeityPutaway", @@ -793,11 +785,9 @@ void DrawEnhancementsMenu() { } if (UIWidgets::BeginMenu("Difficulty Options")) { - if (UIWidgets::CVarCheckbox("Disable Takkuri Steal", "gEnhancements.Cheats.DisableTakkuriSteal", - { .tooltip = "Prevents the Takkuri from stealing key items like bottles and " - "swords. It may still steal other items." })) { - RegisterDisableTakkuriSteal(); - } + UIWidgets::CVarCheckbox("Disable Takkuri Steal", "gEnhancements.Cheats.DisableTakkuriSteal", + { .tooltip = "Prevents the Takkuri from stealing key items like bottles and " + "swords. It may still steal other items." }); UIWidgets::CVarCombobox( "Deku Guard Search Balls", "gEnhancements.Cheats.DekuGuardSearchBalls", dekuGuardSearchBallsOptions, @@ -833,21 +823,17 @@ void DrawCheatsMenu() { UIWidgets::CVarCheckbox("Infinite Magic", "gCheats.InfiniteMagic"); UIWidgets::CVarCheckbox("Infinite Rupees", "gCheats.InfiniteRupees"); UIWidgets::CVarCheckbox("Infinite Consumables", "gCheats.InfiniteConsumables"); - if (UIWidgets::CVarCheckbox( - "Longer Deku Flower Glide", "gCheats.LongerFlowerGlide", - { .tooltip = "Allows Deku Link to glide longer, no longer dropping after a certain distance" })) { - RegisterLongerFlowerGlide(); - } + UIWidgets::CVarCheckbox( + "Longer Deku Flower Glide", "gCheats.LongerFlowerGlide", + { .tooltip = "Allows Deku Link to glide longer, no longer dropping after a certain distance" }); UIWidgets::CVarCheckbox("No Clip", "gCheats.NoClip"); UIWidgets::CVarCheckbox("Unbreakable Razor Sword", "gCheats.UnbreakableRazorSword"); UIWidgets::CVarCheckbox("Unrestricted Items", "gCheats.UnrestrictedItems"); UIWidgets::CVarCheckbox("Hookshot Anywhere", "gCheats.HookshotAnywhere", { .tooltip = "Allows most surfaces to be hookshot-able" }); - if (UIWidgets::CVarCheckbox("Moon Jump on L", "gCheats.MoonJumpOnL", - { .tooltip = "Holding L makes you float into the air" })) { - RegisterMoonJumpOnL(); - } + UIWidgets::CVarCheckbox("Moon Jump on L", "gCheats.MoonJumpOnL", + { .tooltip = "Holding L makes you float into the air" }); UIWidgets::CVarCheckbox("Elegy of Emptiness Anywhere", "gCheats.ElegyAnywhere", { .tooltip = "Allows Elegy of Emptiness outside of Ikana" }); UIWidgets::CVarCombobox( diff --git a/mm/2s2h/BenGui/SearchableMenuItems.h b/mm/2s2h/BenGui/SearchableMenuItems.h index f5b2ff2ba9..8313ba1700 100644 --- a/mm/2s2h/BenGui/SearchableMenuItems.h +++ b/mm/2s2h/BenGui/SearchableMenuItems.h @@ -1014,12 +1014,9 @@ void AddEnhancements() { { "Infinite Rupees", "gCheats.InfiniteRupees", "Always have a full Wallet.", WIDGET_CVAR_CHECKBOX, {} }, { "Infinite Consumables", "gCheats.InfiniteConsumables", "Always have max Consumables, you must have collected the consumables first.", WIDGET_CVAR_CHECKBOX }, - { "Longer Deku Flower Glide", - "gCheats.LongerFlowerGlide", + { "Longer Deku Flower Glide", "gCheats.LongerFlowerGlide", "Allows Deku Link to glide longer, no longer dropping after a certain distance.", - WIDGET_CVAR_CHECKBOX, - {}, - [](widgetInfo& info) { RegisterLongerFlowerGlide(); } }, + WIDGET_CVAR_CHECKBOX }, { "No Clip", "gCheats.NoClip", "Allows Link to phase through collision.", WIDGET_CVAR_CHECKBOX }, { "Unbreakable Razor Sword", "gCheats.UnbreakableRazorSword", "Allows to Razor Sword to be used indefinitely without dulling its blade.", WIDGET_CVAR_CHECKBOX }, @@ -1027,12 +1024,8 @@ void AddEnhancements() { WIDGET_CVAR_CHECKBOX }, { "Hookshot Anywhere", "gCheats.HookshotAnywhere", "Allows most surfaces to be hookshot-able", WIDGET_CVAR_CHECKBOX }, - { "Moon Jump on L", - "gCheats.MoonJumpOnL", - "Holding L makes you float into the air.", - WIDGET_CVAR_CHECKBOX, - {}, - [](widgetInfo& info) { RegisterMoonJumpOnL(); } }, + { "Moon Jump on L", "gCheats.MoonJumpOnL", "Holding L makes you float into the air.", + WIDGET_CVAR_CHECKBOX }, { "Elegy of Emptiness Anywhere", "gCheats.ElegyAnywhere", "Allows Elegy of Emptiness outside of Ikana", WIDGET_CVAR_CHECKBOX }, { "Stop Time in Dungeons", @@ -1049,12 +1042,9 @@ void AddEnhancements() { { "Gameplay", 3, { { { .widgetName = "Player", .widgetType = WIDGET_SEPARATOR_TEXT }, - { "Fast Deku Flower Launch", - "gEnhancements.Player.FastFlowerLaunch", + { "Fast Deku Flower Launch", "gEnhancements.Player.FastFlowerLaunch", "Speeds up the time it takes to be able to get maximum height from launching out of a deku flower", - WIDGET_CVAR_CHECKBOX, - {}, - ([](widgetInfo& info) { RegisterFastFlowerLaunch(); }) }, + WIDGET_CVAR_CHECKBOX }, { "Instant Putaway", "gEnhancements.Player.InstantPutaway", "Allows Link to instantly puts away held item without waiting.", WIDGET_CVAR_CHECKBOX }, { "Fierce Deity Putaway", "gEnhancements.Player.FierceDeityPutaway", @@ -1103,12 +1093,8 @@ void AddEnhancements() { "When acquired, places the Keaton and Fierce Deity masks on Link similarly to how he wears them in " "Hyrule Warriors", WIDGET_CVAR_CHECKBOX }, - { "Time Moves when you Move", - "gModes.TimeMovesWhenYouMove", - "Time only moves when Link is not standing still.", - WIDGET_CVAR_CHECKBOX, - {}, - ([](widgetInfo& info) { RegisterTimeMovesWhenYouMove(); }) }, + { "Time Moves when you Move", "gModes.TimeMovesWhenYouMove", + "Time only moves when Link is not standing still.", WIDGET_CVAR_CHECKBOX }, { "Mirrored World", "gModes.MirroredWorld.Mode", "Mirrors the world horizontally.", @@ -1241,12 +1227,7 @@ void AddEnhancements() { disabledMap.at(DISABLE_FOR_MOTION_BLUR_OFF).active; } }, { .widgetName = "Other", .widgetType = WIDGET_SEPARATOR_TEXT }, - { "3D Item Drops", - "gEnhancements.Graphics.3DItemDrops", - "Makes item drops 3D", - WIDGET_CVAR_CHECKBOX, - {}, - [](widgetInfo& info) { Register3DItemDrops(); } }, + { "3D Item Drops", "gEnhancements.Graphics.3DItemDrops", "Makes item drops 3D", WIDGET_CVAR_CHECKBOX }, { "Authentic Logo", "gEnhancements.Graphics.AuthenticLogo", "Hide the game version and build details and display the authentic " "model and texture on the boot logo start screen", @@ -1291,13 +1272,10 @@ void AddEnhancements() { "Removes the delay when using transformation masks.", WIDGET_CVAR_CHECKBOX }, { "Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere", "Allow using Fierce Deity's mask outside of boss rooms.", WIDGET_CVAR_CHECKBOX }, - { "Persistent Bunny Hood", - "gEnhancements.Masks.PersistentBunnyHood.Enabled", + { "Persistent Bunny Hood", "gEnhancements.Masks.PersistentBunnyHood.Enabled", "Permanently toggle a speed boost from the bunny hood by pressing " "'A' on it in the mask menu.", - WIDGET_CVAR_CHECKBOX, - {}, - [](widgetInfo& info) { UpdatePersistentMasksState(); } }, + WIDGET_CVAR_CHECKBOX }, { "No Blast Mask Cooldown", "gEnhancements.Masks.NoBlastMaskCooldown", "Eliminates the Cooldown between Blast Mask usage.", WIDGET_CVAR_CHECKBOX } }, // Song Enhancements @@ -1322,12 +1300,8 @@ void AddEnhancements() { "Prevent dropping inputs when playing the ocarina quickly.", WIDGET_CVAR_CHECKBOX }, { "Skip Scarecrow Song", "gEnhancements.Playback.SkipScarecrowSong", "Pierre appears when the Ocarina is pulled out.", WIDGET_CVAR_CHECKBOX }, - { "Faster Song Playback", - "gEnhancements.Songs.FasterSongPlayback", - "Speeds up the playback of songs.", - WIDGET_CVAR_CHECKBOX, - {}, - [](widgetInfo& info) { RegisterFasterSongPlayback(); } } } } }); + { "Faster Song Playback", "gEnhancements.Songs.FasterSongPlayback", "Speeds up the playback of songs.", + WIDGET_CVAR_CHECKBOX } } } }); enhancementsSidebar.push_back( { "Time Savers", 3, @@ -1423,12 +1397,9 @@ void AddEnhancements() { enhancementsSidebar.push_back( { "Difficulty Options", 3, - { { { "Disable Takkuri Steal", - "gEnhancements.Cheats.DisableTakkuriSteal", + { { { "Disable Takkuri Steal", "gEnhancements.Cheats.DisableTakkuriSteal", "Prevents the Takkuri from stealing key items like bottles and swords. It may still steal other items.", - WIDGET_CVAR_CHECKBOX, - {}, - [](widgetInfo& info) { RegisterDisableTakkuriSteal(); } }, + WIDGET_CVAR_CHECKBOX }, { "Deku Guard Search Balls", "gEnhancements.Cheats.DekuGuardSearchBalls", "Choose when to show the Deku Palace Guards' search balls\n" diff --git a/mm/2s2h/Enhancements/Cheats/Cheats.h b/mm/2s2h/Enhancements/Cheats/Cheats.h deleted file mode 100644 index ec6cbe80f3..0000000000 --- a/mm/2s2h/Enhancements/Cheats/Cheats.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef CHEATS_H -#define CHEATS_H - -void RegisterInfiniteCheats(); -void RegisterLongerFlowerGlide(); -void RegisterMoonJumpOnL(); -void RegisterTimeStopInTemples(); -void RegisterUnbreakableRazorSword(); -void RegisterUnrestrictedItems(); -void RegisterElegyAnywhere(); -void RegisterHookshotAnywhere(); - -#endif // CHEATS_H diff --git a/mm/2s2h/Enhancements/Cheats/ElegyAnywhere.cpp b/mm/2s2h/Enhancements/Cheats/ElegyAnywhere.cpp index ee04b4f5c0..9bfad607e7 100644 --- a/mm/2s2h/Enhancements/Cheats/ElegyAnywhere.cpp +++ b/mm/2s2h/Enhancements/Cheats/ElegyAnywhere.cpp @@ -1,10 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gCheats.ElegyAnywhere" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterElegyAnywhere() { - REGISTER_VB_SHOULD(VB_ELEGY_CHECK_SCENE, { - if (CVarGetInteger("gCheats.ElegyAnywhere", 0)) { - *should = true; - } - }); + COND_VB_SHOULD(VB_ELEGY_CHECK_SCENE, CVAR, { *should = true; }); } + +static RegisterShipInitFunc initFunc(RegisterElegyAnywhere, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cheats/HookshotAnywhere.cpp b/mm/2s2h/Enhancements/Cheats/HookshotAnywhere.cpp index 103670cf03..970541370d 100644 --- a/mm/2s2h/Enhancements/Cheats/HookshotAnywhere.cpp +++ b/mm/2s2h/Enhancements/Cheats/HookshotAnywhere.cpp @@ -1,10 +1,12 @@ #include -#include "GameInteractor/GameInteractor.h" +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gCheats.HookshotAnywhere" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterHookshotAnywhere() { - REGISTER_VB_SHOULD(VB_BE_HOOKSHOT_SURFACE, { - if (CVarGetInteger("gCheats.HookshotAnywhere", 0)) { - *should = true; - } - }); + COND_VB_SHOULD(VB_BE_HOOKSHOT_SURFACE, CVAR, { *should = true; }); } + +static RegisterShipInitFunc initFunc(RegisterHookshotAnywhere, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cheats/Infinite.cpp b/mm/2s2h/Enhancements/Cheats/Infinite.cpp index 92a75fda2a..004bd5a747 100644 --- a/mm/2s2h/Enhancements/Cheats/Infinite.cpp +++ b/mm/2s2h/Enhancements/Cheats/Infinite.cpp @@ -1,30 +1,42 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" -#include "variables.h" +#include "2s2h/ShipInit.hpp" -void RegisterInfiniteCheats() { - GameInteractor::Instance->RegisterGameHook([]() { - if (gPlayState == nullptr) - return; +extern "C" { +#include "variables.h" +} - if (CVarGetInteger("gCheats.InfiniteHealth", 0)) { +static RegisterShipInitFunc healthInitFunc( + []() { + COND_HOOK(OnGameStateUpdate, CVarGetInteger("gCheats.InfiniteHealth", 0), []() { gSaveContext.save.saveInfo.playerData.health = gSaveContext.save.saveInfo.playerData.healthCapacity; - } + }); + }, + { "gCheats.InfiniteHealth" }); - if (CVarGetInteger("gCheats.InfiniteMagic", 0)) { +static RegisterShipInitFunc magicInitFunc( + []() { + COND_HOOK(OnGameStateUpdate, CVarGetInteger("gCheats.InfiniteMagic", 0), []() { uint8_t magicLevel = gSaveContext.save.saveInfo.playerData.magicLevel; if (magicLevel == 1) { gSaveContext.save.saveInfo.playerData.magic = MAGIC_NORMAL_METER; } else if (magicLevel == 2) { gSaveContext.save.saveInfo.playerData.magic = MAGIC_DOUBLE_METER; } - } + }); + }, + { "gCheats.InfiniteMagic" }); - if (CVarGetInteger("gCheats.InfiniteRupees", 0)) { - gSaveContext.save.saveInfo.playerData.rupees = CUR_CAPACITY(UPG_WALLET); - } +static RegisterShipInitFunc rupeesInitFunc( + []() { + COND_HOOK(OnGameStateUpdate, CVarGetInteger("gCheats.InfiniteRupees", 0), + []() { gSaveContext.save.saveInfo.playerData.rupees = CUR_CAPACITY(UPG_WALLET); }); + }, + { "gCheats.InfiniteRupees" }); - if (CVarGetInteger("gCheats.InfiniteConsumables", 0)) { +static RegisterShipInitFunc consumeablesInitFunc( + []() { + COND_HOOK(OnGameStateUpdate, CVarGetInteger("gCheats.InfiniteConsumables", 0), []() { if (INV_CONTENT(ITEM_BOW) == ITEM_BOW) { AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); } @@ -52,6 +64,6 @@ void RegisterInfiniteCheats() { if (INV_CONTENT(ITEM_POWDER_KEG) == ITEM_POWDER_KEG) { AMMO(ITEM_POWDER_KEG) = 1; } - } - }); -} + }); + }, + { "gCheats.InfiniteConsumables" }); diff --git a/mm/2s2h/Enhancements/Cheats/LongerFlowerGlide.cpp b/mm/2s2h/Enhancements/Cheats/LongerFlowerGlide.cpp index 4012e9a5a0..29d7943340 100644 --- a/mm/2s2h/Enhancements/Cheats/LongerFlowerGlide.cpp +++ b/mm/2s2h/Enhancements/Cheats/LongerFlowerGlide.cpp @@ -1,12 +1,16 @@ #include +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h"; +#include "variables.h"; extern f32 D_8085D958[2]; } +#define CVAR_NAME "gCheats.LongerFlowerGlide" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterLongerFlowerGlide() { - if (CVarGetInteger("gCheats.LongerFlowerGlide", 0)) { + if (CVAR) { D_8085D958[0] = 99999.9f; D_8085D958[1] = 99999.9f; } else { @@ -14,3 +18,5 @@ void RegisterLongerFlowerGlide() { D_8085D958[1] = 960.0f; } } + +static RegisterShipInitFunc initFunc(RegisterLongerFlowerGlide, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cheats/MoonJump.cpp b/mm/2s2h/Enhancements/Cheats/MoonJump.cpp index a41edc9b12..d8c98bcf4b 100644 --- a/mm/2s2h/Enhancements/Cheats/MoonJump.cpp +++ b/mm/2s2h/Enhancements/Cheats/MoonJump.cpp @@ -1,26 +1,22 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" -#include "variables.h" +#include "2s2h/ShipInit.hpp" -static HOOK_ID moonJumpOnLGameStateUpdateHookId = 0; -void RegisterMoonJumpOnL() { - if (moonJumpOnLGameStateUpdateHookId) { - GameInteractor::Instance->UnregisterGameHook( - moonJumpOnLGameStateUpdateHookId); - moonJumpOnLGameStateUpdateHookId = 0; - } +extern "C" { +#include "variables.h" +} - if (CVarGetInteger("gCheats.MoonJumpOnL", 0)) { - moonJumpOnLGameStateUpdateHookId = - GameInteractor::Instance->RegisterGameHook([]() { - if (gPlayState == nullptr) - return; +#define CVAR_NAME "gCheats.MoonJumpOnL" +#define CVAR CVarGetInteger(CVAR_NAME, 0) - Player* player = GET_PLAYER(gPlayState); +void RegisterMoonJump() { + COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR, [](Actor* actor) { + Player* player = GET_PLAYER(gPlayState); - if (player != nullptr && CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) { - player->actor.velocity.y = 6.34375f; - } - }); - } + if (player != nullptr && CHECK_BTN_ANY(gPlayState->state.input[0].cur.button, BTN_L)) { + player->actor.velocity.y = 6.34375f; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterMoonJump, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cheats/TimeStop.cpp b/mm/2s2h/Enhancements/Cheats/TimeStop.cpp index bae6edf375..df4c840007 100644 --- a/mm/2s2h/Enhancements/Cheats/TimeStop.cpp +++ b/mm/2s2h/Enhancements/Cheats/TimeStop.cpp @@ -1,15 +1,17 @@ -#include -#include "BenPort.h" +#include #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/Enhancements/Enhancements.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include -#include +#include "variables.h" } +#define CVAR_NAME "gCheats.TempleTimeStop" +#define CVAR CVarGetInteger(CVAR_NAME, TIME_STOP_OFF) + void RegisterTimeStopInTemples() { - GameInteractor::Instance->RegisterGameHook([](s16 sceneId, s8 roomNum) { + COND_HOOK(AfterRoomSceneCommands, CVAR != TIME_STOP_OFF, [](s16 sceneId, s8 roomNum) { uint8_t selectedOption = CVarGetInteger("gCheats.TempleTimeStop", TIME_STOP_OFF); switch (selectedOption) { @@ -63,3 +65,5 @@ void RegisterTimeStopInTemples() { } }); } + +static RegisterShipInitFunc initFunc(RegisterTimeStopInTemples, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cheats/UnbreakableRazorSword.cpp b/mm/2s2h/Enhancements/Cheats/UnbreakableRazorSword.cpp index da03acf239..6aa6b02ab9 100644 --- a/mm/2s2h/Enhancements/Cheats/UnbreakableRazorSword.cpp +++ b/mm/2s2h/Enhancements/Cheats/UnbreakableRazorSword.cpp @@ -1,10 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gCheats.UnbreakableRazorSword" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterUnbreakableRazorSword() { - REGISTER_VB_SHOULD(VB_LOWER_RAZOR_SWORD_DURABILITY, { - if (CVarGetInteger("gCheats.UnbreakableRazorSword", 0)) { - *should = false; - } - }); + COND_VB_SHOULD(VB_LOWER_RAZOR_SWORD_DURABILITY, CVAR, { *should = false; }); } + +static RegisterShipInitFunc initFunc(RegisterUnbreakableRazorSword, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Cheats/UnrestrictedItems.cpp b/mm/2s2h/Enhancements/Cheats/UnrestrictedItems.cpp index 385102a487..448d279823 100644 --- a/mm/2s2h/Enhancements/Cheats/UnrestrictedItems.cpp +++ b/mm/2s2h/Enhancements/Cheats/UnrestrictedItems.cpp @@ -1,10 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gCheats.UnrestrictedItems" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterUnrestrictedItems() { - REGISTER_VB_SHOULD(VB_ITEM_BE_RESTRICTED, { - if (CVarGetInteger("gCheats.UnrestrictedItems", 0)) { - *should = false; - } - }); + COND_VB_SHOULD(VB_ITEM_BE_RESTRICTED, CVAR, { *should = false; }); } + +static RegisterShipInitFunc initFunc(RegisterUnrestrictedItems, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Dialogue/Dialogue.h b/mm/2s2h/Enhancements/Dialogue/Dialogue.h deleted file mode 100644 index 980e7d5233..0000000000 --- a/mm/2s2h/Enhancements/Dialogue/Dialogue.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DIALOGUES_H -#define DIALOGUES_H - -void RegisterFastBankSelection(); - -#endif // DIALOGUES_H \ No newline at end of file diff --git a/mm/2s2h/Enhancements/Dialogue/FastBankSelection.cpp b/mm/2s2h/Enhancements/Dialogue/FastBankSelection.cpp index 879fafc754..92b261110a 100644 --- a/mm/2s2h/Enhancements/Dialogue/FastBankSelection.cpp +++ b/mm/2s2h/Enhancements/Dialogue/FastBankSelection.cpp @@ -1,13 +1,15 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h" -#include "global.h" - +#include "variables.h" #include "overlays/actors/ovl_En_Ginko_Man/z_en_ginko_man.h" } +#define CVAR_NAME "gEnhancements.Dialogue.FastBankSelection" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + static const char zeroRupees[3] = { '0', '0', '0' }; void FastBankSelection_UpdateMessage(const char rupeeValue[3]) { @@ -19,71 +21,53 @@ void FastBankSelection_UpdateMessage(const char rupeeValue[3]) { Audio_PlaySfx(NA_SE_SY_RUPY_COUNT); } -void RegisterFastBankSelection() { - GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_GINKO_MAN, [](Actor* outerActor) { - static HOOK_ID enGinkoUpdateHook = 0; - static HOOK_ID enGinkoKillHook = 0; - GameInteractor::Instance->UnregisterGameHookForPtr(enGinkoUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enGinkoKillHook); - enGinkoUpdateHook = 0; - enGinkoKillHook = 0; +void OnEnGinkoManUpdate(Actor* actor) { + EnGinkoMan* enGinko = (EnGinkoMan*)actor; + if (gPlayState->msgCtx.currentTextId == 0x450) { + if (CHECK_BTN_ALL(gPlayState->state.input[0].cur.button, BTN_Z) && + gPlayState->msgCtx.bankRupeesSelected != gSaveContext.save.saveInfo.playerData.rupees) { + char firstChar = (gSaveContext.save.saveInfo.playerData.rupees / 100) + '0'; + char secondChar = ((gSaveContext.save.saveInfo.playerData.rupees / 10) % 10) + '0'; + char thirdChar = (gSaveContext.save.saveInfo.playerData.rupees % 10) + '0'; + const char rupeeChar[3] = { firstChar, secondChar, thirdChar }; - enGinkoUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr( - (uintptr_t)outerActor, [](Actor* actor) { - EnGinkoMan* enGinko = (EnGinkoMan*)actor; - if (CVarGetInteger("gEnhancements.Dialogue.FastBankSelection", 0)) { - if (gPlayState->msgCtx.currentTextId == 0x450) { - if (CHECK_BTN_ALL(gPlayState->state.input[0].cur.button, BTN_Z) && - gPlayState->msgCtx.bankRupeesSelected != gSaveContext.save.saveInfo.playerData.rupees) { - char firstChar = (gSaveContext.save.saveInfo.playerData.rupees / 100) + '0'; - char secondChar = ((gSaveContext.save.saveInfo.playerData.rupees / 10) % 10) + '0'; - char thirdChar = (gSaveContext.save.saveInfo.playerData.rupees % 10) + '0'; - const char rupeeChar[3] = { firstChar, secondChar, thirdChar }; + FastBankSelection_UpdateMessage(rupeeChar); + } + } else if (gPlayState->msgCtx.currentTextId == 0x46E) { + uint32_t walletSize = CUR_UPG_VALUE(UPG_WALLET); + uint32_t currentRupees = gSaveContext.save.saveInfo.playerData.rupees; + uint32_t maxWallet; + if (CHECK_BTN_ALL(gPlayState->state.input[0].cur.button, BTN_Z)) { + switch (ITEM_WALLET_DEFAULT + walletSize) { + case ITEM_WALLET_ADULT: + maxWallet = (200 - currentRupees); + break; + case ITEM_WALLET_GIANT: + maxWallet = (500 - currentRupees); + break; + default: + maxWallet = (99 - currentRupees); + break; + } + if (maxWallet != 0 && gPlayState->msgCtx.bankRupeesSelected != maxWallet) { + char firstChar = (maxWallet / 100) + '0'; + char secondChar = ((maxWallet / 10) % 10) + '0'; + char thirdChar = (maxWallet % 10) + '0'; + const char rupeeChar[3] = { firstChar, secondChar, thirdChar }; - FastBankSelection_UpdateMessage(rupeeChar); - } - } else if (gPlayState->msgCtx.currentTextId == 0x46E) { - uint32_t walletSize = CUR_UPG_VALUE(UPG_WALLET); - uint32_t currentRupees = gSaveContext.save.saveInfo.playerData.rupees; - uint32_t maxWallet; - if (CHECK_BTN_ALL(gPlayState->state.input[0].cur.button, BTN_Z)) { - switch (ITEM_WALLET_DEFAULT + walletSize) { - case ITEM_WALLET_ADULT: - maxWallet = (200 - currentRupees); - break; - case ITEM_WALLET_GIANT: - maxWallet = (500 - currentRupees); - break; - default: - maxWallet = (99 - currentRupees); - break; - } - if (maxWallet != 0 && gPlayState->msgCtx.bankRupeesSelected != maxWallet) { - char firstChar = (maxWallet / 100) + '0'; - char secondChar = ((maxWallet / 10) % 10) + '0'; - char thirdChar = (maxWallet % 10) + '0'; - const char rupeeChar[3] = { firstChar, secondChar, thirdChar }; + FastBankSelection_UpdateMessage(rupeeChar); + } + } + } + if (gPlayState->msgCtx.currentTextId == 0x450 || gPlayState->msgCtx.currentTextId == 0x46E) { + if (CHECK_BTN_ALL(gPlayState->state.input[0].cur.button, BTN_R) && gPlayState->msgCtx.bankRupeesSelected != 0) { + FastBankSelection_UpdateMessage(zeroRupees); + } + } +} - FastBankSelection_UpdateMessage(rupeeChar); - } - } - } - if (gPlayState->msgCtx.currentTextId == 0x450 || gPlayState->msgCtx.currentTextId == 0x46E) { - if (CHECK_BTN_ALL(gPlayState->state.input[0].cur.button, BTN_R) && - gPlayState->msgCtx.bankRupeesSelected != 0) { +void RegisterFastBankSelection() { + COND_ID_HOOK(OnActorUpdate, ACTOR_EN_GINKO_MAN, CVAR, OnEnGinkoManUpdate); +} - FastBankSelection_UpdateMessage(zeroRupees); - } - } - } - }); - enGinkoKillHook = - GameInteractor::Instance->RegisterGameHook([](s8 sceneId, s8 spawnNum) { - GameInteractor::Instance->UnregisterGameHook(enGinkoUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enGinkoKillHook); - enGinkoUpdateHook = 0; - enGinkoKillHook = 0; - }); - }); -} \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterFastBankSelection, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/DifficultyOptions/DekuGuardSearchBalls.cpp b/mm/2s2h/Enhancements/DifficultyOptions/DekuGuardSearchBalls.cpp index 20b34326dc..4465b22863 100644 --- a/mm/2s2h/Enhancements/DifficultyOptions/DekuGuardSearchBalls.cpp +++ b/mm/2s2h/Enhancements/DifficultyOptions/DekuGuardSearchBalls.cpp @@ -1,16 +1,14 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" #include "Enhancements/Enhancements.h" +#include "2s2h/ShipInit.hpp" -extern "C" { -#include "variables.h" -} +#define CVAR_NAME "gEnhancements.Cheats.DekuGuardSearchBalls" +#define CVAR CVarGetInteger(CVAR_NAME, DEKU_GUARD_SEARCH_BALLS_NIGHT_ONLY) void RegisterShowDekuGuardSearchBalls() { - REGISTER_VB_SHOULD(VB_DEKU_GUARD_SHOW_SEARCH_BALLS, { - uint8_t selectedOption = - CVarGetInteger("gEnhancements.Cheats.DekuGuardSearchBalls", DEKU_GUARD_SEARCH_BALLS_NIGHT_ONLY); - switch (selectedOption) { + COND_VB_SHOULD(VB_DEKU_GUARD_SHOW_SEARCH_BALLS, CVAR != DEKU_GUARD_SEARCH_BALLS_NIGHT_ONLY, { + switch (CVAR) { case DEKU_GUARD_SEARCH_BALLS_NEVER: *should = false; break; @@ -20,3 +18,5 @@ void RegisterShowDekuGuardSearchBalls() { } }); } + +static RegisterShipInitFunc initFunc(RegisterShowDekuGuardSearchBalls, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/DifficultyOptions/DifficultyOptions.h b/mm/2s2h/Enhancements/DifficultyOptions/DifficultyOptions.h deleted file mode 100644 index 8706cd177b..0000000000 --- a/mm/2s2h/Enhancements/DifficultyOptions/DifficultyOptions.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef DIFFICULTY_OPTIONS_H -#define DIFFICULTY_OPTIONS_H - -void RegisterDisableTakkuriSteal(); -void RegisterShowDekuGuardSearchBalls(); - -#endif // DIFFICULTY_OPTIONS_H \ No newline at end of file diff --git a/mm/2s2h/Enhancements/DifficultyOptions/DisableTakkuriSteal.cpp b/mm/2s2h/Enhancements/DifficultyOptions/DisableTakkuriSteal.cpp index 214c38202a..063efff620 100644 --- a/mm/2s2h/Enhancements/DifficultyOptions/DisableTakkuriSteal.cpp +++ b/mm/2s2h/Enhancements/DifficultyOptions/DisableTakkuriSteal.cpp @@ -1,14 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" -void RegisterDisableTakkuriSteal() { - static HOOK_ID thiefBirdStealHookID = 0; - GameInteractor::Instance->UnregisterGameHookForID(thiefBirdStealHookID); - thiefBirdStealHookID = 0; +#define CVAR_NAME "gEnhancements.Cheats.DisableTakkuriSteal" +#define CVAR CVarGetInteger(CVAR_NAME, 0) - if (!CVarGetInteger("gEnhancements.Cheats.DisableTakkuriSteal", 0)) { - return; - } +void RegisterDisableTakkuriSteal() { + COND_VB_SHOULD(VB_THIEF_BIRD_STEAL, CVAR, { *should = false; }); +} - thiefBirdStealHookID = REGISTER_VB_SHOULD(VB_THIEF_BIRD_STEAL, { *should = false; }); -} \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterDisableTakkuriSteal, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Enhancements.cpp b/mm/2s2h/Enhancements/Enhancements.cpp index 10390c43a0..cb8b81f33c 100644 --- a/mm/2s2h/Enhancements/Enhancements.cpp +++ b/mm/2s2h/Enhancements/Enhancements.cpp @@ -6,69 +6,12 @@ void InitEnhancements() { RegisterCameraFreeLook(); RegisterDebugCam(); - // Cheats - RegisterInfiniteCheats(); - RegisterLongerFlowerGlide(); - RegisterMoonJumpOnL(); - RegisterUnbreakableRazorSword(); - RegisterUnrestrictedItems(); - RegisterTimeStopInTemples(); - RegisterElegyAnywhere(); - RegisterHookshotAnywhere(); - - // Clock - RegisterTextBasedClock(); - Register3DSClock(); - // Cycle & Saving RegisterEndOfCycleSaveHooks(); RegisterSavingEnhancements(); RegisterAutosave(); RegisterKeepExpressMail(); - // Dialogue - RegisterFastBankSelection(); - - // Equipment - RegisterSkipMagicArrowEquip(); - RegisterInstantRecall(); - - // Fixes - RegisterFierceDeityZTargetMovement(); - RegisterTwoHandedSwordSpinAttack(); - RegisterCompletedHeartContainerAudio(); - - // Graphics - RegisterDisableBlackBars(); - RegisterHyruleWarriorsStyledLink(); - Register3DItemDrops(); - - // Masks - RegisterFastTransformation(); - RegisterFierceDeityAnywhere(); - RegisterBlastMaskKeg(); - RegisterNoBlastMaskCooldown(); - RegisterPersistentMasks(); - - // Minigames - RegisterAlwaysWinDoggyRace(); - RegisterCremiaHugs(); - RegisterCuccoShackCuccoCount(); - RegisterSwordsmanSchool(); - - // Player - RegisterClimbSpeed(); - RegisterFastFlowerLaunch(); - RegisterInstantPutaway(); - RegisterFierceDeityPutaway(); - - // Songs - RegisterEnableSunsSong(); - RegisterFasterSongPlayback(); - RegisterPauseOwlWarp(); - RegisterZoraEggCount(); - RegisterSkipScarecrowSong(); - // Restorations RegisterPowerCrouchStab(); RegisterSideRoll(); @@ -78,12 +21,4 @@ void InitEnhancements() { // Cutscenes RegisterCutscenes(); - - // Modes - RegisterPlayAsKafei(); - RegisterTimeMovesWhenYouMove(); - - // Difficulty Options - RegisterDisableTakkuriSteal(); - RegisterShowDekuGuardSearchBalls(); } diff --git a/mm/2s2h/Enhancements/Enhancements.h b/mm/2s2h/Enhancements/Enhancements.h index a2064dfc06..4f34e4491a 100644 --- a/mm/2s2h/Enhancements/Enhancements.h +++ b/mm/2s2h/Enhancements/Enhancements.h @@ -2,21 +2,10 @@ #define ENHANCEMENTS_H #include "Camera/Camera.h" -#include "Cheats/Cheats.h" #include "Cutscenes/Cutscenes.h" #include "Cycle/Cycle.h" -#include "Dialogue/Dialogue.h" -#include "Equipment/Equipment.h" -#include "Fixes/Fixes.h" -#include "Graphics/Graphics.h" -#include "Masks/Masks.h" -#include "Minigames/Minigames.h" -#include "Modes/Modes.h" -#include "Player/Player.h" #include "Restorations/Restorations.h" #include "Saving/SavingEnhancements.h" -#include "Songs/Songs.h" -#include "DifficultyOptions/DifficultyOptions.h" enum AlwaysWinDoggyRaceOptions { ALWAYS_WIN_DOGGY_RACE_OFF, @@ -48,14 +37,7 @@ enum DekuGuardSearchBallsOptions { DEKU_GUARD_SEARCH_BALLS_ALWAYS, }; -#ifdef __cplusplus -extern "C" { -#endif - +// Old Entry Point void InitEnhancements(); -#ifdef __cplusplus -} -#endif - #endif // ENHANCEMENTS_H diff --git a/mm/2s2h/Enhancements/Equipment/Equipment.h b/mm/2s2h/Enhancements/Equipment/Equipment.h deleted file mode 100644 index 849c102570..0000000000 --- a/mm/2s2h/Enhancements/Equipment/Equipment.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef EQUIPMENT_H -#define EQUIPMENT_H - -void RegisterInstantRecall(); -void RegisterSkipMagicArrowEquip(); -void RegisterTwoHandedSwordSpinAttack(); - -#endif // EQUIPMENT_H diff --git a/mm/2s2h/Enhancements/Equipment/InstantRecall.cpp b/mm/2s2h/Enhancements/Equipment/InstantRecall.cpp index 5ed46406c9..6ffabd1b24 100644 --- a/mm/2s2h/Enhancements/Equipment/InstantRecall.cpp +++ b/mm/2s2h/Enhancements/Equipment/InstantRecall.cpp @@ -1,12 +1,14 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { +#include "variables.h" #include "src/overlays/actors/ovl_En_Boom/z_en_boom.h" -extern PlayState* gPlayState; } -static HOOK_ID onActorUpdateHookId = 0; +#define CVAR_NAME "gEnhancements.PlayerActions.InstantRecall" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void Player_ReturnBoomerangs() { Player* player = GET_PLAYER(gPlayState); @@ -27,15 +29,11 @@ void Player_ReturnBoomerangs() { } void RegisterInstantRecall() { - GameInteractor::Instance->UnregisterGameHookForID(onActorUpdateHookId); - onActorUpdateHookId = 0; - - onActorUpdateHookId = GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_BOOM, [](Actor* outerActor) { - if (CVarGetInteger("gEnhancements.PlayerActions.InstantRecall", 0)) { - if (CHECK_BTN_ALL(gPlayState->state.input->press.button, BTN_B)) { - Player_ReturnBoomerangs(); - } - } - }); + COND_ID_HOOK(OnActorUpdate, ACTOR_EN_BOOM, CVAR, [](Actor* actor) { + if (CHECK_BTN_ALL(gPlayState->state.input->press.button, BTN_B)) { + Player_ReturnBoomerangs(); + } + }); } + +static RegisterShipInitFunc initFunc(RegisterInstantRecall, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Equipment/SkipMagicArrowEquip.cpp b/mm/2s2h/Enhancements/Equipment/SkipMagicArrowEquip.cpp index e5e68cfc26..887e171bfd 100644 --- a/mm/2s2h/Enhancements/Equipment/SkipMagicArrowEquip.cpp +++ b/mm/2s2h/Enhancements/Equipment/SkipMagicArrowEquip.cpp @@ -1,21 +1,24 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h" #include "src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" extern s16 sEquipState; extern s16 sEquipAnimTimer; } +#define CVAR_NAME "gEnhancements.Equipment.MagicArrowEquipSpeed" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterSkipMagicArrowEquip() { - GameInteractor::Instance->RegisterGameHook([](PauseContext* pauseCtx) { - if (CVarGetInteger("gEnhancements.Equipment.MagicArrowEquipSpeed", 0)) { - if (sEquipState == EQUIP_STATE_MAGIC_ARROW_GROW_ORB) { - sEquipState = EQUIP_STATE_MAGIC_ARROW_MOVE_TO_BOW_SLOT; - sEquipAnimTimer = 2; - pauseCtx->equipAnimAlpha = 255; - } + COND_HOOK(OnKaleidoUpdate, CVAR, [](PauseContext* pauseCtx) { + if (sEquipState == EQUIP_STATE_MAGIC_ARROW_GROW_ORB) { + sEquipState = EQUIP_STATE_MAGIC_ARROW_MOVE_TO_BOW_SLOT; + sEquipAnimTimer = 2; + pauseCtx->equipAnimAlpha = 255; } }); } + +static RegisterShipInitFunc initFunc(RegisterSkipMagicArrowEquip, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Equipment/TwoHandedSwordSpinAttack.cpp b/mm/2s2h/Enhancements/Equipment/TwoHandedSwordSpinAttack.cpp index 53b4df2a1f..671a75f316 100644 --- a/mm/2s2h/Enhancements/Equipment/TwoHandedSwordSpinAttack.cpp +++ b/mm/2s2h/Enhancements/Equipment/TwoHandedSwordSpinAttack.cpp @@ -1,57 +1,56 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" -#include "overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h" +#include "2s2h/ShipInit.hpp" extern "C" { -extern PlayState* gPlayState; +#include "variables.h" +#include "overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h" extern Input* sPlayerControlInput; } -void RegisterTwoHandedSwordSpinAttack() { +#define CVAR_NAME "gEnhancements.Equipment.TwoHandedSwordSpinAttack" +#define CVAR CVarGetInteger(CVAR_NAME, 0) - REGISTER_VB_SHOULD(VB_CHECK_HELD_ITEM_BUTTON_PRESS, { - if (CVarGetInteger("gEnhancements.Equipment.TwoHandedSwordSpinAttack", 0)) { - // Instead of checking B only, check whichever button is assigned to the currently held item. This allows - // the Great Fairy Sword, a C button item, to be held for charged spin attacks. - Player* player = GET_PLAYER(gPlayState); - u16* sDpadItemButtons = va_arg(args, u16*); - u16* sPlayerItemButtons = va_arg(args, u16*); +void RegisterTwoHandedSwordSpinAttack() { + COND_VB_SHOULD(VB_CHECK_HELD_ITEM_BUTTON_PRESS, CVAR, { + // Instead of checking B only, check whichever button is assigned to the currently held item. This allows + // the Great Fairy Sword, a C button item, to be held for charged spin attacks. + Player* player = GET_PLAYER(gPlayState); + u16* sDpadItemButtons = va_arg(args, u16*); + u16* sPlayerItemButtons = va_arg(args, u16*); - if (player->heldItemButton < 0) { - *should = false; + if (player->heldItemButton < 0) { + *should = false; + } else { + uint16_t buttonToCheck; + if (IS_HELD_DPAD(player->heldItemButton)) { + buttonToCheck = sDpadItemButtons[HELD_ITEM_TO_DPAD(player->heldItemButton)]; } else { - uint16_t buttonToCheck; - if (IS_HELD_DPAD(player->heldItemButton)) { - buttonToCheck = sDpadItemButtons[HELD_ITEM_TO_DPAD(player->heldItemButton)]; - } else { - buttonToCheck = sPlayerItemButtons[player->heldItemButton]; - } - *should = CHECK_BTN_ALL(sPlayerControlInput->cur.button, buttonToCheck); + buttonToCheck = sPlayerItemButtons[player->heldItemButton]; } + *should = CHECK_BTN_ALL(sPlayerControlInput->cur.button, buttonToCheck); } }); - REGISTER_VB_SHOULD(VB_MAGIC_SPIN_ATTACK_CHECK_FORM, { - if (CVarGetInteger("gEnhancements.Equipment.TwoHandedSwordSpinAttack", 0)) { - // Additionally allow the Fierce Deity form to use charged spin attacks - Player* player = GET_PLAYER(gPlayState); - if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { - *should = true; - } + COND_VB_SHOULD(VB_MAGIC_SPIN_ATTACK_CHECK_FORM, CVAR, { + // Additionally allow the Fierce Deity form to use charged spin attacks + Player* player = GET_PLAYER(gPlayState); + if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + *should = true; } }); - REGISTER_VB_SHOULD(VB_TRANSFORM_THUNDER_MATRIX, { - if (CVarGetInteger("gEnhancements.Equipment.TwoHandedSwordSpinAttack", 0)) { - EnMThunder* enMThunder = va_arg(args, EnMThunder*); - // Define new thunder matrix transformation for two-handed sword magic. Applies to both the GFS and the - // Fierce Deity sword. - if (enMThunder->type == ENMTHUNDER_TYPE_GREAT_FAIRYS_SWORD) { - Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY); - Matrix_Scale(-1.7f, -1.0f, -0.6f, MTXMODE_APPLY); - Matrix_RotateXS(0x4000, MTXMODE_APPLY); - *should = false; - } + COND_VB_SHOULD(VB_TRANSFORM_THUNDER_MATRIX, CVAR, { + EnMThunder* enMThunder = va_arg(args, EnMThunder*); + // Define new thunder matrix transformation for two-handed sword magic. Applies to both the GFS and the + // Fierce Deity sword. + if (enMThunder->type == ENMTHUNDER_TYPE_GREAT_FAIRYS_SWORD) { + Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(-1.7f, -1.0f, -0.6f, MTXMODE_APPLY); + Matrix_RotateXS(0x4000, MTXMODE_APPLY); + *should = false; } }); } + +static RegisterShipInitFunc initFunc(RegisterTwoHandedSwordSpinAttack, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Fixes/CompletedHeartContainerAudio.cpp b/mm/2s2h/Enhancements/Fixes/CompletedHeartContainerAudio.cpp index cd90b31a69..57967a43d0 100644 --- a/mm/2s2h/Enhancements/Fixes/CompletedHeartContainerAudio.cpp +++ b/mm/2s2h/Enhancements/Fixes/CompletedHeartContainerAudio.cpp @@ -1,16 +1,21 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "variables.h" } +#define CVAR_NAME "gEnhancements.Fixes.CompletedHeartContainerAudio" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterCompletedHeartContainerAudio() { - REGISTER_VB_SHOULD(VB_PLAY_HEART_CONTAINER_GET_FANFARE, { + COND_VB_SHOULD(VB_PLAY_HEART_CONTAINER_GET_FANFARE, CVAR, { GetItemId getItemId = (GetItemId)va_arg(args, int); - if (CVarGetInteger("gEnhancements.Fixes.CompletedHeartContainerAudio", 0) && getItemId == GI_HEART_PIECE && - GET_QUEST_HEART_PIECE_COUNT == 0) { + if (getItemId == GI_HEART_PIECE && GET_QUEST_HEART_PIECE_COUNT == 0) { *should = true; } }); } + +static RegisterShipInitFunc initFunc(RegisterCompletedHeartContainerAudio, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Fixes/FierceDeityZTargetMovement.cpp b/mm/2s2h/Enhancements/Fixes/FierceDeityZTargetMovement.cpp index e359d76a56..b0f4721e64 100644 --- a/mm/2s2h/Enhancements/Fixes/FierceDeityZTargetMovement.cpp +++ b/mm/2s2h/Enhancements/Fixes/FierceDeityZTargetMovement.cpp @@ -1,21 +1,26 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "variables.h" } +#define CVAR_NAME "gEnhancements.Fixes.FierceDeityZTargetMovement" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterFierceDeityZTargetMovement() { - REGISTER_VB_SHOULD(VB_ZTARGET_SPEED_CHECK, { + COND_VB_SHOULD(VB_ZTARGET_SPEED_CHECK, CVAR, { Player* player = GET_PLAYER(gPlayState); float* speedArg = va_arg(args, float*); // If the player is Fierce Deity and targeting, - if (player->lockOnActor != NULL && player->transformation == PLAYER_FORM_FIERCE_DEITY && - CVarGetInteger("gEnhancements.Fixes.FierceDeityZTargetMovement", 0)) { + if (player->lockOnActor != NULL && player->transformation == PLAYER_FORM_FIERCE_DEITY) { // 6.0f is the maximum speed of Zora/Goron/Deku link, whereas FD can be up to 10 // Clamping to 6.0 keeps z target movement similar to other transformations *speedArg = CLAMP_MAX(*speedArg, 6.0f); } }); } + +static RegisterShipInitFunc initFunc(RegisterFierceDeityZTargetMovement, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Fixes/Fixes.h b/mm/2s2h/Enhancements/Fixes/Fixes.h deleted file mode 100644 index 1360723727..0000000000 --- a/mm/2s2h/Enhancements/Fixes/Fixes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef ENHANCEMENTS_FIXES_H -#define ENHANCEMENTS_FIXES_H - -void RegisterCompletedHeartContainerAudio(); -void RegisterFierceDeityZTargetMovement(); - -#endif // ENHANCEMENTS_FIXES_H diff --git a/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp b/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp index e5b4de1024..78ddbdf2b8 100644 --- a/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp +++ b/mm/2s2h/Enhancements/Graphics/3DItemDrops.cpp @@ -1,14 +1,16 @@ -#include "libultraship/libultraship.h" +#include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h" -#include "functions.h" +#include "variables.h" #include "overlays/actors/ovl_En_Slime/z_en_slime.h" -extern PlayState* gPlayState; void EnItem00_Draw(Actor* thisx, PlayState* play); } +#define CVAR_NAME "gEnhancements.Graphics.3DItemDrops" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + bool ItemShouldSpinWhen3D(Actor* actor) { EnItem00* enItem00 = (EnItem00*)actor; @@ -135,16 +137,6 @@ void DrawSlime3DItem(Actor* actor, bool* should) { } void Register3DItemDrops() { - static HOOK_ID actorInitHookID = 0; - static HOOK_ID actorUpdateHookID = 0; - static HOOK_ID slimeVBHookID = 0; - GameInteractor::Instance->UnregisterGameHookForID(actorInitHookID); - GameInteractor::Instance->UnregisterGameHookForID(actorUpdateHookID); - GameInteractor::Instance->UnregisterGameHookForID(slimeVBHookID); - actorInitHookID = 0; - actorUpdateHookID = 0; - slimeVBHookID = 0; - if (gPlayState != NULL) { Actor* actor = gPlayState->actorCtx.actorLists[ACTORCAT_MISC].first; @@ -166,21 +158,19 @@ void Register3DItemDrops() { } } - if (!CVarGetInteger("gEnhancements.Graphics.3DItemDrops", 0)) { - return; - } + COND_ID_HOOK(OnActorInit, ACTOR_EN_ITEM00, CVAR, [](Actor* actor) { actor->draw = EnItem00_3DItemsDraw; }); - actorInitHookID = GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_ITEM00, [](Actor* actor) { actor->draw = EnItem00_3DItemsDraw; }); - actorUpdateHookID = GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_ITEM00, [](Actor* actor) { - // Add spin to normally bill-boarded items - if (ItemShouldSpinWhen3D(actor)) { - actor->shape.rot.y += 0x3C0; - } - }); - slimeVBHookID = REGISTER_VB_SHOULD(VB_DRAW_SLIME_BODY_ITEM, { + COND_ID_HOOK(OnActorUpdate, ACTOR_EN_ITEM00, CVAR, [](Actor* actor) { + // Add spin to normally bill-boarded items + if (ItemShouldSpinWhen3D(actor)) { + actor->shape.rot.y += 0x3C0; + } + }); + + COND_VB_SHOULD(VB_DRAW_SLIME_BODY_ITEM, CVAR, { Actor* actor = va_arg(args, Actor*); DrawSlime3DItem(actor, should); }); } + +static RegisterShipInitFunc initFunc(Register3DItemDrops, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Graphics/3DSClock.cpp b/mm/2s2h/Enhancements/Graphics/3DSClock.cpp index ba5abb48e2..bcb11f75cb 100644 --- a/mm/2s2h/Enhancements/Graphics/3DSClock.cpp +++ b/mm/2s2h/Enhancements/Graphics/3DSClock.cpp @@ -1,18 +1,15 @@ -#include +#include #include "2s2h/BenGui/HudEditor.h" #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/Enhancements/Enhancements.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" -#include "misc/title_static/title_static.h" #include "2s2h_assets.h" extern "C" { -#include -#include +#include "variables.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" #include "interface/parameter_static/parameter_static.h" - -extern PlayState* gPlayState; +#include "misc/title_static/title_static.h" Gfx* Gfx_DrawTexRectIA8(Gfx* gfx, TexturePtr texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop, s16 rectWidth, s16 rectHeight, u16 dsdx, u16 dtdy); @@ -25,6 +22,9 @@ Gfx* Gfx_DrawTexRectIA8_DropShadowOffset(Gfx* gfx, TexturePtr texture, s16 textu s16 r, s16 g, s16 b, s16 a, s32 masks, s32 rects); } +#define CVAR_NAME "gEnhancements.Graphics.ClockType" +#define CVAR CVarGetInteger(CVAR_NAME, CLOCK_TYPE_ORIGINAL) + #define SECONDS_IN_THREE_DAYS (3 * 24 * 60 * 60) #define SECONDS_IN_SIX_HOURS (6 * 60 * 60) #define CLOCK_SECTION_HALFWIDTH 24 @@ -48,304 +48,297 @@ static TexturePtr sFinalHoursDigitTextures[] = { s16 finalHoursClockSlots[8]; -void Register3DSClock() { +void Draw3DSClock() { + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + if (HudEditor_IsActiveElementHidden()) { + return; + } + + static s32 sPreviousTimeCheck = -1; + + if ((R_TIME_SPEED != 0) && + ((gPlayState->msgCtx.msgMode == MSGMODE_NONE) || + ((gPlayState->actorCtx.flags & ACTORCTX_FLAG_1) && !Play_InCsMode(gPlayState)) || + (gPlayState->msgCtx.msgMode == MSGMODE_NONE) || + ((gPlayState->msgCtx.currentTextId >= 0x100) && (gPlayState->msgCtx.currentTextId <= 0x200)) || + (gSaveContext.gameMode == GAMEMODE_END_CREDITS)) && + !FrameAdvance_IsEnabled(&gPlayState->state) && !Environment_IsTimeStopped() && (gSaveContext.save.day <= 3)) { - REGISTER_VB_SHOULD(VB_PREVENT_CLOCK_DISPLAY, { - if (CVarGetInteger("gEnhancements.Graphics.ClockType", CLOCK_TYPE_ORIGINAL) == CLOCK_TYPE_3DS) { - *should = true; + if ((gPlayState->pauseCtx.state == PAUSE_STATE_OFF) && + (gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE)) { + + static s16 sThreeDayClockAlpha = 255; + + static s32 sFinalHoursIntro = 0; + + sThreeDayClockAlpha = gPlayState->interfaceCtx.aAlpha; + + OPEN_DISPS(gPlayState->state.gfxCtx); + s16 posX = 160; + s16 posY = 210; + + // Draw background of 3DS clock + // TODO: Replace this with matrix/vertex handling to avoid gaps when scaled + OVERLAY_DISP = Gfx_DrawTexRectIA8_DropShadow( + OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSEdgeTex, CLOCK_SECTION_HALFWIDTH * 3, 12, + posX - (CLOCK_SECTION_HALFWIDTH * 4), posY, CLOCK_SECTION_HALFWIDTH * 3, 12, 1 << 10, 1 << 10, 255, 255, + 255, sThreeDayClockAlpha); + + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = + Gfx_DrawTexRectIA8_DropShadow(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSMiddleTex, CLOCK_SECTION_WIDTH, + 12, posX - CLOCK_SECTION_HALFWIDTH, posY, CLOCK_SECTION_WIDTH, 12, + 1 << 10, 1 << 10, 255, 255, 255, sThreeDayClockAlpha); HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - if (HudEditor_IsActiveElementHidden()) { - return; + OVERLAY_DISP = Gfx_DrawTexRectIA8_DropShadowOffset( + OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSEdgeTex, CLOCK_SECTION_HALFWIDTH * 3, 12, + posX + CLOCK_SECTION_HALFWIDTH, posY, CLOCK_SECTION_HALFWIDTH * 3, 12, 1 << 10, 1 << 10, 255, 255, 255, + sThreeDayClockAlpha, 3, (CLOCK_SECTION_HALFWIDTH * 3) << 5); + + // Coloured day markers, which highlights the current day with its own colour + u16 fillalpha = 64; + if (gSaveContext.save.day <= 1) { + fillalpha = 255; } + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 128, 255, (fillalpha * sThreeDayClockAlpha) / 255); - static s32 sPreviousTimeCheck = -1; + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFillTex, CLOCK_SECTION_WIDTH, + 12, posX - CLOCK_SECTION_HALFWIDTH - CLOCK_SECTION_WIDTH, posY, + CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10); - if ((R_TIME_SPEED != 0) && - ((gPlayState->msgCtx.msgMode == MSGMODE_NONE) || - ((gPlayState->actorCtx.flags & ACTORCTX_FLAG_1) && !Play_InCsMode(gPlayState)) || - (gPlayState->msgCtx.msgMode == MSGMODE_NONE) || - ((gPlayState->msgCtx.currentTextId >= 0x100) && (gPlayState->msgCtx.currentTextId <= 0x200)) || - (gSaveContext.gameMode == GAMEMODE_END_CREDITS)) && - !FrameAdvance_IsEnabled(&gPlayState->state) && !Environment_IsTimeStopped() && - (gSaveContext.save.day <= 3)) { + fillalpha = 64; + if (gSaveContext.save.day == 2) { + fillalpha = 255; + } + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 192, 0, (fillalpha * sThreeDayClockAlpha) / 255); - if ((gPlayState->pauseCtx.state == PAUSE_STATE_OFF) && - (gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE)) { + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = + Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFillTex, CLOCK_SECTION_WIDTH, 12, + posX - CLOCK_SECTION_HALFWIDTH, posY, CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10); - static s16 sThreeDayClockAlpha = 255; + fillalpha = 64; + if (gSaveContext.save.day >= 3) { + fillalpha = 255; + } + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 64, 0, (fillalpha * sThreeDayClockAlpha) / 255); - static s32 sFinalHoursIntro = 0; + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = + Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFillTex, CLOCK_SECTION_WIDTH, 12, + posX + CLOCK_SECTION_HALFWIDTH, posY, CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10); - sThreeDayClockAlpha = gPlayState->interfaceCtx.aAlpha; + // This next part is for the little arrow that shows what the current time is - OPEN_DISPS(gPlayState->state.gfxCtx); - s16 posX = 160; - s16 posY = 210; + s32 timeUntilCrash = (s32)TIME_TO_SECONDS_F(TIME_UNTIL_MOON_CRASH); - // Draw background of 3DS clock - // TODO: Replace this with matrix/vertex handling to avoid gaps when scaled - OVERLAY_DISP = Gfx_DrawTexRectIA8_DropShadow( - OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSEdgeTex, CLOCK_SECTION_HALFWIDTH * 3, 12, - posX - (CLOCK_SECTION_HALFWIDTH * 4), posY, CLOCK_SECTION_HALFWIDTH * 3, 12, 1 << 10, 1 << 10, - 255, 255, 255, sThreeDayClockAlpha); + // This is a safety measure to delay skipping the arrow marker back a day on the frame before the + // day changes by just checking if time went backwards + if (sPreviousTimeCheck != -1 && sPreviousTimeCheck > SECONDS_IN_THREE_DAYS - timeUntilCrash) { + s32 trueTimeUntilCrash = timeUntilCrash; + timeUntilCrash = SECONDS_IN_THREE_DAYS - sPreviousTimeCheck; + sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - trueTimeUntilCrash; + } else { + sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - timeUntilCrash; + } - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8_DropShadow( - OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSMiddleTex, CLOCK_SECTION_WIDTH, 12, - posX - CLOCK_SECTION_HALFWIDTH, posY, CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10, 255, 255, 255, - sThreeDayClockAlpha); + // Compute the position of the arrow, and then draw it + s32 timeoffset = std::max( + std::min(3 * CLOCK_SECTION_WIDTH - (timeUntilCrash * 3 * CLOCK_SECTION_WIDTH) / SECONDS_IN_THREE_DAYS, + 3 * CLOCK_SECTION_WIDTH), + 0); - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8_DropShadowOffset( - OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSEdgeTex, CLOCK_SECTION_HALFWIDTH * 3, 12, - posX + CLOCK_SECTION_HALFWIDTH, posY, CLOCK_SECTION_HALFWIDTH * 3, 12, 1 << 10, 1 << 10, 255, - 255, 255, sThreeDayClockAlpha, 3, (CLOCK_SECTION_HALFWIDTH * 3) << 5); - - // Coloured day markers, which highlights the current day with its own colour - u16 fillalpha = 64; - if (gSaveContext.save.day <= 1) { - fillalpha = 255; - } - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 128, 255, (fillalpha * sThreeDayClockAlpha) / 255); + u16 counterX = posX - (CLOCK_SECTION_HALFWIDTH * 3) + timeoffset; + u16 counterY = posY - 4; - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = - Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFillTex, CLOCK_SECTION_WIDTH, 12, - posX - CLOCK_SECTION_HALFWIDTH - CLOCK_SECTION_WIDTH, posY, - CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10); - - fillalpha = 64; - if (gSaveContext.save.day == 2) { - fillalpha = 255; - } - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 192, 0, (fillalpha * sThreeDayClockAlpha) / 255); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 0, 0, sThreeDayClockAlpha); - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFillTex, - CLOCK_SECTION_WIDTH, 12, posX - CLOCK_SECTION_HALFWIDTH, posY, - CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10); + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSArrowTex, 8, 8, counterX - 4, + posY + 4, 8, 8, 1 << 10, 1 << 10); + + u16 curMinutes = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) % 60; + u16 curHours = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) / 60; + + // Final hours timer + if ((CURRENT_DAY >= 4) || + ((CURRENT_DAY == 3) && (((void)0, gSaveContext.save.time) >= (CLOCK_TIME(0, 0) + 5)) && + (((void)0, gSaveContext.save.time) < CLOCK_TIME(6, 0)))) { + + // This all just gets the time to display in each number slot + s32 timeInSeconds = timeUntilCrash % 60; + s32 timeInMinutes = (timeUntilCrash / 60) % 60; + s32 timeInHours = (timeUntilCrash / 60) / 60; + + finalHoursClockSlots[0] = std::min(timeInHours / 10, 9); + finalHoursClockSlots[1] = timeInHours % 10; + finalHoursClockSlots[2] = 10; + finalHoursClockSlots[3] = timeInMinutes / 10; + finalHoursClockSlots[4] = timeInMinutes % 10; + finalHoursClockSlots[5] = 10; + + finalHoursClockSlots[6] = timeInSeconds / 10; + finalHoursClockSlots[7] = timeInSeconds % 10; + + u16 finalTimerSpacing = 8; + + u16 finalTimerPos = posX - finalTimerSpacing * 4 - finalTimerSpacing / 2; + s16 i; + + s32 percentToCrash = std::min(std::max((timeUntilCrash * 255) / SECONDS_IN_SIX_HOURS, 0), 255); + + // This is a lerp between yellow and red based on the remaining time + u16 finalHoursR1 = 255; + u16 finalHoursR2 = 255; + u16 finalHoursG1 = 0; + u16 finalHoursG2 = 255; + u16 finalHoursB1 = 0; + u16 finalHoursB2 = 0; + + u16 finalHoursR = (((255 - percentToCrash) * finalHoursR1) + (percentToCrash * finalHoursR2)) / 255; + u16 finalHoursG = (((255 - percentToCrash) * finalHoursG1) + (percentToCrash * finalHoursG2)) / 255; + u16 finalHoursB = (((255 - percentToCrash) * finalHoursB1) + (percentToCrash * finalHoursB2)) / 255; + + // Controls the distance and speed modifier of the final hours clock intro animation + // finalHoursOffset controls the distance offset for the intro animation + // finalHoursModifier controls the speed of the intro animation - larger is slower + s32 finalHoursOffset = 10; + s32 finalHoursModifier = 2; + if (sFinalHoursIntro < finalHoursOffset * finalHoursModifier) { + sFinalHoursIntro++; + } - fillalpha = 64; - if (gSaveContext.save.day >= 3) { - fillalpha = 255; - } - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 64, 0, (fillalpha * sThreeDayClockAlpha) / 255); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, finalHoursR, finalHoursG, finalHoursB, + (sThreeDayClockAlpha * sFinalHoursIntro) / (finalHoursOffset * finalHoursModifier)); + // This just loops through and draws all the numbers + for (i = 0; i < 8; i++) { HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFillTex, - CLOCK_SECTION_WIDTH, 12, posX + CLOCK_SECTION_HALFWIDTH, posY, - CLOCK_SECTION_WIDTH, 12, 1 << 10, 1 << 10); + OVERLAY_DISP = Gfx_DrawTexRectIA8( + OVERLAY_DISP, sFinalHoursDigitTextures[finalHoursClockSlots[i]], 16, 16, finalTimerPos, + posY - 14 - finalHoursOffset + (sFinalHoursIntro / finalHoursModifier), 16, 16, 1 << 10, + 1 << 10); + finalTimerPos += finalTimerSpacing; + } + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectIA8( + OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFinalHoursMoonTex, 16, 16, posX - 8, + posY - 28 - finalHoursOffset + (sFinalHoursIntro / finalHoursModifier), 16, 16, 1 << 10, 1 << 10); + } else { - // This next part is for the little arrow that shows what the current time is + sFinalHoursIntro = 0; - s32 timeUntilCrash = (s32)TIME_TO_SECONDS_F(TIME_UNTIL_MOON_CRASH); + // Draw the current time in a small box + // TODO: Add scale slider to allow this box to be scaled independently of the main UI element - // This is a safety measure to delay skipping the arrow marker back a day on the frame before the - // day changes by just checking if time went backwards - if (sPreviousTimeCheck != -1 && sPreviousTimeCheck > SECONDS_IN_THREE_DAYS - timeUntilCrash) { - s32 trueTimeUntilCrash = timeUntilCrash; - timeUntilCrash = SECONDS_IN_THREE_DAYS - sPreviousTimeCheck; - sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - trueTimeUntilCrash; + // Draw the background box + if (gSaveContext.save.timeSpeedOffset == -2) { + u16 pulseTime = ((s32)TIME_TO_SECONDS_F(gSaveContext.save.time) % 120); + u16 pulse; + if (pulseTime < 60) { + pulse = (pulseTime * 255) / 60; } else { - sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - timeUntilCrash; + pulse = 255 - ((pulseTime - 60) * 255) / 60; + } + + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, pulse, pulse, 0, sThreeDayClockAlpha / 2); + } else { + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 0, 0, sThreeDayClockAlpha / 2); + } + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSTimeBackdropTex, + CLOCK_SECTION_WIDTH, 16, counterX - CLOCK_SECTION_HALFWIDTH, + counterY - 4, CLOCK_SECTION_WIDTH, 16, 1 << 10, 1 << 10); + + counterX -= 8; + + // Draw the sun/moon next to the current time + TexturePtr daynightmarker; + if (curHours < 6 || curHours >= 18) { + daynightmarker = (TexturePtr)gThreeDayClockMoonHourTex; + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 200, 0, sThreeDayClockAlpha); + } else { + daynightmarker = (TexturePtr)gThreeDayClockSunHourTex; + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 64, 0, sThreeDayClockAlpha); + } + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, daynightmarker, 24, 24, counterX - 11, counterY - 2, 12, + 12, 1 << 11, 1 << 11); + if (!CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { + curHours %= 12; + if (curHours == 0) { + curHours = 12; } + } - // Compute the position of the arrow, and then draw it - s32 timeoffset = - std::max(std::min(3 * CLOCK_SECTION_WIDTH - - (timeUntilCrash * 3 * CLOCK_SECTION_WIDTH) / SECONDS_IN_THREE_DAYS, - 3 * CLOCK_SECTION_WIDTH), - 0); + u16 curTensHours = curHours / 10; + curHours %= 10; - u16 counterX = posX - (CLOCK_SECTION_HALFWIDTH * 3) + timeoffset; - u16 counterY = posY - 4; + u16 curTensMinutes = curMinutes / 10; + curMinutes %= 10; - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 0, 0, sThreeDayClockAlpha); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, sThreeDayClockAlpha); + // Inverted time + if (gSaveContext.save.timeSpeedOffset == -2) { HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSArrowTex, 8, 8, - counterX - 4, posY + 4, 8, 8, 1 << 10, 1 << 10); - - u16 curMinutes = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) % 60; - u16 curHours = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) / 60; - - // Final hours timer - if ((CURRENT_DAY >= 4) || - ((CURRENT_DAY == 3) && (((void)0, gSaveContext.save.time) >= (CLOCK_TIME(0, 0) + 5)) && - (((void)0, gSaveContext.save.time) < CLOCK_TIME(6, 0)))) { - - // This all just gets the time to display in each number slot - s32 timeInSeconds = timeUntilCrash % 60; - s32 timeInMinutes = (timeUntilCrash / 60) % 60; - s32 timeInHours = (timeUntilCrash / 60) / 60; - - finalHoursClockSlots[0] = std::min(timeInHours / 10, 9); - finalHoursClockSlots[1] = timeInHours % 10; - finalHoursClockSlots[2] = 10; - finalHoursClockSlots[3] = timeInMinutes / 10; - finalHoursClockSlots[4] = timeInMinutes % 10; - finalHoursClockSlots[5] = 10; - - finalHoursClockSlots[6] = timeInSeconds / 10; - finalHoursClockSlots[7] = timeInSeconds % 10; - - u16 finalTimerSpacing = 8; - - u16 finalTimerPos = posX - finalTimerSpacing * 4 - finalTimerSpacing / 2; - s16 i; - - s32 percentToCrash = std::min(std::max((timeUntilCrash * 255) / SECONDS_IN_SIX_HOURS, 0), 255); - - // This is a lerp between yellow and red based on the remaining time - u16 finalHoursR1 = 255; - u16 finalHoursR2 = 255; - u16 finalHoursG1 = 0; - u16 finalHoursG2 = 255; - u16 finalHoursB1 = 0; - u16 finalHoursB2 = 0; - - u16 finalHoursR = - (((255 - percentToCrash) * finalHoursR1) + (percentToCrash * finalHoursR2)) / 255; - u16 finalHoursG = - (((255 - percentToCrash) * finalHoursG1) + (percentToCrash * finalHoursG2)) / 255; - u16 finalHoursB = - (((255 - percentToCrash) * finalHoursB1) + (percentToCrash * finalHoursB2)) / 255; - - // Controls the distance and speed modifier of the final hours clock intro animation - // finalHoursOffset controls the distance offset for the intro animation - // finalHoursModifier controls the speed of the intro animation - larger is slower - s32 finalHoursOffset = 10; - s32 finalHoursModifier = 2; - if (sFinalHoursIntro < finalHoursOffset * finalHoursModifier) { - sFinalHoursIntro++; - } - - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, finalHoursR, finalHoursG, finalHoursB, - (sThreeDayClockAlpha * sFinalHoursIntro) / - (finalHoursOffset * finalHoursModifier)); - // This just loops through and draws all the numbers - for (i = 0; i < 8; i++) { - - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8( - OVERLAY_DISP, sFinalHoursDigitTextures[finalHoursClockSlots[i]], 16, 16, finalTimerPos, - posY - 14 - finalHoursOffset + (sFinalHoursIntro / finalHoursModifier), 16, 16, 1 << 10, - 1 << 10); - finalTimerPos += finalTimerSpacing; - } - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8( - OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSFinalHoursMoonTex, 16, 16, posX - 8, - posY - 28 - finalHoursOffset + (sFinalHoursIntro / finalHoursModifier), 16, 16, 1 << 10, - 1 << 10); - } else { + OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSSlowTimeTex, 16, 16, + counterX + 8 + 20, counterY - 4, 16, 16, 1 << 10, 1 << 10); - sFinalHoursIntro = 0; - - // Draw the current time in a small box - // TODO: Add scale slider to allow this box to be scaled independently of the main UI element - - // Draw the background box - if (gSaveContext.save.timeSpeedOffset == -2) { - u16 pulseTime = ((s32)TIME_TO_SECONDS_F(gSaveContext.save.time) % 120); - u16 pulse; - if (pulseTime < 60) { - pulse = (pulseTime * 255) / 60; - } else { - pulse = 255 - ((pulseTime - 60) * 255) / 60; - } - - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, pulse, pulse, 0, sThreeDayClockAlpha / 2); - } else { - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 0, 0, sThreeDayClockAlpha / 2); - } - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSTimeBackdropTex, - CLOCK_SECTION_WIDTH, 16, counterX - CLOCK_SECTION_HALFWIDTH, - counterY - 4, CLOCK_SECTION_WIDTH, 16, 1 << 10, 1 << 10); - - counterX -= 8; - - // Draw the sun/moon next to the current time - TexturePtr daynightmarker; - if (curHours < 6 || curHours >= 18) { - daynightmarker = (TexturePtr)gThreeDayClockMoonHourTex; - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 200, 0, sThreeDayClockAlpha); - } else { - daynightmarker = (TexturePtr)gThreeDayClockSunHourTex; - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 64, 0, sThreeDayClockAlpha); - } - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, daynightmarker, 24, 24, counterX - 11, - counterY - 2, 12, 12, 1 << 11, 1 << 11); - if (!CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { - curHours %= 12; - if (curHours == 0) { - curHours = 12; - } - } - - u16 curTensHours = curHours / 10; - curHours %= 10; - - u16 curTensMinutes = curMinutes / 10; - curMinutes %= 10; - - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, sThreeDayClockAlpha); - - // Inverted time - if (gSaveContext.save.timeSpeedOffset == -2) { - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = - Gfx_DrawTexRectIA8(OVERLAY_DISP, (TexturePtr)gThreeDayClock3DSSlowTimeTex, 16, 16, - counterX + 8 + 20, counterY - 4, 16, 16, 1 << 10, 1 << 10); - - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 64, 192, 255, sThreeDayClockAlpha); - } - - // Digital time - u16 timerSpacing = 6; - - if (curTensHours > 0 || CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { - timerSpacing = 4; - - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curTensHours], 8, 8, counterX, - counterY, 8, 8, 1 << 10, 1 << 10); - counterX += timerSpacing; - } - - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curHours], 8, 8, counterX, - counterY, 8, 8, 1 << 10, 1 << 10); - counterX += timerSpacing; - - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[10], 8, 8, counterX, counterY, 8, - 8, 1 << 10, 1 << 10); - counterX += timerSpacing; - - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curTensMinutes], 8, 8, counterX, - counterY, 8, 8, 1 << 10, 1 << 10); - counterX += timerSpacing; - - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curMinutes], 8, 8, counterX, - counterY, 8, 8, 1 << 10, 1 << 10); - } - gDPPipeSync(OVERLAY_DISP++); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 64, 192, 255, sThreeDayClockAlpha); + } - CLOSE_DISPS(gPlayState->state.gfxCtx); - } else { - sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - (s32)TIME_TO_SECONDS_F(TIME_UNTIL_MOON_CRASH); + // Digital time + u16 timerSpacing = 6; + + if (curTensHours > 0 || CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { + timerSpacing = 4; + + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curTensHours], 8, 8, counterX, + counterY, 8, 8, 1 << 10, 1 << 10); + counterX += timerSpacing; } - } else { - sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - (s32)TIME_TO_SECONDS_F(TIME_UNTIL_MOON_CRASH); + + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curHours], 8, 8, counterX, counterY, 8, 8, + 1 << 10, 1 << 10); + counterX += timerSpacing; + + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[10], 8, 8, counterX, counterY, 8, 8, + 1 << 10, 1 << 10); + counterX += timerSpacing; + + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curTensMinutes], 8, 8, counterX, counterY, + 8, 8, 1 << 10, 1 << 10); + counterX += timerSpacing; + + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + OVERLAY_DISP = Gfx_DrawTexRectI8(OVERLAY_DISP, sDigitTextures[curMinutes], 8, 8, counterX, counterY, 8, + 8, 1 << 10, 1 << 10); } + gDPPipeSync(OVERLAY_DISP++); - hudEditorActiveElement = HUD_EDITOR_ELEMENT_NONE; + CLOSE_DISPS(gPlayState->state.gfxCtx); + } else { + sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - (s32)TIME_TO_SECONDS_F(TIME_UNTIL_MOON_CRASH); } + } else { + sPreviousTimeCheck = SECONDS_IN_THREE_DAYS - (s32)TIME_TO_SECONDS_F(TIME_UNTIL_MOON_CRASH); + } + + hudEditorActiveElement = HUD_EDITOR_ELEMENT_NONE; +} + +void Register3DSClock() { + COND_VB_SHOULD(VB_PREVENT_CLOCK_DISPLAY, CVAR == CLOCK_TYPE_3DS, { + *should = true; + Draw3DSClock(); }); } + +static RegisterShipInitFunc initFunc(Register3DSClock, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Graphics/DisableBlackBars.cpp b/mm/2s2h/Enhancements/Graphics/DisableBlackBars.cpp index 67eb5cf7ae..2904dcd60e 100644 --- a/mm/2s2h/Enhancements/Graphics/DisableBlackBars.cpp +++ b/mm/2s2h/Enhancements/Graphics/DisableBlackBars.cpp @@ -1,10 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gEnhancements.Graphics.DisableBlackBars" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterDisableBlackBars() { - REGISTER_VB_SHOULD(VB_DISABLE_LETTERBOX, { - if (CVarGetInteger("gEnhancements.Graphics.DisableBlackBars", 0)) { - *should = true; - } - }); + COND_VB_SHOULD(VB_DISABLE_LETTERBOX, CVAR, { *should = true; }); } + +static RegisterShipInitFunc initFunc(RegisterDisableBlackBars, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Graphics/Graphics.h b/mm/2s2h/Enhancements/Graphics/Graphics.h index 04871e33a2..d7e69b1fcb 100644 --- a/mm/2s2h/Enhancements/Graphics/Graphics.h +++ b/mm/2s2h/Enhancements/Graphics/Graphics.h @@ -1,13 +1,7 @@ #ifndef GRAPHICS_H #define GRAPHICS_H -void Register3DItemDrops(); -void Register3DSClock(); -void RegisterDisableBlackBars(); void MotionBlur_RenderMenuOptions(); -void RegisterPlayAsKafei(); -void RegisterTextBasedClock(); -void RegisterHyruleWarriorsStyledLink(); #ifdef __cplusplus #include diff --git a/mm/2s2h/Enhancements/Graphics/HyruleWarriorsStyledLink.cpp b/mm/2s2h/Enhancements/Graphics/HyruleWarriorsStyledLink.cpp deleted file mode 100644 index 275c827889..0000000000 --- a/mm/2s2h/Enhancements/Graphics/HyruleWarriorsStyledLink.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "libultraship/libultraship.h" -#include "2s2h/GameInteractor/GameInteractor.h" -#include "Enhancements/FrameInterpolation/FrameInterpolation.h" - -extern "C" { -#include "z64.h" -#include "z64player.h" -#include "functions.h" -#include "macros.h" -#include "src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" - -extern PlayState* gPlayState; -extern const char* D_801C0B20[28]; -extern SaveContext gSaveContext; -#include "objects/object_link_child/object_link_child.h" -void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); -void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); -} - -void UpdateHyruleWarriorsStyledLink() { - GameInteractor::Instance->RegisterGameHookForID( - PLAYER_LIMB_HEAD, [](Player* player, s32 limbIndex) { - if (CVarGetInteger("gModes.HyruleWarriorsStyledLink", 0) && player->currentMask == PLAYER_MASK_NONE && - player->transformation == PLAYER_FORM_HUMAN && INV_CONTENT(ITEM_MASK_KEATON) == ITEM_MASK_KEATON) { - OPEN_DISPS(gPlayState->state.gfxCtx); - Matrix_Push(); - Matrix_RotateYS(0x38e3, MTXMODE_APPLY); - Matrix_RotateZS(-0x12F6, MTXMODE_APPLY); - Matrix_Translate(300.0f, -250.0f, 77.7f, MTXMODE_APPLY); - Matrix_Scale(0.648f, 0.648f, 0.648f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gPlayState->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)D_801C0B20[PLAYER_MASK_KEATON - 1]); - Matrix_Pop(); - CLOSE_DISPS(gPlayState->state.gfxCtx); - } - }); - GameInteractor::Instance->RegisterGameHookForID( - PLAYER_LIMB_WAIST, [](Player* player, s32 limbIndex) { - if (CVarGetInteger("gModes.HyruleWarriorsStyledLink", 0) && player->transformation == PLAYER_FORM_HUMAN && - player->itemAction != PLAYER_IA_MASK_FIERCE_DEITY && - INV_CONTENT(ITEM_MASK_FIERCE_DEITY) == ITEM_MASK_FIERCE_DEITY) { - OPEN_DISPS(gPlayState->state.gfxCtx); - Matrix_Push(); - Matrix_RotateXS(-0x61A8, MTXMODE_APPLY); - Matrix_RotateYS(-0x7D0, MTXMODE_APPLY); - Matrix_RotateZS(-0x3A98, MTXMODE_APPLY); - Matrix_Translate(-85.0f, 658.0f, -165.0f, MTXMODE_APPLY); - Matrix_Scale(0.635f, 0.635f, 0.635f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gPlayState->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)D_801C0B20[PLAYER_MASK_FIERCE_DEITY - 1]); - Matrix_Pop(); - CLOSE_DISPS(gPlayState->state.gfxCtx); - } - }); -} - -void RegisterHyruleWarriorsStyledLink() { - UpdateHyruleWarriorsStyledLink(); - - GameInteractor::Instance->RegisterGameHook( - [](s8 sceneId, s8 spawnNum) { UpdateHyruleWarriorsStyledLink(); }); -} \ No newline at end of file diff --git a/mm/2s2h/Enhancements/Graphics/MotionBlur.cpp b/mm/2s2h/Enhancements/Graphics/MotionBlur.cpp index 0c4dc1c0a7..8ccdf516d5 100644 --- a/mm/2s2h/Enhancements/Graphics/MotionBlur.cpp +++ b/mm/2s2h/Enhancements/Graphics/MotionBlur.cpp @@ -1,9 +1,8 @@ #include - #include "2s2h/BenGui/UIWidgets.hpp" extern "C" { -#include "z64.h" +#include "variables.h" } const char* motionBlurOptions[] = { "Dynamic (default)", "Always Off", "Always On" }; diff --git a/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp b/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp index 517d2b7f2d..fba535c019 100644 --- a/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp +++ b/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp @@ -1,108 +1,110 @@ -#include +#include #include "2s2h/BenGui/HudEditor.h" #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/Enhancements/Enhancements.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" extern "C" { -#include -#include +#include "variables.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" - -extern PlayState* gPlayState; } -void RegisterTextBasedClock() { - REGISTER_VB_SHOULD(VB_PREVENT_CLOCK_DISPLAY, { - if (CVarGetInteger("gEnhancements.Graphics.ClockType", CLOCK_TYPE_ORIGINAL) == CLOCK_TYPE_TEXT_BASED) { - *should = true; +#define CVAR_NAME "gEnhancements.Graphics.ClockType" +#define CVAR CVarGetInteger(CVAR_NAME, CLOCK_TYPE_ORIGINAL) - HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); - if (HudEditor_IsActiveElementHidden()) { - return; - } +void DrawTextBasedClock() { + HudEditor_SetActiveElement(HUD_EDITOR_ELEMENT_CLOCK); + if (HudEditor_IsActiveElementHidden()) { + return; + } - if ((R_TIME_SPEED != 0) && - ((gPlayState->msgCtx.msgMode == MSGMODE_NONE) || - ((gPlayState->actorCtx.flags & ACTORCTX_FLAG_1) && !Play_InCsMode(gPlayState)) || - (gPlayState->msgCtx.msgMode == MSGMODE_NONE) || - ((gPlayState->msgCtx.currentTextId >= 0x100) && (gPlayState->msgCtx.currentTextId <= 0x200)) || - (gSaveContext.gameMode == GAMEMODE_END_CREDITS)) && - !FrameAdvance_IsEnabled(&gPlayState->state) && !Environment_IsTimeStopped() && - (gSaveContext.save.day <= 3)) { + if ((R_TIME_SPEED != 0) && + ((gPlayState->msgCtx.msgMode == MSGMODE_NONE) || + ((gPlayState->actorCtx.flags & ACTORCTX_FLAG_1) && !Play_InCsMode(gPlayState)) || + (gPlayState->msgCtx.msgMode == MSGMODE_NONE) || + ((gPlayState->msgCtx.currentTextId >= 0x100) && (gPlayState->msgCtx.currentTextId <= 0x200)) || + (gSaveContext.gameMode == GAMEMODE_END_CREDITS)) && + !FrameAdvance_IsEnabled(&gPlayState->state) && !Environment_IsTimeStopped() && (gSaveContext.save.day <= 3)) { - OPEN_DISPS(gPlayState->state.gfxCtx); + OPEN_DISPS(gPlayState->state.gfxCtx); - if ((gPlayState->pauseCtx.state == PAUSE_STATE_OFF) && - (gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE)) { - Gfx_SetupDL39_Overlay(gPlayState->state.gfxCtx); + if ((gPlayState->pauseCtx.state == PAUSE_STATE_OFF) && + (gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE)) { + Gfx_SetupDL39_Overlay(gPlayState->state.gfxCtx); - u16 curMinutes = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) % 60; - u16 curHours = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) / 60; + u16 curMinutes = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) % 60; + u16 curHours = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) / 60; - u16 timeUntilMoonCrash = (s32)TIME_UNTIL_MOON_CRASH; - u16 timeInMinutes = (s32)TIME_TO_MINUTES_F(timeUntilMoonCrash) % 60; - u16 timeInHours = (s32)TIME_TO_MINUTES_F(timeUntilMoonCrash) / 60; + u16 timeUntilMoonCrash = (s32)TIME_UNTIL_MOON_CRASH; + u16 timeInMinutes = (s32)TIME_TO_MINUTES_F(timeUntilMoonCrash) % 60; + u16 timeInHours = (s32)TIME_TO_MINUTES_F(timeUntilMoonCrash) / 60; - char formattedTime[10]; - char formattedCrashTime[10]; + char formattedTime[10]; + char formattedCrashTime[10]; - OPEN_PRINTER(OVERLAY_DISP); - - // Inverted time - if (gSaveContext.save.timeSpeedOffset == -2) { - GfxPrint_SetColor(&printer, 0, 204, 255, 255); - } else { - GfxPrint_SetColor(&printer, 255, 255, 255, 255); - } + OPEN_PRINTER(OVERLAY_DISP); - // Scale starting position values by 8 for use with hud editor - s16 posX = 13 * 8; - s16 posY = 26 * 8; - - HudEditor_ModifyRectPosValues(&posX, &posY); - - // scale back down and clamp to avoid negative values - posX = std::max(posX / 8, 0); - posY = std::max(posY / 8, 0); - - if (CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { - sprintf(formattedTime, "%02d:%02d", curHours, curMinutes); - GfxPrint_SetPos(&printer, posX + 1, posY); - } else { // Format hours and minutes for 12-hour AM/PM clock - char amPm[3] = "am"; - if (curHours >= 12) { - strcpy(amPm, "pm"); - if (curHours > 12) { - curHours -= 12; - } - } - if (curHours == 0) { - curHours = 12; - } - sprintf(formattedTime, "%02d:%02d%s", curHours, curMinutes, amPm); - GfxPrint_SetPos(&printer, posX, posY); - } - - GfxPrint_Printf(&printer, "Day %d: %s", gSaveContext.save.day, formattedTime); - GfxPrint_SetPos(&printer, posX, posY + 1); + // Inverted time + if (gSaveContext.save.timeSpeedOffset == -2) { + GfxPrint_SetColor(&printer, 0, 204, 255, 255); + } else { + GfxPrint_SetColor(&printer, 255, 255, 255, 255); + } - // Crash Countdown - if ((CURRENT_DAY >= 4) || - ((CURRENT_DAY == 3) && (((void)0, gSaveContext.save.time) >= (CLOCK_TIME(0, 0) + 5)) && - (((void)0, gSaveContext.save.time) < CLOCK_TIME(6, 0)))) { - GfxPrint_SetColor(&printer, 255, 0, 0, 255); - sprintf(formattedCrashTime, "%02d:%02d", timeInHours, timeInMinutes); - GfxPrint_Printf(&printer, "Crash in %s", formattedCrashTime); + // Scale starting position values by 8 for use with hud editor + s16 posX = 13 * 8; + s16 posY = 26 * 8; + + HudEditor_ModifyRectPosValues(&posX, &posY); + + // scale back down and clamp to avoid negative values + posX = std::max(posX / 8, 0); + posY = std::max(posY / 8, 0); + + if (CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { + sprintf(formattedTime, "%02d:%02d", curHours, curMinutes); + GfxPrint_SetPos(&printer, posX + 1, posY); + } else { // Format hours and minutes for 12-hour AM/PM clock + char amPm[3] = "am"; + if (curHours >= 12) { + strcpy(amPm, "pm"); + if (curHours > 12) { + curHours -= 12; } - - CLOSE_PRINTER(printer, OVERLAY_DISP); } + if (curHours == 0) { + curHours = 12; + } + sprintf(formattedTime, "%02d:%02d%s", curHours, curMinutes, amPm); + GfxPrint_SetPos(&printer, posX, posY); + } + + GfxPrint_Printf(&printer, "Day %d: %s", gSaveContext.save.day, formattedTime); + GfxPrint_SetPos(&printer, posX, posY + 1); - CLOSE_DISPS(gPlayState->state.gfxCtx); + // Crash Countdown + if ((CURRENT_DAY >= 4) || + ((CURRENT_DAY == 3) && (((void)0, gSaveContext.save.time) >= (CLOCK_TIME(0, 0) + 5)) && + (((void)0, gSaveContext.save.time) < CLOCK_TIME(6, 0)))) { + GfxPrint_SetColor(&printer, 255, 0, 0, 255); + sprintf(formattedCrashTime, "%02d:%02d", timeInHours, timeInMinutes); + GfxPrint_Printf(&printer, "Crash in %s", formattedCrashTime); } - hudEditorActiveElement = HUD_EDITOR_ELEMENT_NONE; + CLOSE_PRINTER(printer, OVERLAY_DISP); } + + CLOSE_DISPS(gPlayState->state.gfxCtx); + } + + hudEditorActiveElement = HUD_EDITOR_ELEMENT_NONE; +} + +void RegisterTextBasedClock() { + COND_VB_SHOULD(VB_PREVENT_CLOCK_DISPLAY, CVAR == CLOCK_TYPE_TEXT_BASED, { + *should = true; + DrawTextBasedClock(); }); } + +static RegisterShipInitFunc initFunc(RegisterTextBasedClock, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Masks/BlastMaskKeg.cpp b/mm/2s2h/Enhancements/Masks/BlastMaskKeg.cpp index 74c2a03373..2c7c9f1eda 100644 --- a/mm/2s2h/Enhancements/Masks/BlastMaskKeg.cpp +++ b/mm/2s2h/Enhancements/Masks/BlastMaskKeg.cpp @@ -1,31 +1,33 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" - -static uint32_t bombType; +#include "2s2h/ShipInit.hpp" extern "C" { -#include "global.h" +#include "variables.h" #include "overlays/actors/ovl_En_Bom/z_en_bom.h" + EquipSlot func_8082FDC4(void); } +#define CVAR_NAME "gEnhancements.Masks.BlastMaskKeg" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterBlastMaskKeg() { - GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_BOM, [](Actor* actor, bool* should) { - Player* player = GET_PLAYER(gPlayState); - if (CVarGetInteger("gEnhancements.Masks.BlastMaskKeg", 0)) { - ItemId item; - EquipSlot i = func_8082FDC4(); + COND_ID_HOOK(ShouldActorInit, ACTOR_EN_BOM, CVAR, [](Actor* actor, bool* should) { + Player* player = GET_PLAYER(gPlayState); + ItemId item; + EquipSlot i = func_8082FDC4(); - i = ((i >= EQUIP_SLOT_A) && (player->transformation == PLAYER_FORM_FIERCE_DEITY) && - (player->heldItemAction != PLAYER_IA_SWORD_TWO_HANDED)) - ? EQUIP_SLOT_B - : i; + i = ((i >= EQUIP_SLOT_A) && (player->transformation == PLAYER_FORM_FIERCE_DEITY) && + (player->heldItemAction != PLAYER_IA_SWORD_TWO_HANDED)) + ? EQUIP_SLOT_B + : i; - item = Player_GetItemOnButton(gPlayState, player, i); - if (item == ITEM_F0) { - actor->shape.rot.x = BOMB_EXPLOSIVE_TYPE_POWDER_KEG; - } - } - }); + item = Player_GetItemOnButton(gPlayState, player, i); + if (item == ITEM_F0) { + actor->shape.rot.x = BOMB_EXPLOSIVE_TYPE_POWDER_KEG; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterBlastMaskKeg, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Masks/FastTransformation.cpp b/mm/2s2h/Enhancements/Masks/FastTransformation.cpp index 0e970a8415..ed4c5808d9 100644 --- a/mm/2s2h/Enhancements/Masks/FastTransformation.cpp +++ b/mm/2s2h/Enhancements/Masks/FastTransformation.cpp @@ -1,13 +1,10 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include -#include -extern PlayState* gPlayState; -extern SaveContext gSaveContext; -extern ActorOverlay gActorOverlayTable[ACTOR_ID_MAX]; -extern s16 gPlayerFormObjectIds[PLAYER_FORM_MAX]; +#include "variables.h" + void Player_PlaySfx(Player* player, u16 sfxId); void PlayerCall_Init(Actor* thisx, PlayState* play); void PlayerCall_Update(Actor* thisx, PlayState* play); @@ -15,36 +12,38 @@ void PlayerCall_Draw(Actor* thisx, PlayState* play); void TransitionFade_SetColor(void* thisx, u32 color); } +#define CVAR_NAME "gEnhancements.Masks.FastTransformation" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterFastTransformation() { - REGISTER_VB_SHOULD(VB_PREVENT_MASK_TRANSFORMATION_CS, { - if (CVarGetInteger("gEnhancements.Masks.FastTransformation", 0)) { - *should = true; - Player* player = GET_PLAYER(gPlayState); - - // This was mostly copied directly from func_8012301C within z_player_lib.c - s16 objectId = gPlayerFormObjectIds[GET_PLAYER_FORM]; - - gActorOverlayTable[ACTOR_PLAYER].initInfo->objectId = objectId; - func_8012F73C(&gPlayState->objectCtx, player->actor.objectSlot, objectId); - player->actor.objectSlot = Object_GetSlot(&gPlayState->objectCtx, GAMEPLAY_KEEP); - - s32 objectSlot = - Object_GetSlot(&gPlayState->objectCtx, gActorOverlayTable[ACTOR_PLAYER].initInfo->objectId); - player->actor.objectSlot = objectSlot; - player->actor.shape.rot.z = GET_PLAYER_FORM + 1; - player->actor.init = PlayerCall_Init; - player->actor.update = PlayerCall_Update; - player->actor.draw = PlayerCall_Draw; - gSaveContext.save.equippedMask = PLAYER_MASK_NONE; - - TransitionFade_SetColor(&gPlayState->unk_18E48, 0x000000); - R_TRANS_FADE_FLASH_ALPHA_STEP = -1; - Player_PlaySfx(GET_PLAYER(gPlayState), NA_SE_SY_TRANSFORM_MASK_FLASH); - - // Clear previous mask to prevent crashing with masks being drawn while we switch transformations - if (player->transformation == PLAYER_FORM_HUMAN) { - player->prevMask = PLAYER_MASK_NONE; - } + COND_VB_SHOULD(VB_PREVENT_MASK_TRANSFORMATION_CS, CVAR, { + *should = true; + Player* player = GET_PLAYER(gPlayState); + + // This was mostly copied directly from func_8012301C within z_player_lib.c + s16 objectId = gPlayerFormObjectIds[GET_PLAYER_FORM]; + + gActorOverlayTable[ACTOR_PLAYER].initInfo->objectId = objectId; + func_8012F73C(&gPlayState->objectCtx, player->actor.objectSlot, objectId); + player->actor.objectSlot = Object_GetSlot(&gPlayState->objectCtx, GAMEPLAY_KEEP); + + s32 objectSlot = Object_GetSlot(&gPlayState->objectCtx, gActorOverlayTable[ACTOR_PLAYER].initInfo->objectId); + player->actor.objectSlot = objectSlot; + player->actor.shape.rot.z = GET_PLAYER_FORM + 1; + player->actor.init = PlayerCall_Init; + player->actor.update = PlayerCall_Update; + player->actor.draw = PlayerCall_Draw; + gSaveContext.save.equippedMask = PLAYER_MASK_NONE; + + TransitionFade_SetColor(&gPlayState->unk_18E48, 0x000000); + R_TRANS_FADE_FLASH_ALPHA_STEP = -1; + Player_PlaySfx(GET_PLAYER(gPlayState), NA_SE_SY_TRANSFORM_MASK_FLASH); + + // Clear previous mask to prevent crashing with masks being drawn while we switch transformations + if (player->transformation == PLAYER_FORM_HUMAN) { + player->prevMask = PLAYER_MASK_NONE; } }); } + +static RegisterShipInitFunc initFunc(RegisterFastTransformation, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp b/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp index 5bf0e5c280..83a79b768e 100644 --- a/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp +++ b/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp @@ -1,21 +1,24 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { #include "z64.h" #include "overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.h" #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" #include "overlays/actors/ovl_En_Firefly/z_en_firefly.h" #include "overlays/actors/ovl_En_Fz/z_en_fz.h" #include "overlays/actors/ovl_En_Neo_Reeba/z_en_neo_reeba.h" +} #define HIT_BY_SWORD_BEAM 1 #define NOT_HIT_BY_SWORD_BEAM 0 +#define CVAR_NAME "gEnhancements.Masks.FierceDeitysAnywhere" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterFierceDeityAnywhere() { - REGISTER_VB_SHOULD(VB_DISABLE_FD_MASK, { - if (CVarGetInteger("gEnhancements.Masks.FierceDeitysAnywhere", 0)) { - *should = false; - } - }); + COND_VB_SHOULD(VB_DISABLE_FD_MASK, CVAR, { *should = false; }); REGISTER_VB_SHOULD(VB_DAMAGE_MULTIPLIER, { if (CVarGetInteger("gEnhancements.Masks.FierceDeitysAnywhere", 0)) { @@ -164,3 +167,5 @@ void RegisterFierceDeityAnywhere() { } }); } + +static RegisterShipInitFunc initFunc(RegisterFierceDeityAnywhere, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Masks/Masks.h b/mm/2s2h/Enhancements/Masks/Masks.h deleted file mode 100644 index f65949ef07..0000000000 --- a/mm/2s2h/Enhancements/Masks/Masks.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef MASKS_H -#define MASKS_H - -void RegisterBlastMaskKeg(); -void RegisterFastTransformation(); -void RegisterFierceDeityAnywhere(); -void RegisterNoBlastMaskCooldown(); -void RegisterPersistentMasks(); -void UpdatePersistentMasksState(); - -#endif // MASKS_H diff --git a/mm/2s2h/Enhancements/Masks/NoBlastMaskCooldown.cpp b/mm/2s2h/Enhancements/Masks/NoBlastMaskCooldown.cpp index 45a967a486..f97fc93dd9 100644 --- a/mm/2s2h/Enhancements/Masks/NoBlastMaskCooldown.cpp +++ b/mm/2s2h/Enhancements/Masks/NoBlastMaskCooldown.cpp @@ -1,10 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gEnhancements.Masks.NoBlastMaskCooldown" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterNoBlastMaskCooldown() { - REGISTER_VB_SHOULD(VB_SET_BLAST_MASK_COOLDOWN_TIMER, { - if (CVarGetInteger("gEnhancements.Masks.NoBlastMaskCooldown", 0)) { - *should = false; - } - }); + COND_VB_SHOULD(VB_SET_BLAST_MASK_COOLDOWN_TIMER, CVAR, { *should = false; }); } + +static RegisterShipInitFunc initFunc(RegisterNoBlastMaskCooldown, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp b/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp index 5e6704475e..9661d54717 100644 --- a/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp +++ b/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp @@ -1,24 +1,23 @@ #include -#include #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h" -#include "z64player.h" -#include "functions.h" -#include "macros.h" -#include "gfx.h" +#include "variables.h" #include "src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" #include "assets/interface/parameter_static/parameter_static.h" void func_8082E1F0(Player* player, u16 sfxId); void Player_DrawBunnyHood(PlayState* play); -extern PlayState* gPlayState; extern const char* D_801C0B20[28]; -extern SaveContext gSaveContext; } +#define CVAR_NAME "gEnhancements.Masks.PersistentBunnyHood.Enabled" +#define STATE_CVAR_NAME "gEnhancements.Masks.PersistentBunnyHood.State" +#define CVAR CVarGetInteger(CVAR_NAME, 0) +#define STATE_CVAR CVarGetInteger(STATE_CVAR_NAME, 0) + void UpdatePersistentMasksState() { static Vtx* persistentMasksVtx; static HOOK_ID beforePageDrawHook = 0; @@ -26,15 +25,15 @@ void UpdatePersistentMasksState() { GameInteractor::Instance->UnregisterGameHook(beforePageDrawHook); GameInteractor::Instance->UnregisterGameHookForID(onPlayerPostLimbDrawHook); - if (!CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) { - CVarClear("gEnhancements.Masks.PersistentBunnyHood.State"); + if (!CVAR) { + CVarClear(STATE_CVAR_NAME); return; } // If the mask is equipped, unequip it if (gSaveContext.save.equippedMask == PLAYER_MASK_BUNNY) { gSaveContext.save.equippedMask = PLAYER_MASK_NONE; - CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 1); + CVarSetInteger(STATE_CVAR_NAME, 1); if (gPlayState != NULL) { Player* player = GET_PLAYER(gPlayState); @@ -45,15 +44,14 @@ void UpdatePersistentMasksState() { // If they don't have the mask, clear the state if (INV_CONTENT(ITEM_MASK_BUNNY) != ITEM_MASK_BUNNY) { - CVarClear("gEnhancements.Masks.PersistentBunnyHood.State"); + CVarClear(STATE_CVAR_NAME); } // This hook draws the mask on the players head when it's active and they aren't in first person onPlayerPostLimbDrawHook = GameInteractor::Instance->RegisterGameHookForID( PLAYER_LIMB_HEAD, [](Player* player, s32 limbIndex) { // Ensure they aren't in first person - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0) && - !(player->stateFlags1 & PLAYER_STATE1_100000)) { + if (STATE_CVAR && !(player->stateFlags1 & PLAYER_STATE1_100000)) { OPEN_DISPS(gPlayState->state.gfxCtx); Matrix_Push(); Player_DrawBunnyHood(gPlayState); @@ -118,7 +116,7 @@ void UpdatePersistentMasksState() { persistentMasksVtx[i + 0].v.cn[3] = persistentMasksVtx[i + 1].v.cn[3] = persistentMasksVtx[i + 2].v.cn[3] = persistentMasksVtx[i + 3].v.cn[3] = pauseCtx->alpha; - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + if (STATE_CVAR) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 200, 255, 255); gSPVertex(POLY_OPA_DISP++, (uintptr_t)persistentMasksVtx, 4, 0); POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, (TexturePtr)gEquippedItemOutlineTex, 32, 32, 0); @@ -133,36 +131,33 @@ void RegisterPersistentMasks() { UpdatePersistentMasksState(); // Easiest way to handle things like loading into a different file, debug warping, etc. - GameInteractor::Instance->RegisterGameHook( - [](s8 sceneId, s8 spawnNum) { UpdatePersistentMasksState(); }); + COND_HOOK(OnSceneInit, CVAR, [](s8 sceneId, s8 spawnNum) { UpdatePersistentMasksState(); }); // Speed the player up when the bunny hood state is active - REGISTER_VB_SHOULD(VB_CONSIDER_BUNNY_HOOD_EQUIPPED, { - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + COND_VB_SHOULD(VB_CONSIDER_BUNNY_HOOD_EQUIPPED, CVAR, { + if (STATE_CVAR) { *should = true; } }); // Overrides allowing them to equip a mask while transformed - REGISTER_VB_SHOULD(VB_USE_ITEM_CONSIDER_LINK_HUMAN, { + COND_VB_SHOULD(VB_USE_ITEM_CONSIDER_LINK_HUMAN, CVAR, { PlayerItemAction* itemAction = va_arg(args, PlayerItemAction*); - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0) && - *itemAction == PLAYER_IA_MASK_BUNNY) { + if (*itemAction == PLAYER_IA_MASK_BUNNY) { *should = true; } }); // When they do equip the mask, prevent it and instead set our state - REGISTER_VB_SHOULD(VB_USE_ITEM_EQUIP_MASK, { + COND_VB_SHOULD(VB_USE_ITEM_EQUIP_MASK, CVAR, { PlayerMask* maskId = va_arg(args, PlayerMask*); Player* player = GET_PLAYER(gPlayState); - if (*maskId == PLAYER_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) { + if (*maskId == PLAYER_MASK_BUNNY) { *should = false; - CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", - !CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)); - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + CVarSetInteger(STATE_CVAR_NAME, !STATE_CVAR); + if (STATE_CVAR) { func_8082E1F0(player, NA_SE_PL_CHANGE_ARMS); } else { func_8082E1F0(player, NA_SE_PL_TAKE_OUT_SHIELD); @@ -172,38 +167,34 @@ void RegisterPersistentMasks() { // Prevent the "equipped" white border from being drawn so ours shows instead (ours was drawn before it, so it's // underneath) - REGISTER_VB_SHOULD(VB_DRAW_ITEM_EQUIPPED_OUTLINE, { + COND_VB_SHOULD(VB_DRAW_ITEM_EQUIPPED_OUTLINE, CVAR, { ItemId* itemId = va_arg(args, ItemId*); - if (*itemId == ITEM_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + if (*itemId == ITEM_MASK_BUNNY && STATE_CVAR) { *should = false; } }); // Typically when you are in a transformation all masks are dimmed on the C-Buttons - REGISTER_VB_SHOULD(VB_ITEM_BE_RESTRICTED, { + COND_VB_SHOULD(VB_ITEM_BE_RESTRICTED, CVAR, { ItemId* itemId = va_arg(args, ItemId*); - if (*itemId == ITEM_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) { + if (*itemId == ITEM_MASK_BUNNY) { *should = false; } }); // Override "A" press behavior on kaleido scope to toggle the mask state - REGISTER_VB_SHOULD(VB_KALEIDO_DISPLAY_ITEM_TEXT, { + COND_VB_SHOULD(VB_KALEIDO_DISPLAY_ITEM_TEXT, CVAR, { ItemId* itemId = va_arg(args, ItemId*); - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0) && *itemId == ITEM_MASK_BUNNY) { + if (*itemId == ITEM_MASK_BUNNY) { *should = false; - CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", - !CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)); - if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) { + CVarSetInteger(STATE_CVAR_NAME, !STATE_CVAR); + if (STATE_CVAR) { Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_DOWN); } else { Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_UP); } - } else if (CVarGetInteger("gEnhancements.Masks.PersistentGreatFairyMask.Enabled", 0) && - *itemId == ITEM_MASK_GREAT_FAIRY) { - *should = false; - CVarSetInteger("gEnhancements.Masks.PersistentGreatFairyMask.State", - !CVarGetInteger("gEnhancements.Masks.PersistentGreatFairyMask.State", 0)); } }); } + +static RegisterShipInitFunc initFunc(RegisterPersistentMasks, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Minigames/AlwaysWinDoggyRace.cpp b/mm/2s2h/Enhancements/Minigames/AlwaysWinDoggyRace.cpp index 9f7ed23ad8..8c1eb12983 100644 --- a/mm/2s2h/Enhancements/Minigames/AlwaysWinDoggyRace.cpp +++ b/mm/2s2h/Enhancements/Minigames/AlwaysWinDoggyRace.cpp @@ -1,19 +1,22 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/Enhancements/Enhancements.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include -extern SaveContext gSaveContext; -extern u8 gItemSlots[77]; +#include "variables.h" } +#define CVAR_NAME "gEnhancements.Minigames.AlwaysWinDoggyRace" +#define CVAR CVarGetInteger(CVAR_NAME, ALWAYS_WIN_DOGGY_RACE_OFF) + void RegisterAlwaysWinDoggyRace() { - REGISTER_VB_SHOULD(VB_DOGGY_RACE_SET_MAX_SPEED, { - uint8_t selectedOption = CVarGetInteger("gEnhancements.Minigames.AlwaysWinDoggyRace", 0); - if (selectedOption == ALWAYS_WIN_DOGGY_RACE_ALWAYS || (selectedOption == ALWAYS_WIN_DOGGY_RACE_MASKOFTRUTH && - (INV_CONTENT(ITEM_MASK_TRUTH) == ITEM_MASK_TRUTH))) { + COND_VB_SHOULD(VB_DOGGY_RACE_SET_MAX_SPEED, CVAR != ALWAYS_WIN_DOGGY_RACE_OFF, { + if (CVAR == ALWAYS_WIN_DOGGY_RACE_ALWAYS || + (CVAR == ALWAYS_WIN_DOGGY_RACE_MASKOFTRUTH && (INV_CONTENT(ITEM_MASK_TRUTH) == ITEM_MASK_TRUTH))) { *should = true; } }); } + +static RegisterShipInitFunc initFunc(RegisterAlwaysWinDoggyRace, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Minigames/CremiaHugs.cpp b/mm/2s2h/Enhancements/Minigames/CremiaHugs.cpp index 2a9123fe35..75f38664f1 100644 --- a/mm/2s2h/Enhancements/Minigames/CremiaHugs.cpp +++ b/mm/2s2h/Enhancements/Minigames/CremiaHugs.cpp @@ -1,18 +1,19 @@ #include -#include "GameInteractor/GameInteractor.h" -#include "Enhancements/Enhancements.h" +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/Enhancements/Enhancements.h" +#include "2s2h/ShipInit.hpp" -extern "C" { -#include -} +#define CVAR_NAME "gEnhancements.Minigames.CremiaHugs" +#define CVAR CVarGetInteger(CVAR_NAME, CREMIA_REWARD_RANDOM) void RegisterCremiaHugs() { - REGISTER_VB_SHOULD(VB_PLAY_CREMIA_HUG_CUTSCENE, { - uint8_t selectedOption = CVarGetInteger("gEnhancements.Minigames.CremiaHugs", 0); - if (selectedOption == CREMIA_REWARD_ALWAYS_HUG) { + COND_VB_SHOULD(VB_PLAY_CREMIA_HUG_CUTSCENE, CVAR != CREMIA_REWARD_RANDOM, { + if (CVAR == CREMIA_REWARD_ALWAYS_HUG) { *should = true; - } else if (selectedOption == CREMIA_REWARD_ALWAYS_RUPEE) { + } else if (CVAR == CREMIA_REWARD_ALWAYS_RUPEE) { *should = false; } }); } + +static RegisterShipInitFunc initFunc(RegisterCremiaHugs, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Minigames/CuccoShackCuccoCount.cpp b/mm/2s2h/Enhancements/Minigames/CuccoShackCuccoCount.cpp index 3a02182b5a..deb6c0c6d8 100644 --- a/mm/2s2h/Enhancements/Minigames/CuccoShackCuccoCount.cpp +++ b/mm/2s2h/Enhancements/Minigames/CuccoShackCuccoCount.cpp @@ -1,5 +1,6 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "overlays/actors/ovl_En_Hs/z_en_hs.h" @@ -8,26 +9,27 @@ extern "C" { void func_8095345C(EnHs* enHs, PlayState* play); } +#define CVAR_NAME "gEnhancements.Minigames.CuccoShackCuccoCount" +#define CVAR CVarGetInteger(CVAR_NAME, 10) + void RegisterCuccoShackCuccoCount() { - GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_HS, [](Actor* actor, bool* should) { - EnHs* enHs = (EnHs*)actor; - - if (enHs->actionFunc != func_8095345C || - CVarGetInteger("gEnhancements.Minigames.CuccoShackCuccoCount", 10) == 10) { - return; - } - - // As soon as enough have grown up, set the count to the max - if (enHs->actor.home.rot.x >= (CVarGetInteger("gEnhancements.Minigames.CuccoShackCuccoCount", 10) * 2) && - enHs->actor.home.rot.x != 20) { - enHs->actor.home.rot.x = 20; - } - - // As soon as enough are following the player, set the count to the max - if (enHs->actor.home.rot.z >= (CVarGetInteger("gEnhancements.Minigames.CuccoShackCuccoCount", 10) * 2) && - enHs->actor.home.rot.z != 20) { - enHs->actor.home.rot.z = 20; - } - }); + COND_ID_HOOK(ShouldActorUpdate, ACTOR_EN_HS, CVAR != 10, [](Actor* actor, bool* should) { + EnHs* enHs = (EnHs*)actor; + + if (enHs->actionFunc != func_8095345C) { + return; + } + + // As soon as enough have grown up, set the count to the max + if (enHs->actor.home.rot.x >= (CVAR * 2) && enHs->actor.home.rot.x != 20) { + enHs->actor.home.rot.x = 20; + } + + // As soon as enough are following the player, set the count to the max + if (enHs->actor.home.rot.z >= (CVAR * 2) && enHs->actor.home.rot.z != 20) { + enHs->actor.home.rot.z = 20; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterCuccoShackCuccoCount, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Minigames/Minigames.h b/mm/2s2h/Enhancements/Minigames/Minigames.h deleted file mode 100644 index bf63a26ba4..0000000000 --- a/mm/2s2h/Enhancements/Minigames/Minigames.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MINIGAMES_H -#define MINIGAMES_H - -void RegisterAlwaysWinDoggyRace(); -void RegisterCremiaHugs(); -void RegisterCuccoShackCuccoCount(); -void RegisterSwordsmanSchool(); - -#endif // MINIGAMES_H diff --git a/mm/2s2h/Enhancements/Minigames/SwordsmanSchool.cpp b/mm/2s2h/Enhancements/Minigames/SwordsmanSchool.cpp index 6bd0448d9e..84cf8e0f02 100644 --- a/mm/2s2h/Enhancements/Minigames/SwordsmanSchool.cpp +++ b/mm/2s2h/Enhancements/Minigames/SwordsmanSchool.cpp @@ -1,5 +1,6 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "overlays/actors/ovl_En_Kendo_Js/z_en_kendo_js.h" @@ -7,25 +8,28 @@ extern "C" { void func_80B274BC(EnKendoJs* thisx, PlayState* play); } +#define CVAR_NAME "gEnhancements.Minigames.SwordsmanSchoolScore" +#define CVAR CVarGetInteger(CVAR_NAME, 30) + void RegisterSwordsmanSchool() { - GameInteractor::Instance->RegisterGameHookForID( - ACTOR_EN_KENDO_JS, [](Actor* actor, bool* should) { - EnKendoJs* kendo = (EnKendoJs*)actor; - - if (kendo->actionFunc != func_80B274BC) { - return; - } - - // Finishes the game early, as soon as the player reaches the required score - if (gSaveContext.minigameScore >= CVarGetInteger("gEnhancements.Minigames.SwordsmanSchoolScore", 30)) { - kendo->unk_290 = 140; - kendo->unk_284 = 5; - } - - // Each time player chops a log, check if they've reached the required score - if (kendo->unk_290 >= 140 && kendo->unk_284 == 5 && - gSaveContext.minigameScore >= CVarGetInteger("gEnhancements.Minigames.SwordsmanSchoolScore", 30)) { - gSaveContext.minigameScore = 30; - } - }); + COND_ID_HOOK(ShouldActorUpdate, ACTOR_EN_KENDO_JS, CVAR != 30, [](Actor* actor, bool* should) { + EnKendoJs* kendo = (EnKendoJs*)actor; + + if (kendo->actionFunc != func_80B274BC) { + return; + } + + // Finishes the game early, as soon as the player reaches the required score + if (gSaveContext.minigameScore >= CVAR) { + kendo->unk_290 = 140; + kendo->unk_284 = 5; + } + + // Each time player chops a log, check if they've reached the required score + if (kendo->unk_290 >= 140 && kendo->unk_284 == 5 && gSaveContext.minigameScore >= CVAR) { + gSaveContext.minigameScore = 30; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterSwordsmanSchool, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Modes/HyruleWarriorsStyledLink.cpp b/mm/2s2h/Enhancements/Modes/HyruleWarriorsStyledLink.cpp new file mode 100644 index 0000000000..e22ba5783d --- /dev/null +++ b/mm/2s2h/Enhancements/Modes/HyruleWarriorsStyledLink.cpp @@ -0,0 +1,51 @@ +#include +#include "2s2h/GameInteractor/GameInteractor.h" +#include "Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { +#include "variables.h" +#include "functions.h" +extern const char* D_801C0B20[28]; +} + +#define CVAR_NAME "gModes.HyruleWarriorsStyledLink" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void RegisterHyruleWarriorsStyledLink() { + COND_ID_HOOK(OnPlayerPostLimbDraw, PLAYER_LIMB_HEAD, CVAR, [](Player* player, s32 limbIndex) { + if (player->currentMask == PLAYER_MASK_NONE && player->transformation == PLAYER_FORM_HUMAN && + INV_CONTENT(ITEM_MASK_KEATON) == ITEM_MASK_KEATON) { + OPEN_DISPS(gPlayState->state.gfxCtx); + Matrix_Push(); + Matrix_RotateYS(0x38e3, MTXMODE_APPLY); + Matrix_RotateZS(-0x12F6, MTXMODE_APPLY); + Matrix_Translate(300.0f, -250.0f, 77.7f, MTXMODE_APPLY); + Matrix_Scale(0.648f, 0.648f, 0.648f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gPlayState->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)D_801C0B20[PLAYER_MASK_KEATON - 1]); + Matrix_Pop(); + CLOSE_DISPS(gPlayState->state.gfxCtx); + } + }); + COND_ID_HOOK(OnPlayerPostLimbDraw, PLAYER_LIMB_WAIST, CVAR, [](Player* player, s32 limbIndex) { + if (player->transformation == PLAYER_FORM_HUMAN && player->itemAction != PLAYER_IA_MASK_FIERCE_DEITY && + INV_CONTENT(ITEM_MASK_FIERCE_DEITY) == ITEM_MASK_FIERCE_DEITY) { + OPEN_DISPS(gPlayState->state.gfxCtx); + Matrix_Push(); + Matrix_RotateXS(-0x61A8, MTXMODE_APPLY); + Matrix_RotateYS(-0x7D0, MTXMODE_APPLY); + Matrix_RotateZS(-0x3A98, MTXMODE_APPLY); + Matrix_Translate(-85.0f, 658.0f, -165.0f, MTXMODE_APPLY); + Matrix_Scale(0.635f, 0.635f, 0.635f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gPlayState->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)D_801C0B20[PLAYER_MASK_FIERCE_DEITY - 1]); + Matrix_Pop(); + CLOSE_DISPS(gPlayState->state.gfxCtx); + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterHyruleWarriorsStyledLink, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Modes/Modes.h b/mm/2s2h/Enhancements/Modes/Modes.h deleted file mode 100644 index f46466f1a8..0000000000 --- a/mm/2s2h/Enhancements/Modes/Modes.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MODES_H -#define MODES_H - -void RegisterTimeMovesWhenYouMove(); - -#endif // MODES_H diff --git a/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp b/mm/2s2h/Enhancements/Modes/PlayAsKafei.cpp similarity index 86% rename from mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp rename to mm/2s2h/Enhancements/Modes/PlayAsKafei.cpp index a07a50fa0c..73821cd237 100644 --- a/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp +++ b/mm/2s2h/Enhancements/Modes/PlayAsKafei.cpp @@ -1,12 +1,12 @@ -#include "libultraship/libultraship.h" +#include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h" -#include "functions.h" -extern PlayState* gPlayState; +#include "variables.h" #include "objects/object_link_child/object_link_child.h" #include "objects/object_test3/object_test3.h" + void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); extern TexturePtr sPlayerEyesTextures[PLAYER_FORM_MAX][PLAYER_EYES_MAX]; @@ -16,8 +16,11 @@ extern TexturePtr sPlayerMouthTextures[PLAYER_FORM_MAX][PLAYER_MOUTH_MAX]; static SkeletonHeader gLinkHumanSkelBackup; static SkeletonHeader gKafeiSkelBackup; +#define CVAR_NAME "gModes.PlayAsKafei" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void UpdatePlayAsKafei() { - if (CVarGetInteger("gModes.PlayAsKafei", 0)) { + if (CVAR) { auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); memcpy(gLinkHumanSkelPtr, &gKafeiSkelBackup, sizeof(SkeletonHeader)); @@ -64,6 +67,14 @@ void UpdatePlayAsKafei() { } void RegisterPlayAsKafei() { + // Even though this isn't run when a cvar is changed, it can still run if ShipInit::InitAll(); is called again, + // likely in the case of setting a preset or something. So we need to make sure this only runs once. + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); auto gKafeiSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gKafeiSkel); @@ -77,3 +88,6 @@ void RegisterPlayAsKafei() { GameInteractor::Instance->RegisterGameHook([]() { UpdatePlayAsKafei(); }); } + +// We only want this running at boot, we don't want this running when the cvar is changed, only on scene destroy +static RegisterShipInitFunc initFunc(RegisterPlayAsKafei, {}); diff --git a/mm/2s2h/Enhancements/Modes/TimeMovesWhenYouMove.cpp b/mm/2s2h/Enhancements/Modes/TimeMovesWhenYouMove.cpp index 98ec35ecd5..e1068c37c7 100644 --- a/mm/2s2h/Enhancements/Modes/TimeMovesWhenYouMove.cpp +++ b/mm/2s2h/Enhancements/Modes/TimeMovesWhenYouMove.cpp @@ -1,30 +1,25 @@ -#include "libultraship/libultraship.h" +#include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "macros.h" -#include "z64.h" -extern PlayState* gPlayState; -extern SaveContext gSaveContext; +#include "variables.h" } -static HOOK_ID onActorUpdateHookId = 0; +#define CVAR_NAME "gModes.TimeMovesWhenYouMove" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterTimeMovesWhenYouMove() { - GameInteractor::Instance->UnregisterGameHookForID(onActorUpdateHookId); - onActorUpdateHookId = 0; gSaveContext.save.timeSpeedOffset = 0; - if (CVarGetInteger("gModes.TimeMovesWhenYouMove", 0)) { - onActorUpdateHookId = GameInteractor::Instance->RegisterGameHookForID( - ACTOR_PLAYER, [](Actor* actor) { - Player* player = GET_PLAYER(gPlayState); + COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR, [](Actor* actor) { + Player* player = GET_PLAYER(gPlayState); - gSaveContext.save.timeSpeedOffset = -R_TIME_SPEED; - if (player->linearVelocity != 0) { - gSaveContext.save.timeSpeedOffset = - CLAMP(player->linearVelocity / 2 - R_TIME_SPEED, -R_TIME_SPEED, 10); - } - }); - } + gSaveContext.save.timeSpeedOffset = -R_TIME_SPEED; + if (player->linearVelocity != 0) { + gSaveContext.save.timeSpeedOffset = CLAMP(player->linearVelocity / 2 - R_TIME_SPEED, -R_TIME_SPEED, 10); + } + }); } + +static RegisterShipInitFunc initFunc(RegisterTimeMovesWhenYouMove, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Player/ClimbSpeed.cpp b/mm/2s2h/Enhancements/Player/ClimbSpeed.cpp index 65ee403c8e..1579659b22 100644 --- a/mm/2s2h/Enhancements/Player/ClimbSpeed.cpp +++ b/mm/2s2h/Enhancements/Player/ClimbSpeed.cpp @@ -1,11 +1,15 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gEnhancements.Player.ClimbSpeed" +#define CVAR CVarGetInteger(CVAR_NAME, 1) void RegisterClimbSpeed() { - REGISTER_VB_SHOULD(VB_SET_CLIMB_SPEED, { - if (CVarGetInteger("gEnhancements.Player.ClimbSpeed", 1) > 1) { - f32* speed = va_arg(args, f32*); - *speed *= CVarGetInteger("gEnhancements.Player.ClimbSpeed", 1); - } + COND_VB_SHOULD(VB_SET_CLIMB_SPEED, CVAR > 1, { + f32* speed = va_arg(args, f32*); + *speed *= CVAR; }); } + +static RegisterShipInitFunc initFunc(RegisterClimbSpeed, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Player/FastFlowerLaunch.cpp b/mm/2s2h/Enhancements/Player/FastFlowerLaunch.cpp index 9d9e8d0422..e1595a3eb0 100644 --- a/mm/2s2h/Enhancements/Player/FastFlowerLaunch.cpp +++ b/mm/2s2h/Enhancements/Player/FastFlowerLaunch.cpp @@ -1,46 +1,40 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "macros.h" -#include "z64.h" -extern PlayState* gPlayState; -extern Input* sPlayerControlInput; +#include "variables.h" void Player_Action_93(Player* player, PlayState* play); } -void RegisterFastFlowerLaunch() { - static HOOK_ID playerUpdateHook = 0; - GameInteractor::Instance->UnregisterGameHookForID(playerUpdateHook); - playerUpdateHook = 0; - - if (!CVarGetInteger("gEnhancements.Player.FastFlowerLaunch", 0)) { - return; - } +#define CVAR_NAME "gEnhancements.Player.FastFlowerLaunch" +#define CVAR CVarGetInteger(CVAR_NAME, 0) - playerUpdateHook = - GameInteractor::Instance->RegisterGameHookForID(ACTOR_PLAYER, [](Actor* actor) { - Player* player = GET_PLAYER(gPlayState); - if (player->actionFunc != Player_Action_93) { - return; - } +void RegisterFastFlowerLaunch() { + COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR, [](Actor* actor) { + Player* player = GET_PLAYER(gPlayState); + if (player->actionFunc != Player_Action_93) { + return; + } - DynaPolyActor* dyna; - Input* input = &gPlayState->state.input[0]; + DynaPolyActor* dyna; + Input* input = &gPlayState->state.input[0]; - if (player->av1.actionVar1 != 0 && !(player->av1.actionVar1 == 1 && player->unk_B48 > -170.0f) && - player->av2.actionVar2 != 10 && !CHECK_BTN_ALL(input->cur.button, BTN_A)) { - player->unk_ABC = -3900.0f; - player->unk_B48 = -170.0f; - player->av1.actionVar1 = 2; - player->av2.actionVar2 = 10; - player->actor.scale.y = 0.01f; - dyna = DynaPoly_GetActor(&gPlayState->colCtx, player->actor.floorBgId); + if (player->av1.actionVar1 != 0 && !(player->av1.actionVar1 == 1 && player->unk_B48 > -170.0f) && + player->av2.actionVar2 != 10 && !CHECK_BTN_ALL(input->cur.button, BTN_A)) { + player->unk_ABC = -3900.0f; + player->unk_B48 = -170.0f; + player->av1.actionVar1 = 2; + player->av2.actionVar2 = 10; + player->actor.scale.y = 0.01f; + dyna = DynaPoly_GetActor(&gPlayState->colCtx, player->actor.floorBgId); - if (dyna != NULL) { - player->actor.world.pos.x = dyna->actor.world.pos.x; - player->actor.world.pos.z = dyna->actor.world.pos.z; - } + if (dyna != NULL) { + player->actor.world.pos.x = dyna->actor.world.pos.x; + player->actor.world.pos.z = dyna->actor.world.pos.z; } - }); + } + }); } + +static RegisterShipInitFunc initFunc(RegisterFastFlowerLaunch, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Player/FierceDeityPutaway.cpp b/mm/2s2h/Enhancements/Player/FierceDeityPutaway.cpp index cad33ae434..891343acdc 100644 --- a/mm/2s2h/Enhancements/Player/FierceDeityPutaway.cpp +++ b/mm/2s2h/Enhancements/Player/FierceDeityPutaway.cpp @@ -1,19 +1,23 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { #include "variables.h" +} + +#define CVAR_NAME "gEnhancements.Player.FierceDeityPutaway" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterFierceDeityPutaway() { - REGISTER_VB_SHOULD(VB_SHOULD_PUTAWAY, { - if (CVarGetInteger("gEnhancements.Player.FierceDeityPutaway", 0)) { - Player* player = GET_PLAYER(gPlayState); - if (player->transformation == PLAYER_FORM_FIERCE_DEITY) - *should = true; + COND_VB_SHOULD(VB_SHOULD_PUTAWAY, CVAR, { + Player* player = GET_PLAYER(gPlayState); + if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + *should = true; } }); - REGISTER_VB_SHOULD(VB_FD_ALWAYS_WIELD_SWORD, { - if (CVarGetInteger("gEnhancements.Player.FierceDeityPutaway", 0)) { - *should = false; - } - }); + COND_VB_SHOULD(VB_FD_ALWAYS_WIELD_SWORD, CVAR, { *should = false; }); } + +static RegisterShipInitFunc initFunc(RegisterFierceDeityPutaway, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Player/InstantPutaway.cpp b/mm/2s2h/Enhancements/Player/InstantPutaway.cpp index 2afd233a9f..40e4d88575 100644 --- a/mm/2s2h/Enhancements/Player/InstantPutaway.cpp +++ b/mm/2s2h/Enhancements/Player/InstantPutaway.cpp @@ -1,10 +1,12 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gEnhancements.Player.InstantPutaway" +#define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterInstantPutaway() { - REGISTER_VB_SHOULD(VB_RESET_PUTAWAY_TIMER, { - if (CVarGetInteger("gEnhancements.Player.InstantPutaway", 0)) { - *should = false; - } - }); + COND_VB_SHOULD(VB_RESET_PUTAWAY_TIMER, CVAR, { *should = false; }); } + +static RegisterShipInitFunc initFunc(RegisterInstantPutaway, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Player/Player.h b/mm/2s2h/Enhancements/Player/Player.h deleted file mode 100644 index 6aebb110a6..0000000000 --- a/mm/2s2h/Enhancements/Player/Player.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef PLAYER_H -#define PLAYER_H - -void RegisterClimbSpeed(); -void RegisterFastFlowerLaunch(); -void RegisterInstantPutaway(); -void RegisterFierceDeityPutaway(); - -#endif // PLAYER_H diff --git a/mm/2s2h/Enhancements/Songs/EnableSunsSong.cpp b/mm/2s2h/Enhancements/Songs/EnableSunsSong.cpp index 8165b1f21d..555b695cfd 100644 --- a/mm/2s2h/Enhancements/Songs/EnableSunsSong.cpp +++ b/mm/2s2h/Enhancements/Songs/EnableSunsSong.cpp @@ -1,16 +1,22 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include } +#define CVAR_NAME "gEnhancements.Songs.EnableSunsSong" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterEnableSunsSong() { - REGISTER_VB_SHOULD(VB_SONG_AVAILABLE_TO_PLAY, { + COND_VB_SHOULD(VB_SONG_AVAILABLE_TO_PLAY, CVAR, { uint8_t* songIndex = va_arg(args, uint8_t*); - // If the enhancement is on, and the currently played song is Sun's Song, set it to be available to be played. - if (CVarGetInteger("gEnhancements.Songs.EnableSunsSong", 0) && *songIndex == OCARINA_SONG_SUNS) { + // If the currently played song is Sun's Song, set it to be available to be played. + if (*songIndex == OCARINA_SONG_SUNS) { *should = true; } }); } + +static RegisterShipInitFunc initFunc(RegisterEnableSunsSong, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Songs/FasterSongPlayback.cpp b/mm/2s2h/Enhancements/Songs/FasterSongPlayback.cpp index fe4dc02c09..9ecc02596a 100644 --- a/mm/2s2h/Enhancements/Songs/FasterSongPlayback.cpp +++ b/mm/2s2h/Enhancements/Songs/FasterSongPlayback.cpp @@ -1,5 +1,6 @@ +#include #include "2s2h/GameInteractor/GameInteractor.h" -#include "libultraship/libultraship.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "variables.h" @@ -7,24 +8,19 @@ extern "C" { extern u8 sPlaybackState; } -void RegisterFasterSongPlayback() { - static uint32_t onPlayerUpdate = 0; - GameInteractor::Instance->UnregisterGameHookForID(onPlayerUpdate); - - onPlayerUpdate = 0; - - if (!CVarGetInteger("gEnhancements.Songs.FasterSongPlayback", 0)) { - return; - } +#define CVAR_NAME "gEnhancements.Songs.FasterSongPlayback" +#define CVAR CVarGetInteger(CVAR_NAME, 0) - onPlayerUpdate = - GameInteractor::Instance->RegisterGameHookForID(ACTOR_PLAYER, [](Actor* actor) { - if (gPlayState->msgCtx.msgMode >= MSGMODE_SONG_PLAYED && gPlayState->msgCtx.msgMode <= MSGMODE_17) { - if (gPlayState->msgCtx.stateTimer > 1) { - gPlayState->msgCtx.stateTimer = 1; - } - gPlayState->msgCtx.ocarinaSongEffectActive = 0; - sPlaybackState = 0; +void RegisterFasterSongPlayback() { + COND_ID_HOOK(OnActorUpdate, ACTOR_PLAYER, CVAR, [](Actor* actor) { + if (gPlayState->msgCtx.msgMode >= MSGMODE_SONG_PLAYED && gPlayState->msgCtx.msgMode <= MSGMODE_17) { + if (gPlayState->msgCtx.stateTimer > 1) { + gPlayState->msgCtx.stateTimer = 1; } - }); + gPlayState->msgCtx.ocarinaSongEffectActive = 0; + sPlaybackState = 0; + } + }); } + +static RegisterShipInitFunc initFunc(RegisterFasterSongPlayback, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Songs/PauseOwlWarp.cpp b/mm/2s2h/Enhancements/Songs/PauseOwlWarp.cpp index 8415565654..f1e8ed9547 100644 --- a/mm/2s2h/Enhancements/Songs/PauseOwlWarp.cpp +++ b/mm/2s2h/Enhancements/Songs/PauseOwlWarp.cpp @@ -1,5 +1,6 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" @@ -11,8 +12,11 @@ extern u16 D_80AF343C[]; extern s16 sInDungeonScene; } +#define CVAR_NAME "gEnhancements.Songs.PauseOwlWarp" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + extern "C" bool PauseOwlWarp_IsOwlWarpEnabled() { - return CVarGetInteger("gEnhancements.Songs.PauseOwlWarp", 0) && CHECK_QUEST_ITEM(QUEST_SONG_SOARING) && + return CVAR && CHECK_QUEST_ITEM(QUEST_SONG_SOARING) && gSaveContext.save.saveInfo.playerData.owlActivationFlags != 0 && gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE; } @@ -191,9 +195,11 @@ void HandlePauseOwlWarp(PauseContext* pauseCtx) { } void RegisterPauseOwlWarp() { - GameInteractor::Instance->RegisterGameHook([](PauseContext* pauseCtx) { + COND_HOOK(OnKaleidoUpdate, CVAR, [](PauseContext* pauseCtx) { if (!sInDungeonScene && PauseOwlWarp_IsOwlWarpEnabled() && CHECK_QUEST_ITEM(QUEST_SONG_SOARING)) { HandlePauseOwlWarp(pauseCtx); } }); } + +static RegisterShipInitFunc initFunc(RegisterPauseOwlWarp, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Songs/SkipScarecrowSong.cpp b/mm/2s2h/Enhancements/Songs/SkipScarecrowSong.cpp index 1804de1485..11f90c9874 100644 --- a/mm/2s2h/Enhancements/Songs/SkipScarecrowSong.cpp +++ b/mm/2s2h/Enhancements/Songs/SkipScarecrowSong.cpp @@ -1,29 +1,32 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { -#include "z64.h" +#include "variables.h" #include "functions.h" #include "src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.h" -extern PlayState* gPlayState; } +#define CVAR_NAME "gEnhancements.Playback.SkipScarecrowSong" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + void RegisterSkipScarecrowSong() { - REGISTER_VB_SHOULD(VB_NEED_SCARECROW_SONG, { - if (CVarGetInteger("gEnhancements.Playback.SkipScarecrowSong", 0)) { - EnKakasi* enKakasi = va_arg(args, EnKakasi*); - /* - * This is somewhat similar to the condition that the scarecrow normally checks, except it checks if the - * instrument is being played at all instead of having played the Scarecrow's Song in particular, and it - * bypasses the check that Link has taught Pierre a song this cycle. - */ - if ((enKakasi->picto.actor.xzDistToPlayer < enKakasi->songSummonDist) && - ((BREG(1) != 0) || (gPlayState->msgCtx.ocarinaMode == OCARINA_MODE_ACTIVE))) { - *should = true; - // Properly get out of the ocarina playing state - AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); - Message_CloseTextbox(gPlayState); - } + COND_VB_SHOULD(VB_NEED_SCARECROW_SONG, CVAR, { + EnKakasi* enKakasi = va_arg(args, EnKakasi*); + /* + * This is somewhat similar to the condition that the scarecrow normally checks, except it checks if the + * instrument is being played at all instead of having played the Scarecrow's Song in particular, and it + * bypasses the check that Link has taught Pierre a song this cycle. + */ + if ((enKakasi->picto.actor.xzDistToPlayer < enKakasi->songSummonDist) && + ((BREG(1) != 0) || (gPlayState->msgCtx.ocarinaMode == OCARINA_MODE_ACTIVE))) { + *should = true; + // Properly get out of the ocarina playing state + AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); + Message_CloseTextbox(gPlayState); } }); } + +static RegisterShipInitFunc initFunc(RegisterSkipScarecrowSong, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Songs/Songs.h b/mm/2s2h/Enhancements/Songs/Songs.h index d4df3cc88d..cefec6d8e7 100644 --- a/mm/2s2h/Enhancements/Songs/Songs.h +++ b/mm/2s2h/Enhancements/Songs/Songs.h @@ -1,12 +1,6 @@ #ifndef SONGS_H #define SONGS_H -void RegisterEnableSunsSong(); -void RegisterFasterSongPlayback(); -void RegisterZoraEggCount(); -void RegisterPauseOwlWarp(); -void RegisterSkipScarecrowSong(); - #ifdef __cplusplus extern "C" { #endif diff --git a/mm/2s2h/Enhancements/Songs/ZoraEggCount.cpp b/mm/2s2h/Enhancements/Songs/ZoraEggCount.cpp index 92adaaa5d7..e2b9c99f45 100644 --- a/mm/2s2h/Enhancements/Songs/ZoraEggCount.cpp +++ b/mm/2s2h/Enhancements/Songs/ZoraEggCount.cpp @@ -1,5 +1,6 @@ #include #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" extern "C" { #include "src/overlays/actors/ovl_En_Mk/z_en_mk.h" @@ -7,31 +8,18 @@ extern "C" { const uint32_t MAX_EGGS = 7; -void RegisterZoraEggCount() { - // marine researcher, his actor update call is more consistent than the eggs - GameInteractor::Instance->RegisterGameHookForID(ACTOR_EN_MK, [](Actor* outerActor) { - static uint32_t enMkUpdateHook = 0; - static uint32_t enMkKillHook = 0; - GameInteractor::Instance->UnregisterGameHookForPtr(enMkUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enMkKillHook); - enMkUpdateHook = 0; - enMkKillHook = 0; +#define CVAR_NAME "gEnhancements.Songs.ZoraEggCount" +#define CVAR CVarGetInteger(CVAR_NAME, MAX_EGGS) - enMkUpdateHook = GameInteractor::Instance->RegisterGameHookForPtr( - (uintptr_t)outerActor, [](Actor* actor) { - // complete quest if you have enough eggs - if (gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_LABO].unk_14 != MAX_EGGS && - CVarGetInteger("gEnhancements.Songs.ZoraEggCount", MAX_EGGS) <= - gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_LABO].unk_14) { - gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_LABO].unk_14 = MAX_EGGS; - } - }); - enMkKillHook = - GameInteractor::Instance->RegisterGameHook([](s8 sceneId, s8 spawnNum) { - GameInteractor::Instance->UnregisterGameHook(enMkUpdateHook); - GameInteractor::Instance->UnregisterGameHook(enMkKillHook); - enMkUpdateHook = 0; - enMkKillHook = 0; - }); +void RegisterZoraEggCount() { + COND_ID_HOOK(OnActorUpdate, ACTOR_EN_MK, CVAR != MAX_EGGS, [](Actor* actor) { + // complete quest if you have enough eggs + if (gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_LABO].unk_14 != MAX_EGGS && + CVarGetInteger("gEnhancements.Songs.ZoraEggCount", MAX_EGGS) <= + gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_LABO].unk_14) { + gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_LABO].unk_14 = MAX_EGGS; + } }); -} \ No newline at end of file +} + +static RegisterShipInitFunc initFunc(RegisterZoraEggCount, { CVAR_NAME });