Fix companion identification, extract offsets and vtable indices to separate file.

This commit is contained in:
Ottermandias 2023-01-16 13:02:22 +01:00
parent 79eee0e2c7
commit 4059e0630a
9 changed files with 60 additions and 22 deletions

View file

@ -204,7 +204,7 @@ public sealed partial class ActorManager : IDisposable
if (agent == null || agent->Data == null) if (agent == null || agent->Data == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;
var worldId = *(ushort*)((byte*)agent->Data + 0xC0); var worldId = *(ushort*)((byte*)agent->Data + Offsets.AgentCharaCardDataWorldId);
return CreatePlayer(new ByteString(agent->Data->Name.StringPtr), worldId); return CreatePlayer(new ByteString(agent->Data->Name.StringPtr), worldId);
} }

View file

@ -306,7 +306,7 @@ public partial class ActorManager
{ {
var dataId = actor->DataID; var dataId = actor->DataID;
// Special case for squadron that is also in the game functions, cf. E8 ?? ?? ?? ?? 89 87 ?? ?? ?? ?? 4C 89 BF // Special case for squadron that is also in the game functions, cf. E8 ?? ?? ?? ?? 89 87 ?? ?? ?? ?? 4C 89 BF
if (dataId == 0xf845d) if (dataId == 0xF845D)
dataId = actor->GetNpcID(); dataId = actor->GetNpcID();
if (MannequinIds.Contains(dataId)) if (MannequinIds.Contains(dataId))
{ {
@ -338,7 +338,7 @@ public partial class ActorManager
if (owner == null) if (owner == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;
var dataId = GetCompanionId(actor, owner); var dataId = GetCompanionId(actor, (Character*) owner);
var name = new ByteString(owner->Name); var name = new ByteString(owner->Name);
var homeWorld = ((Character*)owner)->HomeWorld; var homeWorld = ((Character*)owner)->HomeWorld;
return check return check
@ -365,13 +365,13 @@ public partial class ActorManager
/// Obtain the current companion ID for an object by its actor and owner. /// Obtain the current companion ID for an object by its actor and owner.
/// </summary> /// </summary>
private unsafe uint GetCompanionId(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor, private unsafe uint GetCompanionId(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor,
FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* owner) // TODO: CS Update Character* owner) // TODO: CS Update
{ {
return (ObjectKind)actor->ObjectKind switch return (ObjectKind)actor->ObjectKind switch
{ {
ObjectKind.MountType => *(ushort*)((byte*)owner + 0x650 + 0x18), ObjectKind.MountType => owner->Mount.MountId,
(ObjectKind)15 => *(ushort*)((byte*)owner + 0x860 + 0x18), (ObjectKind)15 => owner->Ornament.OrnamentId,
ObjectKind.Companion => *(ushort*)((byte*)actor + 0x1AAC), ObjectKind.Companion => actor->DataID,
_ => actor->DataID, _ => actor->DataID,
}; };
} }

View file

@ -400,17 +400,17 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier
public static unsafe ulong KeyFromCharacterBase(CharacterBase* drawObject) public static unsafe ulong KeyFromCharacterBase(CharacterBase* drawObject)
{ {
var type = (*(delegate* unmanaged<CharacterBase*, uint>**)drawObject)[50](drawObject); var type = (*(delegate* unmanaged<CharacterBase*, uint>**)drawObject)[Offsets.DrawObjectGetModelTypeVfunc](drawObject);
var unk = (ulong)*((byte*)drawObject + 0x8E8) << 8; var unk = (ulong)*((byte*)drawObject + Offsets.DrawObjectModelUnk1) << 8;
return type switch return type switch
{ {
1 => type | unk, 1 => type | unk,
2 => type | unk | ((ulong)*(ushort*)((byte*)drawObject + 0x908) << 16), 2 => type | unk | ((ulong)*(ushort*)((byte*)drawObject + Offsets.DrawObjectModelUnk3) << 16),
3 => type 3 => type
| unk | unk
| ((ulong)*(ushort*)((byte*)drawObject + 0x8F0) << 16) | ((ulong)*(ushort*)((byte*)drawObject + Offsets.DrawObjectModelUnk2) << 16)
| ((ulong)**(ushort**)((byte*)drawObject + 0x910) << 32) | ((ulong)**(ushort**)((byte*)drawObject + Offsets.DrawObjectModelUnk4) << 32)
| ((ulong)**(ushort**)((byte*)drawObject + 0x910) << 40), | ((ulong)**(ushort**)((byte*)drawObject + Offsets.DrawObjectModelUnk3) << 40),
_ => 0u, _ => 0u,
}; };
} }

View file

@ -0,0 +1,35 @@
namespace Penumbra.GameData;
public static class Offsets
{
// ActorManager.Data
public const int AgentCharaCardDataWorldId = 0xC0;
// ObjectIdentification
public const int DrawObjectGetModelTypeVfunc = 50;
private const int DrawObjectModelBase = 0x8E8;
public const int DrawObjectModelUnk1 = DrawObjectModelBase;
public const int DrawObjectModelUnk2 = DrawObjectModelBase + 0x08;
public const int DrawObjectModelUnk3 = DrawObjectModelBase + 0x20;
public const int DrawObjectModelUnk4 = DrawObjectModelBase + 0x28;
// PathResolver.AnimationState
public const int GetGameObjectIdxVfunc = 28;
public const int TimeLinePtr = 0x50;
// PathResolver.Meta
public const int UpdateModelSkip = 0x90c;
public const int GetEqpIndirectSkip1 = 0xA30;
public const int GetEqpIndirectSkip2 = 0xA28;
// FontReloader
public const int ReloadFontsVfunc = 43;
// ObjectReloader
public const int EnableDrawVfunc = 16;
public const int DisableDrawVfunc = 17;
// ResourceHandle
public const int ResourceHandleGetDataVfunc = 23;
public const int ResourceHandleGetLengthVfunc = 17;
}

View file

@ -1,5 +1,6 @@
using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Client.System.Framework;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
using Penumbra.GameData;
namespace Penumbra.Interop; namespace Penumbra.Interop;
@ -51,6 +52,6 @@ public static unsafe class FontReloader
} }
AtkModule = &atkModule->AtkModule; AtkModule = &atkModule->AtkModule;
ReloadFontsFunc = ( ( delegate* unmanaged< AtkModule*, bool, bool, void >* )AtkModule->vtbl )[ 43 ]; ReloadFontsFunc = ( ( delegate* unmanaged< AtkModule*, bool, bool, void >* )AtkModule->vtbl )[ Offsets.ReloadFontsVfunc ];
} }
} }

