diff --git a/Dalamud/Game/ClientState/Actors/ActorTable.cs b/Dalamud/Game/ClientState/Actors/ActorTable.cs index 1b82708e1..d520b5979 100644 --- a/Dalamud/Game/ClientState/Actors/ActorTable.cs +++ b/Dalamud/Game/ClientState/Actors/ActorTable.cs @@ -60,7 +60,7 @@ namespace Dalamud.Game.ClientState.Actors { get => ActorsCache[index]; } - private Actor ReadActorFromMemory(IntPtr offset) + internal Actor ReadActorFromMemory(IntPtr offset) { try { var actorStruct = Marshal.PtrToStructure(offset); diff --git a/Dalamud/Game/ClientState/Actors/Targets.cs b/Dalamud/Game/ClientState/Actors/Targets.cs new file mode 100644 index 000000000..04bdb8839 --- /dev/null +++ b/Dalamud/Game/ClientState/Actors/Targets.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.InteropServices; +using Dalamud.Game.ClientState.Actors.Types; + +namespace Dalamud.Game.ClientState.Actors { + public static class TargetOffsets { + public const int CurrentTarget = 0x80; + public const int MouseOverTarget = 0xD0; + public const int FocusTarget = 0xF8; + public const int PreviousTarget = 0x110; + } + + public sealed class Targets { + private ClientStateAddressResolver Address { get; } + private Dalamud dalamud; + + public Actor CurrentTarget => GetActorByOffset(TargetOffsets.CurrentTarget); + public Actor MouseOverTarget => GetActorByOffset(TargetOffsets.MouseOverTarget); + public Actor FocusTarget => GetActorByOffset(TargetOffsets.FocusTarget); + public Actor PreviousTarget => GetActorByOffset(TargetOffsets.PreviousTarget); + + internal Targets(Dalamud dalamud, ClientStateAddressResolver addressResolver) { + this.dalamud = dalamud; + Address = addressResolver; + } + + public void SetCurrentTarget(Actor actor) => SetTarget(actor?.Address ?? IntPtr.Zero, TargetOffsets.CurrentTarget); + public void SetCurrentTarget(IntPtr actorAddress) => SetTarget(actorAddress, TargetOffsets.CurrentTarget); + + public void SetFocusTarget(Actor actor) => SetTarget(actor?.Address ?? IntPtr.Zero, TargetOffsets.FocusTarget); + public void SetFocusTarget(IntPtr actorAddress) => SetTarget(actorAddress, TargetOffsets.FocusTarget); + + public void ClearCurrentTarget() => SetCurrentTarget(IntPtr.Zero); + public void ClearFocusTarget() => SetFocusTarget(IntPtr.Zero); + + private void SetTarget(IntPtr actorAddress, int offset) { + if (Address.TargetManager == IntPtr.Zero) return; + Marshal.WriteIntPtr(Address.TargetManager, offset, actorAddress); + } + + private Actor GetActorByOffset(int offset) { + if (Address.TargetManager == IntPtr.Zero) return null; + var actorAddress = Marshal.ReadIntPtr(Address.TargetManager + offset); + if (actorAddress == IntPtr.Zero) return null; + return this.dalamud.ClientState.Actors.ReadActorFromMemory(actorAddress); + } + } +} diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index 2275345a5..8745931b8 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -97,6 +97,11 @@ namespace Dalamud.Game.ClientState /// public Condition Condition; + /// + /// The class facilitating target data access + /// + public Targets Targets; + /// /// Set up client state access. /// @@ -121,6 +126,8 @@ namespace Dalamud.Game.ClientState this.Condition = new Condition( Address ); + this.Targets = new Targets(dalamud, Address); + Log.Verbose("SetupTerritoryType address {SetupTerritoryType}", Address.SetupTerritoryType); this.setupTerritoryTypeHook = new Hook(Address.SetupTerritoryType, diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index e858ac6fc..9787cb7ee 100644 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs @@ -10,6 +10,7 @@ namespace Dalamud.Game.ClientState public IntPtr LocalContentId { get; private set; } public IntPtr JobGaugeData { get; private set; } public IntPtr KeyboardState { get; private set; } + public IntPtr TargetManager { get; private set; } // Functions public IntPtr SetupTerritoryType { get; private set; } @@ -35,6 +36,8 @@ namespace Dalamud.Game.ClientState PartyListUpdate = sig.ScanText("E8 ?? ?? ?? ?? 49 8B D4 4C 8D 87 ?? ?? ?? ??"); ConditionFlags = sig.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? BA ?? ?? ?? ?? 45 33 C0"); + + TargetManager = sig.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? FF 50 ?? 48 85 DB", 3); } } }