mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-13 12:14:18 +01:00
Fix issue with Penumbra load order and visor state.
This commit is contained in:
parent
205a95b254
commit
5cf6b0eb75
3 changed files with 31 additions and 6 deletions
|
|
@ -12,5 +12,8 @@ public sealed class PenumbraReloaded()
|
||||||
{
|
{
|
||||||
/// <seealso cref="Interop.ChangeCustomizeService.Restore"/>
|
/// <seealso cref="Interop.ChangeCustomizeService.Restore"/>
|
||||||
ChangeCustomizeService = 0,
|
ChangeCustomizeService = 0,
|
||||||
|
|
||||||
|
/// <seealso cref="Interop.VisorService.Restore"/>
|
||||||
|
VisorService = 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,24 @@ namespace Glamourer.Interop;
|
||||||
|
|
||||||
public class VisorService : IDisposable
|
public class VisorService : IDisposable
|
||||||
{
|
{
|
||||||
public readonly VisorStateChanged Event;
|
private readonly PenumbraReloaded _penumbra;
|
||||||
|
private readonly IGameInteropProvider _interop;
|
||||||
|
public readonly VisorStateChanged Event;
|
||||||
|
|
||||||
public unsafe VisorService(VisorStateChanged visorStateChanged, IGameInteropProvider interop)
|
public VisorService(VisorStateChanged visorStateChanged, IGameInteropProvider interop, PenumbraReloaded penumbra)
|
||||||
{
|
{
|
||||||
|
_interop = interop;
|
||||||
|
_penumbra = penumbra;
|
||||||
Event = visorStateChanged;
|
Event = visorStateChanged;
|
||||||
_setupVisorHook = interop.HookFromAddress<UpdateVisorDelegateInternal>((nint)Human.MemberFunctionPointers.SetupVisor, SetupVisorDetour);
|
_setupVisorHook = Create();
|
||||||
_setupVisorHook.Enable();
|
_penumbra.Subscribe(Restore, PenumbraReloaded.Priority.VisorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
=> _setupVisorHook.Dispose();
|
{
|
||||||
|
_setupVisorHook.Dispose();
|
||||||
|
_penumbra.Unsubscribe(Restore);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Obtain the current state of the Visor for the given draw object (true: toggled). </summary>
|
/// <summary> Obtain the current state of the Visor for the given draw object (true: toggled). </summary>
|
||||||
public static unsafe bool GetVisorState(Model characterBase)
|
public static unsafe bool GetVisorState(Model characterBase)
|
||||||
|
|
@ -45,7 +52,7 @@ public class VisorService : IDisposable
|
||||||
|
|
||||||
private delegate void UpdateVisorDelegateInternal(nint humanPtr, ushort modelId, byte on);
|
private delegate void UpdateVisorDelegateInternal(nint humanPtr, ushort modelId, byte on);
|
||||||
|
|
||||||
private readonly Hook<UpdateVisorDelegateInternal> _setupVisorHook;
|
private Hook<UpdateVisorDelegateInternal> _setupVisorHook;
|
||||||
|
|
||||||
private void SetupVisorDetour(nint human, ushort modelId, byte value)
|
private void SetupVisorDetour(nint human, ushort modelId, byte value)
|
||||||
{
|
{
|
||||||
|
|
@ -72,4 +79,17 @@ public class VisorService : IDisposable
|
||||||
human.AsCharacterBase->VisorToggled = on;
|
human.AsCharacterBase->VisorToggled = on;
|
||||||
_setupVisorHook.Original(human.Address, modelId, on ? (byte)1 : (byte)0);
|
_setupVisorHook.Original(human.Address, modelId, on ? (byte)1 : (byte)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe Hook<UpdateVisorDelegateInternal> Create()
|
||||||
|
{
|
||||||
|
var hook = _interop.HookFromAddress<UpdateVisorDelegateInternal>((nint)Human.MemberFunctionPointers.SetupVisor, SetupVisorDetour);
|
||||||
|
hook.Enable();
|
||||||
|
return hook;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Restore()
|
||||||
|
{
|
||||||
|
_setupVisorHook.Dispose();
|
||||||
|
_setupVisorHook = Create();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -578,6 +578,8 @@ public class StateListener : IDisposable
|
||||||
// We do not need to handle fixed designs,
|
// We do not need to handle fixed designs,
|
||||||
// since a fixed design would already have established state-tracking.
|
// since a fixed design would already have established state-tracking.
|
||||||
var actor = _penumbra.GameObjectFromDrawObject(model);
|
var actor = _penumbra.GameObjectFromDrawObject(model);
|
||||||
|
if (!actor.IsCharacter)
|
||||||
|
return;
|
||||||
|
|
||||||
// Only actually change anything if the actor state changed,
|
// Only actually change anything if the actor state changed,
|
||||||
// when equipping headgear the method is called with the current draw object state,
|
// when equipping headgear the method is called with the current draw object state,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue