|
3 | 3 | using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; |
4 | 4 | using Dalamud.Game.Text; |
5 | 5 | using Dalamud.Game.Text.SeStringHandling; |
| 6 | +using Dalamud.Hooking; |
6 | 7 | using Dalamud.Plugin.Services; |
| 8 | +using Dalamud.Utility.Signatures; |
| 9 | +using ECommons; |
| 10 | +using FFXIVClientStructs.FFXIV.Client.Game.Object; |
7 | 11 | using NLua; |
8 | 12 | using SomethingNeedDoing.Core.Events; |
9 | 13 | using SomethingNeedDoing.Core.Interfaces; |
@@ -43,8 +47,15 @@ public class MacroScheduler : IMacroScheduler, IDisposable |
43 | 47 | /// </summary> |
44 | 48 | public event EventHandler<MacroErrorEventArgs>? MacroError; |
45 | 49 |
|
| 50 | + private unsafe delegate long OnEmoteFuncDelegate(IntPtr a1, GameObject* source, ushort emoteId, GameObjectId targetId, long a5); |
| 51 | + [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 4C 8B 74 24 ?? 48 8B D9", DetourName = nameof(OnEmoteFuncDetour))] |
| 52 | + private readonly Hook<OnEmoteFuncDelegate> OnEmoteFuncHook = null!; |
| 53 | + |
46 | 54 | public MacroScheduler(NativeMacroEngine nativeEngine, NLuaMacroEngine luaEngine, TriggerEventManager triggerEventManager, MacroHierarchyManager hierarchyManager, IEnumerable<IDisableable> disableablePlugins) |
47 | 55 | { |
| 56 | + Svc.Hook.InitializeFromAttributes(this); |
| 57 | + OnEmoteFuncHook?.Enable(); |
| 58 | + |
48 | 59 | _nativeEngine = nativeEngine; |
49 | 60 | _luaEngine = luaEngine; |
50 | 61 | _triggerEventManager = triggerEventManager; |
@@ -797,6 +808,14 @@ private void OnDutyCompleted(object? sender, ushort e) |
797 | 808 | _ = _triggerEventManager.RaiseTriggerEvent(TriggerEvent.OnDutyCompleted); |
798 | 809 | } |
799 | 810 |
|
| 811 | + private unsafe long OnEmoteFuncDetour(IntPtr a1, GameObject* source, ushort emoteId, GameObjectId targetId, long a5) |
| 812 | + { |
| 813 | + FrameworkLogger.Verbose($"Emote performed: Source={source->NameString}, EmoteId={emoteId}, TargetId={targetId.Id}, a5={a5}"); |
| 814 | + var eventData = new Dictionary<string, object> { { "SourceId", source->EntityId }, { "SourceName", source->NameString }, { "EmoteId", emoteId }, { "TargetId", targetId } }; |
| 815 | + _ = _triggerEventManager.RaiseTriggerEvent(TriggerEvent.OnEmote, eventData); |
| 816 | + return OnEmoteFuncHook!.Original(a1, source, emoteId, targetId, a5); |
| 817 | + } |
| 818 | + |
800 | 819 | private void CheckCharacterPostProcess(IMacro macro) |
801 | 820 | { |
802 | 821 | if (C.ARCharacterPostProcessExcludedCharacters.Any(x => x == Svc.ClientState.LocalContentId)) |
@@ -933,6 +952,7 @@ public void Dispose() |
933 | 952 | _addonEvents.Clear(); |
934 | 953 |
|
935 | 954 | _triggerEventManager.Dispose(); |
| 955 | + OnEmoteFuncHook?.Dispose(); |
936 | 956 | } |
937 | 957 |
|
938 | 958 | /// <inheritdoc/> |
|
0 commit comments