diff --git a/Penumbra/Interop/Resolver/PathResolver.Animation.cs b/Penumbra/Interop/Resolver/PathResolver.Animation.cs index 604b40af..fcab01e3 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Animation.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Animation.cs @@ -1,5 +1,6 @@ using System; using Dalamud.Hooking; +using Dalamud.Logging; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Penumbra.Collections; @@ -59,16 +60,16 @@ public unsafe partial class PathResolver _animationLoadCollection = last; } - public delegate ulong LoadSomeAvfx( uint a1, IntPtr gameObject, IntPtr gameObject2 ); + public delegate ulong LoadSomeAvfx( uint a1, IntPtr gameObject, IntPtr gameObject2, float unk1, IntPtr unk2, IntPtr unk3 ); [Signature( "E8 ?? ?? ?? ?? 45 0F B6 F7", DetourName = nameof( LoadSomeAvfxDetour ) )] public Hook< LoadSomeAvfx >? LoadSomeAvfxHook; - private ulong LoadSomeAvfxDetour( uint a1, IntPtr gameObject, IntPtr gameObject2 ) + private ulong LoadSomeAvfxDetour( uint a1, IntPtr gameObject, IntPtr gameObject2, float unk1, IntPtr unk2, IntPtr unk3 ) { var last = _animationLoadCollection; _animationLoadCollection = IdentifyCollection( ( GameObject* )gameObject ); - var ret = LoadSomeAvfxHook!.Original( a1, gameObject, gameObject2 ); + var ret = LoadSomeAvfxHook!.Original( a1, gameObject, gameObject2, unk1, unk2, unk3 ); _animationLoadCollection = last; return ret; } diff --git a/Penumbra/Interop/Resolver/PathResolver.Data.cs b/Penumbra/Interop/Resolver/PathResolver.Data.cs index afc4f7d1..14a876b4 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Data.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Data.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Dalamud.Hooking; +using Dalamud.Logging; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; @@ -277,40 +278,48 @@ public unsafe partial class PathResolver return Penumbra.CollectionManager.Default; } - // Housing Retainers - if( Penumbra.Config.UseDefaultCollectionForRetainers - && gameObject->ObjectKind == ( byte )ObjectKind.EventNpc - && gameObject->DataID == 1011832 ) + try { + // Housing Retainers + if( Penumbra.Config.UseDefaultCollectionForRetainers + && gameObject->ObjectKind == ( byte )ObjectKind.EventNpc + && gameObject->DataID == 1011832 ) + { + return Penumbra.CollectionManager.Default; + } + + 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 ) ) + { + 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 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // try-on + 243 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // dye preview + >= 200 => GetCutsceneName( gameObject ), + _ => null, + } + ?? GetOwnerName( gameObject ) ?? actorName ?? new Utf8String( gameObject->Name ).ToString(); + + // First check temporary character collections, then the own configuration. + return Penumbra.TempMods.Collections.TryGetValue( actualName, out var c ) ? c : Penumbra.CollectionManager.Character( actualName ); + } + catch( Exception e ) + { + PluginLog.Error( $"Error identifying collection:\n{e}" ); return Penumbra.CollectionManager.Default; } - - 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 ) ) - { - 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 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // try-on - 243 => Penumbra.Config.UseCharacterCollectionInTryOn ? GetPlayerName() : null, // dye preview - >= 200 => GetCutsceneName( gameObject ), - _ => null, - } - ?? GetOwnerName( gameObject ) ?? actorName ?? new Utf8String( gameObject->Name ).ToString(); - - // First check temporary character collections, then the own configuration. - return Penumbra.TempMods.Collections.TryGetValue(actualName, out var c) ? c : Penumbra.CollectionManager.Character( actualName ); } // Update collections linked to Game/DrawObjects due to a change in collection configuration.