From 62622ee75f1da94e7f73e0ec1f67921c7171bc0a Mon Sep 17 00:00:00 2001 From: Poliwrath Date: Thu, 23 Jul 2020 22:40:51 -0400 Subject: [PATCH 1/7] fix formatting for commands --- Dalamud/Dalamud.cs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 7a33caf87..34da8ef30 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -424,12 +424,12 @@ namespace Dalamud { CommandManager.AddHandler("/xldreloadplugins", new CommandInfo(OnPluginReloadCommand) { HelpMessage = Loc.Localize("DalamudPluginReloadHelp", "Reloads all plugins."), - ShowInHelp = false + ShowInHelp = false }); CommandManager.AddHandler("/xldsay", new CommandInfo(OnCommandDebugSay) { HelpMessage = Loc.Localize("DalamudPrintChatHelp", "Print to chat."), - ShowInHelp = false + ShowInHelp = false }); CommandManager.AddHandler("/xlhelp", new CommandInfo(OnHelpCommand) { @@ -456,57 +456,48 @@ namespace Dalamud { HelpMessage = Loc.Localize("DalamudBotJoinHelp", "Add the XIVLauncher discord bot you set up to your server.") }); - CommandManager.AddHandler("/xlbgmset", new CommandInfo(OnBgmSetCommand) - { + CommandManager.AddHandler("/xlbgmset", new CommandInfo(OnBgmSetCommand) { HelpMessage = Loc.Localize("DalamudBgmSetHelp", "Set the Game background music. Usage: /xlbgmset ") }); #if DEBUG - CommandManager.AddHandler("/xldzpi", new CommandInfo(OnDebugZoneDownInjectCommand) - { + CommandManager.AddHandler("/xldzpi", new CommandInfo(OnDebugZoneDownInjectCommand) { HelpMessage = "Inject zone down channel", ShowInHelp = false }); #endif - CommandManager.AddHandler("/xlbonus", new CommandInfo(OnRouletteBonusNotifyCommand) - { + CommandManager.AddHandler("/xlbonus", new CommandInfo(OnRouletteBonusNotifyCommand) { HelpMessage = Loc.Localize("DalamudBonusHelp", "Notify when a roulette has a bonus you specified. Run without parameters for more info. Usage: /xlbonus ") }); CommandManager.AddHandler("/xldev", new CommandInfo(OnDebugDrawDevMenu) { HelpMessage = Loc.Localize("DalamudDevMenuHelp", "Draw dev menu DEBUG"), - ShowInHelp = false + ShowInHelp = false }); - CommandManager.AddHandler("/xlplugins", new CommandInfo(OnOpenInstallerCommand) - { + CommandManager.AddHandler("/xlplugins", new CommandInfo(OnOpenInstallerCommand) { HelpMessage = Loc.Localize("DalamudInstallerHelp", "Open the plugin installer") }); - this.CommandManager.AddHandler("/xlcredits", new CommandInfo(OnOpenCreditsCommand) { + CommandManager.AddHandler("/xlcredits", new CommandInfo(OnOpenCreditsCommand) { HelpMessage = Loc.Localize("DalamudCreditsHelp", "Opens the credits for dalamud.") }); - this.CommandManager.AddHandler("/xllanguage", new CommandInfo(OnSetLanguageCommand) - { + CommandManager.AddHandler("/xllanguage", new CommandInfo(OnSetLanguageCommand) { HelpMessage = Loc.Localize("DalamudLanguageHelp", "Set the language for the in-game addon and plugins that support it. Available languages: ") + Localization.ApplicableLangCodes.Aggregate("en", (current, code) => current + ", " + code) }); - this.CommandManager.AddHandler("/xlsettings", new CommandInfo(OnOpenSettingsCommand) - { + CommandManager.AddHandler("/xlsettings", new CommandInfo(OnOpenSettingsCommand) { HelpMessage = Loc.Localize("DalamudSettingsHelp", "Change various In-Game-Addon settings like chat channels and the discord bot setup.") }); - this.CommandManager.AddHandler("/xlbugreport", new CommandInfo(OnBugReportCommand) - { + CommandManager.AddHandler("/xlbugreport", new CommandInfo(OnBugReportCommand) { HelpMessage = Loc.Localize("DalamudBugReport", "Upload a log to be analyzed by our professional development team."), ShowInHelp = false }); - - this.CommandManager.AddHandler("/imdebug", new CommandInfo(OnDebugImInfoCommand) - { + CommandManager.AddHandler("/imdebug", new CommandInfo(OnDebugImInfoCommand) { HelpMessage = "ImGui DEBUG", ShowInHelp = false }); From 9d2114ed4bcca4e8cd55e5d5605b6b56e9599cf0 Mon Sep 17 00:00:00 2001 From: Poliwrath Date: Thu, 23 Jul 2020 22:43:49 -0400 Subject: [PATCH 2/7] use Path.Combine for startInfo paths --- Dalamud.Injector/Program.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Dalamud.Injector/Program.cs b/Dalamud.Injector/Program.cs index 4c9d791ca..1328d77ef 100644 --- a/Dalamud.Injector/Program.cs +++ b/Dalamud.Injector/Program.cs @@ -169,12 +169,9 @@ namespace Dalamud.Injector { var ffxivDir = Path.GetDirectoryName(process.MainModule.FileName); var startInfo = new DalamudStartInfo { WorkingDirectory = null, - ConfigurationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + - @"\XIVLauncher\dalamudConfig.json", - PluginDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + - @"\XIVLauncher\installedPlugins", - DefaultPluginDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + - @"\XIVLauncher\devPlugins", + ConfigurationPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "XIVLauncher", "dalamudConfig.json"), + PluginDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "XIVLauncher", "installedPlugins"), + DefaultPluginDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "XIVLauncher", "devPlugins"), GameVersion = File.ReadAllText(Path.Combine(ffxivDir, "ffxivgame.ver")), Language = ClientLanguage.English From 4d541666023b323e84db1d7ce10a46a2f605d936 Mon Sep 17 00:00:00 2001 From: Poliwrath Date: Thu, 23 Jul 2020 22:56:25 -0400 Subject: [PATCH 3/7] move actor offset constants to a separate class --- Dalamud/Game/ClientState/Structs/Actor.cs | 82 ++++++++++++++++------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs index 0d7c9e50a..537963efb 100644 --- a/Dalamud/Game/ClientState/Structs/Actor.cs +++ b/Dalamud/Game/ClientState/Structs/Actor.cs @@ -8,48 +8,78 @@ using Dalamud.Game.ClientState.Actors; namespace Dalamud.Game.ClientState.Structs { + public class ActorOffsets + { + public const int Name = 0x30; + public const int ActorId = 116; + public const int DataId = 128; + public const int OwnerId = 132; + public const int ObjectKind = 140; + public const int SubKind = 141; + public const int IsFriendly = 142; + public const int YalmDistanceFromPlayerX = 144; + public const int PlayerTargetStatus = 145; + public const int YalmDistanceFromPlayerY = 146; + public const int Position = 160; + public const int Rotation = 176; + public const int Customize = 0x17B8; + public const int PlayerCharacterTargetActorId = 0x1F0; + public const int BattleNpcTargetActorId = 0x17F8; + public const int CompanyTag = 0x17D0; + public const int NameId = 0x1868; + public const int CurrentWorld = 0x1884; + public const int HomeWorld = 0x1886; + public const int CurrentHp = 0x1898; + public const int MaxHp = 0x189C; + public const int CurrentMp = 0x18A0; + public const int MaxMp = 0x18AA; + public const int ClassJob = 6358; + public const int Level = 6360; + public const int UIStatusEffects = 0x1958; + } + /// /// Native memory representation of a FFXIV actor. /// [StructLayout(LayoutKind.Explicit)] public struct Actor { - [FieldOffset(0x30)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] + [FieldOffset(ActorOffsets.Name)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Name; - [FieldOffset(116)] public int ActorId; - [FieldOffset(128)] public int DataId; - [FieldOffset(132)] public int OwnerId; - [FieldOffset(140)] public ObjectKind ObjectKind; - [FieldOffset(141)] public byte SubKind; - [FieldOffset(142)] public bool IsFriendly; - [FieldOffset(144)] public byte YalmDistanceFromPlayerX; // Demo says one of these is x distance - [FieldOffset(145)] public byte PlayerTargetStatus; // This is some kind of enum - [FieldOffset(146)] public byte YalmDistanceFromPlayerY; // and the other is z distance - [FieldOffset(160)] public Position3 Position; - [FieldOffset(176)] public float Rotation; // Rotation around the vertical axis (yaw), from -pi to pi radians + [FieldOffset(ActorOffsets.ActorId)] public int ActorId; + [FieldOffset(ActorOffsets.DataId)] public int DataId; + [FieldOffset(ActorOffsets.OwnerId)] public int OwnerId; + [FieldOffset(ActorOffsets.ObjectKind)] public ObjectKind ObjectKind; + [FieldOffset(ActorOffsets.SubKind)] public byte SubKind; + [FieldOffset(ActorOffsets.IsFriendly)] public bool IsFriendly; + [FieldOffset(ActorOffsets.YalmDistanceFromPlayerX)] public byte YalmDistanceFromPlayerX; // Demo says one of these is x distance + [FieldOffset(ActorOffsets.PlayerTargetStatus)] public byte PlayerTargetStatus; // This is some kind of enum + [FieldOffset(ActorOffsets.YalmDistanceFromPlayerY)] public byte YalmDistanceFromPlayerY; // and the other is z distance + [FieldOffset(ActorOffsets.Position)] public Position3 Position; + [FieldOffset(ActorOffsets.Rotation)] public float Rotation; // Rotation around the vertical axis (yaw), from -pi to pi radians - [FieldOffset(0x17B8)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize; + [FieldOffset(ActorOffsets.Customize)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize; - [FieldOffset(0x1F0)] public int PlayerCharacterTargetActorId; - [FieldOffset(0x17F8)] public int BattleNpcTargetActorId; + [FieldOffset(ActorOffsets.PlayerCharacterTargetActorId)] public int PlayerCharacterTargetActorId; + [FieldOffset(ActorOffsets.BattleNpcTargetActorId)] public int BattleNpcTargetActorId; // This field can't be correctly aligned, so we have to cut it manually. - [FieldOffset(0x17d0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + [FieldOffset(ActorOffsets.CompanyTag)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public byte[] CompanyTag; - [FieldOffset(0x1868)] public int NameId; - [FieldOffset(0x1884)] public byte CurrentWorld; - [FieldOffset(0x1886)] public byte HomeWorld; - [FieldOffset(0x1898)] public int CurrentHp; - [FieldOffset(0x189C)] public int MaxHp; - [FieldOffset(0x18A0)] public int CurrentMp; + [FieldOffset(ActorOffsets.NameId)] public int NameId; + [FieldOffset(ActorOffsets.CurrentWorld)] public byte CurrentWorld; + [FieldOffset(ActorOffsets.HomeWorld)] public byte HomeWorld; + [FieldOffset(ActorOffsets.CurrentHp)] public int CurrentHp; + [FieldOffset(ActorOffsets.MaxHp)] public int MaxHp; + [FieldOffset(ActorOffsets.CurrentMp)] public int CurrentMp; // This value is weird. It seems to change semi-randomly between 0 and 10k, definitely // in response to mp-using events, but it doesn't often have a value and the changing seems // somewhat arbitrary. - [FieldOffset(0x18AA)] public int MaxMp; - [FieldOffset(6358)] public byte ClassJob; - [FieldOffset(6360)] public byte Level; - [FieldOffset(0x1958)][MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public StatusEffect[] UIStatusEffects; + [FieldOffset(ActorOffsets.MaxMp)] public int MaxMp; + [FieldOffset(ActorOffsets.ClassJob)] public byte ClassJob; + [FieldOffset(ActorOffsets.Level)] public byte Level; + [FieldOffset(ActorOffsets.UIStatusEffects)][MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public StatusEffect[] UIStatusEffects; } } From 2c02a4b28ba9f47415b2f4393886dfc981adfa0f Mon Sep 17 00:00:00 2001 From: Poliwrath Date: Thu, 23 Jul 2020 23:07:04 -0400 Subject: [PATCH 4/7] toggle dev menu --- Dalamud/Dalamud.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 34da8ef30..36cd31cb8 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -662,7 +662,7 @@ namespace Dalamud { } private void OnDebugDrawDevMenu(string command, string arguments) { - this.isImguiDrawDevMenu = true; + this.isImguiDrawDevMenu = !this.isImguiDrawDevMenu; } private void OnDebugImInfoCommand(string command, string arguments) { From 73bb52d1b525390871c08067b0a860967202cf08 Mon Sep 17 00:00:00 2001 From: Poliwrath Date: Mon, 27 Jul 2020 02:45:02 -0400 Subject: [PATCH 5/7] catch exception if loading DalamudConfiguration fails --- Dalamud/Configuration/DalamudConfiguration.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Dalamud/Configuration/DalamudConfiguration.cs b/Dalamud/Configuration/DalamudConfiguration.cs index b7296344c..5e52d5c7e 100644 --- a/Dalamud/Configuration/DalamudConfiguration.cs +++ b/Dalamud/Configuration/DalamudConfiguration.cs @@ -5,6 +5,7 @@ using Dalamud.Configuration; using Dalamud.DiscordBot; using Dalamud.Game.Chat; using Newtonsoft.Json; +using Serilog; namespace Dalamud { @@ -43,7 +44,17 @@ namespace Dalamud public string ConfigPath; public static DalamudConfiguration Load(string path) { - var deserialized = JsonConvert.DeserializeObject(File.ReadAllText(path)); + DalamudConfiguration deserialized; + try + { + deserialized = JsonConvert.DeserializeObject(File.ReadAllText(path)); + } + catch (Exception ex) + { + Log.Warning(ex, "Failed to load DalamudConfiguration at {0}", path); + deserialized = new DalamudConfiguration(); + } + deserialized.ConfigPath = path; return deserialized; From d9c8eeedd34ec67f869ffa6f64f465983a513be6 Mon Sep 17 00:00:00 2001 From: pohky Date: Tue, 28 Jul 2020 10:40:32 +0200 Subject: [PATCH 6/7] Target Info add target info to ClientState --- Dalamud/Game/ClientState/ClientState.cs | 7 +++++ .../ClientState/ClientStateAddressResolver.cs | 3 ++ Dalamud/Game/ClientState/Targets.cs | 28 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 Dalamud/Game/ClientState/Targets.cs 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); } } } diff --git a/Dalamud/Game/ClientState/Targets.cs b/Dalamud/Game/ClientState/Targets.cs new file mode 100644 index 000000000..0046093b5 --- /dev/null +++ b/Dalamud/Game/ClientState/Targets.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.InteropServices; +using Dalamud.Game.ClientState.Actors.Types; + +namespace Dalamud.Game.ClientState { + public sealed class Targets { + private ClientStateAddressResolver Address { get; } + private Dalamud dalamud; + + public Actor CurrentTarget => GetActorByOffset(0x80); + public Actor MouseOverTarget => GetActorByOffset(0xD0); + public Actor FocusTarget => GetActorByOffset(0xF8); + public Actor PreviousTarget => GetActorByOffset(0x110); + + internal Targets(Dalamud dalamud, ClientStateAddressResolver addressResolver) { + this.dalamud = dalamud; + Address = addressResolver; + } + + 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; + var data = Marshal.PtrToStructure(actorAddress); + return new Actor(actorAddress, data, this.dalamud); + } + } +} From 469fecf48452cc0b7dfba6b86c5f915e122a34bb Mon Sep 17 00:00:00 2001 From: pohky Date: Tue, 28 Jul 2020 12:07:25 +0200 Subject: [PATCH 7/7] Target Info Change casting actors to the right type methods for changing targets --- Dalamud/Game/ClientState/Actors/ActorTable.cs | 2 +- Dalamud/Game/ClientState/Actors/Targets.cs | 48 +++++++++++++++++++ Dalamud/Game/ClientState/Targets.cs | 28 ----------- 3 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 Dalamud/Game/ClientState/Actors/Targets.cs delete mode 100644 Dalamud/Game/ClientState/Targets.cs 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/Targets.cs b/Dalamud/Game/ClientState/Targets.cs deleted file mode 100644 index 0046093b5..000000000 --- a/Dalamud/Game/ClientState/Targets.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Dalamud.Game.ClientState.Actors.Types; - -namespace Dalamud.Game.ClientState { - public sealed class Targets { - private ClientStateAddressResolver Address { get; } - private Dalamud dalamud; - - public Actor CurrentTarget => GetActorByOffset(0x80); - public Actor MouseOverTarget => GetActorByOffset(0xD0); - public Actor FocusTarget => GetActorByOffset(0xF8); - public Actor PreviousTarget => GetActorByOffset(0x110); - - internal Targets(Dalamud dalamud, ClientStateAddressResolver addressResolver) { - this.dalamud = dalamud; - Address = addressResolver; - } - - 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; - var data = Marshal.PtrToStructure(actorAddress); - return new Actor(actorAddress, data, this.dalamud); - } - } -}