Initial release: HSUI v1.0.0.0 - HUD replacement with configurable hotbars
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Memory;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using System;
|
||||
|
||||
namespace HSUI.Interface.Party
|
||||
{
|
||||
public enum ReadyCheckStatus
|
||||
{
|
||||
Ready = 0,
|
||||
NotReady = 1,
|
||||
None = 2
|
||||
}
|
||||
|
||||
public class PartyReadyCheckHelper : IDisposable
|
||||
{
|
||||
private delegate void ReadyCheckDelegate(IntPtr ptr);
|
||||
private Hook<AgentReadyCheck.Delegates.InitiateReadyCheck>? _onReadyCheckStartHook;
|
||||
private Hook<AgentReadyCheck.Delegates.EndReadyCheck>? _onReadyCheckEndHook;
|
||||
|
||||
private delegate void ActorControlDelegate(uint entityId, uint type, uint buffID, uint direct, uint actionId, uint sourceId, uint arg7, uint arg8, uint arg9, uint arg10, ulong targetId, byte arg12);
|
||||
private Hook<ActorControlDelegate>? _actorControlHook;
|
||||
|
||||
private bool _readyCheckOngoing = false;
|
||||
private double _lastReadyCheckEndTime = -1;
|
||||
|
||||
|
||||
public unsafe PartyReadyCheckHelper()
|
||||
{
|
||||
try
|
||||
{
|
||||
_onReadyCheckStartHook = Plugin.GameInteropProvider.HookFromAddress<AgentReadyCheck.Delegates.InitiateReadyCheck>(
|
||||
AgentReadyCheck.MemberFunctionPointers.InitiateReadyCheck,
|
||||
OnReadyCheckStart
|
||||
);
|
||||
_onReadyCheckStartHook?.Enable();
|
||||
|
||||
_onReadyCheckEndHook = Plugin.GameInteropProvider.HookFromAddress<AgentReadyCheck.Delegates.EndReadyCheck>(
|
||||
AgentReadyCheck.MemberFunctionPointers.EndReadyCheck,
|
||||
OnReadycheckEnd
|
||||
);
|
||||
_onReadyCheckEndHook?.Enable();
|
||||
|
||||
_actorControlHook = Plugin.GameInteropProvider.HookFromSignature<ActorControlDelegate>(
|
||||
"E8 ?? ?? ?? ?? 0F B7 0B 83 E9 64",
|
||||
OnActorControl
|
||||
);
|
||||
_actorControlHook?.Enable();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Logger.Error("Error initiating ready check sigs!!!\n" + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_onReadyCheckStartHook?.Disable();
|
||||
_onReadyCheckStartHook?.Dispose();
|
||||
|
||||
_onReadyCheckEndHook?.Disable();
|
||||
_onReadyCheckEndHook?.Dispose();
|
||||
|
||||
_actorControlHook?.Disable();
|
||||
_actorControlHook?.Dispose();
|
||||
}
|
||||
|
||||
private unsafe void OnReadyCheckStart(AgentReadyCheck *ptr)
|
||||
{
|
||||
_onReadyCheckStartHook?.Original(ptr);
|
||||
_readyCheckOngoing = true;
|
||||
_lastReadyCheckEndTime = -1;
|
||||
}
|
||||
|
||||
private unsafe void OnReadycheckEnd(AgentReadyCheck *ptr)
|
||||
{
|
||||
_onReadyCheckEndHook?.Original(ptr);
|
||||
_lastReadyCheckEndTime = ImGui.GetTime();
|
||||
}
|
||||
|
||||
private void OnActorControl(uint entityId, uint type, uint buffID, uint direct, uint actionId, uint sourceId, uint arg7, uint arg8, uint arg9, uint arg10, ulong targetId, byte arg12)
|
||||
{
|
||||
_actorControlHook?.Original(entityId, type, buffID, direct, actionId, sourceId, arg7, arg8, arg9, arg10, targetId, arg12);
|
||||
|
||||
// I'm not exactly sure what id == 503 means, but its always triggered when the fight starts
|
||||
// which is all I care about
|
||||
if (type == 503)
|
||||
{
|
||||
_readyCheckOngoing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(double maxDuration)
|
||||
{
|
||||
if (_readyCheckOngoing &&
|
||||
_lastReadyCheckEndTime != -1 &&
|
||||
ImGui.GetTime() - _lastReadyCheckEndTime >= maxDuration)
|
||||
{
|
||||
_readyCheckOngoing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe ReadyCheckStatus GetStatusForContentId(ulong contentId)
|
||||
{
|
||||
if (!_readyCheckOngoing)
|
||||
{
|
||||
return ReadyCheckStatus.None;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
ReadyCheckEntry entry = AgentReadyCheck.Instance()->ReadyCheckEntries[i];
|
||||
if (entry.ContentId == contentId)
|
||||
{
|
||||
return ParseStatus(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return ReadyCheckStatus.None;
|
||||
}
|
||||
|
||||
private ReadyCheckStatus ParseStatus(ReadyCheckEntry entry)
|
||||
{
|
||||
if (entry.Status == FFXIVClientStructs.FFXIV.Client.UI.Agent.ReadyCheckStatus.Ready)
|
||||
{
|
||||
return ReadyCheckStatus.Ready;
|
||||
}
|
||||
else if (entry.Status == FFXIVClientStructs.FFXIV.Client.UI.Agent.ReadyCheckStatus.NotReady ||
|
||||
entry.Status == FFXIVClientStructs.FFXIV.Client.UI.Agent.ReadyCheckStatus.MemberNotPresent)
|
||||
{
|
||||
return ReadyCheckStatus.NotReady;
|
||||
}
|
||||
|
||||
return ReadyCheckStatus.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user