View file

@ -7,6 +7,7 @@ using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
namespace Penumbra.Interop; namespace Penumbra.Interop;
@ -23,10 +24,10 @@ public unsafe partial class ObjectReloader
// VFuncs that disable and enable draw, used only for GPose actors. // VFuncs that disable and enable draw, used only for GPose actors.
private static void DisableDraw( GameObject actor ) private static void DisableDraw( GameObject actor )
=> ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ 17 ]( actor.Address ); => ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ Offsets.DisableDrawVfunc ]( actor.Address );
private static void EnableDraw( GameObject actor ) private static void EnableDraw( GameObject actor )
=> ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ 16 ]( actor.Address ); => ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ Offsets.EnableDrawVfunc ]( actor.Address );
// Check whether we currently are in GPose. // Check whether we currently are in GPose.
// Also clear the name list. // Also clear the name list.

View file

@ -129,7 +129,7 @@ public unsafe partial class PathResolver
{ {
if( timeline != IntPtr.Zero ) if( timeline != IntPtr.Zero )
{ {
var getGameObjectIdx = ( ( delegate* unmanaged< IntPtr, int >** )timeline )[ 0 ][ 28 ]; var getGameObjectIdx = ( ( delegate* unmanaged< IntPtr, int >** )timeline )[ 0 ][ Offsets.GetGameObjectIdxVfunc ];
var idx = getGameObjectIdx( timeline ); var idx = getGameObjectIdx( timeline );
if( idx >= 0 && idx < Dalamud.Objects.Length ) if( idx >= 0 && idx < Dalamud.Objects.Length )
{ {
@ -192,7 +192,7 @@ public unsafe partial class PathResolver
private void LoadSomePapDetour( IntPtr a1, int a2, IntPtr a3, int a4 ) private void LoadSomePapDetour( IntPtr a1, int a2, IntPtr a3, int a4 )
{ {
using var performance = Penumbra.Performance.Measure( PerformanceType.LoadPap ); using var performance = Penumbra.Performance.Measure( PerformanceType.LoadPap );
var timelinePtr = a1 + 0x50; var timelinePtr = a1 + Offsets.TimeLinePtr;
var last = _animationLoadData; var last = _animationLoadData;
if( timelinePtr != IntPtr.Zero ) if( timelinePtr != IntPtr.Zero )
{ {

View file

@ -95,7 +95,7 @@ public unsafe partial class PathResolver
{ {
// Shortcut because this is called all the time. // Shortcut because this is called all the time.
// Same thing is checked at the beginning of the original function. // Same thing is checked at the beginning of the original function.
if( *( int* )( drawObject + 0x90c ) == 0 ) if( *( int* )( drawObject + Offsets.UpdateModelSkip ) == 0 )
{ {
return; return;
} }
@ -133,7 +133,7 @@ public unsafe partial class PathResolver
{ {
// Shortcut because this is also called all the time. // Shortcut because this is also called all the time.
// Same thing is checked at the beginning of the original function. // Same thing is checked at the beginning of the original function.
if( ( *( byte* )( drawObject + 0xa30 ) & 1 ) == 0 || *( ulong* )( drawObject + 0xa28 ) == 0 ) if( ( *( byte* )( drawObject + Offsets.GetEqpIndirectSkip1 ) & 1 ) == 0 || *( ulong* )( drawObject + Offsets.GetEqpIndirectSkip2 ) == 0 )
{ {
return; return;
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.System.Resource;
using Penumbra.GameData;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
namespace Penumbra.Interop.Structs; namespace Penumbra.Interop.Structs;
@ -87,10 +88,10 @@ public unsafe struct ResourceHandle
// May return null. // May return null.
public static byte* GetData( ResourceHandle* handle ) public static byte* GetData( ResourceHandle* handle )
=> ( ( delegate* unmanaged< ResourceHandle*, byte* > )handle->VTable[ 23 ] )( handle ); => ( ( delegate* unmanaged< ResourceHandle*, byte* > )handle->VTable[ Offsets.ResourceHandleGetDataVfunc ] )( handle );
public static ulong GetLength( ResourceHandle* handle ) public static ulong GetLength( ResourceHandle* handle )
=> ( ( delegate* unmanaged< ResourceHandle*, ulong > )handle->VTable[ 17 ] )( handle ); => ( ( delegate* unmanaged< ResourceHandle*, ulong > )handle->VTable[ Offsets.ResourceHandleGetLengthVfunc ] )( handle );
// Only use these if you know what you are doing. // Only use these if you know what you are doing.