From 3a31dc3202c809bd0277c896fd2cc83f72a5f780 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:05:39 +0900 Subject: [PATCH 1/4] Add Blood Color options to Cosmetics Editor --- .../cosmetics/CosmeticsEditor.cpp | 76 ++++++++++ .../Enhancements/cosmetics/CosmeticsEditor.h | 3 +- .../vanilla-behavior/GIVanillaBehavior.h | 16 +++ soh/src/code/z_collision_check.c | 132 +++++++++--------- 4 files changed, 162 insertions(+), 65 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 3a475516bad..18180141fb6 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -97,6 +97,7 @@ std::map groupLabels = { { COSMETICS_GROUP_NAVI, "Navi" }, { COSMETICS_GROUP_IVAN, "Ivan" }, { COSMETICS_GROUP_MESSAGE, "Message" }, + { COSMETICS_GROUP_BLOOD, "Blood" }, }; static const std::unordered_map cosmeticsRandomizerModes = { @@ -420,6 +421,23 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("SpinAttack.Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ColorRGBA8(255, 255, 170, 255), false, true, true), COSMETIC_OPTION("SpinAttack.Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ColorRGBA8(255, 100, 0, 255), false, true, false), + COSMETIC_OPTION("Blood.Blue0Begin", "Blue 0 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 10, 10, 200, 255), true, true, false), + COSMETIC_OPTION("Blood.Blue0End", "Blue 0 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 32, 0), true, true, false), + COSMETIC_OPTION("Blood.Blue1Begin", "Blue 1 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 128, 255), true, true, false), + COSMETIC_OPTION("Blood.Blue1End", "Blue 1 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 32, 0), true, true, false), + COSMETIC_OPTION("Blood.Blue2Begin", "Blue 2 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 128, 255), true, true, false), + COSMETIC_OPTION("Blood.Blue2End", "Blue 2 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 64, 0), true, true, false), + COSMETIC_OPTION("Blood.Blue3Begin", "Blue 3 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 128, 255), true, true, false), + COSMETIC_OPTION("Blood.Blue3End", "Blue 3 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 0, 64, 0), true, true, false), + COSMETIC_OPTION("Blood.Green0Begin", "Green 0 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 10, 200, 10, 255), true, true, false), + COSMETIC_OPTION("Blood.Green0End", "Green 0 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 32, 0, 0), true, true, false), + COSMETIC_OPTION("Blood.Green1Begin", "Green 1 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 128, 0, 255), true, true, false), + COSMETIC_OPTION("Blood.Green1End", "Green 1 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 32, 0, 0), true, true, false), + COSMETIC_OPTION("Blood.Green2Begin", "Green 2 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 128, 0, 255), true, true, false), + COSMETIC_OPTION("Blood.Green2End", "Green 2 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 64, 0, 0), true, true, false), + COSMETIC_OPTION("Blood.Green3Begin", "Green 3 Begin", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 128, 0, 255), true, true, false), + COSMETIC_OPTION("Blood.Green3End", "Green 3 End", COSMETICS_GROUP_BLOOD, ColorRGBA8( 0, 64, 0, 0), true, true, false), + COSMETIC_OPTION("Trails.Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ColorRGBA8(250, 0, 0, 255), false, true, true), COSMETIC_OPTION("Trails.Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ColorRGBA8(255, 255, 100, 255), false, true, true), COSMETIC_OPTION("Trails.KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ColorRGBA8(255, 255, 255, 255), false, true, false), @@ -2528,6 +2546,7 @@ void CosmeticsEditorWindow::DrawElement() { DrawCosmeticGroup(COSMETICS_GROUP_MAGIC); DrawCosmeticGroup(COSMETICS_GROUP_ARROWS); DrawCosmeticGroup(COSMETICS_GROUP_SPIN_ATTACK); + DrawCosmeticGroup(COSMETICS_GROUP_BLOOD); DrawCosmeticGroup(COSMETICS_GROUP_TRAILS); if (UIWidgets::CVarSliderInt("Trails Duration: %d", CVAR_COSMETIC("Trails.Duration.Value"), UIWidgets::IntSliderOptions() @@ -2678,6 +2697,50 @@ void CosmeticsEditor_ResetGroup(CosmeticGroup group) { ApplyOrResetCustomGfxPatches(); } +static void SetBlueBloodColor(EffectSparkInit* effectSparkInit) { + Color_RGBA8 blue0begin = { 10, 10, 200, 255 }; + effectSparkInit->colorStart[0] = CVarGetColor(CVAR_COSMETIC("Blood.Blue0Begin.Value"), blue0begin); + Color_RGBA8 blue0end = { 0, 0, 32, 0 }; + effectSparkInit->colorEnd[0] = CVarGetColor(CVAR_COSMETIC("Blood.Blue0End.Value"), blue0end); + + Color_RGBA8 blue1begin = { 0, 0, 128, 255 }; + effectSparkInit->colorStart[1] = CVarGetColor(CVAR_COSMETIC("Blood.Blue1Begin.Value"), blue1begin); + Color_RGBA8 blue1end = { 0, 0, 32, 0 }; + effectSparkInit->colorEnd[1] = CVarGetColor(CVAR_COSMETIC("Blood.Blue1End.Value"), blue1end); + + Color_RGBA8 blue2begin = { 0, 0, 128, 255 }; + effectSparkInit->colorStart[2] = CVarGetColor(CVAR_COSMETIC("Blood.Blue2Begin.Value"), blue2begin); + Color_RGBA8 blue2end = { 0, 0, 64, 0 }; + effectSparkInit->colorEnd[2] = CVarGetColor(CVAR_COSMETIC("Blood.Blue2End.Value"), blue2end); + + Color_RGBA8 blue3begin = { 0, 0, 128, 255 }; + effectSparkInit->colorStart[3] = CVarGetColor(CVAR_COSMETIC("Blood.Blue3Begin.Value"), blue3begin); + Color_RGBA8 blue3end = { 0, 0, 64, 0 }; + effectSparkInit->colorEnd[3] = CVarGetColor(CVAR_COSMETIC("Blood.Blue3End.Value"), blue3end); +} + +static void SetGreenBloodColor(EffectSparkInit* effectSparkInit) { + Color_RGBA8 green0begin = { 10, 200, 10, 255 }; + effectSparkInit->colorStart[0] = CVarGetColor(CVAR_COSMETIC("Blood.Green0Begin.Value"), green0begin); + Color_RGBA8 green0end = { 0, 32, 0, 0 }; + effectSparkInit->colorEnd[0] = CVarGetColor(CVAR_COSMETIC("Blood.Green0End.Value"), green0end); + + Color_RGBA8 green1begin = { 0, 128, 0, 255 }; + effectSparkInit->colorStart[1] = CVarGetColor(CVAR_COSMETIC("Blood.Green1Begin.Value"), green1begin); + Color_RGBA8 green1end = { 0, 32, 0, 0 }; + effectSparkInit->colorEnd[1] = CVarGetColor(CVAR_COSMETIC("Blood.Green1End.Value"), green1end); + + Color_RGBA8 green2begin = { 0, 128, 0, 255 }; + effectSparkInit->colorStart[2] = CVarGetColor(CVAR_COSMETIC("Blood.Green2Begin.Value"), green2begin); + Color_RGBA8 green2end = { 0, 64, 0, 0 }; + effectSparkInit->colorEnd[2] = CVarGetColor(CVAR_COSMETIC("Blood.Green2End.Value"), green2end); + + Color_RGBA8 green3begin = { 0, 128, 0, 255 }; + effectSparkInit->colorStart[3] = CVarGetColor(CVAR_COSMETIC("Blood.Green3Begin.Value"), green3begin); + Color_RGBA8 green3end = { 0, 64, 0, 0 }; + effectSparkInit->colorEnd[3] = CVarGetColor(CVAR_COSMETIC("Blood.Green3End.Value"), green3end); +} + void RegisterCosmeticHooks() { COND_HOOK(OnGenerationCompletion, CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), RANDOMIZE_OFF) == RANDOMIZE_ON_RANDO_GEN_ONLY, @@ -2700,6 +2763,19 @@ void RegisterCosmeticHooks() { [](s16 sceneNum) { CosmeticsEditor_AutoRandomizeAll(); }); COND_HOOK(OnGameFrameUpdate, true, CosmeticsUpdateTick); + + COND_VB_SHOULD(VB_BLOOD_SET_COLOR_BLUE, true, { + EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); + *should = false; // Don't run vanilla color set code + // Call a separate color set function (Inlining code here breaks COND_VB_SHOULD macro for some reason) + SetBlueBloodColor(effectSparkInit); + }); + + COND_VB_SHOULD(VB_BLOOD_SET_COLOR_GREEN, true, { + EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); + *should = false; + SetGreenBloodColor(effectSparkInit); + }); } void RegisterCosmeticWidgets() { diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h index 7da88bdbc6b..7e1c59ca6a8 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h @@ -26,6 +26,7 @@ typedef enum { COSMETICS_GROUP_NAVI, COSMETICS_GROUP_IVAN, COSMETICS_GROUP_MESSAGE, + COSMETICS_GROUP_BLOOD, COSMETICS_GROUP_MAX, } CosmeticGroup; @@ -70,4 +71,4 @@ class CosmeticsEditorWindow final : public Ship::GuiWindow { void ApplyDungeonKeyColors(); void UpdateElement() override{}; }; -#endif //__cplusplus \ No newline at end of file +#endif //__cplusplus diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 6c472930930..2644ebd5080 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -227,6 +227,22 @@ typedef enum { // - None VB_BIGGORON_CONSIDER_TRADE_COMPLETE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EffectSparkInit` + VB_BLOOD_SET_COLOR_BLUE, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EffectSparkInit` + VB_BLOOD_SET_COLOR_GREEN, + // #### `result` // Actor is ACTOR_EN_ELF, ACTOR_EN_FISH, ACTOR_EN_ICE_HONO, or ACTOR_EN_INSECT // ```c diff --git a/soh/src/code/z_collision_check.c b/soh/src/code/z_collision_check.c index aa466e412eb..f46a1c34ff3 100644 --- a/soh/src/code/z_collision_check.c +++ b/soh/src/code/z_collision_check.c @@ -1473,38 +1473,40 @@ void CollisionCheck_BlueBlood(PlayState* play, Collider* collider, Vec3f* v) { D_8015D8A0.position.z = v->z; D_8015D8A0.uDiv = 5; D_8015D8A0.vDiv = 5; - D_8015D8A0.colorStart[0].r = 10; - D_8015D8A0.colorStart[0].g = 10; - D_8015D8A0.colorStart[0].b = 200; - D_8015D8A0.colorStart[0].a = 255; - D_8015D8A0.colorStart[1].r = 0; - D_8015D8A0.colorStart[1].g = 0; - D_8015D8A0.colorStart[1].b = 128; - D_8015D8A0.colorStart[1].a = 255; - D_8015D8A0.colorStart[2].r = 0; - D_8015D8A0.colorStart[2].g = 0; - D_8015D8A0.colorStart[2].b = 128; - D_8015D8A0.colorStart[2].a = 255; - D_8015D8A0.colorStart[3].r = 0; - D_8015D8A0.colorStart[3].g = 0; - D_8015D8A0.colorStart[3].b = 128; - D_8015D8A0.colorStart[3].a = 255; - D_8015D8A0.colorEnd[0].r = 0; - D_8015D8A0.colorEnd[0].g = 0; - D_8015D8A0.colorEnd[0].b = 32; - D_8015D8A0.colorEnd[0].a = 0; - D_8015D8A0.colorEnd[1].r = 0; - D_8015D8A0.colorEnd[1].g = 0; - D_8015D8A0.colorEnd[1].b = 32; - D_8015D8A0.colorEnd[1].a = 0; - D_8015D8A0.colorEnd[2].r = 0; - D_8015D8A0.colorEnd[2].g = 0; - D_8015D8A0.colorEnd[2].b = 64; - D_8015D8A0.colorEnd[2].a = 0; - D_8015D8A0.colorEnd[3].r = 0; - D_8015D8A0.colorEnd[3].g = 0; - D_8015D8A0.colorEnd[3].b = 64; - D_8015D8A0.colorEnd[3].a = 0; + if (GameInteractor_Should(VB_BLOOD_SET_COLOR_BLUE, true, &D_8015D8A0)) { + D_8015D8A0.colorStart[0].r = 10; + D_8015D8A0.colorStart[0].g = 10; + D_8015D8A0.colorStart[0].b = 200; + D_8015D8A0.colorStart[0].a = 255; + D_8015D8A0.colorStart[1].r = 0; + D_8015D8A0.colorStart[1].g = 0; + D_8015D8A0.colorStart[1].b = 128; + D_8015D8A0.colorStart[1].a = 255; + D_8015D8A0.colorStart[2].r = 0; + D_8015D8A0.colorStart[2].g = 0; + D_8015D8A0.colorStart[2].b = 128; + D_8015D8A0.colorStart[2].a = 255; + D_8015D8A0.colorStart[3].r = 0; + D_8015D8A0.colorStart[3].g = 0; + D_8015D8A0.colorStart[3].b = 128; + D_8015D8A0.colorStart[3].a = 255; + D_8015D8A0.colorEnd[0].r = 0; + D_8015D8A0.colorEnd[0].g = 0; + D_8015D8A0.colorEnd[0].b = 32; + D_8015D8A0.colorEnd[0].a = 0; + D_8015D8A0.colorEnd[1].r = 0; + D_8015D8A0.colorEnd[1].g = 0; + D_8015D8A0.colorEnd[1].b = 32; + D_8015D8A0.colorEnd[1].a = 0; + D_8015D8A0.colorEnd[2].r = 0; + D_8015D8A0.colorEnd[2].g = 0; + D_8015D8A0.colorEnd[2].b = 64; + D_8015D8A0.colorEnd[2].a = 0; + D_8015D8A0.colorEnd[3].r = 0; + D_8015D8A0.colorEnd[3].g = 0; + D_8015D8A0.colorEnd[3].b = 64; + D_8015D8A0.colorEnd[3].a = 0; + } D_8015D8A0.timer = 0; D_8015D8A0.duration = 16; D_8015D8A0.speed = 8.0f; @@ -1526,38 +1528,40 @@ void CollisionCheck_GreenBlood(PlayState* play, Collider* collider, Vec3f* v) { D_8015DD68.position.z = v->z; D_8015DD68.uDiv = 5; D_8015DD68.vDiv = 5; - D_8015DD68.colorStart[0].r = 10; - D_8015DD68.colorStart[0].g = 200; - D_8015DD68.colorStart[0].b = 10; - D_8015DD68.colorStart[0].a = 255; - D_8015DD68.colorStart[1].r = 0; - D_8015DD68.colorStart[1].g = 128; - D_8015DD68.colorStart[1].b = 0; - D_8015DD68.colorStart[1].a = 255; - D_8015DD68.colorStart[2].r = 0; - D_8015DD68.colorStart[2].g = 128; - D_8015DD68.colorStart[2].b = 0; - D_8015DD68.colorStart[2].a = 255; - D_8015DD68.colorStart[3].r = 0; - D_8015DD68.colorStart[3].g = 128; - D_8015DD68.colorStart[3].b = 0; - D_8015DD68.colorStart[3].a = 255; - D_8015DD68.colorEnd[0].r = 0; - D_8015DD68.colorEnd[0].g = 32; - D_8015DD68.colorEnd[0].b = 0; - D_8015DD68.colorEnd[0].a = 0; - D_8015DD68.colorEnd[1].r = 0; - D_8015DD68.colorEnd[1].g = 32; - D_8015DD68.colorEnd[1].b = 0; - D_8015DD68.colorEnd[1].a = 0; - D_8015DD68.colorEnd[2].r = 0; - D_8015DD68.colorEnd[2].g = 64; - D_8015DD68.colorEnd[2].b = 0; - D_8015DD68.colorEnd[2].a = 0; - D_8015DD68.colorEnd[3].r = 0; - D_8015DD68.colorEnd[3].g = 64; - D_8015DD68.colorEnd[3].b = 0; - D_8015DD68.colorEnd[3].a = 0; + if (GameInteractor_Should(VB_BLOOD_SET_COLOR_GREEN, true, &D_8015DD68)) { + D_8015DD68.colorStart[0].r = 10; + D_8015DD68.colorStart[0].g = 200; + D_8015DD68.colorStart[0].b = 10; + D_8015DD68.colorStart[0].a = 255; + D_8015DD68.colorStart[1].r = 0; + D_8015DD68.colorStart[1].g = 128; + D_8015DD68.colorStart[1].b = 0; + D_8015DD68.colorStart[1].a = 255; + D_8015DD68.colorStart[2].r = 0; + D_8015DD68.colorStart[2].g = 128; + D_8015DD68.colorStart[2].b = 0; + D_8015DD68.colorStart[2].a = 255; + D_8015DD68.colorStart[3].r = 0; + D_8015DD68.colorStart[3].g = 128; + D_8015DD68.colorStart[3].b = 0; + D_8015DD68.colorStart[3].a = 255; + D_8015DD68.colorEnd[0].r = 0; + D_8015DD68.colorEnd[0].g = 32; + D_8015DD68.colorEnd[0].b = 0; + D_8015DD68.colorEnd[0].a = 0; + D_8015DD68.colorEnd[1].r = 0; + D_8015DD68.colorEnd[1].g = 32; + D_8015DD68.colorEnd[1].b = 0; + D_8015DD68.colorEnd[1].a = 0; + D_8015DD68.colorEnd[2].r = 0; + D_8015DD68.colorEnd[2].g = 64; + D_8015DD68.colorEnd[2].b = 0; + D_8015DD68.colorEnd[2].a = 0; + D_8015DD68.colorEnd[3].r = 0; + D_8015DD68.colorEnd[3].g = 64; + D_8015DD68.colorEnd[3].b = 0; + D_8015DD68.colorEnd[3].a = 0; + } D_8015DD68.timer = 0; D_8015DD68.duration = 16; D_8015DD68.speed = 8.0f; From 76e45ee3629aca4df16f80be5bcb36f6bd2cb539 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:50:33 +0900 Subject: [PATCH 2/4] Mac-exclusive fix (use of undeclared identifier 'GameInteractor_Should') --- soh/src/code/z_collision_check.c | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/src/code/z_collision_check.c b/soh/src/code/z_collision_check.c index f46a1c34ff3..8dfb4e366d7 100644 --- a/soh/src/code/z_collision_check.c +++ b/soh/src/code/z_collision_check.c @@ -2,6 +2,7 @@ #include "vt.h" #include "overlays/effects/ovl_Effect_Ss_HitMark/z_eff_ss_hitmark.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include typedef s32 (*ColChkResetFunc)(PlayState*, Collider*); From aaf0db6ff344c53bb1337a75a9e9b3079d5fd272 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Fri, 5 Dec 2025 20:49:07 +0900 Subject: [PATCH 3/4] Register the hooks only when the blood color is changed from default --- .../cosmetics/CosmeticsEditor.cpp | 86 +++++++++++++++---- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 18180141fb6..b6f454649ff 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -59,6 +59,8 @@ u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); } static WidgetInfo goronNeck; +static void RegisterBlueBloodHook(); +static void RegisterGreenBloodHook(); namespace SohGui { extern std::shared_ptr mSohMenu; @@ -1527,6 +1529,12 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { player->actor.scale.z = scale; } } + + // (Un)register Hooks + if (manualChange) { + RegisterBlueBloodHook(); + RegisterGreenBloodHook(); + } } extern "C" Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id) { @@ -2741,6 +2749,41 @@ static void SetGreenBloodColor(EffectSparkInit* effectSparkInit) { effectSparkInit->colorEnd[3] = CVarGetColor(CVAR_COSMETIC("Blood.Green3End.Value"), green3end); } +static void RegisterBlueBloodHook() { + bool hookEnabled = CVarGetInteger(CVAR_COSMETIC("Blood.Blue0Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue0End.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue1Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue1End.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue2Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue2End.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue3Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Blue3End.Changed"), 0); + + COND_VB_SHOULD(VB_BLOOD_SET_COLOR_BLUE, hookEnabled, { + EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); + *should = false; // Don't run vanilla color set code + // Call a separate color set function (Inlining code here breaks COND_VB_SHOULD macro for some reason) + SetBlueBloodColor(effectSparkInit); + }); +} + +static void RegisterGreenBloodHook() { + bool hookEnabled = CVarGetInteger(CVAR_COSMETIC("Blood.Green0Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green0End.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green1Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green1End.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green2Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green2End.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green3Begin.Changed"), 0) || + CVarGetInteger(CVAR_COSMETIC("Blood.Green3End.Changed"), 0); + + COND_VB_SHOULD(VB_BLOOD_SET_COLOR_GREEN, hookEnabled, { + EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); + *should = false; + SetGreenBloodColor(effectSparkInit); + }); +} + void RegisterCosmeticHooks() { COND_HOOK(OnGenerationCompletion, CVarGetInteger(CVAR_COSMETIC("RandomizeCosmeticsGenModes"), RANDOMIZE_OFF) == RANDOMIZE_ON_RANDO_GEN_ONLY, @@ -2763,19 +2806,6 @@ void RegisterCosmeticHooks() { [](s16 sceneNum) { CosmeticsEditor_AutoRandomizeAll(); }); COND_HOOK(OnGameFrameUpdate, true, CosmeticsUpdateTick); - - COND_VB_SHOULD(VB_BLOOD_SET_COLOR_BLUE, true, { - EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); - *should = false; // Don't run vanilla color set code - // Call a separate color set function (Inlining code here breaks COND_VB_SHOULD macro for some reason) - SetBlueBloodColor(effectSparkInit); - }); - - COND_VB_SHOULD(VB_BLOOD_SET_COLOR_GREEN, true, { - EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); - *should = false; - SetGreenBloodColor(effectSparkInit); - }); } void RegisterCosmeticWidgets() { @@ -2792,7 +2822,31 @@ void RegisterCosmeticWidgets() { SohGui::mSohMenu->AddSearchWidget({ goronNeck, "Enhancements", "Cosmetics Editor", "Silly" }); } -static RegisterShipInitFunc initFunc(RegisterCosmeticHooks, { - CVAR_COSMETIC("RandomizeCosmeticsGenModes"), - }); +static RegisterShipInitFunc initFunc_BlueBlood(RegisterBlueBloodHook, { + CVAR_COSMETIC("Blood.Blue0Begin.Changed"), + CVAR_COSMETIC("Blood.Blue0End.Changed"), + CVAR_COSMETIC("Blood.Blue1Begin.Changed"), + CVAR_COSMETIC("Blood.Blue1End.Changed"), + CVAR_COSMETIC("Blood.Blue2Begin.Changed"), + CVAR_COSMETIC("Blood.Blue2End.Changed"), + CVAR_COSMETIC("Blood.Blue3Begin.Changed"), + CVAR_COSMETIC("Blood.Blue3End.Changed"), + }); + +static RegisterShipInitFunc initFunc_GreenBlood(RegisterGreenBloodHook, { + CVAR_COSMETIC("Blood.Green0Begin.Changed"), + CVAR_COSMETIC("Blood.Green0End.Changed"), + CVAR_COSMETIC("Blood.Green1Begin.Changed"), + CVAR_COSMETIC("Blood.Green1End.Changed"), + CVAR_COSMETIC("Blood.Green2Begin.Changed"), + CVAR_COSMETIC("Blood.Green2End.Changed"), + CVAR_COSMETIC("Blood.Green3Begin.Changed"), + CVAR_COSMETIC("Blood.Green3End.Changed"), + }); + +static RegisterShipInitFunc initFunc_CosmeticHooks(RegisterCosmeticHooks, + { + CVAR_COSMETIC("RandomizeCosmeticsGenModes"), + }); + static RegisterMenuInitFunc menuInitFunc(RegisterCosmeticWidgets); From 8aaa9eab4694a05e68f6901d0245f3ca91d682c8 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Fri, 5 Dec 2025 21:35:46 +0900 Subject: [PATCH 4/4] Don't needlessly re-register the hook --- .../cosmetics/CosmeticsEditor.cpp | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index b6f454649ff..2b38f29f567 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -2750,6 +2750,7 @@ static void SetGreenBloodColor(EffectSparkInit* effectSparkInit) { } static void RegisterBlueBloodHook() { + static bool previousHookState = false; // Previous hook enabled state (we don't re-register if unchanged) bool hookEnabled = CVarGetInteger(CVAR_COSMETIC("Blood.Blue0Begin.Changed"), 0) || CVarGetInteger(CVAR_COSMETIC("Blood.Blue0End.Changed"), 0) || CVarGetInteger(CVAR_COSMETIC("Blood.Blue1Begin.Changed"), 0) || @@ -2759,15 +2760,20 @@ static void RegisterBlueBloodHook() { CVarGetInteger(CVAR_COSMETIC("Blood.Blue3Begin.Changed"), 0) || CVarGetInteger(CVAR_COSMETIC("Blood.Blue3End.Changed"), 0); - COND_VB_SHOULD(VB_BLOOD_SET_COLOR_BLUE, hookEnabled, { - EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); - *should = false; // Don't run vanilla color set code - // Call a separate color set function (Inlining code here breaks COND_VB_SHOULD macro for some reason) - SetBlueBloodColor(effectSparkInit); - }); + if (previousHookState != hookEnabled) { + previousHookState = hookEnabled; + + COND_VB_SHOULD(VB_BLOOD_SET_COLOR_BLUE, hookEnabled, { + EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); + *should = false; // Don't run vanilla color set code + // Call a separate color set function (Inlining code here breaks COND_VB_SHOULD macro for some reason) + SetBlueBloodColor(effectSparkInit); + }); + } } static void RegisterGreenBloodHook() { + static bool previousHookState = false; bool hookEnabled = CVarGetInteger(CVAR_COSMETIC("Blood.Green0Begin.Changed"), 0) || CVarGetInteger(CVAR_COSMETIC("Blood.Green0End.Changed"), 0) || CVarGetInteger(CVAR_COSMETIC("Blood.Green1Begin.Changed"), 0) || @@ -2777,11 +2783,15 @@ static void RegisterGreenBloodHook() { CVarGetInteger(CVAR_COSMETIC("Blood.Green3Begin.Changed"), 0) || CVarGetInteger(CVAR_COSMETIC("Blood.Green3End.Changed"), 0); - COND_VB_SHOULD(VB_BLOOD_SET_COLOR_GREEN, hookEnabled, { - EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); - *should = false; - SetGreenBloodColor(effectSparkInit); - }); + if (previousHookState != hookEnabled) { + previousHookState = hookEnabled; + + COND_VB_SHOULD(VB_BLOOD_SET_COLOR_GREEN, hookEnabled, { + EffectSparkInit* effectSparkInit = va_arg(args, EffectSparkInit*); + *should = false; + SetGreenBloodColor(effectSparkInit); + }); + } } void RegisterCosmeticHooks() {