summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Longstaff <JordanLongstaff@users.noreply.github.com>2025-10-29 16:36:29 -0400
committerGitHub <noreply@github.com>2025-10-29 13:36:29 -0700
commit1ba6cf643dedd0bb4e92e20eb2ad5c459cacf731 (patch)
tree07437a389890f3dbd21a1a50536549446af4a92b
parentb30191f36935e870ee521fa085c9bd88126cb0ab (diff)
Modularize coloured ToT Medallions hook (#5877)
* Modularize colourized ToT Medallions hook * Add overlooked reset of Forest Medallion colour * Move asset variables to hook file * Fix includes * Remove forward declarations * Use data structures to reduceboilerplate code * Simplify data structures, reduce boilerplate even more * Correct patchName2 checks * Clang format * Add brackets on if statements
-rw-r--r--soh/soh/Enhancements/Graphics/ToTMedallions.cpp129
-rw-r--r--soh/soh/Enhancements/mods.cpp112
-rw-r--r--soh/soh/Enhancements/mods.h2
-rw-r--r--soh/soh/SohGui/SohMenuEnhancements.cpp2
4 files changed, 131 insertions, 114 deletions
diff --git a/soh/soh/Enhancements/Graphics/ToTMedallions.cpp b/soh/soh/Enhancements/Graphics/ToTMedallions.cpp
new file mode 100644
index 000000000..13c752a62
--- /dev/null
+++ b/soh/soh/Enhancements/Graphics/ToTMedallions.cpp
@@ -0,0 +1,129 @@
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/Enhancements/mods.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+#include "align_asset_macro.h"
+#include "macros.h"
+#include "variables.h"
+#include "soh/ResourceManagerHelpers.h"
+extern PlayState* gPlayState;
+}
+
+static constexpr int32_t CVAR_TOT_MEDALLION_COLORS_DEFAULT = 0;
+#define CVAR_TOT_MEDALLION_COLORS_NAME CVAR_ENHANCEMENT("ToTMedallionsColors")
+#define CVAR_TOT_MEDALLION_COLORS_VALUE \
+ CVarGetInteger(CVAR_TOT_MEDALLION_COLORS_NAME, CVAR_TOT_MEDALLION_COLORS_DEFAULT)
+
+// GreyScaleEndDlist
+#define dgEndGrayscaleAndEndDlistDL "__OTR__helpers/cosmetics/gEndGrayscaleAndEndDlistDL"
+static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL;
+
+// This is used for the Temple of Time Medalions' color
+#define dtokinoma_room_0DL_007A70 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007A70"
+static const ALIGN_ASSET(2) char tokinoma_room_0DL_007A70[] = dtokinoma_room_0DL_007A70;
+#define dtokinoma_room_0DL_007FD0 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007FD0"
+static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL_007FD0;
+
+static Gfx grayscaleWhite = gsDPSetGrayscaleColor(255, 255, 255, 255);
+
+class ToTPatchSetup {
+ public:
+ ToTPatchSetup(Gfx ifColored, const char* patchName, int index, const char* patchName2 = "", int index2 = 0)
+ : patchName(patchName), index(index), ifColored(ifColored), patchName2(patchName2), index2(index2) {
+ }
+
+ void ApplyPatch(bool colored = true) {
+ Gfx colorGfx = colored ? ifColored : grayscaleWhite;
+ ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, patchName, index, colorGfx);
+ if (patchName2 && *patchName2) {
+ ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, patchName2, index2, colorGfx);
+ }
+ }
+
+ void RevertPatch() {
+ ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, patchName);
+ if (patchName2 && *patchName2) {
+ ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007FD0, patchName2);
+ }
+ }
+
+ private:
+ const char* patchName;
+ const char* patchName2;
+ int index;
+ int index2;
+ Gfx ifColored;
+};
+
+typedef struct MedallionColorPatch {
+ QuestItem questItemId;
+ ToTPatchSetup patch;
+} MedallionColorPatch;
+
+static ToTPatchSetup startGrayscale =
+ ToTPatchSetup(gsSPGrayscale(true), "ToTMedallions_StartGrayscale", 7, "ToTMedallions_2_StartGrayscale", 7);
+
+static MedallionColorPatch medallionColorPatches[] = {
+ { QUEST_MEDALLION_WATER, ToTPatchSetup(gsDPSetGrayscaleColor(0, 161, 255, 255), "ToTMedallions_MakeBlue", 16) },
+ { QUEST_MEDALLION_SPIRIT, ToTPatchSetup(gsDPSetGrayscaleColor(255, 135, 0, 255), "ToTMedallions_MakeOrange", 45) },
+ { QUEST_MEDALLION_LIGHT, ToTPatchSetup(gsDPSetGrayscaleColor(255, 255, 0, 255), "ToTMedallions_MakeYellow", 69,
+ "ToTMedallions_2_MakeYellow", 16) },
+ { QUEST_MEDALLION_FOREST, ToTPatchSetup(gsDPSetGrayscaleColor(0, 255, 0, 255), "ToTMedallions_MakeGreen", 94) },
+ { QUEST_MEDALLION_FIRE, ToTPatchSetup(gsDPSetGrayscaleColor(255, 0, 0, 255), "ToTMedallions_MakeRed", 118) },
+ { QUEST_MEDALLION_SHADOW, ToTPatchSetup(gsDPSetGrayscaleColor(212, 0, 255, 255), "ToTMedallions_MakePurple", 142,
+ "ToTMedallions_2_MakePurple", 27) },
+};
+
+static ToTPatchSetup endGrayscale =
+ ToTPatchSetup(gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL), "ToTMedallions_EndGrayscaleAndEndDlist", 160,
+ "ToTMedallions_2_EndGrayscaleAndEndDlist", 51);
+
+static void PatchToTMedallions() {
+ // TODO: Refactor the DemoEffect_UpdateJewelAdult and DemoEffect_UpdateJewelChild from z_demo_effect
+ // effects to take effect in there
+ startGrayscale.ApplyPatch();
+
+ for (auto& medallionPatch : medallionColorPatches) {
+ medallionPatch.patch.ApplyPatch(CHECK_QUEST_ITEM(medallionPatch.questItemId));
+ }
+
+ endGrayscale.ApplyPatch();
+}
+
+static void ResetToTMedallions() {
+ // Unpatch everything
+ startGrayscale.RevertPatch();
+
+ for (auto& medallionPatch : medallionColorPatches) {
+ medallionPatch.patch.RevertPatch();
+ }
+
+ endGrayscale.RevertPatch();
+}
+
+void UpdateToTMedallions() {
+ if (CVAR_TOT_MEDALLION_COLORS_VALUE) {
+ PatchToTMedallions();
+ } else {
+ ResetToTMedallions();
+ }
+}
+
+static void CheckTempleOfTime(int16_t sceneNum) {
+ if (sceneNum != SCENE_TEMPLE_OF_TIME) {
+ return;
+ }
+ PatchToTMedallions();
+}
+
+static void RegisterToTMedallions() {
+ COND_HOOK(OnItemReceive, CVAR_TOT_MEDALLION_COLORS_VALUE, [](GetItemEntry) {
+ if (gPlayState) {
+ CheckTempleOfTime(gPlayState->sceneNum);
+ }
+ });
+ COND_HOOK(OnSceneInit, CVAR_TOT_MEDALLION_COLORS_VALUE, CheckTempleOfTime);
+}
+
+static RegisterShipInitFunc initFunc(RegisterToTMedallions, { CVAR_TOT_MEDALLION_COLORS_NAME });
diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp
index 08c226340..2577b7dd2 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -49,16 +49,6 @@ extern SaveContext gSaveContext;
extern PlayState* gPlayState;
}
-// GreyScaleEndDlist
-#define dgEndGrayscaleAndEndDlistDL "__OTR__helpers/cosmetics/gEndGrayscaleAndEndDlistDL"
-static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL;
-
-// This is used for the Temple of Time Medalions' color
-#define dtokinoma_room_0DL_007A70 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007A70"
-static const ALIGN_ASSET(2) char tokinoma_room_0DL_007A70[] = dtokinoma_room_0DL_007A70;
-#define dtokinoma_room_0DL_007FD0 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007FD0"
-static const ALIGN_ASSET(2) char tokinoma_room_0DL_007FD0[] = dtokinoma_room_0DL_007FD0;
-
/// Switches Link's age and respawns him at the last entrance he entered.
void SwitchAge() {
if (gPlayState == NULL)
@@ -741,107 +731,6 @@ void RegisterRandomizedEnemySizes() {
});
}
-void PatchToTMedallions() {
- // TODO: Refactor the DemoEffect_UpdateJewelAdult and DemoEffect_UpdateJewelChild from z_demo_effect
- // effects to take effect in there
- if (CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale", 7, gsSPGrayscale(true));
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale", 7, gsSPGrayscale(true));
-
- if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
- gsDPSetGrayscaleColor(0, 161, 255, 255));
- } else {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue", 16,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- }
-
- if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
- gsDPSetGrayscaleColor(255, 135, 0, 255));
- } else {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange", 45,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- }
-
- if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
- gsDPSetGrayscaleColor(255, 255, 0, 255));
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
- gsDPSetGrayscaleColor(255, 255, 0, 255));
- } else {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow", 69,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow", 16,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- }
-
- if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
- gsDPSetGrayscaleColor(0, 255, 0, 255));
- } else {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeGreen", 94,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- }
-
- if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
- gsDPSetGrayscaleColor(255, 0, 0, 255));
- } else {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed", 118,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- }
-
- if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
- gsDPSetGrayscaleColor(212, 0, 255, 255));
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
- gsDPSetGrayscaleColor(212, 0, 255, 255));
- } else {
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple", 142,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple", 27,
- gsDPSetGrayscaleColor(255, 255, 255, 255));
- }
-
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist", 160,
- gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
- ResourceMgr_PatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist", 51,
- gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL));
- } else {
- // Unpatch everything
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_StartGrayscale");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_StartGrayscale");
-
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeBlue");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeOrange");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeYellow");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakeYellow");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakeRed");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_MakePurple");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_MakePurple");
-
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007A70, "ToTMedallions_EndGrayscaleAndEndDlist");
- ResourceMgr_UnpatchGfxByName(tokinoma_room_0DL_007FD0, "ToTMedallions_2_EndGrayscaleAndEndDlist");
- }
-}
-
-void RegisterToTMedallions() {
- GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry _unused) {
- if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || !gPlayState ||
- gPlayState->sceneNum != SCENE_TEMPLE_OF_TIME) {
- return;
- }
- PatchToTMedallions();
- });
- GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
- if (!CVarGetInteger(CVAR_ENHANCEMENT("ToTMedallionsColors"), 0) || sceneNum != SCENE_TEMPLE_OF_TIME) {
- return;
- }
- PatchToTMedallions();
- });
-}
-
void RegisterFloorSwitchesHook() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>([](void* refActor) {
Actor* actor = static_cast<Actor*>(refActor);
@@ -896,7 +785,6 @@ void InitMods() {
RegisterEnemyDefeatCounts();
RegisterBossDefeatTimestamps();
RegisterRandomizedEnemySizes();
- RegisterToTMedallions();
RegisterFloorSwitchesHook();
RegisterPatchHandHandler();
RegisterHurtContainerModeHandler();
diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h
index 8ada99f1e..f28ef1e7e 100644
--- a/soh/soh/Enhancements/mods.h
+++ b/soh/soh/Enhancements/mods.h
@@ -10,7 +10,7 @@ extern "C" {
void UpdateDirtPathFixState(int32_t sceneNum);
void UpdateMirrorModeState(int32_t sceneNum);
void UpdateHurtContainerModeState(bool newState);
-void PatchToTMedallions();
+void UpdateToTMedallions();
void UpdatePermanentHeartLossState();
void UpdateHyperEnemiesState();
void UpdateHyperBossesState();
diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp
index a48706035..e81478df9 100644
--- a/soh/soh/SohGui/SohMenuEnhancements.cpp
+++ b/soh/soh/SohGui/SohMenuEnhancements.cpp
@@ -602,7 +602,7 @@ void SohMenu::AddMenuEnhancements() {
AddWidget(path, "Color Temple of Time's Medallions", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("ToTMedallionsColors"))
.RaceDisable(false)
- .Callback([](WidgetInfo& info) { PatchToTMedallions(); })
+ .Callback([](WidgetInfo& info) { UpdateToTMedallions(); })
.Options(CheckboxOptions().Tooltip(
"When Medallions are collected, the Medallion imprints around the Master Sword Pedestal in the Temple "
"of Time will become colored-in."));