This commit is contained in:
Ottermandias 2023-06-22 12:15:44 +02:00
parent 803fd1b247
commit 1aba34f34a
11 changed files with 631 additions and 32 deletions

View file

@ -0,0 +1,72 @@
using System;
using Dalamud.Hooking;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using static OtterGui.Raii.ImRaii;
namespace Glamourer.Interop;
public unsafe class MetaService : IDisposable
{
private readonly HeadGearVisibilityChanged _headGearEvent;
private readonly WeaponVisibilityChanged _weaponEvent;
private delegate void HideHatGearDelegate(DrawDataContainer* drawData, uint id, byte value);
private delegate void HideWeaponsDelegate(DrawDataContainer* drawData, bool value);
private readonly Hook<HideHatGearDelegate> _hideHatGearHook;
private readonly Hook<HideWeaponsDelegate> _hideWeaponsHook;
public MetaService(WeaponVisibilityChanged weaponEvent, HeadGearVisibilityChanged headGearEvent)
{
_weaponEvent = weaponEvent;
_headGearEvent = headGearEvent;
_hideHatGearHook = Hook<HideHatGearDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.HideHeadgear, HideHatDetour);
_hideWeaponsHook = Hook<HideWeaponsDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.HideWeapons, HideWeaponsDetour);
_hideHatGearHook.Enable();
_hideWeaponsHook.Enable();
}
public void Dispose()
{
_hideHatGearHook.Dispose();
_hideWeaponsHook.Dispose();
}
public void SetHatState(Actor actor, bool value)
{
if (!actor.IsCharacter)
return;
_hideHatGearHook.Original(&actor.AsCharacter->DrawData, 0, (byte) (value ? 1 : 0));
}
public void SetWeaponState(Actor actor, bool value)
{
if (!actor.IsCharacter)
return;
_hideWeaponsHook.Original(&actor.AsCharacter->DrawData, value);
}
private void HideHatDetour(DrawDataContainer* drawData, uint id, byte value)
{
Actor actor = drawData->Parent;
var v = value == 0;
_headGearEvent.Invoke(actor, ref v);
value = (byte) (v ? 0 : 1);
Glamourer.Log.Information($"[MetaService] Hide Hat triggered with 0x{(nint)drawData:X} {id} {value} for {actor.Utf8Name}.");
_hideHatGearHook.Original(drawData, id, value);
}
private void HideWeaponsDetour(DrawDataContainer* drawData, bool value)
{
Actor actor = drawData->Parent;
value = !value;
_weaponEvent.Invoke(actor, ref value);
value = !value;
Glamourer.Log.Information($"[MetaService] Hide Weapon triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
_hideWeaponsHook.Original(drawData, value);
}
}

View file

@ -4,6 +4,7 @@ using Dalamud.Hooking;
using Dalamud.Utility.Signatures;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using Penumbra.GameData.Enums;
namespace Glamourer.Interop;
@ -39,7 +40,7 @@ public class VisorService : IDisposable
if (oldState == on)
return false;
SetupVisorHook(human, (ushort)human.AsHuman->HeadSetID, on);
SetupVisorHook(human, human.GetArmor(EquipSlot.Head).Set.Value, on);
return true;
}
@ -50,17 +51,15 @@ public class VisorService : IDisposable
private void SetupVisorDetour(nint human, ushort modelId, bool on)
{
var callOriginal = true;
var originalOn = on;
// Invoke an event that can change the requested value
// and also control whether the function should be called at all.
Event.Invoke(human, ref on, ref callOriginal);
Event.Invoke(human, ref on);
Glamourer.Log.Excessive(
$"[SetVisorState] Invoked from game on 0x{human:X} switching to {on} (original {originalOn}, call original {callOriginal}).");
$"[SetVisorState] Invoked from game on 0x{human:X} switching to {on} (original {originalOn}).");
if (callOriginal)
SetupVisorHook(human, modelId, on);
SetupVisorHook(human, modelId, on);
}
/// <summary>

View file

@ -92,4 +92,4 @@ public unsafe class WeaponService : IDisposable
var weapon = new CharacterWeapon(value.Value) { Stain = stain.Value };
LoadWeapon(character, slot, weapon);
}
}
}