|
|
|
@ -3,6 +3,7 @@ using System.Runtime.InteropServices;
|
|
|
|
|
using Dalamud.Game.Text.SeStringHandling;
|
|
|
|
|
using Dalamud.Hooking;
|
|
|
|
|
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|
|
|
|
using Siggingway;
|
|
|
|
|
|
|
|
|
|
namespace NominaOcculta {
|
|
|
|
|
internal class GameFunctions : IDisposable {
|
|
|
|
@ -14,6 +15,8 @@ namespace NominaOcculta {
|
|
|
|
|
internal const string LoadExd = "40 53 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 41 0F B6 D9";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Delegates
|
|
|
|
|
|
|
|
|
|
private delegate IntPtr GenerateNameDelegate(int race, int clan, int gender, IntPtr first, IntPtr last);
|
|
|
|
|
|
|
|
|
|
private delegate IntPtr Utf8StringCtorDelegate(IntPtr memory);
|
|
|
|
@ -26,14 +29,29 @@ namespace NominaOcculta {
|
|
|
|
|
|
|
|
|
|
private delegate IntPtr GetExcelModuleDelegate(IntPtr uiModule);
|
|
|
|
|
|
|
|
|
|
private Utf8StringCtorDelegate Utf8StringCtor { get; }
|
|
|
|
|
private Utf8StringDtorDelegate Utf8StringDtor { get; }
|
|
|
|
|
private GenerateNameDelegate InternalGenerateName { get; }
|
|
|
|
|
private LoadExdDelegate LoadExd { get; }
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private Hook<AtkTextNodeSetTextDelegate> AtkTextNodeSetTextHook { get; }
|
|
|
|
|
#region Functions
|
|
|
|
|
|
|
|
|
|
[Signature(Signatures.Utf8StringCtor)]
|
|
|
|
|
private Utf8StringCtorDelegate Utf8StringCtor { get; init; } = null!;
|
|
|
|
|
|
|
|
|
|
[Signature(Signatures.Utf8StringDtor)]
|
|
|
|
|
private Utf8StringDtorDelegate Utf8StringDtor { get; init; } = null!;
|
|
|
|
|
|
|
|
|
|
[Signature(Signatures.GenerateName)]
|
|
|
|
|
private GenerateNameDelegate InternalGenerateName { get; init; } = null!;
|
|
|
|
|
|
|
|
|
|
[Signature(Signatures.LoadExd)]
|
|
|
|
|
private LoadExdDelegate LoadExd { get; init; } = null!;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
[Signature(Signatures.AtkTextNodeSetText, DetourName = nameof(AtkTextNodeSetTextDetour))]
|
|
|
|
|
private Hook<AtkTextNodeSetTextDelegate> AtkTextNodeSetTextHook { get; init; } = null!;
|
|
|
|
|
|
|
|
|
|
internal delegate void AtkTextNodeSetTextEventDelegate(IntPtr node, IntPtr text, ref SeString? overwrite);
|
|
|
|
|
|
|
|
|
|
internal event AtkTextNodeSetTextEventDelegate? AtkTextNodeSetText;
|
|
|
|
|
|
|
|
|
|
private Plugin Plugin { get; }
|
|
|
|
@ -44,15 +62,8 @@ namespace NominaOcculta {
|
|
|
|
|
internal GameFunctions(Plugin plugin) {
|
|
|
|
|
this.Plugin = plugin;
|
|
|
|
|
|
|
|
|
|
this.Utf8StringCtor = Marshal.GetDelegateForFunctionPointer<Utf8StringCtorDelegate>(this.Plugin.SigScanner.ScanText(Signatures.Utf8StringCtor));
|
|
|
|
|
this.Utf8StringDtor = Marshal.GetDelegateForFunctionPointer<Utf8StringDtorDelegate>(this.Plugin.SigScanner.ScanText(Signatures.Utf8StringDtor));
|
|
|
|
|
this.InternalGenerateName = Marshal.GetDelegateForFunctionPointer<GenerateNameDelegate>(this.Plugin.SigScanner.ScanText(Signatures.GenerateName));
|
|
|
|
|
this.LoadExd = Marshal.GetDelegateForFunctionPointer<LoadExdDelegate>(this.Plugin.SigScanner.ScanText(Signatures.LoadExd));
|
|
|
|
|
Siggingway.Siggingway.Initialise(this.Plugin.SigScanner, this);
|
|
|
|
|
|
|
|
|
|
this.AtkTextNodeSetTextHook = new Hook<AtkTextNodeSetTextDelegate>(
|
|
|
|
|
this.Plugin.SigScanner.ScanText(Signatures.AtkTextNodeSetText),
|
|
|
|
|
this.OnAtkTextNodeSetText
|
|
|
|
|
);
|
|
|
|
|
this.AtkTextNodeSetTextHook.Enable();
|
|
|
|
|
|
|
|
|
|
this.First = Marshal.AllocHGlobal(128);
|
|
|
|
@ -70,7 +81,7 @@ namespace NominaOcculta {
|
|
|
|
|
this.AtkTextNodeSetTextHook.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private unsafe void OnAtkTextNodeSetText(IntPtr node, IntPtr text) {
|
|
|
|
|
private unsafe void AtkTextNodeSetTextDetour(IntPtr node, IntPtr text) {
|
|
|
|
|
SeString? overwrite = null;
|
|
|
|
|
this.AtkTextNodeSetText?.Invoke(node, text, ref overwrite);
|
|
|
|
|
|
|
|
|
|