add Hovered Action

This commit is contained in:
Cara 2021-01-29 12:24:43 +10:30
parent 17d6901cd3
commit 1133bd7af0
4 changed files with 115 additions and 0 deletions

View file

@ -23,6 +23,14 @@ namespace Dalamud.Game.Internal.Gui {
private delegate IntPtr HandleItemOutDelegate(IntPtr hoverState, IntPtr a2, IntPtr a3, ulong a4);
private readonly Hook<HandleItemOutDelegate> handleItemOutHook;
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void HandleActionHoverDelegate(IntPtr hoverState, HoverActionKind a2, uint a3, int a4, byte a5);
private readonly Hook<HandleActionHoverDelegate> handleActionHoverHook;
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr HandleActionOutDelegate(IntPtr agentActionDetail, IntPtr a2, IntPtr a3, int a4);
private Hook<HandleActionOutDelegate> handleActionOutHook;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr GetUIObjectDelegate();
private readonly GetUIObjectDelegate getUIObject;
@ -69,11 +77,21 @@ namespace Dalamud.Game.Internal.Gui {
/// If > 1.000.000, subtract 1.000.000 and treat it as HQ
/// </summary>
public ulong HoveredItem { get; set; }
/// <summary>
/// The action ID that is current hovered by the player. 0 when no action is hovered.
/// </summary>
public HoveredAction HoveredAction { get; } = new HoveredAction();
/// <summary>
/// Event that is fired when the currently hovered item changes.
/// </summary>
public EventHandler<ulong> HoveredItemChanged { get; set; }
/// <summary>
/// Event that is fired when the currently hovered action changes.
/// </summary>
public EventHandler<HoveredAction> HoveredActionChanged { get; set; }
public GameGui(IntPtr baseAddress, SigScanner scanner, Dalamud dalamud) {
Address = new GameGuiAddressResolver(baseAddress);
@ -103,6 +121,15 @@ namespace Dalamud.Game.Internal.Gui {
new HandleItemOutDelegate(HandleItemOutDetour),
this);
this.handleActionHoverHook =
new Hook<HandleActionHoverDelegate>(Address.HandleActionHover,
new HandleActionHoverDelegate(HandleActionHoverDetour),
this);
this.handleActionOutHook =
new Hook<HandleActionOutDelegate>(Address.HandleActionOut,
new HandleActionOutDelegate(HandleActionOutDetour),
this);
this.getUIObject = Marshal.GetDelegateForFunctionPointer<GetUIObjectDelegate>(Address.GetUIObject);
this.getMatrixSingleton =
@ -167,6 +194,51 @@ namespace Dalamud.Game.Internal.Gui {
return retVal;
}
private void HandleActionHoverDetour(IntPtr hoverState, HoverActionKind actionKind, uint actionId, int a4, byte a5)
{
handleActionHoverHook.Original(hoverState, actionKind, actionId, a4, a5);
HoveredAction.ActionKind = actionKind;
HoveredAction.BaseActionID = actionId;
HoveredAction.ActionID = (uint) Marshal.ReadInt32(hoverState, 0x3C);
try
{
HoveredActionChanged?.Invoke(this, this.HoveredAction);
} catch (Exception e)
{
Log.Error(e, "Could not dispatch HoveredItemChanged event.");
}
Log.Verbose("HoverActionId: {0}/{1} this:{2}", actionKind, actionId, hoverState.ToInt64().ToString("X"));
}
private IntPtr HandleActionOutDetour(IntPtr agentActionDetail, IntPtr a2, IntPtr a3, int a4)
{
var retVal = handleActionOutHook.Original(agentActionDetail, a2, a3, a4);
if (a3 != IntPtr.Zero && a4 == 1)
{
var a3Val = Marshal.ReadByte(a3, 0x8);
if (a3Val == 255)
{
this.HoveredAction.ActionKind = HoverActionKind.None;
HoveredAction.BaseActionID = 0;
HoveredAction.ActionID = 0;
try
{
HoveredActionChanged?.Invoke(this, this.HoveredAction);
} catch (Exception e)
{
Log.Error(e, "Could not dispatch HoveredActionChanged event.");
}
Log.Verbose("HoverActionId: 0");
}
}
return retVal;
}
/// <summary>
/// Opens the in-game map with a flag on the location of the parameter
/// </summary>
@ -347,6 +419,8 @@ namespace Dalamud.Game.Internal.Gui {
this.handleItemHoverHook.Enable();
this.handleItemOutHook.Enable();
this.toggleUiHideHook.Enable();
this.handleActionHoverHook.Enable();
this.handleActionOutHook.Enable();
}
public void Dispose() {
@ -355,6 +429,8 @@ namespace Dalamud.Game.Internal.Gui {
this.handleItemHoverHook.Dispose();
this.handleItemOutHook.Dispose();
this.toggleUiHideHook.Dispose();
this.handleActionHoverHook.Dispose();
this.handleActionOutHook.Dispose();
}
}
}

View file

@ -11,6 +11,8 @@ namespace Dalamud.Game.Internal.Gui {
public IntPtr SetGlobalBgm { get; private set; }
public IntPtr HandleItemHover { get; set; }
public IntPtr HandleItemOut { get; set; }
public IntPtr HandleActionHover { get; set; }
public IntPtr HandleActionOut { get; set; }
public IntPtr GetUIObject { get; private set; }
public IntPtr GetMatrixSingleton { get; private set; }
public IntPtr ScreenToWorld { get; private set; }
@ -35,6 +37,8 @@ namespace Dalamud.Game.Internal.Gui {
SetGlobalBgm = sig.ScanText("4C 8B 15 ?? ?? ?? ?? 4D 85 D2 74 58");
HandleItemHover = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 89 AE ?? ?? ?? ??");
HandleItemOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 4D");
HandleActionHover = sig.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 83 F8 0F");
HandleActionOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B DA 48 8B F9 4D 85 C0 74 1F");
GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9");
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");

View file

@ -0,0 +1,16 @@
namespace Dalamud.Game.Internal.Gui {
/// <summary>
/// ActionKinds used in AgentActionDetail.
/// </summary>
public enum HoverActionKind {
None = 0,
Action = 21,
GeneralAction = 23,
CompanionOrder = 24,
MainCommand = 25,
ExtraCommand = 26,
PetOrder = 28,
Trait = 29,
}
}

View file

@ -0,0 +1,19 @@
namespace Dalamud.Game.Internal.Gui {
public class HoveredAction {
/// <summary>
/// The base action ID
/// </summary>
public uint BaseActionID { get; set; } = 0;
/// <summary>
/// Action ID accounting for automatic upgrades.
/// </summary>
public uint ActionID { get; set; } = 0;
/// <summary>
/// The type of action
/// </summary>
public HoverActionKind ActionKind { get; set; } = HoverActionKind.None;
}
}