mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-13 12:14:18 +01:00
Add CrestService.
This commit is contained in:
parent
3177e6ca29
commit
668d4c033f
6 changed files with 100 additions and 10 deletions
|
|
@ -23,7 +23,7 @@ public unsafe class ChangeCustomizeService : EventWrapper<Action<Model, Ref<Cust
|
||||||
private readonly delegate* unmanaged[Stdcall]<Human*, byte*, bool, bool> _original;
|
private readonly delegate* unmanaged[Stdcall]<Human*, byte*, bool, bool> _original;
|
||||||
|
|
||||||
/// <summary> Check whether we in a manual customize update, in which case we need to not toggle certain flags. </summary>
|
/// <summary> Check whether we in a manual customize update, in which case we need to not toggle certain flags. </summary>
|
||||||
public static readonly ThreadLocal<bool> InUpdate = new(() => false);
|
public static readonly InMethodChecker InUpdate = new();
|
||||||
|
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
|
@ -70,9 +70,8 @@ public unsafe class ChangeCustomizeService : EventWrapper<Action<Model, Ref<Cust
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Glamourer.Log.Verbose($"[ChangeCustomize] Invoked on 0x{model.Address:X} with {customize}.");
|
Glamourer.Log.Verbose($"[ChangeCustomize] Invoked on 0x{model.Address:X} with {customize}.");
|
||||||
InUpdate.Value = true;
|
using var _ = InUpdate.EnterMethod();
|
||||||
var ret = _original(model.AsHuman, customize.Data, true);
|
var ret = _original(model.AsHuman, customize.Data, true);
|
||||||
InUpdate.Value = false;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +80,7 @@ public unsafe class ChangeCustomizeService : EventWrapper<Action<Model, Ref<Cust
|
||||||
|
|
||||||
private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment)
|
private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment)
|
||||||
{
|
{
|
||||||
if (!InUpdate.Value)
|
if (!InUpdate.InMethod)
|
||||||
{
|
{
|
||||||
var customize = new Ref<Customize>(new Customize(*(CustomizeData*)data));
|
var customize = new Ref<Customize>(new Customize(*(CustomizeData*)data));
|
||||||
Invoke(this, (Model)human, customize);
|
Invoke(this, (Model)human, customize);
|
||||||
|
|
|
||||||
92
Glamourer/Interop/CrestService.cs
Normal file
92
Glamourer/Interop/CrestService.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
using System;
|
||||||
|
using Dalamud.Hooking;
|
||||||
|
using Dalamud.Plugin.Services;
|
||||||
|
using Dalamud.Utility.Signatures;
|
||||||
|
using Glamourer.Interop.Structs;
|
||||||
|
using OtterGui.Classes;
|
||||||
|
using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
|
namespace Glamourer.Interop;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when the crest visibility is updated on a model.
|
||||||
|
/// <list type="number">
|
||||||
|
/// <item>Parameter is the model with an update. </item>
|
||||||
|
/// <item>Parameter is the equipment slot changed. </item>
|
||||||
|
/// <item>Parameter is the whether the crest will be shown. </item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public sealed unsafe class CrestService : EventWrapper<Action<Model, EquipSlot, Ref<bool>>, CrestService.Priority>, IDisposable
|
||||||
|
{
|
||||||
|
public enum Priority
|
||||||
|
{
|
||||||
|
/// <seealso cref="State.StateListener.OnCrestVisibilityUpdating"/>
|
||||||
|
StateListener = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrestService(IGameInteropProvider interop)
|
||||||
|
: base(nameof(CrestService))
|
||||||
|
{
|
||||||
|
_humanSetFreeCompanyCrestVisibleOnSlot =
|
||||||
|
interop.HookFromAddress<SetCrestDelegateIntern>(_humanVTable[96], HumanSetFreeCompanyCrestVisibleOnSlotDetour);
|
||||||
|
_weaponSetFreeCompanyCrestVisibleOnSlot =
|
||||||
|
interop.HookFromAddress<SetCrestDelegateIntern>(_weaponVTable[96], WeaponSetFreeCompanyCrestVisibleOnSlotDetour);
|
||||||
|
_humanSetFreeCompanyCrestVisibleOnSlot.Enable();
|
||||||
|
_weaponSetFreeCompanyCrestVisibleOnSlot.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool _)
|
||||||
|
{
|
||||||
|
_humanSetFreeCompanyCrestVisibleOnSlot.Dispose();
|
||||||
|
_weaponSetFreeCompanyCrestVisibleOnSlot.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Invoke(Model model, EquipSlot slot, ref bool visible)
|
||||||
|
{
|
||||||
|
var ret = new Ref<bool>(visible);
|
||||||
|
Invoke(this, model, slot, ret);
|
||||||
|
visible = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateCrest(Model drawObject, EquipSlot slot, bool crest)
|
||||||
|
{
|
||||||
|
using var _ = _inUpdate.EnterMethod();
|
||||||
|
drawObject.SetFreeCompanyCrestVisibleOnSlot(slot, crest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly InMethodChecker _inUpdate = new();
|
||||||
|
|
||||||
|
private delegate void SetCrestDelegateIntern(nint drawObject, byte slot, byte visible);
|
||||||
|
|
||||||
|
[Signature(global::Penumbra.GameData.Sigs.HumanVTable, ScanType = ScanType.StaticAddress)]
|
||||||
|
private readonly nint* _humanVTable = null!;
|
||||||
|
|
||||||
|
[Signature(global::Penumbra.GameData.Sigs.WeaponVTable, ScanType = ScanType.StaticAddress)]
|
||||||
|
private readonly nint* _weaponVTable = null!;
|
||||||
|
|
||||||
|
private readonly Hook<SetCrestDelegateIntern> _humanSetFreeCompanyCrestVisibleOnSlot;
|
||||||
|
private readonly Hook<SetCrestDelegateIntern> _weaponSetFreeCompanyCrestVisibleOnSlot;
|
||||||
|
|
||||||
|
private void HumanSetFreeCompanyCrestVisibleOnSlotDetour(nint drawObject, byte slotIdx, byte visible)
|
||||||
|
{
|
||||||
|
var slot = ((uint)slotIdx).ToEquipSlot();
|
||||||
|
var rVisible = visible != 0;
|
||||||
|
var inUpdate = _inUpdate.InMethod;
|
||||||
|
if (!inUpdate)
|
||||||
|
Invoke(drawObject, slot, ref rVisible);
|
||||||
|
Glamourer.Log.Excessive(
|
||||||
|
$"[Human.SetFreeCompanyCrestVisibleOnSlot] Called with 0x{drawObject:X} for slot {slot} with {rVisible} (original: {visible != 0}, in update: {inUpdate}).");
|
||||||
|
_humanSetFreeCompanyCrestVisibleOnSlot.Original(drawObject, slotIdx, rVisible ? (byte)1 : (byte)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WeaponSetFreeCompanyCrestVisibleOnSlotDetour(nint drawObject, byte slotIdx, byte visible)
|
||||||
|
{
|
||||||
|
var rVisible = visible != 0;
|
||||||
|
var inUpdate = _inUpdate.InMethod;
|
||||||
|
if (!inUpdate)
|
||||||
|
Invoke(drawObject, EquipSlot.BothHand, ref rVisible);
|
||||||
|
Glamourer.Log.Excessive(
|
||||||
|
$"[Weapon.SetFreeCompanyCrestVisibleOnSlot] Called with 0x{drawObject:X} with {rVisible} (original: {visible != 0}, in update: {inUpdate}).");
|
||||||
|
_weaponSetFreeCompanyCrestVisibleOnSlot.Original(drawObject, slotIdx, rVisible ? (byte)1 : (byte)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,9 +21,7 @@ public unsafe class UpdateSlotService : IDisposable
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
=> _flagSlotForUpdateHook.Dispose();
|
||||||
_flagSlotForUpdateHook.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateSlot(Model drawObject, EquipSlot slot, CharacterArmor data)
|
public void UpdateSlot(Model drawObject, EquipSlot slot, CharacterArmor data)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@ public static class ServiceManager
|
||||||
.AddSingleton<CustomizeUnlockManager>()
|
.AddSingleton<CustomizeUnlockManager>()
|
||||||
.AddSingleton<ItemUnlockManager>()
|
.AddSingleton<ItemUnlockManager>()
|
||||||
.AddSingleton<ImportService>()
|
.AddSingleton<ImportService>()
|
||||||
|
.AddSingleton<CrestService>()
|
||||||
.AddSingleton<InventoryService>()
|
.AddSingleton<InventoryService>()
|
||||||
.AddSingleton<ContextMenuService>()
|
.AddSingleton<ContextMenuService>()
|
||||||
.AddSingleton<ScalingService>();
|
.AddSingleton<ScalingService>();
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,7 @@ public class StateListener : IDisposable
|
||||||
private void OnVisorChange(Model model, Ref<bool> value)
|
private void OnVisorChange(Model model, Ref<bool> value)
|
||||||
{
|
{
|
||||||
// Skip updates when in customize update.
|
// Skip updates when in customize update.
|
||||||
if (ChangeCustomizeService.InUpdate.IsValueCreated && ChangeCustomizeService.InUpdate.Value)
|
if (ChangeCustomizeService.InUpdate.InMethod)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Find appropriate actor and state.
|
// Find appropriate actor and state.
|
||||||
|
|
|
||||||
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3e2d4ae934694918d312280d62127cf1a55b03e4
|
Subproject commit f624aca526bd1f36364d63443ed1c6e83499b8b7
|
||||||
Loading…
Add table
Add a link
Reference in a new issue