From 7662fa4c3cf7810b509d490fec9685a6cb5e9b1e Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Mon, 25 Nov 2024 13:21:45 -0500 Subject: [PATCH 01/28] fix readme link formatting (#4576) * fix readme link formatting * Update README.md * Update README.md * Update README.md * Update README.md --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c84059892..e7f929bad 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Official Website: https://www.shipofharkinian.com/ Official Discord: https://discord.com/invite/shipofharkinian -If you're having any trouble after reading through this `README`, feel free ask for help in the Support text channels. Please keep in mind that we do not condone piracy. +If you're having any trouble after reading through this `README`, feel free to ask for help in the Support text channels. Please keep in mind that we do not condone piracy. # Quick Start @@ -73,7 +73,7 @@ Congratulations, you are now sailing with the Ship of Harkinian! Have fun! # Project Overview Ship of Harkinian (SOH) is built atop a custom library dubbed libultraship (LUS). Back in the N64 days, there was an SDK distributed to developers named libultra; LUS is designed to mimic the functionality of libultra on modern hardware. In addition, we are dependant on the source code provided by the OOT decompilation project. -In order for the game to function, you will require a **legally aquired** ROM for Ocarina of Time. Click [here](https://ship.equipment/) to check the compatability of your specific rom. Any copyrighted assets are extracted from the ROM and reformated as a .otr archive file which the code uses. +In order for the game to function, you will require a **legally acquired** ROM for Ocarina of Time. Click [here](https://ship.equipment/) to check the compatibility of your specific rom. Any copyrighted assets are extracted from the ROM and reformatted as a .otr archive file which the code uses. ### Graphics Backends Currently, there are three rendering APIs supported: DirectX11 (Windows), OpenGL (all platforms), and Metal (MacOS). You can change which API to use in the `Settings` menu of the menubar, which requires a restart. If you're having an issue with crashing, you can change the API in the `shipofharkinian.json` file by finding the line `gfxbackend:""` and changing the value to `sdl` for OpenGL. DirectX 11 is the default on Windows. @@ -99,13 +99,13 @@ If you want to playtest a continuous integration build, you can find them at the * [Linux](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux.zip) ### Further Reading -More detailed documentation can be found in the 'docs' directory, including the afformentioned [building instructions](docs/BUILDING.md). +More detailed documentation can be found in the 'docs' directory, including the aforementioned [building instructions](docs/BUILDING.md). -*[Credits](docs/CREDITS.md) -*[Custom Music](docs/CUSTOM_MUSIC.md) -*[Controler Maping](docs/GAME_CONTROLLER_DB.md) -*[Modding](docs/MODDING.md) -*[Versioning](docs/VERSIONING.md) +* [Credits](docs/CREDITS.md) +* [Custom Music](docs/CUSTOM_MUSIC.md) +* [Controller Mapping](docs/GAME_CONTROLLER_DB.md) +* [Modding](docs/MODDING.md) +* [Versioning](docs/VERSIONING.md) <a href="https://github.com/Kenix3/libultraship/"> <picture> From 31120b71883f68e10368a9e6bd6c48f504b54999 Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Mon, 25 Nov 2024 20:36:35 -0700 Subject: [PATCH 02/28] Add master sword to ItemIDtoRandomizerGetMap to prevent assert crash in Return_Item after custom GIE was removed for MS. (#4584) --- soh/soh/OTRGlobals.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7f300476f..8fd817740 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -874,6 +874,7 @@ std::unordered_map<ItemID, RandomizerGet> ItemIDtoRandomizerGetMap { { ITEM_KOKIRI_EMERALD, RG_KOKIRI_EMERALD }, { ITEM_GORON_RUBY, RG_GORON_RUBY }, { ITEM_ZORA_SAPPHIRE, RG_ZORA_SAPPHIRE }, + { ITEM_SWORD_MASTER, RG_MASTER_SWORD }, }; extern "C" RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID) { From d0f7d30c163ca56229c0c469b5a7fa005d97e0e6 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 26 Nov 2024 19:43:20 +0000 Subject: [PATCH 03/28] Fix OnePoint cutscenes, make Skip Glitch cutscenes into Exclude Glitch Cutscenes (#4575) * Fix OnePoint chutscenes, make skip glitch cutscenes into exclude cutscenes * address comments --- .../Enhancements/timesaver_hook_handlers.cpp | 23 +++++++------------ soh/soh/SohMenuBar.cpp | 4 ++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 9bc5fa523..03fc4593c 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -263,7 +263,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li // The switch in jabu that you are intended to press with a box to reach barrinade // can be skipped by either a frame perfect roll open or with OI // The One Point for that switch is used in common setups for the former and is required for the latter to work - if (actor->params == 14848 && gPlayState->sceneNum == SCENE_JABU_JABU && !CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)){ + if (actor->params == 14848 && gPlayState->sceneNum == SCENE_JABU_JABU && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)){ break; } BgBdanSwitch* switchActor = (BgBdanSwitch*)actor; @@ -280,18 +280,9 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li RateLimitedSuccessChime(); break; } - case ACTOR_BG_HIDAN_FWBIG: { - *should = false; - break; - } - case ACTOR_EN_EX_ITEM: { - *should = false; - break; - } - case ACTOR_EN_DNT_NOMAL: { - *should = false; - break; - } + case ACTOR_BG_HIDAN_FWBIG: + case ACTOR_EN_EX_ITEM: + case ACTOR_EN_DNT_NOMAL: case ACTOR_EN_DNT_DEMO: { *should = false; break; @@ -311,6 +302,8 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li case ACTOR_BG_SPOT18_BASKET: case ACTOR_BG_HIDAN_CURTAIN: case ACTOR_BG_MORI_HINERI: + case ACTOR_BG_MIZU_SHUTTER: + case ACTOR_SHOT_SUN: *should = false; RateLimitedSuccessChime(); break; @@ -786,7 +779,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { // or poes from which the cutscene is triggered until we can have a "BeforeActorInit" hook. // So for now we're just going to set the flag before they get to the room the cutscene is in if (gPlayState->sceneNum == SCENE_FOREST_TEMPLE && actor->id == ACTOR_EN_ST && !Flags_GetSwitch(gPlayState, 0x1B)) { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), 0) && !CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { Flags_SetSwitch(gPlayState, 0x1B); } } @@ -812,7 +805,7 @@ void TimeSaverOnActorInitHandler(void* actorRef) { // Fire Temple Darunia cutscene if (actor->id == ACTOR_EN_DU && gPlayState->sceneNum == SCENE_FIRE_TEMPLE) { - if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), 0) && !CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) { Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); Actor_Kill(actor); } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 28a0c1c26..b19749fb2 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -681,8 +681,8 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, IS_RANDO); - UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); - UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS"); + UIWidgets::PaddedEnhancementCheckbox("Exclude Glitch-Aiding Cutscenes", CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, 0); + UIWidgets::Tooltip("Don't skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS, Forest Temple Poe Sisters CS and the Box Skip One Point in Jabu"); UIWidgets::PaddedEnhancementCheckbox("Skip Child Stealth", CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); UIWidgets::Tooltip("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); UIWidgets::PaddedEnhancementCheckbox("Skip Tower Escape", CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), false, false, false, "", UIWidgets::CheckboxGraphics::Cross, false); From 7ccb3ac7c3be86c03202d8da9d28bcf4830f8473 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 26 Nov 2024 23:48:58 +0100 Subject: [PATCH 04/28] Cosmetics Changes (#4275) * Clean CosmeticsEditor.h * Add CosmeticsEditor_GetDefaultValue * Add message text cosmetics * Format cleanup * Remove dependency on 3drando random functions * Fix rainbow for every cosmetic * Add "Rainbow All" & "Un-Rainbow All" * Add HookshotChain cosmetic * Add Nayru's cosmetics * Add Farore's cosmetics * Add Din's cosmetics * Add Title card cosmetics * Update CosmeticsEditor.cpp * Add Copyright text cosmetic --- .../cosmetics/CosmeticsEditor.cpp | 986 ++++++++++-------- .../Enhancements/cosmetics/CosmeticsEditor.h | 23 +- soh/soh/Enhancements/debugconsole.cpp | 1 + soh/soh/UIWidgets.cpp | 2 +- soh/src/code/z_actor.c | 35 +- soh/src/code/z_message_PAL.c | 78 ++ soh/src/code/z_parameter.c | 7 +- soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c | 17 +- .../actors/ovl_Magic_Dark/z_magic_dark.c | 35 +- .../actors/ovl_Magic_Fire/z_magic_fire.c | 21 +- 10 files changed, 739 insertions(+), 466 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index fdbec131a..8a9f3d97a 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -8,8 +8,6 @@ #include <random> #include <math.h> #include <algorithm> -#include <libultraship/libultra/types.h> -#include "soh/Enhancements/randomizer/3drando/random.hpp" #include <libultraship/libultraship.h> #include "soh/UIWidgets.hpp" @@ -17,42 +15,55 @@ #include "soh/ResourceManagerHelpers.h" extern "C" { -#include <z64.h> -#include "macros.h" -#include "soh/cvar_prefixes.h" -extern PlayState* gPlayState; -#include "objects/object_link_boy/object_link_boy.h" -#include "objects/object_link_child/object_link_child.h" -#include "objects/object_gi_shield_3/object_gi_shield_3.h" -#include "objects/object_gi_heart/object_gi_heart.h" -#include "objects/object_gi_bow/object_gi_bow.h" -#include "objects/object_gi_bracelet/object_gi_bracelet.h" -#include "objects/object_gi_rupy/object_gi_rupy.h" -#include "objects/object_gi_magicpot/object_gi_magicpot.h" -#include "objects/object_gi_gloves/object_gi_gloves.h" -#include "objects/object_gi_hammer/object_gi_hammer.h" -#include "objects/object_gi_sutaru/object_gi_sutaru.h" -#include "objects/object_st/object_st.h" -#include "objects/object_gi_boomerang/object_gi_boomerang.h" -#include "objects/object_gi_liquid/object_gi_liquid.h" -#include "objects/object_gi_bow/object_gi_bow.h" -#include "objects/object_gi_hearts/object_gi_hearts.h" -#include "objects/gameplay_keep/gameplay_keep.h" -#include "objects/object_gi_sword_1/object_gi_sword_1.h" -#include "objects/object_gi_longsword/object_gi_longsword.h" -#include "objects/object_gi_clothes/object_gi_clothes.h" -#include "objects/object_gi_bomb_2/object_gi_bomb_2.h" -#include "objects/object_gla/object_gla.h" -#include "objects/object_toki_objects/object_toki_objects.h" -#include "objects/object_gi_pachinko/object_gi_pachinko.h" -#include "objects/object_trap/object_trap.h" -#include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" -#include "objects/object_gjyo_objects/object_gjyo_objects.h" -#include "textures/nintendo_rogo_static/nintendo_rogo_static.h" -#include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h" -u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); + #include "z64.h" + #include "macros.h" + #include "soh/cvar_prefixes.h" + #include "objects/object_link_boy/object_link_boy.h" + #include "objects/object_link_child/object_link_child.h" + #include "objects/object_gi_shield_3/object_gi_shield_3.h" + #include "objects/object_gi_heart/object_gi_heart.h" + #include "objects/object_gi_bow/object_gi_bow.h" + #include "objects/object_gi_bracelet/object_gi_bracelet.h" + #include "objects/object_gi_rupy/object_gi_rupy.h" + #include "objects/object_gi_magicpot/object_gi_magicpot.h" + #include "objects/object_gi_gloves/object_gi_gloves.h" + #include "objects/object_gi_hammer/object_gi_hammer.h" + #include "objects/object_gi_sutaru/object_gi_sutaru.h" + #include "objects/object_st/object_st.h" + #include "objects/object_gi_boomerang/object_gi_boomerang.h" + #include "objects/object_gi_liquid/object_gi_liquid.h" + #include "objects/object_gi_bow/object_gi_bow.h" + #include "objects/object_gi_hearts/object_gi_hearts.h" + #include "objects/gameplay_keep/gameplay_keep.h" + #include "objects/object_gi_sword_1/object_gi_sword_1.h" + #include "objects/object_gi_longsword/object_gi_longsword.h" + #include "objects/object_gi_clothes/object_gi_clothes.h" + #include "objects/object_gi_bomb_2/object_gi_bomb_2.h" + #include "objects/object_gla/object_gla.h" + #include "objects/object_toki_objects/object_toki_objects.h" + #include "objects/object_gi_pachinko/object_gi_pachinko.h" + #include "objects/object_trap/object_trap.h" + #include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" + #include "objects/object_gjyo_objects/object_gjyo_objects.h" + #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" + #include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h" + #include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" + #include "overlays/ovl_Magic_Wind/ovl_Magic_Wind.h" + #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" + extern PlayState* gPlayState; + void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); + void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const char* patchName, int destinationIndex, int sourceIndex); + void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); + u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); } +#define PATCH_GFX(path, name, cvar, index, instruction) \ + if (CVarGetInteger(cvar, 0)) { \ + ResourceMgr_PatchGfxByName(path, name, index, instruction); \ + } else { \ + ResourceMgr_UnpatchGfxByName(path, name); \ + } + // This is used for the greg bridge #define dgEndGrayscaleAndEndDlistDL "__OTR__helpers/cosmetics/gEndGrayscaleAndEndDlistDL" static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL; @@ -74,7 +85,8 @@ std::map<CosmeticGroup, const char*> groupLabels = { { COSMETICS_GROUP_SPIN_ATTACK, "Spin Attack" }, { COSMETICS_GROUP_TRAILS, "Trails" }, { COSMETICS_GROUP_NAVI, "Navi" }, - { COSMETICS_GROUP_IVAN, "Ivan" } + { COSMETICS_GROUP_IVAN, "Ivan" }, + { COSMETICS_GROUP_MESSAGE, "Message" }, }; typedef struct { @@ -91,11 +103,11 @@ typedef struct { bool advancedOption; } CosmeticOption; -#define COSMETIC_OPTION(id, label, group, defaultColor, supportsAlpha, supportsRainbow, advancedOption) \ - { id, { \ +#define COSMETIC_OPTION(id, label, group, defaultColor, supportsAlpha, supportsRainbow, advancedOption) \ + { id, { \ CVAR_COSMETIC(id ".Value"), CVAR_COSMETIC(id ".Rainbow"), CVAR_COSMETIC(id ".Locked"), CVAR_COSMETIC(id ".Changed"), label, group, \ - defaultColor, defaultColor, \ - supportsAlpha, supportsRainbow, advancedOption \ + defaultColor, defaultColor, \ + supportsAlpha, supportsRainbow, advancedOption \ } } /* @@ -172,195 +184,250 @@ typedef struct { colors were darker than the gDPSetPrimColor. You will see many more examples of this below in the `ApplyOrResetCustomGfxPatches` method */ static std::map<std::string, CosmeticOption> cosmeticOptions = { - COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), - COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), - COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), - COSMETIC_OPTION("Link.Hair", "Hair", COSMETICS_GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), - COSMETIC_OPTION("Link.Linen", "Linen", COSMETICS_GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Link.Boots", "Boots", COSMETICS_GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), + COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), + COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), + COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), + COSMETIC_OPTION("Link.Hair", "Hair", COSMETICS_GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), + COSMETIC_OPTION("Link.Linen", "Linen", COSMETICS_GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Link.Boots", "Boots", COSMETICS_GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), - COSMETIC_OPTION("MirrorShield.Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), - COSMETIC_OPTION("MirrorShield.Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("MirrorShield.Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield.Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), + COSMETIC_OPTION("MirrorShield.Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield.Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), - COSMETIC_OPTION("Swords.KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords.KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords.MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords.MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords.BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Swords.BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords.KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Swords.MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Swords.BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + /* Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Swords.KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), + COSMETIC_OPTION("Swords.MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), + COSMETIC_OPTION("Swords.BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), + */ - COSMETIC_OPTION("Gloves.GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), - COSMETIC_OPTION("Gloves.SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Gloves.GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), - COSMETIC_OPTION("Gloves.GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), + COSMETIC_OPTION("Gloves.GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), + COSMETIC_OPTION("Gloves.SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Gloves.GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), + COSMETIC_OPTION("Gloves.GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), - COSMETIC_OPTION("Equipment.BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), - COSMETIC_OPTION("Equipment.BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), - // COSMETIC_OPTION("Equipment.SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), // Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Equipment.SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment.HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), - COSMETIC_OPTION("Equipment.HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), - // COSMETIC_OPTION("Equipment.HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Equipment.HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement - COSMETIC_OPTION("HookshotReticle.Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, false, false), - COSMETIC_OPTION("HookshotReticle.NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, false, false), - COSMETIC_OPTION("Equipment.BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Equipment.BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment.BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), - COSMETIC_OPTION("Equipment.BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment.ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), - COSMETIC_OPTION("Equipment.ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), - COSMETIC_OPTION("Equipment.BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), + COSMETIC_OPTION("Equipment.BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), + COSMETIC_OPTION("Equipment.BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), + /* Todo (Cosmetics): Broken, need a better way to grayscale + COSMETIC_OPTION("Equipment.SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), + */ + COSMETIC_OPTION("Equipment.SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), + COSMETIC_OPTION("Equipment.HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment.HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + /* Todo (Cosmetics): Implement + COSMETIC_OPTION("Equipment.HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), + */ + COSMETIC_OPTION("HookshotReticle.Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, true, false), + COSMETIC_OPTION("HookshotReticle.NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Equipment.BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment.BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), + COSMETIC_OPTION("Equipment.BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), + COSMETIC_OPTION("Equipment.ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), + COSMETIC_OPTION("Equipment.BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), - COSMETIC_OPTION("Consumable.Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), - COSMETIC_OPTION("Consumable.HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), - COSMETIC_OPTION("Consumable.DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), - COSMETIC_OPTION("Consumable_MagicInfinite", "Infinite Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 0, 200, 255), false, true, true), - COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), - COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), - COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable.BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable.PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), - COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), + COSMETIC_OPTION("Consumable.HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), + COSMETIC_OPTION("Consumable.DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), + COSMETIC_OPTION("Consumable_MagicInfinite", "Infinite Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 0, 200, 255), false, true, true), + COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable.BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable.PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), + COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("HUD.AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), - COSMETIC_OPTION("HUD.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), - COSMETIC_OPTION("HUD.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("HUD.Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), - COSMETIC_OPTION("HUD.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("HUD.Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), - COSMETIC_OPTION("HUD.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, false, true), - COSMETIC_OPTION("HUD.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), - COSMETIC_OPTION("HUD.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4(0, 0, 0, 80), true, false, true), - // Todo (Cosmetics): re-implement title card colors + COSMETIC_OPTION("HUD.AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), + COSMETIC_OPTION("HUD.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("HUD.Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), + COSMETIC_OPTION("HUD.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, true), + COSMETIC_OPTION("HUD.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), + COSMETIC_OPTION("HUD.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4( 0, 0, 0, 80), true, true, true), + COSMETIC_OPTION("HUD.TitleCard.Map", "Map Title Card", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.TitleCard.Boss", "Boss Title Card", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, false), - COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kaleido.ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kaleido.ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), + #define MESSAGE_COSMETIC_OPTION(id, label, r, g, b) COSMETIC_OPTION("Message." id, label, COSMETICS_GROUP_MESSAGE, ImVec4(r, g, b, 255), false, true, true) - COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 40, 255), false, true, false), - COSMETIC_OPTION("Kaleido.EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4(90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4(10, 50, 80, 255), false, true, true), + MESSAGE_COSMETIC_OPTION("Default.Normal", "Message Default Color", 255, 255, 255), + MESSAGE_COSMETIC_OPTION("Default.NoneNoShadow", "Message Default (None No Shadow) Color", 0, 0, 0), + MESSAGE_COSMETIC_OPTION("Red.Normal", "Message Red Color", 255, 60, 60), + MESSAGE_COSMETIC_OPTION("Red.Wooden", "Message Red (Wooden) Color", 255, 120, 0), + MESSAGE_COSMETIC_OPTION("Adjustable.Normal", "Message Adjustable Color", 70, 255, 80), + MESSAGE_COSMETIC_OPTION("Adjustable.Wooden", "Message Adjustable (Wooden) Color", 70, 255, 80), + MESSAGE_COSMETIC_OPTION("Blue.Normal", "Message Blue Color", 80, 90, 255), + MESSAGE_COSMETIC_OPTION("Blue.Wooden", "Message Blue (Wooden) Color", 80, 110, 255), + MESSAGE_COSMETIC_OPTION("LightBlue.Normal", "Message Light Blue Color", 100, 180, 255), + MESSAGE_COSMETIC_OPTION("LightBlue.Wooden", "Message Light Blue (Wooden) Color", 90, 180, 255), + MESSAGE_COSMETIC_OPTION("LightBlue.LightBlue.NoneNoShadow", "Message Light Blue (None No Shadow) Color", 80, 150, 180), + MESSAGE_COSMETIC_OPTION("Purple.Normal", "Message Purple Color", 255, 150, 180), + MESSAGE_COSMETIC_OPTION("Purple.Wooden", "Message Purple (Wooden) Color", 210, 100, 255), + MESSAGE_COSMETIC_OPTION("Yellow.Normal", "Message Yellow Color", 255, 255, 50), + MESSAGE_COSMETIC_OPTION("Yellow.Wooden", "Message Yellow (Wooden) Color", 255, 255, 30), + MESSAGE_COSMETIC_OPTION("Black", "Message Black Color", 0, 0, 0), - COSMETIC_OPTION("Kaleido.MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + #undef MESSAGE_COSMETIC_OPTION - COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, false), - COSMETIC_OPTION("Kaleido.QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kaleido.QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kaleido.QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 80, 50, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4( 70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4( 70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, false), - COSMETIC_OPTION("Kaleido.MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ImVec4(80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 40, 255), false, true, false), + COSMETIC_OPTION("Kaleido.EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4( 90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4( 90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, false), - COSMETIC_OPTION("Kaleido.SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kaleido.SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kaleido.SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ImVec4(50, 50, 50, 255), false, true, true), - - COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ImVec4(90,100,130,255), true, true, false), - - COSMETIC_OPTION("Title.FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Title.NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), - // COSMETIC_OPTION("Title.FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), // Todo (Cosmetics): Kinda complicated - // COSMETIC_OPTION("Title.FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), // Todo (Cosmetics): Kinda complicated - - COSMETIC_OPTION("Arrows.NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows.NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("Arrows.FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows.FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Arrows.IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), - COSMETIC_OPTION("Arrows.IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Arrows.LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Arrows.LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), - - // COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), - // COSMETIC_OPTION("Magic.FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic.FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Implement - // COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, false), - // COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 255, 255), false, true, true), - - COSMETIC_OPTION("SpinAttack.Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), - COSMETIC_OPTION("SpinAttack.Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), - COSMETIC_OPTION("SpinAttack.Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("SpinAttack.Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), - - COSMETIC_OPTION("Trails.Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Trails.Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), - COSMETIC_OPTION("Trails.KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails.MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails.BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails.Stick", "Stick", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails.Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - - COSMETIC_OPTION("World.BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), - COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), - COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), - COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ImVec4(0, 60, 100, 255), false, true, false), - - COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), - COSMETIC_OPTION("Navi.NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Navi.NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), - COSMETIC_OPTION("Navi.EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi.EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), - COSMETIC_OPTION("Navi.PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi.PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Ivan.IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Ivan.IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kaleido.QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 80, 50, 255), false, true, true), - COSMETIC_OPTION("NPC.FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC.IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kaleido.MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, true), + + COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ImVec4( 50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kaleido.SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 50, 50, 50, 255), false, true, true), + + COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ImVec4( 90, 100, 130, 255), true, true, false), + + COSMETIC_OPTION("Title.FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Title.NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), + + /* Todo (Cosmetics): Kinda complicated + COSMETIC_OPTION("Title.FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), + COSMETIC_OPTION("Title.FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), + */ + COSMETIC_OPTION("Title.Copyright", "Copyright Text", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 255, 255), true, true, false), + + COSMETIC_OPTION("Arrows.NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows.NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("Arrows.FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows.FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Arrows.IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), + COSMETIC_OPTION("Arrows.IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Arrows.LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Arrows.LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), + + COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 200, 0, 255), false, true, false), + COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Magic.FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Magic.FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(100, 200, 0, 255), false, true, true), + COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(170, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4( 0, 100, 255, 255), false, true, true), + + COSMETIC_OPTION("SpinAttack.Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), + COSMETIC_OPTION("SpinAttack.Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), + COSMETIC_OPTION("SpinAttack.Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("SpinAttack.Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), + + COSMETIC_OPTION("Trails.Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Trails.Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), + COSMETIC_OPTION("Trails.KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails.MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails.BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Stick", "Stick", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + + COSMETIC_OPTION("World.BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), + COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), + COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ImVec4( 0, 60, 100, 255), false, true, false), + + COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), + COSMETIC_OPTION("Navi.NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Navi.NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), + COSMETIC_OPTION("Navi.EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi.EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), + COSMETIC_OPTION("Navi.PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi.PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), + + COSMETIC_OPTION("Ivan.IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Ivan.IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), + + COSMETIC_OPTION("NPC.FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Health fairy - COSMETIC_OPTION("NPC.Dog1", "Dog 1", COSMETICS_GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), - COSMETIC_OPTION("NPC.Dog2", "Dog 2", COSMETICS_GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), - COSMETIC_OPTION("NPC.GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), - COSMETIC_OPTION("NPC.Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), - COSMETIC_OPTION("NPC.MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC.IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), + COSMETIC_OPTION("NPC.Dog1", "Dog 1", COSMETICS_GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), + COSMETIC_OPTION("NPC.Dog2", "Dog 2", COSMETICS_GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), + COSMETIC_OPTION("NPC.GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), + COSMETIC_OPTION("NPC.Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), + COSMETIC_OPTION("NPC.MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), }; static const char* MarginCvarList[] { - CVAR_COSMETIC("HUD.Hearts"), CVAR_COSMETIC("HUD.HeartsCount"), CVAR_COSMETIC("HUD.MagicBar"), CVAR_COSMETIC("HUD.VisualSoA"), CVAR_COSMETIC("HUD.BButton"), CVAR_COSMETIC("HUD.AButton"), CVAR_COSMETIC("HUD.StartButton"), - CVAR_COSMETIC("HUD.CUpButton"), CVAR_COSMETIC("HUD.CDownButton"), CVAR_COSMETIC("HUD.CLeftButton"), CVAR_COSMETIC("HUD.CRightButton"), CVAR_COSMETIC("HUD.Dpad"), CVAR_COSMETIC("HUD.Minimap"), - CVAR_COSMETIC("HUD.SmallKey"), CVAR_COSMETIC("HUD.Rupees"), CVAR_COSMETIC("HUD.Carrots"), CVAR_COSMETIC("HUD.Timers"), CVAR_COSMETIC("HUD.ArcheryScore"), CVAR_COSMETIC("HUD.TitleCard.Map"), CVAR_COSMETIC("HUD.TitleCard.Boss"), CVAR_COSMETIC("HUD.IGT") + CVAR_COSMETIC("HUD.Hearts"), + CVAR_COSMETIC("HUD.HeartsCount"), + CVAR_COSMETIC("HUD.MagicBar"), + CVAR_COSMETIC("HUD.VisualSoA"), + CVAR_COSMETIC("HUD.BButton"), + CVAR_COSMETIC("HUD.AButton"), + CVAR_COSMETIC("HUD.StartButton"), + CVAR_COSMETIC("HUD.CUpButton"), + CVAR_COSMETIC("HUD.CDownButton"), + CVAR_COSMETIC("HUD.CLeftButton"), + CVAR_COSMETIC("HUD.CRightButton"), + CVAR_COSMETIC("HUD.Dpad"), + CVAR_COSMETIC("HUD.Minimap"), + CVAR_COSMETIC("HUD.SmallKey"), + CVAR_COSMETIC("HUD.Rupees"), + CVAR_COSMETIC("HUD.Carrots"), + CVAR_COSMETIC("HUD.Timers"), + CVAR_COSMETIC("HUD.ArcheryScore"), + CVAR_COSMETIC("HUD.TitleCard.Map"), + CVAR_COSMETIC("HUD.TitleCard.Boss"), + CVAR_COSMETIC("HUD.IGT") }; -static const char* MarginCvarNonAnchor[]{ CVAR_COSMETIC("HUD.Carrots"), CVAR_COSMETIC("HUD.Timers"), CVAR_COSMETIC("HUD.ArcheryScore"), CVAR_COSMETIC("HUD.TitleCard.Map"),CVAR_COSMETIC("HUD.TitleCard.Boss") }; -ImVec4 GetRandomValue(int MaximumPossible){ - ImVec4 NewColor; - unsigned long range = 255 - 0; +static const char* MarginCvarNonAnchor[] { + CVAR_COSMETIC("HUD.Carrots"), + CVAR_COSMETIC("HUD.Timers"), + CVAR_COSMETIC("HUD.ArcheryScore"), + CVAR_COSMETIC("HUD.TitleCard.Map"), + CVAR_COSMETIC("HUD.TitleCard.Boss") +}; + +ImVec4 GetRandomValue() { #if !defined(__SWITCH__) && !defined(__WIIU__) std::random_device rd; std::mt19937 rng(rd()); @@ -369,7 +436,8 @@ ImVec4 GetRandomValue(int MaximumPossible){ std::mt19937_64 rng(seed); #endif std::uniform_int_distribution<int> dist(0, 255 - 1); - + + ImVec4 NewColor; NewColor.x = (float)(dist(rng)) / 255; NewColor.y = (float)(dist(rng)) / 255; NewColor.z = (float)(dist(rng)) / 255; @@ -384,24 +452,22 @@ void SetMarginAll(const char* ButtonName, bool SetActivated) { std::string cvarPosType = std::string(cvarName).append(".PosType"); std::string cvarNameMargins = std::string(cvarName).append(".UseMargins"); if (CVarGetInteger(cvarPosType.c_str(),0) <= 2 && SetActivated) { //Our element is not Hidden or Non anchor - for (int i = 0; i < arrayLengthNonMargin; i++){ + for (int i = 0; i < arrayLengthNonMargin; i++) { if ((strcmp(cvarName, MarginCvarNonAnchor[i]) == 0) && (CVarGetInteger(cvarPosType.c_str(), 0) == 0)) { //Our element is both in original position and do not have anchor by default so we skip it. CVarSetInteger(cvarNameMargins.c_str(), false); //force set off - } - else if ((strcmp(cvarName, MarginCvarNonAnchor[i]) == 0) && (CVarGetInteger(cvarPosType.c_str(), 0) != 0)) { //Our element is not in original position regarless it has no anchor by default since player made it anchored we can toggle margins + } else if ((strcmp(cvarName, MarginCvarNonAnchor[i]) == 0) && (CVarGetInteger(cvarPosType.c_str(), 0) != 0)) { //Our element is not in original position regarless it has no anchor by default since player made it anchored we can toggle margins CVarSetInteger(cvarNameMargins.c_str(), SetActivated); - } - else if (strcmp(cvarName, MarginCvarNonAnchor[i]) != 0) { //Our elements has an anchor by default so regarless of it's position right now that okay to toggle margins. + } else if (strcmp(cvarName, MarginCvarNonAnchor[i]) != 0) { //Our elements has an anchor by default so regarless of it's position right now that okay to toggle margins. CVarSetInteger(cvarNameMargins.c_str(), SetActivated); } } - } - else { //Since the user requested to turn all margin off no need to do any check there. + } else { //Since the user requested to turn all margin off no need to do any check there. CVarSetInteger(cvarNameMargins.c_str(), SetActivated); } } } } + void ResetPositionAll() { if (ImGui::Button("Reset all positions")) { for (auto cvarName : MarginCvarList) { @@ -443,12 +509,14 @@ void CosmeticsUpdateTick() { // Technically this would work if you replaced "60" with 1 but the hue would be so close it's // indistinguishable, 60 gives us a big enough gap to notice the difference. if (!CVarGetInteger(CVAR_COSMETIC("RainbowSync"), 0)) { - index+= (60 * rainbowSpeed); + index += (60 * rainbowSpeed); } } ApplyOrResetCustomGfxPatches(false); hue++; - if (hue >= (360 * rainbowSpeed)) hue = 0; + if (hue >= (360 * rainbowSpeed)) { + hue = 0; + } } /* @@ -461,6 +529,22 @@ void CosmeticsUpdateTick() { 5. GFX Command: The GFX command you want to insert */ void ApplyOrResetCustomGfxPatches(bool manualChange) { + static CosmeticOption& magicFaroresPrimary = cosmeticOptions.at("Magic.FaroresPrimary"); + if (manualChange || CVarGetInteger(magicFaroresPrimary.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {magicFaroresPrimary.defaultColor.x, magicFaroresPrimary.defaultColor.y, magicFaroresPrimary.defaultColor.z, magicFaroresPrimary.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(magicFaroresPrimary.cvar, defaultColor); + PATCH_GFX(sInnerCylinderDL, "Magic_FaroresPrimary1", magicFaroresPrimary.changedCvar, 24, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(sOuterCylinderDL, "Magic_FaroresPrimary2", magicFaroresPrimary.changedCvar, 24, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + } + + static CosmeticOption& magicFaroresSecondary = cosmeticOptions.at("Magic.FaroresSecondary"); + if (manualChange || CVarGetInteger(magicFaroresSecondary.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {magicFaroresSecondary.defaultColor.x, magicFaroresSecondary.defaultColor.y, magicFaroresSecondary.defaultColor.z, magicFaroresSecondary.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(magicFaroresSecondary.cvar, defaultColor); + PATCH_GFX(sInnerCylinderDL, "Magic_FaroresSecondary1", magicFaroresSecondary.changedCvar, 25, gsDPSetEnvColor(color.r, color.g, color.b, 255)); + PATCH_GFX(sOuterCylinderDL, "Magic_FaroresSecondary2", magicFaroresSecondary.changedCvar, 25, gsDPSetEnvColor(color.r, color.g, color.b, 255)); + } + static CosmeticOption& linkGoronTunic = cosmeticOptions.at("Link.GoronTunic"); if (manualChange || CVarGetInteger(linkGoronTunic.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {linkGoronTunic.defaultColor.x, linkGoronTunic.defaultColor.y, linkGoronTunic.defaultColor.z, linkGoronTunic.defaultColor.w}; @@ -491,16 +575,16 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultHeadFarDL, "Link_Hair4", linkHair.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); if (manualChange) { - PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair5", linkHair.changedCvar, 46, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair6", linkHair.changedCvar, 54, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair7", linkHair.changedCvar, 136, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair8", linkHair.changedCvar, 162, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildHeadFarDL, "Link_Hair9", linkHair.changedCvar, 101, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildHeadFarDL, "Link_Hair10", linkHair.changedCvar, 118, gsSPGrayscale(false)); - PATCH_GFX(gLinkAdultHeadNearDL, "Link_Hair11", linkHair.changedCvar, 125, gsSPGrayscale(true)); - PATCH_GFX(gLinkAdultHeadNearDL, "Link_Hair12", linkHair.changedCvar, 159, gsSPGrayscale(false)); - PATCH_GFX(gLinkAdultHeadFarDL, "Link_Hair13", linkHair.changedCvar, 102, gsSPGrayscale(true)); - PATCH_GFX(gLinkAdultHeadFarDL, "Link_Hair14", linkHair.changedCvar, 122, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair5", linkHair.changedCvar, 46, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair6", linkHair.changedCvar, 54, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair7", linkHair.changedCvar, 136, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair8", linkHair.changedCvar, 162, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildHeadFarDL, "Link_Hair9", linkHair.changedCvar, 101, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildHeadFarDL, "Link_Hair10", linkHair.changedCvar, 118, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultHeadNearDL, "Link_Hair11", linkHair.changedCvar, 125, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultHeadNearDL, "Link_Hair12", linkHair.changedCvar, 159, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultHeadFarDL, "Link_Hair13", linkHair.changedCvar, 102, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultHeadFarDL, "Link_Hair14", linkHair.changedCvar, 122, gsSPGrayscale(false)); } } @@ -532,17 +616,17 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultLeftLegFarDL, "Link_Linen22", linkLinen.changedCvar, 30, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); if (manualChange) { - PATCH_GFX(gLinkAdultLeftArmFarDL, "Link_Linen23", linkLinen.changedCvar, 35, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultLeftArmOutNearDL, "Link_Linen24", linkLinen.changedCvar, 45, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultLeftArmNearDL, "Link_Linen25", linkLinen.changedCvar, 40, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultLeftArmFarDL, "Link_Linen26", linkLinen.changedCvar, 77, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultRightArmFarDL, "Link_Linen27", linkLinen.changedCvar, 35, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultRightArmFarDL, "Link_Linen28", linkLinen.changedCvar, 77, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultRightArmNearDL, "Link_Linen29", linkLinen.changedCvar, 42, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultRightLegNearDL, "Link_Linen30", linkLinen.changedCvar, 43, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultLeftLegNearDL, "Link_Linen31", linkLinen.changedCvar, 43, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultRightLegFarDL, "Link_Linen32", linkLinen.changedCvar, 38, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); - PATCH_GFX(gLinkAdultLeftLegFarDL, "Link_Linen33", linkLinen.changedCvar, 38, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultLeftArmFarDL, "Link_Linen23", linkLinen.changedCvar, 35, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultLeftArmOutNearDL, "Link_Linen24", linkLinen.changedCvar, 45, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultLeftArmNearDL, "Link_Linen25", linkLinen.changedCvar, 40, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultLeftArmFarDL, "Link_Linen26", linkLinen.changedCvar, 77, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultRightArmFarDL, "Link_Linen27", linkLinen.changedCvar, 35, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultRightArmFarDL, "Link_Linen28", linkLinen.changedCvar, 77, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultRightArmNearDL, "Link_Linen29", linkLinen.changedCvar, 42, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultRightLegNearDL, "Link_Linen30", linkLinen.changedCvar, 43, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultLeftLegNearDL, "Link_Linen31", linkLinen.changedCvar, 43, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultRightLegFarDL, "Link_Linen32", linkLinen.changedCvar, 38, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); + PATCH_GFX(gLinkAdultLeftLegFarDL, "Link_Linen33", linkLinen.changedCvar, 38, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)); } } @@ -556,30 +640,30 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultRightLegFarDL, "Link_Boots4", linkBoots.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); if (manualChange) { - PATCH_GFX(gLinkChildRightShinNearDL, "Link_Boots5", linkBoots.changedCvar, 53, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildRightShinNearDL, "Link_Boots6", linkBoots.changedCvar, 69, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildRightShinFarDL, "Link_Boots7", linkBoots.changedCvar, 52, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildRightShinFarDL, "Link_Boots8", linkBoots.changedCvar, 61, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildLeftShinNearDL, "Link_Boots9", linkBoots.changedCvar, 53, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildLeftShinNearDL, "Link_Boots10", linkBoots.changedCvar, 69, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildLeftShinFarDL, "Link_Boots11", linkBoots.changedCvar, 52, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildLeftShinFarDL, "Link_Boots12", linkBoots.changedCvar, 61, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildRightFootNearDL, "Link_Boots13", linkBoots.changedCvar, 30, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildRightFootFarDL, "Link_Boots14", linkBoots.changedCvar, 30, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildLeftFootNearDL, "Link_Boots15", linkBoots.changedCvar, 30, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildLeftFootFarDL, "Link_Boots16", linkBoots.changedCvar, 30, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildLeftThighNearDL, "Link_Boots17", linkBoots.changedCvar, 10, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildLeftThighFarDL, "Link_Boots18", linkBoots.changedCvar, 10, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildHeadNearDL, "Link_Boots19", linkBoots.changedCvar, 20, gsSPGrayscale(false)); - PATCH_GFX(gLinkChildHeadFarDL, "Link_Boots20", linkBoots.changedCvar, 20, gsSPGrayscale(false)); - PATCH_GFX(gLinkAdultRightLegNearDL, "Link_Boots21", linkBoots.changedCvar, 57, gsSPGrayscale(true)); - PATCH_GFX(gLinkAdultRightLegFarDL, "Link_Boots22", linkBoots.changedCvar, 52, gsSPGrayscale(true)); - PATCH_GFX(gLinkAdultLeftLegNearDL, "Link_Boots23", linkBoots.changedCvar, 57, gsSPGrayscale(true)); - PATCH_GFX(gLinkAdultLeftLegFarDL, "Link_Boots24", linkBoots.changedCvar, 52, gsSPGrayscale(true)); - PATCH_GFX(gLinkAdultLeftThighNearDL, "Link_Boots25", linkBoots.changedCvar, 10, gsSPGrayscale(false)); - PATCH_GFX(gLinkAdultLeftThighFarDL, "Link_Boots26", linkBoots.changedCvar, 10, gsSPGrayscale(false)); - PATCH_GFX(gLinkAdultHeadNearDL, "Link_Boots27", linkBoots.changedCvar, 20, gsSPGrayscale(false)); - PATCH_GFX(gLinkAdultHeadFarDL, "Link_Boots28", linkBoots.changedCvar, 20, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildRightShinNearDL, "Link_Boots5", linkBoots.changedCvar, 53, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildRightShinNearDL, "Link_Boots6", linkBoots.changedCvar, 69, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildRightShinFarDL, "Link_Boots7", linkBoots.changedCvar, 52, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildRightShinFarDL, "Link_Boots8", linkBoots.changedCvar, 61, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildLeftShinNearDL, "Link_Boots9", linkBoots.changedCvar, 53, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftShinNearDL, "Link_Boots10", linkBoots.changedCvar, 69, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildLeftShinFarDL, "Link_Boots11", linkBoots.changedCvar, 52, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftShinFarDL, "Link_Boots12", linkBoots.changedCvar, 61, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildRightFootNearDL, "Link_Boots13", linkBoots.changedCvar, 30, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildRightFootFarDL, "Link_Boots14", linkBoots.changedCvar, 30, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftFootNearDL, "Link_Boots15", linkBoots.changedCvar, 30, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftFootFarDL, "Link_Boots16", linkBoots.changedCvar, 30, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftThighNearDL, "Link_Boots17", linkBoots.changedCvar, 10, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildLeftThighFarDL, "Link_Boots18", linkBoots.changedCvar, 10, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildHeadNearDL, "Link_Boots19", linkBoots.changedCvar, 20, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildHeadFarDL, "Link_Boots20", linkBoots.changedCvar, 20, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultRightLegNearDL, "Link_Boots21", linkBoots.changedCvar, 57, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultRightLegFarDL, "Link_Boots22", linkBoots.changedCvar, 52, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftLegNearDL, "Link_Boots23", linkBoots.changedCvar, 57, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftLegFarDL, "Link_Boots24", linkBoots.changedCvar, 52, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftThighNearDL, "Link_Boots25", linkBoots.changedCvar, 10, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultLeftThighFarDL, "Link_Boots26", linkBoots.changedCvar, 10, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultHeadNearDL, "Link_Boots27", linkBoots.changedCvar, 20, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultHeadFarDL, "Link_Boots28", linkBoots.changedCvar, 20, gsSPGrayscale(false)); } } @@ -632,47 +716,49 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriBlade3", swordsKokiriBlade.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriBlade4", swordsKokiriBlade.changedCvar, 6, gsDPSetEnvColor(color.r / 4, color.g / 4, color.b / 4, 255)); } - // static CosmeticOption& swordsKokiriHilt = cosmeticOptions.at("Swords.KokiriHilt"); - // if (manualChange || CVarGetInteger(swordsKokiriHilt.rainbowCvar, 0)) { - // static Color_RGBA8 defaultColor = {swordsKokiriHilt.defaultColor.x, swordsKokiriHilt.defaultColor.y, swordsKokiriHilt.defaultColor.z, swordsKokiriHilt.defaultColor.w}; - // Color_RGBA8 color = CVarGetColor(swordsKokiriHilt.cvar, defaultColor); - // PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt1", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt2", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt3", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt4", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt5", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt6", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt7", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt8", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt9", swordsKokiriHilt.changedCvar, 64, gsDPSetPrimColor(0, 0, MAX(color.r - 50, 0), MAX(color.g - 50, 0), MAX(color.b - 50, 0), 255)); - // PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt10", swordsKokiriHilt.changedCvar, 66, gsDPSetEnvColor(MAX(color.r - 50, 0) / 3, MAX(color.g - 50, 0) / 3, MAX(color.b - 50, 0) / 3, 255)); - // PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt11", swordsKokiriHilt.changedCvar, 162, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt12", swordsKokiriHilt.changedCvar, 164, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); + /* + static CosmeticOption& swordsKokiriHilt = cosmeticOptions.at("Swords.KokiriHilt"); + if (manualChange || CVarGetInteger(swordsKokiriHilt.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {swordsKokiriHilt.defaultColor.x, swordsKokiriHilt.defaultColor.y, swordsKokiriHilt.defaultColor.z, swordsKokiriHilt.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(swordsKokiriHilt.cvar, defaultColor); + PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt1", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt2", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt3", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt4", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt5", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt6", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt7", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt8", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt9", swordsKokiriHilt.changedCvar, 64, gsDPSetPrimColor(0, 0, MAX(color.r - 50, 0), MAX(color.g - 50, 0), MAX(color.b - 50, 0), 255)); + PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt10", swordsKokiriHilt.changedCvar, 66, gsDPSetEnvColor(MAX(color.r - 50, 0) / 3, MAX(color.g - 50, 0) / 3, MAX(color.b - 50, 0) / 3, 255)); + PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt11", swordsKokiriHilt.changedCvar, 162, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriHilt12", swordsKokiriHilt.changedCvar, 164, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); - // if (manualChange) { - // PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt13", swordsKokiriHilt.changedCvar, 108, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt14", swordsKokiriHilt.changedCvar, 134, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt15", swordsKokiriHilt.changedCvar, 106, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt16", swordsKokiriHilt.changedCvar, 126, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt17", swordsKokiriHilt.changedCvar, 100, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt18", swordsKokiriHilt.changedCvar, 126, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt19", swordsKokiriHilt.changedCvar, 128, gsSPEndDisplayList()); - // PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt20", swordsKokiriHilt.changedCvar, 98, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt21", swordsKokiriHilt.changedCvar, 118, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt22", swordsKokiriHilt.changedCvar, 120, gsSPEndDisplayList()); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt23", swordsKokiriHilt.changedCvar, 166, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt24", swordsKokiriHilt.changedCvar, 192, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt25", swordsKokiriHilt.changedCvar, 194, gsSPEndDisplayList()); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt26", swordsKokiriHilt.changedCvar, 156, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt27", swordsKokiriHilt.changedCvar, 176, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt28", swordsKokiriHilt.changedCvar, 178, gsSPEndDisplayList()); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt29", swordsKokiriHilt.changedCvar, 162, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt30", swordsKokiriHilt.changedCvar, 188, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt31", swordsKokiriHilt.changedCvar, 190, gsSPEndDisplayList()); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt32", swordsKokiriHilt.changedCvar, 98, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt33", swordsKokiriHilt.changedCvar, 118, gsSPGrayscale(false)); - // } - // } + if (manualChange) { + PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt13", swordsKokiriHilt.changedCvar, 108, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt14", swordsKokiriHilt.changedCvar, 134, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt15", swordsKokiriHilt.changedCvar, 106, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt16", swordsKokiriHilt.changedCvar, 126, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt17", swordsKokiriHilt.changedCvar, 100, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt18", swordsKokiriHilt.changedCvar, 126, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt19", swordsKokiriHilt.changedCvar, 128, gsSPEndDisplayList()); + PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt20", swordsKokiriHilt.changedCvar, 98, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt21", swordsKokiriHilt.changedCvar, 118, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildSwordAndSheathFarDL, "Swords_KokiriHilt22", swordsKokiriHilt.changedCvar, 120, gsSPEndDisplayList()); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt23", swordsKokiriHilt.changedCvar, 166, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt24", swordsKokiriHilt.changedCvar, 192, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathNearDL, "Swords_KokiriHilt25", swordsKokiriHilt.changedCvar, 194, gsSPEndDisplayList()); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt26", swordsKokiriHilt.changedCvar, 156, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt27", swordsKokiriHilt.changedCvar, 176, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildDekuShieldSwordAndSheathFarDL, "Swords_KokiriHilt28", swordsKokiriHilt.changedCvar, 178, gsSPEndDisplayList()); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt29", swordsKokiriHilt.changedCvar, 162, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt30", swordsKokiriHilt.changedCvar, 188, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathNearDL, "Swords_KokiriHilt31", swordsKokiriHilt.changedCvar, 190, gsSPEndDisplayList()); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt32", swordsKokiriHilt.changedCvar, 98, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildHylianShieldSwordAndSheathFarDL, "Swords_KokiriHilt33", swordsKokiriHilt.changedCvar, 118, gsSPGrayscale(false)); + } + } + */ static CosmeticOption& swordsMasterBlade = cosmeticOptions.at("Swords.MasterBlade"); if (manualChange || CVarGetInteger(swordsMasterBlade.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {swordsMasterBlade.defaultColor.x, swordsMasterBlade.defaultColor.y, swordsMasterBlade.defaultColor.z, swordsMasterBlade.defaultColor.w}; @@ -684,53 +770,55 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterBlade5", swordsMasterBlade.changedCvar, 13, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterBlade6", swordsMasterBlade.changedCvar, 14, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); } - // static CosmeticOption& swordsMasterHilt = cosmeticOptions.at("Swords.MasterHilt"); - // if (manualChange || CVarGetInteger(swordsMasterHilt.rainbowCvar, 0)) { - // static Color_RGBA8 defaultColor = {swordsMasterHilt.defaultColor.x, swordsMasterHilt.defaultColor.y, swordsMasterHilt.defaultColor.z, swordsMasterHilt.defaultColor.w}; - // Color_RGBA8 color = CVarGetColor(swordsMasterHilt.cvar, defaultColor); - // PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt1", swordsMasterHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt2", swordsMasterHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt3", swordsMasterHilt.changedCvar, 16, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt4", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt5", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "Swords_MasterHilt6", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt7", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathNearDL, "Swords_MasterHilt8", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt9", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt10", swordsMasterHilt.changedCvar, 16, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + /* + static CosmeticOption& swordsMasterHilt = cosmeticOptions.at("Swords.MasterHilt"); + if (manualChange || CVarGetInteger(swordsMasterHilt.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {swordsMasterHilt.defaultColor.x, swordsMasterHilt.defaultColor.y, swordsMasterHilt.defaultColor.z, swordsMasterHilt.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(swordsMasterHilt.cvar, defaultColor); + PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt1", swordsMasterHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt2", swordsMasterHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt3", swordsMasterHilt.changedCvar, 16, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt4", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt5", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "Swords_MasterHilt6", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt7", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathNearDL, "Swords_MasterHilt8", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt9", swordsMasterHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt10", swordsMasterHilt.changedCvar, 16, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // if (manualChange) { - // PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt11", swordsMasterHilt.changedCvar, 38, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt12", swordsMasterHilt.changedCvar, 64, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt13", swordsMasterHilt.changedCvar, 106, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt14", swordsMasterHilt.changedCvar, 120, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt15", swordsMasterHilt.changedCvar, 104, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt16", swordsMasterHilt.changedCvar, 182, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt17", swordsMasterHilt.changedCvar, 184, gsSPEndDisplayList()); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt18", swordsMasterHilt.changedCvar, 80, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt19", swordsMasterHilt.changedCvar, 94, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt20", swordsMasterHilt.changedCvar, 162, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt21", swordsMasterHilt.changedCvar, 180, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathNearDL, "Swords_MasterHilt22", swordsMasterHilt.changedCvar, 154, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathNearDL, "Swords_MasterHilt23", swordsMasterHilt.changedCvar, 232, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt24", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt25", swordsMasterHilt.changedCvar, 130, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt26", swordsMasterHilt.changedCvar, 172, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt27", swordsMasterHilt.changedCvar, 186, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "Swords_MasterHilt28", swordsMasterHilt.changedCvar, 220, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "Swords_MasterHilt29", swordsMasterHilt.changedCvar, 298, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt30", swordsMasterHilt.changedCvar, 38, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt31", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt32", swordsMasterHilt.changedCvar, 86, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt33", swordsMasterHilt.changedCvar, 208, gsSPGrayscale(false)); - // PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt34", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(true)); - // PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt35", swordsMasterHilt.changedCvar, 278, gsSPGrayscale(false)); - // PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt36", swordsMasterHilt.changedCvar, 280, gsSPEndDisplayList()); - // PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt37", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(true)); - // PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt38", swordsMasterHilt.changedCvar, 278, gsSPGrayscale(false)); - // PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt39", swordsMasterHilt.changedCvar, 280, gsSPEndDisplayList()); - // } - // } + if (manualChange) { + PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt11", swordsMasterHilt.changedCvar, 38, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt12", swordsMasterHilt.changedCvar, 64, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt13", swordsMasterHilt.changedCvar, 106, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathFarDL, "Swords_MasterHilt14", swordsMasterHilt.changedCvar, 120, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt15", swordsMasterHilt.changedCvar, 104, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt16", swordsMasterHilt.changedCvar, 182, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultMasterSwordAndSheathNearDL, "Swords_MasterHilt17", swordsMasterHilt.changedCvar, 184, gsSPEndDisplayList()); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt18", swordsMasterHilt.changedCvar, 80, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt19", swordsMasterHilt.changedCvar, 94, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt20", swordsMasterHilt.changedCvar, 162, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathFarDL, "Swords_MasterHilt21", swordsMasterHilt.changedCvar, 180, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathNearDL, "Swords_MasterHilt22", swordsMasterHilt.changedCvar, 154, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultHylianShieldSwordAndSheathNearDL, "Swords_MasterHilt23", swordsMasterHilt.changedCvar, 232, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt24", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt25", swordsMasterHilt.changedCvar, 130, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt26", swordsMasterHilt.changedCvar, 172, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathFarDL, "Swords_MasterHilt27", swordsMasterHilt.changedCvar, 186, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "Swords_MasterHilt28", swordsMasterHilt.changedCvar, 220, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "Swords_MasterHilt29", swordsMasterHilt.changedCvar, 298, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt30", swordsMasterHilt.changedCvar, 38, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt31", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt32", swordsMasterHilt.changedCvar, 86, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt33", swordsMasterHilt.changedCvar, 208, gsSPGrayscale(false)); + PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt34", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(true)); + PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt35", swordsMasterHilt.changedCvar, 278, gsSPGrayscale(false)); + PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt36", swordsMasterHilt.changedCvar, 280, gsSPEndDisplayList()); + PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt37", swordsMasterHilt.changedCvar, 112, gsSPGrayscale(true)); + PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt38", swordsMasterHilt.changedCvar, 278, gsSPGrayscale(false)); + PATCH_GFX(gGanonMasterSwordDL, "Swords_MasterHilt39", swordsMasterHilt.changedCvar, 280, gsSPEndDisplayList()); + } + } + */ static CosmeticOption& swordsBiggoronBlade = cosmeticOptions.at("Swords.BiggoronBlade"); if (manualChange || CVarGetInteger(swordsBiggoronBlade.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {swordsBiggoronBlade.defaultColor.x, swordsBiggoronBlade.defaultColor.y, swordsBiggoronBlade.defaultColor.z, swordsBiggoronBlade.defaultColor.w}; @@ -740,26 +828,27 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronBlade3", swordsBiggoronBlade.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronBlade4", swordsBiggoronBlade.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); } - // static CosmeticOption& swordsBiggoronHilt = cosmeticOptions.at("Swords.BiggoronHilt"); - // if (manualChange || CVarGetInteger(swordsBiggoronHilt.rainbowCvar, 0)) { - // static Color_RGBA8 defaultColor = {swordsBiggoronHilt.defaultColor.x, swordsBiggoronHilt.defaultColor.y, swordsBiggoronHilt.defaultColor.z, swordsBiggoronHilt.defaultColor.w}; - // Color_RGBA8 color = CVarGetColor(swordsBiggoronHilt.cvar, defaultColor); - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt1", swordsBiggoronHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt2", swordsBiggoronHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt3", swordsBiggoronHilt.changedCvar, 74, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt4", swordsBiggoronHilt.changedCvar, 76, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); - // PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt5", swordsBiggoronHilt.changedCvar, 154, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt6", swordsBiggoronHilt.changedCvar, 156, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); - - // if (manualChange) { - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt7", swordsBiggoronHilt.changedCvar, 278, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt8", swordsBiggoronHilt.changedCvar, 332, gsSPGrayscale(false)); - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt9", swordsBiggoronHilt.changedCvar, 334, gsSPEndDisplayList()); - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt10", swordsBiggoronHilt.changedCvar, 38, gsSPGrayscale(true)); - // PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt11", swordsBiggoronHilt.changedCvar, 118, gsSPGrayscale(false)); - // } - // } + /* + static CosmeticOption& swordsBiggoronHilt = cosmeticOptions.at("Swords.BiggoronHilt"); + if (manualChange || CVarGetInteger(swordsBiggoronHilt.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {swordsBiggoronHilt.defaultColor.x, swordsBiggoronHilt.defaultColor.y, swordsBiggoronHilt.defaultColor.z, swordsBiggoronHilt.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(swordsBiggoronHilt.cvar, defaultColor); + PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt1", swordsBiggoronHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt2", swordsBiggoronHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt3", swordsBiggoronHilt.changedCvar, 74, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt4", swordsBiggoronHilt.changedCvar, 76, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); + PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt5", swordsBiggoronHilt.changedCvar, 154, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt6", swordsBiggoronHilt.changedCvar, 156, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); + if (manualChange) { + PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt7", swordsBiggoronHilt.changedCvar, 278, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt8", swordsBiggoronHilt.changedCvar, 332, gsSPGrayscale(false)); + PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt9", swordsBiggoronHilt.changedCvar, 334, gsSPEndDisplayList()); + PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt10", swordsBiggoronHilt.changedCvar, 38, gsSPGrayscale(true)); + PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt11", swordsBiggoronHilt.changedCvar, 118, gsSPGrayscale(false)); + } + } + */ static CosmeticOption& glovesGoronBracelet = cosmeticOptions.at("Gloves.GoronBracelet"); if (manualChange || CVarGetInteger(glovesGoronBracelet.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {glovesGoronBracelet.defaultColor.x, glovesGoronBracelet.defaultColor.y, glovesGoronBracelet.defaultColor.z, glovesGoronBracelet.defaultColor.w}; @@ -769,8 +858,8 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet3", glovesGoronBracelet.changedCvar, 3, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); if (manualChange) { - PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet4", glovesGoronBracelet.changedCvar, 11, gsSPGrayscale(true)); - PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet5", glovesGoronBracelet.changedCvar, 39, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet4", glovesGoronBracelet.changedCvar, 11, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet5", glovesGoronBracelet.changedCvar, 39, gsSPGrayscale(false)); } } static CosmeticOption& glovesSilverGauntlets = cosmeticOptions.at("Gloves.SilverGauntlets"); @@ -820,31 +909,32 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { // There appears to be no gem rendered on the far LOD variant, not sure if this is an SOH bug or what. // PATCH_GFX(gLinkChildLeftFistAndBoomerangFarDL, "Equipment_BoomerangGem5", equipmentBoomerangGem.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } + /* + static CosmeticOption& equipmentSlingshotBody = cosmeticOptions.at("Equipment.SlingshotBody"); + if (manualChange || CVarGetInteger(equipmentSlingshotBody.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {equipmentSlingshotBody.defaultColor.x, equipmentSlingshotBody.defaultColor.y, equipmentSlingshotBody.defaultColor.z, equipmentSlingshotBody.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(equipmentSlingshotBody.cvar, defaultColor); + PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody1", equipmentSlingshotBody.changedCvar, 10, gsDPSetPrimColor(0, 0, MAX(color.r - 100, 0), MAX(color.g - 100, 0), MAX(color.b - 100, 0), 255)); + PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody2", equipmentSlingshotBody.changedCvar, 12, gsDPSetEnvColor(MAX(color.r - 100, 0) / 3, MAX(color.g - 100, 0) / 3, MAX(color.b - 100, 0) / 3, 255)); + PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody3", equipmentSlingshotBody.changedCvar, 74, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody4", equipmentSlingshotBody.changedCvar, 76, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); + PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody5", equipmentSlingshotBody.changedCvar, 128, gsDPSetPrimColor(0, 0, MAX(color.r - 100, 0), MAX(color.g - 100, 0), MAX(color.b - 100, 0), 255)); + PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody6", equipmentSlingshotBody.changedCvar, 130, gsDPSetEnvColor(MAX(color.r - 100, 0) / 3, MAX(color.g - 100, 0) / 3, MAX(color.b - 100, 0) / 3, 255)); + PATCH_GFX(gLinkChildRightArmStretchedSlingshotDL, "Equipment_SlingshotBody7", equipmentSlingshotBody.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody8", equipmentSlingshotBody.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotFarDL, "Equipment_SlingshotBody9", equipmentSlingshotBody.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // static CosmeticOption& equipmentSlingshotBody = cosmeticOptions.at("Equipment.SlingshotBody"); - // if (manualChange || CVarGetInteger(equipmentSlingshotBody.rainbowCvar, 0)) { - // static Color_RGBA8 defaultColor = {equipmentSlingshotBody.defaultColor.x, equipmentSlingshotBody.defaultColor.y, equipmentSlingshotBody.defaultColor.z, equipmentSlingshotBody.defaultColor.w}; - // Color_RGBA8 color = CVarGetColor(equipmentSlingshotBody.cvar, defaultColor); - // PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody1", equipmentSlingshotBody.changedCvar, 10, gsDPSetPrimColor(0, 0, MAX(color.r - 100, 0), MAX(color.g - 100, 0), MAX(color.b - 100, 0), 255)); - // PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody2", equipmentSlingshotBody.changedCvar, 12, gsDPSetEnvColor(MAX(color.r - 100, 0) / 3, MAX(color.g - 100, 0) / 3, MAX(color.b - 100, 0) / 3, 255)); - // PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody3", equipmentSlingshotBody.changedCvar, 74, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody4", equipmentSlingshotBody.changedCvar, 76, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); - // PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody5", equipmentSlingshotBody.changedCvar, 128, gsDPSetPrimColor(0, 0, MAX(color.r - 100, 0), MAX(color.g - 100, 0), MAX(color.b - 100, 0), 255)); - // PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody6", equipmentSlingshotBody.changedCvar, 130, gsDPSetEnvColor(MAX(color.r - 100, 0) / 3, MAX(color.g - 100, 0) / 3, MAX(color.b - 100, 0) / 3, 255)); - // PATCH_GFX(gLinkChildRightArmStretchedSlingshotDL, "Equipment_SlingshotBody7", equipmentSlingshotBody.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody8", equipmentSlingshotBody.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotFarDL, "Equipment_SlingshotBody9", equipmentSlingshotBody.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - - // if (manualChange) { - // PATCH_GFX(gLinkChildRightArmStretchedSlingshotDL, "Equipment_SlingshotBody10",equipmentSlingshotBody.changedCvar, 20, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildRightArmStretchedSlingshotDL, "Equipment_SlingshotBody11",equipmentSlingshotBody.changedCvar, 74, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotFarDL, "Equipment_SlingshotBody12",equipmentSlingshotBody.changedCvar, 20, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotFarDL, "Equipment_SlingshotBody13",equipmentSlingshotBody.changedCvar, 66, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody14",equipmentSlingshotBody.changedCvar, 96, gsSPGrayscale(true)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody15",equipmentSlingshotBody.changedCvar, 136, gsSPGrayscale(false)); - // PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody16",equipmentSlingshotBody.changedCvar, 138, gsSPEndDisplayList()); - // } - // } + if (manualChange) { + PATCH_GFX(gLinkChildRightArmStretchedSlingshotDL, "Equipment_SlingshotBody10",equipmentSlingshotBody.changedCvar, 20, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildRightArmStretchedSlingshotDL, "Equipment_SlingshotBody11",equipmentSlingshotBody.changedCvar, 74, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotFarDL, "Equipment_SlingshotBody12",equipmentSlingshotBody.changedCvar, 20, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotFarDL, "Equipment_SlingshotBody13",equipmentSlingshotBody.changedCvar, 66, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody14",equipmentSlingshotBody.changedCvar, 96, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody15",equipmentSlingshotBody.changedCvar, 136, gsSPGrayscale(false)); + PATCH_GFX(gLinkChildRightHandHoldingSlingshotNearDL, "Equipment_SlingshotBody16",equipmentSlingshotBody.changedCvar, 138, gsSPEndDisplayList()); + } + } + */ static CosmeticOption& equipmentSlingshotString = cosmeticOptions.at("Equipment.SlingshotString"); if (manualChange || CVarGetInteger(equipmentSlingshotString.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentSlingshotString.defaultColor.x, equipmentSlingshotString.defaultColor.y, equipmentSlingshotString.defaultColor.z, equipmentSlingshotString.defaultColor.w}; @@ -913,6 +1003,13 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { PATCH_GFX(gLinkAdultLeftHandHoldingHammerNearDL, "Equipment_HammerHandle5", equipmentHammerHandle.changedCvar, 18, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingHammerFarDL, "Equipment_HammerHandle6", equipmentHammerHandle.changedCvar, 18, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } + + static CosmeticOption& equipmentHookshotChain = cosmeticOptions.at("Equipment.HookshotChain"); + if (manualChange || CVarGetInteger(equipmentHookshotChain.rainbowCvar, 0)) { + static Color_RGBA8 defaultColor = {equipmentHookshotChain.defaultColor.x, equipmentHookshotChain.defaultColor.y, equipmentHookshotChain.defaultColor.z, equipmentHookshotChain.defaultColor.w}; + Color_RGBA8 color = CVarGetColor(equipmentHookshotChain.cvar, defaultColor); + PATCH_GFX(gLinkAdultHookshotChainDL, "Equipment_HookshotChain1", equipmentHookshotChain.changedCvar, 17, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + } static CosmeticOption& equipmentChuFace = cosmeticOptions.at("Equipment.ChuFace"); if (manualChange || CVarGetInteger(equipmentChuFace.rainbowCvar, 0)) { @@ -942,16 +1039,16 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { if (manualChange || CVarGetInteger(equipmentBunnyHood.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {equipmentBunnyHood.defaultColor.x, equipmentBunnyHood.defaultColor.y, equipmentBunnyHood.defaultColor.z, equipmentBunnyHood.defaultColor.w}; Color_RGBA8 color = CVarGetColor(equipmentBunnyHood.cvar, defaultColor); - PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood1", equipmentBunnyHood.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood2", equipmentBunnyHood.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); - PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood3", equipmentBunnyHood.changedCvar, 83, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); - PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood4", equipmentBunnyHood.changedCvar, 84, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); - PATCH_GFX(gLinkChildBunnyHoodDL, "Equipment_BunnyHood5", equipmentBunnyHood.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood1", equipmentBunnyHood.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood2", equipmentBunnyHood.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); + PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood3", equipmentBunnyHood.changedCvar, 83, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); + PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood4", equipmentBunnyHood.changedCvar, 84, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); + PATCH_GFX(gLinkChildBunnyHoodDL, "Equipment_BunnyHood5", equipmentBunnyHood.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); if (manualChange) { - PATCH_GFX(gLinkChildBunnyHoodDL, "Equipment_BunnyHood6", equipmentBunnyHood.changedCvar, 13, gsSPGrayscale(true)); + PATCH_GFX(gLinkChildBunnyHoodDL, "Equipment_BunnyHood6", equipmentBunnyHood.changedCvar, 13, gsSPGrayscale(true)); if (CVarGetInteger(equipmentBunnyHood.changedCvar, 0)) { - ResourceMgr_PatchGfxByName(gLinkChildBunnyHoodDL, "Equipment_BunnyHood7", 125, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL)); + ResourceMgr_PatchGfxByName(gLinkChildBunnyHoodDL, "Equipment_BunnyHood7", 125, gsSPBranchListOTRFilePath(gEndGrayscaleAndEndDlistDL)); } else { ResourceMgr_UnpatchGfxByName(gLinkChildBunnyHoodDL, "Equipment_BunnyHood7"); } @@ -1019,10 +1116,12 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { if (manualChange || CVarGetInteger(consumableHearts.rainbowCvar, 0)) { static Color_RGBA8 defaultColor = {consumableHearts.defaultColor.x, consumableHearts.defaultColor.y, consumableHearts.defaultColor.z, consumableHearts.defaultColor.w}; Color_RGBA8 color = CVarGetColor(consumableHearts.cvar, defaultColor); - // PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts1", consumableHearts.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); - // PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts2", consumableHearts.changedCvar, 26, gsSPGrayscale(true)); - // PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts3", consumableHearts.changedCvar, 72, gsSPGrayscale(false)); - // PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts4", consumableHearts.changedCvar, 74, gsSPEndDisplayList()); + /* + PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts1", consumableHearts.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); + PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts2", consumableHearts.changedCvar, 26, gsSPGrayscale(true)); + PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts3", consumableHearts.changedCvar, 72, gsSPGrayscale(false)); + PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts4", consumableHearts.changedCvar, 74, gsSPEndDisplayList()); + */ PATCH_GFX(gGiHeartPieceDL, "Consumable_Hearts5", consumableHearts.changedCvar, 2, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiHeartPieceDL, "Consumable_Hearts6", consumableHearts.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gGiHeartContainerDL, "Consumable_Hearts7", consumableHearts.changedCvar, 2, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -1119,6 +1218,15 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } } +extern "C" Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id) { + return Color_RGBA8 { + (uint8_t)(cosmeticOptions[id].defaultColor.x * 255.0f), + (uint8_t)(cosmeticOptions[id].defaultColor.y * 255.0f), + (uint8_t)(cosmeticOptions[id].defaultColor.z * 255.0f), + (uint8_t)(cosmeticOptions[id].defaultColor.w * 255.0f) + }; +} + void Table_InitHeader(bool has_header = true) { if (has_header) { ImGui::TableHeadersRow(); @@ -1129,12 +1237,14 @@ void Table_InitHeader(bool has_header = true) { ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 2); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60); } + void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){ std::string CvarLabel = CvarName + ".UseMargins"; std::string Label = ElementName + " use margins"; UIWidgets::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); UIWidgets::Tooltip("Using this allow you move the element with General margins sliders"); } + void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = true){ std::string CvarLabel = CvarName + ".PosType"; UIWidgets::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); @@ -1150,6 +1260,7 @@ void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = UIWidgets::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4); UIWidgets::Tooltip("This will make your elements hidden"); } + void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){ std::string PosXCvar = CvarName + ".PosX"; std::string PosYCvar = CvarName + ".PosY"; @@ -1160,12 +1271,14 @@ void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX UIWidgets::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0); UIWidgets::Tooltip("This slider is used to move Left and Right your elements."); } + void DrawScaleSlider(const std::string CvarName,float DefaultValue){ std::string InvisibleLabel = "##"+CvarName; std::string CvarLabel = CvarName + ".Scale"; //Disabled for now. feature not done and several fixes needed to be merged. //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true); } + void Draw_Table_Dropdown(const char* Header_Title, const char* Table_ID, const char* Column_Title, const char* Slider_Title, const char* Slider_ID, int MinY, int MaxY, int MinX, int MaxX, float Default_Value) { if (ImGui::CollapsingHeader(Header_Title)) { if (ImGui::BeginTable(Table_ID, 1, FlagsTable)) { @@ -1180,6 +1293,7 @@ void Draw_Table_Dropdown(const char* Header_Title, const char* Table_ID, const c } } } + void C_Button_Dropdown(const char* Header_Title, const char* Table_ID, const char* Column_Title, const char* Slider_Title, const char* Slider_ID, const char* Int_Type, float Slider_Scale_Value) { if (ImGui::CollapsingHeader(Header_Title)) { if (ImGui::BeginTable(Table_ID, 1, FlagsTable)) { @@ -1216,6 +1330,7 @@ void C_Button_Dropdown(const char* Header_Title, const char* Table_ID, const cha } } } + void Draw_Placements(){ if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); @@ -1344,6 +1459,7 @@ void Draw_Placements(){ } } } + void Reset_Option_Single(const char* Button_Title, const char* name) { ImGui::SameLine(); if (ImGui::Button(Button_Title)) { @@ -1351,6 +1467,7 @@ void Reset_Option_Single(const char* Button_Title, const char* name) { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } + void Reset_Option_Double(const char* Button_Title, const char* name) { ImGui::SameLine(); if (ImGui::Button(Button_Title)) { @@ -1359,6 +1476,7 @@ void Reset_Option_Double(const char* Button_Title, const char* name) { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } } + void DrawSillyTab() { ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { @@ -1527,10 +1645,11 @@ void ApplySideEffects(CosmeticOption& cosmeticOption) { } void RandomizeColor(CosmeticOption& cosmeticOption) { + ImVec4 randomColor = GetRandomValue(); Color_RGBA8 newColor; - newColor.r = Random(0, 255); - newColor.g = Random(0, 255); - newColor.b = Random(0, 255); + newColor.r = randomColor.x * 255; + newColor.g = randomColor.y * 255; + newColor.b = randomColor.z * 255; newColor.a = 255; // For alpha supported options, retain the last set alpha instead of overwriting if (cosmeticOption.supportsAlpha) { @@ -1543,8 +1662,8 @@ void RandomizeColor(CosmeticOption& cosmeticOption) { cosmeticOption.currentColor.w = newColor.a / 255.0; CVarSetColor(cosmeticOption.cvar, newColor); - CVarSetInteger((cosmeticOption.rainbowCvar), 0); - CVarSetInteger((cosmeticOption.changedCvar), 1); + CVarSetInteger(cosmeticOption.rainbowCvar, 0); + CVarSetInteger(cosmeticOption.changedCvar, 1); ApplySideEffects(cosmeticOption); } @@ -1631,7 +1750,8 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { } ImGui::SameLine(); ImGui::Text("%s", cosmeticOption.label.c_str()); - ImGui::SameLine((ImGui::CalcTextSize("Mirror Shield Mirror").x * 1.0f) + 60.0f); + //the longest option name + ImGui::SameLine((ImGui::CalcTextSize("Message Light Blue (None No Shadow) Color").x * 1.0f) + 60.0f); if (ImGui::Button(("Random##" + cosmeticOption.label).c_str())) { RandomizeColor(cosmeticOption); ApplyOrResetCustomGfxPatches(); @@ -1667,7 +1787,8 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { void DrawCosmeticGroup(CosmeticGroup cosmeticGroup) { std::string label = groupLabels.at(cosmeticGroup); ImGui::Text("%s", label.c_str()); - ImGui::SameLine((ImGui::CalcTextSize("Mirror Shield Mirror").x * 1.0f) + 60.0f); + // the longest option name + ImGui::SameLine((ImGui::CalcTextSize("Message Light Blue (None No Shadow) Color").x * 1.0f) + 60.0f); if (ImGui::Button(("Random##" + label).c_str())) { for (auto& [id, cosmeticOption] : cosmeticOptions) { if (cosmeticOption.group == cosmeticGroup && (!cosmeticOption.advancedOption || CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) && !CVarGetInteger(cosmeticOption.lockedCvar, 0)) { @@ -1763,6 +1884,36 @@ void CosmeticsEditorWindow::DrawElement() { } Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } + + if (ImGui::Button("Rainbow All", ImVec2(ImGui::GetContentRegionAvail().x / 2, 30.0f))) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if ( + !CVarGetInteger(cosmeticOption.lockedCvar, 0) && + ( + !cosmeticOption.advancedOption || + CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0) + ) + ) { + CVarSetInteger(cosmeticOption.rainbowCvar, 1); + } + } + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } + ImGui::SameLine(); + if (ImGui::Button("Un-Rainbow All", ImVec2(ImGui::GetContentRegionAvail().x, 30.0f))) { + for (auto& [id, cosmeticOption] : cosmeticOptions) { + if ( + !CVarGetInteger(cosmeticOption.lockedCvar, 0) && + ( + !cosmeticOption.advancedOption || + CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0) + ) + ) { + CVarSetInteger(cosmeticOption.rainbowCvar, 0); + } + } + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); + } if (ImGui::BeginTabBar("CosmeticsContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Link & Items")) { @@ -1775,7 +1926,7 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Effects")) { - // DrawCosmeticGroup(COSMETICS_GROUP_MAGIC); // Cosmetics TODO: Implement magic effect colors + DrawCosmeticGroup(COSMETICS_GROUP_MAGIC); DrawCosmeticGroup(COSMETICS_GROUP_ARROWS); DrawCosmeticGroup(COSMETICS_GROUP_SPIN_ATTACK); DrawCosmeticGroup(COSMETICS_GROUP_TRAILS); @@ -1816,6 +1967,11 @@ void CosmeticsEditorWindow::DrawElement() { DrawCosmeticGroup(COSMETICS_GROUP_KALEIDO); ImGui::EndTabItem(); } + + if (ImGui::BeginTabItem("Message")) { + DrawCosmeticGroup(COSMETICS_GROUP_MESSAGE); + ImGui::EndTabItem(); + } ImGui::EndTabBar(); } } diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h index 88f60c76c..55dba5780 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h @@ -1,13 +1,6 @@ #pragma once #include <libultraship/libultraship.h> -#define PATCH_GFX(path, name, cvar, index, instruction) \ - if (CVarGetInteger(cvar, 0)) { \ - ResourceMgr_PatchGfxByName(path, name, index, instruction); \ - } else { \ - ResourceMgr_UnpatchGfxByName(path, name); \ - } - // Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize // every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor` typedef enum { @@ -28,9 +21,19 @@ typedef enum { COSMETICS_GROUP_TRAILS, COSMETICS_GROUP_NAVI, COSMETICS_GROUP_IVAN, + COSMETICS_GROUP_MESSAGE, COSMETICS_GROUP_MAX } CosmeticGroup; +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id); + +#ifdef __cplusplus +} + typedef struct { const std::string Name; const std::string ToolTip; @@ -46,8 +49,7 @@ static float TablesCellsWidth = 300.0f; static ImGuiTableColumnFlags FlagsTable = ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV; static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoSort; -void InitCosmeticsEditor();//Init the menu itself -ImVec4 GetRandomValue(int MaximumPossible); +ImVec4 GetRandomValue(); void CosmeticsEditor_RandomizeAll(); void CosmeticsEditor_RandomizeGroup(CosmeticGroup group); void CosmeticsEditor_ResetAll(); @@ -61,4 +63,5 @@ class CosmeticsEditorWindow : public Ship::GuiWindow { void InitElement() override; void DrawElement() override; void UpdateElement() override {}; -}; \ No newline at end of file +}; +#endif //__cplusplus \ No newline at end of file diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 4f65ef9a5..829d1161e 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1312,6 +1312,7 @@ static constexpr std::array<std::pair<const char*, CosmeticGroup>, COSMETICS_GRO {"trials", COSMETICS_GROUP_TRAILS}, {"navi", COSMETICS_GROUP_NAVI}, {"ivan", COSMETICS_GROUP_IVAN}, + {"message", COSMETICS_GROUP_MESSAGE}, }}; static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args, std::string* output) { diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 1d7a56c00..a371ef52b 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -593,7 +593,7 @@ namespace UIWidgets { #if defined(__SWITCH__) || defined(__WIIU__) srand(time(NULL)); #endif - ImVec4 color = GetRandomValue(255); + ImVec4 color = GetRandomValue(); colors->x = color.x; colors->y = color.y; colors->z = color.z; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index a9f5aeab0..8ceca43f2 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1081,14 +1081,11 @@ void TitleCard_InitPlaceName(PlayState* play, TitleCardContext* titleCtx, void* } void TitleCard_Update(PlayState* play, TitleCardContext* titleCtx) { - const Color_RGB8 TitleCard_Colors_ori = {255,255,255}; - Color_RGB8 TitleCard_Colors = {255,255,255}; - if (titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Boss.Changed"), 1) == 2) { - TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Boss.Value"), TitleCard_Colors_ori); - } else if (!titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Map.Changed"), 1) == 2) { - TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Map.Value"), TitleCard_Colors_ori); - } else { - TitleCard_Colors = TitleCard_Colors_ori; + Color_RGB8 TitleCard_Colors = { 255, 255, 255 }; + if (titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Boss.Changed"), 0) == 1) { + TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Boss.Value"), TitleCard_Colors); + } else if (!titleCtx->isBossCard && CVarGetInteger(CVAR_COSMETIC("HUD.TitleCard.Map.Changed"), 0) == 1) { + TitleCard_Colors = CVarGetColor24(CVAR_COSMETIC("HUD.TitleCard.Map.Value"), TitleCard_Colors); } if (DECR(titleCtx->delayTimer) == 0) { @@ -2345,8 +2342,14 @@ void Actor_DrawFaroresWindPointer(PlayState* play) { } else if (D_8015BC18 > 0.0f) { static Vec3f effectVel = { 0.0f, -0.05f, 0.0f }; static Vec3f effectAccel = { 0.0f, -0.025f, 0.0f }; - static Color_RGBA8 effectPrimCol = { 255, 255, 255, 0 }; - static Color_RGBA8 effectEnvCol = { 100, 200, 0, 0 }; + Color_RGBA8 effectPrimCol = { 255, 255, 255, 0 }; + Color_RGBA8 effectEnvCol = { 100, 200, 0, 0 }; + if (CVarGetInteger(CVAR_COSMETIC("Magic.FaroresSecondary.Changed"), 0)) { + effectEnvCol = CVarGetColor(CVAR_COSMETIC("Magic.FaroresSecondary.Value"), effectEnvCol); + } + if (CVarGetInteger(CVAR_COSMETIC("Magic.FaroresPrimary.Changed"), 0)) { + effectPrimCol = CVarGetColor(CVAR_COSMETIC("Magic.FaroresPrimary.Value"), effectPrimCol); + } Vec3f* curPos = &gSaveContext.respawn[RESPAWN_MODE_TOP].pos; Vec3f* nextPos = &gSaveContext.respawn[RESPAWN_MODE_DOWN].pos; f32 prevNum = D_8015BC18; @@ -2441,8 +2444,16 @@ void Actor_DrawFaroresWindPointer(PlayState* play) { Matrix_Push(); gDPPipeSync(POLY_XLU_DISP++); - gDPSetPrimColor(POLY_XLU_DISP++, 128, 128, 255, 255, 200, alpha); - gDPSetEnvColor(POLY_XLU_DISP++, 100, 200, 0, 255); + Color_RGB8 Spell_env = { 100, 200, 0 }; + Color_RGB8 Spell_col = { 255, 255, 200 }; + if (CVarGetInteger(CVAR_COSMETIC("Magic.FaroresSecondary.Changed"), 0)) { + Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.FaroresSecondary.Value"), Spell_env); + } + if (CVarGetInteger(CVAR_COSMETIC("Magic.FaroresPrimary.Changed"), 0)) { + Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.FaroresPrimary.Value"), Spell_col); + } + gDPSetPrimColor(POLY_XLU_DISP++, 128, 128, Spell_col.r, Spell_col.g, Spell_col.b, alpha); + gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, 255); Matrix_RotateZ(((play->gameplayFrames * 1500) & 0xFFFF) * M_PI / 32768.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 08be75112..e6b944a73 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -7,6 +7,7 @@ #include "textures/parameter_static/parameter_static.h" #include "textures/message_static/message_static.h" #include "textures/message_texture_static/message_texture_static.h" +#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" @@ -367,6 +368,80 @@ void Message_FindCreditsMessage(PlayState* play, u16 textId) { } } +#pragma region [SoH] Cosmetics + +#define MESSAGE_COSMETICS_HANDLE_COLOR(id) \ + if (CVarGetInteger(CVAR_COSMETIC("Message." id ".Changed"), 0)) { \ + Color_RGBA8 color = CVarGetColor(CVAR_COSMETIC("Message." id ".Value"), CosmeticsEditor_GetDefaultValue("Message." id)); \ + msgCtx->textColorR = color.r; \ + msgCtx->textColorG = color.g; \ + msgCtx->textColorB = color.b; \ + } + +void Cosmetics_MaybeSetTextColor(MessageContext* msgCtx, u16 colorParameter) { + switch (colorParameter) { + case MSGCOL_RED: + if (msgCtx->textBoxType == TEXTBOX_TYPE_WOODEN) { + MESSAGE_COSMETICS_HANDLE_COLOR("Red.Wooden") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("Red.Normal") + } + break; + case MSGCOL_ADJUSTABLE: + if (msgCtx->textBoxType == TEXTBOX_TYPE_WOODEN) { + MESSAGE_COSMETICS_HANDLE_COLOR("Adjustable.Wooden") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("Adjustable.Normal") + } + break; + case MSGCOL_BLUE: + if (msgCtx->textBoxType == TEXTBOX_TYPE_WOODEN) { + MESSAGE_COSMETICS_HANDLE_COLOR("Blue.Wooden") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("Blue.Normal") + } + break; + case MSGCOL_LIGHTBLUE: + if (msgCtx->textBoxType == TEXTBOX_TYPE_WOODEN) { + MESSAGE_COSMETICS_HANDLE_COLOR("LightBlue.Wooden") + } else if (msgCtx->textBoxType == TEXTBOX_TYPE_NONE_NO_SHADOW) { + MESSAGE_COSMETICS_HANDLE_COLOR("LightBlue.NoneNoShadow") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("LightBlue.Normal") + } + break; + case MSGCOL_PURPLE: + if (msgCtx->textBoxType == TEXTBOX_TYPE_WOODEN) { + MESSAGE_COSMETICS_HANDLE_COLOR("Purple.Wooden") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("Purple.Normal") + } + break; + case MSGCOL_YELLOW: + if (msgCtx->textBoxType == TEXTBOX_TYPE_WOODEN) { + MESSAGE_COSMETICS_HANDLE_COLOR("Yellow.Wooden") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("Yellow.Normal") + } + break; + case MSGCOL_BLACK: + MESSAGE_COSMETICS_HANDLE_COLOR("Black") + break; + case MSGCOL_DEFAULT: + default: + if (msgCtx->textBoxType == TEXTBOX_TYPE_NONE_NO_SHADOW) { + MESSAGE_COSMETICS_HANDLE_COLOR("Default.NoneNoShadow") + } else { + MESSAGE_COSMETICS_HANDLE_COLOR("Default.Normal") + } + break; + } +} + +#undef MESSAGE_COSMETICS_HANDLE_COLOR + +#pragma endregion + void Message_SetTextColor(MessageContext* msgCtx, u16 colorParameter) { switch (colorParameter) { case MSGCOL_RED: @@ -451,6 +526,7 @@ void Message_SetTextColor(MessageContext* msgCtx, u16 colorParameter) { } break; } + Cosmetics_MaybeSetTextColor(msgCtx, colorParameter); } void Message_DrawTextboxIcon(PlayState* play, Gfx** p, s16 x, s16 y) { @@ -853,6 +929,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { msgCtx->textColorR = msgCtx->textColorG = msgCtx->textColorB = 255; } + Cosmetics_MaybeSetTextColor(msgCtx, MSGCOL_DEFAULT); + msgCtx->unk_E3D0 = 0; charTexIdx = 0; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 2c180c584..0792e71cf 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3388,6 +3388,9 @@ void Interface_UpdateMagicBar(PlayState* play) { default: gSaveContext.magicState = MAGIC_STATE_IDLE; + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); + } break; } } @@ -3617,8 +3620,8 @@ void Interface_DrawEnemyHealthBar(TargetContext* targetCtx, PlayState* play) { s32 healthbar_offsetY = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.PosY"), 0); s8 anchorType = CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.PosType"), ENEMYHEALTH_ANCHOR_ACTOR); - if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar..Changed"), 0)) { - healthbar_red = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBar..Value"), healthbar_red); + if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Changed"), 0)) { + healthbar_red = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBar.Value"), healthbar_red); } if (CVarGetInteger(CVAR_COSMETIC("HUD.EnemyHealthBorder.Changed"), 0)) { healthbar_border = CVarGetColor(CVAR_COSMETIC("HUD.EnemyHealthBorder.Value"), healthbar_border); diff --git a/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c b/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c index bad7e9b52..77773e92a 100644 --- a/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c +++ b/soh/src/overlays/actors/ovl_En_Mag/z_en_mag.c @@ -931,8 +931,21 @@ void EnMag_DrawInnerVanilla(Actor* thisx, PlayState* play, Gfx** gfxp) { gDPSetAlphaCompare(gfx++, G_AC_NONE); gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - gDPSetPrimColor(gfx++, 0, 0, (s16)this->copyrightAlpha, (s16)this->copyrightAlpha, (s16)this->copyrightAlpha, - (s16)this->copyrightAlpha); + if (CVarGetInteger(CVAR_COSMETIC("Title.Copyright.Changed"), 0)) { + Color_RGBA8 copyrightColor = CVarGetColor(CVAR_COSMETIC("Title.Copyright.Value"), (Color_RGBA8){ 255, 255, 255, 255 }); + gDPSetPrimColor( + gfx++, + 0, + 0, + (s16)(((f32)copyrightColor.r / 255.0f) * this->copyrightAlpha), + (s16)(((f32)copyrightColor.g / 255.0f) * this->copyrightAlpha), + (s16)(((f32)copyrightColor.b / 255.0f) * this->copyrightAlpha), + (s16)(((f32)copyrightColor.a / 255.0f) * this->copyrightAlpha) + ); + } else { + gDPSetPrimColor(gfx++, 0, 0, (s16)this->copyrightAlpha, (s16)this->copyrightAlpha, (s16)this->copyrightAlpha, + (s16)this->copyrightAlpha); + } if ((s16)this->copyrightAlpha != 0) { gDPLoadTextureBlock(gfx++, copy_tex, G_IM_FMT_IA, G_IM_SIZ_8b, copy_width, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, diff --git a/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c b/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c index db1ea8208..069e7ddbe 100644 --- a/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c +++ b/soh/src/overlays/actors/ovl_Magic_Dark/z_magic_dark.c @@ -198,10 +198,14 @@ void MagicDark_DiamondDraw(Actor* thisx, PlayState* play) { MagicDark* this = (MagicDark*)thisx; s32 pad; u16 gameplayFrames = play->gameplayFrames; - Color_RGB8 Spell_env_ori = {0, 100, 255}; - Color_RGB8 Spell_col_ori = {170, 255, 255}; - Color_RGB8 Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusSecondary.Value"), Spell_env_ori); - Color_RGB8 Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusPrimary.Value"), Spell_col_ori); + Color_RGB8 Spell_env = { 0, 100, 255 }; + Color_RGB8 Spell_col = { 170, 255, 255 }; + if (CVarGetInteger(CVAR_COSMETIC("Magic.NayrusSecondary.Changed"), 0)) { + Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusSecondary.Value"), Spell_env); + } + if (CVarGetInteger(CVAR_COSMETIC("Magic.NayrusPrimary.Changed"), 0)) { + Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusPrimary.Value"), Spell_col); + } OPEN_DISPS(play->state.gfxCtx); @@ -224,13 +228,8 @@ void MagicDark_DiamondDraw(Actor* thisx, PlayState* play) { Matrix_RotateY(this->actor.shape.rot.y * (M_PI / 0x8000), MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - if (CVarGetInteger(CVAR_COSMETIC("UseSpellsColors"),0)) { - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, (s32)(this->primAlpha * 0.6f) & 0xFF); - gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, 128); - } else { - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 170, 255, 255, (s32)(this->primAlpha * 0.6f) & 0xFF); - gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128); - } + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, Spell_col.r, Spell_col.g, Spell_col.b, (s32)(this->primAlpha * 0.6f) & 0xFF); + gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, 128); gSPDisplayList(POLY_XLU_DISP++, sDiamondMaterialDL); gSPDisplayList(POLY_XLU_DISP++, Gfx_TwoTexScroll(play->state.gfxCtx, 0, gameplayFrames * 2, gameplayFrames * -4, 32, 32, 1, @@ -271,8 +270,18 @@ void MagicDark_OrbDraw(Actor* thisx, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, 255); - gDPSetEnvColor(POLY_XLU_DISP++, 0, 150, 255, 255); + + Color_RGB8 Spell_env = { 0, 150, 255 }; + Color_RGB8 Spell_col = { 170, 255, 255 }; + if (CVarGetInteger(CVAR_COSMETIC("Magic.NayrusSecondary.Changed"), 0)) { + Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusSecondary.Value"), Spell_env); + } + if (CVarGetInteger(CVAR_COSMETIC("Magic.NayrusPrimary.Changed"), 0)) { + Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.NayrusPrimary.Value"), Spell_col); + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, 255); + gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, 255); Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_NEW); Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); diff --git a/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c b/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c index 46fdccaa6..da0fb02e5 100644 --- a/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c +++ b/soh/src/overlays/actors/ovl_Magic_Fire/z_magic_fire.c @@ -217,10 +217,14 @@ void MagicFire_Draw(Actor* thisx, PlayState* play) { s32 pad2; s32 i; u8 alpha; - Color_RGB8 Spell_env_ori = {255, 0, 0}; - Color_RGB8 Spell_col_ori = {255, 200, 0}; - Color_RGB8 Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.DinsSecondary.Value"), Spell_env_ori); - Color_RGB8 Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.DinsPrimaryary.Value"), Spell_col_ori); + Color_RGB8 Spell_env = { 255, 0, 0 }; + Color_RGB8 Spell_col = { 255, 200, 0 }; + if (CVarGetInteger(CVAR_COSMETIC("Magic.DinsSecondary.Changed"), 0)) { + Spell_env = CVarGetColor24(CVAR_COSMETIC("Magic.DinsSecondary.Value"), Spell_env); + } + if (CVarGetInteger(CVAR_COSMETIC("Magic.DinsPrimaryary.Changed"), 0)) { + Spell_col = CVarGetColor24(CVAR_COSMETIC("Magic.DinsPrimary.Value"), Spell_col); + } if (this->action > 0) { OPEN_DISPS(play->state.gfxCtx); @@ -232,13 +236,8 @@ void MagicFire_Draw(Actor* thisx, PlayState* play) { gDPSetColorDither(POLY_XLU_DISP++, G_CD_DISABLE); gDPFillRectangle(POLY_XLU_DISP++, 0, 0, 319, 239); Gfx_SetupDL_25Xlu(play->state.gfxCtx); - if (CVarGetInteger(CVAR_COSMETIC("UseSpellsColors"),0)) { - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, (u8)(this->alphaMultiplier * 255)); - gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, (u8)(this->alphaMultiplier * 255)); - } else { - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col_ori.r, Spell_col_ori.g, Spell_col_ori.b, (u8)(this->alphaMultiplier * 255)); - gDPSetEnvColor(POLY_XLU_DISP++, Spell_env_ori.r, Spell_env_ori.g, Spell_env_ori.b, (u8)(this->alphaMultiplier * 255)); - } + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, Spell_col.r, Spell_col.g, Spell_col.b, (u8)(this->alphaMultiplier * 255)); + gDPSetEnvColor(POLY_XLU_DISP++, Spell_env.r, Spell_env.g, Spell_env.b, (u8)(this->alphaMultiplier * 255)); Matrix_Scale(0.15f, 0.15f, 0.15f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); From 13789a1dfb738d2bfb7850e31b45837720197db1 Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Tue, 26 Nov 2024 18:28:24 -0700 Subject: [PATCH 05/28] Prevent void and teleport traps from being added to the shuffle pool while fishing in the pond. (#4586) --- soh/soh/Enhancements/mods.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 8c18daa00..0c11c79b2 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1036,6 +1036,9 @@ std::vector<AltTrapType> getEnabledAddTraps () { std::vector<AltTrapType> enabledAddTraps; for (int i = 0; i < ADD_TRAP_MAX; i++) { if (CVarGetInteger(altTrapTypeCvars[i], 0)) { + if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) { + continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues + } enabledAddTraps.push_back(static_cast<AltTrapType>(i)); } } From c9604338329364b1a13d9bcfdc839eacc3530d1c Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Tue, 26 Nov 2024 18:28:50 -0700 Subject: [PATCH 06/28] Setup AdvancePond to run in OnItemReceive. (#4585) --- .../Enhancements/randomizer/fishsanity.cpp | 25 +++++++------------ soh/soh/Enhancements/randomizer/fishsanity.h | 8 +++--- .../Enhancements/randomizer/hook_handlers.cpp | 8 +++--- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/fishsanity.cpp b/soh/soh/Enhancements/randomizer/fishsanity.cpp index 5fa2974ae..46b01e2d3 100644 --- a/soh/soh/Enhancements/randomizer/fishsanity.cpp +++ b/soh/soh/Enhancements/randomizer/fishsanity.cpp @@ -59,6 +59,7 @@ namespace Rando { const FishIdentity Fishsanity::defaultIdentity = { RAND_INF_MAX, RC_UNKNOWN_CHECK }; bool Fishsanity::fishsanityHelpersInit = false; s16 Fishsanity::fishGroupCounter = 0; + bool Fishsanity::enableAdvance = false; std::unordered_map<RandomizerCheck, LinkAge> Fishsanity::pondFishAgeMap; std::vector<RandomizerCheck> Fishsanity::childPondFish; std::vector<RandomizerCheck> Fishsanity::adultPondFish; @@ -395,22 +396,6 @@ namespace Rando { } } - void Fishsanity::OnFlagSetHandler(int16_t flagType, int16_t flag) { - if (flagType != FLAG_RANDOMIZER_INF) { - return; - } - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)flag); - FishsanityCheckType fsType = Rando::Fishsanity::GetCheckType(rc); - if (fsType == FSC_NONE) { - return; - } - - // When a pond fish is caught, advance the pond. - if (fsType == FSC_POND) { - OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond(); - } - } - void Fishsanity::OnActorUpdateHandler(void* refActor) { if (gPlayState->sceneNum != SCENE_GROTTOS && gPlayState->sceneNum != SCENE_ZORAS_DOMAIN && gPlayState->sceneNum != SCENE_FISHING_POND) { return; @@ -428,6 +413,7 @@ namespace Rando { FishIdentity identity = OTRGlobals::Instance->gRandomizer->IdentifyFish(gPlayState->sceneNum, actor->params); if (identity.randomizerCheck != RC_UNKNOWN_CHECK) { Flags_SetRandomizerInf(identity.randomizerInf); + enableAdvance = true; // Remove uncaught effect if (actor->shape.shadowDraw != NULL) { actor->shape.shadowDraw = NULL; @@ -483,6 +469,13 @@ namespace Rando { } } } + + void Fishsanity::OnItemReceiveHandler(GetItemEntry itemEntry) { + if (enableAdvance) { + enableAdvance = false; + OTRGlobals::Instance->gRandoContext->GetFishsanity()->AdvancePond(); + } + } } // namespace Rando // C interface diff --git a/soh/soh/Enhancements/randomizer/fishsanity.h b/soh/soh/Enhancements/randomizer/fishsanity.h index c98e9ab9c..91d021157 100644 --- a/soh/soh/Enhancements/randomizer/fishsanity.h +++ b/soh/soh/Enhancements/randomizer/fishsanity.h @@ -133,11 +133,6 @@ class Fishsanity { */ static void OnActorInitHandler(void* refActor); - /** - * @brief FlagSet hook handler for fishsanity - */ - static void OnFlagSetHandler(int16_t flagType, int16_t flag); - /** * @brief PlayerUpdate hook handler for fishsanity */ @@ -158,6 +153,8 @@ class Fishsanity { */ static void OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs); + static void OnItemReceiveHandler(GetItemEntry itemEntry); + private: /** * @brief Initialize helper statics if they have not been initialized yet @@ -184,6 +181,7 @@ class Fishsanity { static bool fishsanityHelpersInit; static s16 fishGroupCounter; + static bool enableAdvance; ///////////////////////////////////////////////////////// //// Helper data structures derived from static data //// diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 35badbce6..c98dabf74 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -2119,10 +2119,10 @@ void RandomizerRegisterHooks() { static uint32_t onKaleidoUpdateHook = 0; static uint32_t fishsanityOnActorInitHook = 0; - static uint32_t fishsanityOnFlagSetHook = 0; static uint32_t fishsanityOnActorUpdateHook = 0; static uint32_t fishsanityOnSceneInitHook = 0; static uint32_t fishsanityOnVanillaBehaviorHook = 0; + static uint32_t fishsanityOnItemReceiveHook = 0; GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) { randomizerQueuedChecks = std::queue<RandomizerCheck>(); @@ -2146,10 +2146,10 @@ void RandomizerRegisterHooks() { GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnKaleidoscopeUpdate>(onKaleidoUpdateHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(fishsanityOnActorInitHook); - GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnFlagSet>(fishsanityOnFlagSetHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(fishsanityOnActorUpdateHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(fishsanityOnSceneInitHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(fishsanityOnVanillaBehaviorHook); + GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(fishsanityOnItemReceiveHook); onFlagSetHook = 0; onSceneFlagSetHook = 0; @@ -2168,10 +2168,10 @@ void RandomizerRegisterHooks() { onKaleidoUpdateHook = 0; fishsanityOnActorInitHook = 0; - fishsanityOnFlagSetHook = 0; fishsanityOnActorUpdateHook = 0; fishsanityOnSceneInitHook = 0; fishsanityOnVanillaBehaviorHook = 0; + fishsanityOnItemReceiveHook = 0; if (!IS_RANDO) return; @@ -2203,10 +2203,10 @@ void RandomizerRegisterHooks() { OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave(); fishsanityOnActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(Rando::Fishsanity::OnActorInitHandler); - fishsanityOnFlagSetHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(Rando::Fishsanity::OnFlagSetHandler); fishsanityOnActorUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>(Rando::Fishsanity::OnActorUpdateHandler); fishsanityOnSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(Rando::Fishsanity::OnSceneInitHandler); fishsanityOnVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(Rando::Fishsanity::OnVanillaBehaviorHandler); + fishsanityOnItemReceiveHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(Rando::Fishsanity::OnItemReceiveHandler); } }); } From 5b7b38f198a777f18bb391b5fc3e104e6e64df1f Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Wed, 27 Nov 2024 01:29:27 +0000 Subject: [PATCH 07/28] Add some +/- buttons and clean up timesavers menu (#4571) * Add some +/- buttons and clean up timesavers menu * Better implement Image Button Style --- .../Enhancements/randomizer/Plandomizer.cpp | 46 +++++++++++++----- .../Enhancements/timesplits/TimeSplits.cpp | 48 ++++++++++++++----- soh/soh/SohMenuBar.cpp | 25 +++++----- 3 files changed, 84 insertions(+), 35 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Plandomizer.cpp b/soh/soh/Enhancements/randomizer/Plandomizer.cpp index fcec76887..f346eeb18 100644 --- a/soh/soh/Enhancements/randomizer/Plandomizer.cpp +++ b/soh/soh/Enhancements/randomizer/Plandomizer.cpp @@ -270,6 +270,16 @@ Rando::Item plandomizerRandoRetrieveItem(RandomizerGet randoGetItem) { return randoGetItemEntry; } +void PlandoPushImageButtonStyle(){ + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f)); +} + +void PlandoPopImageButtonStyle(){ + ImGui::PopStyleColor(3); +} + ImVec4 plandomizerGetItemColor(Rando::Item randoItem) { itemColor = ImVec4( 1.0f, 1.0f, 1.0f, 1.0f ); if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_FORTRESS_SMALLKEY @@ -698,6 +708,7 @@ void PlandomizerOverlayText(std::pair<Rando::Item, uint32_t> drawObject ) { void PlandomizerDrawItemPopup(uint32_t index) { if (shouldPopup && ImGui::BeginPopup("ItemList")) { + PlandoPushImageButtonStyle(); ImGui::SeparatorText("Resources"); ImGui::BeginTable("Infinite Item Table", 7); for (auto& item : infiniteItemList) { @@ -759,6 +770,7 @@ void PlandomizerDrawItemPopup(uint32_t index) { PlandomizerRemoveFromItemList(drawnItemsList[temporaryItemIndex].first); PlandomizerAddToItemList(temporaryItem); } + PlandoPopImageButtonStyle(); ImGui::EndTable(); ImGui::EndPopup(); } @@ -767,6 +779,7 @@ void PlandomizerDrawItemPopup(uint32_t index) { void PlandomizerDrawIceTrapPopUp(uint32_t index) { if (shouldTrapPopup && ImGui::BeginPopup("TrapList")) { ImGui::BeginTable("Ice Trap Table", 8); + PlandoPushImageButtonStyle(); for (auto& items : itemImageMap) { if (items.first == RG_ICE_TRAP) { continue; @@ -785,6 +798,7 @@ void PlandomizerDrawIceTrapPopUp(uint32_t index) { ImGui::PopID(); } + PlandoPopImageButtonStyle(); ImGui::EndTable(); ImGui::EndPopup(); } @@ -792,12 +806,14 @@ void PlandomizerDrawIceTrapPopUp(uint32_t index) { void PlandomizerDrawItemSlots(uint32_t index) { ImGui::PushID(index); + PlandoPushImageButtonStyle(); PlandomizerItemImageCorrection(plandoLogData[index].checkRewardItem); if (ImGui::ImageButton(textureID, imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) { shouldPopup = true; temporaryItem = plandoLogData[index].checkRewardItem; ImGui::OpenPopup("ItemList"); }; + PlandoPopImageButtonStyle(); UIWidgets::Tooltip(plandoLogData[index].checkRewardItem.GetName().english.c_str()); PlandomizerOverlayText(std::make_pair(plandoLogData[index].checkRewardItem, 1)); PlandomizerDrawItemPopup(index); @@ -808,9 +824,19 @@ void PlandomizerDrawShopSlider(uint32_t index) { ImGui::PushID(index); ImGui::Text("Price:"); ImGui::SameLine(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 20.0f); + std::string MinusBTNName = " - ##Price"; + if (ImGui::Button(MinusBTNName.c_str()) && plandoLogData[index].shopPrice > 0) { + plandoLogData[index].shopPrice--; + } + ImGui::SameLine(); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 40.0f); ImGui::SliderInt("", &plandoLogData[index].shopPrice, 0, 999, "%d Rupees"); ImGui::PopItemWidth(); + ImGui::SameLine(); + std::string PlusBTNName = " + ##Price"; + if (ImGui::Button(PlusBTNName.c_str()) && plandoLogData[index].shopPrice < 999) { + plandoLogData[index].shopPrice++; + } ImGui::PopID(); } @@ -825,10 +851,12 @@ void PlandomizerDrawIceTrapSetup(uint32_t index) { ImGui::TableNextColumn(); PlandomizerItemImageCorrection(plandoLogData[index].iceTrapModel); + PlandoPushImageButtonStyle(); if (ImGui::ImageButton(textureID, imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) { shouldTrapPopup = true; ImGui::OpenPopup("TrapList"); }; + PlandoPopImageButtonStyle(); UIWidgets::Tooltip(plandoLogData[index].iceTrapModel.GetName().english.c_str()); PlandomizerDrawIceTrapPopUp(index); ImGui::SameLine(); @@ -847,7 +875,7 @@ void PlandomizerDrawIceTrapSetup(uint32_t index) { plandoLogData[index].iceTrapName = trapTextInput.c_str(); } - if (plandoLogData[index].shopPrice > -1) { + if (plandoLogData[index].shopPrice >= 0) { PlandomizerDrawShopSlider(index); } ImGui::EndTable(); @@ -860,7 +888,7 @@ void PlandomizerDrawOptions() { ImGui::TableNextColumn(); ImGui::SeparatorText("Load/Save Spoiler Log"); PlandomizerPopulateSeedList(); - static int32_t selectedList = 0; + static size_t selectedList = 0; if (existingSeedList.size() != 0) { if (ImGui::BeginCombo("##JsonFiles", existingSeedList[selectedList].c_str())) { for (size_t i = 0; i < existingSeedList.size(); i++) { @@ -895,15 +923,13 @@ void PlandomizerDrawOptions() { ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (ImGui::GetContentRegionAvail().x * 0.5f) - (34.0f * 5.0f)); if (spoilerLogData.size() > 0) { ImGui::BeginTable("HashIcons", 5); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f)); for (int i = 0; i < 5; i++) { ImGui::TableSetupColumn("Icon", ImGuiTableColumnFlags_WidthFixed, 34.0f); } ImGui::TableNextColumn(); - int32_t index = 0; + size_t index = 0; + PlandoPushImageButtonStyle(); for (auto& hash : plandoHash) { ImGui::PushID(index); textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(gSeedTextures[hash].tex); @@ -930,7 +956,7 @@ void PlandomizerDrawOptions() { ImGui::PopID(); index++; } - ImGui::PopStyleColor(3); + PlandoPopImageButtonStyle(); ImGui::EndTable(); } else { ImGui::Text("No Spoiler Log Loaded"); @@ -1039,9 +1065,6 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) { ImGui::TableSetupColumn("Additional Options"); ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableHeadersRow(); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f)); for (auto& spoilerData : spoilerLogData) { auto checkID = Rando::StaticData::locationNameToEnum[spoilerData.checkName]; @@ -1070,7 +1093,6 @@ void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) { } index++; } - ImGui::PopStyleColor(3); ImGui::EndTable(); ImGui::EndChild(); } diff --git a/soh/soh/Enhancements/timesplits/TimeSplits.cpp b/soh/soh/Enhancements/timesplits/TimeSplits.cpp index 7471acfa7..330e39989 100644 --- a/soh/soh/Enhancements/timesplits/TimeSplits.cpp +++ b/soh/soh/Enhancements/timesplits/TimeSplits.cpp @@ -301,6 +301,16 @@ void TimeSplitsGetImageSize(uint32_t item) { } } +void SplitsPushImageButtonStyle(){ + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f)); +} + +void SplitsPopImageButtonStyle(){ + ImGui::PopStyleColor(3); +} + void TimeSplitsUpdateSplitStatus() { uint32_t index = 0; for (auto& data : splitList) { @@ -310,7 +320,7 @@ void TimeSplitsUpdateSplitStatus() { } index++; } - for (int i = index; i < splitList.size(); i++) { + for (size_t i = index; i < splitList.size(); i++) { if (splitList[i].splitTimeStatus != SPLIT_STATUS_ACTIVE && splitList[i].splitTimeStatus != SPLIT_STATUS_COLLECTED) { splitList[i].splitTimeStatus = SPLIT_STATUS_INACTIVE; } @@ -421,11 +431,28 @@ void TimeSplitsPopUpContext() { if (popupID == ITEM_SKULL_TOKEN) { ImGui::BeginTable("Token Table", 2); ImGui::TableNextColumn(); + SplitsPushImageButtonStyle(); ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("QUEST_SKULL_TOKEN"), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 2.0f, ImVec4(0, 0, 0, 0)); ImGui::TableNextColumn(); + SplitsPopImageButtonStyle(); ImGui::PushItemWidth(150.0f); + + ImGui::BeginGroup(); + std::string MinusBTNName = " - ##Set Tokens"; + ImGui::SameLine(); + if (ImGui::Button(MinusBTNName.c_str()) && skullTokenCount > 0) { + skullTokenCount--; + } + ImGui::SameLine(); ImGui::SliderInt("##count", &skullTokenCount, 0, 100, "%d Tokens"); + std::string PlusBTNName = " + ##Set Tokens"; + ImGui::SameLine(); + if (ImGui::Button(PlusBTNName.c_str()) && skullTokenCount < 100) { + skullTokenCount++; + } + ImGui::EndGroup(); + ImGui::PopItemWidth(); if (ImGui::Button("Set Tokens")) { auto findID = std::find_if(splitObjectList.begin(), splitObjectList.end(), [&](const SplitObject& obj) { return obj.splitID == ITEM_SKULL_TOKEN; }); @@ -442,6 +469,7 @@ void TimeSplitsPopUpContext() { ImGui::EndTable(); } else { int rowIndex = 0; + SplitsPushImageButtonStyle(); for (auto item : popupList[popupID]) { auto findID = std::find_if(splitObjectList.begin(), splitObjectList.end(), [&](const SplitObject& obj) { return obj.splitID == item; }); if (findID == splitObjectList.end()) { @@ -468,7 +496,7 @@ void TimeSplitsPopUpContext() { if (popupID <= ITEM_SLINGSHOT && popupID != -1) { ImVec2 imageMin = ImGui::GetItemRectMin(); ImVec2 imageMax = ImGui::GetItemRectMax(); - ImVec2 imageSize = ImVec2(imageMax.x - imageMin.x, imageMax.y - imageMin.y); + //ImVec2 imageSize = ImVec2(imageMax.x - imageMin.x, imageMax.y - imageMin.y); UNUSED ImVec2 textPos = ImVec2(imageMax.x - ImGui::CalcTextSize("00").x - 5, imageMax.y - ImGui::CalcTextSize("00").y - 5); @@ -484,6 +512,7 @@ void TimeSplitsPopUpContext() { } rowIndex++; } + SplitsPopImageButtonStyle(); } ImGui::EndPopup(); } @@ -610,10 +639,8 @@ void TimeSplitsDrawSplitsList() { ImGui::TableSetupColumn("Prev. Best"); ImGui::TableHeadersRow(); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f)); + SplitsPushImageButtonStyle(); for (auto& split : splitList) { ImGui::TableNextColumn(); TimeSplitsSplitBestTimeDisplay(split); @@ -648,10 +675,10 @@ void TimeSplitsDrawSplitsList() { dragIndex++; } + SplitsPopImageButtonStyle(); TimeSplitsPostDragAndDrop(); - ImGui::PopStyleColor(3); ImGui::PopStyleVar(1); ImGui::EndTable(); ImGui::EndChild(); @@ -677,7 +704,7 @@ void TimeSplitsDrawItemList(uint32_t type) { ImGui::BeginChild("Item Child"); ImGui::BeginTable("Item List", tableSize); - for (int i = 0; i < tableSize; i++) { + for (size_t i = 0; i < tableSize; i++) { if (i == 0) { ImGui::TableSetupColumn("Item Image", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHeaderLabel, 39.0f); } else { @@ -689,15 +716,12 @@ void TimeSplitsDrawItemList(uint32_t type) { } } - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f)); - for (auto& split : splitObjectList) { if (split.splitType == type) { ImGui::TableNextColumn(); ImGui::PushID(split.splitID); TimeSplitsGetImageSize(split.splitID); + SplitsPushImageButtonStyle(); if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(split.splitImage), imageSize, ImVec2(0, 0), ImVec2(1, 1), imagePadding, ImVec4(0, 0, 0, 0), split.splitTint)) { @@ -715,6 +739,7 @@ void TimeSplitsDrawItemList(uint32_t type) { } } } + SplitsPopImageButtonStyle(); TimeSplitsPopUpContext(); ImGui::PopID(); @@ -729,7 +754,6 @@ void TimeSplitsDrawItemList(uint32_t type) { } } - ImGui::PopStyleColor(3); ImGui::EndTable(); ImGui::EndChild(); } diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index b19749fb2..a133a8ef9 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -583,9 +583,9 @@ void DrawSettingsMenu() { ImGui::Text("Position"); UIWidgets::EnhancementCombobox(CVAR_SETTING("Notifications.Position"), notificationPosition, 0); - UIWidgets::EnhancementSliderFloat("Duration: %.0f seconds", "##NotificationDuration", CVAR_SETTING("Notifications.Duration"), 3.0f, 30.0f, "", 10.0f, false, false, false); - UIWidgets::EnhancementSliderFloat("BG Opacity: %.1f %%", "##NotificaitonBgOpacity", CVAR_SETTING("Notifications.BgOpacity"), 0.0f, 1.0f, "", 0.5f, true, false, false); - UIWidgets::EnhancementSliderFloat("Size: %.1f", "##NotificaitonSize", CVAR_SETTING("Notifications.Size"), 1.0f, 5.0f, "", 1.8f, false, false, false); + UIWidgets::EnhancementSliderFloat("Duration: %.1f seconds", "##NotificationDuration", CVAR_SETTING("Notifications.Duration"), 3.0f, 30.0f, "", 10.0f, false, true, false); + UIWidgets::EnhancementSliderFloat("BG Opacity: %.1f %%", "##NotificaitonBgOpacity", CVAR_SETTING("Notifications.BgOpacity"), 0.0f, 1.0f, "", 0.5f, true, true, false); + UIWidgets::EnhancementSliderFloat("Size: %.1f", "##NotificaitonSize", CVAR_SETTING("Notifications.Size"), 1.0f, 20.0f, "", 1.8f, false, true, false); UIWidgets::Spacer(0); @@ -714,23 +714,15 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 4, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", CVAR_ENHANCEMENT("FasterHeavyBlockLift"), false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); - UIWidgets::PaddedEnhancementCheckbox("Faster Rupee Accumulator", CVAR_ENHANCEMENT("TimeSavers.FasterRupeeAccumulator"), false, false); UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", CVAR_ENHANCEMENT("FastDrops"), true, false); UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", CVAR_ENHANCEMENT("FastOcarinaPlayback"), true, false); UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); - static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; - UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", CVAR_ENHANCEMENT("InstantScarecrow"), true, false, - forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); - UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", CVAR_ENHANCEMENT("SkipArrowAnimation"), true, false); UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", CVAR_ENHANCEMENT("SkipSaveConfirmation"), true, false); UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", CVAR_ENHANCEMENT("FastFarores"), true, false); UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell."); - UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), true, false); - UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); ImGui::TableNextColumn(); UIWidgets::Spacer(0); @@ -797,6 +789,14 @@ void DrawEnhancementsMenu() { "- Not within range of Ocarina playing spots"); UIWidgets::PaddedEnhancementCheckbox("Pause Warp", CVAR_ENHANCEMENT("PauseWarp"), true, false); UIWidgets::Tooltip("Selection of warp song in pause menu initiates warp. Disables song playback."); + UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", CVAR_ENHANCEMENT("SkipSwimDeepEndAnim"), true, false); + UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater."); + bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); + static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", CVAR_ENHANCEMENT("InstantScarecrow"), true, false, + forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); + UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); + ImGui::EndTable(); ImGui::EndMenu(); @@ -1269,6 +1269,9 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Targetable Hookshot Reticle", CVAR_ENHANCEMENT("HookshotableReticle"), true, false); UIWidgets::Tooltip("Use a different color when aiming at hookshotable collision"); + UIWidgets::PaddedEnhancementCheckbox("Faster Rupee Accumulator", CVAR_ENHANCEMENT("TimeSavers.FasterRupeeAccumulator"), true, false); + UIWidgets::Tooltip("Causes your wallet to fill and empty faster when you gain or lose money."); + ImGui::EndMenu(); } From a92c08dea1948481647a1d1061175162edd431f4 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Wed, 27 Nov 2024 18:33:50 +0100 Subject: [PATCH 08/28] Fix some situations where trade items spoiled (#4569) * Fix some situations where trade items reverted * Update z_game_over.c * Hopefully fix mac --- soh/src/code/z_game_over.c | 4 +++- soh/src/code/z_parameter.c | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/soh/src/code/z_game_over.c b/soh/src/code/z_game_over.c index a2bdfc1a5..1850133aa 100644 --- a/soh/src/code/z_game_over.c +++ b/soh/src/code/z_game_over.c @@ -1,5 +1,7 @@ #include "global.h" #include "soh/OTRGlobals.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" void GameOver_Init(PlayState* play) { play->gameOverCtx.state = GAMEOVER_INACTIVE; @@ -34,7 +36,7 @@ void GameOver_Update(PlayState* play) { gSaveContext.eventInf[1] &= ~1; // search inventory for spoiling items and revert if necessary - if (!(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + if (GameInteractor_Should(VB_REVERT_SPOILING_ITEMS, true)) { for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 0792e71cf..754e40ae2 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -5685,17 +5685,19 @@ void Interface_Draw(PlayState* play) { } // Revert any spoiling trade quest items - for (svar1 = 0; svar1 < ARRAY_COUNT(gSpoilingItems); svar1++) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[svar1]) { - gSaveContext.eventInf[0] &= 0x7F80; - osSyncPrintf("EVENT_INF=%x\n", gSaveContext.eventInf[0]); - play->nextEntranceIndex = spoilingItemEntrances[svar1]; - INV_CONTENT(gSpoilingItemReverts[svar1]) = gSpoilingItemReverts[svar1]; + if (GameInteractor_Should(VB_REVERT_SPOILING_ITEMS, true)) { + for (svar1 = 0; svar1 < ARRAY_COUNT(gSpoilingItems); svar1++) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[svar1]) { + gSaveContext.eventInf[0] &= 0x7F80; + osSyncPrintf("EVENT_INF=%x\n", gSaveContext.eventInf[0]); + play->nextEntranceIndex = spoilingItemEntrances[svar1]; + INV_CONTENT(gSpoilingItemReverts[svar1]) = gSpoilingItemReverts[svar1]; - for (svar2 = 1; svar2 < ARRAY_COUNT(gSaveContext.equips.buttonItems); svar2++) { - if (gSaveContext.equips.buttonItems[svar2] == gSpoilingItems[svar1]) { - gSaveContext.equips.buttonItems[svar2] = gSpoilingItemReverts[svar1]; - Interface_LoadItemIcon1(play, svar2); + for (svar2 = 1; svar2 < ARRAY_COUNT(gSaveContext.equips.buttonItems); svar2++) { + if (gSaveContext.equips.buttonItems[svar2] == gSpoilingItems[svar1]) { + gSaveContext.equips.buttonItems[svar2] = gSpoilingItemReverts[svar1]; + Interface_LoadItemIcon1(play, svar2); + } } } } From f7378a9f76dd2e17dddd3160c9e7e36ae89fb0fd Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Fri, 29 Nov 2024 11:38:40 -0700 Subject: [PATCH 09/28] Cosmetics cleanup (#4587) * Convert defaultColor from ImVec4 to Color_RGBA8. Convert defaultColor's ints to floats when being applied to currentColor in the macro. * Address previous cleanup comments. Surround `Message` tab in an advanced check. * Resolve warnings and cleanup whitespace/formatting. * Make Color_RGBA8 constructing function because... platform differences... * Function name clarification. * Remove default color conversion, reference default colors directly in CosmeticOption initialization. --- .../cosmetics/CosmeticsEditor.cpp | 782 +++++++++--------- soh/src/code/z_parameter.c | 2 + 2 files changed, 377 insertions(+), 407 deletions(-) diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 8a9f3d97a..30b725094 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -15,46 +15,46 @@ #include "soh/ResourceManagerHelpers.h" extern "C" { - #include "z64.h" - #include "macros.h" - #include "soh/cvar_prefixes.h" - #include "objects/object_link_boy/object_link_boy.h" - #include "objects/object_link_child/object_link_child.h" - #include "objects/object_gi_shield_3/object_gi_shield_3.h" - #include "objects/object_gi_heart/object_gi_heart.h" - #include "objects/object_gi_bow/object_gi_bow.h" - #include "objects/object_gi_bracelet/object_gi_bracelet.h" - #include "objects/object_gi_rupy/object_gi_rupy.h" - #include "objects/object_gi_magicpot/object_gi_magicpot.h" - #include "objects/object_gi_gloves/object_gi_gloves.h" - #include "objects/object_gi_hammer/object_gi_hammer.h" - #include "objects/object_gi_sutaru/object_gi_sutaru.h" - #include "objects/object_st/object_st.h" - #include "objects/object_gi_boomerang/object_gi_boomerang.h" - #include "objects/object_gi_liquid/object_gi_liquid.h" - #include "objects/object_gi_bow/object_gi_bow.h" - #include "objects/object_gi_hearts/object_gi_hearts.h" - #include "objects/gameplay_keep/gameplay_keep.h" - #include "objects/object_gi_sword_1/object_gi_sword_1.h" - #include "objects/object_gi_longsword/object_gi_longsword.h" - #include "objects/object_gi_clothes/object_gi_clothes.h" - #include "objects/object_gi_bomb_2/object_gi_bomb_2.h" - #include "objects/object_gla/object_gla.h" - #include "objects/object_toki_objects/object_toki_objects.h" - #include "objects/object_gi_pachinko/object_gi_pachinko.h" - #include "objects/object_trap/object_trap.h" - #include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" - #include "objects/object_gjyo_objects/object_gjyo_objects.h" - #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" - #include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h" - #include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" - #include "overlays/ovl_Magic_Wind/ovl_Magic_Wind.h" - #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" - extern PlayState* gPlayState; - void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); - void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const char* patchName, int destinationIndex, int sourceIndex); - void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); - u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); +#include "z64.h" +#include "macros.h" +#include "soh/cvar_prefixes.h" +#include "objects/object_link_boy/object_link_boy.h" +#include "objects/object_link_child/object_link_child.h" +#include "objects/object_gi_shield_3/object_gi_shield_3.h" +#include "objects/object_gi_heart/object_gi_heart.h" +#include "objects/object_gi_bow/object_gi_bow.h" +#include "objects/object_gi_bracelet/object_gi_bracelet.h" +#include "objects/object_gi_rupy/object_gi_rupy.h" +#include "objects/object_gi_magicpot/object_gi_magicpot.h" +#include "objects/object_gi_gloves/object_gi_gloves.h" +#include "objects/object_gi_hammer/object_gi_hammer.h" +#include "objects/object_gi_sutaru/object_gi_sutaru.h" +#include "objects/object_st/object_st.h" +#include "objects/object_gi_boomerang/object_gi_boomerang.h" +#include "objects/object_gi_liquid/object_gi_liquid.h" +#include "objects/object_gi_bow/object_gi_bow.h" +#include "objects/object_gi_hearts/object_gi_hearts.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "objects/object_gi_sword_1/object_gi_sword_1.h" +#include "objects/object_gi_longsword/object_gi_longsword.h" +#include "objects/object_gi_clothes/object_gi_clothes.h" +#include "objects/object_gi_bomb_2/object_gi_bomb_2.h" +#include "objects/object_gla/object_gla.h" +#include "objects/object_toki_objects/object_toki_objects.h" +#include "objects/object_gi_pachinko/object_gi_pachinko.h" +#include "objects/object_trap/object_trap.h" +#include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" +#include "objects/object_gjyo_objects/object_gjyo_objects.h" +#include "textures/nintendo_rogo_static/nintendo_rogo_static.h" +#include "objects/object_gi_rabit_mask/object_gi_rabit_mask.h" +#include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h" +#include "overlays/ovl_Magic_Wind/ovl_Magic_Wind.h" +#include "textures/nintendo_rogo_static/nintendo_rogo_static.h" +extern PlayState* gPlayState; +void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); +void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const char* patchName, int destinationIndex, int sourceIndex); +void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); +u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); } #define PATCH_GFX(path, name, cvar, index, instruction) \ @@ -69,24 +69,24 @@ extern "C" { static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL; std::map<CosmeticGroup, const char*> groupLabels = { - { COSMETICS_GROUP_LINK, "Link" }, + { COSMETICS_GROUP_LINK, "Link" }, { COSMETICS_GROUP_MIRRORSHIELD, "Mirror Shield" }, - { COSMETICS_GROUP_SWORDS, "Swords" }, - { COSMETICS_GROUP_GLOVES, "Gloves" }, - { COSMETICS_GROUP_EQUIPMENT, "Equipment" }, - { COSMETICS_GROUP_CONSUMABLE, "Consumables" }, - { COSMETICS_GROUP_HUD, "HUD" }, - { COSMETICS_GROUP_KALEIDO, "Pause Menu" }, - { COSMETICS_GROUP_TITLE, "Title Screen" }, - { COSMETICS_GROUP_NPC, "NPCs" }, - { COSMETICS_GROUP_WORLD, "World" }, - { COSMETICS_GROUP_MAGIC, "Magic Effects" }, - { COSMETICS_GROUP_ARROWS, "Arrow Effects" }, - { COSMETICS_GROUP_SPIN_ATTACK, "Spin Attack" }, - { COSMETICS_GROUP_TRAILS, "Trails" }, - { COSMETICS_GROUP_NAVI, "Navi" }, - { COSMETICS_GROUP_IVAN, "Ivan" }, - { COSMETICS_GROUP_MESSAGE, "Message" }, + { COSMETICS_GROUP_SWORDS, "Swords" }, + { COSMETICS_GROUP_GLOVES, "Gloves" }, + { COSMETICS_GROUP_EQUIPMENT, "Equipment" }, + { COSMETICS_GROUP_CONSUMABLE, "Consumables" }, + { COSMETICS_GROUP_HUD, "HUD" }, + { COSMETICS_GROUP_KALEIDO, "Pause Menu" }, + { COSMETICS_GROUP_TITLE, "Title Screen" }, + { COSMETICS_GROUP_NPC, "NPCs" }, + { COSMETICS_GROUP_WORLD, "World" }, + { COSMETICS_GROUP_MAGIC, "Magic Effects" }, + { COSMETICS_GROUP_ARROWS, "Arrow Effects" }, + { COSMETICS_GROUP_SPIN_ATTACK, "Spin Attack" }, + { COSMETICS_GROUP_TRAILS, "Trails" }, + { COSMETICS_GROUP_NAVI, "Navi" }, + { COSMETICS_GROUP_IVAN, "Ivan" }, + { COSMETICS_GROUP_MESSAGE, "Message" }, }; typedef struct { @@ -97,16 +97,21 @@ typedef struct { std::string label; CosmeticGroup group; ImVec4 currentColor; - ImVec4 defaultColor; + Color_RGBA8 defaultColor; bool supportsAlpha; bool supportsRainbow; bool advancedOption; } CosmeticOption; +Color_RGBA8 ColorRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + Color_RGBA8 color = { r, g, b, a }; + return color; +} + #define COSMETIC_OPTION(id, label, group, defaultColor, supportsAlpha, supportsRainbow, advancedOption) \ { id, { \ CVAR_COSMETIC(id ".Value"), CVAR_COSMETIC(id ".Rainbow"), CVAR_COSMETIC(id ".Locked"), CVAR_COSMETIC(id ".Changed"), label, group, \ - defaultColor, defaultColor, \ + ImVec4(defaultColor.r / 255.0f, defaultColor.g / 255.0f, defaultColor.b / 255.0f, defaultColor.a / 255.0f), defaultColor, \ supportsAlpha, supportsRainbow, advancedOption \ } } @@ -184,91 +189,91 @@ typedef struct { colors were darker than the gDPSetPrimColor. You will see many more examples of this below in the `ApplyOrResetCustomGfxPatches` method */ static std::map<std::string, CosmeticOption> cosmeticOptions = { - COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ImVec4( 30, 105, 27, 255), false, true, false), - COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ImVec4(100, 20, 0, 255), false, true, false), - COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ImVec4( 0, 60, 100, 255), false, true, false), - COSMETIC_OPTION("Link.Hair", "Hair", COSMETICS_GROUP_LINK, ImVec4(255, 173, 27, 255), false, true, true), - COSMETIC_OPTION("Link.Linen", "Linen", COSMETICS_GROUP_LINK, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Link.Boots", "Boots", COSMETICS_GROUP_LINK, ImVec4( 93, 44, 18, 255), false, true, true), + COSMETIC_OPTION("Link.KokiriTunic", "Kokiri Tunic", COSMETICS_GROUP_LINK, ColorRGBA8( 30, 105, 27, 255), false, true, false), + COSMETIC_OPTION("Link.GoronTunic", "Goron Tunic", COSMETICS_GROUP_LINK, ColorRGBA8(100, 20, 0, 255), false, true, false), + COSMETIC_OPTION("Link.ZoraTunic", "Zora Tunic", COSMETICS_GROUP_LINK, ColorRGBA8( 0, 60, 100, 255), false, true, false), + COSMETIC_OPTION("Link.Hair", "Hair", COSMETICS_GROUP_LINK, ColorRGBA8(255, 173, 27, 255), false, true, true), + COSMETIC_OPTION("Link.Linen", "Linen", COSMETICS_GROUP_LINK, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Link.Boots", "Boots", COSMETICS_GROUP_LINK, ColorRGBA8( 93, 44, 18, 255), false, true, true), - COSMETIC_OPTION("MirrorShield.Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(215, 0, 0, 255), false, true, false), - COSMETIC_OPTION("MirrorShield.Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("MirrorShield.Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ImVec4(205, 225, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield.Body", "Body", COSMETICS_GROUP_MIRRORSHIELD, ColorRGBA8(215, 0, 0, 255), false, true, false), + COSMETIC_OPTION("MirrorShield.Mirror", "Mirror", COSMETICS_GROUP_MIRRORSHIELD, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("MirrorShield.Emblem", "Emblem", COSMETICS_GROUP_MIRRORSHIELD, ColorRGBA8(205, 225, 255, 255), false, true, true), - COSMETIC_OPTION("Swords.KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Swords.MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Swords.BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Swords.KokiriBlade", "Kokiri Sword Blade", COSMETICS_GROUP_SWORDS, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Swords.MasterBlade", "Master Sword Blade", COSMETICS_GROUP_SWORDS, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Swords.BiggoronBlade", "Biggoron Sword Blade", COSMETICS_GROUP_SWORDS, ColorRGBA8(255, 255, 255, 255), false, true, false), /* Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Swords.KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4(160, 100, 15, 255), false, true, true), - COSMETIC_OPTION("Swords.MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), - COSMETIC_OPTION("Swords.BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ImVec4( 80, 80, 168, 255), false, true, true), + COSMETIC_OPTION("Swords.KokiriHilt", "Kokiri Sword Hilt", COSMETICS_GROUP_SWORDS, ColorRGBA8(160, 100, 15, 255), false, true, true), + COSMETIC_OPTION("Swords.MasterHilt", "Master Sword Hilt", COSMETICS_GROUP_SWORDS, ColorRGBA8( 80, 80, 168, 255), false, true, true), + COSMETIC_OPTION("Swords.BiggoronHilt", "Biggoron Sword Hilt", COSMETICS_GROUP_SWORDS, ColorRGBA8( 80, 80, 168, 255), false, true, true), */ - COSMETIC_OPTION("Gloves.GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 170, 255), false, true, false), - COSMETIC_OPTION("Gloves.SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Gloves.GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ImVec4(254, 207, 15, 255), false, true, false), - COSMETIC_OPTION("Gloves.GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ImVec4(255, 60, 100, 255), false, true, true), + COSMETIC_OPTION("Gloves.GoronBracelet", "Goron Bracelet", COSMETICS_GROUP_GLOVES, ColorRGBA8(255, 255, 170, 255), false, true, false), + COSMETIC_OPTION("Gloves.SilverGauntlets", "Silver Gauntlets", COSMETICS_GROUP_GLOVES, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Gloves.GoldenGauntlets", "Golden Gauntlets", COSMETICS_GROUP_GLOVES, ColorRGBA8(254, 207, 15, 255), false, true, false), + COSMETIC_OPTION("Gloves.GauntletsGem", "Gauntlets Gem", COSMETICS_GROUP_GLOVES, ColorRGBA8(255, 60, 100, 255), false, true, true), - COSMETIC_OPTION("Equipment.BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, false), - COSMETIC_OPTION("Equipment.BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 50, 150, 255), false, true, true), + COSMETIC_OPTION("Equipment.BoomerangBody", "Boomerang Body", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(160, 100, 0, 255), false, true, false), + COSMETIC_OPTION("Equipment.BoomerangGem", "Boomerang Gem", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 50, 150, 255), false, true, true), /* Todo (Cosmetics): Broken, need a better way to grayscale - COSMETIC_OPTION("Equipment.SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(160, 100, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment.SlingshotBody", "Slingshot Body", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(160, 100, 0, 255), false, true, true), */ - COSMETIC_OPTION("Equipment.SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment.HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ImVec4(155, 192, 201, 255), false, true, false), - COSMETIC_OPTION("Equipment.HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4(110, 60, 0, 255), false, true, true), - COSMETIC_OPTION("Equipment.HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.SlingshotString", "Slingshot String", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.HammerHead", "Hammer Head", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(155, 192, 201, 255), false, true, false), + COSMETIC_OPTION("Equipment.HammerHandle", "Hammer Handle", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(110, 60, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment.HookshotChain", "Hookshot Chain", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 255, 255, 255), false, true, true), /* Todo (Cosmetics): Implement - COSMETIC_OPTION("Equipment.HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Equipment.HookshotTip", "Hookshot Tip", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 255, 255, 255), false, true, false), */ - COSMETIC_OPTION("HookshotReticle.Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 255, 0, 255), false, true, false), - COSMETIC_OPTION("HookshotReticle.NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Equipment.BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Equipment.BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment.BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(140, 90, 10, 255), false, true, false), - COSMETIC_OPTION("Equipment.BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ImVec4( 50, 150, 255, 255), false, true, true), - COSMETIC_OPTION("Equipment.ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ImVec4( 0, 100, 150, 255), false, true, true), - COSMETIC_OPTION("Equipment.ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ImVec4(180, 130, 50, 255), false, true, true), - COSMETIC_OPTION("Equipment.BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ImVec4(255, 235, 109, 255), false, true, true), + COSMETIC_OPTION("HookshotReticle.Target", "Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8( 0, 255, 0, 255), false, true, false), + COSMETIC_OPTION("HookshotReticle.NonTarget", "Non-Hookshotable Reticle", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Equipment.BowTips", "Bow Tips", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Equipment.BowString", "Bow String", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.BowBody", "Bow Body", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(140, 90, 10, 255), false, true, false), + COSMETIC_OPTION("Equipment.BowHandle", "Bow Handle", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8( 50, 150, 255, 255), false, true, true), + COSMETIC_OPTION("Equipment.ChuFace", "Bombchu Face", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8( 0, 100, 150, 255), false, true, true), + COSMETIC_OPTION("Equipment.ChuBody", "Bombchu Body", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(180, 130, 50, 255), false, true, true), + COSMETIC_OPTION("Equipment.BunnyHood", "Bunny Hood", COSMETICS_GROUP_EQUIPMENT, ColorRGBA8(255, 235, 109, 255), false, true, true), - COSMETIC_OPTION("Consumable.Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 70, 50, 255), false, true, false), - COSMETIC_OPTION("Consumable.HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 40, 60, 255), false, true, true), - COSMETIC_OPTION("Consumable.DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), - COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), - COSMETIC_OPTION("Consumable_MagicInfinite", "Infinite Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 0, 200, 255), false, true, true), - COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable.BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Consumable.PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(150, 50, 255, 255), false, true, true), - COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 190, 55, 255), false, true, true), - COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.Hearts", "Hearts", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 70, 50, 255), false, true, false), + COSMETIC_OPTION("Consumable.HeartBorder", "Heart Border", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8( 50, 40, 60, 255), false, true, true), + COSMETIC_OPTION("Consumable.DDHearts", "DD Hearts", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8( 0, 200, 0, 255), false, true, false), + COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(250, 250, 0, 255), false, true, true), + COSMETIC_OPTION("Consumable_MagicInfinite", "Infinite Magic", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8( 0, 0, 200, 255), false, true, true), + COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8( 50, 255, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable.BlueRupee", "Blue Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8( 50, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.RedRupee", "Red Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Consumable.PurpleRupee", "Purple Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(150, 50, 255, 255), false, true, true), + COSMETIC_OPTION("Consumable.GoldRupee", "Gold Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 190, 55, 255), false, true, true), + COSMETIC_OPTION("Consumable.SilverRupee", "Silver Rupee", COSMETICS_GROUP_CONSUMABLE, ColorRGBA8(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("HUD.AButton", "A Button", COSMETICS_GROUP_HUD, ImVec4( 90, 90, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.BButton", "B Button", COSMETICS_GROUP_HUD, ImVec4( 0, 150, 0, 255), false, true, false), - COSMETIC_OPTION("HUD.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, false), - COSMETIC_OPTION("HUD.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ImVec4(255, 160, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.StartButton", "Start Button", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, false), - COSMETIC_OPTION("HUD.Dpad", "Dpad", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ImVec4(200, 230, 255, 255), false, true, true), - COSMETIC_OPTION("HUD.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("HUD.Minimap", "Minimap", COSMETICS_GROUP_HUD, ImVec4( 0, 255, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ImVec4(200, 255, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ImVec4(200, 0, 0, 255), false, true, true), - COSMETIC_OPTION("HUD.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ImVec4(255, 0, 0, 255), true, true, false), - COSMETIC_OPTION("HUD.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, true), - COSMETIC_OPTION("HUD.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), true, true, false), - COSMETIC_OPTION("HUD.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ImVec4( 0, 0, 0, 80), true, true, true), - COSMETIC_OPTION("HUD.TitleCard.Map", "Map Title Card", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("HUD.TitleCard.Boss", "Boss Title Card", COSMETICS_GROUP_HUD, ImVec4(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.AButton", "A Button", COSMETICS_GROUP_HUD, ColorRGBA8( 90, 90, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.BButton", "B Button", COSMETICS_GROUP_HUD, ColorRGBA8( 0, 150, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.CButtons", "C Buttons", COSMETICS_GROUP_HUD, ColorRGBA8(255, 160, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.CUpButton", "C Up Button", COSMETICS_GROUP_HUD, ColorRGBA8(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CDownButton", "C Down Button", COSMETICS_GROUP_HUD, ColorRGBA8(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CLeftButton", "C Left Button", COSMETICS_GROUP_HUD, ColorRGBA8(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.CRightButton", "C Right Button", COSMETICS_GROUP_HUD, ColorRGBA8(255, 160, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.StartButton", "Start Button", COSMETICS_GROUP_HUD, ColorRGBA8(200, 0, 0, 255), false, true, false), + COSMETIC_OPTION("HUD.Dpad", "Dpad", COSMETICS_GROUP_HUD, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.KeyCount", "Key Count", COSMETICS_GROUP_HUD, ColorRGBA8(200, 230, 255, 255), false, true, true), + COSMETIC_OPTION("HUD.StoneOfAgony", "Stone of Agony", COSMETICS_GROUP_HUD, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("HUD.Minimap", "Minimap", COSMETICS_GROUP_HUD, ColorRGBA8( 0, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.MinimapPosition", "Minimap Position", COSMETICS_GROUP_HUD, ColorRGBA8(200, 255, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.MinimapEntrance", "Minimap Entrance", COSMETICS_GROUP_HUD, ColorRGBA8(200, 0, 0, 255), false, true, true), + COSMETIC_OPTION("HUD.EnemyHealthBar", "Enemy Health Bar", COSMETICS_GROUP_HUD, ColorRGBA8(255, 0, 0, 255), true, true, false), + COSMETIC_OPTION("HUD.EnemyHealthBorder", "Enemy Health Border", COSMETICS_GROUP_HUD, ColorRGBA8(255, 255, 255, 255), true, true, true), + COSMETIC_OPTION("HUD.NameTagActorText", "Nametag Text", COSMETICS_GROUP_HUD, ColorRGBA8(255, 255, 255, 255), true, true, false), + COSMETIC_OPTION("HUD.NameTagActorBackground", "Nametag Background", COSMETICS_GROUP_HUD, ColorRGBA8( 0, 0, 0, 80), true, true, true), + COSMETIC_OPTION("HUD.TitleCard.Map", "Map Title Card", COSMETICS_GROUP_HUD, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("HUD.TitleCard.Boss", "Boss Title Card", COSMETICS_GROUP_HUD, ColorRGBA8(255, 255, 255, 255), false, true, false), - #define MESSAGE_COSMETIC_OPTION(id, label, r, g, b) COSMETIC_OPTION("Message." id, label, COSMETICS_GROUP_MESSAGE, ImVec4(r, g, b, 255), false, true, true) + #define MESSAGE_COSMETIC_OPTION(id, label, r, g, b) COSMETIC_OPTION("Message." id, label, COSMETICS_GROUP_MESSAGE, ColorRGBA8(r, g, b, 255), false, true, true) MESSAGE_COSMETIC_OPTION("Default.Normal", "Message Default Color", 255, 255, 255), MESSAGE_COSMETIC_OPTION("Default.NoneNoShadow", "Message Default (None No Shadow) Color", 0, 0, 0), @@ -289,110 +294,110 @@ static std::map<std::string, CosmeticOption> cosmeticOptions = { #undef MESSAGE_COSMETIC_OPTION - COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 80, 255), false, true, false), - COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4( 70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kaleido.ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4( 70, 100, 130, 255), false, true, true), - COSMETIC_OPTION("Kaleido.ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 80, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelA", "Item Select Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, false), + COSMETIC_OPTION("Kaleido.ItemSelB", "Item Select Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelC", "Item Select Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 70, 100, 130, 255), false, true, true), + COSMETIC_OPTION("Kaleido.ItemSelD", "Item Select Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 40, 255), false, true, false), - COSMETIC_OPTION("Kaleido.EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ImVec4( 90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ImVec4( 90, 100, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 10, 50, 80, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelA", "Equip Select Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 40, 255), false, true, false), + COSMETIC_OPTION("Kaleido.EquipSelB", "Equip Select Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelC", "Equip Select Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.EquipSelD", "Equip Select Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 10, 50, 80, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunA", "Map Dungeon Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunB", "Map Dungeon Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunC", "Map Dungeon Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelDunD", "Map Dungeon Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 80, 50, 255), false, true, false), - COSMETIC_OPTION("Kaleido.QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kaleido.QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ImVec4(120, 120, 70, 255), false, true, true), - COSMETIC_OPTION("Kaleido.QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 80, 50, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusA", "Quest Status Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 80, 50, 255), false, true, false), + COSMETIC_OPTION("Kaleido.QuestStatusB", "Quest Status Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusC", "Quest Status Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(120, 120, 70, 255), false, true, true), + COSMETIC_OPTION("Kaleido.QuestStatusD", "Quest Status Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 80, 50, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, false), - COSMETIC_OPTION("Kaleido.MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ImVec4(140, 60, 60, 255), false, true, true), - COSMETIC_OPTION("Kaleido.MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 80, 40, 30, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectA", "Map Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, false), + COSMETIC_OPTION("Kaleido.MapSelectB", "Map Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectC", "Map Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(140, 60, 60, 255), false, true, true), + COSMETIC_OPTION("Kaleido.MapSelectD", "Map Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 80, 40, 30, 255), false, true, true), - COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ImVec4( 50, 50, 50, 255), false, true, false), - COSMETIC_OPTION("Kaleido.SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kaleido.SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ImVec4(110, 110, 110, 255), false, true, true), - COSMETIC_OPTION("Kaleido.SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ImVec4( 50, 50, 50, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveA", "Save Color", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 50, 50, 50, 255), false, true, false), + COSMETIC_OPTION("Kaleido.SaveB", "Save Color B", COSMETICS_GROUP_KALEIDO, ColorRGBA8(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveC", "Save Color C", COSMETICS_GROUP_KALEIDO, ColorRGBA8(110, 110, 110, 255), false, true, true), + COSMETIC_OPTION("Kaleido.SaveD", "Save Color D", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 50, 50, 50, 255), false, true, true), - COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ImVec4( 90, 100, 130, 255), true, true, false), + COSMETIC_OPTION("Kaleido.NamePanel", "Name Panel", COSMETICS_GROUP_KALEIDO, ColorRGBA8( 90, 100, 130, 255), true, true, false), - COSMETIC_OPTION("Title.FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ImVec4(100, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Title.NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ImVec4( 0, 0, 255, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ImVec4(150, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ImVec4( 0, 50, 150, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ImVec4( 50, 100, 0, 255), false, true, true), - COSMETIC_OPTION("Title.N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ImVec4(200, 150, 0, 255), false, true, true), + COSMETIC_OPTION("Title.FileChoose", "File Choose", COSMETICS_GROUP_TITLE, ColorRGBA8(100, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Title.NintendoLogo", "Nintendo Logo", COSMETICS_GROUP_TITLE, ColorRGBA8( 0, 0, 255, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoRed", "N64 Red", COSMETICS_GROUP_TITLE, ColorRGBA8(150, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoBlue", "N64 Blue", COSMETICS_GROUP_TITLE, ColorRGBA8( 0, 50, 150, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoGreen", "N64 Green", COSMETICS_GROUP_TITLE, ColorRGBA8( 50, 100, 0, 255), false, true, true), + COSMETIC_OPTION("Title.N64LogoYellow", "N64 Yellow", COSMETICS_GROUP_TITLE, ColorRGBA8(200, 150, 0, 255), false, true, true), /* Todo (Cosmetics): Kinda complicated - COSMETIC_OPTION("Title.FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 170, 255), false, true, false), - COSMETIC_OPTION("Title.FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ImVec4(255, 100, 0, 255), false, true, true), + COSMETIC_OPTION("Title.FirePrimary", "Title Fire Primary", COSMETICS_GROUP_TITLE, ColorRGBA8(255, 255, 170, 255), false, true, false), + COSMETIC_OPTION("Title.FireSecondary", "Title Fire Secondary", COSMETICS_GROUP_TITLE, ColorRGBA8(255, 100, 0, 255), false, true, true), */ - COSMETIC_OPTION("Title.Copyright", "Copyright Text", COSMETICS_GROUP_TITLE, ImVec4(255, 255, 255, 255), true, true, false), + COSMETIC_OPTION("Title.Copyright", "Copyright Text", COSMETICS_GROUP_TITLE, ColorRGBA8(255, 255, 255, 255), true, true, false), - COSMETIC_OPTION("Arrows.NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 150, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows.NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("Arrows.FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 200, 0, 0), false, true, false), - COSMETIC_OPTION("Arrows.FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Arrows.IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ImVec4( 0, 0, 255, 255), false, true, false), - COSMETIC_OPTION("Arrows.IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Arrows.LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Arrows.LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ImVec4(255, 255, 170, 0), false, true, true), + COSMETIC_OPTION("Arrows.NormalPrimary", "Normal Primary", COSMETICS_GROUP_ARROWS, ColorRGBA8( 0, 150, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows.NormalSecondary", "Normal Secondary", COSMETICS_GROUP_ARROWS, ColorRGBA8(255, 255, 170, 255), false, true, true), + COSMETIC_OPTION("Arrows.FirePrimary", "Fire Primary", COSMETICS_GROUP_ARROWS, ColorRGBA8(255, 200, 0, 0), false, true, false), + COSMETIC_OPTION("Arrows.FireSecondary", "Fire Secondary", COSMETICS_GROUP_ARROWS, ColorRGBA8(255, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Arrows.IcePrimary", "Ice Primary", COSMETICS_GROUP_ARROWS, ColorRGBA8( 0, 0, 255, 255), false, true, false), + COSMETIC_OPTION("Arrows.IceSecondary", "Ice Secondary", COSMETICS_GROUP_ARROWS, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Arrows.LightPrimary", "Light Primary", COSMETICS_GROUP_ARROWS, ColorRGBA8(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Arrows.LightSecondary", "Light Secondary", COSMETICS_GROUP_ARROWS, ColorRGBA8(255, 255, 170, 0), false, true, true), - COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 200, 0, 255), false, true, false), - COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(255, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Magic.FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Magic.FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ImVec4(100, 200, 0, 255), false, true, true), - COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ImVec4(170, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ImVec4( 0, 100, 255, 255), false, true, true), + COSMETIC_OPTION("Magic.DinsPrimary", "Din's Primary", COSMETICS_GROUP_MAGIC, ColorRGBA8(255, 200, 0, 255), false, true, false), + COSMETIC_OPTION("Magic.DinsSecondary", "Din's Secondary", COSMETICS_GROUP_MAGIC, ColorRGBA8(255, 0, 0, 255), false, true, true), + COSMETIC_OPTION("Magic.FaroresPrimary", "Farore's Primary", COSMETICS_GROUP_MAGIC, ColorRGBA8(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Magic.FaroresSecondary", "Farore's Secondary", COSMETICS_GROUP_MAGIC, ColorRGBA8(100, 200, 0, 255), false, true, true), + COSMETIC_OPTION("Magic.NayrusPrimary", "Nayru's Primary", COSMETICS_GROUP_MAGIC, ColorRGBA8(170, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Magic.NayrusSecondary", "Nayru's Secondary", COSMETICS_GROUP_MAGIC, ColorRGBA8( 0, 100, 255, 255), false, true, true), - COSMETIC_OPTION("SpinAttack.Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(170, 255, 255, 255), false, true, true), - COSMETIC_OPTION("SpinAttack.Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4( 0, 100, 255, 255), false, true, false), - COSMETIC_OPTION("SpinAttack.Level2Primary", "Level 2 Primary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 255, 170, 255), false, true, true), - COSMETIC_OPTION("SpinAttack.Level2Secondary", "Level 2 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ImVec4(255, 100, 0, 255), false, true, false), + COSMETIC_OPTION("SpinAttack.Level1Primary", "Level 1 Primary", COSMETICS_GROUP_SPIN_ATTACK, ColorRGBA8(170, 255, 255, 255), false, true, true), + COSMETIC_OPTION("SpinAttack.Level1Secondary", "Level 1 Secondary", COSMETICS_GROUP_SPIN_ATTACK, ColorRGBA8( 0, 100, 255, 255), false, true, false), + 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("Trails.Bombchu", "Bombchu", COSMETICS_GROUP_TRAILS, ImVec4(250, 0, 0, 255), false, true, true), - COSMETIC_OPTION("Trails.Boomerang", "Boomerang", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 100, 255), false, true, true), - COSMETIC_OPTION("Trails.KokiriSword", "Kokiri Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails.MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Trails.BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails.Stick", "Stick", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("Trails.Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ImVec4(255, 255, 255, 255), false, true, true), + 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), + COSMETIC_OPTION("Trails.MasterSword", "Master Sword", COSMETICS_GROUP_TRAILS, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Trails.BiggoronSword", "Biggoron Sword", COSMETICS_GROUP_TRAILS, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Stick", "Stick", COSMETICS_GROUP_TRAILS, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("Trails.Hammer", "Hammer", COSMETICS_GROUP_TRAILS, ColorRGBA8(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World.BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), - COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), - COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), - COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ImVec4( 0, 60, 100, 255), false, true, false), + COSMETIC_OPTION("World.BlockOfTime", "Block of Time", COSMETICS_GROUP_WORLD, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ColorRGBA8(240, 255, 180, 255), false, true, true), + COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ColorRGBA8(200, 200, 200, 255), false, true, true), + COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ColorRGBA8(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ColorRGBA8( 0, 60, 100, 255), false, true, false), - COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), - COSMETIC_OPTION("Navi.NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 255), false, true, false), - COSMETIC_OPTION("Navi.NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ImVec4(150, 150, 255, 0), false, true, true), - COSMETIC_OPTION("Navi.EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi.EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ImVec4(200, 155, 0, 0), false, true, true), - COSMETIC_OPTION("Navi.PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 255), false, true, false), - COSMETIC_OPTION("Navi.PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 255, 0, 0), false, true, true), + COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ColorRGBA8( 0, 0, 255, 0), false, true, true), + COSMETIC_OPTION("Navi.NPCPrimary", "NPC Primary", COSMETICS_GROUP_NAVI, ColorRGBA8(150, 150, 255, 255), false, true, false), + COSMETIC_OPTION("Navi.NPCSecondary", "NPC Secondary", COSMETICS_GROUP_NAVI, ColorRGBA8(150, 150, 255, 0), false, true, true), + COSMETIC_OPTION("Navi.EnemyPrimary", "Enemy Primary", COSMETICS_GROUP_NAVI, ColorRGBA8(255, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi.EnemySecondary", "Enemy Secondary", COSMETICS_GROUP_NAVI, ColorRGBA8(200, 155, 0, 0), false, true, true), + COSMETIC_OPTION("Navi.PropsPrimary", "Props Primary", COSMETICS_GROUP_NAVI, ColorRGBA8( 0, 255, 0, 255), false, true, false), + COSMETIC_OPTION("Navi.PropsSecondary", "Props Secondary", COSMETICS_GROUP_NAVI, ColorRGBA8( 0, 255, 0, 0), false, true, true), - COSMETIC_OPTION("Ivan.IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("Ivan.IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ImVec4( 0, 255, 0, 255), false, true, true), + COSMETIC_OPTION("Ivan.IdlePrimary", "Ivan Idle Primary", COSMETICS_GROUP_IVAN, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("Ivan.IdleSecondary", "Ivan Idle Secondary", COSMETICS_GROUP_IVAN, ColorRGBA8( 0, 255, 0, 255), false, true, true), - COSMETIC_OPTION("NPC.FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC.IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.FireKeesePrimary", "Fire Keese Primary", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.FireKeeseSecondary", "Fire Keese Secondary", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.IceKeesePrimary", "Ice Keese Primary", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.IceKeeseSecondary", "Ice Keese Secondary", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, true), // Todo (Cosmetics): Health fairy - COSMETIC_OPTION("NPC.Dog1", "Dog 1", COSMETICS_GROUP_NPC, ImVec4(255, 255, 200, 255), false, true, true), - COSMETIC_OPTION("NPC.Dog2", "Dog 2", COSMETICS_GROUP_NPC, ImVec4(150, 100, 50, 255), false, true, true), - COSMETIC_OPTION("NPC.GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, false), - COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ImVec4( 0, 130, 70, 255), false, true, false), - COSMETIC_OPTION("NPC.Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ImVec4( 90, 0, 140, 255), false, true, false), - COSMETIC_OPTION("NPC.MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ImVec4(255, 255, 255, 255), false, true, true), - COSMETIC_OPTION("NPC.IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ImVec4(245, 255, 205, 255), false, true, false), + COSMETIC_OPTION("NPC.Dog1", "Dog 1", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 200, 255), false, true, true), + COSMETIC_OPTION("NPC.Dog2", "Dog 2", COSMETICS_GROUP_NPC, ColorRGBA8(150, 100, 50, 255), false, true, true), + COSMETIC_OPTION("NPC.GoldenSkulltula", "Golden Skulltula", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, false), + COSMETIC_OPTION("NPC.Kokiri", "Kokiri", COSMETICS_GROUP_NPC, ColorRGBA8( 0, 130, 70, 255), false, true, false), + COSMETIC_OPTION("NPC.Gerudo", "Gerudo", COSMETICS_GROUP_NPC, ColorRGBA8( 90, 0, 140, 255), false, true, false), + COSMETIC_OPTION("NPC.MetalTrap", "Metal Trap", COSMETICS_GROUP_NPC, ColorRGBA8(255, 255, 255, 255), false, true, true), + COSMETIC_OPTION("NPC.IronKnuckles", "Iron Knuckles", COSMETICS_GROUP_NPC, ColorRGBA8(245, 255, 205, 255), false, true, false), }; static const char* MarginCvarList[] { @@ -438,9 +443,9 @@ ImVec4 GetRandomValue() { std::uniform_int_distribution<int> dist(0, 255 - 1); ImVec4 NewColor; - NewColor.x = (float)(dist(rng)) / 255; - NewColor.y = (float)(dist(rng)) / 255; - NewColor.z = (float)(dist(rng)) / 255; + NewColor.x = (float)(dist(rng)) / 255.0f; + NewColor.y = (float)(dist(rng)) / 255.0f; + NewColor.z = (float)(dist(rng)) / 255.0f; return NewColor; } @@ -487,21 +492,21 @@ void CosmeticsUpdateTick() { float rainbowSpeed = CVarGetFloat(CVAR_COSMETIC("RainbowSpeed"), 0.6f); for (auto& [id, cosmeticOption] : cosmeticOptions) { if (cosmeticOption.supportsRainbow && CVarGetInteger(cosmeticOption.rainbowCvar, 0)) { - float frequency = 2 * M_PI / (360 * rainbowSpeed); + double frequency = 2 * M_PI / (360 * rainbowSpeed); Color_RGBA8 newColor; - newColor.r = sin(frequency * (hue + index) + 0) * 127 + 128; - newColor.g = sin(frequency * (hue + index) + (2 * M_PI / 3)) * 127 + 128; - newColor.b = sin(frequency * (hue + index) + (4 * M_PI / 3)) * 127 + 128; + newColor.r = static_cast<uint8_t>(sin(frequency * (hue + index) + 0) * 127) + 128; + newColor.g = static_cast<uint8_t>(sin(frequency * (hue + index) + (2 * M_PI / 3)) * 127) + 128; + newColor.b = static_cast<uint8_t>(sin(frequency * (hue + index) + (4 * M_PI / 3)) * 127) + 128; newColor.a = 255; // For alpha supported options, retain the last set alpha instead of overwriting if (cosmeticOption.supportsAlpha) { - newColor.a = cosmeticOption.currentColor.w * 255; + newColor.a = static_cast<uint8_t>(cosmeticOption.currentColor.w * 255.0f); } - cosmeticOption.currentColor.x = newColor.r / 255.0; - cosmeticOption.currentColor.y = newColor.g / 255.0; - cosmeticOption.currentColor.z = newColor.b / 255.0; - cosmeticOption.currentColor.w = newColor.a / 255.0; + cosmeticOption.currentColor.x = newColor.r / 255.0f; + cosmeticOption.currentColor.y = newColor.g / 255.0f; + cosmeticOption.currentColor.z = newColor.b / 255.0f; + cosmeticOption.currentColor.w = newColor.a / 255.0f; CVarSetColor(cosmeticOption.cvar, newColor); } @@ -509,7 +514,7 @@ void CosmeticsUpdateTick() { // Technically this would work if you replaced "60" with 1 but the hue would be so close it's // indistinguishable, 60 gives us a big enough gap to notice the difference. if (!CVarGetInteger(CVAR_COSMETIC("RainbowSync"), 0)) { - index += (60 * rainbowSpeed); + index += static_cast<int>(60 * rainbowSpeed); } } ApplyOrResetCustomGfxPatches(false); @@ -531,24 +536,21 @@ void CosmeticsUpdateTick() { void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& magicFaroresPrimary = cosmeticOptions.at("Magic.FaroresPrimary"); if (manualChange || CVarGetInteger(magicFaroresPrimary.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {magicFaroresPrimary.defaultColor.x, magicFaroresPrimary.defaultColor.y, magicFaroresPrimary.defaultColor.z, magicFaroresPrimary.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(magicFaroresPrimary.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(magicFaroresPrimary.cvar, magicFaroresPrimary.defaultColor); PATCH_GFX(sInnerCylinderDL, "Magic_FaroresPrimary1", magicFaroresPrimary.changedCvar, 24, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(sOuterCylinderDL, "Magic_FaroresPrimary2", magicFaroresPrimary.changedCvar, 24, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } static CosmeticOption& magicFaroresSecondary = cosmeticOptions.at("Magic.FaroresSecondary"); if (manualChange || CVarGetInteger(magicFaroresSecondary.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {magicFaroresSecondary.defaultColor.x, magicFaroresSecondary.defaultColor.y, magicFaroresSecondary.defaultColor.z, magicFaroresSecondary.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(magicFaroresSecondary.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(magicFaroresSecondary.cvar, magicFaroresSecondary.defaultColor); PATCH_GFX(sInnerCylinderDL, "Magic_FaroresSecondary1", magicFaroresSecondary.changedCvar, 25, gsDPSetEnvColor(color.r, color.g, color.b, 255)); PATCH_GFX(sOuterCylinderDL, "Magic_FaroresSecondary2", magicFaroresSecondary.changedCvar, 25, gsDPSetEnvColor(color.r, color.g, color.b, 255)); } static CosmeticOption& linkGoronTunic = cosmeticOptions.at("Link.GoronTunic"); if (manualChange || CVarGetInteger(linkGoronTunic.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {linkGoronTunic.defaultColor.x, linkGoronTunic.defaultColor.y, linkGoronTunic.defaultColor.z, linkGoronTunic.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(linkGoronTunic.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(linkGoronTunic.cvar, linkGoronTunic.defaultColor); PATCH_GFX(gGiGoronTunicColorDL, "Link_GoronTunic1", linkGoronTunic.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGoronCollarColorDL, "Link_GoronTunic2", linkGoronTunic.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gGiGoronTunicColorDL, "Link_GoronTunic3", linkGoronTunic.changedCvar, 4, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); @@ -557,8 +559,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& linkZoraTunic = cosmeticOptions.at("Link.ZoraTunic"); if (manualChange || CVarGetInteger(linkZoraTunic.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {linkZoraTunic.defaultColor.x, linkZoraTunic.defaultColor.y, linkZoraTunic.defaultColor.z, linkZoraTunic.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(linkZoraTunic.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(linkZoraTunic.cvar, linkZoraTunic.defaultColor); PATCH_GFX(gGiZoraTunicColorDL, "Link_ZoraTunic1", linkZoraTunic.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiZoraCollarColorDL, "Link_ZoraTunic2", linkZoraTunic.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gGiZoraTunicColorDL, "Link_ZoraTunic3", linkZoraTunic.changedCvar, 4, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); @@ -567,8 +568,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& linkHair = cosmeticOptions.at("Link.Hair"); if (manualChange || CVarGetInteger(linkHair.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {linkHair.defaultColor.x, linkHair.defaultColor.y, linkHair.defaultColor.z, linkHair.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(linkHair.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(linkHair.cvar, linkHair.defaultColor); PATCH_GFX(gLinkChildHeadNearDL, "Link_Hair1", linkHair.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkChildHeadFarDL, "Link_Hair2", linkHair.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultHeadNearDL, "Link_Hair3", linkHair.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); @@ -590,8 +590,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& linkLinen = cosmeticOptions.at("Link.Linen"); if (manualChange || CVarGetInteger(linkLinen.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {linkLinen.defaultColor.x, linkLinen.defaultColor.y, linkLinen.defaultColor.z, linkLinen.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(linkLinen.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(linkLinen.cvar, linkLinen.defaultColor); PATCH_GFX(gLinkAdultLeftArmNearDL, "Link_Linen1", linkLinen.changedCvar, 30, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftArmNearDL, "Link_Linen2", linkLinen.changedCvar, 83, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftArmOutNearDL, "Link_Linen3", linkLinen.changedCvar, 25, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -632,8 +631,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& linkBoots = cosmeticOptions.at("Link.Boots"); if (manualChange || CVarGetInteger(linkBoots.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {linkBoots.defaultColor.x, linkBoots.defaultColor.y, linkBoots.defaultColor.z, linkBoots.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(linkBoots.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(linkBoots.cvar, linkBoots.defaultColor); PATCH_GFX(gLinkChildRightShinNearDL, "Link_Boots1", linkBoots.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkChildRightShinFarDL, "Link_Boots2", linkBoots.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultRightLegNearDL, "Link_Boots3", linkBoots.changedCvar, 10, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); @@ -669,8 +667,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& mirrorShieldBody = cosmeticOptions.at("MirrorShield.Body"); if (manualChange || CVarGetInteger(mirrorShieldBody.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {mirrorShieldBody.defaultColor.x, mirrorShieldBody.defaultColor.y, mirrorShieldBody.defaultColor.z, mirrorShieldBody.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(mirrorShieldBody.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(mirrorShieldBody.cvar, mirrorShieldBody.defaultColor); PATCH_GFX(gGiMirrorShieldDL, "MirrorShield_Body1", mirrorShieldBody.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiMirrorShieldDL, "MirrorShield_Body2", mirrorShieldBody.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "MirrorShield_Body3", mirrorShieldBody.changedCvar, 28, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -682,8 +679,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& mirrorShieldMirror = cosmeticOptions.at("MirrorShield.Mirror"); if (manualChange || CVarGetInteger(mirrorShieldMirror.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {mirrorShieldMirror.defaultColor.x, mirrorShieldMirror.defaultColor.y, mirrorShieldMirror.defaultColor.z, mirrorShieldMirror.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(mirrorShieldMirror.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(mirrorShieldMirror.cvar, mirrorShieldMirror.defaultColor); PATCH_GFX(gGiMirrorShieldDL, "MirrorShield_Mirror1", mirrorShieldMirror.changedCvar, 47, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiMirrorShieldDL, "MirrorShield_Mirror2", mirrorShieldMirror.changedCvar, 48, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "MirrorShield_Mirror3", mirrorShieldMirror.changedCvar, 17, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -695,8 +691,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& mirrorShieldEmblem = cosmeticOptions.at("MirrorShield.Emblem"); if (manualChange || CVarGetInteger(mirrorShieldEmblem.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {mirrorShieldEmblem.defaultColor.x, mirrorShieldEmblem.defaultColor.y, mirrorShieldEmblem.defaultColor.z, mirrorShieldEmblem.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(mirrorShieldEmblem.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(mirrorShieldEmblem.cvar, mirrorShieldEmblem.defaultColor); PATCH_GFX(gGiMirrorShieldSymbolDL, "MirrorShield_Emblem1", mirrorShieldEmblem.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 140)); PATCH_GFX(gGiMirrorShieldSymbolDL, "MirrorShield_Emblem2", mirrorShieldEmblem.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultMirrorShieldSwordAndSheathNearDL, "MirrorShield_Emblem3", mirrorShieldEmblem.changedCvar, 165, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -709,8 +704,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& swordsKokiriBlade = cosmeticOptions.at("Swords.KokiriBlade"); if (manualChange || CVarGetInteger(swordsKokiriBlade.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {swordsKokiriBlade.defaultColor.x, swordsKokiriBlade.defaultColor.y, swordsKokiriBlade.defaultColor.z, swordsKokiriBlade.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(swordsKokiriBlade.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(swordsKokiriBlade.cvar, swordsKokiriBlade.defaultColor); PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriBlade1", swordsKokiriBlade.changedCvar, 79, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriBlade2", swordsKokiriBlade.changedCvar, 75, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiKokiriSwordDL, "Swords_KokiriBlade3", swordsKokiriBlade.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -719,8 +713,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { /* static CosmeticOption& swordsKokiriHilt = cosmeticOptions.at("Swords.KokiriHilt"); if (manualChange || CVarGetInteger(swordsKokiriHilt.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {swordsKokiriHilt.defaultColor.x, swordsKokiriHilt.defaultColor.y, swordsKokiriHilt.defaultColor.z, swordsKokiriHilt.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(swordsKokiriHilt.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(swordsKokiriHilt.cvar, swordsKokiriHilt.defaultColor); PATCH_GFX(gLinkChildLeftFistAndKokiriSwordNearDL, "Swords_KokiriHilt1", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkChildLeftFistAndKokiriSwordFarDL, "Swords_KokiriHilt2", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkChildSwordAndSheathNearDL, "Swords_KokiriHilt3", swordsKokiriHilt.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); @@ -761,8 +754,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { */ static CosmeticOption& swordsMasterBlade = cosmeticOptions.at("Swords.MasterBlade"); if (manualChange || CVarGetInteger(swordsMasterBlade.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {swordsMasterBlade.defaultColor.x, swordsMasterBlade.defaultColor.y, swordsMasterBlade.defaultColor.z, swordsMasterBlade.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(swordsMasterBlade.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(swordsMasterBlade.cvar, swordsMasterBlade.defaultColor); PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterBlade1", swordsMasterBlade.changedCvar, 60, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterBlade2", swordsMasterBlade.changedCvar, 17, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterBlade3", swordsMasterBlade.changedCvar, 13, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -773,8 +765,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { /* static CosmeticOption& swordsMasterHilt = cosmeticOptions.at("Swords.MasterHilt"); if (manualChange || CVarGetInteger(swordsMasterHilt.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {swordsMasterHilt.defaultColor.x, swordsMasterHilt.defaultColor.y, swordsMasterHilt.defaultColor.z, swordsMasterHilt.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(swordsMasterHilt.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(swordsMasterHilt.cvar, swordsMasterHilt.defaultColor); PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordNearDL, "Swords_MasterHilt1", swordsMasterHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingMasterSwordFarDL, "Swords_MasterHilt2", swordsMasterHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(object_toki_objects_DL_001BD0, "Swords_MasterHilt3", swordsMasterHilt.changedCvar, 16, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); @@ -821,8 +812,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { */ static CosmeticOption& swordsBiggoronBlade = cosmeticOptions.at("Swords.BiggoronBlade"); if (manualChange || CVarGetInteger(swordsBiggoronBlade.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {swordsBiggoronBlade.defaultColor.x, swordsBiggoronBlade.defaultColor.y, swordsBiggoronBlade.defaultColor.z, swordsBiggoronBlade.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(swordsBiggoronBlade.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(swordsBiggoronBlade.cvar, swordsBiggoronBlade.defaultColor); PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronBlade1", swordsBiggoronBlade.changedCvar, 108, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronBlade2", swordsBiggoronBlade.changedCvar, 63, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronBlade3", swordsBiggoronBlade.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -831,8 +821,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { /* static CosmeticOption& swordsBiggoronHilt = cosmeticOptions.at("Swords.BiggoronHilt"); if (manualChange || CVarGetInteger(swordsBiggoronHilt.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {swordsBiggoronHilt.defaultColor.x, swordsBiggoronHilt.defaultColor.y, swordsBiggoronHilt.defaultColor.z, swordsBiggoronHilt.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(swordsBiggoronHilt.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(swordsBiggoronHilt.cvar, swordsBiggoronHilt.defaultColor); PATCH_GFX(gLinkAdultLeftHandHoldingBgsNearDL, "Swords_BiggoronHilt1", swordsBiggoronHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingBgsFarDL, "Swords_BiggoronHilt2", swordsBiggoronHilt.changedCvar, 20, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gGiBiggoronSwordDL, "Swords_BiggoronHilt3", swordsBiggoronHilt.changedCvar, 74, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -851,8 +840,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { */ static CosmeticOption& glovesGoronBracelet = cosmeticOptions.at("Gloves.GoronBracelet"); if (manualChange || CVarGetInteger(glovesGoronBracelet.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {glovesGoronBracelet.defaultColor.x, glovesGoronBracelet.defaultColor.y, glovesGoronBracelet.defaultColor.z, glovesGoronBracelet.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(glovesGoronBracelet.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(glovesGoronBracelet.cvar, glovesGoronBracelet.defaultColor); PATCH_GFX(gGiGoronBraceletDL, "Gloves_GoronBracelet1", glovesGoronBracelet.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGoronBraceletDL, "Gloves_GoronBracelet2", glovesGoronBracelet.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkChildGoronBraceletDL, "Gloves_GoronBracelet3", glovesGoronBracelet.changedCvar, 3, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); @@ -864,22 +852,19 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& glovesSilverGauntlets = cosmeticOptions.at("Gloves.SilverGauntlets"); if (manualChange || CVarGetInteger(glovesSilverGauntlets.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {glovesSilverGauntlets.defaultColor.x, glovesSilverGauntlets.defaultColor.y, glovesSilverGauntlets.defaultColor.z, glovesSilverGauntlets.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(glovesSilverGauntlets.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(glovesSilverGauntlets.cvar, glovesSilverGauntlets.defaultColor); PATCH_GFX(gGiSilverGauntletsColorDL, "Gloves_SilverGauntlets1", glovesSilverGauntlets.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiSilverGauntletsColorDL, "Gloves_SilverGauntlets2", glovesSilverGauntlets.changedCvar, 4, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); } static CosmeticOption& glovesGoldenGauntlets = cosmeticOptions.at("Gloves.GoldenGauntlets"); if (manualChange || CVarGetInteger(glovesGoldenGauntlets.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {glovesGoldenGauntlets.defaultColor.x, glovesGoldenGauntlets.defaultColor.y, glovesGoldenGauntlets.defaultColor.z, glovesGoldenGauntlets.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(glovesGoldenGauntlets.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(glovesGoldenGauntlets.cvar, glovesGoldenGauntlets.defaultColor); PATCH_GFX(gGiGoldenGauntletsColorDL, "Gloves_GoldenGauntlets1", glovesGoldenGauntlets.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGoldenGauntletsColorDL, "Gloves_GoldenGauntlets2", glovesGoldenGauntlets.changedCvar, 4, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); } static CosmeticOption& glovesGauntletsGem = cosmeticOptions.at("Gloves.GauntletsGem"); if (manualChange || CVarGetInteger(glovesGauntletsGem.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {glovesGauntletsGem.defaultColor.x, glovesGauntletsGem.defaultColor.y, glovesGauntletsGem.defaultColor.z, glovesGauntletsGem.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(glovesGauntletsGem.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(glovesGauntletsGem.cvar, glovesGauntletsGem.defaultColor); PATCH_GFX(gGiGauntletsDL, "Gloves_GauntletsGem1", glovesGauntletsGem.changedCvar, 84, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGauntletsDL, "Gloves_GauntletsGem2", glovesGauntletsGem.changedCvar, 85, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultLeftGauntletPlate2DL, "Gloves_GauntletsGem3", glovesGauntletsGem.changedCvar, 42, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -890,8 +875,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& equipmentBoomerangBody = cosmeticOptions.at("Equipment.BoomerangBody"); if (manualChange || CVarGetInteger(equipmentBoomerangBody.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBoomerangBody.defaultColor.x, equipmentBoomerangBody.defaultColor.y, equipmentBoomerangBody.defaultColor.z, equipmentBoomerangBody.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBoomerangBody.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBoomerangBody.cvar, equipmentBoomerangBody.defaultColor); PATCH_GFX(gGiBoomerangDL, "Equipment_BoomerangBody1", equipmentBoomerangBody.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBoomerangDL, "Equipment_BoomerangBody2", equipmentBoomerangBody.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkChildLeftFistAndBoomerangNearDL, "Equipment_BoomerangBody3", equipmentBoomerangBody.changedCvar, 34, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -900,8 +884,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& equipmentBoomerangGem = cosmeticOptions.at("Equipment.BoomerangGem"); if (manualChange || CVarGetInteger(equipmentBoomerangGem.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBoomerangGem.defaultColor.x, equipmentBoomerangGem.defaultColor.y, equipmentBoomerangGem.defaultColor.z, equipmentBoomerangGem.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBoomerangGem.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBoomerangGem.cvar, equipmentBoomerangGem.defaultColor); PATCH_GFX(gGiBoomerangDL, "Equipment_BoomerangGem1", equipmentBoomerangGem.changedCvar, 84, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBoomerangDL, "Equipment_BoomerangGem2", equipmentBoomerangGem.changedCvar, 85, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkChildLeftFistAndBoomerangNearDL, "Equipment_BoomerangGem3", equipmentBoomerangGem.changedCvar, 16, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -912,8 +895,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { /* static CosmeticOption& equipmentSlingshotBody = cosmeticOptions.at("Equipment.SlingshotBody"); if (manualChange || CVarGetInteger(equipmentSlingshotBody.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentSlingshotBody.defaultColor.x, equipmentSlingshotBody.defaultColor.y, equipmentSlingshotBody.defaultColor.z, equipmentSlingshotBody.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentSlingshotBody.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentSlingshotBody.cvar, equipmentSlingshotBody.defaultColor); PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody1", equipmentSlingshotBody.changedCvar, 10, gsDPSetPrimColor(0, 0, MAX(color.r - 100, 0), MAX(color.g - 100, 0), MAX(color.b - 100, 0), 255)); PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody2", equipmentSlingshotBody.changedCvar, 12, gsDPSetEnvColor(MAX(color.r - 100, 0) / 3, MAX(color.g - 100, 0) / 3, MAX(color.b - 100, 0) / 3, 255)); PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotBody3", equipmentSlingshotBody.changedCvar, 74, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -937,8 +919,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { */ static CosmeticOption& equipmentSlingshotString = cosmeticOptions.at("Equipment.SlingshotString"); if (manualChange || CVarGetInteger(equipmentSlingshotString.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentSlingshotString.defaultColor.x, equipmentSlingshotString.defaultColor.y, equipmentSlingshotString.defaultColor.z, equipmentSlingshotString.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentSlingshotString.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentSlingshotString.cvar, equipmentSlingshotString.defaultColor); PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotString1",equipmentSlingshotString.changedCvar, 75, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiSlingshotDL, "Equipment_SlingshotString2",equipmentSlingshotString.changedCvar, 76, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gLinkChildSlingshotStringDL, "Equipment_SlingshotString3",equipmentSlingshotString.changedCvar, 9, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -946,8 +927,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& equipmentBowTips = cosmeticOptions.at("Equipment.BowTips"); if (manualChange || CVarGetInteger(equipmentBowTips.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBowTips.defaultColor.x, equipmentBowTips.defaultColor.y, equipmentBowTips.defaultColor.z, equipmentBowTips.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBowTips.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBowTips.cvar, equipmentBowTips.defaultColor); PATCH_GFX(gGiBowDL, "Equipment_BowTips1", equipmentBowTips.changedCvar, 86, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBowDL, "Equipment_BowTips2", equipmentBowTips.changedCvar, 87, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultRightHandHoldingBowFirstPersonDL, "Equipment_BowTips3", equipmentBowTips.changedCvar, 34, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -956,16 +936,14 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& equipmentBowString = cosmeticOptions.at("Equipment.BowString"); if (manualChange || CVarGetInteger(equipmentBowString.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBowString.defaultColor.x, equipmentBowString.defaultColor.y, equipmentBowString.defaultColor.z, equipmentBowString.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBowString.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBowString.cvar, equipmentBowString.defaultColor); PATCH_GFX(gGiBowDL, "Equipment_BowString1", equipmentBowString.changedCvar, 105, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBowDL, "Equipment_BowString2", equipmentBowString.changedCvar, 106, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultBowStringDL, "Equipment_BowString3", equipmentBowString.changedCvar, 9, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } static CosmeticOption& equipmentBowBody = cosmeticOptions.at("Equipment.BowBody"); if (manualChange || CVarGetInteger(equipmentBowBody.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBowBody.defaultColor.x, equipmentBowBody.defaultColor.y, equipmentBowBody.defaultColor.z, equipmentBowBody.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBowBody.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBowBody.cvar, equipmentBowBody.defaultColor); PATCH_GFX(gGiBowDL, "Equipment_BowBody1", equipmentBowBody.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBowDL, "Equipment_BowBody2", equipmentBowBody.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultRightHandHoldingBowFirstPersonDL, "Equipment_BowBody3", equipmentBowBody.changedCvar, 42, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -974,8 +952,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& equipmentBowHandle = cosmeticOptions.at("Equipment.BowHandle"); if (manualChange || CVarGetInteger(equipmentBowHandle.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBowHandle.defaultColor.x, equipmentBowHandle.defaultColor.y, equipmentBowHandle.defaultColor.z, equipmentBowHandle.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBowHandle.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBowHandle.cvar, equipmentBowHandle.defaultColor); PATCH_GFX(gGiBowDL, "Equipment_BowHandle1", equipmentBowHandle.changedCvar, 51, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBowDL, "Equipment_BowHandle2", equipmentBowHandle.changedCvar, 52, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gLinkAdultRightHandHoldingBowFirstPersonDL, "Equipment_BowHandle3", equipmentBowHandle.changedCvar, 18, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -985,8 +962,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& equipmentHammerHead = cosmeticOptions.at("Equipment.HammerHead"); if (manualChange || CVarGetInteger(equipmentHammerHead.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentHammerHead.defaultColor.x, equipmentHammerHead.defaultColor.y, equipmentHammerHead.defaultColor.z, equipmentHammerHead.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentHammerHead.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentHammerHead.cvar, equipmentHammerHead.defaultColor); PATCH_GFX(gGiHammerDL, "Equipment_HammerHead1", equipmentHammerHead.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiHammerDL, "Equipment_HammerHead2", equipmentHammerHead.changedCvar, 6, gsDPSetEnvColor(color.r / 5, color.g / 5, color.b / 5, 255)); PATCH_GFX(gGiHammerDL, "Equipment_HammerHead3", equipmentHammerHead.changedCvar, 68, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -996,8 +972,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& equipmentHammerHandle = cosmeticOptions.at("Equipment.HammerHandle"); if (manualChange || CVarGetInteger(equipmentHammerHandle.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentHammerHandle.defaultColor.x, equipmentHammerHandle.defaultColor.y, equipmentHammerHandle.defaultColor.z, equipmentHammerHandle.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentHammerHandle.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentHammerHandle.cvar, equipmentHammerHandle.defaultColor); PATCH_GFX(gGiHammerDL, "Equipment_HammerHandle1", equipmentHammerHandle.changedCvar, 84, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiHammerDL, "Equipment_HammerHandle2", equipmentHammerHandle.changedCvar, 85, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gLinkAdultLeftHandHoldingHammerNearDL, "Equipment_HammerHandle5", equipmentHammerHandle.changedCvar, 18, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -1006,15 +981,13 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& equipmentHookshotChain = cosmeticOptions.at("Equipment.HookshotChain"); if (manualChange || CVarGetInteger(equipmentHookshotChain.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentHookshotChain.defaultColor.x, equipmentHookshotChain.defaultColor.y, equipmentHookshotChain.defaultColor.z, equipmentHookshotChain.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentHookshotChain.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentHookshotChain.cvar, equipmentHookshotChain.defaultColor); PATCH_GFX(gLinkAdultHookshotChainDL, "Equipment_HookshotChain1", equipmentHookshotChain.changedCvar, 17, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } static CosmeticOption& equipmentChuFace = cosmeticOptions.at("Equipment.ChuFace"); if (manualChange || CVarGetInteger(equipmentChuFace.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentChuFace.defaultColor.x, equipmentChuFace.defaultColor.y, equipmentChuFace.defaultColor.z, equipmentChuFace.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentChuFace.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentChuFace.cvar, equipmentChuFace.defaultColor); PATCH_GFX(gGiBombchuDL, "Equipment_ChuFace1", equipmentChuFace.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBombchuDL, "Equipment_ChuFace2", equipmentChuFace.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gBombchuDL, "Equipment_ChuFace3", equipmentChuFace.changedCvar, 2, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); @@ -1026,8 +999,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& equipmentChuBody = cosmeticOptions.at("Equipment.ChuBody"); if (manualChange || CVarGetInteger(equipmentChuBody.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentChuBody.defaultColor.x, equipmentChuBody.defaultColor.y, equipmentChuBody.defaultColor.z, equipmentChuBody.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentChuBody.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentChuBody.cvar, equipmentChuBody.defaultColor); PATCH_GFX(gGiBombchuDL, "Equipment_ChuBody1", equipmentChuBody.changedCvar, 39, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBombchuDL, "Equipment_ChuBody2", equipmentChuBody.changedCvar, 40, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gGiBombchuDL, "Equipment_ChuBody3", equipmentChuBody.changedCvar, 60, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -1037,8 +1009,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& equipmentBunnyHood = cosmeticOptions.at("Equipment.BunnyHood"); if (manualChange || CVarGetInteger(equipmentBunnyHood.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {equipmentBunnyHood.defaultColor.x, equipmentBunnyHood.defaultColor.y, equipmentBunnyHood.defaultColor.z, equipmentBunnyHood.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(equipmentBunnyHood.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(equipmentBunnyHood.cvar, equipmentBunnyHood.defaultColor); PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood1", equipmentBunnyHood.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood2", equipmentBunnyHood.changedCvar, 6, gsDPSetEnvColor(color.r / 3, color.g / 3, color.b / 3, 255)); PATCH_GFX(gGiBunnyHoodDL, "Equipment_BunnyHood3", equipmentBunnyHood.changedCvar, 83, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -1057,8 +1028,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& consumableGreenRupee = cosmeticOptions.at("Consumable.GreenRupee"); if (manualChange || CVarGetInteger(consumableGreenRupee.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumableGreenRupee.defaultColor.x, consumableGreenRupee.defaultColor.y, consumableGreenRupee.defaultColor.z, consumableGreenRupee.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumableGreenRupee.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumableGreenRupee.cvar, consumableGreenRupee.defaultColor); PATCH_GFX(gGiGreenRupeeInnerColorDL, "Consumable_GreenRupee1", consumableGreenRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGreenRupeeInnerColorDL, "Consumable_GreenRupee2", consumableGreenRupee.changedCvar, 4, gsDPSetEnvColor(color.r / 5, color.g / 5, color.b / 5, 255)); PATCH_GFX(gGiGreenRupeeOuterColorDL, "Consumable_GreenRupee3", consumableGreenRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); @@ -1077,8 +1047,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& consumableBlueRupee = cosmeticOptions.at("Consumable.BlueRupee"); if (manualChange || CVarGetInteger(consumableBlueRupee.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumableBlueRupee.defaultColor.x, consumableBlueRupee.defaultColor.y, consumableBlueRupee.defaultColor.z, consumableBlueRupee.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumableBlueRupee.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumableBlueRupee.cvar, consumableBlueRupee.defaultColor); PATCH_GFX(gGiBlueRupeeInnerColorDL, "Consumable_BlueRupee1", consumableBlueRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiBlueRupeeInnerColorDL, "Consumable_BlueRupee2", consumableBlueRupee.changedCvar, 4, gsDPSetEnvColor(color.r / 5, color.g / 5, color.b / 5, 255)); PATCH_GFX(gGiBlueRupeeOuterColorDL, "Consumable_BlueRupee3", consumableBlueRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); @@ -1086,8 +1055,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& consumableRedRupee = cosmeticOptions.at("Consumable.RedRupee"); if (manualChange || CVarGetInteger(consumableRedRupee.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumableRedRupee.defaultColor.x, consumableRedRupee.defaultColor.y, consumableRedRupee.defaultColor.z, consumableRedRupee.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumableRedRupee.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumableRedRupee.cvar, consumableRedRupee.defaultColor); PATCH_GFX(gGiRedRupeeInnerColorDL, "Consumable_RedRupee1", consumableRedRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiRedRupeeInnerColorDL, "Consumable_RedRupee2", consumableRedRupee.changedCvar, 4, gsDPSetEnvColor(color.r / 5, color.g / 5, color.b / 5, 255)); PATCH_GFX(gGiRedRupeeOuterColorDL, "Consumable_RedRupee3", consumableRedRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); @@ -1095,8 +1063,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& consumablePurpleRupee = cosmeticOptions.at("Consumable.PurpleRupee"); if (manualChange || CVarGetInteger(consumablePurpleRupee.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumablePurpleRupee.defaultColor.x, consumablePurpleRupee.defaultColor.y, consumablePurpleRupee.defaultColor.z, consumablePurpleRupee.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumablePurpleRupee.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumablePurpleRupee.cvar, consumablePurpleRupee.defaultColor); PATCH_GFX(gGiPurpleRupeeInnerColorDL, "Consumable_PurpleRupee1", consumablePurpleRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiPurpleRupeeInnerColorDL, "Consumable_PurpleRupee2", consumablePurpleRupee.changedCvar, 4, gsDPSetEnvColor(color.r / 5, color.g / 5, color.b / 5, 255)); PATCH_GFX(gGiPurpleRupeeOuterColorDL, "Consumable_PurpleRupee3", consumablePurpleRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); @@ -1104,8 +1071,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& consumableGoldRupee = cosmeticOptions.at("Consumable.GoldRupee"); if (manualChange || CVarGetInteger(consumableGoldRupee.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumableGoldRupee.defaultColor.x, consumableGoldRupee.defaultColor.y, consumableGoldRupee.defaultColor.z, consumableGoldRupee.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumableGoldRupee.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumableGoldRupee.cvar, consumableGoldRupee.defaultColor); PATCH_GFX(gGiGoldRupeeInnerColorDL, "Consumable_GoldRupee1", consumableGoldRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiGoldRupeeInnerColorDL, "Consumable_GoldRupee2", consumableGoldRupee.changedCvar, 4, gsDPSetEnvColor(color.r / 5, color.g / 5, color.b / 5, 255)); PATCH_GFX(gGiGoldRupeeOuterColorDL, "Consumable_GoldRupee3", consumableGoldRupee.changedCvar, 3, gsDPSetPrimColor(0, 0, MIN(color.r + 100, 255), MIN(color.g + 100, 255), MIN(color.b + 100, 255), 255)); @@ -1114,8 +1080,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& consumableHearts = cosmeticOptions.at("Consumable.Hearts"); if (manualChange || CVarGetInteger(consumableHearts.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumableHearts.defaultColor.x, consumableHearts.defaultColor.y, consumableHearts.defaultColor.z, consumableHearts.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumableHearts.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumableHearts.cvar, consumableHearts.defaultColor); /* PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts1", consumableHearts.changedCvar, 4, gsDPSetGrayscaleColor(color.r, color.g, color.b, 255)); PATCH_GFX(gGiRecoveryHeartDL, "Consumable_Hearts2", consumableHearts.changedCvar, 26, gsSPGrayscale(true)); @@ -1131,8 +1096,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { } static CosmeticOption& consumableMagic = cosmeticOptions.at("Consumable.Magic"); if (manualChange || CVarGetInteger(consumableMagic.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {consumableMagic.defaultColor.x, consumableMagic.defaultColor.y, consumableMagic.defaultColor.z, consumableMagic.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(consumableMagic.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(consumableMagic.cvar, consumableMagic.defaultColor); PATCH_GFX(gGiMagicJarSmallDL, "Consumable_Magic1", consumableMagic.changedCvar, 31, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gGiMagicJarSmallDL, "Consumable_Magic2", consumableMagic.changedCvar, 32, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gGiMagicJarLargeDL, "Consumable_Magic3", consumableMagic.changedCvar, 31, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -1143,8 +1107,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& npcGoldenSkulltula = cosmeticOptions.at("NPC.GoldenSkulltula"); if (manualChange || CVarGetInteger(npcGoldenSkulltula.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {npcGoldenSkulltula.defaultColor.x, npcGoldenSkulltula.defaultColor.y, npcGoldenSkulltula.defaultColor.z, npcGoldenSkulltula.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(npcGoldenSkulltula.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(npcGoldenSkulltula.cvar, npcGoldenSkulltula.defaultColor); PATCH_GFX(gSkulltulaTokenDL, "NPC_GoldenSkulltula1", npcGoldenSkulltula.changedCvar, 5, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); PATCH_GFX(gSkulltulaTokenDL, "NPC_GoldenSkulltula2", npcGoldenSkulltula.changedCvar, 6, gsDPSetEnvColor(color.r / 2, color.g / 2, color.b / 2, 255)); PATCH_GFX(gSkulltulaTokenFlameDL, "NPC_GoldenSkulltula3", npcGoldenSkulltula.changedCvar, 32, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); @@ -1159,8 +1122,7 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& npcGerudo = cosmeticOptions.at("NPC.Gerudo"); if (manualChange || CVarGetInteger(npcGerudo.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {npcGerudo.defaultColor.x, npcGerudo.defaultColor.y, npcGerudo.defaultColor.z, npcGerudo.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(npcGerudo.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(npcGerudo.cvar, npcGerudo.defaultColor); PATCH_GFX(gGerudoPurpleTorsoDL, "NPC_Gerudo1", npcGerudo.changedCvar, 139, gsDPSetEnvColor( color.r, color.g, color.b, 255)); PATCH_GFX(gGerudoPurpleRightThighDL, "NPC_Gerudo2", npcGerudo.changedCvar, 11, gsDPSetEnvColor(color.r, color.g, color.b, 255)); PATCH_GFX(gGerudoPurpleLeftThighDL, "NPC_Gerudo3", npcGerudo.changedCvar, 11, gsDPSetEnvColor(color.r, color.g, color.b, 255)); @@ -1173,36 +1135,31 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { static CosmeticOption& npcMetalTrap = cosmeticOptions.at("NPC.MetalTrap"); if (manualChange || CVarGetInteger(npcMetalTrap.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {npcMetalTrap.defaultColor.x, npcMetalTrap.defaultColor.y, npcMetalTrap.defaultColor.z, npcMetalTrap.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(npcMetalTrap.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(npcMetalTrap.cvar, npcMetalTrap.defaultColor); PATCH_GFX(gSlidingBladeTrapDL, "NPC_MetalTrap1", npcMetalTrap.changedCvar, 59, gsDPSetPrimColor(0, 0, color.r, color.g, color.b, 255)); } static CosmeticOption& n64LogoRed = cosmeticOptions.at("Title.N64LogoRed"); if (manualChange || CVarGetInteger(n64LogoRed.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {n64LogoRed.defaultColor.x, n64LogoRed.defaultColor.y, n64LogoRed.defaultColor.z, n64LogoRed.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(n64LogoRed.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(n64LogoRed.cvar, n64LogoRed.defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoRed1", n64LogoRed.changedCvar, 17, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoRed2", n64LogoRed.changedCvar, 18, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } static CosmeticOption& n64LogoBlue = cosmeticOptions.at("Title.N64LogoBlue"); if (manualChange || CVarGetInteger(n64LogoBlue.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {n64LogoBlue.defaultColor.x, n64LogoBlue.defaultColor.y, n64LogoBlue.defaultColor.z, n64LogoBlue.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(n64LogoBlue.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(n64LogoBlue.cvar, n64LogoBlue.defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoBlue1", n64LogoBlue.changedCvar, 29, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoBlue2", n64LogoBlue.changedCvar, 30, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } static CosmeticOption& n64LogoGreen = cosmeticOptions.at("Title.N64LogoGreen"); if (manualChange || CVarGetInteger(n64LogoGreen.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {n64LogoGreen.defaultColor.x, n64LogoGreen.defaultColor.y, n64LogoGreen.defaultColor.z, n64LogoGreen.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(n64LogoGreen.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(n64LogoGreen.cvar, n64LogoGreen.defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoGreen1", n64LogoGreen.changedCvar, 56, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoGreen2", n64LogoGreen.changedCvar, 57, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } static CosmeticOption& n64LogoYellow = cosmeticOptions.at("Title.N64LogoYellow"); if (manualChange || CVarGetInteger(n64LogoYellow.rainbowCvar, 0)) { - static Color_RGBA8 defaultColor = {n64LogoYellow.defaultColor.x, n64LogoYellow.defaultColor.y, n64LogoYellow.defaultColor.z, n64LogoYellow.defaultColor.w}; - Color_RGBA8 color = CVarGetColor(n64LogoYellow.cvar, defaultColor); + Color_RGBA8 color = CVarGetColor(n64LogoYellow.cvar, n64LogoYellow.defaultColor); PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoYellow1", n64LogoYellow.changedCvar, 81, gsDPSetPrimColor(0, 0, 255, 255, 255, 255)) PATCH_GFX(gNintendo64LogoDL, "Title_N64LogoYellow2", n64LogoYellow.changedCvar, 82, gsDPSetEnvColor(color.r, color.g, color.b, 128)); } @@ -1220,10 +1177,10 @@ void ApplyOrResetCustomGfxPatches(bool manualChange) { extern "C" Color_RGBA8 CosmeticsEditor_GetDefaultValue(const char* id) { return Color_RGBA8 { - (uint8_t)(cosmeticOptions[id].defaultColor.x * 255.0f), - (uint8_t)(cosmeticOptions[id].defaultColor.y * 255.0f), - (uint8_t)(cosmeticOptions[id].defaultColor.z * 255.0f), - (uint8_t)(cosmeticOptions[id].defaultColor.w * 255.0f) + (uint8_t)(cosmeticOptions[id].defaultColor.r * 255.0f), + (uint8_t)(cosmeticOptions[id].defaultColor.g * 255.0f), + (uint8_t)(cosmeticOptions[id].defaultColor.b * 255.0f), + (uint8_t)(cosmeticOptions[id].defaultColor.a * 255.0f) }; } @@ -1235,7 +1192,7 @@ void Table_InitHeader(bool has_header = true) { ImGui::TableNextColumn(); ImGui::AlignTextToFramePadding(); //This is to adjust Vertical pos of item in a cell to be normlized. ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 2); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 60); } void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){ @@ -1264,16 +1221,16 @@ void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){ std::string PosXCvar = CvarName + ".PosX"; std::string PosYCvar = CvarName + ".PosY"; - std::string InvisibleLabelX = "##"+PosXCvar; - std::string InvisibleLabelY = "##"+PosYCvar; + std::string InvisibleLabelX = "##" + PosXCvar; + std::string InvisibleLabelY = "##" + PosYCvar; UIWidgets::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0); UIWidgets::Tooltip("This slider is used to move Up and Down your elements."); UIWidgets::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0); UIWidgets::Tooltip("This slider is used to move Left and Right your elements."); } -void DrawScaleSlider(const std::string CvarName,float DefaultValue){ - std::string InvisibleLabel = "##"+CvarName; +void DrawScaleSlider(const std::string CvarName, float DefaultValue){ + std::string InvisibleLabel = "##" + CvarName; std::string CvarLabel = CvarName + ".Scale"; //Disabled for now. feature not done and several fixes needed to be merged. //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true); @@ -1302,15 +1259,15 @@ void C_Button_Dropdown(const char* Header_Title, const char* Table_ID, const cha DrawUseMarginsSlider(Slider_Title, Slider_ID); DrawPositionsRadioBoxes(Slider_ID); s16 Min_X_CU = 0; - s16 Max_X_CU = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger(Int_Type,0) == 2){ + s16 Max_X_CU = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2); + if(CVarGetInteger(Int_Type, 0) == 2){ Max_X_CU = 294; - } else if(CVarGetInteger(Int_Type,0) == 3){ - Max_X_CU = ImGui::GetWindowViewport()->Size.x/2; - } else if(CVarGetInteger(Int_Type,0) == 4){ - Min_X_CU = (ImGui::GetWindowViewport()->Size.x/2)*-1; + } else if(CVarGetInteger(Int_Type, 0) == 3){ + Max_X_CU = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2); + } else if(CVarGetInteger(Int_Type, 0) == 4){ + Min_X_CU = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2) * -1; } - DrawPositionSlider(Slider_ID, 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_CU, Max_X_CU); + DrawPositionSlider(Slider_ID, 0, static_cast<s16>(ImGui::GetWindowViewport()->Size.y / 2), Min_X_CU, Max_X_CU); DrawScaleSlider(Slider_ID, Slider_Scale_Value); ImGui::NewLine(); ImGui::EndTable(); @@ -1335,10 +1292,10 @@ void Draw_Placements(){ if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); Table_InitHeader(); - UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", CVAR_COSMETIC("HUD.Margin.T"), (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0); - UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", CVAR_COSMETIC("HUD.Margin.L"), -25, ImGui::GetWindowViewport()->Size.x, "", 0); - UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", CVAR_COSMETIC("HUD.Margin.R"), (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0); - UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", CVAR_COSMETIC("HUD.Margin.B"), (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0); + UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", CVAR_COSMETIC("HUD.Margin.T"), static_cast<s16>(ImGui::GetWindowViewport()->Size.y / 2) * -1, 25, "", 0); + UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", CVAR_COSMETIC("HUD.Margin.L"), -25, static_cast<s16>(ImGui::GetWindowViewport()->Size.x), "", 0); + UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", CVAR_COSMETIC("HUD.Margin.R"), static_cast<s16>(ImGui::GetWindowViewport()->Size.x) * -1, 25, "", 0); + UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", CVAR_COSMETIC("HUD.Margin.B"), static_cast<s16>(ImGui::GetWindowViewport()->Size.y / 2) * -1, 25, "", 0); SetMarginAll("All margins on",true); UIWidgets::Tooltip("Set most of the elements to use margins\nSome elements with default position will not be affected\nElements without Anchor or Hidden will not be turned on"); ImGui::SameLine(); @@ -1356,8 +1313,8 @@ void Draw_Placements(){ Table_InitHeader(false); DrawUseMarginsSlider("Hearts counts", CVAR_COSMETIC("HUD.Hearts")); DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.HeartsCount")); - DrawPositionSlider(CVAR_COSMETIC("HUD.HeartsCount"),-22,ImGui::GetWindowViewport()->Size.y,-125,ImGui::GetWindowViewport()->Size.x); - DrawScaleSlider(CVAR_COSMETIC("HUD.HeartsCount"),0.7f); + DrawPositionSlider(CVAR_COSMETIC("HUD.HeartsCount"), -22, static_cast<s16>(ImGui::GetWindowViewport()->Size.y), -125, static_cast<s16>(ImGui::GetWindowViewport()->Size.x)); + DrawScaleSlider(CVAR_COSMETIC("HUD.HeartsCount"), 0.7f); UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", CVAR_COSMETIC("HUD.Hearts.LineLength"), 0, 20, "", 10); UIWidgets::Tooltip("This will set the length of a row of hearts. Set to 0 for unlimited length."); ImGui::NewLine(); @@ -1372,34 +1329,34 @@ void Draw_Placements(){ DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.MagicBar")); UIWidgets::EnhancementRadioButton("Anchor to life bar", CVAR_COSMETIC("HUD.MagicBar.PosType"), 5); UIWidgets::Tooltip("This will make your elements follow the bottom of the life meter"); - DrawPositionSlider(CVAR_COSMETIC("HUD.MagicBar"), 0, ImGui::GetWindowViewport()->Size.y/2, -5, ImGui::GetWindowViewport()->Size.x/2); - DrawScaleSlider(CVAR_COSMETIC("HUD.MagicBar"),1.0f); + DrawPositionSlider(CVAR_COSMETIC("HUD.MagicBar"), 0, static_cast<s16>(ImGui::GetWindowViewport()->Size.y / 2), -5, static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2)); + DrawScaleSlider(CVAR_COSMETIC("HUD.MagicBar"), 1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"),0) && ImGui::CollapsingHeader("Visual stone of agony position")) { + if (CVarGetInteger(CVAR_ENHANCEMENT("VisualAgony"), 0) && ImGui::CollapsingHeader("Visual stone of agony position")) { if (ImGui::BeginTable("tabledvisualstoneofagony", 1, FlagsTable)) { ImGui::TableSetupColumn("Visual stone of agony settings", FlagsCell, TablesCellsWidth); Table_InitHeader(false); DrawUseMarginsSlider("Visual stone of agony", CVAR_COSMETIC("HUD.VisualSoA")); DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.VisualSoA")); s16 Min_X_VSOA = 0; - s16 Max_X_VSOA = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"),0) == 2){ + s16 Max_X_VSOA = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2); + if(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 2){ Max_X_VSOA = 290; - } else if(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"),0) == 4){ - Min_X_VSOA = (ImGui::GetWindowViewport()->Size.x/2)*-1; + } else if(CVarGetInteger(CVAR_COSMETIC("HUD.VisualSoA.PosType"), 0) == 4){ + Min_X_VSOA = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2) * -1; } - DrawPositionSlider(CVAR_COSMETIC("HUD.VisualSoA"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_VSOA, Max_X_VSOA); - DrawScaleSlider(CVAR_COSMETIC("HUD.VisualSoA"),1.0f); + DrawPositionSlider(CVAR_COSMETIC("HUD.VisualSoA"), 0, static_cast<s16>(ImGui::GetWindowViewport()->Size.y / 2), Min_X_VSOA, Max_X_VSOA); + DrawScaleSlider(CVAR_COSMETIC("HUD.VisualSoA"), 1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", CVAR_COSMETIC("HUD.BButton"), 0, ImGui::GetWindowViewport()->Size.y/4+50, -1, ImGui::GetWindowViewport()->Size.x-50, 0.95f); - Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", CVAR_COSMETIC("HUD.AButton"), -10, ImGui::GetWindowViewport()->Size.y/4+50, -20, ImGui::GetWindowViewport()->Size.x-50, 0.95f); - Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", CVAR_COSMETIC("HUD.StartButton"), 0, ImGui::GetWindowViewport()->Size.y/2, 0, ImGui::GetWindowViewport()->Size.x/2+70, 0.75f); + Draw_Table_Dropdown("B Button position", "tablebbtn", "B Button settings", "B Button", CVAR_COSMETIC("HUD.BButton"), 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 4) + 50, -1, static_cast<int>(ImGui::GetWindowViewport()->Size.x) - 50, 0.95f); + Draw_Table_Dropdown("A Button position", "tableabtn", "A Button settings", "A Button", CVAR_COSMETIC("HUD.AButton"), -10, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 4) + 50, -20, static_cast<int>(ImGui::GetWindowViewport()->Size.x) - 50, 0.95f); + Draw_Table_Dropdown("Start Button position", "tablestartbtn", "Start Button settings", "Start Button", CVAR_COSMETIC("HUD.StartButton"), 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), 0, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) + 70, 0.75f); C_Button_Dropdown("C Button Up position", "tablecubtn", "C Button Up settings", "C Button Up", CVAR_COSMETIC("HUD.CUpButton"), CVAR_COSMETIC("HUD.CUpButton.PosType"), 0.5f); C_Button_Dropdown("C Button Down position", "tablecdbtn", "C Button Down settings", "C Button Down", CVAR_COSMETIC("HUD.CDownButton"), CVAR_COSMETIC("HUD.CDownButton.PosType"), 0.87f); C_Button_Dropdown("C Button Left position", "tableclbtn", "C Button Left settings", "C Button Left", CVAR_COSMETIC("HUD.CLeftButton"), CVAR_COSMETIC("HUD.CLeftButton.PosType"), 0.87f); @@ -1411,27 +1368,36 @@ void Draw_Placements(){ DrawUseMarginsSlider("DPad items", CVAR_COSMETIC("HUD.Dpad")); DrawPositionsRadioBoxes(CVAR_COSMETIC("HUD.Dpad")); s16 Min_X_Dpad = 0; - s16 Max_X_Dpad = ImGui::GetWindowViewport()->Size.x/2; - if(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"),0) == 2){ + s16 Max_X_Dpad = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2); + if(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 2){ Max_X_Dpad = 290; - } else if(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"),0) == 4){ - Min_X_Dpad = (ImGui::GetWindowViewport()->Size.x/2)*-1; + } else if(CVarGetInteger(CVAR_COSMETIC("HUD.Dpad.PosType"), 0) == 4){ + Min_X_Dpad = static_cast<s16>(ImGui::GetWindowViewport()->Size.x / 2) * -1; } - DrawPositionSlider(CVAR_COSMETIC("HUD.Dpad"), 0, ImGui::GetWindowViewport()->Size.y/2, Min_X_Dpad, Max_X_Dpad); - DrawScaleSlider(CVAR_COSMETIC("HUD.Dpad"),1.0f); + DrawPositionSlider(CVAR_COSMETIC("HUD.Dpad"), 0, static_cast<s16>(ImGui::GetWindowViewport()->Size.y / 2), Min_X_Dpad, Max_X_Dpad); + DrawScaleSlider(CVAR_COSMETIC("HUD.Dpad"), 1.0f); ImGui::NewLine(); ImGui::EndTable(); } } - Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", CVAR_COSMETIC("HUD.Minimap"), (ImGui::GetWindowViewport()->Size.y/3)*-1, ImGui::GetWindowViewport()->Size.y/3, ImGui::GetWindowViewport()->Size.x*-1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", CVAR_COSMETIC("HUD.SmallKey"), 0, ImGui::GetWindowViewport()->Size.y/3, -1, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", CVAR_COSMETIC("HUD.Rupees"), -2, ImGui::GetWindowViewport()->Size.y/3, -3, ImGui::GetWindowViewport()->Size.x/2, 1.0f); - Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", CVAR_COSMETIC("HUD.Carrots"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+25, 1.0f); - Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", CVAR_COSMETIC("HUD.Timers"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); - Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", CVAR_COSMETIC("HUD.ArcheryScore"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2-50, 1.0f); - Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", CVAR_COSMETIC("HUD.TitleCard.Map"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); - Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", CVAR_COSMETIC("HUD.TitleCard.Boss"), 0, ImGui::GetWindowViewport()->Size.y/2, -50, ImGui::GetWindowViewport()->Size.x/2+10, 1.0f); - Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", CVAR_COSMETIC("HUD.IGT"), 0, ImGui::GetWindowViewport()->Size.y / 2, -50, ImGui::GetWindowViewport()->Size.x / 2 + 10, 1.0f); + Draw_Table_Dropdown("Minimaps position", "tableminimapspos", "minimaps settings", "Minimap", CVAR_COSMETIC("HUD.Minimap"), + static_cast<int>(ImGui::GetWindowViewport()->Size.y / 3) * -1, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 3), static_cast<int>(ImGui::GetWindowViewport()->Size.x) * -1, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2), 1.0f); + Draw_Table_Dropdown("Small Keys counter position", "tablesmolekeys", "Small Keys counter settings", "Small Keys counter", CVAR_COSMETIC("HUD.SmallKey"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 3), -1, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2), 1.0f); + Draw_Table_Dropdown("Rupee counter position", "tablerupeecount", "Rupee counter settings", "Rupee counter", CVAR_COSMETIC("HUD.Rupees"), + -2, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 3), -3, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2), 1.0f); + Draw_Table_Dropdown("Carrots position", "tableCarrots", "Carrots settings", "Carrots", CVAR_COSMETIC("HUD.Carrots"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), -50, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) + 25, 1.0f); + Draw_Table_Dropdown("Timers position", "tabletimers", "Timers settings", "Timers", CVAR_COSMETIC("HUD.Timers"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), -50, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) - 50, 1.0f); + Draw_Table_Dropdown("Archery Scores position", "tablearchery", "Archery Scores settings", "Archery scores", CVAR_COSMETIC("HUD.ArcheryScore"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), -50, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) - 50, 1.0f); + Draw_Table_Dropdown("Title cards (Maps) position", "tabletcmaps", "Titlecard maps settings", "Title cards (overworld)", CVAR_COSMETIC("HUD.TitleCard.Map"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), -50, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) + 10, 1.0f); + Draw_Table_Dropdown("Title cards (Bosses) position", "tabletcbosses", "Title cards (Bosses) settings", "Title cards (Bosses)", CVAR_COSMETIC("HUD.TitleCard.Boss"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), -50, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) + 10, 1.0f); + Draw_Table_Dropdown("In-game Gameplay Timer position", "tablegameplaytimer", "In-game Gameplay Timer settings", "In-game Gameplay Timer", CVAR_COSMETIC("HUD.IGT"), + 0, static_cast<int>(ImGui::GetWindowViewport()->Size.y / 2), -50, static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2) + 10, 1.0f); if (ImGui::CollapsingHeader("Enemy Health Bar position")) { if (ImGui::BeginTable("enemyhealthbar", 1, FlagsTable)) { ImGui::TableSetupColumn("Enemy Health Bar settings", FlagsCell, TablesCellsWidth); @@ -1443,7 +1409,7 @@ void Draw_Placements(){ UIWidgets::Tooltip("This will make your elements follow the top edge of your game window"); UIWidgets::EnhancementRadioButton("Anchor to the bottom", posTypeCVar.c_str(), ENEMYHEALTH_ANCHOR_BOTTOM); UIWidgets::Tooltip("This will make your elements follow the bottom edge of your game window"); - DrawPositionSlider(CVAR_COSMETIC("HUD.EnemyHealthBar."), -SCREEN_HEIGHT, SCREEN_HEIGHT, -ImGui::GetWindowViewport()->Size.x / 2, ImGui::GetWindowViewport()->Size.x / 2); + DrawPositionSlider(CVAR_COSMETIC("HUD.EnemyHealthBar."), -SCREEN_HEIGHT, SCREEN_HEIGHT, -static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2), static_cast<int>(ImGui::GetWindowViewport()->Size.x / 2)); if (UIWidgets::EnhancementSliderInt("Health Bar Width: %d", "##EnemyHealthBarWidth", CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Value"), 32, 128, "", 64)) { CVarSetInteger(CVAR_COSMETIC("HUD.EnemyHealthBar.Width.Changed"), 1); } @@ -1531,15 +1497,15 @@ void DrawSillyTab() { // allows you create and use multiple shades of the same color. void CopyMultipliedColor(CosmeticOption& cosmeticOptionSrc, CosmeticOption& cosmeticOptionTarget, float amount = 0.75f) { Color_RGBA8 newColor; - newColor.r = MIN((cosmeticOptionSrc.currentColor.x * 255.0) * amount, 255); - newColor.g = MIN((cosmeticOptionSrc.currentColor.y * 255.0) * amount, 255); - newColor.b = MIN((cosmeticOptionSrc.currentColor.z * 255.0) * amount, 255); + newColor.r = static_cast<uint8_t>(MIN((cosmeticOptionSrc.currentColor.x * 255.0f) * amount, 255)); + newColor.g = static_cast<uint8_t>(MIN((cosmeticOptionSrc.currentColor.y * 255.0f) * amount, 255)); + newColor.b = static_cast<uint8_t>(MIN((cosmeticOptionSrc.currentColor.z * 255.0f) * amount, 255)); newColor.a = 255; - cosmeticOptionTarget.currentColor.x = newColor.r / 255.0; - cosmeticOptionTarget.currentColor.y = newColor.g / 255.0; - cosmeticOptionTarget.currentColor.z = newColor.b / 255.0; - cosmeticOptionTarget.currentColor.w = newColor.a / 255.0; + cosmeticOptionTarget.currentColor.x = newColor.r / 255.0f; + cosmeticOptionTarget.currentColor.y = newColor.g / 255.0f; + cosmeticOptionTarget.currentColor.z = newColor.b / 255.0f; + cosmeticOptionTarget.currentColor.w = newColor.a / 255.0f; CVarSetColor(cosmeticOptionTarget.cvar, newColor); CVarSetInteger((cosmeticOptionTarget.rainbowCvar), 0); @@ -1647,19 +1613,19 @@ void ApplySideEffects(CosmeticOption& cosmeticOption) { void RandomizeColor(CosmeticOption& cosmeticOption) { ImVec4 randomColor = GetRandomValue(); Color_RGBA8 newColor; - newColor.r = randomColor.x * 255; - newColor.g = randomColor.y * 255; - newColor.b = randomColor.z * 255; + newColor.r = static_cast<uint8_t>(randomColor.x * 255.0f); + newColor.g = static_cast<uint8_t>(randomColor.y * 255.0f); + newColor.b = static_cast<uint8_t>(randomColor.z * 255.0f); newColor.a = 255; // For alpha supported options, retain the last set alpha instead of overwriting if (cosmeticOption.supportsAlpha) { - newColor.a = cosmeticOption.currentColor.w * 255; + newColor.a = static_cast<uint8_t>(cosmeticOption.currentColor.w * 255.0f); } - cosmeticOption.currentColor.x = newColor.r / 255.0; - cosmeticOption.currentColor.y = newColor.g / 255.0; - cosmeticOption.currentColor.z = newColor.b / 255.0; - cosmeticOption.currentColor.w = newColor.a / 255.0; + cosmeticOption.currentColor.x = newColor.r / 255.0f; + cosmeticOption.currentColor.y = newColor.g / 255.0f; + cosmeticOption.currentColor.z = newColor.b / 255.0f; + cosmeticOption.currentColor.w = newColor.a / 255.0f; CVarSetColor(cosmeticOption.cvar, newColor); CVarSetInteger(cosmeticOption.rainbowCvar, 0); @@ -1668,11 +1634,11 @@ void RandomizeColor(CosmeticOption& cosmeticOption) { } void ResetColor(CosmeticOption& cosmeticOption) { - Color_RGBA8 defaultColor = {cosmeticOption.defaultColor.x, cosmeticOption.defaultColor.y, cosmeticOption.defaultColor.z, cosmeticOption.defaultColor.w}; - cosmeticOption.currentColor.x = defaultColor.r / 255.0; - cosmeticOption.currentColor.y = defaultColor.g / 255.0; - cosmeticOption.currentColor.z = defaultColor.b / 255.0; - cosmeticOption.currentColor.w = defaultColor.a / 255.0; + Color_RGBA8 defaultColor = {cosmeticOption.defaultColor.r, cosmeticOption.defaultColor.g, cosmeticOption.defaultColor.b, cosmeticOption.defaultColor.a}; + cosmeticOption.currentColor.x = defaultColor.r / 255.0f; + cosmeticOption.currentColor.y = defaultColor.g / 255.0f; + cosmeticOption.currentColor.z = defaultColor.b / 255.0f; + cosmeticOption.currentColor.w = defaultColor.a / 255.0f; CVarClear(cosmeticOption.changedCvar); CVarClear(cosmeticOption.rainbowCvar); @@ -1736,10 +1702,10 @@ void DrawCosmeticRow(CosmeticOption& cosmeticOption) { } if (colorChanged) { Color_RGBA8 color; - color.r = cosmeticOption.currentColor.x * 255.0; - color.g = cosmeticOption.currentColor.y * 255.0; - color.b = cosmeticOption.currentColor.z * 255.0; - color.a = cosmeticOption.currentColor.w * 255.0; + color.r = static_cast<uint8_t>(cosmeticOption.currentColor.x * 255.0f); + color.g = static_cast<uint8_t>(cosmeticOption.currentColor.y * 255.0f); + color.b = static_cast<uint8_t>(cosmeticOption.currentColor.z * 255.0f); + color.a = static_cast<uint8_t>(cosmeticOption.currentColor.w * 255.0f); CVarSetColor(cosmeticOption.cvar, color); CVarSetInteger((cosmeticOption.rainbowCvar), 0); @@ -1968,9 +1934,11 @@ void CosmeticsEditorWindow::DrawElement() { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Message")) { - DrawCosmeticGroup(COSMETICS_GROUP_MESSAGE); - ImGui::EndTabItem(); + if (CVarGetInteger(CVAR_COSMETIC("AdvancedMode"), 0)) { + if (ImGui::BeginTabItem("Message")) { + DrawCosmeticGroup(COSMETICS_GROUP_MESSAGE); + ImGui::EndTabItem(); + } } ImGui::EndTabBar(); } @@ -1999,13 +1967,13 @@ void Cosmetics_RegisterOnSceneInitHook() { void CosmeticsEditorWindow::InitElement() { // Convert the `current color` into the format that the ImGui color picker expects for (auto& [id, cosmeticOption] : cosmeticOptions) { - Color_RGBA8 defaultColor = {cosmeticOption.defaultColor.x, cosmeticOption.defaultColor.y, cosmeticOption.defaultColor.z, cosmeticOption.defaultColor.w}; + Color_RGBA8 defaultColor = {cosmeticOption.defaultColor.r, cosmeticOption.defaultColor.g, cosmeticOption.defaultColor.b, cosmeticOption.defaultColor.a}; Color_RGBA8 cvarColor = CVarGetColor(cosmeticOption.cvar, defaultColor); - cosmeticOption.currentColor.x = cvarColor.r / 255.0; - cosmeticOption.currentColor.y = cvarColor.g / 255.0; - cosmeticOption.currentColor.z = cvarColor.b / 255.0; - cosmeticOption.currentColor.w = cvarColor.a / 255.0; + cosmeticOption.currentColor.x = cvarColor.r / 255.0f; + cosmeticOption.currentColor.y = cvarColor.g / 255.0f; + cosmeticOption.currentColor.z = cvarColor.b / 255.0f; + cosmeticOption.currentColor.w = cvarColor.a / 255.0f; } Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); ApplyOrResetCustomGfxPatches(); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 754e40ae2..84c71c83b 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3390,6 +3390,8 @@ void Interface_UpdateMagicBar(PlayState* play) { gSaveContext.magicState = MAGIC_STATE_IDLE; if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); + } else { + sMagicBorder = sMagicBorder_ori; } break; } From 55960da4027b13234d1ee3a5a6a2fad2b7320f1a Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Fri, 29 Nov 2024 17:58:30 -0700 Subject: [PATCH 10/28] Separate option values into context and menu indexes. (#4581) * Separate option values into context and menu indexes. * Fix option index reference in `CleanCheckConditionString`. * Update soh/soh/Enhancements/randomizer/3drando/location_access.cpp Co-authored-by: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> * Restore `const` classification to functions returning `string&`. * Restore `const` classification to getter functions. * Restore a couple more `const`s; cleanup header. * Final consts; rename `SetCVar` to `SaveCVar`. --- .../SkipCutscene/Story/SkipBlueWarp.cpp | 2 +- soh/soh/Enhancements/kaleido.cpp | 4 +- .../Enhancements/randomizer/3drando/fill.cpp | 6 +- .../Enhancements/randomizer/3drando/hints.cpp | 34 +- .../randomizer/3drando/item_pool.cpp | 8 +- .../randomizer/3drando/location_access.cpp | 4 +- .../Enhancements/randomizer/3drando/shops.cpp | 20 +- .../randomizer/3drando/spoiler_log.cpp | 8 +- .../randomizer/3drando/starting_inventory.cpp | 10 +- soh/soh/Enhancements/randomizer/entrance.cpp | 12 +- .../Enhancements/randomizer/fishsanity.cpp | 2 +- soh/soh/Enhancements/randomizer/hint.cpp | 20 +- .../Enhancements/randomizer/hook_handlers.cpp | 2 +- .../Enhancements/randomizer/item_location.cpp | 6 +- .../Enhancements/randomizer/item_location.h | 2 +- soh/soh/Enhancements/randomizer/logic.cpp | 24 +- soh/soh/Enhancements/randomizer/option.cpp | 55 ++- soh/soh/Enhancements/randomizer/option.h | 52 +- .../Enhancements/randomizer/randomizer.cpp | 2 +- soh/soh/Enhancements/randomizer/settings.cpp | 459 +++++++++--------- .../Enhancements/timesaver_hook_handlers.cpp | 2 +- soh/soh/OTRGlobals.cpp | 2 +- soh/soh/SaveManager.cpp | 10 +- 23 files changed, 377 insertions(+), 369 deletions(-) diff --git a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp index 0bb65a8de..9f9b67fec 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipCutscene/Story/SkipBlueWarp.cpp @@ -10,7 +10,7 @@ extern "C" { #include "variables.h" } -#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex() static bool sEnteredBlueWarp = false; diff --git a/soh/soh/Enhancements/kaleido.cpp b/soh/soh/Enhancements/kaleido.cpp index 9822b1956..33075ca50 100644 --- a/soh/soh/Enhancements/kaleido.cpp +++ b/soh/soh/Enhancements/kaleido.cpp @@ -125,8 +125,8 @@ namespace Rando { std::make_shared<KaleidoEntryIconCountRequired>( gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0, yOffset, reinterpret_cast<int*>(&gSaveContext.triforcePiecesCollected), - ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetSelectedOptionIndex() + 1, - ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetSelectedOptionIndex() + 1)); + ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1, + ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1)); yOffset += 18; } if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 833f4d028..93501b8fe 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -238,10 +238,10 @@ static int GetMaxGSCount() { int maxBridge = 0; int maxLACS = 0; if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { - maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>(); + maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex(); } if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { - maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>(); + maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex(); } maxBridge = std::max(maxBridge, maxLACS); //Get the max amount of GS which could be useful from token reward locations @@ -266,7 +266,7 @@ static int GetMaxGSCount() { maxUseful = 10; } //Return max of the two possible reasons tokens could be important, minus the tokens in the starting inventory - return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Value<uint8_t>(); + return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex(); } std::string GetShopItemBaseName(std::string itemName) { diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index ee6a638f5..941f0924b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -222,18 +222,18 @@ uint8_t StonesRequiredBySettings() { auto ctx = Rando::Context::GetInstance(); uint8_t stones = 0; if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { - stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value<uint8_t>(); + stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex(); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { - stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>() - 6; + stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 6; } else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) { - stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>() - 6; + stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 6; } if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { - stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Value<uint8_t>() }); + stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex() }); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { - stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>() - 6 )}); + stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 6 )}); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { - stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>() - 6 )}); + stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 6 )}); } return stones; } @@ -242,18 +242,18 @@ uint8_t MedallionsRequiredBySettings() { auto ctx = Rando::Context::GetInstance(); uint8_t medallions = 0; if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { - medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value<uint8_t>(); + medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex(); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { - medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>() - 3; + medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 3; } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { - medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>() - 3; + medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 3; } if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { - medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value<uint8_t>() }); + medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex() }); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { - medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>() - 3 )}); + medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 3 )}); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { - medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>() - 3 )}); + medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 3 )}); } return medallions; } @@ -262,10 +262,10 @@ uint8_t TokensRequiredBySettings() { auto ctx = Rando::Context::GetInstance(); uint8_t tokens = 0; if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { - tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>(); + tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex(); } if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { - tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>() }); + tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex() }); } return tokens; } @@ -273,7 +273,7 @@ uint8_t TokensRequiredBySettings() { std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlwaysHints = { std::make_pair(RC_MARKET_10_BIG_POES, []() { auto ctx = Rando::Context::GetInstance(); - return ctx->GetOption(RSK_BIG_POE_COUNT).Value<uint8_t>() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); + return ctx->GetOption(RSK_BIG_POE_COUNT).GetContextOptionIndex() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); }), // Remember, the option's value being 3 means 4 are required std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { auto ctx = Rando::Context::GetInstance(); @@ -483,7 +483,7 @@ static void CreateTrialHints(uint8_t copies) { AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_ZERO_TRIALS}); } else { std::vector<TrialInfo*> trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment - if (ctx->GetOption(RSK_TRIAL_COUNT).Value<uint8_t>() >= 4) {//4 or 5 required trials, get skipped trials + if (ctx->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() >= 4) {//4 or 5 required trials, get skipped trials trials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();}); } else {//1 to 3 trials, get requried trials auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();}); @@ -611,7 +611,7 @@ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistribu void CreateStoneHints() { auto ctx = Rando::Context::GetInstance(); SPDLOG_DEBUG("\nNOW CREATING HINTS\n"); - const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Value<uint8_t>()]; + const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).GetContextOptionIndex()]; std::vector<HintDistributionSetting> distTable = hintSetting.distTable; // Apply impa's song exclusions when zelda is skipped diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 52f6359c5..5d7a290c0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -655,7 +655,7 @@ static void SetMinimalItemPool() { ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1); ReplaceMaxItem(RG_PIECE_OF_HEART, 0); // Need an extra heart container when starting with 1 heart to be able to reach 3 hearts - ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Value<uint8_t>() == 18)? 1 : 0); + ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() == 18)? 1 : 0); } void GenerateItemPool() { @@ -721,7 +721,7 @@ void GenerateItemPool() { if (ctx->GetOption(RSK_TRIFORCE_HUNT)) { ctx->possibleIceTrapModels.push_back(RG_TRIFORCE_PIECE); - AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Value<uint8_t>() + 1)); + AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1)); ctx->PlaceItemInLocation(RC_TRIFORCE_COMPLETED, RG_TRIFORCE); // Win condition ctx->PlaceItemInLocation(RC_GANON, GetJunkItem(), false, true); } else { @@ -821,7 +821,7 @@ void GenerateItemPool() { if (fsMode.IsNot(RO_FISHSANITY_OFF)) { if (fsMode.Is(RO_FISHSANITY_POND) || fsMode.Is(RO_FISHSANITY_BOTH)) { // 17 max child pond fish - uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).GetSelectedOptionIndex(); + uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).GetContextOptionIndex(); for (uint8_t i = 0; i < pondCt; i++) { AddItemToMainPool(GetJunkItem()); } @@ -1348,7 +1348,7 @@ void GenerateItemPool() { if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY); - } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Value<uint8_t>() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { + } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).GetContextOptionIndex() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) { ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY); diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp index efb15780e..aa384e665 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access.cpp @@ -260,7 +260,7 @@ void RegionTable_Init() { areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, {}, { //Locations LOCATION(RC_LINKS_POCKET, true), - LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Value<uint8_t>();), + LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex();), LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)), }, { //Exits @@ -395,7 +395,7 @@ void ReplaceAllInString(std::string& s, std::string const& toReplace, std::strin std::string CleanCheckConditionString(std::string condition) { ReplaceAllInString(condition, "logic->", ""); ReplaceAllInString(condition, "ctx->", ""); - ReplaceAllInString(condition, ".Value<uint8_t>()", ""); + ReplaceAllInString(condition, ".GetContextOptionIndex()", ""); ReplaceAllInString(condition, "GetSaveContext()->", ""); return condition; } diff --git a/soh/soh/Enhancements/randomizer/3drando/shops.cpp b/soh/soh/Enhancements/randomizer/3drando/shops.cpp index f6c73de32..ecf4ea1be 100644 --- a/soh/soh/Enhancements/randomizer/3drando/shops.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/shops.cpp @@ -156,7 +156,7 @@ int GetPriceFromMax(int max) { uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSettings) { auto ctx = Rando::Context::GetInstance(); - switch (ctx->GetOption(priceSettings.main).Value<uint8_t>()){ + switch (ctx->GetOption(priceSettings.main).GetContextOptionIndex()){ case RO_PRICE_VANILLA: return loc->GetVanillaPrice(); case RO_PRICE_CHEAP_BALANCED: @@ -172,19 +172,19 @@ uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSet return 150; } case RO_PRICE_FIXED: - return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).Value<uint8_t>() * 5; + return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).GetContextOptionIndex() * 5; case RO_PRICE_RANGE:{ - uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).Value<uint8_t>() * 5; - uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).Value<uint8_t>() * 5; + uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).GetContextOptionIndex() * 5; + uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).GetContextOptionIndex() * 5; return range1 < range2 ? Random(range1, range2+1) : Random(range2, range1+1); } case RO_PRICE_SET_BY_WALLET:{ - bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).Value<bool>(); - uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).Value<uint8_t>(); - uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).Value<uint8_t>(); - uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).Value<uint8_t>(); - uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).Value<uint8_t>(); - uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).Value<uint8_t>() : 0; + bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).GetContextOptionIndex(); + uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).GetContextOptionIndex(); + uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).GetContextOptionIndex(); + uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).GetContextOptionIndex(); + uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).GetContextOptionIndex(); + uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).GetContextOptionIndex() : 0; uint16_t totalWeight = noWeight + childWeight + adultWeight + giantWeight + tycoonWeight; if (totalWeight == 0){ //if no weight, return from sane range return Random(0, 501); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index a418b8b5d..fb77fd97f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -176,7 +176,7 @@ static void WriteSettings() { auto allOptionGroups = ctx->GetSettings()->GetOptionGroups(); for (const Rando::OptionGroup& optionGroup : allOptionGroups) { if (optionGroup.GetContainsType() == Rando::OptionGroupType::DEFAULT && optionGroup.PrintInSpoiler()) { - for (const Rando::Option* option : optionGroup.GetOptions()) { + for (Rando::Option* option : optionGroup.GetOptions()) { std::string settingName = optionGroup.GetName() + ":" + option->GetName(); jsonData["settings"][settingName] = option->GetSelectedOptionText(); } @@ -191,7 +191,7 @@ static void WriteExcludedLocations() { for (size_t i = 1; i < ctx->GetSettings()->GetExcludeLocationsOptions().size(); i++) { for (const auto& location : ctx->GetSettings()->GetExcludeLocationsOptions()[i]) { - if (location->GetSelectedOptionIndex() == RO_LOCATION_INCLUDE) { + if (location->GetContextOptionIndex() == RO_LOCATION_INCLUDE) { continue; } @@ -214,7 +214,7 @@ static void WriteStartingInventory() { const Rando::OptionGroup& optionGroup = ctx->GetSettings()->GetOptionGroup(RSG_STARTING_INVENTORY); for (const Rando::OptionGroup* subGroup : optionGroup.GetSubGroups()) { if (subGroup->GetContainsType() == Rando::OptionGroupType::DEFAULT) { - for (const Rando::Option* option : subGroup->GetOptions()) { + for (Rando::Option* option : subGroup->GetOptions()) { jsonData["settings"][option->GetName()] = option->GetSelectedOptionText(); } } @@ -227,7 +227,7 @@ static void WriteEnabledTricks(tinyxml2::XMLDocument& spoilerLog) { auto ctx = Rando::Context::GetInstance(); for (const auto& setting : ctx->GetSettings()->GetOptionGroup(RSG_TRICKS).GetOptions()) { - if (setting->GetSelectedOptionIndex() != RO_GENERIC_ON/* || !setting->IsCategory(OptionCategory::Setting)*/) { + if (setting->GetContextOptionIndex() != RO_GENERIC_ON/* || !setting->IsCategory(OptionCategory::Setting)*/) { continue; } jsonData["enabledTricks"].push_back(RemoveLineBreaks(setting->GetName()).c_str()); diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp index 781b54ad3..035259fdb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp @@ -112,7 +112,7 @@ void GenerateStartingInventory() { // AddItemToInventory(RG_EMPTY_BOTTLE, 1); // } // AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>()); - AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Value<uint8_t>()); + AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).GetContextOptionIndex()); AddItemToInventory(RG_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY) ? 1 : 0); AddItemToInventory(RG_EPONAS_SONG, ctx->GetOption(RSK_STARTING_EPONAS_SONG) ? 1 : 0); AddItemToInventory(RG_SARIAS_SONG, ctx->GetOption(RSK_STARTING_SARIAS_SONG) ? 1 : 0); @@ -153,21 +153,21 @@ void GenerateStartingInventory() { // AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>()); // AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>()); // AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>()); - AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Value<uint8_t>()); + AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex()); - int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).Value<uint8_t>() - 2; + int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() - 2; AdditionalHeartContainers = 0; if (hearts < 0) { AddItemToInventory(RG_PIECE_OF_HEART, 4); // Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart - if (ctx->GetOption(RSK_ITEM_POOL).Value<uint8_t>() == 0 || ctx->GetOption(RSK_ITEM_POOL).Value<uint8_t>() == 3) { + if (ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 0 || ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 3) { AddItemToInventory(RG_TREASURE_GAME_HEART); } AdditionalHeartContainers = 1 - hearts; } else if (hearts > 0) { // 16 containers in plentiful, 8 in balanced and 0 in the others - uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).Value<uint8_t>()); + uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex()); if (hearts <= maxContainers) { AddItemToInventory(RG_HEART_CONTAINER, hearts); diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index bc9cb5513..bce400d91 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -1333,12 +1333,12 @@ int EntranceShuffler::ShuffleAllEntrances() { (ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES) ? 1 : 0); if (totalMixedPools < 2) { - ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).SetSelectedIndex(RO_GENERIC_OFF); - ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); - ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); - ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); - ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); - ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).SetSelectedIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).SetContextIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).SetContextIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).SetContextIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).SetContextIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).SetContextIndex(RO_GENERIC_OFF); + ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).SetContextIndex(RO_GENERIC_OFF); } if (ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS)) { std::set<EntranceType> poolsToMix = {}; diff --git a/soh/soh/Enhancements/randomizer/fishsanity.cpp b/soh/soh/Enhancements/randomizer/fishsanity.cpp index 46b01e2d3..f3ff89d70 100644 --- a/soh/soh/Enhancements/randomizer/fishsanity.cpp +++ b/soh/soh/Enhancements/randomizer/fishsanity.cpp @@ -17,7 +17,7 @@ extern PlayState* gPlayState; #define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity() -#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex() /** * @brief Parallel list of pond fish checks for both ages diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index 056102195..e248eebe0 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -559,23 +559,23 @@ CustomMessage Hint::GetBridgeReqsText() { } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) { bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_STONES_HINT].GetHintMessage(); - bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value<uint8_t>()); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) { bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT].GetHintMessage(); - bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value<uint8_t>()); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) { bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_REWARDS_HINT].GetHintMessage(); - bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>()); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) { bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_DUNGEONS_HINT].GetHintMessage(); - bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>()); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) { bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_TOKENS_HINT].GetHintMessage(); - bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>()); + bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) { return StaticData::hintTextTable[RHT_BRIDGE_GREG_HINT].GetHintMessage(); @@ -613,23 +613,23 @@ CustomMessage Hint::GetGanonBossKeyText() { } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) { ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_STONES_HINT].GetHintMessage(); - ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).Value<uint8_t>()); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) { ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_MEDALLIONS_HINT].GetHintMessage(); - ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value<uint8_t>()); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) { ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_REWARDS_HINT].GetHintMessage(); - ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>()); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) { ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_DUNGEONS_HINT].GetHintMessage(); - ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>()); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) { ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_TOKENS_HINT].GetHintMessage(); - ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>()); + ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex()); } else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) { return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage(); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index c98dabf74..f59cae9fe 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -62,7 +62,7 @@ extern s32 Player_SetupWaitForPutAway(PlayState* play, Player* player, AfterPutA extern void Play_InitEnvironment(PlayState * play, s16 skyboxId); } -#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex() bool LocMatchesQuest(Rando::Location loc) { if (loc.GetQuest() == RCQUEST_BOTH) { diff --git a/soh/soh/Enhancements/randomizer/item_location.cpp b/soh/soh/Enhancements/randomizer/item_location.cpp index 6b1e3003e..9f0f84509 100644 --- a/soh/soh/Enhancements/randomizer/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/item_location.cpp @@ -176,8 +176,8 @@ void ItemLocation::SetHidden(const bool hidden_) { hidden = hidden_; } -bool ItemLocation::IsExcluded() const { - return excludedOption.Value<bool>(); +bool ItemLocation::IsExcluded() { + return excludedOption.GetContextOptionIndex(); } Option* ItemLocation::GetExcludedOption() { @@ -197,7 +197,7 @@ void ItemLocation::AddExcludeOption() { // RANDOTODO: this without string compares and loops bool alreadyAdded = false; const Location* loc = StaticData::GetLocation(rc); - for (const Option* location : Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea())) { + for (Option* location : Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea())) { if (location->GetName() == excludedOption.GetName()) { alreadyAdded = true; } diff --git a/soh/soh/Enhancements/randomizer/item_location.h b/soh/soh/Enhancements/randomizer/item_location.h index d49debf5f..4ec8b8b9e 100644 --- a/soh/soh/Enhancements/randomizer/item_location.h +++ b/soh/soh/Enhancements/randomizer/item_location.h @@ -45,7 +45,7 @@ class ItemLocation { const std::vector<RandomizerHint>& GetHintedBy() const; void AddHintedBy(RandomizerHint hintKey); bool IsHidden() const; - bool IsExcluded() const; + bool IsExcluded(); void AddExcludeOption(); Option* GetExcludedOption(); void SetHidden(bool hidden_); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 15271534c..1ef328496 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -974,7 +974,7 @@ namespace Rando { 10 for OHKO. This is the number of shifts to apply, not a real multiplier */ - uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value<uint8_t>() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Value<uint8_t>() : 10; + uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() : 10; //(Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) is quarter hearts after DD //>> Multiplier halves on normal and does nothing on half, meaning we're working with half hearts on normal damage return ((Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) >> Multiplier) + @@ -1103,21 +1103,21 @@ namespace Rando { bool Logic::CanBuildRainbowBridge(){ return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN) || (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA) && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION) && CanUse(RG_LIGHT_ARROWS)) || - (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Value<uint8_t>()) || - (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Value<uint8_t>()) || - (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Value<uint8_t>()) || - (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Value<uint8_t>()) || - (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Value<uint8_t>()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex()) || + (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex()) || (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && HasItem(RG_GREG_RUPEE)); } bool Logic::CanTriggerLACS(){ return (ctx->GetSettings()->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) || - (ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).Value<uint8_t>()) || - (ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Value<uint8_t>()) || - (ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).Value<uint8_t>()) || - (ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Value<uint8_t>()) || - (ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Value<uint8_t>()); + (ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex()) || + (ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex()); } bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) { @@ -2089,7 +2089,7 @@ namespace Rando { //CanPlantBean = false; BigPoeKill = false; - BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Value<uint8_t>() + 1; + BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() + 1; //Bridge Requirements diff --git a/soh/soh/Enhancements/randomizer/option.cpp b/soh/soh/Enhancements/randomizer/option.cpp index af7ba150e..75b02bf51 100644 --- a/soh/soh/Enhancements/randomizer/option.cpp +++ b/soh/soh/Enhancements/randomizer/option.cpp @@ -31,10 +31,7 @@ Option Option::LogicTrick(std::string name_) { } Option::operator bool() const { - if (std::holds_alternative<bool>(var)) { - return Value<bool>(); - } - return Value<uint8_t>() != 0; + return contextSelection != 0; } size_t Option::GetOptionCount() const { @@ -49,12 +46,16 @@ const std::string& Option::GetDescription() const { return description; } -uint8_t Option::GetSelectedOptionIndex() const { - return selectedOption; +uint8_t Option::GetMenuOptionIndex() const { + return menuSelection; +} + +uint8_t Option::GetContextOptionIndex() const { + return contextSelection; } const std::string& Option::GetSelectedOptionText() const { - return options[selectedOption]; + return options[menuSelection]; } const std::string& Option::GetCVarName() const { @@ -63,39 +64,45 @@ const std::string& Option::GetCVarName() const { void Option::SetVariable() { if (std::holds_alternative<bool>(var)) { - var.emplace<bool>(selectedOption != 0); + var.emplace<bool>(menuSelection != 0); } else { - var.emplace<uint8_t>(selectedOption); + var.emplace<uint8_t>(menuSelection); } } -void Option::SetCVar() const { +void Option::SaveCVar() const { if (!cvarName.empty()) { - CVarSetInteger(cvarName.c_str(), GetSelectedOptionIndex()); + CVarSetInteger(cvarName.c_str(), GetMenuOptionIndex()); } } void Option::SetFromCVar() { if (!cvarName.empty()) { - SetSelectedIndex(CVarGetInteger(cvarName.c_str(), defaultOption)); + SetMenuIndex(CVarGetInteger(cvarName.c_str(), defaultOption)); } } void Option::SetDelayedOption() { - delayedOption = selectedOption; + delayedSelection = contextSelection; } void Option::RestoreDelayedOption() { - selectedOption = delayedOption; + contextSelection = delayedSelection; +} + +void Option::SetMenuIndex(size_t idx) { + menuSelection = idx; + if (menuSelection > options.size() - 1) { + menuSelection = options.size() - 1; + } SetVariable(); } -void Option::SetSelectedIndex(size_t idx) { - selectedOption = idx; - if (selectedOption > options.size() - 1) { - selectedOption = options.size() - 1; +void Option::SetContextIndex(size_t idx) { + contextSelection = idx; + if (contextSelection > options.size() - 1) { + contextSelection = options.size() - 1; } - SetVariable(); } void Option::Hide() { @@ -111,8 +118,8 @@ bool Option::IsHidden() const { } void Option::ChangeOptions(std::vector<std::string> opts) { - if (selectedOption >= opts.size()) { - selectedOption = opts.size() - 1; + if (menuSelection >= opts.size()) { + menuSelection = opts.size() - 1; } options = std::move(opts); } @@ -177,7 +184,7 @@ Option::Option(uint8_t var_, std::string name_, std::vector<std::string> options : var(var_), name(std::move(name_)), options(std::move(options_)), category(category_), cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_), defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) { - selectedOption = defaultOption; + menuSelection = contextSelection = defaultOption; hidden = defaultHidden; SetFromCVar(); } @@ -187,7 +194,7 @@ Option::Option(bool var_, std::string name_, std::vector<std::string> options_, : var(var_), name(std::move(name_)), options(std::move(options_)), category(category_), cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_), defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) { - selectedOption = defaultOption; + menuSelection = contextSelection = defaultOption; hidden = defaultHidden; SetFromCVar(); } @@ -270,7 +277,7 @@ bool Option::RenderCombobox() { bool Option::RenderSlider() { bool changed = false; - int val = GetSelectedOptionIndex(); + int val = GetMenuOptionIndex(); if (val > options.size() - 1) { val = options.size() - 1; CVarSetInteger(cvarName.c_str(), val); diff --git a/soh/soh/Enhancements/randomizer/option.h b/soh/soh/Enhancements/randomizer/option.h index 1bb979ebc..5b7eb5b9d 100644 --- a/soh/soh/Enhancements/randomizer/option.h +++ b/soh/soh/Enhancements/randomizer/option.h @@ -126,42 +126,25 @@ class Option { */ static Option LogicTrick(std::string name_); - /** - * @brief Gets the selected index or boolean value of the Option. - * - * @tparam T uint8_t or bool, depending on how the option was constructed. - * @return T - */ - template <typename T> T Value() const { - return std::get<T>(var); - } - /** * @brief Determines if the value/selected index of this Option matches the provided value. * - * @tparam T uint8_t, bool, or an enum (which will be cast to uint8_t). * @param other The value to compare. * @return true * @return false */ - template <typename T> bool Is(T other) const { - static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "T must be an integral type or an enum."); - if constexpr ((std::is_integral_v<T> && !std::is_same_v<bool, T>) || std::is_enum_v<T>) { - return Value<uint8_t>() == static_cast<uint8_t>(other); - } else { - return Value<bool>() == static_cast<bool>(other); - } + bool Is(uint32_t other) const { + return contextSelection == other; } /** * @brief Determines if the value/selected index of this Option does not match the provided value. * - * @tparam T uint8_t, book, or an enum (which will be cast to uint8_t). * @param other The value to compare. * @return true * @return false */ - template <typename T> bool IsNot(T other) const { + bool IsNot(uint32_t other) const { return !Is(other); } @@ -203,11 +186,18 @@ class Option { const std::string& GetCVarName() const; /** - * @brief Get the selected index for this Option. + * @brief Get the menu index for this Option. * * @return uint8_t */ - uint8_t GetSelectedOptionIndex() const; + uint8_t GetMenuOptionIndex() const; + + /** + * @brief Get the rando context index for this Option. + * + * @return uint8_t + */ + uint8_t GetContextOptionIndex() const; /** * @brief Sets the variable to the currently selected index for this Option. @@ -218,7 +208,7 @@ class Option { * @brief Sets the CVar corresponding to the property `cvarName` equal to the value * of the property `selectedValue`. */ - void SetCVar() const; + void SaveCVar() const; /** * @brief Sets the value of property `selectedValue` equal to the CVar corresponding @@ -237,11 +227,18 @@ class Option { void RestoreDelayedOption(); /** - * @brief Set the selected index for this Option. Also calls `SetVariable()`. + * @brief Set the menu index for this Option. Also calls `SetVariable()`. * * @param idx the index to set as the selected index. */ - void SetSelectedIndex(size_t idx); + void SetMenuIndex(size_t idx); + + /** + * @brief Set the rando context index for this Option. Also calls `SetVariable()`. + * + * @param idx the index to set as the selected index. + */ + void SetContextIndex(size_t idx); /** * @brief Hides this Option in the menu. (Not currently being used afaik, we prefer to @@ -324,8 +321,9 @@ protected: std::variant<bool, uint8_t> var; std::string name; std::vector<std::string> options; - uint8_t selectedOption = 0; - uint8_t delayedOption = 0; + uint8_t menuSelection = 0; + uint8_t contextSelection = 0; + uint8_t delayedSelection = 0; bool hidden = false; OptionCategory category = OptionCategory::Setting; std::string cvarName; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index eb748dae9..12f52516a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1270,7 +1270,7 @@ FishIdentity Randomizer::IdentifyFish(s32 sceneNum, s32 actorParams) { } u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { - return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetSelectedOptionIndex(); + return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetContextOptionIndex(); } GetItemEntry Randomizer::GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability) { diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index ce9330adb..df3d31c76 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1468,7 +1468,7 @@ TrickOption& Settings::GetTrickOption(const RandomizerTrick key) { void Settings::ResetTrickOptions() { for (int count = 0; count < RT_MAX; count++){ - mTrickOptions[count].SetSelectedIndex(0); //RANDOTODO this can probably be done better + mTrickOptions[count].SetContextIndex(0); //RANDOTODO this can probably be done better }; } @@ -2212,6 +2212,9 @@ void Settings::UpdateOptionProperties() { void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocations, const std::set<RandomizerTrick>& enabledTricks) { const auto ctx = Rando::Context::GetInstance(); if (!ctx->IsSpoilerLoaded()) { + for (Option& option : mOptions) { + option.SetContextIndex(option.GetMenuOptionIndex()); + } // If we've loaded a spoiler file, the settings have already been populated, so we // only need to do things like resolve the starting age or determine MQ dungeons. // Any logic dependent on cvarSettings should go in this if statement @@ -2219,39 +2222,39 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio // if we skip child zelda, we start with zelda's letter, and malon starts // at the ranch, so we should *not* shuffle the weird egg if (mOptions[RSK_SKIP_CHILD_ZELDA]) { - mOptions[RSK_SHUFFLE_WEIRD_EGG].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_SHUFFLE_WEIRD_EGG].SetContextIndex(RO_GENERIC_OFF); } // With certain access settings, the seed is only beatable if Starting Age is set to Child. if (mOptions[RSK_FOREST].Is(RO_FOREST_CLOSED) || (mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA])) { - mOptions[RSK_STARTING_AGE].SetSelectedIndex(RO_AGE_CHILD); + mOptions[RSK_STARTING_AGE].SetContextIndex(RO_AGE_CHILD); } if (mOptions[RSK_TRIFORCE_HUNT]) { - mOptions[RSK_GANONS_BOSS_KEY].SetSelectedIndex(RO_GANON_BOSS_KEY_TRIFORCE_HUNT); + mOptions[RSK_GANONS_BOSS_KEY].SetContextIndex(RO_GANON_BOSS_KEY_TRIFORCE_HUNT); } // Force 100 GS Shuffle if that's where Ganon's Boss Key is if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) { - mOptions[RSK_SHUFFLE_100_GS_REWARD].SetSelectedIndex(1); + mOptions[RSK_SHUFFLE_100_GS_REWARD].SetContextIndex(1); } // If we only have MQ, set all dungeons to MQ if (OTRGlobals::Instance->HasMasterQuest() && !OTRGlobals::Instance->HasOriginal()) { - mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_SET_NUMBER); - mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(12); - mOptions[RSK_MQ_DUNGEON_SET].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_MQ_DUNGEON_RANDOM].SetContextIndex(RO_MQ_DUNGEONS_SET_NUMBER); + mOptions[RSK_MQ_DUNGEON_COUNT].SetContextIndex(12); + mOptions[RSK_MQ_DUNGEON_SET].SetContextIndex(RO_GENERIC_OFF); } // If we don't have MQ, set all dungeons to Vanilla if (OTRGlobals::Instance->HasOriginal() && !OTRGlobals::Instance->HasMasterQuest()) { - mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_NONE); + mOptions[RSK_MQ_DUNGEON_RANDOM].SetContextIndex(RO_MQ_DUNGEONS_NONE); } if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_NONE)) { - mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(0); - mOptions[RSK_MQ_DUNGEON_SET].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_MQ_DUNGEON_COUNT].SetContextIndex(0); + mOptions[RSK_MQ_DUNGEON_SET].SetContextIndex(RO_GENERIC_OFF); } // If any of the individual shuffle settings are on, turn on the main Shuffle Entrances option @@ -2261,53 +2264,53 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio || mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].IsNot(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES] || mOptions[RSK_SHUFFLE_OWL_DROPS] || mOptions[RSK_SHUFFLE_WARP_SONGS] || mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]) { - mOptions[RSK_SHUFFLE_ENTRANCES].SetSelectedIndex(RO_GENERIC_ON); + mOptions[RSK_SHUFFLE_ENTRANCES].SetContextIndex(RO_GENERIC_ON); } else { - mOptions[RSK_SHUFFLE_ENTRANCES].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_SHUFFLE_ENTRANCES].SetContextIndex(RO_GENERIC_OFF); } if (mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) { - mOptions[RSK_LINKS_POCKET].SetSelectedIndex(RO_LINKS_POCKET_DUNGEON_REWARD); + mOptions[RSK_LINKS_POCKET].SetContextIndex(RO_LINKS_POCKET_DUNGEON_REWARD); } if (!ctx->IsSpoilerLoaded()) { ctx->AddExcludedOptions(); for (const auto locationKey : ctx->everyPossibleLocation) { if (const auto location = ctx->GetItemLocation(locationKey); excludedLocations.contains(location->GetRandomizerCheck())) { - location->GetExcludedOption()->SetSelectedIndex(1); + location->GetExcludedOption()->SetContextIndex(1); } else { - location->GetExcludedOption()->SetSelectedIndex(0); + location->GetExcludedOption()->SetContextIndex(0); } } // Tricks ResetTrickOptions(); for (const auto randomizerTrick : enabledTricks) { - mTrickOptions[randomizerTrick].SetSelectedIndex(1); + mTrickOptions[randomizerTrick].SetContextIndex(1); } } if (!mOptions[RSK_SHUFFLE_KOKIRI_SWORD]) { if (mOptions[RSK_STARTING_KOKIRI_SWORD]) { - ctx->GetItemLocation(RC_KF_KOKIRI_SWORD_CHEST)->GetExcludedOption()->SetSelectedIndex(1); + ctx->GetItemLocation(RC_KF_KOKIRI_SWORD_CHEST)->GetExcludedOption()->SetContextIndex(1); } } if (!mOptions[RSK_SHUFFLE_MASTER_SWORD]) { if (mOptions[RSK_STARTING_MASTER_SWORD]) { - ctx->GetItemLocation(RC_MASTER_SWORD_PEDESTAL)->GetExcludedOption()->SetSelectedIndex(1); + ctx->GetItemLocation(RC_MASTER_SWORD_PEDESTAL)->GetExcludedOption()->SetContextIndex(1); } } if (!mOptions[RSK_SHUFFLE_OCARINA]) { if (mOptions[RSK_STARTING_OCARINA].IsNot(RO_STARTING_OCARINA_OFF)) { - ctx->GetItemLocation(RC_LW_GIFT_FROM_SARIA)->GetExcludedOption()->SetSelectedIndex(1); + ctx->GetItemLocation(RC_LW_GIFT_FROM_SARIA)->GetExcludedOption()->SetContextIndex(1); if (mOptions[RSK_STARTING_OCARINA].Is(RO_STARTING_OCARINA_TIME)) { - ctx->GetItemLocation(RC_HF_OCARINA_OF_TIME_ITEM)->GetExcludedOption()->SetSelectedIndex(1); + ctx->GetItemLocation(RC_HF_OCARINA_OF_TIME_ITEM)->GetExcludedOption()->SetContextIndex(1); } } } } // RANDOTODO implement chest shuffle with keysanity - // ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); - mOptions[RSK_SHUFFLE_CHEST_MINIGAME].SetSelectedIndex(RO_CHEST_GAME_OFF); + // ShuffleChestMinigame.SetContextIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); + mOptions[RSK_SHUFFLE_CHEST_MINIGAME].SetContextIndex(RO_CHEST_GAME_OFF); //TODO: RandomizeAllSettings(true) when implementing the ability to randomize the options themselves. std::array<DungeonInfo*, 12> dungeons = ctx->GetDungeons()->GetDungeonList(); @@ -2318,12 +2321,12 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio dungeon->SetDungeonKnown(true); } //if it's selection mode, process the selection directly - if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value<uint8_t>() == RO_MQ_DUNGEONS_SELECTION){ - mOptions[RSK_MQ_DUNGEON_SET].SetSelectedIndex(RO_GENERIC_ON); + if (mOptions[RSK_MQ_DUNGEON_RANDOM].GetContextOptionIndex() == RO_MQ_DUNGEONS_SELECTION){ + mOptions[RSK_MQ_DUNGEON_SET].SetContextIndex(RO_GENERIC_ON); //How many dungeons are set to MQ in selection uint8_t mqSet = 0; for (auto dungeon: dungeons) { - switch (mOptions[dungeon->GetMQSetting()].Value<uint8_t>()) { + switch (mOptions[dungeon->GetMQSetting()].GetContextOptionIndex()) { case RO_MQ_SET_MQ: dungeon->SetMQ(); mqSet += 1; @@ -2342,11 +2345,11 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio } } //override the dungeons set with the ones set by selection, so it's accurate for anything that wants to know MQ dungeon count - mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(mqSet); + mOptions[RSK_MQ_DUNGEON_COUNT].SetContextIndex(mqSet); //handling set number and random number together - } else if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value<uint8_t>() != RO_MQ_DUNGEONS_NONE){ + } else if (mOptions[RSK_MQ_DUNGEON_RANDOM].GetContextOptionIndex() != RO_MQ_DUNGEONS_NONE){ // so we don't have to call this repeatedly - uint8_t mqCount = mOptions[RSK_MQ_DUNGEON_COUNT].Value<uint8_t>(); + uint8_t mqCount = mOptions[RSK_MQ_DUNGEON_COUNT].GetContextOptionIndex(); //How many dungeons are set to MQ in selection uint8_t mqSet = 0; //the number of random @@ -2356,7 +2359,7 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio //if dungeons have been preset, process them if (mOptions[RSK_MQ_DUNGEON_SET]){ for (size_t i = 0; i < dungeons.size(); i++) { - switch (mOptions[dungeons[i]->GetMQSetting()].Value<uint8_t>()) { + switch (mOptions[dungeons[i]->GetMQSetting()].GetContextOptionIndex()) { case RO_MQ_SET_MQ: dungeons[i]->SetMQ(); mqSet += 1; @@ -2372,22 +2375,22 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio //otherwise, every dungeon is possible } else { //if the count is fixed to 12, we know everything is MQ, so can skip some setps and do not set Known - if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value<uint8_t>() == RO_MQ_DUNGEONS_SET_NUMBER && + if (mOptions[RSK_MQ_DUNGEON_RANDOM].GetContextOptionIndex() == RO_MQ_DUNGEONS_SET_NUMBER && mqCount == 12) { randMQOption = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; for (auto dungeon: dungeons) { - mOptions[dungeon->GetMQSetting()].SetSelectedIndex(RO_MQ_SET_MQ); + mOptions[dungeon->GetMQSetting()].SetContextIndex(RO_MQ_SET_MQ); } //if it's fixed to zero, set it to None instead. the rest is processed after - } else if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value<uint8_t>() == RO_MQ_DUNGEONS_SET_NUMBER && + } else if (mOptions[RSK_MQ_DUNGEON_RANDOM].GetContextOptionIndex() == RO_MQ_DUNGEONS_SET_NUMBER && mqCount == 0){ - mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_NONE); + mOptions[RSK_MQ_DUNGEON_RANDOM].SetContextIndex(RO_MQ_DUNGEONS_NONE); //otherwise, make everything a possibility and unknown } else { for (size_t i = 0; i < dungeons.size(); i++) { randMQOption.push_back(i); dungeons[i]->SetDungeonKnown(false); - mOptions[dungeons[i]->GetMQSetting()].SetSelectedIndex(RO_MQ_SET_RANDOM); + mOptions[dungeons[i]->GetMQSetting()].SetContextIndex(RO_MQ_SET_RANDOM); } } } @@ -2409,20 +2412,20 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio } else { //if there's no random options, check if we can collapse the setting into None or Selection if (mqSet == 0){ - mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_NONE); + mOptions[RSK_MQ_DUNGEON_RANDOM].SetContextIndex(RO_MQ_DUNGEONS_NONE); } else { - mOptions[RSK_MQ_DUNGEON_RANDOM].SetSelectedIndex(RO_MQ_DUNGEONS_SELECTION); + mOptions[RSK_MQ_DUNGEON_RANDOM].SetContextIndex(RO_MQ_DUNGEONS_SELECTION); } } //reset the value set based on what was actually set - mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(mqToSet + mqSet); + mOptions[RSK_MQ_DUNGEON_COUNT].SetContextIndex(mqToSet + mqSet); } //Not an if else as other settings can become None in processing - if (mOptions[RSK_MQ_DUNGEON_RANDOM].Value<uint8_t>() == RO_MQ_DUNGEONS_NONE) { - mOptions[RSK_MQ_DUNGEON_SET].SetSelectedIndex(RO_GENERIC_OFF); - mOptions[RSK_MQ_DUNGEON_COUNT].SetSelectedIndex(0); + if (mOptions[RSK_MQ_DUNGEON_RANDOM].GetContextOptionIndex() == RO_MQ_DUNGEONS_NONE) { + mOptions[RSK_MQ_DUNGEON_SET].SetContextIndex(RO_GENERIC_OFF); + mOptions[RSK_MQ_DUNGEON_COUNT].SetContextIndex(0); for (auto dungeon: dungeons) { - mOptions[dungeon->GetMQSetting()].SetSelectedIndex(RO_MQ_SET_VANILLA); + mOptions[dungeon->GetMQSetting()].SetContextIndex(RO_MQ_SET_VANILLA); } } @@ -2448,16 +2451,16 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio if (mOptions[RSK_GERUDO_FORTRESS].Is(RO_GF_NORMAL) && mOptions[RSK_GERUDO_KEYS].IsNot(RO_GERUDO_KEYS_VANILLA)) { keyrings.push_back(&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS]); } else { - mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF); + mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].SetContextIndex(RO_KEYRING_FOR_DUNGEON_OFF); } if (mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_RANDOM) || mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT)) { - const uint32_t keyRingCount = mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT) ? mOptions[RSK_KEYRINGS_RANDOM_COUNT].Value<uint8_t>() : Random(0, static_cast<int>(keyrings.size())); + const uint32_t keyRingCount = mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT) ? mOptions[RSK_KEYRINGS_RANDOM_COUNT].GetContextOptionIndex() : Random(0, static_cast<int>(keyrings.size())); Shuffle(keyrings); for (size_t i = 0; i < keyRingCount; i++) { - keyrings[i]->SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_ON); + keyrings[i]->SetContextIndex(RO_KEYRING_FOR_DUNGEON_ON); } for (size_t i = keyRingCount; i < keyrings.size(); i++) { - keyrings[i]->SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF); + keyrings[i]->SetContextIndex(RO_KEYRING_FOR_DUNGEON_OFF); } } if (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_ON) || (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) { @@ -2492,11 +2495,11 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio trial->SetAsSkipped(); } if(mOptions[RSK_GANONS_TRIALS].Is(RO_GANONS_TRIALS_SKIP)){ - mOptions[RSK_TRIAL_COUNT].SetSelectedIndex(0); + mOptions[RSK_TRIAL_COUNT].SetContextIndex(0); } else if(mOptions[RSK_GANONS_TRIALS].Is(RO_GANONS_TRIALS_RANDOM_NUMBER)) { - mOptions[RSK_TRIAL_COUNT].SetSelectedIndex(Random(0, static_cast<int>(mOptions[RSK_TRIAL_COUNT].GetOptionCount()))); + mOptions[RSK_TRIAL_COUNT].SetContextIndex(Random(0, static_cast<int>(mOptions[RSK_TRIAL_COUNT].GetOptionCount()))); } - for (uint8_t i = 0; i < mOptions[RSK_TRIAL_COUNT].Value<uint8_t>(); i++) { + for (uint8_t i = 0; i < mOptions[RSK_TRIAL_COUNT].GetContextOptionIndex(); i++) { trials[i]->SetAsRequired(); } @@ -2504,7 +2507,7 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio (mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) || mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] || mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] || mOptions[RSK_DECOUPLED_ENTRANCES] || mOptions[RSK_MIXED_ENTRANCE_POOLS])) { - mOptions[RSK_FOREST].SetSelectedIndex(RO_FOREST_CLOSED_DEKU); + mOptions[RSK_FOREST].SetContextIndex(RO_FOREST_CLOSED_DEKU); } if (mOptions[RSK_STARTING_AGE].Is(RO_AGE_RANDOM)) { @@ -2514,7 +2517,7 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio mResolvedStartingAge = RO_AGE_ADULT; } } else { - mResolvedStartingAge = static_cast<RandoOptionStartingAge>(mOptions[RSK_STARTING_AGE].Value<uint8_t>()); + mResolvedStartingAge = static_cast<RandoOptionStartingAge>(mOptions[RSK_STARTING_AGE].GetContextOptionIndex()); } // TODO: Random Starting Time @@ -2535,35 +2538,35 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio if (mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) { for (Option* setting : VanillaLogicDefaults) { - setting->SetDelayedOption(); - setting->SetSelectedIndex(0); + //setting->SetDelayedOption(); + setting->SetContextIndex(0); } - mOptions[RSK_KEYSANITY].SetDelayedOption(); - mOptions[RSK_KEYSANITY].SetSelectedIndex(3); + //mOptions[RSK_KEYSANITY].SetDelayedOption(); + mOptions[RSK_KEYSANITY].SetContextIndex(3); } if (!mOptions[RSK_SHUFFLE_WARP_SONGS]) { - mOptions[RSK_WARP_SONG_HINTS].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_WARP_SONG_HINTS].SetContextIndex(RO_GENERIC_OFF); } if (!mOptions[RSK_SHUFFLE_COWS]) { - mOptions[RSK_MALON_HINT].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_MALON_HINT].SetContextIndex(RO_GENERIC_OFF); } if (!mOptions[RSK_SHUFFLE_100_GS_REWARD]) { - mOptions[RSK_KAK_100_SKULLS_HINT].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_KAK_100_SKULLS_HINT].SetContextIndex(RO_GENERIC_OFF); } if (!mOptions[RSK_SHUFFLE_FISHING_POLE]) { - mOptions[RSK_FISHING_POLE_HINT].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_FISHING_POLE_HINT].SetContextIndex(RO_GENERIC_OFF); } if (mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) { - mOptions[RSK_LOACH_HINT].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_LOACH_HINT].SetContextIndex(RO_GENERIC_OFF); } if (mOptions[RSK_CUCCO_COUNT].Is(0)) { - mOptions[RSK_CHICKENS_HINT].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[RSK_CHICKENS_HINT].SetContextIndex(RO_GENERIC_OFF); } } void Settings::ParseJson(nlohmann::json spoilerFileJson) { @@ -2581,115 +2584,115 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { switch (const RandomizerSettingKey index = mSpoilerfileSettingNameToEnum[it.key()]) { case RSK_LOGIC_RULES: if (it.value() == "Glitchless") { - mOptions[index].SetSelectedIndex(RO_LOGIC_GLITCHLESS); + mOptions[index].SetContextIndex(RO_LOGIC_GLITCHLESS); } else if (it.value() == "No Logic") { - mOptions[index].SetSelectedIndex(RO_LOGIC_NO_LOGIC); + mOptions[index].SetContextIndex(RO_LOGIC_NO_LOGIC); } else if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_LOGIC_VANILLA); + mOptions[index].SetContextIndex(RO_LOGIC_VANILLA); } break; case RSK_FOREST: if (it.value() == "Closed") { - mOptions[index].SetSelectedIndex(RO_FOREST_CLOSED); + mOptions[index].SetContextIndex(RO_FOREST_CLOSED); } else if (it.value() == "Open") { - mOptions[index].SetSelectedIndex(RO_FOREST_OPEN); + mOptions[index].SetContextIndex(RO_FOREST_OPEN); } else if (it.value() == "Closed Deku") { - mOptions[index].SetSelectedIndex(RO_FOREST_CLOSED_DEKU); + mOptions[index].SetContextIndex(RO_FOREST_CLOSED_DEKU); } break; case RSK_KAK_GATE: if (it.value() == "Closed") { - mOptions[index].SetSelectedIndex(RO_KAK_GATE_CLOSED); + mOptions[index].SetContextIndex(RO_KAK_GATE_CLOSED); } else if (it.value() == "Open") { - mOptions[index].SetSelectedIndex(RO_KAK_GATE_OPEN); + mOptions[index].SetContextIndex(RO_KAK_GATE_OPEN); } break; case RSK_DOOR_OF_TIME: if (it.value() == "Open") { - mOptions[index].SetSelectedIndex(RO_DOOROFTIME_OPEN); + mOptions[index].SetContextIndex(RO_DOOROFTIME_OPEN); } else if (it.value() == "Song only") { - mOptions[index].SetSelectedIndex(RO_DOOROFTIME_SONGONLY); + mOptions[index].SetContextIndex(RO_DOOROFTIME_SONGONLY); } else if (it.value() == "Closed") { - mOptions[index].SetSelectedIndex(RO_DOOROFTIME_CLOSED); + mOptions[index].SetContextIndex(RO_DOOROFTIME_CLOSED); } break; case RSK_ZORAS_FOUNTAIN: if (it.value() == "Closed") { - mOptions[index].SetSelectedIndex(RO_ZF_CLOSED); + mOptions[index].SetContextIndex(RO_ZF_CLOSED); } else if (it.value() == "Closed as child") { - mOptions[index].SetSelectedIndex(RO_ZF_CLOSED_CHILD); + mOptions[index].SetContextIndex(RO_ZF_CLOSED_CHILD); } else if (it.value() == "Open") { - mOptions[index].SetSelectedIndex(RO_ZF_OPEN); + mOptions[index].SetContextIndex(RO_ZF_OPEN); } break; case RSK_STARTING_AGE: if (it.value() == "Child") { - mOptions[index].SetSelectedIndex(RO_AGE_CHILD); + mOptions[index].SetContextIndex(RO_AGE_CHILD); } else if (it.value() == "Adult") { - mOptions[index].SetSelectedIndex(RO_AGE_ADULT); + mOptions[index].SetContextIndex(RO_AGE_ADULT); } break; case RSK_GERUDO_FORTRESS: if (it.value() == "Normal") { - mOptions[index].SetSelectedIndex(RO_GF_NORMAL); + mOptions[index].SetContextIndex(RO_GF_NORMAL); } else if (it.value() == "Fast") { - mOptions[index].SetSelectedIndex(RO_GF_FAST); + mOptions[index].SetContextIndex(RO_GF_FAST); } else if (it.value() == "Open") { - mOptions[index].SetSelectedIndex(RO_GF_OPEN); + mOptions[index].SetContextIndex(RO_GF_OPEN); } break; case RSK_RAINBOW_BRIDGE: if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_VANILLA); + mOptions[index].SetContextIndex(RO_BRIDGE_VANILLA); } else if (it.value() == "Always open") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_ALWAYS_OPEN); + mOptions[index].SetContextIndex(RO_BRIDGE_ALWAYS_OPEN); } else if (it.value() == "Stones") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_STONES); + mOptions[index].SetContextIndex(RO_BRIDGE_STONES); } else if (it.value() == "Medallions") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_MEDALLIONS); + mOptions[index].SetContextIndex(RO_BRIDGE_MEDALLIONS); } else if (it.value() == "Dungeon rewards") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_DUNGEON_REWARDS); + mOptions[index].SetContextIndex(RO_BRIDGE_DUNGEON_REWARDS); } else if (it.value() == "Dungeons") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_DUNGEONS); + mOptions[index].SetContextIndex(RO_BRIDGE_DUNGEONS); } else if (it.value() == "Tokens") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_TOKENS); + mOptions[index].SetContextIndex(RO_BRIDGE_TOKENS); } else if (it.value() == "Greg") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_GREG); + mOptions[index].SetContextIndex(RO_BRIDGE_GREG); } break; case RSK_BRIDGE_OPTIONS: if (it.value() == "Standard Rewards") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_STANDARD_REWARD); + mOptions[index].SetContextIndex(RO_BRIDGE_STANDARD_REWARD); } else if (it.value() == "Greg as Reward") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_GREG_REWARD); + mOptions[index].SetContextIndex(RO_BRIDGE_GREG_REWARD); } else if (it.value() == "Greg as Wildcard") { - mOptions[index].SetSelectedIndex(RO_BRIDGE_WILDCARD_REWARD); + mOptions[index].SetContextIndex(RO_BRIDGE_WILDCARD_REWARD); } break; case RSK_LACS_OPTIONS: if (it.value() == "Standard Reward") { - mOptions[index].SetSelectedIndex(RO_LACS_STANDARD_REWARD); + mOptions[index].SetContextIndex(RO_LACS_STANDARD_REWARD); } else if (it.value() == "Greg as Reward") { - mOptions[index].SetSelectedIndex(RO_LACS_GREG_REWARD); + mOptions[index].SetContextIndex(RO_LACS_GREG_REWARD); } else if (it.value() == "Greg as Wildcard") { - mOptions[index].SetSelectedIndex(RO_LACS_WILDCARD_REWARD); + mOptions[index].SetContextIndex(RO_LACS_WILDCARD_REWARD); } break; case RSK_DAMAGE_MULTIPLIER: if (it.value() == "x1/2") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_HALF); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_HALF); } else if (it.value() == "x1") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_DEFAULT); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_DEFAULT); } else if (it.value() == "x2") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_DOUBLE); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_DOUBLE); } else if (it.value() == "x4") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_QUADRUPLE); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_QUADRUPLE); } else if (it.value() == "x8") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_OCTUPLE); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_OCTUPLE); } else if (it.value() == "x16") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_SEXDECUPLE); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_SEXDECUPLE); } else if (it.value() == "OHKO") { - mOptions[index].SetSelectedIndex(RO_DAMAGE_MULTIPLIER_OHKO); + mOptions[index].SetContextIndex(RO_DAMAGE_MULTIPLIER_OHKO); } break; case RSK_RAINBOW_BRIDGE_STONE_COUNT: @@ -2709,7 +2712,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_STARTING_SKULLTULA_TOKEN: case RSK_SHOPSANITY_COUNT: numericValueString = it.value(); - mOptions[index].SetSelectedIndex(std::stoi(numericValueString)); + mOptions[index].SetContextIndex(std::stoi(numericValueString)); break; // Same as the above section, but the indexes are off by one from the text // (i.e. 10 Big Poes is index 9). @@ -2718,49 +2721,49 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_TRIFORCE_HUNT_PIECES_REQUIRED: case RSK_STARTING_HEARTS: numericValueString = it.value(); - mOptions[index].SetSelectedIndex(std::stoi(numericValueString) - 1); + mOptions[index].SetContextIndex(std::stoi(numericValueString) - 1); break; case RSK_GANONS_TRIALS: if (it.value() == "Skip") { - mOptions[index].SetSelectedIndex(RO_GANONS_TRIALS_SKIP); + mOptions[index].SetContextIndex(RO_GANONS_TRIALS_SKIP); } else if (it.value() == "Set Number") { - mOptions[index].SetSelectedIndex(RO_GANONS_TRIALS_SET_NUMBER); + mOptions[index].SetContextIndex(RO_GANONS_TRIALS_SET_NUMBER); } else if (it.value() == "Random Number") { - mOptions[index].SetSelectedIndex(RO_GANONS_TRIALS_RANDOM_NUMBER); + mOptions[index].SetContextIndex(RO_GANONS_TRIALS_RANDOM_NUMBER); } case RSK_SHOPSANITY: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_SHOPSANITY_OFF); + mOptions[index].SetContextIndex(RO_SHOPSANITY_OFF); } else if (it.value() == "Specific Count") { - mOptions[index].SetSelectedIndex(RO_SHOPSANITY_SPECIFIC_COUNT); + mOptions[index].SetContextIndex(RO_SHOPSANITY_SPECIFIC_COUNT); } else if (it.value() == "Random") { - mOptions[index].SetSelectedIndex(RO_SHOPSANITY_RANDOM); + mOptions[index].SetContextIndex(RO_SHOPSANITY_RANDOM); } break; case RSK_SHOPSANITY_PRICES: case RSK_SCRUBS_PRICES: case RSK_MERCHANT_PRICES: if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_PRICE_VANILLA); + mOptions[index].SetContextIndex(RO_PRICE_VANILLA); } else if (it.value() == "Cheap Balanced") { - mOptions[index].SetSelectedIndex(RO_PRICE_CHEAP_BALANCED); + mOptions[index].SetContextIndex(RO_PRICE_CHEAP_BALANCED); } else if (it.value() == "Balanced") { - mOptions[index].SetSelectedIndex(RO_PRICE_BALANCED); + mOptions[index].SetContextIndex(RO_PRICE_BALANCED); } else if (it.value() == "Fixed") { - mOptions[index].SetSelectedIndex(RO_PRICE_FIXED); + mOptions[index].SetContextIndex(RO_PRICE_FIXED); } else if (it.value() == "Range") { - mOptions[index].SetSelectedIndex(RO_PRICE_RANGE); + mOptions[index].SetContextIndex(RO_PRICE_RANGE); } else if (it.value() == "Set By Wallet") { - mOptions[index].SetSelectedIndex(RO_PRICE_SET_BY_WALLET); + mOptions[index].SetContextIndex(RO_PRICE_SET_BY_WALLET); } break; case RSK_SHUFFLE_SCRUBS: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_SCRUBS_OFF); + mOptions[index].SetContextIndex(RO_SCRUBS_OFF); } else if (it.value() == "Major Items Only") { - mOptions[index].SetSelectedIndex(RO_SCRUBS_MAJOR_ONLY); + mOptions[index].SetContextIndex(RO_SCRUBS_MAJOR_ONLY); } else if (it.value() == "All") { - mOptions[index].SetSelectedIndex(RO_SCRUBS_ALL); + mOptions[index].SetContextIndex(RO_SCRUBS_ALL); } break; case RSK_SHUFFLE_FISHING_POLE: @@ -2848,20 +2851,20 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SHUFFLE_DEKU_NUT_BAG: case RSK_SHUFFLE_DEKU_STICK_BAG: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_GENERIC_OFF); + mOptions[index].SetContextIndex(RO_GENERIC_OFF); } else if (it.value() == "On") { - mOptions[index].SetSelectedIndex(RO_GENERIC_ON); + mOptions[index].SetContextIndex(RO_GENERIC_ON); } break; case RSK_KEYRINGS: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_KEYRINGS_OFF); + mOptions[index].SetContextIndex(RO_KEYRINGS_OFF); } else if (it.value() == "Random") { - mOptions[index].SetSelectedIndex(RO_KEYRINGS_RANDOM); + mOptions[index].SetContextIndex(RO_KEYRINGS_RANDOM); } else if (it.value() == "Count") { - mOptions[index].SetSelectedIndex(RO_KEYRINGS_COUNT); + mOptions[index].SetContextIndex(RO_KEYRINGS_COUNT); } else if (it.value() == "Selection") { - mOptions[index].SetSelectedIndex(RO_KEYRINGS_SELECTION); + mOptions[index].SetContextIndex(RO_KEYRINGS_SELECTION); } break; case RSK_KEYRINGS_GERUDO_FORTRESS: @@ -2874,283 +2877,283 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_KEYRINGS_GTG: case RSK_KEYRINGS_GANONS_CASTLE: if (it.value() == "No") { - mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_OFF); + mOptions[index].SetContextIndex(RO_KEYRING_FOR_DUNGEON_OFF); } else if (it.value() == "Random") { - mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_RANDOM); + mOptions[index].SetContextIndex(RO_KEYRING_FOR_DUNGEON_RANDOM); } else if (it.value() == "Yes") { - mOptions[index].SetSelectedIndex(RO_KEYRING_FOR_DUNGEON_ON); + mOptions[index].SetContextIndex(RO_KEYRING_FOR_DUNGEON_ON); } break; case RSK_SHUFFLE_MERCHANTS: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_SHUFFLE_MERCHANTS_OFF); + mOptions[index].SetContextIndex(RO_SHUFFLE_MERCHANTS_OFF); } else if (it.value() == "Beans Only") { - mOptions[index].SetSelectedIndex(RO_SHUFFLE_MERCHANTS_BEANS_ONLY); + mOptions[index].SetContextIndex(RO_SHUFFLE_MERCHANTS_BEANS_ONLY); } else if (it.value() == "All but Beans") { - mOptions[index].SetSelectedIndex(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS); + mOptions[index].SetContextIndex(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS); } else if (it.value() == "All") { - mOptions[index].SetSelectedIndex(RO_SHUFFLE_MERCHANTS_ALL); + mOptions[index].SetContextIndex(RO_SHUFFLE_MERCHANTS_ALL); } break; // Uses Ammo Drops option for now. "Off" not yet implemented // TODO: Change to Ammo Drops case RSK_ENABLE_BOMBCHU_DROPS: if (it.value() == "Yes") { - mOptions[index].SetSelectedIndex(RO_AMMO_DROPS_ON); + mOptions[index].SetContextIndex(RO_AMMO_DROPS_ON); // } else if (it.value() == "On + Bombchu") { - // mOptions[index].SetSelectedIndex(RO_AMMO_DROPS_ON_PLUS_BOMBCHU); + // mOptions[index].SetContextIndex(RO_AMMO_DROPS_ON_PLUS_BOMBCHU); } else if (it.value() == "No") { - mOptions[index].SetSelectedIndex(RO_AMMO_DROPS_OFF); + mOptions[index].SetContextIndex(RO_AMMO_DROPS_OFF); } break; case RSK_FISHSANITY: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_FISHSANITY_OFF); + mOptions[index].SetContextIndex(RO_FISHSANITY_OFF); } else if (it.value() == "Shuffle Fishing Pond") { - mOptions[index].SetSelectedIndex(RO_FISHSANITY_POND); + mOptions[index].SetContextIndex(RO_FISHSANITY_POND); } else if (it.value() == "Shuffle Overworld Fish") { - mOptions[index].SetSelectedIndex(RO_FISHSANITY_OVERWORLD); + mOptions[index].SetContextIndex(RO_FISHSANITY_OVERWORLD); } else if (it.value() == "Shuffle Both") { - mOptions[index].SetSelectedIndex(RO_FISHSANITY_BOTH); + mOptions[index].SetContextIndex(RO_FISHSANITY_BOTH); } break; case RSK_SHUFFLE_BOSS_SOULS: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_OFF); + mOptions[index].SetContextIndex(RO_BOSS_SOULS_OFF); } else if (it.value() == "On") { - mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_ON); + mOptions[index].SetContextIndex(RO_BOSS_SOULS_ON); } else if (it.value() == "On + Ganon") { - mOptions[index].SetSelectedIndex(RO_BOSS_SOULS_ON_PLUS_GANON); + mOptions[index].SetContextIndex(RO_BOSS_SOULS_ON_PLUS_GANON); } case RSK_STARTING_OCARINA: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_STARTING_OCARINA_OFF); + mOptions[index].SetContextIndex(RO_STARTING_OCARINA_OFF); } else if (it.value() == "Fairy Ocarina") { - mOptions[index].SetSelectedIndex(RO_STARTING_OCARINA_FAIRY); + mOptions[index].SetContextIndex(RO_STARTING_OCARINA_FAIRY); } break; case RSK_ITEM_POOL: if (it.value() == "Plentiful") { - mOptions[index].SetSelectedIndex(RO_ITEM_POOL_PLENTIFUL); + mOptions[index].SetContextIndex(RO_ITEM_POOL_PLENTIFUL); } else if (it.value() == "Balanced") { - mOptions[index].SetSelectedIndex(RO_ITEM_POOL_BALANCED); + mOptions[index].SetContextIndex(RO_ITEM_POOL_BALANCED); } else if (it.value() == "Scarce") { - mOptions[index].SetSelectedIndex(RO_ITEM_POOL_SCARCE); + mOptions[index].SetContextIndex(RO_ITEM_POOL_SCARCE); } else if (it.value() == "Minimal") { - mOptions[index].SetSelectedIndex(RO_ITEM_POOL_MINIMAL); + mOptions[index].SetContextIndex(RO_ITEM_POOL_MINIMAL); } break; case RSK_ICE_TRAPS: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_ICE_TRAPS_OFF); + mOptions[index].SetContextIndex(RO_ICE_TRAPS_OFF); } else if (it.value() == "Normal") { - mOptions[index].SetSelectedIndex(RO_ICE_TRAPS_NORMAL); + mOptions[index].SetContextIndex(RO_ICE_TRAPS_NORMAL); } else if (it.value() == "Extra") { - mOptions[index].SetSelectedIndex(RO_ICE_TRAPS_EXTRA); + mOptions[index].SetContextIndex(RO_ICE_TRAPS_EXTRA); } else if (it.value() == "Mayhem") { - mOptions[index].SetSelectedIndex(RO_ICE_TRAPS_MAYHEM); + mOptions[index].SetContextIndex(RO_ICE_TRAPS_MAYHEM); } else if (it.value() == "Onslaught") { - mOptions[index].SetSelectedIndex(RO_ICE_TRAPS_ONSLAUGHT); + mOptions[index].SetContextIndex(RO_ICE_TRAPS_ONSLAUGHT); } break; case RSK_GOSSIP_STONE_HINTS: if (it.value() == "No Hints") { - mOptions[index].SetSelectedIndex(RO_GOSSIP_STONES_NONE); + mOptions[index].SetContextIndex(RO_GOSSIP_STONES_NONE); } else if (it.value() == "Need Nothing") { - mOptions[index].SetSelectedIndex(RO_GOSSIP_STONES_NEED_NOTHING); + mOptions[index].SetContextIndex(RO_GOSSIP_STONES_NEED_NOTHING); } else if (it.value() == "Mask of Truth") { - mOptions[index].SetSelectedIndex(RO_GOSSIP_STONES_NEED_TRUTH); + mOptions[index].SetContextIndex(RO_GOSSIP_STONES_NEED_TRUTH); } else if (it.value() == "Stone of Agony") { - mOptions[index].SetSelectedIndex(RO_GOSSIP_STONES_NEED_STONE); + mOptions[index].SetContextIndex(RO_GOSSIP_STONES_NEED_STONE); } break; case RSK_HINT_CLARITY: if (it.value() == "Obscure") { - mOptions[index].SetSelectedIndex(RO_HINT_CLARITY_OBSCURE); + mOptions[index].SetContextIndex(RO_HINT_CLARITY_OBSCURE); } else if (it.value() == "Ambiguous") { - mOptions[index].SetSelectedIndex(RO_HINT_CLARITY_AMBIGUOUS); + mOptions[index].SetContextIndex(RO_HINT_CLARITY_AMBIGUOUS); } else if (it.value() == "Clear") { - mOptions[index].SetSelectedIndex(RO_HINT_CLARITY_CLEAR); + mOptions[index].SetContextIndex(RO_HINT_CLARITY_CLEAR); } break; case RSK_HINT_DISTRIBUTION: if (it.value() == "Useless") { - mOptions[index].SetSelectedIndex(RO_HINT_DIST_USELESS); + mOptions[index].SetContextIndex(RO_HINT_DIST_USELESS); } else if (it.value() == "Balanced") { - mOptions[index].SetSelectedIndex(RO_HINT_DIST_BALANCED); + mOptions[index].SetContextIndex(RO_HINT_DIST_BALANCED); } else if (it.value() == "Strong") { - mOptions[index].SetSelectedIndex(RO_HINT_DIST_STRONG); + mOptions[index].SetContextIndex(RO_HINT_DIST_STRONG); } else if (it.value() == "Very Strong") { - mOptions[index].SetSelectedIndex(RO_HINT_DIST_VERY_STRONG); + mOptions[index].SetContextIndex(RO_HINT_DIST_VERY_STRONG); } break; case RSK_GERUDO_KEYS: if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_GERUDO_KEYS_VANILLA); + mOptions[index].SetContextIndex(RO_GERUDO_KEYS_VANILLA); } else if (it.value() == "Any Dungeon") { - mOptions[index].SetSelectedIndex(RO_GERUDO_KEYS_ANY_DUNGEON); + mOptions[index].SetContextIndex(RO_GERUDO_KEYS_ANY_DUNGEON); } else if (it.value() == "Overworld") { - mOptions[index].SetSelectedIndex(RO_GERUDO_KEYS_OVERWORLD); + mOptions[index].SetContextIndex(RO_GERUDO_KEYS_OVERWORLD); } else if (it.value() == "Anywhere") { - mOptions[index].SetSelectedIndex(RO_GERUDO_KEYS_ANYWHERE); + mOptions[index].SetContextIndex(RO_GERUDO_KEYS_ANYWHERE); } break; case RSK_KEYSANITY: case RSK_BOSS_KEYSANITY: case RSK_SHUFFLE_MAPANDCOMPASS: if (it.value() == "Start With") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ITEM_LOC_STARTWITH); + mOptions[index].SetContextIndex(RO_DUNGEON_ITEM_LOC_STARTWITH); } else if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ITEM_LOC_VANILLA); + mOptions[index].SetContextIndex(RO_DUNGEON_ITEM_LOC_VANILLA); } else if (it.value() == "Own Dungeon") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); + mOptions[index].SetContextIndex(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); } else if (it.value() == "Any Dungeon") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON); + mOptions[index].SetContextIndex(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON); } else if (it.value() == "Overworld") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ITEM_LOC_OVERWORLD); + mOptions[index].SetContextIndex(RO_DUNGEON_ITEM_LOC_OVERWORLD); } else if (it.value() == "Anywhere") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ITEM_LOC_ANYWHERE); + mOptions[index].SetContextIndex(RO_DUNGEON_ITEM_LOC_ANYWHERE); } break; case RSK_GANONS_BOSS_KEY: if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_VANILLA); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_VANILLA); } else if (it.value() == "Own dungeon") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_OWN_DUNGEON); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_OWN_DUNGEON); } else if (it.value() == "Start with") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_STARTWITH); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_STARTWITH); } else if (it.value() == "Any Dungeon") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_ANY_DUNGEON); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_ANY_DUNGEON); } else if (it.value() == "Overworld") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_OVERWORLD); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_OVERWORLD); } else if (it.value() == "Anywhere") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_ANYWHERE); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_ANYWHERE); } else if (it.value() == "LACS-Vanilla") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_LACS_VANILLA); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_LACS_VANILLA); } else if (it.value() == "LACS-Stones") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_LACS_STONES); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_LACS_STONES); } else if (it.value() == "LACS-Medallions") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_LACS_MEDALLIONS); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_LACS_MEDALLIONS); } else if (it.value() == "LACS-Rewards") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_LACS_REWARDS); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_LACS_REWARDS); } else if (it.value() == "LACS-Dungeons") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_LACS_DUNGEONS); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_LACS_DUNGEONS); } else if (it.value() == "LACS-Tokens") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_LACS_TOKENS); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_LACS_TOKENS); } else if (it.value() == "100 GS Reward") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_KAK_TOKENS); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_KAK_TOKENS); } else if (it.value() == "Triforce Hunt") { - mOptions[index].SetSelectedIndex(RO_GANON_BOSS_KEY_TRIFORCE_HUNT); + mOptions[index].SetContextIndex(RO_GANON_BOSS_KEY_TRIFORCE_HUNT); } break; case RSK_MQ_DUNGEON_RANDOM: if (it.value() == "None") { - mOptions[index].SetSelectedIndex(RO_MQ_DUNGEONS_NONE); + mOptions[index].SetContextIndex(RO_MQ_DUNGEONS_NONE); } else if (it.value() == "Random Number") { - mOptions[index].SetSelectedIndex(RO_MQ_DUNGEONS_RANDOM_NUMBER); + mOptions[index].SetContextIndex(RO_MQ_DUNGEONS_RANDOM_NUMBER); } else if (it.value() == "Set Number") { - mOptions[index].SetSelectedIndex(RO_MQ_DUNGEONS_SET_NUMBER); + mOptions[index].SetContextIndex(RO_MQ_DUNGEONS_SET_NUMBER); } else if (it.value() == "Selection Only") { - mOptions[index].SetSelectedIndex(RO_MQ_DUNGEONS_SELECTION); + mOptions[index].SetContextIndex(RO_MQ_DUNGEONS_SELECTION); } break; case RSK_STARTING_CONSUMABLES: case RSK_FULL_WALLETS: if (it.value() == "No") { - mOptions[index].SetSelectedIndex(RO_GENERIC_NO); + mOptions[index].SetContextIndex(RO_GENERIC_NO); } else if (it.value() == "Yes") { - mOptions[index].SetSelectedIndex(RO_GENERIC_YES); + mOptions[index].SetContextIndex(RO_GENERIC_YES); } break; case RSK_SKIP_CHILD_ZELDA: case RSK_SKIP_CHILD_STEALTH: case RSK_SKIP_EPONA_RACE: if (it.value() == "Don't Skip") { - mOptions[index].SetSelectedIndex(RO_GENERIC_DONT_SKIP); + mOptions[index].SetContextIndex(RO_GENERIC_DONT_SKIP); } else if (it.value() == "Skip") { - mOptions[index].SetSelectedIndex(RO_GENERIC_SKIP); + mOptions[index].SetContextIndex(RO_GENERIC_SKIP); } break; case RSK_SHUFFLE_DUNGEON_REWARDS: if (it.value() == "End of dungeons") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_REWARDS_END_OF_DUNGEON); + mOptions[index].SetContextIndex(RO_DUNGEON_REWARDS_END_OF_DUNGEON); } else if (it.value() == "Any dungeon") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_REWARDS_ANY_DUNGEON); + mOptions[index].SetContextIndex(RO_DUNGEON_REWARDS_ANY_DUNGEON); } else if (it.value() == "Overworld") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_REWARDS_OVERWORLD); + mOptions[index].SetContextIndex(RO_DUNGEON_REWARDS_OVERWORLD); } else if (it.value() == "Anywhere") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_REWARDS_ANYWHERE); + mOptions[index].SetContextIndex(RO_DUNGEON_REWARDS_ANYWHERE); } break; case RSK_SHUFFLE_SONGS: if (it.value() == "Song locations") { - mOptions[index].SetSelectedIndex(RO_SONG_SHUFFLE_SONG_LOCATIONS); + mOptions[index].SetContextIndex(RO_SONG_SHUFFLE_SONG_LOCATIONS); } else if (it.value() == "Dungeon rewards") { - mOptions[index].SetSelectedIndex(RO_SONG_SHUFFLE_DUNGEON_REWARDS); + mOptions[index].SetContextIndex(RO_SONG_SHUFFLE_DUNGEON_REWARDS); } else if (it.value() == "Anywhere") { - mOptions[index].SetSelectedIndex(RO_SONG_SHUFFLE_ANYWHERE); + mOptions[index].SetContextIndex(RO_SONG_SHUFFLE_ANYWHERE); } break; case RSK_SHUFFLE_TOKENS: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_TOKENSANITY_OFF); + mOptions[index].SetContextIndex(RO_TOKENSANITY_OFF); } else if (it.value() == "Dungeons") { - mOptions[index].SetSelectedIndex(RO_TOKENSANITY_DUNGEONS); + mOptions[index].SetContextIndex(RO_TOKENSANITY_DUNGEONS); } else if (it.value() == "Overworld") { - mOptions[index].SetSelectedIndex(RO_TOKENSANITY_OVERWORLD); + mOptions[index].SetContextIndex(RO_TOKENSANITY_OVERWORLD); } else if (it.value() == "All Tokens") { - mOptions[index].SetSelectedIndex(RO_TOKENSANITY_ALL); + mOptions[index].SetContextIndex(RO_TOKENSANITY_ALL); } break; case RSK_LINKS_POCKET: if (it.value() == "Dungeon Reward") { - mOptions[index].SetSelectedIndex(RO_LINKS_POCKET_DUNGEON_REWARD); + mOptions[index].SetContextIndex(RO_LINKS_POCKET_DUNGEON_REWARD); } else if (it.value() == "Advancement") { - mOptions[index].SetSelectedIndex(RO_LINKS_POCKET_ADVANCEMENT); + mOptions[index].SetContextIndex(RO_LINKS_POCKET_ADVANCEMENT); } else if (it.value() == "Anything") { - mOptions[index].SetSelectedIndex(RO_LINKS_POCKET_ANYTHING); + mOptions[index].SetContextIndex(RO_LINKS_POCKET_ANYTHING); } else if (it.value() == "Nothing") { - mOptions[index].SetSelectedIndex(RO_LINKS_POCKET_NOTHING); + mOptions[index].SetContextIndex(RO_LINKS_POCKET_NOTHING); } break; case RSK_MQ_DUNGEON_COUNT: numericValueString = it.value(); - mOptions[index].SetSelectedIndex(std::stoi(numericValueString)); + mOptions[index].SetContextIndex(std::stoi(numericValueString)); break; case RSK_SHUFFLE_DUNGEON_ENTRANCES: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); + mOptions[index].SetContextIndex(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF); } else if (it.value() == "On") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ENTRANCE_SHUFFLE_ON); + mOptions[index].SetContextIndex(RO_DUNGEON_ENTRANCE_SHUFFLE_ON); } else if (it.value() == "On + Ganon") { - mOptions[index].SetSelectedIndex(RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON); + mOptions[index].SetContextIndex(RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON); } break; case RSK_SHUFFLE_BOSS_ENTRANCES: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); + mOptions[index].SetContextIndex(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF); } else if (it.value() == "Age Restricted") { - mOptions[index].SetSelectedIndex(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_AGE_RESTRICTED); + mOptions[index].SetContextIndex(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_AGE_RESTRICTED); } else if (it.value() == "Full") { - mOptions[index].SetSelectedIndex(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL); + mOptions[index].SetContextIndex(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL); } break; case RSK_SHUFFLE_INTERIOR_ENTRANCES: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); + mOptions[index].SetContextIndex(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF); } else if (it.value() == "Simple") { - mOptions[index].SetSelectedIndex(RO_INTERIOR_ENTRANCE_SHUFFLE_SIMPLE); + mOptions[index].SetContextIndex(RO_INTERIOR_ENTRANCE_SHUFFLE_SIMPLE); } else if (it.value() == "All") { - mOptions[index].SetSelectedIndex(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL); + mOptions[index].SetContextIndex(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL); } break; case RSK_SHUFFLE_CHEST_MINIGAME: if (it.value() == "Off") { - mOptions[index].SetSelectedIndex(RO_CHEST_GAME_OFF); + mOptions[index].SetContextIndex(RO_CHEST_GAME_OFF); } else if (it.value() == "On (Separate)") { - mOptions[index].SetSelectedIndex(RO_CHEST_GAME_SINGLE_KEYS); + mOptions[index].SetContextIndex(RO_CHEST_GAME_SINGLE_KEYS); } else if (it.value() == "On (Pack)") { - mOptions[index].SetSelectedIndex(RO_CHEST_GAME_PACK); + mOptions[index].SetContextIndex(RO_CHEST_GAME_PACK); } break; case RSK_MQ_DEKU_TREE: @@ -3166,11 +3169,11 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_MQ_GTG: case RSK_MQ_GANONS_CASTLE: if (it.value() == "Vanilla") { - mOptions[index].SetSelectedIndex(RO_MQ_SET_VANILLA); + mOptions[index].SetContextIndex(RO_MQ_SET_VANILLA); } else if (it.value() == "Master Quest") { - mOptions[index].SetSelectedIndex(RO_MQ_SET_MQ); + mOptions[index].SetContextIndex(RO_MQ_SET_MQ); } else if (it.value() == "Random") { - mOptions[index].SetSelectedIndex(RO_MQ_SET_RANDOM); + mOptions[index].SetContextIndex(RO_MQ_SET_RANDOM); } break; default: @@ -3186,13 +3189,13 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { ctx->AddExcludedOptions(); for (auto it = jsonExcludedLocations.begin(); it != jsonExcludedLocations.end(); ++it) { const RandomizerCheck rc = Rando::StaticData::locationNameToEnum[it.value()]; - ctx->GetItemLocation(rc)->GetExcludedOption()->SetSelectedIndex(RO_GENERIC_ON); + ctx->GetItemLocation(rc)->GetExcludedOption()->SetContextIndex(RO_GENERIC_ON); } nlohmann::json enabledTricksJson = spoilerFileJson["enabledTricks"]; for (auto it = enabledTricksJson.begin(); it != enabledTricksJson.end(); ++it) { const RandomizerTrick rt = mTrickNameToEnum[it.value()]; - GetTrickOption(rt).SetSelectedIndex(RO_GENERIC_ON); + GetTrickOption(rt).SetContextIndex(RO_GENERIC_ON); } } diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 03fc4593c..b7b4c9de6 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -38,7 +38,7 @@ extern int32_t D_8011D3AC; extern void func_80AF36EC(EnRu2* enRu2, PlayState* play); } -#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex() +#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex() void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 8fd817740..bcb328132 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1920,7 +1920,7 @@ extern "C" u32 SpoilerFileExists(const char* spoilerFileName) { } extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey) { - return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).GetSelectedOptionIndex(); + return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).GetContextOptionIndex(); } extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) { diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 1d2ce5a6f..1edec3025 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -180,7 +180,7 @@ void SaveManager::LoadRandomizerVersion1() { int key, value; SaveManager::Instance->LoadData("sk" + std::to_string(i), key); SaveManager::Instance->LoadData("sv" + std::to_string(i), value); - randoContext->GetOption(RandomizerSettingKey(key)).SetSelectedIndex(value); + randoContext->GetOption(RandomizerSettingKey(key)).SetContextIndex(value); } for (int i = 0; i < 50; i++) { @@ -286,7 +286,7 @@ void SaveManager::LoadRandomizerVersion2() { SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) { int value = 0; SaveManager::Instance->LoadData("", value); - randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(value); + randoContext->GetOption(RandomizerSettingKey(i)).SetContextIndex(value); }); SaveManager::Instance->LoadArray("hintLocations", RH_ZR_OPEN_GROTTO_GOSSIP_STONE + 1, [&](size_t i) { @@ -435,7 +435,7 @@ void SaveManager::LoadRandomizerVersion3() { SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) { int value = 0; SaveManager::Instance->LoadData("", value); - randoContext->GetOption(RandomizerSettingKey(i)).SetSelectedIndex(value); + randoContext->GetOption(RandomizerSettingKey(i)).SetContextIndex(value); }); SaveManager::Instance->LoadArray("hintLocations", RH_MAX, [&](size_t i) { @@ -464,7 +464,7 @@ void SaveManager::LoadRandomizerVersion3() { }); randoContext->GetTrials()->SkipAll(); - SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).GetSelectedOptionIndex()+1, [&](size_t i) { + SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() + 1, [&](size_t i) { size_t trialId; SaveManager::Instance->LoadData("", trialId); randoContext->GetTrial(trialId)->SetAsRequired(); @@ -513,7 +513,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f SaveManager::Instance->SaveData("finalSeed", randoContext->GetSettings()->GetSeed()); SaveManager::Instance->SaveArray("randoSettings", RSK_MAX, [&](size_t i) { - SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).GetSelectedOptionIndex()); + SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).GetContextOptionIndex()); }); SaveManager::Instance->SaveArray("hintLocations", RH_MAX, [&](size_t i) { From 573d846cd7db57db9e02621660a72e17067d864b Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Fri, 29 Nov 2024 20:35:38 -0700 Subject: [PATCH 11/28] Add saved status setting to StartingItemGive (#4600) --- soh/soh/Enhancements/randomizer/savefile.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index dd6c27257..02a31e7b5 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -13,7 +13,10 @@ uint8_t Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); } -void StartingItemGive(GetItemEntry getItemEntry) { +void StartingItemGive(GetItemEntry getItemEntry, RandomizerCheck randomizerCheck) { + if (randomizerCheck != RC_MAX) { + OTRGlobals::Instance->gRandoContext->GetItemLocation(randomizerCheck)->SetCheckStatus(RCSHOW_SAVED); + } if (getItemEntry.modIndex == MOD_NONE) { if (getItemEntry.getItemId == GI_SWORD_BGS) { gSaveContext.bgsFlag = true; @@ -96,8 +99,7 @@ void GiveLinkDekuNuts(int howManyNuts) { void GiveLinksPocketItem() { if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE); - StartingItemGive(getItemEntry); - Rando::Context::GetInstance()->GetItemLocation(RC_LINKS_POCKET)->SetCheckStatus(RCSHOW_SAVED); + StartingItemGive(getItemEntry, RC_LINKS_POCKET); // If we re-add the above, we'll get the item on save creation, now it's given on first load Flags_SetRandomizerInf(RAND_INF_LINKS_POCKET); } @@ -381,7 +383,7 @@ extern "C" void Randomizer_InitSaveFile() { if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, (GetItemID)RG_ZELDAS_LULLABY); - StartingItemGive(getItemEntry); + StartingItemGive(getItemEntry, RC_SONG_FROM_IMPA); // malon/talon back at ranch Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG); @@ -403,7 +405,7 @@ extern "C" void Randomizer_InitSaveFile() { if (Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && startingAge == RO_AGE_ADULT) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_MASTER_SWORD, GI_NONE); - StartingItemGive(getItemEntry); + StartingItemGive(getItemEntry, RC_TOT_MASTER_SWORD); Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD); } From ee628059d836c77ad105a5a4c825d51ee59bf5af Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Sun, 1 Dec 2024 01:59:13 +0000 Subject: [PATCH 12/28] Fix Lab Man actor breaking and the invisible UI glitch (#4599) * fix Lab Man actor breaking and the invisible UI glitch * address review --- soh/soh/Enhancements/randomizer/hook_handlers.cpp | 15 +++++++++++++-- soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c | 5 ++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index f59cae9fe..5dce7406f 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -51,6 +51,7 @@ extern "C" { #include "src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.h" #include "src/overlays/actors/ovl_En_Xc/z_en_xc.h" #include "src/overlays/actors/ovl_Fishing/z_fishing.h" +#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h" #include "adult_trade_shuffle.h" #include "draw.h" @@ -60,6 +61,7 @@ extern void func_8084DFAC(PlayState* play, Player* player); extern void Player_SetupActionPreserveAnimMovement(PlayState* play, Player* player, PlayerActionFunc actionFunc, s32 flags); extern s32 Player_SetupWaitForPutAway(PlayState* play, Player* player, AfterPutAwayFunc func); extern void Play_InitEnvironment(PlayState * play, s16 skyboxId); +extern void EnMk_Wait(EnMk* enMk, PlayState* play); } #define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex() @@ -860,7 +862,8 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l // This is typically called when you close the text box after getting an item, in case a previous // function hid the interface. - Interface_ChangeAlpha(gSaveContext.unk_13EE); + gSaveContext.unk_13EA = 0; + Interface_ChangeAlpha(0x32); // EnItem00_SetupAction(item00, func_8001E5C8); // *should = false; } else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) { @@ -1399,9 +1402,17 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l } break; } + case VB_TRADE_TIMER_EYEDROPS:{ + EnMk* enMk = va_arg(args, EnMk*); + Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); + enMk->actor.flags &= ~ACTOR_FLAG_WILL_TALK; + enMk->actionFunc = EnMk_Wait; + enMk->flags |= 1; + *should = false; + break; + } case VB_FREEZE_ON_SKULL_TOKEN: case VB_TRADE_TIMER_ODD_MUSHROOM: - case VB_TRADE_TIMER_EYEDROPS: case VB_TRADE_TIMER_FROG: case VB_ANJU_SET_OBTAINED_TRADE_ITEM: case VB_GIVE_ITEM_FROM_TARGET_IN_WOODS: diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index f5549f86e..4e020f7ec 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -98,9 +98,8 @@ void func_80AACA40(EnMk* this, PlayState* play) { void func_80AACA94(EnMk* this, PlayState* play) { if (Actor_HasParent(&this->actor, play) != 0 || !GameInteractor_Should(VB_TRADE_FROG, true, this)) { this->actor.parent = NULL; - this->actionFunc = func_80AACA40; - Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG); - if (GameInteractor_Should(VB_TRADE_TIMER_EYEDROPS, true)) { + if (GameInteractor_Should(VB_TRADE_TIMER_EYEDROPS, true, this)) { + this->actionFunc = func_80AACA40; func_80088AA0(240); gSaveContext.eventInf[1] &= ~1; } From 9b74a09955d745f97ac7ee2b33971596cd18cfdd Mon Sep 17 00:00:00 2001 From: Jordan Longstaff <JordanLongstaff@users.noreply.github.com> Date: Sat, 30 Nov 2024 20:59:38 -0500 Subject: [PATCH 13/28] Zora's River waterfall always open, take two (#4459) * Zora's River waterfall always open, take two * Remove improper, redundant checks in hook * Move all checks into update hook * Add Randomizer setting for keeping Sleeping Waterfall open * Change header exports to extern exports * Remove "closed as child" option for rando setting * Oops, missed a spot * A bit more cleanup: simplify a redundant condition * Unify hook handlers * Oopsie, fix build error * Add "play only once" option * Force Sleeping Waterfall enhancement in rando mode * Force enhancement only if waterfall is Open in rando * Restore forced-open waterfall in rando * Fix rando condition in hook * Fix? rando entrance logic for OI * Fix build errors --- soh/soh/Enhancements/presets.h | 9 ++- .../location_access/locacc_zoras_domain.cpp | 7 +- .../randomizer/option_descriptions.cpp | 6 ++ .../Enhancements/randomizer/randomizerTypes.h | 7 ++ soh/soh/Enhancements/randomizer/settings.cpp | 11 +++ .../Enhancements/timesaver_hook_handlers.cpp | 67 +++++++++++++++++++ soh/soh/SohMenuBar.cpp | 23 ++++++- 7 files changed, 124 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 96b39ba30..63fd6efc6 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -304,6 +304,7 @@ const std::vector<const char*> enhancementsCvars = { CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), CVAR_ENHANCEMENT("TimeSavers.SkipForcedDialog"), + CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), CVAR_ENHANCEMENT("SlowTextSpeed"), }; @@ -549,6 +550,7 @@ const std::vector<const char*> randomizerCvars = { CVAR_RANDOMIZER_SETTING("SkipChildZelda"), CVAR_RANDOMIZER_SETTING("SkipEponaRace"), CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), + CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), CVAR_RANDOMIZER_SETTING("StartingAge"), CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), CVAR_RANDOMIZER_SETTING("StartingConsumables"), @@ -1175,12 +1177,13 @@ const std::vector<PresetEntry> s6PresetEntries = { PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), RO_WATERFALL_CLOSED), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_RANDOM), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingConsumables"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingDekuShield"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_STARTWITH), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingOcarina"), 1), - PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), RO_ZF_CLOSED), }; const std::vector<PresetEntry> hellModePresetEntries = { @@ -1235,16 +1238,18 @@ const std::vector<PresetEntry> hellModePresetEntries = { PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipTowerEscape"), 1), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), RO_WATERFALL_OPEN), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingAge"), RO_AGE_RANDOM), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_ANYWHERE), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SunlightArrows"), 1), - PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), 2), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), RO_ZF_OPEN), }; const std::vector<PresetEntry> BenchmarkPresetEntries = { PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Forest"), RO_FOREST_CLOSED_DEKU), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("KakarikoGate"), RO_KAK_GATE_OPEN), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_SONGONLY), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), RO_WATERFALL_CLOSED), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ZorasFountain"), RO_ZF_CLOSED), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("GerudoFortress"), RO_GF_NORMAL), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_DUNGEON_REWARDS), diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp index 6ad5ec758..b0be901d9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp @@ -43,7 +43,12 @@ void RegionTable_Init_ZorasDomain() { Entrance(RR_ZR_FAIRY_GROTTO, {[]{return Here(RR_ZORAS_RIVER, []{return logic->BlastOrSmash();});}}), Entrance(RR_THE_LOST_WOODS, {[]{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS);}}), Entrance(RR_ZR_STORMS_GROTTO, {[]{return logic->CanOpenStormsGrotto();}}), - Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return logic->CanUse(RG_ZELDAS_LULLABY) || (logic->IsChild && ctx->GetTrickOption(RT_ZR_CUCCO)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_ZR_HOVERS));}}), + Entrance(RR_ZR_BEHIND_WATERFALL, {[]{ + return ctx->GetOption(RSK_SLEEPING_WATERFALL).Is(RO_WATERFALL_OPEN) || + Here(RR_ZORAS_RIVER, []{return logic->CanUse(RG_ZELDAS_LULLABY);}) || + (logic->IsChild && ctx->GetTrickOption(RT_ZR_CUCCO)) || + (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && ctx->GetTrickOption(RT_ZR_HOVERS)); + }}), }); areaTable[RR_ZR_BEHIND_WATERFALL] = Region("ZR Behind Waterfall", "Zora River", {RA_ZORAS_RIVER}, DAY_NIGHT_CYCLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 7de98b3d0..d119c5e80 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -33,6 +33,12 @@ void Settings::CreateOptionDescriptions() { "\n" "Open - King Zora has already mweeped out of the way in both " "time periods. Ruto's Letter is removed from the item pool."; + mOptionDescriptions[RSK_SLEEPING_WATERFALL] = "Closed - Sleeping Waterfall obstructs the entrance to Zora's " + "Domain. Zelda's Lullaby must be played in order to open it " + "(but only once; then it stays open in both time periods).\n" + "\n" + "Open - Sleeping Waterfall is always open. " + "Link may always enter Zora's Domain."; mOptionDescriptions[RSK_STARTING_AGE] = "Choose which age Link will start as.\n\n" "Starting as adult means you start with the Master Sword in your inventory.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index fe8910c6d..252fc0b28 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -3947,6 +3947,7 @@ typedef enum { RSK_KAK_GATE, RSK_DOOR_OF_TIME, RSK_ZORAS_FOUNTAIN, + RSK_SLEEPING_WATERFALL, RSK_STARTING_AGE, RSK_GERUDO_FORTRESS, RSK_RAINBOW_BRIDGE, @@ -4184,6 +4185,12 @@ typedef enum { RO_ZF_OPEN, } RandoOptionZorasFountain; +//Sleeping Waterfall settings (closed, open) +typedef enum { + RO_WATERFALL_CLOSED, + RO_WATERFALL_OPEN, +} RandoOptionSleepingWaterfall; + //Starting Age settings (child, adult, random) typedef enum { RO_AGE_CHILD, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index df3d31c76..f1fa221da 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -109,6 +109,7 @@ void Settings::CreateOptions() { mOptions[RSK_KAK_GATE] = Option::U8("Kakariko Gate", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("KakarikoGate"), mOptionDescriptions[RSK_KAK_GATE]); mOptions[RSK_DOOR_OF_TIME] = Option::U8("Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox); mOptions[RSK_ZORAS_FOUNTAIN] = Option::U8("Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]); + mOptions[RSK_SLEEPING_WATERFALL] = Option::U8("Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]); mOptions[RSK_GERUDO_FORTRESS] = Option::U8("Gerudo Fortress", {"Normal", "Fast", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoFortress"), mOptionDescriptions[RSK_GERUDO_FORTRESS]); mOptions[RSK_RAINBOW_BRIDGE] = Option::U8("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE); mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT] = Option::U8("Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true); @@ -696,6 +697,7 @@ void Settings::CreateOptions() { &mOptions[RSK_KAK_GATE], &mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_ZORAS_FOUNTAIN], + &mOptions[RSK_SLEEPING_WATERFALL], }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_WORLD_IMGUI] = OptionGroup::SubGroup("World Settings", { &mOptions[RSK_STARTING_AGE], @@ -945,6 +947,7 @@ void Settings::CreateOptions() { &mOptions[RSK_KAK_GATE], &mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_ZORAS_FOUNTAIN], + &mOptions[RSK_SLEEPING_WATERFALL], &mOptions[RSK_GERUDO_FORTRESS], &mOptions[RSK_RAINBOW_BRIDGE], &mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT], @@ -1262,6 +1265,7 @@ void Settings::CreateOptions() { { "Open Settings:Kakariko Gate", RSK_KAK_GATE }, { "Open Settings:Door of Time", RSK_DOOR_OF_TIME }, { "Open Settings:Zora's Fountain", RSK_ZORAS_FOUNTAIN }, + { "Open Settings:Sleeping Waterfall", RSK_SLEEPING_WATERFALL }, { "World Settings:Starting Age", RSK_STARTING_AGE }, { "Open Settings:Gerudo Fortress", RSK_GERUDO_FORTRESS }, { "Open Settings:Rainbow Bridge", RSK_RAINBOW_BRIDGE }, @@ -2625,6 +2629,13 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { mOptions[index].SetContextIndex(RO_ZF_OPEN); } break; + case RSK_SLEEPING_WATERFALL: + if (it.value() == "Closed") { + mOptions[index].SetContextIndex(RO_WATERFALL_CLOSED); + } else if (it.value() == "Open") { + mOptions[index].SetContextIndex(RO_WATERFALL_OPEN); + } + break; case RSK_STARTING_AGE: if (it.value() == "Child") { mOptions[index].SetContextIndex(RO_AGE_CHILD); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index b7b4c9de6..c271b6cb3 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -35,6 +35,9 @@ extern SaveContext gSaveContext; extern PlayState* gPlayState; extern int32_t D_8011D3AC; +extern void func_808ADEF0(BgSpot03Taki* bgSpot03Taki, PlayState* play); +extern void BgSpot03Taki_ApplyOpeningAlpha(BgSpot03Taki* bgSpot03Taki, s32 bufferIndex); + extern void func_80AF36EC(EnRu2* enRu2, PlayState* play); } @@ -96,6 +99,9 @@ void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) { } } +void BgSpot03Taki_KeepOpen(BgSpot03Taki* bgSpot03Taki, PlayState* play) { +} + static int successChimeCooldown = 0; void RateLimitedSuccessChime() { if (successChimeCooldown == 0) { @@ -692,6 +698,8 @@ static uint32_t enFuUpdateHook = 0; static uint32_t enFuKillHook = 0; static uint32_t bgSpot02UpdateHook = 0; static uint32_t bgSpot02KillHook = 0; +static uint32_t bgSpot03UpdateHook = 0; +static uint32_t bgSpot03KillHook = 0; static uint32_t enPoSistersUpdateHook = 0; static uint32_t enPoSistersKillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { @@ -747,6 +755,10 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } + if (actor->id == ACTOR_EN_OWL && gPlayState->sceneNum == SCENE_ZORAS_RIVER && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 0) == 2) { + Actor_Kill(actor); + } + if (actor->id == ACTOR_BG_SPOT02_OBJECTS && actor->params == 2) { bgSpot02UpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable { Actor* innerActor = static_cast<Actor*>(innerActorRef); @@ -769,6 +781,61 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } + if (actor->id == ACTOR_BG_SPOT03_TAKI) { + bgSpot03UpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable { + Actor* innerActor = static_cast<Actor*>(innerActorRef); + + if (innerActor->id != ACTOR_BG_SPOT03_TAKI) { + return; + } + + bool shouldKeepOpen; + switch (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 0)) { + case 1: + shouldKeepOpen = Flags_GetEventChkInf(EVENTCHKINF_OPENED_ZORAS_DOMAIN); + break; + case 2: + if (IS_RANDO && RAND_GET_OPTION(RSK_SLEEPING_WATERFALL) == RO_WATERFALL_OPEN) { + shouldKeepOpen = true; + } else { + shouldKeepOpen = CHECK_QUEST_ITEM(QUEST_SONG_LULLABY) && + (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME || + INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_FAIRY); + } + break; + default: + shouldKeepOpen = false; + break; + } + + if (!shouldKeepOpen) { + return; + } + + BgSpot03Taki* bgSpot03 = static_cast<BgSpot03Taki*>(innerActorRef); + if (bgSpot03->actionFunc == func_808ADEF0) { + bgSpot03->actionFunc = BgSpot03Taki_KeepOpen; + bgSpot03->state = WATERFALL_OPENED; + bgSpot03->openingAlpha = 0.0f; + Flags_SetSwitch(gPlayState, bgSpot03->switchFlag); + func_8003EBF8(gPlayState, &gPlayState->colCtx.dyna, bgSpot03->dyna.bgId); + BgSpot03Taki_ApplyOpeningAlpha(bgSpot03, 0); + BgSpot03Taki_ApplyOpeningAlpha(bgSpot03, 1); + + GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(bgSpot03UpdateHook); + GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(bgSpot03KillHook); + bgSpot03UpdateHook = 0; + bgSpot03KillHook = 0; + } + }); + bgSpot03KillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(bgSpot03UpdateHook); + GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(bgSpot03KillHook); + bgSpot03UpdateHook = 0; + bgSpot03KillHook = 0; + }); + } + if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { EnDntDemo* enDntDemo = static_cast<EnDntDemo*>(actorRef); enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index a133a8ef9..2435af1f8 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -83,6 +83,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" }; static const char* skipGetItemAnimationOptions[3] = { "Disabled", "Junk Items", "All Items" }; static const char* skipForcedDialogOptions[4] = { "None", "Navi Only", "NPCs Only", "All" }; + static const char* sleepingWaterfallOptions[3] = { "Always", "Once", "Never" }; static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" }; static const char* mirroredWorldModes[9] = { "Disabled", "Always", "Random", "Random (Seeded)", "Dungeons", @@ -123,7 +124,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), }; - static const char* itemCountMessageOptions[sizeof(itemCountMessageCVars) / sizeof(const char*)] = { + static const char* itemCountMessageOptions[ARRAY_COUNT(itemCountMessageCVars)] = { "Gold Skulltula Tokens", "Pieces of Heart", "Heart Containers", @@ -796,7 +797,23 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", CVAR_ENHANCEMENT("InstantScarecrow"), true, false, forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); - + bool forceSleepingWaterfallEnhancement = + IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SLEEPING_WATERFALL) == RO_WATERFALL_OPEN; + uint8_t forceSleepingWaterfallValue = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SLEEPING_WATERFALL) + 1; + static const char* forceSleepingWaterfallText = + "This setting is forcefully enabled because a randomizer savefile with \"Sleeping Waterfall: Open\" is loaded."; + UIWidgets::PaddedText("Play Zelda's Lullaby to open Sleeping Waterfall", true, false); + UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), + sleepingWaterfallOptions, 0, forceSleepingWaterfallEnhancement, + forceSleepingWaterfallText, forceSleepingWaterfallValue); + UIWidgets::Tooltip( + "Always: Link must always play Zelda's Lullaby to open " + "the waterfall entrance to Zora's Domain.\n" + "Once: Link only needs to play Zelda's Lullaby once to " + "open the waterfall; after that, it stays open permanently.\n" + "Never: Link never needs to play Zelda's Lullaby to open the " + "waterfall; he only needs to have learned it and have an ocarina." + ); ImGui::EndTable(); ImGui::EndMenu(); @@ -867,7 +884,7 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); if (ImGui::BeginMenu("Item Count Messages")) { - int numOptions = sizeof(itemCountMessageCVars) / sizeof(const char*); + int numOptions = ARRAY_COUNT(itemCountMessageCVars); bool allItemCountsChecked = std::all_of(itemCountMessageCVars, itemCountMessageCVars + numOptions, [](const char* cvar) { return CVarGetInteger(cvar, 0); }); bool someItemCountsChecked = std::any_of(itemCountMessageCVars, itemCountMessageCVars + numOptions, From 19d1fd5545cc71a05311c7f295c7b67211cb323e Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Mon, 2 Dec 2024 11:03:47 -0500 Subject: [PATCH 14/28] Boomerang Reticle and First-Person Aiming (#3374) * First-person, reticle, sway, menu, and presets * Put sway back behind reticle, adjust aim height for age * block vanilla + comments * new documentation method * second try formatting * Correct boomerang distance * Update for CVAR changes * Fix alignment? * Condition cleanup * Change reticle range to match bow behavior * remove magic values --- soh/soh/Enhancements/presets.h | 2 ++ soh/soh/SohMenuBar.cpp | 11 +++++++ soh/src/code/z_player_lib.c | 30 +++++++++++++++++++ .../actors/ovl_player_actor/z_player.c | 30 ++++++++++++++++--- 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 63fd6efc6..9b4482f23 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -242,6 +242,8 @@ const std::vector<const char*> enhancementsCvars = { CVAR_ENHANCEMENT("AuthenticLogo"), CVAR_ENHANCEMENT("PauseLiveLinkRotationSpeed"), CVAR_ENHANCEMENT("BowReticle"), + CVAR_ENHANCEMENT("BoomerangFirstPerson"), + CVAR_ENHANCEMENT("BoomerangReticle"), CVAR_ENHANCEMENT("FixTexturesOOB"), CVAR_ENHANCEMENT("IvanCoopModeEnabled"), CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"), diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 2435af1f8..cd9948092 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -872,6 +872,17 @@ void DrawEnhancementsMenu() { "Toggling while inside the shop will not change prices or restock any SOLD OUTs"); UIWidgets::PaddedEnhancementCheckbox("Aiming reticle for the bow/slingshot", CVAR_ENHANCEMENT("BowReticle"), true, false); UIWidgets::Tooltip("Aiming with a bow or slingshot will display a reticle as with the hookshot when the projectile is ready to fire."); + if (UIWidgets::PaddedEnhancementCheckbox("Aim boomerang in first-person mode", CVAR_ENHANCEMENT("BoomerangFirstPerson"), true, false)) { + if (!CVarGetInteger(CVAR_ENHANCEMENT("BoomerangFirstPerson"), 0)) { + CVarSetInteger(CVAR_ENHANCEMENT("BoomerangReticle"), 0); + } + } + UIWidgets::Tooltip( + "Change aiming for the boomerang from third person to first person to see past Link's head"); + if (CVarGetInteger(CVAR_ENHANCEMENT("BoomerangFirstPerson"), 0)) { + UIWidgets::PaddedEnhancementCheckbox("Aiming reticle for boomerang", CVAR_ENHANCEMENT("BoomerangReticle"), true, false); + UIWidgets::Tooltip("Aiming with the boomerang will display a reticle as with the hookshot"); + } if (UIWidgets::PaddedEnhancementCheckbox("Allow strength equipment to be toggled", CVAR_ENHANCEMENT("ToggleStrength"), true, false)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("ToggleStrength"), 0)) { CVarSetInteger(CVAR_ENHANCEMENT("StrengthDisabled"), 0); diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index a50a49e2d..3207abaf6 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -887,6 +887,16 @@ s32 Player_HoldsSlingshot(Player* this) { return this->heldItemAction == PLAYER_IA_SLINGSHOT; } +// #region SOH [Enhancement] +s32 Player_HoldsBoomerang(Player* this) { + return this->heldItemAction == PLAYER_IA_BOOMERANG; +} + +s32 Player_AimsBoomerang(Player* this) { + return Player_HoldsBoomerang(this) && (this->unk_834 != 0); +} +// #endregion + s32 func_8008F128(Player* this) { return Player_HoldsHookshot(this) && (this->heldActor == NULL); } @@ -1789,6 +1799,9 @@ Vec3f sLeftRightFootLimbModelFootPos[] = { void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { Player* this = (Player*)thisx; + const Vec3s BoomerangViewAdult = { -31200, -9200, 17000 }; + const Vec3s BoomerangViewChild = { -31200, -8700, 17000 }; + if (*dList != NULL) { Matrix_MultVec3f(&sZeroVec, D_80160000); } @@ -1950,6 +1963,8 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve play, this, ((this->heldItemAction == PLAYER_IA_HOOKSHOT) ? 38600.0f : 77600.0f) * CVarGetFloat(CVAR_CHEAT("HookshotReachMultiplier"), 1.0f)); } } + + // #region SOH [Enhancement] } else if (CVarGetInteger(CVAR_ENHANCEMENT("BowReticle"), 0) && ( (this->heldItemAction == PLAYER_IA_BOW_FIRE) || (this->heldItemAction == PLAYER_IA_BOW_ICE) || @@ -1968,6 +1983,21 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve Player_DrawHookshotReticle(play, this, RETICLE_MAX); } } + } else if (CVarGetInteger(CVAR_ENHANCEMENT("BoomerangReticle"), 0) && (this->heldItemAction == PLAYER_IA_BOOMERANG)) { + if (Player_HoldsBoomerang(this)) { + if (LINK_IS_ADULT) { + Matrix_RotateZYX(BoomerangViewAdult.x, BoomerangViewAdult.y, BoomerangViewAdult.z, + MTXMODE_APPLY); + } else { + Matrix_RotateZYX(BoomerangViewChild.x, BoomerangViewChild.y, BoomerangViewChild.z, MTXMODE_APPLY); + } + + if (Player_AimsBoomerang(this)) { + Matrix_Translate(500.0f, 300.0f, 0.0f, MTXMODE_APPLY); + Player_DrawHookshotReticle(play, this, RETICLE_MAX); + } + } + // #endregion } if ((this->unk_862 != 0) || ((func_8002DD6C(this) == 0) && (heldActor != NULL))) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 135c66e89..16abaf568 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -3236,7 +3236,11 @@ s32 func_808358F0(Player* this, PlayState* play) { AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, this->skelAnime.jointTable); } else { - LinkAnimation_Update(play, &this->upperSkelAnime); + // #region SOH [Enhancement] + if (!CVarGetInteger(CVAR_ENHANCEMENT("BoomerangReticle"), 0)) { + // #endregion + LinkAnimation_Update(play, &this->upperSkelAnime); + } } func_80834EB8(this, play); @@ -5823,7 +5827,13 @@ s32 func_8083AD4C(PlayState* play, Player* this) { camMode = shouldUseBowCamera ? CAM_MODE_BOWARROW : CAM_MODE_SLINGSHOT; } else { - camMode = CAM_MODE_BOOMERANG; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("BoomerangFirstPerson"), 0)) { + camMode = CAM_MODE_FIRSTPERSON; + // #endregion + } else { + camMode = CAM_MODE_BOOMERANG; + } } } else { camMode = CAM_MODE_FIRSTPERSON; @@ -11486,7 +11496,13 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { camMode = CAM_MODE_TALK; } else if (this->stateFlags1 & PLAYER_STATE1_FRIENDLY_ACTOR_FOCUS) { if (this->stateFlags1 & PLAYER_STATE1_BOOMERANG_THROWN) { - camMode = CAM_MODE_FOLLOWBOOMERANG; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("BoomerangFirstPerson"), 0)) { + camMode = CAM_MODE_TARGET; + // #endregion + } else { + camMode = CAM_MODE_FOLLOWBOOMERANG; + } } else { camMode = CAM_MODE_FOLLOWTARGET; } @@ -11497,7 +11513,13 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { } else if (this->stateFlags1 & PLAYER_STATE1_CHARGING_SPIN_ATTACK) { camMode = CAM_MODE_CHARGE; } else if (this->stateFlags1 & PLAYER_STATE1_BOOMERANG_THROWN) { - camMode = CAM_MODE_FOLLOWBOOMERANG; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("BoomerangFirstPerson"), 0)) { + camMode = CAM_MODE_TARGET; + // #endregion + } else { + camMode = CAM_MODE_FOLLOWBOOMERANG; + } Camera_SetParam(Play_GetCamera(play, 0), 8, this->boomerangActor); } else if (this->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE)) { if (Player_FriendlyLockOnOrParallel(this)) { From caf0dc40c7d4e65537bb03a6952e9b6988b20a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= <serprex@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:04:21 +0000 Subject: [PATCH 15/28] update check tracker when actor tells what they reward (#4568) * update check tracker when actor tells you what they reward do not render price when 0 * feedback --- .../randomizer/3drando/hint_list.cpp | 2 +- .../Enhancements/randomizer/hook_handlers.cpp | 149 +++++++++++++++++- .../randomizer/randomizer_check_tracker.cpp | 5 +- soh/soh/OTRGlobals.cpp | 1 - 4 files changed, 152 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 14faa479b..3a336b12d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2893,7 +2893,7 @@ void StaticData::HintTable_Init() { {QM_RED, QM_GREEN, QM_GREEN})); hintTextTable[RHT_HBA_HINT_HAVE_1000] = HintText(CustomMessage("Hey, newcomer!&Want to take on the #Horseback Archery# challenge?^" - "Prove yourself to be a horsemaster by scoring 1500 points to win my #[[1]]#!\x0B", + "Prove yourself to be a horsemaster by scoring 1500 points to win my #[[1]]#!\x0B", {QM_RED, QM_GREEN})); hintTextTable[RHT_MALON_HINT_HOW_IS_EPONA] = HintText(CustomMessage("@! You should come back with Epona and try to beat my time on the #Obstacle Course#!^" diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 5dce7406f..53e4c1759 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -621,11 +621,11 @@ void func_8083A434_override(PlayState* play, Player* player) { bool ShouldGiveFishingPrize(f32 sFishOnHandLength){ // RANDOTODO: update the enhancement sliders to not allow // values above rando fish weight values when rando'd - if(LINK_IS_CHILD) { + if(LINK_IS_CHILD) { int32_t weight = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) ? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightChild"), 10) : 10; f32 score = sqrt(((f32)weight - 0.5f) / 0.0036f); return sFishOnHandLength >= score && (IS_RANDO ? !Flags_GetRandomizerInf(RAND_INF_CHILD_FISHING) : !(HIGH_SCORE(HS_FISHING) & HS_FISH_PRIZE_CHILD)); - } else + } else { int32_t weight = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFishing"), 0) ? CVarGetInteger(CVAR_ENHANCEMENT("MinimumFishWeightAdult"), 13) : 13; f32 score = sqrt(((f32)weight - 0.5f) / 0.0036f); @@ -633,6 +633,147 @@ bool ShouldGiveFishingPrize(f32 sFishOnHandLength){ } } +void RandomizerOnDialogMessageHandler() { + MessageContext *msgCtx = &gPlayState->msgCtx; + Actor *actor = msgCtx->talkActor; + auto ctx = Rando::Context::GetInstance(); + bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).GetSelectedOptionIndex() != RO_GENERIC_OFF; + bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || + ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); + + RandomizerCheck reveal = RC_UNKNOWN_CHECK; + if (ctx->GetOption(RSK_CHICKENS_HINT) && (msgCtx->textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && msgCtx->textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { + reveal = RC_KAK_ANJU_AS_CHILD; + } else { + switch (msgCtx->textId) { + case TEXT_SKULLTULA_PEOPLE_IM_CURSED: + if (actor->params == 1 && ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){ + reveal = RC_KAK_10_GOLD_SKULLTULA_REWARD; + } else if (actor->params == 2 && ctx->GetOption(RSK_KAK_20_SKULLS_HINT)){ + reveal = RC_KAK_20_GOLD_SKULLTULA_REWARD; + } else if (actor->params == 3 && ctx->GetOption(RSK_KAK_30_SKULLS_HINT)){ + reveal = RC_KAK_30_GOLD_SKULLTULA_REWARD; + } else if (actor->params == 4 && ctx->GetOption(RSK_KAK_40_SKULLS_HINT)){ + reveal = RC_KAK_40_GOLD_SKULLTULA_REWARD; + } else if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)){ + reveal = RC_KAK_50_GOLD_SKULLTULA_REWARD; + } + break; + case TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH: + if (ctx->GetOption(RSK_KAK_100_SKULLS_HINT)) { + reveal = RC_KAK_100_GOLD_SKULLTULA_REWARD; + } + break; + case TEXT_MASK_SHOP_SIGN: + if (ctx->GetOption(RSK_MASK_SHOP_HINT)) { + auto itemSkull_loc = ctx->GetItemLocation(RC_DEKU_THEATER_SKULL_MASK); + if (itemSkull_loc->GetCheckStatus() == RCSHOW_UNCHECKED) { + itemSkull_loc->SetCheckStatus(RCSHOW_IDENTIFIED); + } + reveal = RC_DEKU_THEATER_MASK_OF_TRUTH; + } + break; + case TEXT_GHOST_SHOP_EXPLAINATION: + case TEXT_GHOST_SHOP_CARD_HAS_POINTS: + if (ctx->GetOption(RSK_BIG_POES_HINT)) { + reveal = RC_MARKET_10_BIG_POES; + } + break; + case TEXT_MALON_EVERYONE_TURNING_EVIL: + case TEXT_MALON_I_SING_THIS_SONG: + case TEXT_MALON_HOW_IS_EPONA_DOING: + case TEXT_MALON_OBSTICLE_COURSE: + case TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED: + if (ctx->GetOption(RSK_MALON_HINT)) { + reveal = RC_KF_LINKS_HOUSE_COW; + } + break; + case TEXT_FROGS_UNDERWATER: + if (ctx->GetOption(RSK_FROGS_HINT)) { + reveal = RC_ZR_FROGS_OCARINA_GAME; + } + break; + case TEXT_GF_HBA_SIGN: + case TEXT_HBA_NOT_ON_HORSE: + case TEXT_HBA_INITIAL_EXPLAINATION: + case TEXT_HBA_ALREADY_HAVE_1000: + if (ctx->GetOption(RSK_HBA_HINT)) { + auto item1000_loc = ctx->GetItemLocation(RC_GF_HBA_1000_POINTS); + if (item1000_loc->GetCheckStatus() == RCSHOW_UNCHECKED) { + item1000_loc->SetCheckStatus(RCSHOW_IDENTIFIED); + } + reveal = RC_GF_HBA_1500_POINTS; + } + break; + case TEXT_SCRUB_RANDOM: + if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).GetSelectedOptionIndex() != RO_GENERIC_OFF) { + EnDns* enDns = (EnDns*)actor; + reveal = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf); + } + break; + case TEXT_BEAN_SALESMAN_BUY_FOR_10: + if (revealMerchant && (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || + ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL))) { + reveal = RC_ZR_MAGIC_BEAN_SALESMAN; + } + break; + case TEXT_GRANNYS_SHOP: + if (revealMerchant && nonBeanMerchants && + (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { + reveal = RC_KAK_GRANNYS_SHOP; + } + break; + case TEXT_MEDIGORON: + if (revealMerchant && nonBeanMerchants) { + reveal = RC_GC_MEDIGORON; + } + break; + case TEXT_CARPET_SALESMAN_1: + if (revealMerchant && nonBeanMerchants) { + reveal = RC_WASTELAND_BOMBCHU_SALESMAN; + } + break; + case TEXT_BIGGORON_BETTER_AT_SMITHING: + case TEXT_BIGGORON_WAITING_FOR_YOU: + case TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS: + case TEXT_BIGGORON_I_MAAAADE_THISSSS: + if (ctx->GetOption(RSK_BIGGORON_HINT)) { + reveal = RC_DMT_TRADE_CLAIM_CHECK; + } + break; + case TEXT_SHEIK_NEED_HOOK: + case TEXT_SHEIK_HAVE_HOOK: + if (ctx->GetOption(RSK_OOT_HINT) && gPlayState->sceneNum == SCENE_TEMPLE_OF_TIME && + !ctx->GetItemLocation(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()) { + auto itemoot_loc = ctx->GetItemLocation(RC_HF_OCARINA_OF_TIME_ITEM); + if (itemoot_loc->GetCheckStatus() == RCSHOW_UNCHECKED) { + itemoot_loc->SetCheckStatus(RCSHOW_IDENTIFIED); + } + reveal = RC_SONG_FROM_OCARINA_OF_TIME; + } + break; + case TEXT_FISHING_CLOUDY: + case TEXT_FISHING_TRY_ANOTHER_LURE: + case TEXT_FISHING_SECRETS: + case TEXT_FISHING_GOOD_FISHERMAN: + case TEXT_FISHING_DIFFERENT_POND: + case TEXT_FISHING_SCRATCHING: + case TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE: + if (ctx->GetOption(RSK_LOACH_HINT)) { + reveal = RC_LH_HYRULE_LOACH; + } + break; + } + } + + if (reveal != RC_UNKNOWN_CHECK) { + auto item_loc = ctx->GetItemLocation(reveal); + if (item_loc->GetCheckStatus() == RCSHOW_UNCHECKED) { + item_loc->SetCheckStatus(RCSHOW_IDENTIFIED); + } + } +} + void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_list originalArgs) { va_list args; va_copy(args, originalArgs); @@ -2118,6 +2259,7 @@ void RandomizerRegisterHooks() { static uint32_t onPlayerUpdateForRCQueueHook = 0; static uint32_t onPlayerUpdateForItemQueueHook = 0; static uint32_t onItemReceiveHook = 0; + static uint32_t onDialogMessageHook = 0; static uint32_t onVanillaBehaviorHook = 0; static uint32_t onSceneInitHook = 0; static uint32_t onActorInitHook = 0; @@ -2145,6 +2287,7 @@ void RandomizerRegisterHooks() { GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(onPlayerUpdateForRCQueueHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(onPlayerUpdateForItemQueueHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(onItemReceiveHook); + GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(onDialogMessageHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitHook); GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHook); @@ -2167,6 +2310,7 @@ void RandomizerRegisterHooks() { onPlayerUpdateForRCQueueHook = 0; onPlayerUpdateForItemQueueHook = 0; onItemReceiveHook = 0; + onDialogMessageHook = 0; onVanillaBehaviorHook = 0; onSceneInitHook = 0; onActorInitHook = 0; @@ -2199,6 +2343,7 @@ void RandomizerRegisterHooks() { onPlayerUpdateForRCQueueHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>(RandomizerOnPlayerUpdateForRCQueueHandler); onPlayerUpdateForItemQueueHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>(RandomizerOnPlayerUpdateForItemQueueHandler); onItemReceiveHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(RandomizerOnItemReceiveHandler); + onDialogMessageHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnDialogMessage>(RandomizerOnDialogMessageHandler); onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(RandomizerOnVanillaBehaviorHandler); onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(RandomizerOnSceneInitHandler); onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(RandomizerOnActorInitHandler); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 2add45f1d..a9d9e72dc 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1503,7 +1503,10 @@ void DrawLocation(RandomizerCheck rc) { txt = itemLoc->GetPlacedItem().GetName().GetForLanguage(gSaveContext.language); } if (IsVisibleInCheckTracker(rc) && status == RCSHOW_IDENTIFIED && !mystery && !itemLoc->IsAddedToPool()) { - txt += fmt::format(" - {}", OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)->GetPrice()); + auto price = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)->GetPrice(); + if (price) { + txt += fmt::format(" - {}", price); + } } } else { if (IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID())) { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index bcb328132..009bf76ad 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2140,7 +2140,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END){ RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)((textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(rc, TEXT_SHOP_ITEM_RANDOM_CONFIRM); - // textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT) } else if (textId == TEXT_SCRUB_RANDOM) { EnDns* enDns = (EnDns*)GET_PLAYER(play)->talkActor; RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf); From fe9bf7d9567f9ed75353a1ee9ff451256871519d Mon Sep 17 00:00:00 2001 From: Garrett Cox <garrettjcox@gmail.com> Date: Mon, 2 Dec 2024 13:40:29 -0600 Subject: [PATCH 16/28] Adjust Actor_GetProjectileActor to behave more like hardware, fixing an issue with Dark Link (#4606) --- soh/src/code/z_actor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 8ceca43f2..4cd4d7584 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -2,6 +2,7 @@ #include "vt.h" #include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h" +#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h" #include "overlays/actors/ovl_En_Part/z_en_part.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" @@ -3854,8 +3855,14 @@ Actor* Actor_GetProjectileActor(PlayState* play, Actor* refActor, f32 radius) { // it can also be an arrow. // Luckily, the field at the same offset in the arrow actor is the x component of a vector // which will rarely ever be 0. So it's very unlikely for this bug to cause an issue. + // + // SoH [Port] We're making a change here, it doesn't technically fix the bug but makes it behave + // more like hardware. Because of pointer size differences in SoH this was accessing a different + // place in memory and causing issues with Dark link behavior, and probably other places too if ((Math_Vec3f_DistXYZ(&refActor->world.pos, &actor->world.pos) > radius) || - (((ArmsHook*)actor)->timer == 0)) { + (actor->id == ACTOR_ARMS_HOOK && ((ArmsHook*)actor)->timer == 0) || + (actor->id == ACTOR_EN_ARROW && ((EnArrow*)actor)->unk_210.x == 0) + ) { actor = actor->next; } else { deltaX = Math_SinS(actor->world.rot.y) * (actor->speedXZ * 10.0f); From 4edb83e2f3c3be1d288f5898118f7857ea8d2817 Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Mon, 2 Dec 2024 13:46:16 -0700 Subject: [PATCH 17/28] Fix errors introduced by actor check reveal PR from references to GetSelectedOptionIndex. (#4607) --- soh/soh/Enhancements/randomizer/hook_handlers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 53e4c1759..6ff188b97 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -637,7 +637,7 @@ void RandomizerOnDialogMessageHandler() { MessageContext *msgCtx = &gPlayState->msgCtx; Actor *actor = msgCtx->talkActor; auto ctx = Rando::Context::GetInstance(); - bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).GetSelectedOptionIndex() != RO_GENERIC_OFF; + bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF; bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); @@ -706,7 +706,7 @@ void RandomizerOnDialogMessageHandler() { } break; case TEXT_SCRUB_RANDOM: - if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).GetSelectedOptionIndex() != RO_GENERIC_OFF) { + if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF) { EnDns* enDns = (EnDns*)actor; reveal = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf); } From bbe3bb72b6ab53e05a30143638535110f69423b7 Mon Sep 17 00:00:00 2001 From: Garrett Cox <garrettjcox@gmail.com> Date: Mon, 2 Dec 2024 18:56:32 -0600 Subject: [PATCH 18/28] VBify Ruto (#4602) --- soh/include/z64save.h | 16 ++-- .../MoveJabuJabuElevator.cpp | 27 ++++++ .../SkipChildRutoInteractions.cpp | 93 +++++++++++++++++++ .../Enhancements/TimeSavers/TimeSavers.cpp | 2 + soh/soh/Enhancements/TimeSavers/TimeSavers.h | 2 + .../game-interactor/GameInteractor.h | 13 +++ .../Enhancements/randomizer/hook_handlers.cpp | 6 ++ soh/soh/Enhancements/randomizer/savefile.cpp | 7 +- soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c | 38 ++++---- 9 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveJabuJabuElevator.cpp create mode 100644 soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp diff --git a/soh/include/z64save.h b/soh/include/z64save.h index bf0d20697..b64efb459 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -735,14 +735,14 @@ typedef enum { #define INFTABLE_12A 0x12A #define INFTABLE_138 0x138 #define INFTABLE_139 0x139 -#define INFTABLE_140 0x140 -#define INFTABLE_RUTO_IN_JJ_MEET_RUTO 0x141 -#define INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME 0x142 -#define INFTABLE_143 0x143 -#define INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE 0x144 -#define INFTABLE_145 0x145 -#define INFTABLE_146 0x146 -#define INFTABLE_147 0x147 +#define INFTABLE_140 0x140 // Left her on blue switch in fork room (causes her to spawn in fork room) +#define INFTABLE_RUTO_IN_JJ_MEET_RUTO 0x141 // Jumped down hole from hole room +#define INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME 0x142 // in the basement +#define INFTABLE_143 0x143 // Sat down in basement (causes her to get upset if this is set when actor is spawned) +#define INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE 0x144 // Entered the room with the sapphire +#define INFTABLE_145 0x145 // Thrown to sapphire (not kidnapped yet) +#define INFTABLE_146 0x146 // Kidnapped +#define INFTABLE_147 0x147 // Brought ruto back up to holes room, causes her to spawn in holes room instead of basement #define INFTABLE_160 0x160 #define INFTABLE_161 0x161 #define INFTABLE_162 0x162 diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveJabuJabuElevator.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveJabuJabuElevator.cpp new file mode 100644 index 000000000..1e1c6ceb5 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/MoveJabuJabuElevator.cpp @@ -0,0 +1,27 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "src/overlays/actors/ovl_Bg_Bdan_Objects/z_bg_bdan_objects.h" +} + +/** + * Adjusts the behavior of the elevator to start near the bottom if you are entering the room from the bottom + */ +void MoveJabuJabuElevator_Register() { + GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_BG_BDAN_OBJECTS, [](void* actorRef) { + Player* player = GET_PLAYER(gPlayState); + BgBdanObjects* bgBdanObjects = static_cast<BgBdanObjects*>(actorRef); + + if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { + return; + } + + if (bgBdanObjects->dyna.actor.params == 1) { + if (player->actor.world.pos.y < -500.0f) { + bgBdanObjects->timer = 220; + } + } + }); +} diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp new file mode 100644 index 000000000..aaaf1b39f --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp @@ -0,0 +1,93 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "overlays/actors/ovl_En_Ru1/z_en_ru1.h" +#include "assets/objects/object_ru1/object_ru1.h" + +Actor* func_80AEB124(PlayState* play); +} + +void SkipChildRutoInteractions_Register() { + // Skips the Child Ruto introduction cutscene, where she drops down into the hole in Jabu-Jabu's Belly + REGISTER_VB_SHOULD(VB_PLAY_CHILD_RUTO_INTRO, { + EnRu1* enRu1 = va_arg(args, EnRu1*); + + if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { + return; + } + + Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO); + Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME); + Flags_SetInfTable(INFTABLE_143); + enRu1->drawConfig = 1; + enRu1->actor.world.pos.x = 127.0f; + enRu1->actor.world.pos.y = -340.0f; + enRu1->actor.world.pos.z = -3041.0f; + enRu1->actor.shape.rot.y = enRu1->actor.world.rot.y = -5098; + + if (*should) { + Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildTurnAroundAnim, 1.0f, 0, + Animation_GetLastFrame((void*)&gRutoChildTurnAroundAnim), ANIMMODE_ONCE, -8.0f); + enRu1->action = 10; + } + + *should = false; + }); + + // Skips a short dialogue sequence where Ruto tells you to throw her to the Sapphire + REGISTER_VB_SHOULD(VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE, { + if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { + return; + } + + if (*should) { + Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE); + *should = false; + } + }); + + // Prevents Ruto from running to the Sapphire when she wants to be tossed to it, instead she just stands up and waits for link to get closer + REGISTER_VB_SHOULD(VB_RUTO_RUN_TO_SAPPHIRE, { + EnRu1* enRu1 = va_arg(args, EnRu1*); + DynaPolyActor* dynaPolyActor = va_arg(args, DynaPolyActor*); + + if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { + return; + } + + if (*should) { + enRu1->unk_28C = (BgBdanObjects*)dynaPolyActor; + Flags_SetInfTable(INFTABLE_145); + Flags_SetSwitch(gPlayState, 0x02); + Flags_SetSwitch(gPlayState, 0x1F); + enRu1->action = 42; + Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildWait2Anim, 1.0f, 0, + Animation_GetLastFrame((void*)&gRutoChildWait2Anim), ANIMMODE_LOOP, -8.0f); + enRu1->unk_28C->cameraSetting = 1; + Actor* sapphire = func_80AEB124(gPlayState); + if (sapphire != NULL) { + Actor_Kill(sapphire); + } + enRu1->actor.room = gPlayState->roomCtx.curRoom.num; + *should = false; + } + }); + + // This overrides the behavior that causes Ruto to get upset at you before sitting back down again when INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME is set + GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(ACTOR_EN_RU1, [](void* actorRef) { + EnRu1* enRu1 = static_cast<EnRu1*>(actorRef); + if (!CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) { + return; + } + + if (enRu1->action == 22) { + enRu1->action = 27; + enRu1->drawConfig = 1; + enRu1->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY; + Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f, + Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f); + } + }); +} diff --git a/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp b/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp index 6814b9332..a198f8289 100644 --- a/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp +++ b/soh/soh/Enhancements/TimeSavers/TimeSavers.cpp @@ -10,7 +10,9 @@ void TimeSavers_Register() { SkipZeldaFleeingCastle_Register(); SkipIntro_Register(); // SkipMiscInteractions + MoveJabuJabuElevator_Register(); MoveMidoInKokiriForest_Register(); + SkipChildRutoInteractions_Register(); FasterHeavyBlockLift_Register(); FasterRupeeAccumulator_Register(); } diff --git a/soh/soh/Enhancements/TimeSavers/TimeSavers.h b/soh/soh/Enhancements/TimeSavers/TimeSavers.h index 0cec3edfa..ad521c6c2 100644 --- a/soh/soh/Enhancements/TimeSavers/TimeSavers.h +++ b/soh/soh/Enhancements/TimeSavers/TimeSavers.h @@ -12,7 +12,9 @@ void TimeSavers_Register(); void SkipZeldaFleeingCastle_Register(); void SkipIntro_Register(); // SkipMiscInteractions + void MoveJabuJabuElevator_Register(); void MoveMidoInKokiriForest_Register(); + void SkipChildRutoInteractions_Register(); void FasterHeavyBlockLift_Register(); void FasterRupeeAccumulator_Register(); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 61cfbe72e..8b52b9b37 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -343,6 +343,19 @@ typedef enum { VB_GIVE_RANDO_FISHING_PRIZE, VB_PLAY_THROW_ANIMATION, VB_INFLICT_VOID_DAMAGE, + // Vanilla condition: Close enough & various cutscene checks + // Opt: *EnRu1 + VB_PLAY_CHILD_RUTO_INTRO, + // Vanilla condition: !INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE && in the big okto room + // Opt: *EnRu1 + VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE, + // Vanilla condition: Landed on the platform in the big okto room + // Opt: *EnRu1 + VB_RUTO_RUN_TO_SAPPHIRE, + // Vanilla condition: !Flags_GetInfTable(INFTABLE_145) + // Opt: *EnRu1 + VB_RUTO_BE_CONSIDERED_NOT_KIDNAPPED, + /*** Give Items ***/ diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 6ff188b97..000081cec 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1552,6 +1552,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should = false; break; } + // We need to override the vanilla behavior here because the player might sequence break and get Ruto kidnapped before accessing other + // checks that require Ruto. So if she's kidnapped we allow her to spawn again + case VB_RUTO_BE_CONSIDERED_NOT_KIDNAPPED: { + *should = !Flags_GetInfTable(INFTABLE_145) || Flags_GetInfTable(INFTABLE_146); + break; + } case VB_FREEZE_ON_SKULL_TOKEN: case VB_TRADE_TIMER_ODD_MUSHROOM: case VB_TRADE_TIMER_FROG: diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 02a31e7b5..0012c8311 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -253,10 +253,11 @@ extern "C" void Randomizer_InitSaveFile() { // Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU); // Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT); + // Now handled by cutscene skips // Ruto already met in jabu and spawns down the hole immediately - Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO); - Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME); - Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE); + // Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO); + // Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_TALK_FIRST_TIME); + // Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE); // Now handled by cutscene skips // Skip cutscenes before Nabooru fight diff --git a/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c b/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c index 9b6e4601e..df5b7e106 100644 --- a/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c +++ b/soh/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c @@ -8,6 +8,7 @@ #include "objects/object_ru1/object_ru1.h" #include "vt.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_CAN_PRESS_SWITCH) @@ -763,14 +764,6 @@ void func_80AEC2C0(EnRu1* this, PlayState* play) { func_80AEC070(this, play, something); } -// Convenience function used so that Ruto always spawns in Jabu in rando, even after she's been kidnapped -// Equivalent to !Flags_GetInfTable(INFTABLE_145) in vanilla -bool shouldSpawnRuto() { - // Flags_GetInfTable(INFTABLE_146) check is to prevent Ruto from spawning during the short period of time when - // she's on the Zora's Sapphire pedestal but hasn't been kidnapped yet (would result in multiple Rutos otherwise) - return !Flags_GetInfTable(INFTABLE_145) || (IS_RANDO && (Flags_GetInfTable(INFTABLE_146))); -} - void func_80AEC320(EnRu1* this, PlayState* play) { s8 actorRoom; @@ -778,7 +771,10 @@ void func_80AEC320(EnRu1* this, PlayState* play) { func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0); this->action = 7; EnRu1_SetMouthIndex(this, 1); - } else if ((Flags_GetInfTable(INFTABLE_147)) && !Flags_GetInfTable(INFTABLE_140) && shouldSpawnRuto()) { + } else if ( + Flags_GetInfTable(INFTABLE_147) && !Flags_GetInfTable(INFTABLE_140) && + GameInteractor_Should(VB_RUTO_BE_CONSIDERED_NOT_KIDNAPPED, !Flags_GetInfTable(INFTABLE_145), this) + ) { if (!func_80AEB020(this, play)) { func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0); actorRoom = this->actor.room; @@ -867,9 +863,9 @@ void func_80AEC780(EnRu1* this, PlayState* play) { s32 pad; Player* player = GET_PLAYER(play); - if ((func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) && + if (GameInteractor_Should(VB_PLAY_CHILD_RUTO_INTRO, (func_80AEC5FC(this, play)) && (!Play_InCsMode(play)) && (!(player->stateFlags1 & (PLAYER_STATE1_HANGING_OFF_LEDGE | PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_CLIMBING_LADDER))) && - (player->actor.bgCheckFlags & 1)) { + (player->actor.bgCheckFlags & 1), this)) { play->csCtx.segment = &D_80AF0880; gSaveContext.cutsceneTrigger = 1; @@ -1183,8 +1179,11 @@ void func_80AED414(EnRu1* this, PlayState* play) { void func_80AED44C(EnRu1* this, PlayState* play) { s8 actorRoom; - if ((Flags_GetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO)) && shouldSpawnRuto() && !Flags_GetInfTable(INFTABLE_140) && - !Flags_GetInfTable(INFTABLE_147)) { + if ( + Flags_GetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO) && + GameInteractor_Should(VB_RUTO_BE_CONSIDERED_NOT_KIDNAPPED, !Flags_GetInfTable(INFTABLE_145), this) && + !Flags_GetInfTable(INFTABLE_140) && !Flags_GetInfTable(INFTABLE_147) + ) { if (!func_80AEB020(this, play)) { func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0); actorRoom = this->actor.room; @@ -1550,8 +1549,8 @@ s32 func_80AEE394(EnRu1* this, PlayState* play) { colCtx = &play->colCtx; floorBgId = this->actor.floorBgId; // necessary match, can't move this out of this block unfortunately dynaPolyActor = DynaPoly_GetActor(colCtx, floorBgId); - if (dynaPolyActor != NULL && dynaPolyActor->actor.id == ACTOR_BG_BDAN_OBJECTS && - dynaPolyActor->actor.params == 0 && !Player_InCsMode(play) && play->msgCtx.msgLength == 0) { + if (GameInteractor_Should(VB_RUTO_RUN_TO_SAPPHIRE, dynaPolyActor != NULL && dynaPolyActor->actor.id == ACTOR_BG_BDAN_OBJECTS && + dynaPolyActor->actor.params == 0 && !Player_InCsMode(play) && play->msgCtx.msgLength == 0, this, dynaPolyActor)) { func_80AEE02C(this); play->csCtx.segment = &D_80AF10A4; gSaveContext.cutsceneTrigger = 1; @@ -1611,7 +1610,7 @@ s32 func_80AEE6D0(EnRu1* this, PlayState* play) { s32 pad; s8 curRoomNum = play->roomCtx.curRoom.num; - if (!Flags_GetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE) && (func_80AEB124(play) != 0)) { + if (GameInteractor_Should(VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE, !Flags_GetInfTable(INFTABLE_RUTO_IN_JJ_WANTS_TO_BE_TOSSED_TO_SAPPHIRE) && (func_80AEB124(play) != 0), this)) { if (!Player_InCsMode(play)) { Animation_Change(&this->skelAnime, &gRutoChildSeesSapphireAnim, 1.0f, 0, Animation_GetLastFrame(&gRutoChildSquirmAnim), ANIMMODE_LOOP, -8.0f); @@ -2190,8 +2189,11 @@ void func_80AEFF40(EnRu1* this, PlayState* play) { void func_80AEFF94(EnRu1* this, PlayState* play) { s8 actorRoom; - if ((Flags_GetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO)) && (Flags_GetInfTable(INFTABLE_140)) && shouldSpawnRuto() && - (!(func_80AEB020(this, play)))) { + if ( + Flags_GetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO) && Flags_GetInfTable(INFTABLE_140) && + GameInteractor_Should(VB_RUTO_BE_CONSIDERED_NOT_KIDNAPPED, !Flags_GetInfTable(INFTABLE_145), this) && + (!(func_80AEB020(this, play))) + ) { func_80AEB264(this, &gRutoChildWait2Anim, 0, 0, 0); actorRoom = this->actor.room; this->action = 22; From e704c5592b89aa31ae6a3f535bef8796af6e663b Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:11:01 +0000 Subject: [PATCH 19/28] fix text Poeverflow on Poes hint (#4598) --- .../custom-message/CustomMessageManager.cpp | 64 ++++++++++++++++++- .../custom-message/CustomMessageManager.h | 6 ++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 3d494b87f..2695cd3ef 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -342,6 +342,15 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin nextPosJump = 1; // Assume worst case for player name 12 * 8 (widest character * longest name length) totalPixelWidth += 96; + } else if (textStr->at(currentPos) == '\x05') { + // Skip colour control characters. + nextPosJump = 2; + } else if (textStr->at(currentPos) == '\x1E') { + //For the high score char, we have to take the next Char, then use that to get a worst case scenario. + if (textStr->at(currentPos+1) == '\x01'){ + totalPixelWidth += 28; + } + nextPosJump = 2; } else { // Some characters only one byte while others are two bytes // So check both possibilities when checking for a character @@ -367,6 +376,59 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin } } + +size_t CustomMessage::FindNEWLINE(std::string& str, size_t lastNewline) const { + size_t newLine = str.find(NEWLINE()[0], lastNewline); + bool done; + do { + done = true; + if (newLine != 0){ + switch (str[newLine - 1]){ + case '\x05'://COLOR + case '\x06'://SHIFT + case '\x07'://TEXTID + case '\x0C'://BOX_BREAK_DELAYED + case '\x0E'://FADE + case '\x11'://FADE2 + case '\x12'://SFX + case '\x13'://ITEM_ICON + case '\x14'://TEXT_SPEED + case '\x15'://BACKGROUND + case '\x1E'://POINTS/HIGH_SCORE + done = false; + break; + default: + break; + } + if (newLine > 1){ + switch (str[newLine - 2]){ + case '\x07'://TEXTID + case '\x11'://FADE2 + case '\x12'://SFX + case '\x15'://BACKGROUND + done = false; + break; + default: + break; + } + if (newLine > 2){ + if (str[newLine - 3] == '\x15'){//BACKGROUND + done = false; + } + } + } + } + if (!done){ + newLine = str.find(NEWLINE()[0], newLine + 1); + if (newLine != std::string::npos){ + //if we reach the end of the string, quit now to save a loop + done = true; + } + } + } while (!done); + return newLine; +} + void CustomMessage::AutoFormatString(std::string& str) const { ReplaceAltarIcons(str); ReplaceColors(str); @@ -381,7 +443,7 @@ void CustomMessage::AutoFormatString(std::string& str) const { const size_t ampersand = str.find('&', lastNewline); const size_t lastSpace = str.rfind(' ', lastNewline + lineLength); size_t waitForInput = str.find(WAIT_FOR_INPUT()[0], lastNewline); - size_t newLine = str.find(NEWLINE()[0], lastNewline); + size_t newLine = FindNEWLINE(str, lastNewline); if (carrot < waitForInput){ waitForInput = carrot; } diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 7f68f2fab..e8a969064 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -178,6 +178,12 @@ class CustomMessage { */ void FormatString(std::string& str) const; + /** + * @brief finds NEWLINEs in a string, while filtering + * /x01's that are used as opperands + */ + size_t FindNEWLINE(std::string& str, size_t lastNewline) const; + /** * @brief formats the string specifically to fit in OoT's * textboxes, and use it's formatting. From f2cc278f8c16971a2da1cacffa291bdc1a533dd2 Mon Sep 17 00:00:00 2001 From: Extloga <141232749+Extloga@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:18:07 +0000 Subject: [PATCH 20/28] Fixes for the English text in several files (#4605) * Fixes for the English text in option_descriptions.cpp * Fixes for the English text in static_data.cpp * Fixes for the English text in option_descriptions.cpp * Fixes for the English text in option_descriptions.cpp * Fixes for the English text in settings.cpp * Fixes for the German translation in hint_list.cpp --- .../randomizer/3drando/hint_list.cpp | 6 +- .../randomizer/option_descriptions.cpp | 192 +++++++++--------- soh/soh/Enhancements/randomizer/settings.cpp | 12 +- .../Enhancements/randomizer/static_data.cpp | 8 +- 4 files changed, 109 insertions(+), 109 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 3a336b12d..e0097a6f6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -1177,7 +1177,7 @@ void StaticData::HintTable_Init() { // /*spanish*/la tienda de pociones de la abuela hintTextTable[RHT_GRAVEYARD_DAMPES_HOUSE] = HintText(CustomMessage("Dampé's Hut", - /*german*/ "der #Hut von Boris#", + /*german*/ "die #Hütte von Boris#", /*french*/ "la #Cabane du Fossoyeur#")); // /*spanish*/la cabaña de Dampé @@ -1277,12 +1277,12 @@ void StaticData::HintTable_Init() { // /*spanish*/la #tumba de la Canción del Sol# hintTextTable[RHT_GRAVEYARD_COMPOSERS_GRAVE] = HintText(CustomMessage("the #Composers' Grave#", - /*german*/ "das Königsgrab", + /*german*/ "das #Königsgrab#", /*french*/ "la #Tombe royale#")); // /*spanish*/el #Panteón Real# hintTextTable[RHT_GRAVEYARD_DAMPES_GRAVE] = HintText(CustomMessage("Dampé's Grave", - /*german*/ "das Grab von Boris", + /*german*/ "das #Grab von Boris#", /*french*/ "la #Tombe d'Igor#")); // /*spanish*/la #tumba de Dampé# diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index d119c5e80..405620849 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -2,30 +2,30 @@ namespace Rando { void Settings::CreateOptionDescriptions() { - mOptionDescriptions[RSK_FOREST] = "Closed - Kokiri sword & shield are required to access " + mOptionDescriptions[RSK_FOREST] = "Closed - Kokiri Sword & Deku Shield are required to access " "the Deku Tree, and completing the Deku Tree is required to " "access the Hyrule Field exit.\n" "\n" "Closed Deku - Kokiri boy no longer blocks the path to Hyrule " - "Field but Mido still requires the Kokiri sword and Deku shield " + "Field but Mido still requires the Kokiri Sword and Deku Shield " "to access the tree.\n" "\n" "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " "boy no longer blocks the path out of the forest."; - mOptionDescriptions[RSK_KAK_GATE] = "Closed - The gate will remain closed until Zelda's letter " + mOptionDescriptions[RSK_KAK_GATE] = "Closed - The gate will remain closed until Zelda's Letter " "is shown to the guard.\n" "\n" - "Open - The gate is always open. The happy mask shop " - "will open immediately after obtaining Zelda's letter."; + "Open - The gate is always open. The Happy Mask Shop " + "will open immediately after obtaining Zelda's Letter."; mOptionDescriptions[RSK_DOOR_OF_TIME] = "Closed - The Ocarina of Time, the Song of Time and all " - "three spiritual stones are required to open the Door of Time.\n" + "three Spiritual Stones are required to open the Door of Time.\n" "\n" "Song only - Play the Song of Time in front of the Door of " "Time to open it.\n" "\n" "Open - The Door of Time is permanently open with no requirements."; mOptionDescriptions[RSK_ZORAS_FOUNTAIN] = "Closed - King Zora obstructs the way to Zora's Fountain. " - "Ruto's letter must be shown as child Link in order to move " + "Ruto's Letter must be shown as child Link in order to move " "him in both time periods.\n" "\n" "Closed as child - Ruto's Letter is only required to move King Zora " @@ -60,12 +60,12 @@ void Settings::CreateOptionDescriptions() { "\n" "Always open - No requirements.\n" "\n" - "Stones - Obtain the specified amount of spiritual stones.\n" + "Stones - Obtain the specified amount of Spiritual Stones.\n" "\n" "Medallions - Obtain the specified amount of medallions.\n" "\n" - "Dungeon rewards - Obtain the specified total sum of spiritual " - "stones or medallions.\n" + "Dungeon rewards - Obtain the specified total sum of Spiritual " + "Stones or medallions.\n" "\n" "Dungeons - Complete the specified amount of dungeons. Dungeons " "are considered complete after stepping in to the blue warp after " @@ -89,10 +89,10 @@ void Settings::CreateOptionDescriptions() { "\n" "Skip - No Trials are required and the barrier is already dispelled.\n" "\n" - "Set Number - Select a number of trials that will be required from the" + "Set Number - Select a number of trials that will be required from the " "slider below. Which specific trials you need to complete will be random.\n" "\n" - "Random Number - A Random number and set of trials will be required."; + "Random Number - A random number and set of trials will be required."; mOptionDescriptions[RSK_TRIAL_COUNT] = "Set the number of trials required to enter Ganon's Tower."; mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM] = "Sets the number of Master Quest Dungeons that are shuffled into the pool.\n" @@ -102,7 +102,7 @@ void Settings::CreateOptionDescriptions() { "Set Number - Select a number of dungeons that will be their Master Quest versions " "using the slider below. Which dungeons are set to be the Master Quest variety will be random.\n" "\n" - "Random Number - A Random number and set of dungeons will be their Master Quest varieties.\n" + "Random Number - A random number and set of dungeons will be their Master Quest varieties.\n" "\n" "Selection Only - Specify which dungeons are Vanilla, Master Quest or a 50/50 between the two.\n" "Differs from Random Number in that they are rolled individually, making the exact total a bell curve."; @@ -124,14 +124,14 @@ void Settings::CreateOptionDescriptions() { "Keep in mind seed generation can fail if more pieces are placed than there are junk items in the item pool."; mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED] = "The amount of Triforce pieces required to win the game."; mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES] = - "Shuffle the pool of dungeon entrances, including Bottom of the Well, Ice Cavern and Gerudo Training Grounds.\n" + "Shuffle the pool of dungeon entrances, including Bottom of the Well, Ice Cavern and Gerudo Training Ground.\n" "\n" "Shuffling Ganon's Castle can be enabled separately.\n" "\n" "Additionally, the entrances of Deku Tree, Fire Temple, Bottom of the Well and Gerudo Training Ground are " "opened for both child and adult.\n" "\n" - "- Deku Tree will be open for adult after Mido has seen child Link with a sword and shield.\n" + "- Deku Tree will be open for adult after Mido has seen child Link with a sword and a shield.\n" "- Bottom of the Well will be open for adult after playing Song of Storms to the Windmill guy as child.\n" "- Gerudo Training Ground will be open for child after adult has paid to open the gate once."; mOptionDescriptions[RSK_SHUFFLE_BOSS_ENTRANCES] = @@ -177,23 +177,23 @@ void Settings::CreateOptionDescriptions() { "This also adds the one-way entrance from Gerudo Valley to Lake Hylia in the pool of " "overworld entrances when they are shuffled."; mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS] = - "Shuffle entrances into a mixed pool instead of separate ones. Has no affect on pools whose " + "Shuffle entrances into a mixed pool instead of separate ones. Has no effect on pools whose " "entrances aren't shuffled, and \"Shuffle Boss Entrances\" must be set to \"Full\" to include them.\n" "\n" "For example, enabling the settings to shuffle grotto, dungeon, and overworld entrances and " "selecting grotto and dungeon entrances here will allow a dungeon to be inside a grotto or " "vice versa, while overworld entrances are shuffled in their own separate pool and indoors stay vanilla."; - mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES] = "Dungeon entrances will be part of the mixed pool"; - mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES] = "Boss entrances will be part of the mixed pool"; - mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES] = "Overworld entrances will be part of the mixed pool"; - mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES] = "Interior entrances will be part of the mixed pool"; - mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES] = "Grotto entrances will be part of the mixed pool"; + mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES] = "Dungeon entrances will be part of the mixed pool."; + mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES] = "Boss entrances will be part of the mixed pool."; + mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES] = "Overworld entrances will be part of the mixed pool."; + mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES] = "Interior entrances will be part of the mixed pool."; + mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES] = "Grotto entrances will be part of the mixed pool."; mOptionDescriptions[RSK_SHUFFLE_SONGS] = "Song locations - Songs will only appear at locations that normally teach songs.\n" "\n" "Dungeon rewards - Songs appear after beating a major dungeon boss.\n" "The 4 remaining songs are located at:\n" - " - Zelda's lullaby location\n" + " - Zelda's Lullaby location\n" " - Ice Cavern's Serenade of Water location\n" " - Bottom of the Well Lens of Truth location\n" " - Gerudo Training Ground's Ice Arrows location\n" @@ -246,33 +246,33 @@ void Settings::CreateOptionDescriptions() { "\n" "The Weird Egg is required to unlock several events:\n" " - Zelda's Lullaby from Impa\n" - " - Saria's song in Sacred Forest Meadow\n" - " - Epona's song and chicken minigame at Lon Lon Ranch\n" - " - Zelda's letter for Kakariko gate (if set to closed)\n" + " - Saria's Song in Sacred Forest Meadow\n" + " - Epona's Song and chicken minigame at Lon Lon Ranch\n" + " - Zelda's Letter for Kakariko gate (if set to closed)\n" " - Happy Mask Shop sidequest\n"; mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = "Shuffles the Gerudo Membership Card into the item pool.\n" "\n" - "The Gerudo Card is required to enter the Gerudo Training Grounds, opening " + "The Gerudo Card is required to enter the Gerudo Training Ground, opening " "the gate to Haunted Wasteland and the Horseback Archery minigame."; mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; - mOptionDescriptions[RSK_INFINITE_UPGRADES] = "Adds upgrades that hold infinite quanities of items (bombs, arrows, etc.)\n" + mOptionDescriptions[RSK_INFINITE_UPGRADES] = "Adds upgrades that hold infinite quantities of items (bombs, arrows, etc.).\n" "\n" - "Progressive - The infinite upgrades are obtained after getting the last normal capacity upgrade\n" + "Progressive - The infinite upgrades are obtained after getting the last normal capacity upgrade.\n" "\n" - "Condensed Progressive - The infinite upgrades are obtained as the first capacity upgrade (doesn't apply to the infinite wallet or to infinite magic)"; - mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG] = "Shuffles the deku stick bag into the item pool.\n" + "Condensed Progressive - The infinite upgrades are obtained as the first capacity upgrade (doesn't apply to the infinite wallet or to infinite magic)."; + mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG] = "Shuffles the Deku Stick bag into the item pool.\n" "\n" - "The deku stick bag is required to hold deku sticks."; - mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG] = "Shuffles the deku nut bag into the item pool.\n" + "The Deku Stick bag is required to hold Deku Sticks."; + mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG] = "Shuffles the Deku Nut bag into the item pool.\n" "\n" - "The deku nut bag is required to hold deku nuts."; + "The Deku Nut bag is required to hold Deku Nuts."; mOptionDescriptions[RSK_SHOPSANITY] = "Off - All shop items will be the same as vanilla.\n" "\n" - "Specifc Count - Vanilla shop items will be shuffled among different shops, and " - "each shop will contain a specifc number (0-7) of non-vanilla shop items.\n" + "Specific Count - Vanilla shop items will be shuffled among different shops, and " + "each shop will contain a specific number (0-7) of non-vanilla shop items.\n" "\n" "Random - Vanilla shop items will be shuffled among different shops, and " "each shop will contain a random number (1-7) of non-vanilla shop items."; @@ -285,12 +285,12 @@ void Settings::CreateOptionDescriptions() { "8 Items - All shops will contain 8 non-vanilla shop items.\n" */; mOptionDescriptions[RSK_SHOPSANITY_PRICES] = - "Vanilla - The same price as the item it replaced\n" - "Cheap Balanced - Prices will range between 0 to 95 rupees, favoring lower numbers\n" - "Balanced - Prices will range between 0 to 300 rupees, favoring lower numbers\n" - "Fixed - A fixed number\n" - "Range - A random point between specific ranges\n" - "Set By Wallet - Set weights that decide the choice of each wallet, and get a random price in that range if that wallet is chosen"; + "Vanilla - The same price as the item it replaced.\n" + "Cheap Balanced - Prices will range between 0 to 95 rupees, favoring lower numbers.\n" + "Balanced - Prices will range between 0 to 300 rupees, favoring lower numbers.\n" + "Fixed - A fixed number.\n" + "Range - A random point between specific ranges.\n" + "Set By Wallet - Set weights that decide the choice of each wallet, and get a random price in that range if that wallet is chosen."; mOptionDescriptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE] = "The price for Shopsanity checks."; mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_1] = @@ -306,13 +306,13 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT] = "The chance for Shopsanity checks to be purchasable with Giant's Wallet (201-500)."; mOptionDescriptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT] = - "The chance for Shopsanity checks to be purchasable with Tycoon Wallet. (500+)"; + "The chance for Shopsanity checks to be purchasable with Tycoon Wallet (500+)."; mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] = "After choosing a price, set it to the affordable amount based on the wallet required.\n\n" "Affordable prices per tier: starter = 1, adult = 100, giant = 201, tycoon = 501\n\n" "Use this to enable wallet tier locking, but make shop items not as expensive as they could be."; mOptionDescriptions[RSK_FISHSANITY] = "Off - Fish will not be shuffled. No changes will be made to fishing behavior.\n\n" - "Shuffle only Hyrule Loach - Allows you to earn an item by catching the hyrule loach at the fishing pond and giving it to the owner.\n\n" + "Shuffle only Hyrule Loach - Allows you to earn an item by catching the Hyrule Loach at the fishing pond and giving it to the owner.\n\n" "Shuffle Fishing Pond - The fishing pond's fish will be shuffled. Catching a fish in the fishing pond will grant a reward.\n\n" "Shuffle Overworld Fish - Fish in generic grottos and Zora's Domain will be shuffled. Catching a fish in a bottle will give a reward.\n\n" "Shuffle Both - Both overworld fish and fish in the fishing pond will be shuffled."; @@ -332,12 +332,12 @@ void Settings::CreateOptionDescriptions() { "\n" "All - All Scrubs are shuffled."; mOptionDescriptions[RSK_SCRUBS_PRICES] = - "Vanilla - The same price as the item it replaced\n" - "Cheap Balanced - Prices will range between 0 to 95 rupees, favoring lower numbers\n" - "Balanced - Prices will range between 0 to 300 rupees, favoring lower numbers\n" - "Fixed - A fixed number\n" - "Range - A random point between specific ranges\n" - "Set By Wallet - Set weights that decide the choice of each wallet, and get a random price in that range if that wallet is chosen"; + "Vanilla - The same price as the item it replaced.\n" + "Cheap Balanced - Prices will range between 0 to 95 rupees, favoring lower numbers.\n" + "Balanced - Prices will range between 0 to 300 rupees, favoring lower numbers.\n" + "Fixed - A fixed number.\n" + "Range - A random point between specific ranges.\n" + "Set By Wallet - Set weights that decide the choice of each wallet, and get a random price in that range if that wallet is chosen."; mOptionDescriptions[RSK_SCRUBS_PRICES_FIXED_PRICE] = "The price for Scrub checks."; mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_1] = @@ -353,7 +353,7 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT] = "The chance for Scrub checks to be purchasable with Giant's Wallet (201-500)."; mOptionDescriptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT] = - "The chance for Scrub checks to be purchasable with Tycoon Wallet. (500+)"; + "The chance for Scrub checks to be purchasable with Tycoon Wallet (500+)."; mOptionDescriptions[RSK_SCRUBS_PRICES_AFFORDABLE] = "After choosing a price, set it to the affordable amount based on the wallet required.\n\n" "Affordable prices per tier: starter = 1, adult = 100, giant = 201, tycoon = 501\n\n" @@ -366,7 +366,7 @@ void Settings::CreateOptionDescriptions() { "This setting governs if the Bean Salesman, Medigoron, Granny and the Carpet Salesman " "sell a random item.\n" "Beans Only - Only the Bean Salesman will have a check, and a pack of Magic Beans will be added " - " to the item pool." + "to the item pool." "All But Beans - Medigoron, Granny and the Carpet Salesman will have checks, " "A Giant's Knife and a pack of Bombchus will be added to the item pool, and " "one of the bottles will contain a Blue Potion.\n\n" @@ -376,12 +376,12 @@ void Settings::CreateOptionDescriptions() { "Otherwise when off, you will need to have found the Claim Check to buy her item (simulating the trade quest " "is complete)."; mOptionDescriptions[RSK_MERCHANT_PRICES] = - "Vanilla - The same price as the Check in vanilla, 60 for the Bean Salesman\n" - "Cheap Balanced - Prices will range between 0 to 95 rupees, favoring lower numbers\n" - "Balanced - Prices will range between 0 to 300 rupees, favoring lower numbers\n" - "Fixed - A fixed number\n" - "Range - A random point between specific ranges\n" - "Set By Wallet - Set weights that decide the choice of each wallet, and get a random price in that range if that wallet is chosen"; + "Vanilla - The same price as the Check in vanilla, 60 for the Bean Salesman.\n" + "Cheap Balanced - Prices will range between 0 to 95 rupees, favoring lower numbers.\n" + "Balanced - Prices will range between 0 to 300 rupees, favoring lower numbers.\n" + "Fixed - A fixed number.\n" + "Range - A random point between specific ranges.\n" + "Set By Wallet - Set weights that decide the choice of each wallet, and get a random price in that range if that wallet is chosen."; mOptionDescriptions[RSK_MERCHANT_PRICES_FIXED_PRICE] = "The price for Merchant checks."; mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_1] = @@ -397,7 +397,7 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT] = "The chance for Merchant checks to be purchasable with Giant's Wallet (201-500)."; mOptionDescriptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT] = - "The chance for Merchant checks to be purchasable with Tycoon Wallet. (500+)"; + "The chance for Merchant checks to be purchasable with Tycoon Wallet (500+)."; mOptionDescriptions[RSK_MERCHANT_PRICES_AFFORDABLE] = "After choosing a price, set it to the affordable amount based on the wallet required.\n\n" "Affordable prices per tier: starter = 1, adult = 100, giant = 201, tycoon = 501\n\n" @@ -422,16 +422,16 @@ void Settings::CreateOptionDescriptions() { "\n" "You can still talk to him multiple times to get Huge Rupees."; mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS] = - "Shuffles the location of spiritual stones and medallions.\n" + "Shuffles the location of Spiritual Stones and medallions.\n" "\n" - "End of dungeons - Spiritual stones and medallions will be given as rewards " + "End of dungeons - Spiritual Stones and medallions will be given as rewards " "for beating major dungeons. Link will always start with one stone or medallion.\n" "\n" - "Any dungeon - Spiritual stones and medallions can be found inside any dungeon.\n" + "Any dungeon - Spiritual Stones and medallions can be found inside any dungeon.\n" "\n" - "Overworld - Spiritual stones and medallions can only be found outside of dungeons.\n" + "Overworld - Spiritual Stones and medallions can only be found outside of dungeons.\n" "\n" - "Anywhere - Spiritual stones and medallions can appear anywhere."; + "Anywhere - Spiritual Stones and medallions can appear anywhere."; mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS] = "Start with - You will start with Maps & Compasses from all dungeons.\n" "\n" @@ -439,7 +439,7 @@ void Settings::CreateOptionDescriptions() { "\n" "Own dungeon - Maps & Compasses can only appear in their respective dungeon.\n" "\n" - "Any dungeon - Maps & Compasses can only appear inside of any dungon.\n" + "Any dungeon - Maps & Compasses can only appear inside of any dungeon.\n" "\n" "Overworld - Maps & Compasses can only appear outside of dungeons.\n" "\n" @@ -453,18 +453,18 @@ void Settings::CreateOptionDescriptions() { "Own dungeon - Small Keys can only appear in their respective dungeon. " "If Fire Temple is not a Master Quest dungeon, the door to the Boss Key chest will be unlocked.\n" "\n" - "Any dungeon - Small Keys can only appear inside of any dungon.\n" + "Any dungeon - Small Keys can only appear inside of any dungeon.\n" "\n" "Overworld - Small Keys can only appear outside of dungeons.\n" "\n" "Anywhere - Small Keys can appear anywhere in the world."; mOptionDescriptions[RSK_KEYRINGS] = "Keyrings will replace all small keys from a particular dungeon with a single keyring that awards all keys for " - "it's associated dungeon\n" + "its associated dungeon.\n" "\n" "Off - No dungeons will have their keys replaced with keyrings.\n" "\n" - "Random - A random amount of dungeons(0-8 or 9) will have their keys replaced with keyrings.\n" + "Random - A random amount of dungeons (0-8 or 9) will have their keys replaced with keyrings.\n" "\n" "Count - A specified amount of randomly selected dungeons will have their keys replaced with keyrings.\n" "\n" @@ -476,20 +476,20 @@ void Settings::CreateOptionDescriptions() { "If Gerudo Fortress Carpenters is set to Normal, and Gerudo Fortress Keys is set to anything " "other than Vanilla, then the maximum amount of Key Rings that can be selected by Random or " "Count will be 9. Otherwise, the maximum amount of Key Rings will be 8."; - mOptionDescriptions[RSK_GERUDO_KEYS] = "Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n" + mOptionDescriptions[RSK_GERUDO_KEYS] = "Vanilla - Thieves' Hideout Keys will appear in their vanilla locations.\n" "\n" - "Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n" + "Any dungeon - Thieves' Hideout Keys can only appear inside of any dungon.\n" "\n" - "Overworld - Thieve's Hideout Keys can only appear outside of dungeons.\n" + "Overworld - Thieves' Hideout Keys can only appear outside of dungeons.\n" "\n" - "Anywhere - Thieve's Hideout Keys can appear anywhere in the world."; + "Anywhere - Thieves' Hideout Keys can appear anywhere in the world."; mOptionDescriptions[RSK_BOSS_KEYSANITY] = "Start with - You will start with Boss keys from all dungeons.\n" "\n" "Vanilla - Boss Keys will appear in their vanilla locations.\n" "\n" "Own dungeon - Boss Keys can only appear in their respective dungeon.\n" "\n" - "Any dungeon - Boss Keys can only appear inside of any dungon.\n" + "Any dungeon - Boss Keys can only appear inside of any dungeon.\n" "\n" "Overworld - Boss Keys can only appear outside of dungeons.\n" "\n" @@ -501,7 +501,7 @@ void Settings::CreateOptionDescriptions() { "\n" "Start with - Places Ganon's Boss Key in your starting inventory." "\n" - "Any dungeon - Ganon's Boss Key Key can only appear inside of any dungon.\n" + "Any dungeon - Ganon's Boss Key Key can only appear inside of any dungeon.\n" "\n" "Overworld - Ganon's Boss Key Key can only appear outside of dungeons.\n" "\n" @@ -510,9 +510,9 @@ void Settings::CreateOptionDescriptions() { "LACS - These settings put the boss key on the Light Arrow Cutscene location, from Zelda in Temple of Time as " "adult, with differing requirements:\n" "- Vanilla: Obtain the Shadow Medallion and Spirit Medallion\n" - "- Stones: Obtain the specified amount of spiritual stones.\n" + "- Stones: Obtain the specified amount of Spiritual Stones.\n" "- Medallions: Obtain the specified amount of medallions.\n" - "- Dungeon rewards: Obtain the specified total sum of spiritual stones or medallions.\n" + "- Dungeon rewards: Obtain the specified total sum of Spiritual Stones or medallions.\n" "- Dungeons: Complete the specified amount of dungeons. Dungeons are considered complete after stepping in to " "the blue warp after the boss.\n" "- Tokens: Obtain the specified amount of Skulltula tokens.\n" @@ -529,7 +529,7 @@ void Settings::CreateOptionDescriptions() { "\n" "Greg as Wildcard - Greg does not change logic, Greg helps obtain GBK, max number of " "rewards on slider does not change."; - mOptionDescriptions[RSK_CUCCO_COUNT] = "The amount of cuccos needed to claim the reward from Anju the cucco lady"; + mOptionDescriptions[RSK_CUCCO_COUNT] = "The amount of cuccos needed to claim the reward from Anju the Cucco Lady."; mOptionDescriptions[RSK_BIG_POE_COUNT] = "The Poe collector will give a reward for turning in this many Big Poes."; mOptionDescriptions[RSK_SKIP_CHILD_STEALTH] = "The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."; @@ -538,11 +538,11 @@ void Settings::CreateOptionDescriptions() { "until after meeting Zelda. Disables the ability to shuffle Weird Egg."; mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo."; mOptionDescriptions[RSK_COMPLETE_MASK_QUEST] = - "Once the happy mask shop is opened, all masks will be available to be borrowed."; + "Once the Happy Mask Shop is opened, all masks will be available to be borrowed."; mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] = - "Start with the ability to summon Pierre the scarecrow. Pulling out an ocarina in the usual locations will " + "Start with the ability to summon Pierre the Scarecrow. Pulling out an Ocarina in the usual locations will " "automatically summon him.\n" - "With \"Shuffle Ocarina Buttons\" enabled, you'll need at least two ocarina buttons to summon him."; + "With \"Shuffle Ocarina Buttons\" enabled, you'll need at least two Ocarina buttons to summon him."; mOptionDescriptions[RSK_ITEM_POOL] = "Sets how many major items appear in the item pool.\n" "\n" "Plentiful - Extra major items are added to the pool.\n" @@ -598,12 +598,12 @@ void Settings::CreateOptionDescriptions() { "Very Strong - Many powerful hints."; mOptionDescriptions[RSK_TOT_ALTAR_HINT] = "Reading the Temple of Time altar as child will tell you the locations of the Spiritual Stones.\n" - "Reading the Temple of Time altar as adult will tell you the locations of the Medallions, as well as the " + "Reading the Temple of Time altar as adult will tell you the locations of the medallions, as well as the " "conditions for building the Rainbow Bridge and getting the Boss Key for Ganon's Castle."; mOptionDescriptions[RSK_GANONDORF_HINT] = "Talking to Ganondorf in his boss room will tell you the location of the Light Arrows and Master Sword." "If this option is enabled and Ganondorf is reachable without these items, Gossip Stones will never hint the " - "appropriote items.";//RANDOTODO make this hint text about no dupe hints a global hint for static hints. Add to navi? + "appropriate items.";//RANDOTODO make this hint text about no dupe hints a global hint for static hints. Add to navi? mOptionDescriptions[RSK_SHEIK_LA_HINT] = "Talking to Sheik inside Ganon's Castle will tell you the location of the Light Arrows." "If this option is enabled and Sheik is reachable without Light Arrows, Gossip Stones will never hint the " @@ -619,37 +619,37 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_FISHING_POLE_HINT] = "Talking to the fishing pond owner without the fishing pole will tell you its location."; mOptionDescriptions[RSK_OOT_HINT] = "Sheik in the Temple of Time will tell you the item and song on the Ocarina of Time."; mOptionDescriptions[RSK_FROGS_HINT] = "Standing near the pedestal for the frogs in Zora's River will tell you the " - "reward for the frogs' ocarina game."; + "reward for the frogs' Ocarina game."; mOptionDescriptions[RSK_BIGGORON_HINT] = "Talking to Biggoron will tell you the item he will give you in exchange for the Claim Check."; mOptionDescriptions[RSK_BIG_POES_HINT] = "Talking to the Poe Collector in the Market Guardhouse while adult will tell you what you receive for handing in Big Poes."; - mOptionDescriptions[RSK_CHICKENS_HINT] = "Talking to Anju as a child will tell you the item she will give you for delivering her Cuccos to the pen"; - mOptionDescriptions[RSK_MALON_HINT] = "Talking to Malon as adult will tell you the item on \"Link's cow\", the cow you win from beating her time on the Lon Lon Obsticle Course."; + mOptionDescriptions[RSK_CHICKENS_HINT] = "Talking to Anju as a child will tell you the item she will give you for delivering her cuccos to the pen."; + mOptionDescriptions[RSK_MALON_HINT] = "Talking to Malon as adult will tell you the item on \"Link's cow\", the cow you win from beating her time on the Lon Lon Obstacle Course."; mOptionDescriptions[RSK_HBA_HINT] = "Talking to the Horseback Archery gerudo in Gerudo Fortress, or the nearby sign, will tell you what you win for scoring 1000 and 1500 points on Horseback Archery."; mOptionDescriptions[RSK_WARP_SONG_HINTS] = "Playing a warp song will tell you where it leads. (If warp song destinations are vanilla, this is always enabled.)"; mOptionDescriptions[RSK_SCRUB_TEXT_HINT] = "Business scrubs will reveal the identity of what they're selling."; mOptionDescriptions[RSK_MERCHANT_TEXT_HINT] = "Merchants will reveal the identity of what they're selling (Shops are not affected by this setting)."; - mOptionDescriptions[RSK_KAK_10_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 10 tokens will tell you the reward"; - mOptionDescriptions[RSK_KAK_20_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 20 tokens will tell you the reward"; - mOptionDescriptions[RSK_KAK_30_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 30 tokens will tell you the reward"; - mOptionDescriptions[RSK_KAK_40_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 40 tokens will tell you the reward"; - mOptionDescriptions[RSK_KAK_50_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 50 tokens will tell you the reward"; - mOptionDescriptions[RSK_KAK_100_SKULLS_HINT] = "Talking to the Cursed Resident in the Skultulla House who is saved after 100 tokens will tell you the reward"; + mOptionDescriptions[RSK_KAK_10_SKULLS_HINT] = "Talking to the Cursed Resident in the Skulltula House who is saved after 10 tokens will tell you the reward."; + mOptionDescriptions[RSK_KAK_20_SKULLS_HINT] = "Talking to the Cursed Resident in the Skulltula House who is saved after 20 tokens will tell you the reward."; + mOptionDescriptions[RSK_KAK_30_SKULLS_HINT] = "Talking to the Cursed Resident in the Skulltula House who is saved after 30 tokens will tell you the reward."; + mOptionDescriptions[RSK_KAK_40_SKULLS_HINT] = "Talking to the Cursed Resident in the Skulltula House who is saved after 40 tokens will tell you the reward."; + mOptionDescriptions[RSK_KAK_50_SKULLS_HINT] = "Talking to the Cursed Resident in the Skulltula House who is saved after 50 tokens will tell you the reward."; + mOptionDescriptions[RSK_KAK_100_SKULLS_HINT] = "Talking to the Cursed Resident in the Skulltula House who is saved after 100 tokens will tell you the reward."; mOptionDescriptions[RSK_MASK_SHOP_HINT] = "Reading the mask shop sign will tell you rewards from showing masks at the Deku Theatre."; mOptionDescriptions[RSK_FULL_WALLETS] = "Start with a full wallet. All wallet upgrades come filled with rupees."; mOptionDescriptions[RSK_BOMBCHUS_IN_LOGIC] = - "Bombchus are properly considered in logic. Without this setting, any Bombchu requirement" - " is filled by Bomb Bag + a renewable source of Bombchus\n" + "Bombchus are properly considered in logic. Without this setting, any Bombchu requirement " + "is filled by Bomb Bag + a renewable source of Bombchus.\n" "\n" "The first Bombchu pack will always be 20, and subsequent packs will be " "5 or 10 based on how many you have.\n" "Once found, they can be replenished at the Bombchu shop.\n" "\n" "Bombchu Bowling is opened by obtaining Bombchus."; - mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS] = "Once you obtain bombchus for the first time, refills can be found " + mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS] = "Once you obtain Bombchus for the first time, refills can be found " "in bushes and other places where bomb drops can normally spawn." "\n" - "If you have Bombchus in Logic disabled, you will also need a" - "Bomb bag for bombchus to drop"; + "If you have Bombchus in Logic disabled, you will also need a " + "Bomb Bag for Bombchus to drop."; mOptionDescriptions[RSK_BLUE_FIRE_ARROWS] = "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress."; @@ -677,4 +677,4 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS] = "Shuffles 8 boss souls (one for each blue warp dungeon). A boss will not appear until you collect its respective soul." "\n\"On + Ganon\" will also hide Ganon and Ganondorf behind a boss soul."; } -} // namespace Rando \ No newline at end of file +} // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index f1fa221da..2ed68397e 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -319,7 +319,7 @@ void Settings::CreateOptions() { mTrickOptions[RT_DOOM_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Doom Jump", "Enables locations requiring doom jumps."); mTrickOptions[RT_EPG] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "EPG", "Enables locations requiring use of the Entrance Point Glitch."); mTrickOptions[RT_EQUIP_SWAP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Equip Swap", "Enables locations requiring use of equip swap; NOTE: this may expect the 'Allow cursor to be over any slot' enhancement to be turned off."); - mTrickOptions[RT_EQUIP_SWAP_EXPECTS_DINS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Equip Swap Require's Din's Fire", "Enables locations requiring use of equip swap once din's fire is found."); + mTrickOptions[RT_EQUIP_SWAP_EXPECTS_DINS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Equip Swap Require's Din's Fire", "Enables locations requiring use of equip swap once Din's Fire is found."); mTrickOptions[RT_FLAME_STORAGE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Flame Storage", "Enables locations requiring flame storage."); mTrickOptions[RT_GROUND_CLIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Ground Clip", "Enables locations requiring ground clips."); mTrickOptions[RT_GROUND_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, true, "Ground Jump", "Enables locations requiring ground jumps."); @@ -331,7 +331,7 @@ void Settings::CreateOptions() { mTrickOptions[RT_GROTTOS_WITHOUT_AGONY] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, false, "Hidden Grottos without Stone of Agony", "Allows entering hidden grottos without the Stone of Agony."); mTrickOptions[RT_FEWER_TUNIC_REQUIREMENTS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, false, "Fewer Tunic Requirements", "Allows the following possible without Tunics:\n- Enter Water Temple. The area below the center pillar still requires Zora Tunic. Applies to MQ also.\n- Enter Fire Temple. Volvagia still requires Goron tunic. Applies to MQ also, and includes child access to first floor with dungeon shuffle."); mTrickOptions[RT_RUSTED_SWITCHES] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::NOVICE}, false, "Hammer Rusted Switches Through Walls", "Applies to: - Fire Temple Highest Goron Chest. - MQ Fire Temple Lizalfos Maze. - MQ Spirit Trial."); - mTrickOptions[RT_FLAMING_CHESTS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, false, "Flaming Chests", "The chests encircled in flames in Gerudo Training Grounds and in Spirit Temple can be opened by running into the flames while Link is invincible after taking damage."); + mTrickOptions[RT_FLAMING_CHESTS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::INTERMEDIATE}, false, "Flaming Chests", "The chests encircled in flames in Gerudo Training Ground and in Spirit Temple can be opened by running into the flames while Link is invincible after taking damage."); // mTrickOptions[RT_BUNNY_HOOD_JUMPS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, false, "Bunny Hood Jumps", "Allows reaching locations using Bunny Hood's extended jumps."); // mTrickOptions[RT_DAMAGE_BOOST_SIMPLE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, false, "Simple damage boosts", "Allows damage boosts to reach Hyrule Castle guards, the bomb bag area in DC and the Gerudo Valley crate Piece of Heart. Can be combined with \"Simple hover boosts\" for reaching far distances."); // mTrickOptions[RT_HOVER_BOOST_SIMPLE] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_NONE, {Tricks::Tag::ADVANCED}, false, "Simple hover boosts", "Allows equipping of hover boots when link is moving at high speeds to extend distance covered. Can be combined with \"Simple damage boosts\" for greater uses."); @@ -365,7 +365,7 @@ void Settings::CreateOptions() { mTrickOptions[RT_GC_GROTTO] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::ADVANCED}, false, "Goron City Grotto with Hookshot While Taking Damage", "It is possible to reach the Goron City Grotto by quickly using the Hookshot while in the midst of taking damage from the lava floor."); mTrickOptions[RT_GC_LINK_GORON_DINS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_GORON_CITY, {Tricks::Tag::NOVICE}, false, "Stop Link the Goron with Din\'s Fire", "The timing is quite awkward."); mTrickOptions[RT_DMC_HOVER_BEAN_POH] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::NOVICE}, false, "Crater\'s Bean PoH with Hover Boots", "Hover from the base of the bridge near Goron City and walk up the very steep slope."); - mTrickOptions[RT_DMC_BOLERO_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::EXTREME}, false, "Death Mountain Crater Jump to Bolero", "As Adult , using a shield to drop a pot while you have the perfect speed and position, the pot can push you that little extra distance you need to jump across the gap in the bridge."); + mTrickOptions[RT_DMC_BOLERO_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::EXTREME}, false, "Death Mountain Crater Jump to Bolero", "As Adult, using a shield to drop a pot while you have the perfect speed and position, the pot can push you that little extra distance you need to jump across the gap in the bridge."); mTrickOptions[RT_DMC_BOULDER_JS] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::NOVICE}, false, "Death Mountain Crater Upper to Lower with Hammer", "With the Hammer, you can jump slash the rock twice in the same jump in order to destroy it before you fall into the lava."); mTrickOptions[RT_DMC_BOULDER_SKIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, {Tricks::Tag::INTERMEDIATE}, false, "Death Mountain Crater Upper to Lower Boulder Skip", "As adult, With careful positioning, you can jump to the ledge where the boulder is, then use repeated ledge grabs to shimmy to a climbable ledge. This trick supersedes \"Death Mountain Crater Upper to Lower with Hammer\"."); mTrickOptions[RT_ZR_LOWER] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_ZORAS_RIVER, {Tricks::Tag::INTERMEDIATE}, false, "Zora\'s River Lower Freestanding PoH as Adult with Nothing", "Adult can reach this PoH with a precise jump, no Hover Boots required."); @@ -388,11 +388,11 @@ void Settings::CreateOptions() { mTrickOptions[RT_DEKU_BASEMENT_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, false, "Deku Tree Basement Vines GS with Jump Slash", "Can be defeated by doing a precise jump slash."); mTrickOptions[RT_DEKU_B1_SKIP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_DEKU_TREE, {Tricks::Tag::INTERMEDIATE}, false, "Deku Tree Basement without Slingshot", "A precise jump can be used to skip needing to use the Slingshot to go around B1 of the Deku Tree. If used with the \"Closed Forest\" setting, a Slingshot will not be guaranteed to exist somewhere inside the Forest. This trick applies to both Vanilla and Master Quest."); mTrickOptions[RT_DEKU_B1_BOW_WEBS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, false, "Deku Tree Basement Web to Gohma with Bow", "All spider web walls in the Deku Tree basement can be burnt as adult with just a bow by shooting through torches. This trick only applies to the circular web leading to Gohma; the two vertical webs are always in logic. Backflip onto the chest near the torch at the bottom of the vine wall. With precise positioning you can shoot through the torch to the right edge of the circular web. This allows completion of adult Deku Tree with no fire source."); - mTrickOptions[RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, false, "Deku Tree Basement Backflip over Spiked Log", "Allows backflipping over the spiked log in the deku tree basement in vanilla. Only relevant if \"Shuffle Swim\" is enabled."); + mTrickOptions[RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, false, "Deku Tree Basement Backflip over Spiked Log", "Allows backflipping over the spiked log in the Deku Tree basement in vanilla. Only relevant if \"Shuffle Swim\" is enabled."); mTrickOptions[RT_DEKU_MQ_COMPASS_GS] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, false, "Deku Tree MQ Compass Room GS Boulders with Just Hammer", "Climb to the top of the vines, then let go and jump slash immediately to destroy the boulders using the Hammer, without needing to spawn a Song of Time block."); mTrickOptions[RT_DEKU_MQ_LOG] = TrickOption::LogicTrick(RCQUEST_MQ, RA_DEKU_TREE, {Tricks::Tag::NOVICE}, false, "Deku Tree MQ Roll Under the Spiked Log", "You can get past the spiked log by rolling to briefly shrink your hitbox. As adult, the timing is a bit more precise."); mTrickOptions[RT_DC_SCARECROW_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, false, "Dodongo\'s Cavern Scarecrow GS with Armos Statue", "You can jump off an Armos Statue to reach the alcove with the Gold Skulltula. It takes quite a long time to pull the statue the entire way. The jump to the alcove can be a bit picky when done as child."); - mTrickOptions[RT_DC_VINES_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, false, "Dodongo\'s Cavern Vines GS from Below with Longshot", "The vines upon which this Skulltula rests are one- sided collision. You can use the Longshot to get it from below, by shooting it through the vines, bypassing the need to lower the staircase."); + mTrickOptions[RT_DC_VINES_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, false, "Dodongo\'s Cavern Vines GS from Below with Longshot", "The vines upon which this Skulltula rests are one-sided collision. You can use the Longshot to get it from below, by shooting it through the vines, bypassing the need to lower the staircase."); mTrickOptions[RT_DC_STAIRCASE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, false, "Dodongo\'s Cavern Staircase with Bow", "The Bow can be used to knock down the stairs with two well-timed shots."); mTrickOptions[RT_DC_SLINGSHOT_SKIP] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::EXPERT}, false, "Dodongo\'s Cavern Child Slingshot Skips", "With precise platforming, child can cross the platforms while the flame circles are there. When enabling this trick, it's recommended that you also enable the Adult variant: \"Dodongo's Cavern Spike Trap Room Jump without Hover Boots\"."); mTrickOptions[RT_DC_SCRUB_ROOM] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_DODONGOS_CAVERN, {Tricks::Tag::NOVICE}, false, "Dodongo\'s Cavern Two Scrub Room with Strength", "With help from a conveniently-positioned block, Adult can quickly carry a bomb flower over to destroy the mud wall blocking the room with two Deku Scrubs."); @@ -445,7 +445,7 @@ void Settings::CreateOptions() { mTrickOptions[RT_WATER_CRACKED_WALL] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Water Temple Cracked Wall with No Additional Items", "A precise jump slash (among other methods) will get you to the cracked wall without needing the Hover Boots or to raise the water to the middle level. This trick supersedes \"Water Temple Cracked Wall with Hover Boots\"."); mTrickOptions[RT_WATER_BK_REGION] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Water Temple Boss Key Region with Hover Boots", "With precise Hover Boots movement it is possible to reach the boss key chest's region without needing the Longshot. It is not necessary to take damage from the spikes. The Gold Skulltula Token in the following room can also be obtained with just the Hover Boots."); mTrickOptions[RT_WATER_NORTH_BASEMENT_LEDGE_JUMP] = TrickOption::LogicTrick(RCQUEST_BOTH, RA_WATER_TEMPLE, {Tricks::Tag::INTERMEDIATE}, false, "Water Temple North Basement Ledge with Precise Jump", "In the northern basement there's a ledge from where, in vanilla Water Temple, boulders roll out into the room. Normally to jump directly to this ledge logically requires the Hover Boots, but with precise jump, it can be done without them. This trick applies to both Vanilla and Master Quest."); - mTrickOptions[RT_WATER_BK_JUMP_DIVE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Boss Key Jump Dive", "Stand on the very edge of the raised corridor leading from the push block room to the rolling boulder corridor. Face the gold skulltula on the waterfall and jump over the boulder corridor floor into the pool of water, swimming right once underwater. This allows access to the boss key room without Iron boots."); + mTrickOptions[RT_WATER_BK_JUMP_DIVE] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Boss Key Jump Dive", "Stand on the very edge of the raised corridor leading from the push block room to the rolling boulder corridor. Face the Gold Skulltula on the waterfall and jump over the boulder corridor floor into the pool of water, swimming right once underwater. This allows access to the boss key room without Iron boots."); //Also used in MQ logic, but won't be relevent unless a way to enter tower without irons exists (likely a clip + swim) mTrickOptions[RT_WATER_FW_CENTRAL_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Central Pillar GS with Farore\'s Wind", "If you set Farore's Wind inside the central pillar and then return to that warp point after raising the water to the highest level, you can obtain this Skulltula Token with Hookshot or Boomerang."); mTrickOptions[RT_WATER_IRONS_CENTRAL_GS] = TrickOption::LogicTrick(RCQUEST_VANILLA, RA_WATER_TEMPLE, {Tricks::Tag::NOVICE}, false, "Water Temple Central Pillar GS with Iron Boots", "After opening the middle water level door into the central pillar, the door will stay unbarred so long as you do not leave the room -- even if you were to raise the water up to the highest level. With the Iron Boots to go through the door after the water has been raised, you can obtain the Skulltula Token with the Hookshot."); diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 5c6f7903b..15697d9e0 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -13,7 +13,7 @@ std::unordered_map<uint32_t, CustomMessage> StaticData::hintTypeNames = { {HINT_TYPE_ITEM_AREA, CustomMessage("Item Area")}, {HINT_TYPE_ALTAR_CHILD, CustomMessage("Child Altar")}, {HINT_TYPE_ALTAR_ADULT, CustomMessage("Adult Altar")}, - {HINT_TYPE_WOTH, CustomMessage("Way of the Hero")}, + {HINT_TYPE_WOTH, CustomMessage("Way of the Hero")}, {HINT_TYPE_FOOLISH, CustomMessage("Foolish")}, {HINT_TYPE_MESSAGE, CustomMessage("Hardcoded Message")} }; @@ -60,7 +60,7 @@ std::unordered_map<uint32_t, CustomMessage> StaticData::hintNames = { {RH_LH_SOUTHEAST_GOSSIP_STONE, CustomMessage("LH Southeast Gossip Stone")}, {RH_LH_SOUTHWEST_GOSSIP_STONE, CustomMessage("LH Southwest Gossip Stone")}, {RH_GV_GOSSIP_STONE, CustomMessage("Gerudo Valley Gossip Stone")}, - {RH_COLOSSUS_GOSSIP_STONE, CustomMessage("Desert Collosus Gossip Stone")}, + {RH_COLOSSUS_GOSSIP_STONE, CustomMessage("Desert Colossus Gossip Stone")}, {RH_DODONGOS_CAVERN_GOSSIP_STONE, CustomMessage("Dodongo's Cavern Gossip Stone")}, {RH_GANONDORF_HINT, CustomMessage("Ganondorf Hint")}, {RH_GANONDORF_JOKE, CustomMessage("Ganondorf Joke")}, @@ -189,7 +189,7 @@ std::unordered_map<uint32_t, RandomizerHintTextKey> StaticData::trialData = { std::unordered_map<RandomizerHint, StaticHintInfo> StaticData::staticHintInfoMap = { // RH_GANONDORF_HINT is special cased due to being different based on master sword shuffle // Altar hints are special cased due to special hint marking rules - // warp song hints are special cased due to entrences not being done properly yet + // warp song hints are special cased due to entrances not being done properly yet // Ganondorf Joke is special cased as the text is random {RH_SHEIK_HINT, StaticHintInfo(HINT_TYPE_AREA, {RHT_SHEIK_HINT_LA_ONLY}, RSK_SHEIK_LA_HINT, true, {}, {RG_LIGHT_ARROWS}, {RC_SHEIK_HINT_GC, RC_SHEIK_HINT_MQ_GC}, true)}, {RH_DAMPES_DIARY, StaticHintInfo(HINT_TYPE_AREA, {RHT_DAMPE_DIARY}, RSK_DAMPES_DIARY_HINT, true, {}, {RG_PROGRESSIVE_HOOKSHOT}, {RC_DAMPE_HINT})}, @@ -301,4 +301,4 @@ std::unordered_map<u32, RandomizerHint> StaticData::grottoChestParamsToHint{ }; std::array<HintText, RHT_MAX> StaticData::hintTextTable = {}; -} \ No newline at end of file +} From 8b60cea1f96b1e6ea10f7c37323879bc67123cca Mon Sep 17 00:00:00 2001 From: Malkierian <malkierian@gmail.com> Date: Tue, 3 Dec 2024 09:18:22 -0700 Subject: [PATCH 21/28] Split "Starting Consumables" to Sticks and Nuts. (#4583) * Split "Starting Consumables" to Sticks and Nuts. Setup disabling for them based on status of bag shuffles. * Updated to split index options format. --- .../Enhancements/randomizer/randomizerTypes.h | 3 +- soh/soh/Enhancements/randomizer/savefile.cpp | 12 +++---- soh/soh/Enhancements/randomizer/settings.cpp | 33 ++++++++++++++++--- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 252fc0b28..a910b043f 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -4050,7 +4050,8 @@ typedef enum { RSK_GANONS_BOSS_KEY, RSK_SKIP_CHILD_STEALTH, RSK_SKIP_CHILD_ZELDA, - RSK_STARTING_CONSUMABLES, + RSK_STARTING_STICKS, + RSK_STARTING_NUTS, RSK_FULL_WALLETS, RSK_SHUFFLE_CHEST_MINIGAME, RSK_CUCCO_COUNT, diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 0012c8311..fd23feb04 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -151,13 +151,11 @@ void SetStartingItems() { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } - if (Randomizer_GetSettingValue(RSK_STARTING_CONSUMABLES)) { - if (!Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG)) { - GiveLinkDekuSticks(10); - } - if (!Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG)) { - GiveLinkDekuNuts(20); - } + if (Randomizer_GetSettingValue(RSK_STARTING_STICKS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG)) { + GiveLinkDekuSticks(10); + } + if (Randomizer_GetSettingValue(RSK_STARTING_NUTS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG)) { + GiveLinkDekuNuts(20); } if (Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 2ed68397e..e13a32cfa 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -288,7 +288,8 @@ void Settings::CreateOptions() { mOptions[RSK_STARTING_DEKU_SHIELD] = Option::Bool("Start with Deku Shield", CVAR_RANDOMIZER_SETTING("StartingDekuShield")); mOptions[RSK_STARTING_KOKIRI_SWORD] = Option::Bool("Start with Kokiri Sword", CVAR_RANDOMIZER_SETTING("StartingKokiriSword")); mOptions[RSK_STARTING_MASTER_SWORD] = Option::Bool("Start with Master Sword", CVAR_RANDOMIZER_SETTING("StartingMasterSword")); - mOptions[RSK_STARTING_CONSUMABLES] = Option::Bool("Start with Consumables", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingConsumables"), "", WidgetType::Checkbox, RO_GENERIC_OFF); + mOptions[RSK_STARTING_STICKS] = Option::Bool("Start with Stick Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSticks"), "", WidgetType::Checkbox, RO_GENERIC_OFF); + mOptions[RSK_STARTING_NUTS] = Option::Bool("Start with Nut Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingNuts"), "", WidgetType::Checkbox, RO_GENERIC_OFF); mOptions[RSK_FULL_WALLETS] = Option::Bool("Full Wallets", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FullWallets"), mOptionDescriptions[RSK_FULL_WALLETS], WidgetType::Checkbox, RO_GENERIC_OFF); mOptions[RSK_STARTING_ZELDAS_LULLABY] = Option::Bool("Start with Zelda's Lullaby", CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), "", IMFLAG_NONE); mOptions[RSK_STARTING_EPONAS_SONG] = Option::Bool("Start with Epona's Song", CVAR_RANDOMIZER_SETTING("StartingEponasSong"), "", IMFLAG_NONE); @@ -913,7 +914,8 @@ void Settings::CreateOptions() { }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_STARTING_ITEMS_IMGUI] = OptionGroup::SubGroup("Starting Items", { &mOptions[RSK_STARTING_OCARINA], - &mOptions[RSK_STARTING_CONSUMABLES], + &mOptions[RSK_STARTING_STICKS], + &mOptions[RSK_STARTING_NUTS], &mOptions[RSK_STARTING_SKULLTULA_TOKEN], &mOptions[RSK_STARTING_HEARTS], }, false, WidgetContainerType::COLUMN); @@ -1104,7 +1106,8 @@ void Settings::CreateOptions() { &mOptions[RSK_STARTING_PRELUDE_OF_LIGHT], }, false); mOptionGroups[RSG_STARTING_OTHER] = OptionGroup::SubGroup("Other", { - &mOptions[RSK_STARTING_CONSUMABLES], + &mOptions[RSK_STARTING_STICKS], + &mOptions[RSK_STARTING_NUTS], &mOptions[RSK_FULL_WALLETS], &mOptions[RSK_STARTING_SKULLTULA_TOKEN], &mOptions[RSK_STARTING_HEARTS], @@ -1368,7 +1371,8 @@ void Settings::CreateOptions() { { "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY }, { "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH }, { "Timesaver Settings:Skip Child Zelda", RSK_SKIP_CHILD_ZELDA }, - { "Start with Consumables", RSK_STARTING_CONSUMABLES }, + { "Start with Sticks", RSK_STARTING_STICKS }, + { "Start with Nuts", RSK_STARTING_NUTS }, { "Full Wallets", RSK_FULL_WALLETS }, { "Timesaver Settings:Cuccos to return", RSK_CUCCO_COUNT }, { "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT }, @@ -1838,6 +1842,17 @@ void Settings::UpdateOptionProperties() { mOptions[lastKey].AddFlag(IMFLAG_SEPARATOR_BOTTOM); } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), 0)) { + mOptions[RSK_STARTING_STICKS].Disable("Disabled because Shuffle Deku Stick Bag is On"); + } else { + mOptions[RSK_STARTING_STICKS].Enable(); + } + if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), 0)) { + mOptions[RSK_STARTING_NUTS].Disable("Disabled because Shuffle Deku Nut Bag is On"); + } else { + mOptions[RSK_STARTING_NUTS].Enable(); + } + // Shuffle Weird Egg - Disabled when Skip Child Zelda is active if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), RO_GENERIC_DONT_SKIP)) { mOptions[RSK_SHUFFLE_WEIRD_EGG].Disable("This option is disabled because \"Skip Child Zelda\" is enabled."); @@ -2312,6 +2327,13 @@ void Settings::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocatio } } + if (mOptions[RSK_SHUFFLE_DEKU_STICK_BAG]) { + mOptions[RSK_STARTING_STICKS].SetContextIndex(false); + } + if (mOptions[RSK_SHUFFLE_DEKU_NUT_BAG]) { + mOptions[RSK_STARTING_NUTS].SetContextIndex(false); + } + // RANDOTODO implement chest shuffle with keysanity // ShuffleChestMinigame.SetContextIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); mOptions[RSK_SHUFFLE_CHEST_MINIGAME].SetContextIndex(RO_CHEST_GAME_OFF); @@ -3068,7 +3090,8 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { mOptions[index].SetContextIndex(RO_MQ_DUNGEONS_SELECTION); } break; - case RSK_STARTING_CONSUMABLES: + case RSK_STARTING_STICKS: + case RSK_STARTING_NUTS: case RSK_FULL_WALLETS: if (it.value() == "No") { mOptions[index].SetContextIndex(RO_GENERIC_NO); From 82d70a2029ed743c19ec3a8ace4f8221e0840824 Mon Sep 17 00:00:00 2001 From: Caladius <Caladius@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:44:10 -0500 Subject: [PATCH 22/28] Add Timer Display Window (#4553) * Add new timer window and display options * Fix overflow spacing * Icons for Timers * Swap Labels for Icons. * Additional Timers * Navi Timer Icon * Clean up unused Defines. * Code clean up and double check. Ready for Review * Update from Suggestions * Update magic numbers, correct indentations hopefully * One moooooore thing * Undo z_param change * Updates --- .../parameter_static/gMoon.rgba32.png | Bin 0 -> 6114 bytes .../parameter_static/gNavi.rgba32.png | Bin 0 -> 6275 bytes .../textures/parameter_static/gSun.rgba32.png | Bin 0 -> 6448 bytes soh/assets/soh_assets.h | 9 + .../Enhancements/TimeDisplay/TimeDisplay.cpp | 262 ++++++++++++++++++ .../Enhancements/TimeDisplay/TimeDisplay.h | 37 +++ soh/soh/SohGui.cpp | 5 + soh/soh/SohMenuBar.cpp | 32 +++ soh/src/code/z_parameter.c | 2 +- 9 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 soh/assets/custom/textures/parameter_static/gMoon.rgba32.png create mode 100644 soh/assets/custom/textures/parameter_static/gNavi.rgba32.png create mode 100644 soh/assets/custom/textures/parameter_static/gSun.rgba32.png create mode 100644 soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp create mode 100644 soh/soh/Enhancements/TimeDisplay/TimeDisplay.h diff --git a/soh/assets/custom/textures/parameter_static/gMoon.rgba32.png b/soh/assets/custom/textures/parameter_static/gMoon.rgba32.png new file mode 100644 index 0000000000000000000000000000000000000000..9c1afa577ffd13c4f63b89be8eadc2428d00c19f GIT binary patch literal 6114 zcmeHLc~}$I77t(%Sp-@XS(G$d1WJ|(2_X?sBw#26!%~6ziB6J92#|#&5Ec<ZD^L|= zE677oQ0fz@6%j>2!F@q&-xCDE1+6SvWU(#J>XUaTprVDU-}m~TlP{B*bAIP{&;8wV zPclj8_%1WhHP^*pFa};Mra$;JLf<;t;B57H6vkktS;hwjEB#>=RwkDUM3D$q87D)q zNUTVJ!NlIE3<}Bq#YX>GkBMU10;9BhKX}$zGz~3m^j3XY8?k+zwZ2^gE-(Fu%fBX# z>OVFl)Lc5}eQn#)AC9gaPIu5h+>sZ=Zaok`3LD-lzg?uYg^=1RUQGSvapt-zTCvUP zY-vXIBdz-}*e5qn-lE^FjQZrK>W)V?{TY^0t?ES=Rt7sR*m~RDCNZMJI9+mNd*1bx zZH6c3w?(8xTPjpP+lTj@(r&oYVUZ6lsqigGi*GkRd{k?OPVL>kx{r;v&S+Wfd(7{C zb?>p;ofY@vO71>l%@iiIOIeS!J8Neqt!{rP84@Qc{_#0)psi$N4*UE!W`2CDCDCmg z7)wKDch9ni@>ggjHF|bxnnvYqENyF<wQ^T`xZW3gnEJKaapAcl&T8=<-L&H4T{;_T zt5)uKfLr*z<Ux;cSEKP4j^7#8658wUeWF*1<WveO%Y$o;%gK#qU0Io%pZuB(3G9qQ zTxvB5-CmAseC`XjiZ~n3`R=n%$&@FtSIsray*TWXHH~|@yHqD}$27@|ev;ph5<2T( z|I8)E-_Bm|CWuW5|9PWk`vuGNCA*jI)bC|s37qxJqZ$hmcAHlF6?@;yVnx{Lm38d2 zN;S(hGTjC<6b9TlV%y@MKL4FFdtoRuh3V&&y+O~FrSs{gIGgU?Qkow(4GQ;xDgq9a zx|Qv-zLK7EdY7&3?gGl5T!+@C!J;AMxs647ra^0s1D2+Hc-z%-p9Zepv&p=oHBfP{ z+q^k*_E(WN{4eid)cB9AitjxbvE0Ql@^Dwvpu6Xss9x6ml70PEuDOPRWvi&6UtCEa z3N)yP<`Kf?EhJMntcl%hWRe-685vew81mUboE?pNC_QV|DU5BvA<qEFrgzaneMYrI zoh>8pX`aOT4~v`s8MPCZE3NEC_IBiji%)EN;2(MUl-IuK3$9yKSN0c>WH<V)2P(Uc zXOzti9j>a>`r}HK3g1xjylMG5qn_pNnKI6Hq+0RY>{EtUOV*`*k1728%+8_j*2EuE z-7{xv?Sdcb#>|L|GBgZ57<IF7b(O=+!R}>70~-z|gq5V2<?9!E8_8lDL<0@AUA;6J zfgYce<DF5QA`+&=C6;b}qPM2iu6stoT|-iRoieOg_@hOCG3Wa5h<W~Y`@@W!)U}Dm zJL0yt9%$T8cwBJnk<Y_njr-li^%px_k1--J)=7I$Hl|+S|NF+?GW=JSc|CXoQ>#r) zP<OP-y|U!n6Mg2D?eqH9V#-X#`zu!&Y^S%*>pXKe!|7ClePVTHas8~Odl6j^f7>>* zPq$vbvomJUm?MnKDcWK2_?wQSKcyO0RMmUrgoX=?`}2wT)eS@5&#z~fB$rq;S*>u& zun$-+q1TPNC0{LhviSGKpSCqSU*9_KF$SZtQRME<@p5;6(I-H6C`!z7VV&lfe7!ti zPwAJ_7o|Bd_xi^88K3t*iwm|9f4yR^Pv{@h+2+|Mrpp=+-??*@+tPS8Bxrh&o6$3k zs2G{QGV9|3Z(Tfh?O?1`Prc&ki0hKDz=H4?4~;JmZ3%R?7APvXcV;E(Xv}FSIOF4z z724FGNW6La{MF++SBKY)^gIX}w$@sUi^}cW<WcA5d|cF5G?MPVe}V0po-;YxvslkA zM7Q6kHG8CfRBT2j|1*wzD>?X=HMJW;E^^X^X{W#0=XYXTbVyg-*^tU>!4<x@VA6rg z-L<|6CQ<gECNE%K*t=_su06B&8VkxQeOi#3bY^Jb#m{mo^gS~^3f#3+{_IZDU_y-m zj=#j#J-7amX~*+9(>0GTIV9=0eZJ<Vv&OTl4SB7<2U#?9F6{fQX11%Q_L1bx4{NLk zH1ZcU4CWBbvgbb$>3yv^xX$x-uGS_=@-3=LQkhWXiZLr}88(o~bbL%~6K<9b6gSuY z_h~uxq}BQp^8K#YF6V=O9wP#MJDBam;7P><m@nlbgjlf*^mPozd2y@^=0zY%EEf@q zBrdpt<0o-g5#I$DL}ioMGIu0Q#EO?A0r9?py!Z$nosV1Ws_Puf00d%031ef$krD+X z)&-~LWq@ncOvGW;5M_i5E||^1x=ZB<mO`KqNO+G}Q4AU9s*81&^92llrsp^XxO2gU zDU~t?k*HFs2r37HR4yb!bUK|#A`{7EJV4+TaS|mQi<c<oqZDHtOhmzxi)2cXRDwl0 zVXib<>4L)nKlVj_Vi}wLl3t=1R{`ijjD=-Hh(IEW#l(pb3Z+L3AQ?|+(g;N$`1&LI zBMND>oQHVCAQI*Li4=U^%XnF|JW@R!K97h*B4PklfKj2>hFs>w=DdtRB@l|lGIbOX z`!%FeBzPs(Yq_Bw^>ijC0>WSNzJ`7=cQqKG*lY$<%8N$R^J2Q-(D503DNn>_s4r<W z3W-YR3GfKw#KTi~G(Mh-P<ePRp8~-U#nB0(kS0)hNfb(0!b4ChKu!<=9-4zAmrSR@ zc&d|w6QH0w;$bq`5zmJyTsnjZ$Yg{(fnvE_1ga8_oR}3##RpV$$caZIk@$GXiA%?W z(Vg&gIxN6bAs$5_5b*hQvZI=c&trH><zg5tr$`J75u!{YR69_?8Ezae7aW-|mblu& ziG-B`5CHaoNWzz@6tBR6A~6!6gi$>qngf~S2szOx6uKjoM0o{Tfyfo07ExA+L~s~O z0$msem=2H@Mk^H%s3X8^818ZeR!Zf8QfZ_M4ov}zM!s~j!G_|)N|*^N5kN{JQy37$ zfark`odMApR0^I%WsoM|rF@Yf?rmsv`(T~N7M&$hfbrwhrm;O0fJBYmjon6y)SC&5 zRc{Lh%p0460**oW>O2A0n2Q$%ON0pMAL9l4!Y-Pm7`Rk~LV+E@;z1PjL?Yo~KI8<Z zL*ok^X;cdRO?HJ;pj5$f#7ziv1X_UtRcnQ{8DA>f*RxTDA?P{)$?y<_pCB2II6he- z+A&_t)|vPxJ)G5m2`vW1joCo!0-ccfvK5Z&g*KhP@fcr+zi|XW{b7*z()WX0ALM#3 z1>Ot%p}IcE^<E0R7x+VU{omx$ef2PfNWd>36?jxiWp%fM$1H8G_cA7C6n*Wi|1Jku zX2@6}3JgZ?6ZEZtDJ+@;jMJ4~Y>(-^dL|fSM@>DY75LB1!i(t^=wz&6G;QE1KumtL zwziH=JSIm?Vl6K(pBSgUo&+|zsio!GpMtZpvPLIIzhOmzlO1osroNplxTB-vt)pvB zO^LzO)YSZyTkTU596562ts_mvq$aSmw4BQSZuax%&rT+R+V(aEbp}_On%{<dyML+_ zhK7dTO`qoG=BYT|jR4JYWMpJYl6R^|6!cdl&!0bkw`?w5x;SMfsAFO_8h<5kc6Rot zt*tFaPfrhXx2p>i91`*;d<xU9rQurPT);CE3HB1O*%&);tuxO1uK={sV7xqhncpv6 Glkz|Q-L?Dx literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/parameter_static/gNavi.rgba32.png b/soh/assets/custom/textures/parameter_static/gNavi.rgba32.png new file mode 100644 index 0000000000000000000000000000000000000000..aae12c3398a5c58ece7e2ce05934bbb53203ff0a GIT binary patch literal 6275 zcmeHLXIK>18XiyqX`&`r3CpSx%l5{uV59|BTzU{8R~dF^ae*!D&eFUfHWUlRU=-A= zC?YBnQBf3(i3JpU0ed4B1Qb!ag?na}!Nuf0_xe0H|2#ayIp;g?_kQ1bPZ@?ZUvCc! z)6u371X&0@-TXmqg*_%l;J59Y9vFfK{+bvVjQYcIB$Zkzl|>^YG(m-ska(FCg5q!Q zm>re7*WUcyrODF4<10?6<C7mWJ)|x)b-xqQ@%%_)dYDOGp=sgn_g#ngEL714?I|*= z+ukvH`5La;#l1B#|H;hT)Ef!g4_BWpZZ}FjyOrIzxAXb&Tf!}5KbH$OhQb_+uDez* zR@2tc(2!VGjLBM~m8{H1rHiB~2fe-C+COqwcDHuFf|b?wOQn0=Vq{?G9cl+R<yZqf z9af~SuB;h(yn92-;p*{htK#Sx#*r~41An|R<KVE@r>-Ttks1c<PC^B{_TQ+#Ra_i7 z=U>#PF8d#x^C%~G6ji&thb2=ER7OmTvk7t=(Oz}DV{%dsOPW<=T$Ah_xv|=R$-GJ{ z@qE9Or$eu~PITs9ToI62GiaBu_R6S;JWul@f;qdh3j;!{T?ScEc&81%erk9n)o<3r zGpEhpH#zLmq^zwmK`E=6YG0)<`x)L&jT|MSt0$B(?MCLE`^Bg2j^(k89W(NgXQpKv zjBlkdvd7FWa~|68Q{Z8%ip@8~^^se*j+vS<VVHCDTvv(5ylIQ(Eaj?D`x_k3yo=CQ z6W3`ezgO=YSaZhVb^ZVi$uP@s(Xg#zgP2sq$75%wNLD==Bwt!}xqjIE7^I3m<z`8a z^WX@_pbe`_jY^8NXSRe5;%9G)spUWWhpKLy*Zug$%^lM_OC}YB?Q=C6@lO+H7jxn2 z;F!7zD?GEm;*XBbrFM_pc4}n6i4B9Zh9^#R$j|0)j6M)>>sjW6s!gU>ciya9Nz3z0 zoA5(%L3mH$uc?zcwbu*n*5%5JyR35$-t_m_t=)d~Me*Bjj<(*sR(w0VE%t*8CwF(t zw(BbM^2mLu`<87j*<6-4YM>YyymGmn!LZ!r(vUMD-&9*%KqW<{%iX;d^MhpeMuX(z zVmEVNeD%vp%O@XZ^1f~o@;)4|-eq@>wywOfJwL=IBX7U`q2d$HySc$huY^-OWlNlt zL5J67+ajZfoG3jwBE!e4tu`#g=Roz#+V*9V0o$5tPT0EKomOPou+&cB9hyz8n62?C z*V<OT7<+H(yTwfng_mruulKn0!px-9Yaw(r$8Dj=Cuv%XZ4SS%{rvffDV?V_bSv&R zyV=xlu&Ox;P1_V2IX1gIHeh1q^v8dsS++rse;&*`IY8Wy`J*ytTXW29tqnRMdv4w3 zA(P^b3b>)0Zrv<d-|k<%$6Kbp?KS0C?p|jL_0{Ej>dK3P-xR*x-}$t*jp@IC%2R43 z8ug$fmlRc1T*R@-NMmyDKs}zFl#Jq6A}vcIy;g`SCkBfbSO>Jd@%I~o&P}LV(0EG8 z{5GWZ+T6nFAr1E~`0n*w9~QaERmj=<Tya4=rYogp&GjQ%MgIMcCLh~z1&Px$cPXL^ zDiXSFd07KCMqZtC2~948ZP%~(sk#2{yU;s9&fMB8?H^t-lWKyl<h7QrG(NgCb%ezn z#o4yt7IsIcz)5@0tD+%zXXVZa$B^{Yq|89+tcv=thKJ5^a%m}9ep*CHj%|E&AXMyk zt!we6>%)J2Ube0wvTR*~>kkW(azgDBNTW~It{8Fodu4h}dt>0mMXlzj-ODuIiN-5t z^)1i+Ys`){KTKR0?Qgb^GBMtE`;C^tA8h9}TfPhA9pXTc!4jFPtFO@2mAJ{k{k176 z%gOWPjIpQZ1+3ck^`KQN93+L_v3^6V{7;jE?d8jYY-Um4FaFj-xN_C@hasw0;*y4k zbwzuY>>-&Xr#MV=m~_-Lt;frh67J~mvZ{PRMtNMy<wAN*(@MkL(owtOXPti<bo%A& zR(RxZB*S5>Hn&8^fJ-gfAs{QV<GHtYw``wxcBA>Lv{QZsW2{?@TAB)WXzow6ELodx zwPm=^Xw<pRqxc;4cnnoA_0{>zEa8RW%U7HZH$G=`erD=SN7u1IfoonbD>`TTjB+t@ zM`cLIW19KX(sk?`vUI!j3F9-DnvCLP`z=~#vUl{PZ~YJ2zIl})_%Qy6M7{3!GbJgL z13lAi-wjEQi?S}*c{e}I+@#`WdzHiGV`l8eL+_KK?_3!ETaWpVGWo(%gY!vi=PIKf zjSCAKQ&y&kdi{;+$bi+3&)3@V*KR5BwTGG`T1EV@dh7asXck1h_@mX}jPLAoyx)Ge zqx<DIX*1$F(DwG`oS=o@xm&BVrMYdT;Dr+_122|f(JX;jDW}2`WjI2Om#e^w2Z9{G zi&w$oC<G;iBM~x%6S=wkIGH4qIFV;_M0AnL6`3#dOjIKQiQa+Y#3(UeLjG>LsbjnV z5Xcb}CdJF66&gXj6B*|ffHr2Pkx4iNjdCIfi+oA0N;N`aQ`uBH#XVjY%Op=XB{`}k zQh~qQ_q`OL=R}^5qACH678e&sjbl-j>IfQx&*#(VOd69(0SJmFL4m^Y6oqCSMxo<y zLo{NwOohsn3KGT%hby(H6PXOgNko2fl}OY_uh8_W0Q8{6!zvnsN~g)?G<^>Z>K+S7 zdK3Cf4^1F=KhyjXjZ&)?Bkr+?0v)GMArbfatF-E9d^!>_4T(nN0IC5|8T~?f2t~eq z9+(6XGPw%(0%G?=qB7}6vHInPjo{PKPXxI4@%BR#bH~8|B@zkTlwvKGp3u#SjKvp7 zlwz4gfHx6DEaf=RVG5naW>eS*k4fQk9at2mgIJ7kSqLKG()Fl>3JnS?#0W+O$f+{G zBjt&u^zd*dg^9pi3Y#TmQyjPm0w_2f29qu2aK(H*3Lmu$>`FLVKP!w%0;t02bQZ#A zaVUH#pHE?Pcnk_0E@4r`bf$#EWs12>4vbSt#DedYYB>y+QznNa5SmI6fe&DU3!Ht0 zPGlxkmpE?mjfPPvZ~$jOrjRJ(G#|l%GC2}}!kC^69*fCjvAIkpht6X#xF115h*|^o zBF4&~Q(3wZY+(doIzU<&+o^y6_W-jIxT+BtRjLD(%4jDtmI4X$>>Cz=10{h`*bPPz zKuTw_1q_CO$p~cd1q_~m&ZN*e0=gbvDUnGN{u>%QJ|suoqI=3TAbtXF(w(UQBu3ZM zb)#kYVIq<6V<CXWx+!SjSVV&73Al7a;`y*50s;3&?}jDpvcK32Y#zcC^Wbobn2Bu$ zJ}jm1d3>0{4|fP>iKSd7B4PDs*C?fE9IQs1BY=)TE3iRvtw{F0OEsxKK5jmOtpkvZ z!eCJJBqP&$CriU_3}Uv9v_I+Lhy(Pl7~rR~fvXGLgtWe^uvaha()k-p?>hXA5dig< zAfKi07rDO3^;rsh7Wm8V`Xbk7Dezg~FT3miCYR~Qk10d}{sM{vpGxXP=sx(&G79(d zaD#fVpRLDs{sb(8Ri1M+5M(wCdkn7LOMVB8#;8!_Zd`9>4GlF+JLG8x{wX*{=;j>g zFx0?mVDnq32NVFqi-CawggyUj>F)0CF~q?7Bp4q-^eLHszpJaO=fj5&;L{#NBnSuq zQR`=d+4Sw5ot=2*hQtgAlHQE^fe9i4i$y1F_!Ni^NC_X%k3@`p>P%#W6BrsA_9;hX zLOAG?VUaOA_81!*<34>E0H8hz9+)r@HD<)xCMG6*SiC_1df9c;*hD0+tGniQ;|(Hm z-zeeSX8;X@RZp-~`xR)TZogo7;?eiP+c=rJqNk#wqMtL-AxJPVLDHwepV<C`0T0qU z28f}41ek#+_4V~c^G`KKLSPMvR6a%3)YL#79UY&V@jl^<b%4K)ji_-1ro&9U1(8T3 z$lBT(vfO0>K?neUQu+)S0kIP?jDhA@KWNVy*S<a;6~hpGz0pBty3#k$=b~#6<5*2# pevYrKKJos689-Pf!9uA>1Wg8QlU~=W0oX+Y3EjQjie17M{~KltvSk1O literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/parameter_static/gSun.rgba32.png b/soh/assets/custom/textures/parameter_static/gSun.rgba32.png new file mode 100644 index 0000000000000000000000000000000000000000..954726e0580b287195b4dc623f6d52abda68a635 GIT binary patch literal 6448 zcmeHKX;f3!7QR6S#R&ncqLdf~rJ8w;gn}dtYJfsCP^)s2+(48JCV?Qxvxro1#sLwj zVnr;2)=I@9pdctXf>x*#&VWN5KmiAocWxjM`r7xFYrX#SWZiqt+56ky+2=b$l9WJy zpW)UH)(`{@_w(fif!YRr23vx+)5~rcf-Dxt3PW^3upX<{sATd;1gl%7MzBbXTn0fg z*AIk*rahQCtgFRdYd)E=bV5UCv!%9c$Y(RY_ZLNpYO@zPZ04Jf+MG4($chio9ut?R zm(6RiXuTA-e&c$EW+wmD+w3<kik7(UI-jNk3%++;=aP82VE4Vw*L%NzwbOalkHu>z zx|U2jq34x6J$IpQVa+h!x>=3i-D5~&qUso%8j60|XnSyejbdB-)s%vt9Ef%~Pk*a< ze{^`*PaK*<v#chfbbag4Z^tdlpEJ|yg1*Y5G<?AenH|&CrmgC?Hx;aUE8#oVL&3H} z@7kx252iJ7t8V&sgul6Zu!fsY$vsgJiTwV$Y(eITp_kUbZ+%)eYj@mf!shm@>(2#_ z^LNnKoeL39$6MFAMaI6~lr<rsYSN3xX7zal&V5(=l!>A#v$xqsEiRlcgf3}<Cj`QT zNZH=>^3=8C-d<}BY=NAo>7>Cqe>A*ENoqd))fl?SuHc&?UOU3pk(#PEzJ0Xnmd{ih zIlI`5(Co<w8`gAsd}Y?)c0t}wbEn$(R2@CAZg`qcGS6n`_LM&!ZX0sm{(4xJSMkZD znT?hnqtc?G#F|6q^);-v>_J+rS*lrrZPui3SzZ{;hG`y$`7xg3@BU27G0*V2M$Q<0 zJ@tInD(Wrsh{TY@kOt1{fJ0_Zvo5lpWWFS@mR@pJm9}4ubL#S4<C-2eS6#8%W^&c0 zs^rmA7OqU@`K9jlysW!aZR318-L_%Qp-j>Y*kjg?!ZVB++u}!rYR>1D$FIR3d~LgC zYe-Pj;xF2K+UdgFpL4v2AG{K&y>PTH`&1g|n*-zP75c``x_#BV{OgMfoN7l3_a1Nv z*mt^Io%daX%?LZ%<&^Omo}_tcSuta6%l9mc$Vn<_+H<pRj*qvHW$DYL<<smFR~C&b z@n0RiX8R9b#ogIEtvdwF55Y}WHa%N?HvVx(_ScTpfjib5m^vYQapJ=#6)tI2#l=C$ zmC5V1s%?2YOG^Z~$8Jc}m-gMXS|Q5Yzd?UL{K*ZR9(p{a;(6AbMvep1rsEWzmpRQp zfNQl@Rw&zc*7;y)<C+PLKJr;h@`I2496N5Nb{}`j63MeI7wH-cOO2p<*zRxaR@%pD zbV)-xcScF4X3*o)d_;!_ufLYOwL}p&IzIV*h~HUi;i5B96N3{jGz1VX7q3@LS+Z)_ ziLUC;8DDoSu{}I?_k_m%qUPIe2}5VLuOGA^)q&R>WH;o8oX~)Ki)eXz_l=jU`SXuj zxZdYej@UG8v=wt)Rkrnu57xLI-dU^M`B_%FI`&tKsSk;Vat9^Owkm0@Tyc4&sC32{ zzwsgT$#w}DH76hWHjiBXQtf+F*v8Jf=)8cx@BzK(GxxZoP7f6}%*PMY#?a`DW0m>* zU*nkZ!5*(F9DLtD&@Ihn>~K-uogKTm^CWhAS^g|?+jWn%talTictZ+Cw5RMg#jj%7 z@j;I4-3#yD*5?;}?sA24Z7JrJK3wAy5tDm4MqW4l#w53|NzX_HyB?LTx}KVq{opy2 zzX<!m^2H2w6t*+Y{rG9(cK`j6zs&y{jtg*h4M_YV@RyCFI?{8F`<qSkI_8)>dc_e( z?3x8PzQB&$e?O18`}oy8Z-;dW*h+iW22t#>KYo04A>rrnzzv6j7FE~3^Mu<vj+%eZ zo98HMuRJ5vj(t_}tk^SDc+X?8yrqFu8W*RVk}{2-JAcDl_kx9Gzjt|$F7^<NT<)AP zmvgB}-4t~3x7K52qMZ3<)@Sb8wK$avf8V<Jbdus_GPSuebl36+L3u}ntP!sIVv8zA zr_=YY^Urb3?$;Jg2?!cl@pA6CuCq0t|6WtMKytJ3@tF4~%GQCC-d!75&ee8R-dQxe zmHKY@$si5{VOGh#yaN5ayo|RlxN9@xQ@OsCf%ZuO!TWxgYc(U8#rx4e`m0gZL8ovb zQx!?`9Oo>2Yb9{lY(K`Q;>evlwc`4UQ=uX&k*7@;W@)rKNSA8+e6}@Sy!=IsQ%jll z*G_kj2x0o-Xg+3c;X0w4i%gp@zB4+0FlKCddet0m>caEo+W5xG>e`aQwQc|EY<Vnd za~ZT8w{+{H@A##jZYA<ZnVl(K1(RK?TB^2Kj`r=UiMrOryvSc|v1=TKlDkZND<R~M zu;RqfGl41L$(3vJzB;}sD)esYsn7#gLh}7@!K9xKWEcC#*)N?wF<~;V=Eptjtf%uH zUhyTT{_rk+^@^(2DQBFw<PY=SU?JQyQ`2>4#f!Ki86107V14@AXJc-B7;9x#;!&u) zal5*x(GAm8TfVKKLo~kp=9EY6VEdX`9!*&Lq{!ttX8Vlt7h4G9HcxsZADU$L;$Pmk zw+{MFnQ)7)S00GVbce=e)VB>+s|U}qca3Y@`+V2M;`i@z=qH@MJ+3KmzjAIn_;!qz zgKxnQ!5of6r69mkl^7w!DAeFv5`x^mj8VgqC5R3yM#AMvF7A2B2^>}~<>Ewi0ZE|t zLL%h8u^J>e)?X-zT_RyiabLPyyTxz-fdbLN*ce5mQp<_q;taeT&_>Nf9M%BQE#cxq z1c6vDl?K7m2s8o-&ySHuQ*iFqST~JS#tGti_fmi!7Z;(^sX0WVUau$UsRWfKoJeM~ z*+deBNTJ{X0<T@B)WI=$rFIfZ(Zj(*v=WV6t&^*iSd<eMtD<yV91i%g#{3j&fuN6G zsqIw(=s}Eu)kHFZL{un<rV&~lKN^tqCiIsPS|Ru`K@38)swj;F;YTA%-6T^AsiZGn z9i@phOh+mqB9Vv!K(%00@_-?I`~-o05vT;=a)sIu1;ieJ)X8Q2VhzX*^%$mOng|H* z;~juD&fNe8D1m^(Q%R!G^!#{S96CNns*=d197B`NVo6wHiWo0u!3ds464UWw29u5_ zvB_d8LINK$Y(nLy)aqcR1VO0)IYAD1NQjgUvnUcglR}o_X><u4&yta8co|*HmeFBE z#$vEcC;~Kcuq)w6)2vV`DWH;x=?sJ_mEhS_Diu$YGGV-!MrGki5(<ONlrSX>3Ee;? zm2kXO8U+lNQ?7u+5u#cdZg8N2b36n6xHt-d)Nculgmp3y0M3A1DOKsU{Vt(gfduPd zR8KOKN+B`GY!aJFX42S{e$YHbqXl~rWhIjcREEKWE(`}u2S^K}I~5QZ>|iz=FAW0g zR2rd570Jb+Nnz2*KDPiIC@HLid9V%vq$CQBLnd>`Y$2J=A+tCXHl9T1kWBC@sa&?~ zf1%OigLUg!bYHm^jK9oa>N!)v$kLu(Pd8F-I80cq;aG5BNzW9ta5N${<O#TXT#^V_ z8IFMaqj$p^?ef3a3=9cNMiDbfc!bK5;b|<Gj%Q0KGCV?~Au<M?L1MCL1KG7InNAOD z5YKR+BhU(LP=i+3sl7|(IuNgqK+tsnlHti@yoqEuV((;$=#62VtsC(_^l&o(Os*IZ z*JA@$7q|(DeOF<xUg)Ls50>6__y<P-)Sm|VD1AT4^+~ReQsAS&pLW+LxjssPj{<+% zUH><^to#2=AxiKINDuxh@#+?m!QU)P@oXO+)Qx_!%Jy#omLY22P%Q)vwL>2al#w|W z7_D@E0>0J5q4toiV^YSgOb9X`@5l2LvPNNS%%8u*eCW;wsGd@B?i=V!dVk+&|8tGv z(1K#kjGaG&Fx{oy{kE$n?S3oTGB+L3gBI2ekeGhRUj-U$eHin8Fa(vK&%$`nfGD7J zV<td1Zmlx7opH-SZ6ur87mPXw5E#(lb^Uf0G=7|;;X!R3oqG%}>miE_wdu>u*y(zo z+l@}a7>wGjtS0t7XupT(YWJ7)<$anASOrwL_Sa=7)(~ip!5P}`K0Jjmm{#b`o7)hY zMa8*QebX3_0Xn*AL3QZH@E{8_uro}GF$2Rgn%JS{r=~ry9NiCq;p#x+pLzqPfa-Aj zZegEzs0PM@rjM5YIt3J9ngtqUd{AFg%Y8#usMu&9Eqxl84-#QcT`a`Rpa`IISMD3Y zJ&>L^8tgJL4AlgK?iZu)FZTgTf~sD1;iLhF_FX1=8Dj?20|?xx?%h=v3Nfg<s2*sb zv7jTPZPX5`z6>xY&Ke;D>mIU`2B2wsAPO-39l@W0f7i!q_P?r7o96@n2qeT$CJ;bh XfcD^C{N-TuqJjMQ{=9=T!&d$q;WOf= literal 0 HcmV?d00001 diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h index c0acacf21..568a87963 100644 --- a/soh/assets/soh_assets.h +++ b/soh/assets/soh_assets.h @@ -106,6 +106,15 @@ static const ALIGN_ASSET(2) char gSplitEntranceTex[] = dgSplitEntrance; #define dgBossSoul "__OTR__textures/parameter_static/gBossSoul" static const ALIGN_ASSET(2) char gBossSoulTex[] = dgBossSoul; +#define dgMoonIcon "__OTR__textures/parameter_static/gMoon" +static const ALIGN_ASSET(2) char gMoonIconTex[] = dgMoonIcon; + +#define dgSunIcon "__OTR__textures/parameter_static/gSun" +static const ALIGN_ASSET(2) char gSunIconTex[] = dgSunIcon; + +#define dgNaviIcon "__OTR__textures/parameter_static/gNavi" +static const ALIGN_ASSET(2) char gNaviIconTex[] = dgNaviIcon; + #define dgFileSelMQButtonTex "__OTR__textures/title_static/gFileSelMQButtonTex" static const ALIGN_ASSET(2) char gFileSelMQButtonTex[] = dgFileSelMQButtonTex; diff --git a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp new file mode 100644 index 000000000..cb9dfbb46 --- /dev/null +++ b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.cpp @@ -0,0 +1,262 @@ +#include "TimeDisplay.h" +#include "soh/Enhancements/gameplaystats.h" +#include <global.h> + +#include "assets/textures/parameter_static/parameter_static.h" +#include "assets/soh_assets.h" +#include "soh/ImGuiUtils.h" + +extern "C" { +#include "macros.h" +#include "functions.h" +#include "variables.h" +extern PlayState* gPlayState; +uint64_t GetUnixTimestamp(); +} + +float fontScale = 1.0f; +std::string timeDisplayTime = ""; +ImTextureID textureDisplay = 0; +ImVec4 windowBG = ImVec4(0, 0, 0, 0.5f); +ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + +// ImVec4 Colors +#define COLOR_WHITE ImVec4(1.0f, 1.0f, 1.0f, 1.0f) +#define COLOR_LIGHT_RED ImVec4(1.0f, 0.05f, 0, 1.0f) +#define COLOR_LIGHT_BLUE ImVec4(0, 0.88f, 1.0f, 1.0f) +#define COLOR_LIGHT_GREEN ImVec4(0.52f, 1.0f, 0.23f, 1.0f) +#define COLOR_GREY ImVec4(0.78f, 0.78f, 0.78f, 1.0f) + +const static std::vector<std::pair<std::string, const char*>> digitList = { + { "DIGIT_0_TEXTURE", gCounterDigit0Tex }, { "DIGIT_1_TEXTURE", gCounterDigit1Tex }, + { "DIGIT_2_TEXTURE", gCounterDigit2Tex }, { "DIGIT_3_TEXTURE", gCounterDigit3Tex }, + { "DIGIT_4_TEXTURE", gCounterDigit4Tex }, { "DIGIT_5_TEXTURE", gCounterDigit5Tex }, + { "DIGIT_6_TEXTURE", gCounterDigit6Tex }, { "DIGIT_7_TEXTURE", gCounterDigit7Tex }, + { "DIGIT_8_TEXTURE", gCounterDigit8Tex }, { "DIGIT_9_TEXTURE", gCounterDigit9Tex }, + { "COLON_TEXTURE", gCounterColonTex }, +}; + +const std::vector<TimeObject> timeDisplayList = { + { DISPLAY_IN_GAME_TIMER, "Display Gameplay Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.InGameTimer") }, + { DISPLAY_TIME_OF_DAY, "Display Time of Day", CVAR_ENHANCEMENT("TimeDisplay.Timers.TimeofDay") }, + { DISPLAY_CONDITIONAL_TIMER, "Display Conditional Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.HotWater") }, + { DISPLAY_NAVI_TIMER, "Display Navi Timer", CVAR_ENHANCEMENT("TimeDisplay.Timers.NaviTimer") } +}; + +static std::vector<TimeObject> activeTimers; + +std::string convertDayTime(uint32_t dayTime) { + uint32_t totalSeconds = 24 * 60 * 60; + uint32_t ss = static_cast<uint32_t>(static_cast<double>(dayTime) * (totalSeconds - 1) / 65535); + uint32_t hh = ss / 3600; + uint32_t mm = (ss % 3600) / 60; + return fmt::format("{:0>2}:{:0>2}", hh, mm); +} + +std::string convertNaviTime(uint32_t value) { + uint32_t totalSeconds = value * 0.05; + uint32_t ss = totalSeconds % 60; + uint32_t mm = totalSeconds / 60; + return fmt::format("{:0>2}:{:0>2}", mm, ss); +} + +std::string formatHotWaterDisplay(uint32_t value) { + uint32_t ss = value % 60; + uint32_t mm = value / 60; + return fmt::format("{:0>2}:{:0>2}", mm, ss); +} + +std::string formatTimeDisplay(uint32_t value) { + uint32_t sec = value / 10; + uint32_t hh = sec / 3600; + uint32_t mm = (sec - hh * 3600) / 60; + uint32_t ss = sec - hh * 3600 - mm * 60; + uint32_t ds = value % 10; + return fmt::format("{}:{:0>2}:{:0>2}.{}", hh, mm, ss, ds); +} + +static void TimeDisplayGetTimer(uint32_t timeID) { + timeDisplayTime = ""; + textureDisplay = 0; + textColor = COLOR_WHITE; + + Player* player = GET_PLAYER(gPlayState); + uint32_t timer1 = gSaveContext.timer1Value; + + switch (timeID) { + case DISPLAY_IN_GAME_TIMER: + textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("GAMEPLAY_TIMER"); + timeDisplayTime = formatTimeDisplay(GAMEPLAYSTAT_TOTAL_TIME).c_str(); + break; + case DISPLAY_TIME_OF_DAY: + if (gSaveContext.dayTime >= DAY_BEGINS && gSaveContext.dayTime < NIGHT_BEGINS) { + textureDisplay = + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("DAY_TIME_TIMER"); + } else { + textureDisplay = + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("NIGHT_TIME_TIMER"); + } + timeDisplayTime = convertDayTime(gSaveContext.dayTime).c_str(); + break; + case DISPLAY_CONDITIONAL_TIMER: + if (gSaveContext.timer1State > 0) { + timeDisplayTime = formatHotWaterDisplay(gSaveContext.timer1Value).c_str(); + textColor = + gSaveContext.timer1State <= 4 + ? (gPlayState->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_3 ? COLOR_LIGHT_RED + : COLOR_LIGHT_BLUE) + : COLOR_WHITE; + if (gSaveContext.timer1State <= 4) { + textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( + gPlayState->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_3 + ? itemMapping[ITEM_TUNIC_GORON].name + : itemMapping[ITEM_TUNIC_ZORA].name); + } + if (gSaveContext.timer1State >= 6) { + textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( + itemMapping[ITEM_SWORD_MASTER].name); + } + } else { + textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( + itemMapping[ITEM_TUNIC_KOKIRI].name); + timeDisplayTime = "-:--"; + } + break; + case DISPLAY_NAVI_TIMER: + if (gSaveContext.naviTimer <= NAVI_PREPARE) { + timeDisplayTime = convertNaviTime(NAVI_PREPARE - gSaveContext.naviTimer).c_str(); + } else if (gSaveContext.naviTimer <= NAVI_ACTIVE) { + timeDisplayTime = convertNaviTime(NAVI_ACTIVE - gSaveContext.naviTimer).c_str(); + textColor = COLOR_LIGHT_GREEN; + } else { + timeDisplayTime = convertNaviTime(NAVI_COOLDOWN - gSaveContext.naviTimer).c_str(); + textColor = COLOR_GREY; + } + textureDisplay = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("NAVI_TIMER"); + break; + default: + break; + } +} + +void TimeDisplayUpdateDisplayOptions() { + activeTimers.clear(); + for (auto& timer : timeDisplayList) { + if (CVarGetInteger(timer.timeEnable, 0)) { + activeTimers.push_back(timer); + } + } + + //if (pushBack) { + // activeTimers.push_back(timeDisplayList[timeID]); + //} else { + // uint32_t index = 0; + // for (auto& check : activeTimers) { + // if (check.timeID == timeID) { + // activeTimers.erase(activeTimers.begin() + index); + // return; + // } + // index++; + // } + //} +} + +void TimeDisplayWindow::Draw() { + if (!gPlayState) { + return; + } + if (!CVarGetInteger(CVAR_WINDOW("TimeDisplayEnabled"), 0)) { + return; + } + + ImGui::PushStyleColor(ImGuiCol_WindowBg, windowBG); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f); + + ImGui::Begin("TimerDisplay", nullptr, + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar); + ImGui::SetWindowFontScale(fontScale); + if (activeTimers.size() == 0) { + ImGui::Text("No Enabled Timers..."); + } else { + ImGui::BeginTable("Timer List", 2, ImGuiTableFlags_NoClip); + for (auto& timers : activeTimers) { + ImGui::PushID(timers.timeID); + TimeDisplayGetTimer(timers.timeID); + ImGui::TableNextColumn(); + ImGui::Image(textureDisplay, ImVec2(16.0f * fontScale, 16.0f * fontScale)); + ImGui::TableNextColumn(); + + if (timeDisplayTime != "-:--") { + char* textToDecode = new char[timeDisplayTime.size() + 1]; + textToDecode = std::strcpy(textToDecode, timeDisplayTime.c_str()); + size_t textLength = timeDisplayTime.length(); + uint16_t textureIndex = 0; + + for (size_t i = 0; i < textLength; i++) { + ImVec2 originalCursorPos = ImGui::GetCursorPos(); + if (textToDecode[i] == ':' || textToDecode[i] == '.') { + textureIndex = 10; + } else { + textureIndex = textToDecode[i] - '0'; + } + if (textToDecode[i] == '.') { + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + (8.0f * fontScale)); + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( + digitList[textureIndex].first), + ImVec2(8.0f * fontScale, 8.0f * fontScale), ImVec2(0, 0.5f), ImVec2(1, 1), + textColor, ImVec4(0, 0, 0, 0)); + } else { + ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( + digitList[textureIndex].first), + ImVec2(8.0f * fontScale, 16.0f * fontScale), ImVec2(0, 0), ImVec2(1, 1), textColor, + ImVec4(0, 0, 0, 0)); + } + ImGui::SameLine(0, 0); + } + } + ImGui::PopID(); + } + ImGui::EndTable(); + } + ImGui::End(); + + ImGui::PopStyleColor(2); + ImGui::PopStyleVar(1); +} + +void TimeDisplayInitSettings() { + fontScale = CVarGetFloat(CVAR_ENHANCEMENT("TimeDisplay.FontScale"), 1.0f); + if (fontScale < 1.0f) { + fontScale = 1.0f; + } + if (CVarGetInteger(CVAR_ENHANCEMENT("TimeDisplay.ShowWindowBG"), 0)) { + windowBG = ImVec4(0, 0, 0, 0); + } else { + windowBG = ImVec4(0, 0, 0, 0.5f); + } +} + +static void TimeDisplayInitTimers() { + for (auto& update : timeDisplayList) { + if (CVarGetInteger(update.timeEnable, 0)) { + activeTimers.push_back(update); + } + } +} + +void TimeDisplayWindow::InitElement() { + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("GAMEPLAY_TIMER", gClockIconTex, ImVec4(1, 1, 1, 1)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("DAY_TIME_TIMER", gSunIconTex, ImVec4(1, 1, 1, 1)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NIGHT_TIME_TIMER", gMoonIconTex, ImVec4(1, 1, 1, 1)); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("NAVI_TIMER", gNaviIconTex, ImVec4(1, 1, 1, 1)); + + for (auto& load : digitList) { + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(load.first.c_str(), load.second, ImVec4(1, 1, 1, 1)); + } + + TimeDisplayInitSettings(); + TimeDisplayInitTimers(); +} diff --git a/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h new file mode 100644 index 000000000..090ac2901 --- /dev/null +++ b/soh/soh/Enhancements/TimeDisplay/TimeDisplay.h @@ -0,0 +1,37 @@ +#include <libultraship/libultraship.h> + +class TimeDisplayWindow : public Ship::GuiWindow { + public: + using GuiWindow::GuiWindow; + + void InitElement() override; + void DrawElement() override {}; + void Draw() override; + void UpdateElement() override {}; +}; + +void TimeDisplayUpdateDisplayOptions(); +void TimeDisplayInitSettings(); + +typedef enum { + DISPLAY_IN_GAME_TIMER, + DISPLAY_TIME_OF_DAY, + DISPLAY_CONDITIONAL_TIMER, + DISPLAY_NAVI_TIMER +}; + +typedef enum { + NAVI_PREPARE = 600, + NAVI_ACTIVE = 3000, + NAVI_COOLDOWN = 25800, + DAY_BEGINS = 17759, + NIGHT_BEGINS = 49155 +}; + +typedef struct { + uint32_t timeID; + std::string timeLabel; + const char* timeEnable; +} TimeObject; + +extern const std::vector<TimeObject> timeDisplayList; \ No newline at end of file diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 19b8639de..2dbf62a99 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -38,6 +38,7 @@ #include "Enhancements/resolution-editor/ResolutionEditor.h" #include "Enhancements/debugger/MessageViewer.h" #include "soh/Notification/Notification.h" +#include "soh/Enhancements/TimeDisplay/TimeDisplay.h" bool isBetaQuestEnabled = false; @@ -136,6 +137,7 @@ namespace SohGui { std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow; std::shared_ptr<SohModalWindow> mModalWindow; std::shared_ptr<Notification::Window> mNotificationWindow; + std::shared_ptr<TimeDisplayWindow> mTimeDisplayWindow; void SetupGuiElements() { auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); @@ -221,6 +223,8 @@ namespace SohGui { mNotificationWindow = std::make_shared<Notification::Window>(CVAR_WINDOW("Notifications"), "Notifications Window"); gui->AddGuiWindow(mNotificationWindow); mNotificationWindow->Show(); + mTimeDisplayWindow = std::make_shared<TimeDisplayWindow>(CVAR_WINDOW("TimeDisplayEnabled"), "Additional Timers"); + gui->AddGuiWindow(mTimeDisplayWindow); } void Destroy() { @@ -256,6 +260,7 @@ namespace SohGui { mInputViewerSettings = nullptr; mTimeSplitWindow = nullptr; mPlandomizerWindow = nullptr; + mTimeDisplayWindow = nullptr; } void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function<void()> button1callback, std::function<void()> button2callback) { diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index cd9948092..a6cbd2d81 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -44,6 +44,7 @@ #include "Enhancements/enemyrandomizer.h" #include "Enhancements/timesplits/TimeSplits.h" #include "Enhancements/randomizer/Plandomizer.h" +#include "Enhancements/TimeDisplay/TimeDisplay.h" // FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but // they don't work how I expect them to so I added that because it looked good when I eyeballed it @@ -607,6 +608,7 @@ extern std::shared_ptr<AudioEditor> mAudioEditorWindow; extern std::shared_ptr<CosmeticsEditorWindow> mCosmeticsEditorWindow; extern std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow; extern std::shared_ptr<TimeSplitWindow> mTimeSplitWindow; +extern std::shared_ptr<TimeDisplayWindow> mTimeDisplayWindow; void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Enhancements")) @@ -1723,6 +1725,36 @@ void DrawEnhancementsMenu() { mTimeSplitWindow->ToggleVisibility(); } } + + if (mTimeDisplayWindow) { + if (ImGui::Button(GetWindowButtonText("Additional Timers", CVarGetInteger(CVAR_WINDOW("TimeDisplayEnabled"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + mTimeDisplayWindow->ToggleVisibility(); + } + } + if (mTimeDisplayWindow->IsVisible()) { + ImGui::SeparatorText("Timer Display Options"); + + if (!gPlayState) { + ImGui::Text("Additional Timer options\n" + "available when a file is\n" + "loaded..."); + } else { + if (UIWidgets::PaddedEnhancementSliderFloat("Font Scale: %.2fx", "##FontScale", CVAR_ENHANCEMENT("TimeDisplay.FontScale"), + 1.0f, 5.0f, "", 1.0f, false, true, false, true)) { + TimeDisplayInitSettings(); + } + if (UIWidgets::PaddedEnhancementCheckbox("Hide Background", CVAR_ENHANCEMENT("TimeDisplay.ShowWindowBG"), + false, false)) { + TimeDisplayInitSettings(); + } + ImGui::Separator(); + for (auto& timer : timeDisplayList) { + if (UIWidgets::PaddedEnhancementCheckbox(timer.timeLabel.c_str(), timer.timeEnable, false, false)) { + TimeDisplayUpdateDisplayOptions(); + } + } + } + } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 84c71c83b..d2c3e1a26 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -6070,7 +6070,7 @@ void Interface_Draw(PlayState* play) { svar5 = CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosX"), 0)+204+X_Margins_Timer; } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Timers.PosType"), 0) == 4) {//Hidden svar5 = -9999; - } + } } OVERLAY_DISP = From 291561667b36b5481a6d515d92855a1ce7b51b61 Mon Sep 17 00:00:00 2001 From: Garrett Cox <garrettjcox@gmail.com> Date: Tue, 3 Dec 2024 10:44:18 -0600 Subject: [PATCH 23/28] Update hook debugger to pull from GameInteractor ptrs rather than cloning the data every frame (#4609) --- soh/soh/Enhancements/debugger/hookDebugger.cpp | 12 +++++------- soh/soh/Enhancements/debugger/hookDebugger.h | 4 ++-- .../Enhancements/game-interactor/GameInteractor.h | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/debugger/hookDebugger.cpp b/soh/soh/Enhancements/debugger/hookDebugger.cpp index b31ddc396..8ee9b3391 100644 --- a/soh/soh/Enhancements/debugger/hookDebugger.cpp +++ b/soh/soh/Enhancements/debugger/hookDebugger.cpp @@ -4,14 +4,14 @@ #include <string> #include <version> -static std::unordered_map<const char*, std::unordered_map<HOOK_ID, HookInfo>> hookData; +static std::unordered_map<const char*, std::unordered_map<HOOK_ID, HookInfo>*> hookData; const ImVec4 grey = ImVec4(0.75, 0.75, 0.75, 1); const ImVec4 yellow = ImVec4(1, 1, 0, 1); const ImVec4 red = ImVec4(1, 0, 0, 1); void DrawHookRegisteringInfos(const char* hookName) { - if (hookData[hookName].size() == 0) { + if ((*hookData[hookName]).size() == 0) { ImGui::TextColored(grey, "No hooks found"); return; } @@ -27,7 +27,7 @@ void DrawHookRegisteringInfos(const char* hookName) { //ImGui::TableSetupColumn("Stub"); ImGui::TableSetupColumn("Number of Calls"); ImGui::TableHeadersRow(); - for (auto& [id, hookInfo] : hookData[hookName]) { + for (auto& [id, hookInfo] : (*hookData[hookName])) { ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -100,12 +100,10 @@ void HookDebuggerWindow::DrawElement() { } } -void HookDebuggerWindow::UpdateElement() { - hookData.clear(); - +void HookDebuggerWindow::InitElement() { #define DEFINE_HOOK(name, _) hookData.insert({#name, GameInteractor::Instance->GetHookData<GameInteractor::name>()}); #include "../game-interactor/GameInteractor_HookTable.h" #undef DEFINE_HOOK -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/debugger/hookDebugger.h b/soh/soh/Enhancements/debugger/hookDebugger.h index 90e6886b5..ae6f5113f 100644 --- a/soh/soh/Enhancements/debugger/hookDebugger.h +++ b/soh/soh/Enhancements/debugger/hookDebugger.h @@ -4,7 +4,7 @@ class HookDebuggerWindow : public Ship::GuiWindow { public: using GuiWindow::GuiWindow; - void InitElement() override {}; + void InitElement() override; void DrawElement() override; - void UpdateElement() override; + void UpdateElement() override {}; }; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 8b52b9b37..e73120501 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -641,8 +641,8 @@ public: inline static std::vector<HOOK_ID> hooksForFilter; }; - template <typename H> std::unordered_map<uint32_t, HookInfo> GetHookData() { - return RegisteredGameHooks<H>::hookData; + template <typename H> std::unordered_map<uint32_t, HookInfo>* GetHookData() { + return &RegisteredGameHooks<H>::hookData; } // General Hooks From b1d18526555ba09d1ed1511173a20676e9f33f08 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:44:36 +0000 Subject: [PATCH 24/28] Rewrite vanilla jabu logic (#4603) * rewrite vanilla jabu logic * cleanup * more cleanup --- .../locacc_jabujabus_belly.cpp | 160 +++++++++--------- soh/soh/Enhancements/randomizer/logic.cpp | 47 ++++- soh/soh/Enhancements/randomizer/logic.h | 3 + .../Enhancements/randomizer/randomizerTypes.h | 18 +- 4 files changed, 137 insertions(+), 91 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp index 55a25ac58..e2e5da9a4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_jabujabus_belly.cpp @@ -21,138 +21,140 @@ void RegionTable_Init_JabuJabusBelly() { if (ctx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla()) { areaTable[RR_JABU_JABUS_BELLY_BEGINNING] = Region("Jabu Jabus Belly Beginning", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return logic->CanUseProjectile();}}), + Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return logic->CanUseProjectile();}}), }); - areaTable[RR_JABU_JABUS_BELLY_LIFT_MIDDLE] = Region("Jabu Jabus Belly Lift Middle", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { +//Combines Lift room middle and lower, 1F holes room, the forked corridor, and it's side rooms + areaTable[RR_JABU_JABUS_BELLY_MAIN] = Region("Jabu Jabus Belly Main", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->JabuRutoInB1, {[]{return true;}}), + EventAccess(&logic->JabuWestTentacle, {[]{return logic->JabuRutoIn1F && logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}}), + }, { + //Locations + LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku()), + //We can kill the Stingers with ruto + LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, logic->JabuRutoIn1F), + LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->JabuWestTentacle), + }, { //Exits Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(RR_JABU_JABUS_BELLY_LIFT_UPPER) || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS));}}), - }); + Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_COMPASS_ROOM, {[]{return logic->JabuWestTentacle;}}), + Entrance(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, {[]{return logic->JabuWestTentacle;}}), + Entrance(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, {[]{return logic->JabuEastTentacle;}}), + Entrance(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, {[]{return logic->JabuNorthTentacle;}}), + Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return logic->LoweredJabuPath || (ctx->GetTrickOption(RT_JABU_BOSS_HOVER) && logic->CanUse(RG_HOVER_BOOTS));}}), + }); - areaTable[RR_JABU_JABUS_BELLY_MAIN_UPPER] = Region("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { - //Exits - Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_BIGOCTO_ROOM, {[]{return Here(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, []{return logic->CanUse(RG_BOOMERANG);});}}), - }); - - areaTable[RR_JABU_JABUS_BELLY_MAIN_LOWER] = Region("Jabu Jabus Belly Main Lower", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { +//contains B1 of hole room (aside from the ledge leading to big octo), 2 octorock room and north water switch room + areaTable[RR_JABU_JABUS_BELLY_B1_NORTH] = Region("Jabu Jabus Belly B1 North", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->JabuRutoIn1F, {[]{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}}), + EventAccess(&logic->FairyPot, {[]{return logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS);}}), + }, { //Locations LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, logic->HookshotOrBoomerang()), LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, logic->HookshotOrBoomerang()), - }, { + LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, logic->HookshotOrBoomerang()), + //PUT 2 OCTO ROOM POTS HERE + }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_LOWER_SIDE_ROOM, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return true;}}), + //there's tricks for getting here with bunny-jumps or just side-hops + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, {[]{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}}), }); - areaTable[RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR] = Region("Jabu Jabus Belly Shabomb Corridor", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { + areaTable[RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE] = Region("Jabu Jabus Belly Water Switch Room Ledge", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->FairyPot, {[]{return true;}}), }, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, true), + //this is the logic for climbing back and forth to use the pots to kill the skull... + LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, logic->HasItem(RG_BRONZE_SCALE) || + (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)) || + //or killing the skull before climbing to grab the token + logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), + //PUT WATER SWITCH POTS HERE }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return logic->HasItem(RG_BRONZE_SCALE);}}), - Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return logic->HasItem(RG_BRONZE_SCALE) && logic->CanUseProjectile();}}), + Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, {[]{return true;}}), }); - areaTable[RR_JABU_JABUS_BELLY_LOWER_SIDE_ROOM] = Region("Jabu Jabus Belly Lower Side Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { - //Events - EventAccess(&logic->FairyPot, {[]{return logic->FairyPot || (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_HOVER_BOOTS));}}), - }, {}, { - //Exits - Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}), - }); - - areaTable[RR_JABU_JABUS_BELLY_LIFT_LOWER] = Region("Jabu Jabus Belly Lift Lower", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { + areaTable[RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH] = Region("Jabu Jabus Belly Water Switch Room South", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_DEKU_SCRUB, logic->HasItem(RG_BRONZE_SCALE) && (logic->IsChild || logic->HasItem(RG_SILVER_SCALE) || ctx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE) || logic->CanUse(RG_IRON_BOOTS)) && logic->CanStunDeku()), + LOCATION(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, logic->HookshotOrBoomerang()), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), - }); - - areaTable[RR_JABU_JABUS_BELLY_FORKED_CORRIDOR] = Region("Jabu Jabus Belly Forked Corridor", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { - //Exits - Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_BOOMERANG_ROOM, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_MAP_ROOM, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_COMPASS_ROOM, {[]{return Here(RR_JABU_JABUS_BELLY_MAP_ROOM, []{return logic->CanUse(RG_BOOMERANG);});}}), - Entrance(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, {[]{return Here(RR_JABU_JABUS_BELLY_MAP_ROOM, []{return logic->CanUse(RG_BOOMERANG);});}}), - Entrance(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, {[]{return Here(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, []{return logic->CanUse(RG_BOOMERANG);});}}), - }); - - areaTable[RR_JABU_JABUS_BELLY_BOOMERANG_ROOM] = Region("Jabu Jabus Belly Boomerang Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { - //Locations - LOCATION(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, true), - }, { - //Exits - Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), - }); - - areaTable[RR_JABU_JABUS_BELLY_MAP_ROOM] = Region("Jabu Jabus Belly Map Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { - //Locations - LOCATION(RC_JABU_JABUS_BELLY_MAP_CHEST, logic->CanUse(RG_BOOMERANG)), - }, { - //Exits - Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, {[]{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, {[]{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return logic->CanUseProjectile();}}), }); areaTable[RR_JABU_JABUS_BELLY_COMPASS_ROOM] = Region("Jabu Jabus Belly Compass Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanAttack()), + //ruto could theoretically clear this room, but it's hard because of the timer and she doesn't appear with you when you respawn after failing, which would force a savewarp + LOCATION(RC_JABU_JABUS_BELLY_COMPASS_CHEST, logic->CanKillEnemy(RE_SHABOM)), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return Here(RR_JABU_JABUS_BELLY_COMPASS_ROOM, []{return logic->CanKillEnemy(RE_SHABOM);});}}), }); - areaTable[RR_JABU_JABUS_BELLY_BLUE_TENTACLE] = Region("Jabu Jabus Belly Blue Tentacle", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { + areaTable[RR_JABU_JABUS_BELLY_BLUE_TENTACLE] = Region("Jabu Jabus Belly Blue Tentacle", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { + EventAccess(&logic->JabuEastTentacle, {[]{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}}), + }, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, []{return logic->CanUse(RG_BOOMERANG);});}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return logic->JabuEastTentacle;}}), }); - areaTable[RR_JABU_JABUS_BELLY_GREEN_TENTACLE] = Region("Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { + areaTable[RR_JABU_JABUS_BELLY_GREEN_TENTACLE] = Region("Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { + EventAccess(&logic->JabuNorthTentacle, {[]{return logic->CanKillEnemy(RE_TENTACLE, ED_BOOMERANG);}}), + }, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, []{return logic->CanUse(RG_BOOMERANG);});}}), + //implied logic->CanKillEnemy(RE_BARI) + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return logic->JabuNorthTentacle;}}), }); - areaTable[RR_JABU_JABUS_BELLY_BIGOCTO_ROOM] = Region("Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { + areaTable[RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE] = Region("Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { + //Locations + //Only adult can get the token without assistance + LOCATION(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_SHORT_JUMPSLASH)), + //You can get the LOWER skull token from here as aduly with hovers backwalk and a backflip, but it's trickworthy and not relevant unless you can beat tentacles without rang + }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, {[]{return Here(RR_JABU_JABUS_BELLY_BIGOCTO_ROOM, []{return (logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_NUTS)) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_STICKS));});}}), + Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, {[]{return logic->JabuRutoIn1F && Here(RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, []{return logic->CanKillEnemy(RE_BIG_OCTO);});}}), }); areaTable[RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO] = Region("Jabu Jabus Belly Above Bigocto", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->FairyPot, {[]{return true;}}), EventAccess(&logic->NutPot, {[]{return true;}}), - }, {}, { + }, { + //Locations + //PUT AFTER OCTO POTS HERE + }, { //Exits Entrance(RR_JABU_JABUS_BELLY_LIFT_UPPER, {[]{return logic->CanUse(RG_BOOMERANG);}}), }); - areaTable[RR_JABU_JABUS_BELLY_LIFT_UPPER] = Region("Jabu Jabus Belly Lift Upper", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, { + areaTable[RR_JABU_JABUS_BELLY_LIFT_UPPER] = Region("Jabu Jabus Belly Lift Upper", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, { + //Events + EventAccess(&logic->LoweredJabuPath, {[]{return true;}}), + }, {}, { //Exits - Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return true;}}), }); areaTable[RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM] = Region("Jabu Jabus Belly Near Boss Room", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, { //Locations - LOCATION(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, logic->CanAttack()), + LOCATION(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}), - Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && ((logic->IsAdult && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW))) || (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)))) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG))));}}), + Entrance(RR_JABU_JABUS_BELLY_MAIN, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return logic->CanUse(RG_BOOMERANG) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT)) || (ctx->GetTrickOption(RT_JABU_NEAR_BOSS_EXPLOSIVES) && (logic->CanUse(RG_BOMBCHU_5) || (logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_BOMB_BAG))));}}), }); } @@ -205,7 +207,7 @@ void RegionTable_Init_JabuJabusBelly() { LOCATION(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, logic->CanUse(RG_FAIRY_SLINGSHOT)), }, { //Exits - Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}), + Entrance(RR_JABU_JABUS_BELLY_MQ_LIFT_ROOM, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_MQ_WATER_SWITCH_ROOM, {[]{return true;}}), Entrance(RR_JABU_JABUS_BELLY_MQ_FORKED_CORRIDOR, {[]{return logic->CanUse(RG_BOOMERANG) && logic->HasExplosives() && Here(RR_JABU_JABUS_BELLY_MQ_HOLES_ROOM, []{return logic->CanUse(RG_FAIRY_SLINGSHOT);});}}), Entrance(RR_JABU_JABUS_BELLY_MQ_INVISIBLE_KEESE_ROOM, {[]{return logic->JabuNorthTentacle;}}), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 1ef328496..da76be1d3 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -415,6 +415,38 @@ namespace Rando { bool killed = false; switch(enemy) { case RE_GOLD_SKULLTULA: + switch (distance){ + case ED_CLOSE: + //hammer jumpslash cannot damage these, but hammer swing can + killed = CanUse(RG_MEGATON_HAMMER); + [[fallthrough]]; + case ED_SHORT_JUMPSLASH: + killed = killed || CanUse(RG_KOKIRI_SWORD); + [[fallthrough]]; + case ED_MASTER_SWORD_JUMPSLASH: + killed = killed || CanUse(RG_MASTER_SWORD); + [[fallthrough]]; + case ED_LONG_JUMPSLASH: + killed = killed || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_STICKS); + [[fallthrough]]; + case ED_BOMB_THROW: + killed = killed || CanUse(RG_BOMB_BAG); + [[fallthrough]]; + case ED_BOOMERANG: + killed = killed || CanUse(RG_BOOMERANG) || CanUse(RG_DINS_FIRE); + [[fallthrough]]; + case ED_HOOKSHOT: + //RANDOTODO test dins and chu range in a practical example + killed = killed || CanUse(RG_HOOKSHOT) || (wallOrFloor && CanUse(RG_BOMBCHU_5)); + [[fallthrough]]; + case ED_LONGSHOT: + killed = killed || CanUse(RG_LONGSHOT); + [[fallthrough]]; + case ED_FAR: + killed = killed || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW); + break; + } + return killed; case RE_GOHMA_LARVA: case RE_MAD_SCRUB: case RE_DEKU_BABA: @@ -618,8 +650,15 @@ namespace Rando { case RE_PURPLE_LEEVER: //dies on it's own, so this is the conditions to spawn it (killing 10 normal leevers) //Sticks and Ice arrows work but will need ammo capacity logic - //other mothods can damage them but not kill them, and they run when hit, making them impractical - return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD); + //other methods can damage them but not kill them, and they run when hit, making them impractical + return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD); + case RE_TENTACLE: + return CanUse(RG_BOOMERANG); + case RE_BARI: + return HookshotOrBoomerang() || CanUse(RG_FAIRY_BOW) || HasExplosives() || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_STICKS) || CanUse(RG_DINS_FIRE) || (TakeDamage() && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))); + case RE_SHABOM: + //RANDOTODO when you add better damage logic, you can kill this by taking hits + return CanUse(RG_BOOMERANG) || CanUse(RG_NUTS) || CanJumpslash() || CanUse(RG_DINS_FIRE) || CanUse(RG_ICE_ARROWS); default: SPDLOG_ERROR("CanKillEnemy reached `default`."); assert(false); @@ -2145,6 +2184,7 @@ namespace Rando { GTGPlatformSilverRupees = false; MQJabuHolesRoomDoor = false; JabuWestTentacle = false; + JabuEastTentacle = false; JabuNorthTentacle = false; LoweredJabuPath = false; MQJabuLiftRoomCow = false; @@ -2158,6 +2198,9 @@ namespace Rando { MQSpiritCrawlBoulder = false; MQSpiritMapRoomEnemies = false; MQSpirit3SunsEnemies = false; + Spirit1FSilverRupees = false; + JabuRutoInB1 = false; + JabuRutoIn1F = false; StopPerformanceTimer(PT_LOGIC_RESET); } diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index de800c3bb..2fafd2cc7 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -156,6 +156,7 @@ class Logic { bool GTGPlatformSilverRupees = false; bool MQJabuHolesRoomDoor = false; bool JabuWestTentacle = false; + bool JabuEastTentacle = false; bool JabuNorthTentacle = false; bool LoweredJabuPath = false; bool MQJabuLiftRoomCow = false; @@ -171,6 +172,8 @@ class Logic { bool MQSpiritTimeTravelChest = false; bool MQSpirit3SunsEnemies = false; bool Spirit1FSilverRupees = false; + bool JabuRutoInB1 = false; + bool JabuRutoIn1F = false; /* --- END OF HELPERS AND LOCATION ACCESS --- */ diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index a910b043f..70a8e19d6 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -568,19 +568,14 @@ typedef enum { RR_DODONGOS_CAVERN_BOSS_ROOM, RR_JABU_JABUS_BELLY_BEGINNING, - RR_JABU_JABUS_BELLY_LIFT_MIDDLE, - RR_JABU_JABUS_BELLY_MAIN_UPPER, - RR_JABU_JABUS_BELLY_MAIN_LOWER, - RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, - RR_JABU_JABUS_BELLY_LOWER_SIDE_ROOM, - RR_JABU_JABUS_BELLY_LIFT_LOWER, - RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, - RR_JABU_JABUS_BELLY_BOOMERANG_ROOM, - RR_JABU_JABUS_BELLY_MAP_ROOM, + RR_JABU_JABUS_BELLY_MAIN, + RR_JABU_JABUS_BELLY_B1_NORTH, + RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, + RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, RR_JABU_JABUS_BELLY_COMPASS_ROOM, RR_JABU_JABUS_BELLY_BLUE_TENTACLE, RR_JABU_JABUS_BELLY_GREEN_TENTACLE, - RR_JABU_JABUS_BELLY_BIGOCTO_ROOM, + RR_JABU_JABUS_BELLY_BIGOCTO_LEDGE, RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, RR_JABU_JABUS_BELLY_LIFT_UPPER, RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, @@ -4638,6 +4633,9 @@ typedef enum { RE_BEAMOS, RE_WALLMASTER, RE_PURPLE_LEEVER, + RE_TENTACLE, + RE_BARI, + RE_SHABOM, } RandomizerEnemy; //RANDOTODO compare child long jumpslash range with adult short From b442c15322dbd22c50c4582c7400f7e8f37b8717 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Tue, 3 Dec 2024 19:30:14 +0000 Subject: [PATCH 25/28] Skip Shadow Statue Cutscene (#4612) * Skip Shadow Statue Cutscene * cleanup --- soh/soh/Enhancements/timesaver_hook_handlers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index c271b6cb3..d9c13ed92 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -289,7 +289,8 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li case ACTOR_BG_HIDAN_FWBIG: case ACTOR_EN_EX_ITEM: case ACTOR_EN_DNT_NOMAL: - case ACTOR_EN_DNT_DEMO: { + case ACTOR_EN_DNT_DEMO: + case ACTOR_BG_HAKA_ZOU: { *should = false; break; } From 9b169af3f561f768c204400e535f54ff4ab2205b Mon Sep 17 00:00:00 2001 From: Archez <Archez@users.noreply.github.com> Date: Wed, 4 Dec 2024 13:01:08 -0500 Subject: [PATCH 26/28] Fix find newline looping to have additional break early cases (#4614) --- .../custom-message/CustomMessageManager.cpp | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 2695cd3ef..4d4d27b3f 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -376,56 +376,62 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin } } - size_t CustomMessage::FindNEWLINE(std::string& str, size_t lastNewline) const { size_t newLine = str.find(NEWLINE()[0], lastNewline); bool done; + + // Bail out early + if (newLine == std::string::npos) { + return newLine; + } + do { done = true; - if (newLine != 0){ - switch (str[newLine - 1]){ - case '\x05'://COLOR - case '\x06'://SHIFT - case '\x07'://TEXTID - case '\x0C'://BOX_BREAK_DELAYED - case '\x0E'://FADE - case '\x11'://FADE2 - case '\x12'://SFX - case '\x13'://ITEM_ICON - case '\x14'://TEXT_SPEED - case '\x15'://BACKGROUND - case '\x1E'://POINTS/HIGH_SCORE + if (newLine != 0) { + switch (str[newLine - 1]) { + case '\x05': // COLOR + case '\x06': // SHIFT + case '\x07': // TEXTID + case '\x0C': // BOX_BREAK_DELAYED + case '\x0E': // FADE + case '\x11': // FADE2 + case '\x12': // SFX + case '\x13': // ITEM_ICON + case '\x14': // TEXT_SPEED + case '\x15': // BACKGROUND + case '\x1E': // POINTS/HIGH_SCORE done = false; break; default: break; } - if (newLine > 1){ - switch (str[newLine - 2]){ - case '\x07'://TEXTID - case '\x11'://FADE2 - case '\x12'://SFX - case '\x15'://BACKGROUND + if (newLine > 1) { + switch (str[newLine - 2]) { + case '\x07': // TEXTID + case '\x11': // FADE2 + case '\x12': // SFX + case '\x15': // BACKGROUND done = false; break; default: break; } - if (newLine > 2){ - if (str[newLine - 3] == '\x15'){//BACKGROUND + if (newLine > 2) { + if (str[newLine - 3] == '\x15') { // BACKGROUND done = false; } } } } - if (!done){ + if (!done) { newLine = str.find(NEWLINE()[0], newLine + 1); - if (newLine != std::string::npos){ - //if we reach the end of the string, quit now to save a loop + if (newLine == std::string::npos) { + // if we reach the end of the string, quit now to save a loop done = true; } } } while (!done); + return newLine; } From c3e4579cbad81d067d9176de29e3cf7d65652003 Mon Sep 17 00:00:00 2001 From: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:01:25 +0000 Subject: [PATCH 27/28] Change GetSelectedOptionText to contextSelection and clean up some junk (#4613) * Change GetSelectedOptionText to contextSelection and clean up some junk * more cleanup * readd a fail alert as an assert --- .../Enhancements/randomizer/3drando/fill.cpp | 5 - .../randomizer/3drando/playthrough.cpp | 8 -- .../randomizer/3drando/spoiler_log.cpp | 128 +----------------- soh/soh/Enhancements/randomizer/entrance.cpp | 7 +- soh/soh/Enhancements/randomizer/option.cpp | 4 +- 5 files changed, 10 insertions(+), 142 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 93501b8fe..e7a6ce38b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -856,11 +856,6 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect SPDLOG_DEBUG(Rando::StaticData::RetrieveItem(item).GetName().GetEnglish()); SPDLOG_DEBUG(". TRYING AGAIN...\n"); -#ifdef ENABLE_DEBUG - Regions::DumpWorldGraph(Rando::StaticData::RetrieveItem(item).GetName().GetEnglish()); - PlacementLog_Write(); -#endif - // reset any locations that got an item for (RandomizerCheck loc : attemptedLocations) { ctx->GetItemLocation(loc)->SetPlacedItem(RG_NONE); diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index e789b16cf..53b02e036 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -80,14 +80,6 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations, SPDLOG_ERROR("Writing Spoiler Log Failed"); } StopPerformanceTimer(PT_SPOILER_LOG); -#ifdef ENABLE_DEBUG - SPDLOG_INFO("Writing Placement Log..."); - if (PlacementLog_Write()) { - SPDLOG_INFO("Writing Placement Log Done"); - } else { - SPDLOG_ERROR("Writing Placement Log Failed"); - } -#endif } ctx->playthroughLocations.clear(); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index fb77fd97f..a665c4eea 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -6,7 +6,6 @@ #include "../entrance.h" #include "random.hpp" #include "../trial.h" -#include "tinyxml2.h" #include "utils.hpp" #include "hints.hpp" #include "pool_functions.hpp" @@ -56,9 +55,6 @@ void GenerateHash() { int number = std::stoi(hash.substr(j, 2)); ctx->hashIconIndexes[i] = number; } - - // Clear out spoiler log data here, in case we aren't going to re-generate it - // spoilerData = { 0 }; } static auto GetGeneralPath() { @@ -79,7 +75,6 @@ static void WriteLocation( Rando::Location* location = Rando::StaticData::GetLocation(locationKey); Rando::ItemLocation* itemLocation = Rando::Context::GetInstance()->GetItemLocation(locationKey); - // auto node = parentNode->InsertNewChildElement("location"); switch (gSaveContext.language) { case LANGUAGE_ENG: default: @@ -89,35 +84,6 @@ static void WriteLocation( jsonData["playthrough"][sphere][location->GetName()] = itemLocation->GetPlacedItemName().GetFrench(); break; } - // node->SetAttribute("name", location->GetName().c_str()); - // node->SetText(location->GetPlacedItemName().GetEnglish().c_str()); - - // if (withPadding) { - // constexpr int16_t LONGEST_NAME = 56; // The longest name of a location. - // constexpr int16_t PRICE_ATTRIBUTE = 12; // Length of a 3-digit price attribute. - - // // Insert a padding so we get a kind of table in the XML document. - // int16_t requiredPadding = LONGEST_NAME - location->GetName().length(); - // if (location->GetRCType() == RCTYPE_SHOP) { - // // Shop items have short location names, but come with an additional price attribute. - // requiredPadding -= PRICE_ATTRIBUTE; - // } - // if (requiredPadding >= 0) { - // std::string padding(requiredPadding, ' '); - // node->SetAttribute("_", padding.c_str()); - // } - // } - - // if (location->GetRCType() == RCTYPE_SHOP) { - // char price[6]; - // sprintf(price, "%03d", location->GetPrice()); - // node->SetAttribute("price", price); - // } - // if (!location->IsAddedToPool()) { - // #ifdef ENABLE_DEBUG - // node->SetAttribute("not-added", true); - // #endif - // } } //Writes a shuffled entrance to the specified node @@ -186,7 +152,6 @@ static void WriteSettings() { // Writes the excluded locations to the spoiler log, if there are any. static void WriteExcludedLocations() { - // auto parentNode = spoilerLog.NewElement("excluded-locations"); auto ctx = Rando::Context::GetInstance(); for (size_t i = 1; i < ctx->GetSettings()->GetExcludeLocationsOptions().size(); i++) { @@ -197,15 +162,8 @@ static void WriteExcludedLocations() { jsonData["excludedLocations"].push_back(RemoveLineBreaks(location->GetName())); - // tinyxml2::XMLElement* node = spoilerLog.NewElement("location"); - // node->SetAttribute("name", RemoveLineBreaks(location->GetName()).c_str()); - // parentNode->InsertEndChild(node); } } - - // if (!parentNode->NoChildren()) { - // spoilerLog.RootElement()->InsertEndChild(parentNode); - // } } // Writes the starting inventory to the spoiler log, if there is any. @@ -221,56 +179,20 @@ static void WriteStartingInventory() { } } -// Writes the enabled tricks to the spoiler log, if there are any. -static void WriteEnabledTricks(tinyxml2::XMLDocument& spoilerLog) { - //auto parentNode = spoilerLog.NewElement("enabled-tricks"); +//Writes the enabled tricks to the spoiler log, if there are any. +static void WriteEnabledTricks() { auto ctx = Rando::Context::GetInstance(); for (const auto& setting : ctx->GetSettings()->GetOptionGroup(RSG_TRICKS).GetOptions()) { - if (setting->GetContextOptionIndex() != RO_GENERIC_ON/* || !setting->IsCategory(OptionCategory::Setting)*/) { + if (setting->GetContextOptionIndex() != RO_GENERIC_ON) { continue; } jsonData["enabledTricks"].push_back(RemoveLineBreaks(setting->GetName()).c_str()); - //auto node = parentNode->InsertNewChildElement("trick"); - //node->SetAttribute("name", RemoveLineBreaks(setting->GetName()).c_str()); } - - // if (!parentNode->NoChildren()) { - // spoilerLog.RootElement()->InsertEndChild(parentNode); - //} } -// Writes the enabled glitches to the spoiler log, if there are any. -// TODO: Implement Glitches -// static void WriteEnabledGlitches(tinyxml2::XMLDocument& spoilerLog) { -// auto parentNode = spoilerLog.NewElement("enabled-glitches"); - -// for (const auto& setting : Settings::glitchCategories) { -// if (setting->Value<uint8_t>() == 0) { -// continue; -// } - -// auto node = parentNode->InsertNewChildElement("glitch-category"); -// node->SetAttribute("name", setting->GetName().c_str()); -// node->SetText(setting->GetSelectedOptionText().c_str()); -// } - -// for (const auto& setting : Settings::miscGlitches) { -// if (!setting->Value<bool>()) { -// continue; -// } - -// auto node = parentNode->InsertNewChildElement("misc-glitch"); -// node->SetAttribute("name", RemoveLineBreaks(setting->GetName()).c_str()); -// } - -// if (!parentNode->NoChildren()) { -// spoilerLog.RootElement()->InsertEndChild(parentNode); -// } -// } - // Writes the Master Quest dungeons to the spoiler log, if there are any. -static void WriteMasterQuestDungeons(tinyxml2::XMLDocument& spoilerLog) { +static void WriteMasterQuestDungeons() { auto ctx = Rando::Context::GetInstance(); for (const auto* dungeon : ctx->GetDungeons()->GetDungeonList()) { std::string dungeonName; @@ -294,7 +216,6 @@ static void WriteRequiredTrials() { // Writes the intended playthrough to the spoiler log, separated into spheres. static void WritePlaythrough() { - // auto playthroughNode = spoilerLog.NewElement("playthrough"); auto ctx = Rando::Context::GetInstance(); for (uint32_t i = 0; i < ctx->playthroughLocations.size(); ++i) { @@ -306,8 +227,6 @@ static void WritePlaythrough() { WriteLocation(sphereString, key, true); } } - - // spoilerLog.RootElement()->InsertEndChild(playthroughNode); } //Write the randomized entrance playthrough to the spoiler log, if applicable @@ -389,11 +308,6 @@ static void WriteAllLocations() { const char* SpoilerLog_Write() { auto ctx = Rando::Context::GetInstance(); - auto spoilerLog = tinyxml2::XMLDocument(false); - spoilerLog.InsertEndChild(spoilerLog.NewDeclaration()); - - auto rootNode = spoilerLog.NewElement("spoiler-log"); - spoilerLog.InsertEndChild(rootNode); jsonData.clear(); @@ -413,11 +327,8 @@ const char* SpoilerLog_Write() { WriteSettings(); WriteExcludedLocations(); WriteStartingInventory(); - WriteEnabledTricks(spoilerLog); //RANDOTODO clean up spoilerLog refernces - //if (Settings::Logic.Is(LOGIC_GLITCHED)) { - // WriteEnabledGlitches(spoilerLog); - //} - WriteMasterQuestDungeons(spoilerLog); + WriteEnabledTricks(); + WriteMasterQuestDungeons(); WriteRequiredTrials(); WritePlaythrough(); @@ -466,30 +377,3 @@ void PlacementLog_Clear() { placementtxt = ""; } -// RANDOTODO: Do we even use this? -bool PlacementLog_Write() { - auto placementLog = tinyxml2::XMLDocument(false); - placementLog.InsertEndChild(placementLog.NewDeclaration()); - - auto rootNode = placementLog.NewElement("placement-log"); - placementLog.InsertEndChild(rootNode); - - // rootNode->SetAttribute("version", Settings::version.c_str()); - // rootNode->SetAttribute("seed", Settings::seed); - - // WriteSettings(placementLog, true); // Include hidden settings. - // WriteExcludedLocations(placementLog); - // WriteStartingInventory(placementLog); - WriteEnabledTricks(placementLog); - //WriteEnabledGlitches(placementLog); - WriteMasterQuestDungeons(placementLog); - //WriteRequiredTrials(placementLog); - - placementtxt = "\n" + placementtxt; - - auto node = rootNode->InsertNewChildElement("log"); - auto contentNode = node->InsertNewText(placementtxt.c_str()); - contentNode->SetCData(true); - - return true; -} diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index bce400d91..b8ca9a3d0 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -672,11 +672,8 @@ bool EntranceShuffler::PlaceOneWayPriorityEntrance( } } } -#ifdef ENABLE_DEBUG - auto message = "ERROR: Unable to place priority one-way entrance for " + priorityName + "\n"; - SPDLOG_DEBUG(message); - PlacementLog_Write(); -#endif + SPDLOG_DEBUG("ERROR: Unable to place priority one-way entrance for " + priorityName + "\n"); + assert(false); return false; } diff --git a/soh/soh/Enhancements/randomizer/option.cpp b/soh/soh/Enhancements/randomizer/option.cpp index 75b02bf51..2729bef6e 100644 --- a/soh/soh/Enhancements/randomizer/option.cpp +++ b/soh/soh/Enhancements/randomizer/option.cpp @@ -55,7 +55,7 @@ uint8_t Option::GetContextOptionIndex() const { } const std::string& Option::GetSelectedOptionText() const { - return options[menuSelection]; + return options[contextSelection]; } const std::string& Option::GetCVarName() const { @@ -184,7 +184,7 @@ Option::Option(uint8_t var_, std::string name_, std::vector<std::string> options : var(var_), name(std::move(name_)), options(std::move(options_)), category(category_), cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_), defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) { - menuSelection = contextSelection = defaultOption; + menuSelection = contextSelection = defaultOption; hidden = defaultHidden; SetFromCVar(); } From 05539fee03474618a96fc640c51a904f7aa64bcb Mon Sep 17 00:00:00 2001 From: Garrett Cox <garrettjcox@gmail.com> Date: Wed, 4 Dec 2024 20:26:11 -0600 Subject: [PATCH 28/28] Add custom collectible thing --- soh/include/z64item.h | 8 +- .../custom-collectible/CustomCollectible.cpp | 209 ++++++++++++++++++ .../custom-collectible/CustomCollectible.h | 24 ++ soh/soh/OTRGlobals.cpp | 3 + soh/src/code/z_draw.c | 3 + soh/src/code/z_parameter.c | 11 + .../actors/ovl_player_actor/z_player.c | 1 + 7 files changed, 256 insertions(+), 3 deletions(-) create mode 100644 soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp create mode 100644 soh/soh/Enhancements/custom-collectible/CustomCollectible.h diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 214d82711..1731800aa 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -306,6 +306,7 @@ typedef enum { /* 0x99 */ ITEM_STICK_UPGRADE_30, /* 0x9A */ ITEM_NUT_UPGRADE_30, /* 0x9B */ ITEM_NUT_UPGRADE_40, + /* 0x9C */ ITEM_SHIP, // SOH [Enhancement] Added to enable custom item gives /* 0xFC */ ITEM_LAST_USED = 0xFC, /* 0xFE */ ITEM_NONE_FE = 0xFE, /* 0xFF */ ITEM_NONE = 0xFF @@ -455,9 +456,10 @@ typedef enum { /* 0x79 */ GI_NUT_UPGRADE_30, /* 0x7A */ GI_NUT_UPGRADE_40, /* 0x7B */ GI_BULLET_BAG_50, - /* 0x7C */ GI_ICE_TRAP, // freezes link when opened from a chest - /* 0x7D */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg) - /* 0x84 */ GI_MAX + /* 0x7C */ GI_SHIP, // SOH [Enhancement] Added to enable custom item gives + /* 0x7D */ GI_ICE_TRAP, // freezes link when opened from a chest + /* 0x7E */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg) + /* 0x7F */ GI_MAX } GetItemID; typedef enum { diff --git a/soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp b/soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp new file mode 100644 index 000000000..7bbbd8b55 --- /dev/null +++ b/soh/soh/Enhancements/custom-collectible/CustomCollectible.cpp @@ -0,0 +1,209 @@ +#include "CustomCollectible.h" +#include <libultraship/libultraship.h> +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/randomizer/3drando/random.hpp" +#include "soh/frame_interpolation.h" +#include "soh/Enhancements/custom-message/CustomMessageManager.h" + +extern "C" { +#include "z64actor.h" +#include "functions.h" +#include "variables.h" +#include "macros.h" +#include "objects/object_md/object_md.h" +extern PlayState* gPlayState; +} + +EnItem00* CustomCollectible::Spawn(f32 posX, f32 posY, f32 posZ, s16 rot, s16 flags, s16 params, ActorFunc actionFunc, + ActorFunc drawFunc) { + if (!gPlayState) { + return nullptr; + } + + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ITEM00, posX, posY, posZ, flags, rot, params, ITEM00_NONE, 0); + EnItem00* enItem00 = (EnItem00*)actor; + + if (actionFunc != NULL) { + enItem00->actionFunc = (EnItem00ActionFunc)actionFunc; + } + + if (drawFunc != NULL) { + actor->draw = drawFunc; + } + + return enItem00; +} + +void CustomCollectible_Init(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_BOBBING) { + actor->shape.yOffset = 1250.0f; + } else { + actor->shape.yOffset = (Math_SinS(actor->shape.rot.y) * 150.0f) + 1250.0f; + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::HIDE_TILL_OVERHEAD) { + Actor_SetScale(actor, 0.0f); + } else { + Actor_SetScale(actor, 0.015f); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::KEEP_ON_PLAYER) { + Math_Vec3f_Copy(&actor->world.pos, &GET_PLAYER(play)->actor.world.pos); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::TOSS_ON_SPAWN) { + actor->velocity.y = 8.0f; + actor->speedXZ = 2.0f; + actor->gravity = -1.4f; + actor->world.rot.y = Rand_ZeroOne() * 40000.0f; + } + + enItem00->unk_15A = -1; +} + +// By default this will just assume the GID was passed in as the rot z, if you want different functionality you should +// override the draw +void CustomCollectible_Draw(Actor* actor, PlayState* play) { + Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY); + GetItem_Draw(play, CUSTOM_ITEM_PARAM); +} + +void CustomCollectible_Update(Actor* actor, PlayState* play) { + EnItem00* enItem00 = (EnItem00*)actor; + Player* player = GET_PLAYER(play); + + if (!(CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_SPINNING)) { + actor->shape.rot.y += 960; + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::STOP_BOBBING) { + actor->shape.yOffset = 1250.0f; + } else { + actor->shape.yOffset = (Math_SinS(actor->shape.rot.y) * 150.0f) + 1250.0f; + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::HIDE_TILL_OVERHEAD) { + Actor_SetScale(actor, 0.0f); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::KEEP_ON_PLAYER) { + actor->gravity = 0.0f; + Math_Vec3f_Copy(&actor->world.pos, &GET_PLAYER(play)->actor.world.pos); + } + + if (CUSTOM_ITEM_FLAGS & CustomCollectible::KILL_ON_TOUCH) { + // Pretty self explanatory, if the player is within range, kill the actor and call the action function + if ((actor->xzDistToPlayer <= 50.0f) && (fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) { + if (enItem00->actionFunc != NULL) { + enItem00->actionFunc(enItem00, play); + CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION; + } + Actor_Kill(actor); + } + } else if (CUSTOM_ITEM_FLAGS & CustomCollectible::GIVE_OVERHEAD) { + // If the item hasn't been picked up (unk_15A == -1) and the player is within range + if (enItem00->unk_15A == -1 && (actor->xzDistToPlayer <= 50.0f) && + (fabsf(actor->yDistToPlayer) <= fabsf(20.0f))) { + // Fire the action function + if (enItem00->actionFunc != NULL) { + enItem00->actionFunc(enItem00, play); + CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION; + } + Sfx_PlaySfxCentered(NA_SE_SY_GET_ITEM); + // Set the unk_15A to 15, this indicates the item has been picked up and will start the overhead animation + enItem00->unk_15A = 15; + CUSTOM_ITEM_FLAGS |= CustomCollectible::STOP_BOBBING; + CUSTOM_ITEM_FLAGS |= CustomCollectible::KEEP_ON_PLAYER; + } + + // If the item has been picked up + if (enItem00->unk_15A > 0) { + // Reduce the size a bit, but also makes it visible for HIDE_TILL_OVERHEAD + Actor_SetScale(actor, 0.010f); + + // Decrement the unk_15A, which will be used to bob the item up and down + enItem00->unk_15A--; + + // Account for the different heights of the player forms + f32 height = 45.0f; + // TODO: Check for adult? + + // Bob the item up and down + actor->world.pos.y += (height + (Math_SinS(enItem00->unk_15A * 15000) * (enItem00->unk_15A * 0.3f))); + } + + // Finally, once the bobbing animation is done, kill the actor + if (enItem00->unk_15A == 0) { + Actor_Kill(actor); + } + } else if (CUSTOM_ITEM_FLAGS & CustomCollectible::GIVE_ITEM_CUTSCENE) { + // If the item hasn't been picked up and the player is within range + if (!Actor_HasParent(actor, play) && enItem00->unk_15A == -1) { + Actor_OfferGetItem(actor, play, GI_SHIP, 50.0f, 20.0f); + } else { + if (enItem00->unk_15A == -1) { + CUSTOM_ITEM_FLAGS |= CustomCollectible::STOP_BOBBING; + CUSTOM_ITEM_FLAGS |= CustomCollectible::KEEP_ON_PLAYER; + CUSTOM_ITEM_FLAGS |= CustomCollectible::HIDE_TILL_OVERHEAD; + } + + // Begin incrementing the unk_15A, indicating the item has been picked up + enItem00->unk_15A++; + + // For the first 20 frames, wait while the player's animation plays + if (enItem00->unk_15A >= 20) { + // After the first 20 frames, show the item and call the action function + if (enItem00->unk_15A == 20 && enItem00->actionFunc != NULL) { + enItem00->actionFunc(enItem00, play); + CUSTOM_ITEM_FLAGS |= CustomCollectible::CALLED_ACTION; + } + // Override the bobbing animation to be a fixed height + actor->shape.yOffset = 900.0f; + Actor_SetScale(actor, 0.007f); + + f32 height = 45.0f; + // TODO: Check for adult? + + actor->world.pos.y += height; + } + + // Once the player is no longer in the "Give Item" state, kill the actor + if (!(player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM)) { + Actor_Kill(actor); + } + } + } + + if (actor->gravity != 0.0f) { + Actor_MoveForward(actor); + Actor_UpdateBgCheckInfo(play, actor, 20.0f, 15.0f, 15.0f, 0x1D); + } + + if (actor->bgCheckFlags & 0x0003) { + actor->speedXZ = 0.0f; + } + + Collider_UpdateCylinder(actor, &enItem00->collider); + CollisionCheck_SetAC(play, &play->colChkCtx, &enItem00->collider.base); +} + +void CustomCollectible::RegisterHooks() { + GameInteractor::Instance->RegisterGameHookForID<GameInteractor::ShouldActorInit>( + ACTOR_EN_ITEM00, [](void* actorRef, bool* should) { + Actor* actor = (Actor*)actorRef; + if (actor->params != ITEM00_NONE) { + return; + } + + actor->init = CustomCollectible_Init; + actor->update = CustomCollectible_Update; + actor->draw = CustomCollectible_Draw; + actor->destroy = NULL; + + // Set the rotX/rotZ back to 0, the original values can be accessed from actor->home + actor->world.rot.x = 0; + actor->world.rot.z = 0; + }); +} diff --git a/soh/soh/Enhancements/custom-collectible/CustomCollectible.h b/soh/soh/Enhancements/custom-collectible/CustomCollectible.h new file mode 100644 index 000000000..ff2549b0f --- /dev/null +++ b/soh/soh/Enhancements/custom-collectible/CustomCollectible.h @@ -0,0 +1,24 @@ +extern "C" { +#include "z64actor.h" +} + +#define CUSTOM_ITEM_FLAGS (actor->home.rot.x) +#define CUSTOM_ITEM_PARAM (actor->home.rot.z) + +namespace CustomCollectible { + +enum CustomCollectibleFlags : int16_t { + KILL_ON_TOUCH = 1 << 0, // 0000 0000 0000 0001 + GIVE_OVERHEAD = 1 << 1, // 0000 0000 0000 0010 + GIVE_ITEM_CUTSCENE = 1 << 2, // 0000 0000 0000 0100 + HIDE_TILL_OVERHEAD = 1 << 3, // 0000 0000 0000 1000 + KEEP_ON_PLAYER = 1 << 4, // 0000 0000 0001 0000 + STOP_BOBBING = 1 << 5, // 0000 0000 0010 0000 + STOP_SPINNING = 1 << 6, // 0000 0000 0100 0000 + CALLED_ACTION = 1 << 7, // 0000 0000 1000 0000 + TOSS_ON_SPAWN = 1 << 8, // 0000 0001 0000 0000 +}; +void RegisterHooks(); +EnItem00* Spawn(f32 posX, f32 posY, f32 posZ, s16 rot, s16 flags, s16 params, ActorFunc actionFunc = NULL, + ActorFunc drawFunc = NULL); +}; // namespace CustomCollectible diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0ae870a33..87e1fee5a 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -84,6 +84,7 @@ Sail* Sail::Instance; #include "Enhancements/mods.h" #include "Enhancements/game-interactor/GameInteractor.h" #include "Enhancements/randomizer/draw.h" +#include "Enhancements/custom-collectible/CustomCollectible.h" #include <libultraship/libultraship.h> // Resource Types/Factories @@ -703,6 +704,7 @@ extern "C" void VanillaItemTable_Init() { GET_ITEM(ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_30), GET_ITEM(ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, GI_NUT_UPGRADE_40), GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_BULLET_BAG_50), + GET_ITEM(ITEM_SHIP, OBJECT_UNSET_16E, GID_MAXIMUM, 0x00, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, GI_SHIP), GET_ITEM_NONE, GET_ITEM_NONE, GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry. @@ -1173,6 +1175,7 @@ extern "C" void InitOTR() { DebugConsole_Init(); InitMods(); + CustomCollectible::RegisterHooks(); ActorDB::AddBuiltInCustomActors(); // #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer CVarClear(CVAR_GENERAL("RandomizerNewFileDropped")); diff --git a/soh/src/code/z_draw.c b/soh/src/code/z_draw.c index e27f230b1..caf31a234 100644 --- a/soh/src/code/z_draw.c +++ b/soh/src/code/z_draw.c @@ -399,6 +399,9 @@ DrawItemTableEntry sDrawItemTable[] = { * Calls the corresponding draw function for the given draw ID */ void GetItem_Draw(PlayState* play, s16 drawId) { + if (drawId < 0 || drawId >= GID_MAXIMUM) { + return; + } sDrawItemTable[drawId].drawFunc(play, drawId); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index be3a28442..71bc672ac 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1891,6 +1891,12 @@ u8 Return_Item(u8 itemID, ModIndex modId, ItemID returnItem) { * @return u8 */ u8 Item_Give(PlayState* play, u8 item) { + // TODO: Add ShouldItemGive + // if (!GameInteractor_ShouldItemGive(item) || item == ITEM_SHIP) { + if (item == ITEM_SHIP) { + return ITEM_NONE; + } + //prevents getting sticks without the bag in case something got missed if ( IS_RANDO && @@ -2486,6 +2492,11 @@ u8 Item_CheckObtainability(u8 item) { s16 slot = SLOT(item); s32 temp; + // SOH [Enhancements] Added to enable custom item gives + if (item == ITEM_SHIP) { + return ITEM_NONE; + } + if (item >= ITEM_STICKS_5) { slot = SLOT(sExtraItemBases[item - ITEM_STICKS_5]); } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 9275f9cab..11ed30ad8 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7312,6 +7312,7 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) { interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != ITEM00_HEART_PIECE && interactedActor->params != ITEM00_SMALL_KEY && + interactedActor->params != ITEM00_NONE && interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY && interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI ) ||