diff --git a/Dalamud/Game/Internal/Gui/Addon/Addon.cs b/Dalamud/Game/Internal/Gui/Addon/Addon.cs new file mode 100644 index 000000000..b586dbd56 --- /dev/null +++ b/Dalamud/Game/Internal/Gui/Addon/Addon.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.Internal.Gui.Addon { + public class Addon { + public IntPtr Address; + protected Structs.Addon addonStruct; + + public Addon(IntPtr address, Structs.Addon addonStruct) { + this.Address = address; + this.addonStruct = addonStruct; + } + + public string Name => this.addonStruct.Name; + public short X => this.addonStruct.X; + public short Y => this.addonStruct.Y; + public float Scale => this.addonStruct.Scale; + + public bool Visible => (this.addonStruct.Flags & 0x20) == 1; + } +} diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs index 16e2ed3e3..adbd592ed 100644 --- a/Dalamud/Game/Internal/Gui/GameGui.cs +++ b/Dalamud/Game/Internal/Gui/GameGui.cs @@ -48,6 +48,14 @@ namespace Dalamud.Game.Internal.Gui { private delegate IntPtr ToggleUiHideDelegate(IntPtr thisPtr, byte unknownByte); private readonly Hook toggleUiHideHook; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate IntPtr GetBaseUIObjectDelegate(); + private readonly GetBaseUIObjectDelegate getBaseUIObject; + + [UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Ansi)] + private delegate IntPtr GetUIObjectByNameDelegate(IntPtr thisPtr, string uiName, int index); + private readonly GetUIObjectByNameDelegate getUIObjectByName; + public bool GameUiHidden { get; private set; } /// @@ -103,6 +111,9 @@ namespace Dalamud.Game.Internal.Gui { Marshal.GetDelegateForFunctionPointer(Address.ScreenToWorld); this.toggleUiHideHook = new Hook(Address.ToggleUiHide, new ToggleUiHideDelegate(ToggleUiHideDetour), this); + + this.getBaseUIObject = Marshal.GetDelegateForFunctionPointer(Address.GetBaseUIObject); + this.getUIObjectByName = Marshal.GetDelegateForFunctionPointer(Address.GetUIObjectByName); } private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) { @@ -306,6 +317,27 @@ namespace Dalamud.Game.Internal.Gui { return this.toggleUiHideHook.Original(thisPtr, unknownByte); } + /// + /// Gets the pointer to the UI Object with the given name and index. + /// + /// Name of UI to find + /// Index of UI to find (1-indexed) + /// IntPtr.Zero if unable to find UI, otherwise IntPtr pointing to the start of the UI Object + public IntPtr GetUiObjectByName(string name, int index) { + var baseUi = this.getBaseUIObject(); + if (baseUi == IntPtr.Zero) return IntPtr.Zero; + var baseUiProperties = Marshal.ReadIntPtr(baseUi, 0x20); + if (baseUiProperties == IntPtr.Zero) return IntPtr.Zero; + return this.getUIObjectByName(baseUiProperties, name, index); + } + + public Addon.Addon GetAddonByName(string name, int index) { + var addonMem = GetUiObjectByName(name, index); + if (addonMem == IntPtr.Zero) return null; + var addonStruct = Marshal.PtrToStructure(addonMem); + return new Addon.Addon(addonMem, addonStruct); + } + public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0); public void Enable() { diff --git a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs index 3da0ecc8a..47e758da7 100644 --- a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs +++ b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs @@ -15,6 +15,8 @@ namespace Dalamud.Game.Internal.Gui { public IntPtr GetMatrixSingleton { get; private set; } public IntPtr ScreenToWorld { get; private set; } public IntPtr ToggleUiHide { get; set; } + public IntPtr GetBaseUIObject { get; private set; } + public IntPtr GetUIObjectByName { get; private set; } public GameGuiAddressResolver(IntPtr baseAddress) { BaseAddress = baseAddress; @@ -37,6 +39,8 @@ namespace Dalamud.Game.Internal.Gui { GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1"); ToggleUiHide = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 0F B6 B9 ?? ?? ?? ?? B8 ?? ?? ?? ??"); + GetBaseUIObject = sig.ScanText("E8 ?? ?? ?? ?? 41 B8 01 00 00 00 48 8D 15 ?? ?? ?? ?? 48 8B 48 20 E8 ?? ?? ?? ?? 48 8B CF"); + GetUIObjectByName = sig.ScanText("E8 ?? ?? ?? ?? 48 8B CF 48 89 87 ?? ?? 00 00 E8 ?? ?? ?? ?? 41 B8 01 00 00 00"); } } } diff --git a/Dalamud/Game/Internal/Gui/Structs/Addon.cs b/Dalamud/Game/Internal/Gui/Structs/Addon.cs new file mode 100644 index 000000000..88b91e969 --- /dev/null +++ b/Dalamud/Game/Internal/Gui/Structs/Addon.cs @@ -0,0 +1,24 @@ +using System.Runtime.InteropServices; + +namespace Dalamud.Game.Internal.Gui.Structs { + + public class AddonOffsets { + public const int Name = 0x8; + public const int Flags = 0x182; + public const int X = 0x1BC; + public const int Y = 0x1BE; + public const int Scale = 0x1AC; + } + + [StructLayout(LayoutKind.Explicit)] + public struct Addon { + [FieldOffset(AddonOffsets.Name), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] + public string Name; + + [FieldOffset(AddonOffsets.Flags)] public byte Flags; + [FieldOffset(AddonOffsets.X)] public short X; + [FieldOffset(AddonOffsets.Y)] public short Y; + [FieldOffset(AddonOffsets.Scale)] public float Scale; + + } +}