Skip to content

Commit aad4284

Browse files
committed
4.0.9
1 parent cb6380a commit aad4284

File tree

5 files changed

+179
-353
lines changed

5 files changed

+179
-353
lines changed

MOAction/Configuration/MoActionStack.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Dalamud.Game.ClientState.Keys;
1+
using Dalamud.Data;
2+
using Dalamud.Game.ClientState.Keys;
23
using System;
34
using System.Collections.Generic;
45
using System.Linq;
@@ -28,6 +29,7 @@ public MoActionStack(Lumina.Excel.GeneratedSheets.Action baseaction, List<StackE
2829

2930
public bool Equals(ConfigurationEntry c)
3031
{
32+
if (c.Stack.Count != Entries.Count) return false;
3133
for (int i = 0; i < Entries.Count; i++)
3234
{
3335
var myEntry = Entries[i];
@@ -50,5 +52,11 @@ public override bool Equals(object obj)
5052
var x = (MoActionStack)obj;
5153
return BaseAction.RowId == x.BaseAction.RowId && Job == x.Job;
5254
}
55+
56+
public string GetJob(DataManager dm)
57+
{
58+
if (Job == "Unset Job") return Job;
59+
return dm.GetExcelSheet<Lumina.Excel.GeneratedSheets.ClassJob>().First(x => x.RowId.ToString() == Job).Abbreviation;
60+
}
5361
}
5462
}

MOAction/MOAction.cs

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
using ImGuiNET;
2222
using Dalamud.Game.ClientState.Statuses;
2323
using FFXIVClientStructs.FFXIV.Client.Game;
24+
using Lumina.Excel.GeneratedSheets;
25+
using static MOAction.MOActionAddressResolver;
2426

