95 lines
3.4 KiB
C#
95 lines
3.4 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using System.Runtime.InteropServices;
|
|
using Dalamud.Hooking;
|
|
|
|
namespace Tourist {
|
|
public class GameFunctions : IDisposable {
|
|
private delegate nint VistaUnlockedDelegate(ushort index, int a2, int a3);
|
|
|
|
private delegate nint CreateVfxDelegate(string name);
|
|
|
|
private delegate nint PlayVfxDelegate(nint vfx, float idk, int idk2);
|
|
|
|
internal delegate nint RemoveVfxDelegate(nint vfx);
|
|
|
|
private Plugin Plugin { get; }
|
|
private nint SightseeingMaskPointer { get; }
|
|
|
|
private CreateVfxDelegate CreateVfx { get; }
|
|
private PlayVfxDelegate PlayVfxInternal { get; }
|
|
internal RemoveVfxDelegate RemoveVfx { get; }
|
|
private Hook<VistaUnlockedDelegate> VistaUnlockedHook { get; }
|
|
|
|
public GameFunctions(Plugin plugin) {
|
|
this.Plugin = plugin;
|
|
|
|
var vistaUnlockedPtr = this.Plugin.SigScanner.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 8B CE E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 44 8B 7C 24");
|
|
this.VistaUnlockedHook = this.Plugin.GameInteropProvider.HookFromAddress<VistaUnlockedDelegate>(vistaUnlockedPtr, this.OnVistaUnlock);
|
|
this.VistaUnlockedHook.Enable();
|
|
|
|
var maskPtr = this.Plugin.SigScanner.GetStaticAddressFromSig("8B EA 48 8D 0D ?? ?? ?? ?? 8B D3");
|
|
this.SightseeingMaskPointer = maskPtr;
|
|
|
|
var createVfxPtr = this.Plugin.SigScanner.ScanText("E8 ?? ?? ?? ?? F3 0F 10 35 ?? ?? ?? ?? 48 89 43 08");
|
|
this.CreateVfx = Marshal.GetDelegateForFunctionPointer<CreateVfxDelegate>(createVfxPtr);
|
|
|
|
var playVfxPtr = this.Plugin.SigScanner.ScanText("E8 ?? ?? ?? ?? 8B 4B 7C 85 C9");
|
|
this.PlayVfxInternal = Marshal.GetDelegateForFunctionPointer<PlayVfxDelegate>(playVfxPtr);
|
|
|
|
var removeVfxPtr = this.Plugin.SigScanner.ScanText("40 53 48 83 EC 20 48 8B D9 48 8B 89 ?? ?? ?? ?? 48 85 C9 74 28 33 D2");
|
|
this.RemoveVfx = Marshal.GetDelegateForFunctionPointer<RemoveVfxDelegate>(removeVfxPtr);
|
|
}
|
|
|
|
public void Dispose() {
|
|
this.VistaUnlockedHook.Dispose();
|
|
}
|
|
|
|
private nint OnVistaUnlock(ushort index, int a2, int a3) {
|
|
try {
|
|
this.Plugin.Markers.RemoveVfx(index);
|
|
} catch (Exception ex) {
|
|
Plugin.Log.Error(ex, "Exception in vista unlock");
|
|
}
|
|
|
|
return this.VistaUnlockedHook.Original(index, a2, a3);
|
|
}
|
|
|
|
public unsafe nint SpawnVfx(string name, Vector3 position) {
|
|
var vfx = this.CreateVfx(name);
|
|
|
|
var pos = (float*) (vfx + 80);
|
|
*pos = position.X;
|
|
*(pos + 1) = position.Z;
|
|
*(pos + 2) = position.Y;
|
|
|
|
pos = (float*) (vfx + 640);
|
|
*pos = 0;
|
|
*(pos + 1) = 0;
|
|
*(pos + 2) = 0;
|
|
|
|
*(long*) (vfx + 56) |= 2;
|
|
*(int*) (vfx + 652) = 0;
|
|
|
|
return vfx;
|
|
}
|
|
|
|
internal bool PlayVfx(nint vfx) {
|
|
return this.PlayVfxInternal(vfx, 0.0f, -1) == nint.Zero;
|
|
}
|
|
|
|
public bool HasVistaUnlocked(short index) {
|
|
if (this.SightseeingMaskPointer == nint.Zero) {
|
|
return false;
|
|
}
|
|
|
|
var byteToCheck = index >> 3;
|
|
var bitToCheck = 1 << (index - 8 * byteToCheck);
|
|
|
|
var maskPart = Marshal.ReadByte(this.SightseeingMaskPointer + byteToCheck);
|
|
|
|
return (maskPart & bitToCheck) != 0;
|
|
}
|
|
}
|
|
}
|