From 8525f71c57c205712ce12c2fbe5d3b0090d7e5be Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Fri, 16 Feb 2024 03:50:17 +0100 Subject: [PATCH] Colored Compasses (#3883) * Colored Compasses * Rename cvar & add explicit rando check --- soh/soh/Enhancements/mods.cpp | 22 ++++++++++ soh/soh/Enhancements/mods.h | 1 + soh/soh/Enhancements/randomizer/draw.cpp | 44 +++++++++++++++++++ soh/soh/Enhancements/randomizer/draw.h | 1 + soh/soh/Enhancements/randomizer/item_list.cpp | 10 +++++ soh/soh/SohMenuBar.cpp | 22 +++++++++- 6 files changed, 98 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 26adf611d..9b8e7076e 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -10,6 +10,7 @@ #include "soh/Enhancements/cosmetics/authenticGfxPatches.h" #include #include "soh/Enhancements/nametag.h" +#include "objects/object_gi_compass/object_gi_compass.h" #include "src/overlays/actors/ovl_En_Bb/z_en_bb.h" #include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h" @@ -1595,6 +1596,26 @@ void RegisterFishsanity() { }); } +extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); + +void PatchCompasses() { + s8 compassesCanBeOutsideDungeon = IS_RANDO && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS); + s8 isColoredCompassesEnabled = compassesCanBeOutsideDungeon && CVarGetInteger("gRandoEnhancement.MatchCompassColors", 1); + if (isColoredCompassesEnabled) { + ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_PrimColor", 5, gsDPNoOp()); + ResourceMgr_PatchGfxByName(gGiCompassDL, "Compass_EnvColor", 6, gsDPNoOp()); + } else { + ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_PrimColor"); + ResourceMgr_UnpatchGfxByName(gGiCompassDL, "Compass_EnvColor"); + } +} + +void RegisterRandomizerCompasses() { + GameInteractor::Instance->RegisterGameHook([](int32_t _unused) { + PatchCompasses(); + }); +} + void InitMods() { RegisterTTS(); RegisterInfiniteMoney(); @@ -1632,6 +1653,7 @@ void InitMods() { RegisterNoSwim(); RegisterNoWallet(); RegisterFishsanity(); + RegisterRandomizerCompasses(); NameTag_RegisterHooks(); RegisterPatchHandHandler(); RegisterHurtContainerModeHandler(); diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h index 57ebedfd9..9289594dc 100644 --- a/soh/soh/Enhancements/mods.h +++ b/soh/soh/Enhancements/mods.h @@ -11,6 +11,7 @@ void UpdateDirtPathFixState(int32_t sceneNum); void UpdateMirrorModeState(int32_t sceneNum); void UpdateHurtContainerModeState(bool newState); void PatchToTMedallions(); +void PatchCompasses(); void UpdatePermanentHeartLossState(); void InitMods(); void UpdatePatchHand(); diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 646d99456..4ee80d919 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -9,6 +9,7 @@ #include #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" +#include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_hearts/object_gi_hearts.h" #include "objects/object_gi_scale/object_gi_scale.h" #include "objects/object_gi_fire/object_gi_fire.h" @@ -63,6 +64,49 @@ extern "C" void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEn CLOSE_DISPS(play->state.gfxCtx); } +extern "C" { + void GetItem_DrawCompass(PlayState* play, s16 drawId); + void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); + void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); +} + +extern "C" void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry) { + + s16 color_slot = getItemEntry->getItemId - RG_DEKU_TREE_COMPASS; + s16 colors[12][3] = { + { 4, 100, 46 }, // Deku Tree + { 140, 30, 30 }, // Dodongo's Cavern + { 30, 60, 255 }, // Jabu Jabu's Belly + { 4, 195, 46 }, // Forest Temple + { 237, 95, 95 }, // Fire Temple + { 85, 180, 223 }, // Water Temple + { 222, 158, 47 }, // Spirit Temple + { 126, 16, 177 }, // Shadow Temple + { 227, 110, 255 }, // Bottom of the Well + { 221, 212, 60 }, // Gerudo Training Grounds + { 255, 255, 255 }, // Thieves' Hideout + { 80, 80, 80 } // Ganon's Castle + }; + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255); + gDPSetEnvColor(POLY_OPA_DISP++, colors[color_slot][0] / 2, colors[color_slot][1] / 2, colors[color_slot][2] / 2, 255); + + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiCompassDL); + + POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 5); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiCompassGlassDL); + + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry) { s8 keysCanBeOutsideDungeon = getItemEntry->getItemId == RG_GANONS_CASTLE_BOSS_KEY ? DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY) : diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 0e8a3e3b5..51300f3a6 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -10,6 +10,7 @@ typedef struct PlayState PlayState; extern "C" { #endif void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawCompass(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawBossSoul(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index a64d62d40..343f680b1 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -107,15 +107,25 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, &logic->noVariable, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, &logic->noVariable, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, &logic->noVariable, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, &logic->noVariable, RHT_DODONGOS_CAVERN_COMPASS,RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, &logic->noVariable, RHT_JABU_JABUS_BELLY_COMPASS,RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, &logic->noVariable, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, &logic->noVariable, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, &logic->noVariable, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, &logic->noVariable, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, &logic->noVariable, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, &logic->noVariable, RHT_BOTTOM_OF_THE_WELL_COMPASS,RG_BOTTOM_OF_THE_WELL_COMPASS,OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, &logic->noVariable, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, &logic->BossKeyForestTemple, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 56e12e53e..c2b560296 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -10,6 +10,7 @@ #include "include/z64audio.h" #include "OTRGlobals.h" #include "z64.h" +#include "macros.h" #include "Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/presets.h" #include "soh/Enhancements/mods.h" @@ -1826,6 +1827,7 @@ extern std::shared_ptr mItemTrackerSettingsWindow; extern std::shared_ptr mEntranceTrackerWindow; extern std::shared_ptr mCheckTrackerWindow; extern std::shared_ptr mCheckTrackerSettingsWindow; +extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); void DrawRandomizerMenu() { if (ImGui::BeginMenu("Randomizer")) { @@ -1916,7 +1918,7 @@ void DrawRandomizerMenu() { disableKeyColors = false; } - static const char* disableKeyColorsText = + static const char* disableKeyColorsText = "This setting is disabled because a savefile is loaded without any key\n" "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; @@ -1925,7 +1927,23 @@ void DrawRandomizerMenu() { UIWidgets::Tooltip( "Matches the color of small keys and boss keys to the dungeon they belong to. " "This helps identify keys from afar and adds a little bit of flair.\n\nThis only " - "applies to seeds with keys and boss keys shuffled to Any Dungeon, Overworld, or Anywhere."); + "applies to seeds with keys and boss keys shuffled to \"Any Dungeon\", \"Overworld\", or \"Anywhere\"."); + + bool disableCompassColors = !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS); + + static const char* disableCompassColorsText = + "This setting is disabled because a savefile is loaded without the compass\n" + "shuffle settings set to \"Any Dungeon\", \"Overworld\" or \"Anywhere\""; + + if (UIWidgets::PaddedEnhancementCheckbox("Compass Colors Match Dungeon", "gRandoEnhancement.MatchCompassColors", true, false, + disableCompassColors, disableCompassColorsText, UIWidgets::CheckboxGraphics::Cross, true)) { + PatchCompasses(); + } + UIWidgets::Tooltip( + "Matches the color of compasses to the dungeon they belong to. " + "This helps identify compasses from afar and adds a little bit of flair.\n\nThis only " + "applies to seeds with compasses shuffled to \"Any Dungeon\", \"Overworld\", or \"Anywhere\"."); + UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", "gRandoQuestItemFanfares", true, false); UIWidgets::Tooltip( "Play unique fanfares when obtaining quest items "