2527
namespace MOAction
2628
{
@@ -49,6 +51,9 @@ public delegate bool OnRequestActionDetour(long param_1, uint param_2, ulong par
4951
private Hook<OnRequestActionDetour> requestActionHook;
5052
private Hook<OnSetUiMouseoverEntityId> uiMoEntityIdHook;
5153

54+
public unsafe delegate RecastTimer* GetGroupTimerDelegate(void* @this, int cooldownGroup);
55+
private readonly GetGroupTimerDelegate getGroupTimer;
56+
5257
public List<MoActionStack> Stacks { get; set; }
5358
private DalamudPluginInterface pluginInterface;
5459
private IEnumerable<Lumina.Excel.GeneratedSheets.Action> RawActions;
@@ -67,7 +72,9 @@ public delegate bool OnRequestActionDetour(long param_1, uint param_2, ulong par
6772
public bool IsGuiMOEnabled = false;
6873
public bool IsFieldMOEnabled = false;
6974

70-
private IntPtr thing;
75+
private IntPtr AnimLock;
76+
77+
private bool IsLocked => Marshal.ReadInt32(AnimLock) != 0;
7178

7279
public DataManager dataManager;
7380
public TargetManager targetManager;
@@ -86,6 +93,8 @@ public MOAction(SigScanner scanner, ClientState clientstate,
8693
{
8794
clientstate.Login += LoadClientModules;
8895
clientstate.Logout += ClearClientModules;
96+
if (clientstate.IsLoggedIn)
97+
LoadClientModules(null, null);
8998

9099
fieldMOLocation = scanner.GetStaticAddressFromSig("E8 ?? ?? ?? ?? 83 BF ?? ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 48 8D 4C 24 ??", 0x283);
91100
focusTargLocation = scanner.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 48 89 5C 24 ?? BB ?? ?? ?? ?? 48 89 7C 24 ??", 0);
@@ -108,7 +117,8 @@ public MOAction(SigScanner scanner, ClientState clientstate,
108117

109118
RALDelegate = Marshal.GetDelegateForFunctionPointer<RequestActionLocationDelegate>(Address.RequestActionLocation);
110119
PostRequestResolver = Marshal.GetDelegateForFunctionPointer<PostRequest>(Address.PostRequest);
111-
thing = scanner.Module.BaseAddress + 0x1d8e490;
120+
getGroupTimer = Marshal.GetDelegateForFunctionPointer<GetGroupTimerDelegate>(Address.GetGroupTimer);
121+
//thing = scanner.Module.BaseAddress + 0x1d8e490;
112122

113123
Stacks = new();
114124

@@ -120,6 +130,7 @@ public MOAction(SigScanner scanner, ClientState clientstate,
120130
requestActionHook = new Hook<OnRequestActionDetour>(Address.RequestAction, new OnRequestActionDetour(HandleRequestAction));
121131
uiMoEntityIdHook = new Hook<OnSetUiMouseoverEntityId>(Address.SetUiMouseoverEntityId, new OnSetUiMouseoverEntityId(HandleUiMoEntityId));
122132
PlaceholderResolver = Marshal.GetDelegateForFunctionPointer<ResolvePlaceholderActor>(Address.ResolvePlaceholderText);
133+
AnimLock = Address.AnimLock;
123134
//MagicUiObject = IntPtr.Zero;
124135

125136
enabledActions = new();
@@ -163,6 +174,11 @@ public void Dispose()
163174
//reqlochook.Dispose();
164175
}
165176

177+
public unsafe RecastTimer* GetGroupRecastTimer(int group)
178+
{
179+
return group < 1 ? null : getGroupTimer(AM, group - 1);
180+
}
181+
166182
private void HandleUiMoEntityId(long param1, long param2)
167183
{
168184
//Log.Information("UI MO: {0}", param2);
@@ -176,25 +192,36 @@ private bool ReqLocDetour(IntPtr actionMgr, uint type, uint id, uint targetId, r
176192
return reqlochook.Original(actionMgr, type, id, targetId, ref location, zero);
177193
}
178194

179-
private bool HandleRequestAction(long param_1, uint param_2, ulong param_3, long param_4,
195+
private unsafe bool HandleRequestAction(long param_1, uint actionType, ulong actionID, long param_4,
180196
uint param_5, uint param_6, int param_7)
181197
{
182-
var (action, target) = GetActionTarget((uint)param_3, param_2);
198+
if (actionType != 1) return requestActionHook.Original(param_1, actionType, actionID, param_4, param_5, param_6, param_7);
199+
var (action, target) = GetActionTarget((uint)actionID, actionType);
183200
void EnqueueGroundTarget()
184201
{
185202
IntPtr self = (IntPtr)param_1;
186-
187203
Marshal.WriteInt32(self + 128, (int)param_6);
188204
Marshal.WriteInt32(self + 132, (int)param_7);
189205
Marshal.WriteByte(self + 104, 1);
190-
Marshal.WriteInt32(self + 108, (int)param_2);
206+
Marshal.WriteInt32(self + 108, (int)actionType);
191207
Marshal.WriteInt32(self + 112, (int)action.RowId);
192208
Marshal.WriteInt64(self + 120, param_4);
193209
}
210+
void DequeueGroundTarget()
211+
{
212+
IntPtr self = (IntPtr)param_1;
213+
214+
Marshal.WriteInt32(self + 128, 0);
215+
Marshal.WriteInt32(self + 132, 0);
216+
Marshal.WriteByte(self + 104, 0);
217+
Marshal.WriteInt32(self + 108, 0);
218+
Marshal.WriteInt32(self + 112, 0);
219+
Marshal.WriteInt64(self + 120, 0);
220+
}
194221

195-
if (action == null) return requestActionHook.Original(param_1, param_2, param_3, param_4, param_5, param_6, param_7);
222+
if (action == null) return requestActionHook.Original(param_1, actionType, actionID, param_4, param_5, param_6, param_7);
196223
if (action.Name == "Earthly Star" && clientState.LocalPlayer.StatusList.Any(x => x.StatusId == 1248 || x.StatusId == 1224))
197-
return requestActionHook.Original(param_1, param_2, param_3, param_4, param_5, param_6, param_7);
224+
return requestActionHook.Original(param_1, actionType, actionID, param_4, param_5, param_6, param_7);
198225
// Ground target "at my cursor"
199226
if (action != null && target == null)
200227
{
@@ -204,40 +231,43 @@ void EnqueueGroundTarget()
204231
{
205232
var playerpos = clientState.LocalPlayer.Position;
206233
var distance = Vector3.Distance(playerpos, pos);
207-
if (distance > action.Range + 1)
234+
if (distance > action.Range)
208235
{
209-
pos = GetClampedGroundCoords(playerpos, pos, action.Range+1);
236+
pos = GetClampedGroundCoords(playerpos, pos, action.Range);
210237
}
211238

212239
}
213-
EnqueueGroundTarget();
214-
bool returnval = RALDelegate((IntPtr)param_1, param_2, action.RowId, (uint)param_4, ref pos, 0);
215-
return returnval;
240+
if (IsLocked) EnqueueGroundTarget();
241+
//if (!AM->IsRecastTimerActive((ActionType)param_2, action.RowId)) return RALDelegate((IntPtr)param_1, param_2, action.RowId, (uint)param_4, ref pos, 0);
242+
return RALDelegate((IntPtr)param_1, actionType, action.RowId, (uint)param_4, ref pos, 0);
243+
//DequeueGroundTarget();
244+
//return false;
216245

217246
}
218247

219248
if (action != null && target != null)
220249
{
221250
// ground target at non-mouse
222-
if (action.CastType == 7) {
251+
if (action.TargetArea) {
223252

224253
var targpos = target.Position;
225254
if (Configuration.OtherGroundClamp)
226255
{
227256
var playerpos = clientState.LocalPlayer.Position;
228257
var distance = Vector3.Distance(playerpos, targpos);
229-
if (distance > action.Range + 1)
258+
if (distance > action.Range)
230259
{
231-
targpos = GetClampedGroundCoords(playerpos, targpos, action.Range + 1);
260+
targpos = GetClampedGroundCoords(playerpos, targpos, action.Range);
232261
}
233262
}
234-
EnqueueGroundTarget();
235-
bool returnval = RALDelegate((IntPtr)param_1, param_2, action.RowId, (uint)param_4, ref targpos, 0);
263+
if (IsLocked)
264+
EnqueueGroundTarget();
265+
bool returnval = RALDelegate((IntPtr)param_1, actionType, action.RowId, (uint)param_4, ref targpos, 0);
236266
return returnval;
237267
}
238-
return requestActionHook.Original(param_1, param_2, action.RowId, target.ObjectId, param_5, param_6, param_7);
268+
return requestActionHook.Original(param_1, actionType, action.RowId, target.ObjectId, param_5, param_6, param_7);
239269
}
240-
return requestActionHook.Original(param_1, param_2, param_3, param_4, param_5, param_6, param_7);
270+
return requestActionHook.Original(param_1, actionType, actionID, param_4, param_5, param_6, param_7);
241271
}
242272

243273
private Vector3 GetClampedGroundCoords(Vector3 self, Vector3 dest, int range)
@@ -276,7 +306,7 @@ private Vector3 GetClampedGroundCoords(Vector3 self, Vector3 dest, int range)
276306
{
277307
if (CanUseAction(entry, ActionType))
278308
{
279-
if (!entry.Action.CanTargetFriendly && !entry.Action.CanTargetHostile) return (entry.Action, clientState.LocalPlayer);
309+
if (!entry.Action.CanTargetFriendly && !entry.Action.CanTargetHostile && !entry.Action.CanTargetParty && !entry.Action.CanTargetDead) return (entry.Action, clientState.LocalPlayer);
280310
return (entry.Action, entry.Target.getPtr());
281311
}
282312
}
@@ -292,11 +322,26 @@ private Vector3 GetClampedGroundCoords(Vector3 self, Vector3 dest, int range)
292322
return (null, null);
293323
}
294324

295-
private bool CanUseAction(StackEntry targ, uint ActionType)
325+
private unsafe int AvailableCharges(Lumina.Excel.GeneratedSheets.Action action)
326+
{
327+
RecastTimer* timer;
328+
if (action.CooldownGroup == 58)
329+
timer = GetGroupRecastTimer(action.AdditionalCooldownGroup);
330+
else
331+
timer = GetGroupRecastTimer(action.CooldownGroup);
332+
if (action.MaxCharges == 0) return timer->IsActive ^ 1;
333+
return (int)((action.MaxCharges+1) * (timer->Elapsed / timer->Total));
334+
}
335+
336+
private unsafe bool CanUseAction(StackEntry targ, uint actionType)
296337
{
297338
if (targ.Target == null || targ.Action == null) return false;
298-
339+
var y = AM->GetActionStatus((ActionType)actionType, targ.Action.RowId, targ.Target.GetTargetActorId());
340+
if (AM->GetActionStatus((ActionType)actionType, AM->GetAdjustedActionId(targ.Action.RowId), targ.Target.GetTargetActorId()) != 0)
341+
return false;
299342
var action = targ.Action;
343+
var action2 = AM->GetAdjustedActionId(action.RowId);
344+
action = RawActions.First(x => x.RowId == action2);
300345
var target = targ.Target.GetTargetActorId();
301346

302347
// ground target "at my mouse cursor"
@@ -310,9 +355,21 @@ private bool CanUseAction(StackEntry targ, uint ActionType)
310355
//var a = clientState.Actors[i];
311356
if (a != null && a.ObjectId == target)
312357
{
358+
313359
unsafe
314360
{
315-
if (AM->IsRecastTimerActive((ActionType)ActionType, action.RowId)) return false;
361+
if (action.ActionCategory.Value.RowId == (uint)ActionType.Ability && action.MaxCharges == 0)
362+
{
363+
if (AM->IsRecastTimerActive((ActionType)actionType, action.RowId))
364+
{
365+
return false;
366+
}
367+
}
368+
else if (action.MaxCharges > 0 || (action.CooldownGroup != 0 && action.AdditionalCooldownGroup != 0))
369+
{
370+
if (AvailableCharges(action) == 0) return false;
371+
372+
}
316373
}
317374
if (Configuration.RangeCheck)
318375
{

MOAction/MOAction.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
<AssemblyTitle>MOActionPlugin</AssemblyTitle>
55
<Product>MOActionPlugin</Product>
66
<Description>This plugin allows for actions to be used on mouseover targets without a macro.</Description>
7-
<Copyright>Copyleft attick 2020 baybeeee</Copyright>
8-
<AssemblyVersion>4.0.0</AssemblyVersion>
9-
<FileVersion>4.0.0</FileVersion>
7+
<Copyright>Copyleft attick 2021 baybeeee</Copyright>
8+
<AssemblyVersion>4.0.9</AssemblyVersion>
9+
<FileVersion>4.0.9</FileVersion>
1010
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1111
<OutputPath>bin\$(Configuration)\</OutputPath>
1212
<AppDesignerFolder>Properties.bak</AppDesignerFolder>

MOAction/MOActionAddressResolver.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using Dalamud.Game;
22
using Dalamud.Game.Internal;
33
using System;
4+
using System.Runtime.InteropServices;
45

56
namespace MOAction
67
{
7-
class MOActionAddressResolver : BaseAddressResolver
8+
public class MOActionAddressResolver : BaseAddressResolver
89
{
910

1011
public IntPtr RequestAction { get; private set; }
@@ -20,6 +21,9 @@ class MOActionAddressResolver : BaseAddressResolver
2021
public IntPtr FocusTarg;
2122
public IntPtr RegularTarg;
2223
public IntPtr PronounModule;
24+
public IntPtr GetGroupTimer;
25+
26+
public IntPtr AnimLock;
2327
// This is so hacky. One day I'm going to figure out how to get proper sigs.
2428
protected override void Setup64Bit(SigScanner sig)
2529
{
@@ -36,6 +40,18 @@ protected override void Setup64Bit(SigScanner sig)
3640
FocusTarg = sig.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 48 89 5C 24 ?? BB ?? ?? ?? ?? 48 89 7C 24 ??", 0);
3741
RegularTarg = sig.GetStaticAddressFromSig("F3 0F 11 05 ?? ?? ?? ?? EB 27", 0) + 0x4;
3842
PronounModule = sig.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 05 ?? ?? ?? ?? 48 85 C9 74 0C", 0);
43+
AnimLock = sig.GetStaticAddressFromSig("E8 ?? ?? ?? ?? 84 DB 75 37", 0x1D);
44+
GetGroupTimer = sig.ScanText("E8 ?? ?? ?? ?? 0F 57 FF 48 85 C0");
45+
}
46+
47+
[StructLayout(LayoutKind.Explicit, Size = 0x14)]
48+
public unsafe struct RecastTimer
49+
{
50+
[FieldOffset(0x0)] public byte IsActive;
51+
[FieldOffset(0x4)] public uint ActionID;
52+
[FieldOffset(0x8)] public float Elapsed;
53+
[FieldOffset(0xC)] public float Total;
3954
}
55+
4056
}
4157
}

0 commit comments

Comments
 (0)