diff --git a/soh/include/z64.h b/soh/include/z64.h index 2172dcb74..23ffcfb17 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -2245,6 +2245,8 @@ typedef enum { LED_SOURCE_TUNIC_ORIGINAL, LED_SOURCE_TUNIC_COSMETICS, LED_SOURCE_HEALTH, + LED_SOURCE_NAVI_ORIGINAL, + LED_SOURCE_NAVI_COSMETICS, LED_SOURCE_CUSTOM } LEDColorSource; diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index 3bd650637..935935c48 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -331,13 +331,14 @@ namespace GameControlEditor { void DrawLEDControlPanel(GameControlEditorWindow* window) { window->BeginGroupPanelPublic("LED Colors", ImGui::GetContentRegionAvail()); - static const char* ledSources[4] = { "Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors", "Custom" }; + static const char* ledSources[] = { "Original Tunic Colors", "Cosmetics Tunic Colors", "Health Colors", + "Original Navi Targeting Colors", "Cosmetics Navi Targeting Colors", "Custom" }; UIWidgets::PaddedText("Source"); UIWidgets::EnhancementCombobox("gLedColorSource", ledSources, LED_SOURCE_TUNIC_ORIGINAL); DrawHelpIcon("Health\n- Red when health critical (13-20% depending on max health)\n- Yellow when health < 40%. Green otherwise.\n\n" \ "Tunics: colors will mirror currently equipped tunic, whether original or the current values in Cosmetics Editor.\n\n" \ "Custom: single, solid color"); - if (CVarGetInteger("gLedColorSource", 1) == 3) { + if (CVarGetInteger("gLedColorSource", 1) == LED_SOURCE_CUSTOM) { UIWidgets::Spacer(3); auto port1Color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 }); ImVec4 colorVec = { port1Color.r / 255.0f, port1Color.g / 255.0f, port1Color.b / 255.0f, 1.0f }; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index eee6a622a..553caef7e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -128,6 +128,34 @@ Color_RGB8 kokiriColor = { 0x1E, 0x69, 0x1B }; Color_RGB8 goronColor = { 0x64, 0x14, 0x00 }; Color_RGB8 zoraColor = { 0x00, 0xEC, 0x64 }; +// Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED. +typedef struct { + Color_RGB8 inner; + Color_RGB8 outer; +} NaviColor_RGB8; + +static NaviColor_RGB8 defaultIdleColor = { { 255, 255, 255 }, { 0, 0, 255 } }; +static NaviColor_RGB8 defaultNPCColor = { { 150, 150, 255 }, { 150, 150, 255 } }; +static NaviColor_RGB8 defaultEnemyColor = { { 255, 255, 0 }, { 200, 155, 0 } }; +static NaviColor_RGB8 defaultPropsColor = { { 0, 255, 0 }, { 0, 255, 0 } }; + +// Labeled according to ActorCategory (included through ActorDB.h) +const NaviColor_RGB8 LEDColorDefaultNaviColorList[] = { + defaultPropsColor, // ACTORCAT_SWITCH Switch + defaultPropsColor, // ACTORCAT_BG Background (Prop type 1) + defaultIdleColor, // ACTORCAT_PLAYER Player + defaultPropsColor, // ACTORCAT_EXPLOSIVE Bomb + defaultNPCColor, // ACTORCAT_NPC NPC + defaultEnemyColor, // ACTORCAT_ENEMY Enemy + defaultPropsColor, // ACTORCAT_PROP Prop type 2 + defaultPropsColor, // ACTORCAT_ITEMACTION Item/Action + defaultPropsColor, // ACTORCAT_MISC Misc. + defaultEnemyColor, // ACTORCAT_BOSS Boss + defaultPropsColor, // ACTORCAT_DOOR Door + defaultPropsColor, // ACTORCAT_CHEST Chest + defaultPropsColor, // ACTORCAT_MAX +}; + // OTRTODO: A lot of these left in Japanese are used by the mempak manager. LUS does not currently support mempaks. Ignore unused ones. const char* constCameraStrings[] = { "INSUFFICIENT", @@ -1718,6 +1746,52 @@ Color_RGB8 GetColorForControllerLED() { break; } } + if (gPlayState && (source == LED_SOURCE_NAVI_ORIGINAL || source == LED_SOURCE_NAVI_COSMETICS)) { + Actor* arrowPointedActor = gPlayState->actorCtx.targetCtx.arrowPointedActor; + if (arrowPointedActor) { + ActorCategory category = (ActorCategory)arrowPointedActor->category; + switch (category) { + case ACTORCAT_PLAYER: + if (source == LED_SOURCE_NAVI_COSMETICS && + CVarGetInteger("gCosmetics.Navi_IdlePrimary.Changed", 0)) { + color = CVarGetColor24("gCosmetics.Navi_IdlePrimary.Value", defaultIdleColor.inner); + break; + } + color = LEDColorDefaultNaviColorList[category].inner; + break; + case ACTORCAT_NPC: + if (source == LED_SOURCE_NAVI_COSMETICS && + CVarGetInteger("gCosmetics.Navi_NPCPrimary.Changed", 0)) { + color = CVarGetColor24("gCosmetics.Navi_NPCPrimary.Value", defaultNPCColor.inner); + break; + } + color = LEDColorDefaultNaviColorList[category].inner; + break; + case ACTORCAT_ENEMY: + case ACTORCAT_BOSS: + if (source == LED_SOURCE_NAVI_COSMETICS && + CVarGetInteger("gCosmetics.Navi_EnemyPrimary.Changed", 0)) { + color = CVarGetColor24("gCosmetics.Navi_EnemyPrimary.Value", defaultEnemyColor.inner); + break; + } + color = LEDColorDefaultNaviColorList[category].inner; + break; + default: + if (source == LED_SOURCE_NAVI_COSMETICS && + CVarGetInteger("gCosmetics.Navi_PropsPrimary.Changed", 0)) { + color = CVarGetColor24("gCosmetics.Navi_PropsPrimary.Value", defaultPropsColor.inner); + break; + } + color = LEDColorDefaultNaviColorList[category].inner; + } + } else { // No target actor. + if (source == LED_SOURCE_NAVI_COSMETICS && CVarGetInteger("gCosmetics.Navi_IdlePrimary.Changed", 0)) { + color = CVarGetColor24("gCosmetics.Navi_IdlePrimary.Value", defaultIdleColor.inner); + } else { + color = LEDColorDefaultNaviColorList[ACTORCAT_PLAYER].inner; + } + } + } if (source == LED_SOURCE_CUSTOM) { color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 }); }