From c0102368c302d6dbcb30c50c4837fb734afe396d Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sat, 4 Jun 2022 00:54:01 +0200 Subject: [PATCH] Add some options to which special actors use which character collection and fix Inspect Actor recognition. --- Penumbra/Configuration.cs | 7 +++ .../Interop/Resolver/PathResolver.Data.cs | 52 ++++++++++++++++--- .../UI/ConfigWindow.SettingsTab.General.cs | 20 +++++++ 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index 896295c8..2e39f4d3 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -21,6 +21,13 @@ public partial class Configuration : IPluginConfiguration public bool HideUiInCutscenes { get; set; } = true; public bool HideUiWhenUiHidden { get; set; } = false; + public bool UseCharacterCollectionInMainWindow { get; set; } = true; + public bool UseCharacterCollectionsInCards { get; set; } = true; + public bool UseCharacterCollectionInInspect { get; set; } = true; + public bool UseCharacterCollectionInTryOn { get; set; } = true; + public bool UseOwnerNameForCharacterCollection { get; set; } = true; + public bool PreferNamedCollectionsOverOwners { get; set; } = false; + #if DEBUG public bool DebugMode { get; set; } = true; #else diff --git a/Penumbra/Interop/Resolver/PathResolver.Data.cs b/Penumbra/Interop/Resolver/PathResolver.Data.cs index c384878a..f32c290e 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Data.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Data.cs @@ -125,6 +125,11 @@ public unsafe partial class PathResolver // Obtain the name of the inspect target from its window, if it exists. private static string? GetInspectName() { + if( !Penumbra.Config.UseCharacterCollectionInInspect ) + { + return null; + } + var addon = Dalamud.GameGui.GetAddonByName( "CharacterInspect", 1 ); if( addon == IntPtr.Zero ) { @@ -137,13 +142,23 @@ public unsafe partial class PathResolver return null; } - var text = ( AtkTextNode* )ui->UldManager.NodeList[ 60 ]; + var text = ( AtkTextNode* )ui->UldManager.NodeList[ 59 ]; + if( text == null || !text->AtkResNode.IsVisible ) + { + text = ( AtkTextNode* )ui->UldManager.NodeList[ 60 ]; + } + return text != null ? text->NodeText.ToString() : null; } // Obtain the name displayed in the Character Card from the agent. private static string? GetCardName() { + if( !Penumbra.Config.UseCharacterCollectionsInCards ) + { + return null; + } + var uiModule = ( UIModule* )Dalamud.GameGui.GetUIModule(); var agentModule = uiModule->GetAgentModule(); var agent = ( byte* )agentModule->GetAgentByInternalID( 393 ); @@ -165,6 +180,11 @@ public unsafe partial class PathResolver // Obtain the name of the player character if the glamour plate edit window is open. private static string? GetGlamourName() { + if( !Penumbra.Config.UseCharacterCollectionInTryOn ) + { + return null; + } + var addon = Dalamud.GameGui.GetAddonByName( "MiragePrismMiragePlate", 1 ); return addon == IntPtr.Zero ? null : GetPlayerName(); } @@ -193,6 +213,11 @@ public unsafe partial class PathResolver // Monsters with a owner use that owner if it exists. private static string? GetOwnerName( GameObject* gameObject ) { + if( !Penumbra.Config.UseOwnerNameForCharacterCollection ) + { + return null; + } + GameObject* owner = null; if( ( ObjectKind )gameObject->GetObjectKind() is ObjectKind.Companion or ObjectKind.MountType && gameObject->ObjectIndex > 0 ) { @@ -200,7 +225,7 @@ public unsafe partial class PathResolver } else if( gameObject->OwnerID != 0xE0000000 ) { - owner = ( GameObject* )(Dalamud.Objects.SearchById( gameObject->OwnerID )?.Address ?? IntPtr.Zero); + owner = ( GameObject* )( Dalamud.Objects.SearchById( gameObject->OwnerID )?.Address ?? IntPtr.Zero ); } if( owner != null ) @@ -219,17 +244,30 @@ public unsafe partial class PathResolver return Penumbra.CollectionManager.Default; } - var name = gameObject->ObjectIndex switch + string? actorName = null; + if( Penumbra.Config.PreferNamedCollectionsOverOwners ) + { + // Early return if we prefer the actors own name over its owner. + actorName = new Utf8String( gameObject->Name ).ToString(); + if( actorName.Length > 0 && Penumbra.CollectionManager.Characters.TryGetValue( actorName, out var actorCollection ) ) { - 240 => GetPlayerName(), // character window + return actorCollection; + } + } + + // All these special cases are relevant for an empty name, so never collide with the above setting. + // Only OwnerName can be applied to something with a non-empty name, and that is the specific case we want to handle. + var actualName = gameObject->ObjectIndex switch + { + 240 => Penumbra.Config.UseCharacterCollectionInMainWindow ? GetPlayerName() : null, // character window 241 => GetInspectName() ?? GetCardName() ?? GetGlamourName(), // inspect, character card, glamour plate editor. - 242 => GetPlayerName(), // try-on + 242 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // try-on >= 200 => GetCutsceneName( gameObject ), _ => null, } - ?? GetOwnerName( gameObject ) ?? new Utf8String( gameObject->Name ).ToString(); + ?? GetOwnerName( gameObject ) ?? actorName ?? new Utf8String( gameObject->Name ).ToString(); - return Penumbra.CollectionManager.Character( name ); + return Penumbra.CollectionManager.Character( actualName ); } // Update collections linked to Game/DrawObjects due to a change in collection configuration. diff --git a/Penumbra/UI/ConfigWindow.SettingsTab.General.cs b/Penumbra/UI/ConfigWindow.SettingsTab.General.cs index 5fe02deb..3f71f6d8 100644 --- a/Penumbra/UI/ConfigWindow.SettingsTab.General.cs +++ b/Penumbra/UI/ConfigWindow.SettingsTab.General.cs @@ -56,6 +56,26 @@ public partial class ConfigWindow Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = !v; } ); ImGui.Dummy( _window._defaultSpace ); + Checkbox( "Use Character Collections in Character Window", + "Use the character collection for your character's name in your main character window, if it is set.", + Penumbra.Config.UseCharacterCollectionInMainWindow, v => Penumbra.Config.UseCharacterCollectionInMainWindow = v ); + Checkbox( "Use Character Collections in Adventurer Cards", + "Use the appropriate character collection for the adventurer card you are currently looking at, based on the adventurer's name.", + Penumbra.Config.UseCharacterCollectionsInCards, v => Penumbra.Config.UseCharacterCollectionsInCards = v ); + Checkbox( "Use Character Collections in Try-On Window", + "Use the character collection for your character's name in your try-on window, if it is set.", + Penumbra.Config.UseCharacterCollectionInTryOn, v => Penumbra.Config.UseCharacterCollectionInTryOn = v ); + Checkbox( "Use Character Collections in Inspect Windows", + "Use the appropriate character collection for the character you are currently inspecting, based on their name.", + Penumbra.Config.UseCharacterCollectionInInspect, v => Penumbra.Config.UseCharacterCollectionInInspect = v ); + Checkbox( "Use Character Collections based on Ownership", + "Use the owner's name to determine the appropriate character collection for mounts, companions and combat pets.", + Penumbra.Config.UseOwnerNameForCharacterCollection, v => Penumbra.Config.UseOwnerNameForCharacterCollection = v ); + Checkbox( "Prefer Named Collections over Ownership", + "If you have a character collection set to a specific name for a companion or combat pet, prefer this collection over the owner's collection.\n" + + "That is, if you have a 'Topaz Carbuncle' collection, it will use this one instead of the one for its owner.", + Penumbra.Config.PreferNamedCollectionsOverOwners, v => Penumbra.Config.PreferNamedCollectionsOverOwners = v ); + ImGui.Dummy( _window._defaultSpace ); DrawFolderSortType(); DrawAbsoluteSizeSelector(); DrawRelativeSizeSelector();