From eeaaecb855a9a5c14325b2c22061da099de32e6d Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 2 Jun 2022 14:15:34 +0200 Subject: [PATCH] Let companions, combat pets and mounts use their owners character collection. --- .../Interop/Resolver/PathResolver.Data.cs | 25 +++++- .../Interop/Resolver/PathResolver.Monster.cs | 88 +++++++++++++++++++ .../Interop/Resolver/PathResolver.Resolve.cs | 37 ++++++++ .../Interop/Resolver/PathResolver.Weapon.cs | 1 - Penumbra/Interop/Resolver/PathResolver.cs | 4 + 5 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 Penumbra/Interop/Resolver/PathResolver.Monster.cs diff --git a/Penumbra/Interop/Resolver/PathResolver.Data.cs b/Penumbra/Interop/Resolver/PathResolver.Data.cs index d6b37dc9..f2e81cad 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Data.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Data.cs @@ -188,6 +188,29 @@ public unsafe partial class PathResolver return pc->ClassJob == ( ( Character* )gameObject )->ClassJob ? player.Name.ToString() : null; } + // Identify the owner of a companion, mount or monster and apply the corresponding collection. + // Companions and mounts get set to the actor before them in the table if it exists. + // Monsters with a owner use that owner if it exists. + private static string? GetOwnerName( GameObject* gameObject ) + { + GameObject* owner = null; + if( ( ObjectKind )gameObject->GetObjectKind() is ObjectKind.Companion or ObjectKind.MountType && gameObject->ObjectIndex > 0 ) + { + owner = ( GameObject* )Dalamud.Objects[ gameObject->ObjectIndex - 1 ]?.Address; + } + else if( gameObject->OwnerID != 0xE0000000 ) + { + owner = ( GameObject* )Dalamud.Objects.SearchById( gameObject->OwnerID )?.Address; + } + + if( owner != null ) + { + return new Utf8String( owner->Name ).ToString(); + } + + return null; + } + // Identify the correct collection for a GameObject by index and name. private static ModCollection IdentifyCollection( GameObject* gameObject ) { @@ -204,7 +227,7 @@ public unsafe partial class PathResolver >= 200 => GetCutsceneName( gameObject ), _ => null, } - ?? new Utf8String( gameObject->Name ).ToString(); + ?? GetOwnerName( gameObject ) ?? new Utf8String( gameObject->Name ).ToString(); return Penumbra.CollectionManager.Character( name ); } diff --git a/Penumbra/Interop/Resolver/PathResolver.Monster.cs b/Penumbra/Interop/Resolver/PathResolver.Monster.cs new file mode 100644 index 00000000..f7baa229 --- /dev/null +++ b/Penumbra/Interop/Resolver/PathResolver.Monster.cs @@ -0,0 +1,88 @@ +using System; +using Dalamud.Hooking; +using Dalamud.Utility.Signatures; + +namespace Penumbra.Interop.Resolver; + +public unsafe partial class PathResolver +{ + [Signature( "48 8D 05 ?? ?? ?? ?? 48 89 03 33 C0 48 89 83 ?? ?? ?? ?? 48 89 83 ?? ?? ?? ?? C7 83", ScanType = ScanType.StaticAddress )] + public IntPtr* DrawObjectMonsterVTable; + + public Hook? ResolveMonsterDecalPathHook; + public Hook? ResolveMonsterEidPathHook; + public Hook? ResolveMonsterImcPathHook; + public Hook? ResolveMonsterMPapPathHook; + public Hook? ResolveMonsterMdlPathHook; + public Hook? ResolveMonsterMtrlPathHook; + public Hook? ResolveMonsterPapPathHook; + public Hook? ResolveMonsterPhybPathHook; + public Hook? ResolveMonsterSklbPathHook; + public Hook? ResolveMonsterSkpPathHook; + public Hook? ResolveMonsterTmbPathHook; + public Hook? ResolveMonsterVfxPathHook; + + private void SetupMonsterHooks() + { + ResolveMonsterDecalPathHook = new Hook( DrawObjectMonsterVTable[ResolveDecalIdx], ResolveMonsterDecalDetour ); + ResolveMonsterEidPathHook = new Hook( DrawObjectMonsterVTable[ResolveEidIdx], ResolveMonsterEidDetour ); + ResolveMonsterImcPathHook = new Hook( DrawObjectMonsterVTable[ResolveImcIdx], ResolveMonsterImcDetour ); + ResolveMonsterMPapPathHook = new Hook( DrawObjectMonsterVTable[ResolveMPapIdx], ResolveMonsterMPapDetour ); + ResolveMonsterMdlPathHook = new Hook( DrawObjectMonsterVTable[ResolveMdlIdx], ResolveMonsterMdlDetour ); + ResolveMonsterMtrlPathHook = new Hook( DrawObjectMonsterVTable[ResolveMtrlIdx], ResolveMonsterMtrlDetour ); + ResolveMonsterPapPathHook = new Hook( DrawObjectMonsterVTable[ResolvePapIdx], ResolveMonsterPapDetour ); + ResolveMonsterPhybPathHook = new Hook( DrawObjectMonsterVTable[ResolvePhybIdx], ResolveMonsterPhybDetour ); + ResolveMonsterSklbPathHook = new Hook( DrawObjectMonsterVTable[ResolveSklbIdx], ResolveMonsterSklbDetour ); + ResolveMonsterSkpPathHook = new Hook( DrawObjectMonsterVTable[ResolveSkpIdx], ResolveMonsterSkpDetour ); + ResolveMonsterTmbPathHook = new Hook( DrawObjectMonsterVTable[ResolveTmbIdx], ResolveMonsterTmbDetour ); + ResolveMonsterVfxPathHook = new Hook( DrawObjectMonsterVTable[ResolveVfxIdx], ResolveMonsterVfxDetour ); + } + + private void EnableMonsterHooks() + { + ResolveMonsterDecalPathHook?.Enable(); + ResolveMonsterEidPathHook?.Enable(); + ResolveMonsterImcPathHook?.Enable(); + ResolveMonsterMPapPathHook?.Enable(); + ResolveMonsterMdlPathHook?.Enable(); + ResolveMonsterMtrlPathHook?.Enable(); + ResolveMonsterPapPathHook?.Enable(); + ResolveMonsterPhybPathHook?.Enable(); + ResolveMonsterSklbPathHook?.Enable(); + ResolveMonsterSkpPathHook?.Enable(); + ResolveMonsterTmbPathHook?.Enable(); + ResolveMonsterVfxPathHook?.Enable(); + } + + private void DisableMonsterHooks() + { + ResolveMonsterDecalPathHook?.Disable(); + ResolveMonsterEidPathHook?.Disable(); + ResolveMonsterImcPathHook?.Disable(); + ResolveMonsterMPapPathHook?.Disable(); + ResolveMonsterMdlPathHook?.Disable(); + ResolveMonsterMtrlPathHook?.Disable(); + ResolveMonsterPapPathHook?.Disable(); + ResolveMonsterPhybPathHook?.Disable(); + ResolveMonsterSklbPathHook?.Disable(); + ResolveMonsterSkpPathHook?.Disable(); + ResolveMonsterTmbPathHook?.Disable(); + ResolveMonsterVfxPathHook?.Disable(); + } + + private void DisposeMonsterHooks() + { + ResolveMonsterDecalPathHook?.Dispose(); + ResolveMonsterEidPathHook?.Dispose(); + ResolveMonsterImcPathHook?.Dispose(); + ResolveMonsterMPapPathHook?.Dispose(); + ResolveMonsterMdlPathHook?.Dispose(); + ResolveMonsterMtrlPathHook?.Dispose(); + ResolveMonsterPapPathHook?.Dispose(); + ResolveMonsterPhybPathHook?.Dispose(); + ResolveMonsterSklbPathHook?.Dispose(); + ResolveMonsterSkpPathHook?.Dispose(); + ResolveMonsterTmbPathHook?.Dispose(); + ResolveMonsterVfxPathHook?.Dispose(); + } +} \ No newline at end of file diff --git a/Penumbra/Interop/Resolver/PathResolver.Resolve.cs b/Penumbra/Interop/Resolver/PathResolver.Resolve.cs index c283e9ce..7338f9e4 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Resolve.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Resolve.cs @@ -98,6 +98,43 @@ public unsafe partial class PathResolver private IntPtr ResolveWeaponVfxDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4, ulong unk5 ) => ResolveWeaponPathDetour( drawObject, ResolveWeaponVfxPathHook!.Original( drawObject, path, unk3, unk4, unk5 ) ); + // Monsters + private IntPtr ResolveMonsterDecalDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 ) + => ResolvePathDetour( drawObject, ResolveMonsterDecalPathHook!.Original( drawObject, path, unk3, unk4 ) ); + + private IntPtr ResolveMonsterEidDetour( IntPtr drawObject, IntPtr path, IntPtr unk3 ) + => ResolvePathDetour( drawObject, ResolveMonsterEidPathHook!.Original( drawObject, path, unk3 ) ); + + private IntPtr ResolveMonsterImcDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 ) + => ResolvePathDetour( drawObject, ResolveMonsterImcPathHook!.Original( drawObject, path, unk3, unk4 ) ); + + private IntPtr ResolveMonsterMPapDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4, uint unk5 ) + => ResolvePathDetour( drawObject, ResolveMonsterMPapPathHook!.Original( drawObject, path, unk3, unk4, unk5 ) ); + + private IntPtr ResolveMonsterMdlDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint modelType ) + => ResolvePathDetour( drawObject, ResolveMonsterMdlPathHook!.Original( drawObject, path, unk3, modelType ) ); + + private IntPtr ResolveMonsterMtrlDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4, ulong unk5 ) + => ResolvePathDetour( drawObject, ResolveMonsterMtrlPathHook!.Original( drawObject, path, unk3, unk4, unk5 ) ); + + private IntPtr ResolveMonsterPapDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4, ulong unk5 ) + => ResolvePathDetour( drawObject, ResolveMonsterPapPathHook!.Original( drawObject, path, unk3, unk4, unk5 ) ); + + private IntPtr ResolveMonsterPhybDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 ) + => ResolvePathDetour( drawObject, ResolveMonsterPhybPathHook!.Original( drawObject, path, unk3, unk4 ) ); + + private IntPtr ResolveMonsterSklbDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 ) + => ResolvePathDetour( drawObject, ResolveMonsterSklbPathHook!.Original( drawObject, path, unk3, unk4 ) ); + + private IntPtr ResolveMonsterSkpDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 ) + => ResolvePathDetour( drawObject, ResolveMonsterSkpPathHook!.Original( drawObject, path, unk3, unk4 ) ); + + private IntPtr ResolveMonsterTmbDetour( IntPtr drawObject, IntPtr path, IntPtr unk3 ) + => ResolvePathDetour( drawObject, ResolveMonsterTmbPathHook!.Original( drawObject, path, unk3 ) ); + + private IntPtr ResolveMonsterVfxDetour( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4, ulong unk5 ) + => ResolvePathDetour( drawObject, ResolveMonsterVfxPathHook!.Original( drawObject, path, unk3, unk4, unk5 ) ); + // Implementation [MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )] diff --git a/Penumbra/Interop/Resolver/PathResolver.Weapon.cs b/Penumbra/Interop/Resolver/PathResolver.Weapon.cs index 7fc1f766..0a9ac900 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Weapon.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Weapon.cs @@ -23,7 +23,6 @@ public unsafe partial class PathResolver public Hook< EidResolveDelegate >? ResolveWeaponTmbPathHook; public Hook< MaterialResolveDetour >? ResolveWeaponVfxPathHook; - private void SetupWeaponHooks() { ResolveWeaponDecalPathHook = new Hook< GeneralResolveDelegate >( DrawObjectWeaponVTable[ ResolveDecalIdx ], ResolveWeaponDecalDetour ); diff --git a/Penumbra/Interop/Resolver/PathResolver.cs b/Penumbra/Interop/Resolver/PathResolver.cs index 4f73e762..ad3e7b41 100644 --- a/Penumbra/Interop/Resolver/PathResolver.cs +++ b/Penumbra/Interop/Resolver/PathResolver.cs @@ -25,6 +25,7 @@ public partial class PathResolver : IDisposable SignatureHelper.Initialise( this ); SetupHumanHooks(); SetupWeaponHooks(); + SetupMonsterHooks(); SetupMetaHooks(); } @@ -82,6 +83,7 @@ public partial class PathResolver : IDisposable EnableHumanHooks(); EnableWeaponHooks(); + EnableMonsterHooks(); EnableMtrlHooks(); EnableDataHooks(); EnableMetaHooks(); @@ -100,6 +102,7 @@ public partial class PathResolver : IDisposable Enabled = false; DisableHumanHooks(); DisableWeaponHooks(); + DisableMonsterHooks(); DisableMtrlHooks(); DisableDataHooks(); DisableMetaHooks(); @@ -116,6 +119,7 @@ public partial class PathResolver : IDisposable Disable(); DisposeHumanHooks(); DisposeWeaponHooks(); + DisposeMonsterHooks(); DisposeMtrlHooks(); DisposeDataHooks(); DisposeMetaHooks();