Penumbra/Penumbra/Interop/Hooks/Objects/WeaponReload.cs
2024-08-01 16:40:37 +02:00

71 lines
2.3 KiB
C#

using Dalamud.Hooking;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using OtterGui.Classes;
using OtterGui.Services;
using Penumbra.GameData.Structs;
namespace Penumbra.Interop.Hooks.Objects;
public sealed unsafe class WeaponReload : EventWrapperPtr<DrawDataContainer, Character, CharacterWeapon, WeaponReload.Priority>, IHookService
{
public enum Priority
{
/// <seealso cref="PathResolving.DrawObjectState"/>
DrawObjectState = 0,
}
public WeaponReload(HookManager hooks)
: base("Reload Weapon")
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, !HookOverrides.Instance.Objects.WeaponReload);
private readonly Task<Hook<Delegate>> _task;
public nint Address
=> (nint)DrawDataContainer.MemberFunctionPointers.LoadWeapon;
public void Enable()
=> _task.Result.Enable();
public void Disable()
=> _task.Result.Disable();
public Task Awaiter
=> _task;
public bool Finished
=> _task.IsCompletedSuccessfully;
private delegate void Delegate(DrawDataContainer* drawData, uint slot, ulong weapon, byte d, byte e, byte f, byte g);
private void Detour(DrawDataContainer* drawData, uint slot, ulong weapon, byte d, byte e, byte f, byte g)
{
var gameObject = drawData->OwnerObject;
Penumbra.Log.Verbose($"[{Name}] Triggered with drawData: 0x{(nint)drawData:X}, {slot}, {weapon}, {d}, {e}, {f}, {g}.");
Invoke(drawData, gameObject, (CharacterWeapon*)(&weapon));
_task.Result.Original(drawData, slot, weapon, d, e, f, g);
_postEvent.Invoke(drawData, gameObject);
}
public void Subscribe(ActionPtr<DrawDataContainer, Character> subscriber, PostEvent.Priority priority)
=> _postEvent.Subscribe(subscriber, priority);
public void Unsubscribe(ActionPtr<DrawDataContainer, Character> subscriber)
=> _postEvent.Unsubscribe(subscriber);
private readonly PostEvent _postEvent = new("Created CharacterBase");
protected override void Dispose(bool disposing)
{
_postEvent.Dispose();
}
public class PostEvent(string name) : EventWrapperPtr<DrawDataContainer, Character, PostEvent.Priority>(name)
{
public enum Priority
{
/// <seealso cref="PathResolving.DrawObjectState"/>
DrawObjectState = 0,
}
}
}