-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathActionManager.cs
118 lines (91 loc) · 4.57 KB
/
ActionManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Hooking;
using Dalamud.Utility;
using ImGuiScene;
using JetBrains.Annotations;
using Action = Lumina.Excel.GeneratedSheets.Action;
namespace RemindMe {
public class ActionManager : IDisposable {
private readonly uint[] forcedActionIds = {3, 7400};
private IntPtr actionManagerPtr;
private RemindMe plugin;
public uint LastActionId;
private Dictionary<uint, Cooldown> cooldownList = new Dictionary<uint, Cooldown>();
private delegate IntPtr StartCooldownDelegate(IntPtr actionManager, uint actionType, uint actionId);
private Hook<StartCooldownDelegate> startCooldownHook;
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate bool IsActionCooldownDelegate(IntPtr actionManager, uint actionType, uint actionId);
private IsActionCooldownDelegate isActionCooldown;
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr GetActionCooldownSlotDelegate(IntPtr actionManager, int cooldownGroup);
public IEnumerable<Action> PlayerActions => Service.Data.Excel.GetSheet<Action>().Where(a => a.IsPlayerAction || forcedActionIds.Contains(a.RowId));
internal TextureWrap GetActionIcon(Action action) {
var iconTex = Service.Data.GetIcon(action.Icon);
var tex = Service.UiBuilder.LoadImageRaw(iconTex.GetRgbaImageData(), iconTex.Header.Width, iconTex.Header.Height, 4);
if (tex != null && tex.ImGuiHandle != IntPtr.Zero) {
return tex;
}
return null;
}
private GetActionCooldownSlotDelegate getActionCooldownSlot;
public ActionManager(RemindMe plugin, IntPtr actionManagerPtr) {
this.actionManagerPtr = actionManagerPtr;
this.plugin = plugin;
var isActionCooldownScan = Service.SigScanner.ScanText("E8 ?? ?? ?? ?? 3C 01 74 45");
isActionCooldown = Marshal.GetDelegateForFunctionPointer<IsActionCooldownDelegate>(isActionCooldownScan);
var getActionCooldownSlotScan = Service.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F 57 FF 48 85 C0");
getActionCooldownSlot = Marshal.GetDelegateForFunctionPointer<GetActionCooldownSlotDelegate>(getActionCooldownSlotScan);
#if DEBUG
var startActionCooldownScan = Service.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? FF 50 18");
startCooldownHook = new Hook<StartCooldownDelegate>(startActionCooldownScan, new StartCooldownDelegate(StartCooldownDetour));
startCooldownHook.Enable();
#endif
Service.Framework.Update += FrameworkOnOnUpdateEvent;
}
private IntPtr StartCooldownDetour(IntPtr actionManager, uint actionType, uint actionId) {
LastActionId = actionId;
return startCooldownHook.Original(actionManager, actionType, actionId);
}
[CanBeNull]
public Action GetAction(uint actionID, bool allowNonPlayer = false) {
return Service.Data.Excel.GetSheet<Action>().FirstOrDefault(a => a.RowId == actionID && (allowNonPlayer || a.IsPlayerAction || forcedActionIds.Contains(a.RowId)));
}
private void FrameworkOnOnUpdateEvent(Framework framework) {
Update();
}
public bool IsActionCooldown(Action action) {
return action.IsPlayerAction && isActionCooldown(actionManagerPtr, 1, action.RowId);
}
public Cooldown GetActionCooldown(Action action) {
if (cooldownList.ContainsKey(action.RowId)) return cooldownList[action.RowId];
var cooldown = new Cooldown(this, action);
cooldownList.Add(action.RowId, cooldown);
return cooldown;
}
public void Dispose() {
startCooldownHook?.Disable();
startCooldownHook?.Dispose();
Service.Framework.Update -= FrameworkOnOnUpdateEvent;
foreach (var a in cooldownList) {
a.Value.Dispose();
}
}
public void Update() {
foreach (var i in cooldownList) {
i.Value.Update();
}
}
public IntPtr GetCooldownPointer(byte actionCooldownGroup) {
return getActionCooldownSlot(actionManagerPtr, actionCooldownGroup - 1);
}
public void ResetTimers() {
foreach (var i in cooldownList) {
i.Value.ResetReadyCountUp();
}
}
}
}