mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Improve handling of meta flags.
This commit is contained in:
parent
5dd9cca14c
commit
a3c02ae179
2 changed files with 46 additions and 15 deletions
|
|
@ -10,27 +10,33 @@ public unsafe class MetaService : IDisposable
|
||||||
{
|
{
|
||||||
private readonly HeadGearVisibilityChanged _headGearEvent;
|
private readonly HeadGearVisibilityChanged _headGearEvent;
|
||||||
private readonly WeaponVisibilityChanged _weaponEvent;
|
private readonly WeaponVisibilityChanged _weaponEvent;
|
||||||
|
private readonly VisorStateChanged _visorEvent;
|
||||||
|
|
||||||
private delegate void HideHatGearDelegate(DrawDataContainer* drawData, uint id, byte value);
|
private delegate void HideHatGearDelegate(DrawDataContainer* drawData, uint id, byte value);
|
||||||
private delegate void HideWeaponsDelegate(DrawDataContainer* drawData, bool value);
|
private delegate void HideWeaponsDelegate(DrawDataContainer* drawData, bool value);
|
||||||
|
|
||||||
private readonly Hook<HideHatGearDelegate> _hideHatGearHook;
|
private readonly Hook<HideHatGearDelegate> _hideHatGearHook;
|
||||||
private readonly Hook<HideWeaponsDelegate> _hideWeaponsHook;
|
private readonly Hook<HideWeaponsDelegate> _hideWeaponsHook;
|
||||||
|
private readonly Hook<HideWeaponsDelegate> _toggleVisorHook;
|
||||||
|
|
||||||
public MetaService(WeaponVisibilityChanged weaponEvent, HeadGearVisibilityChanged headGearEvent)
|
public MetaService(WeaponVisibilityChanged weaponEvent, HeadGearVisibilityChanged headGearEvent, VisorStateChanged visorEvent)
|
||||||
{
|
{
|
||||||
_weaponEvent = weaponEvent;
|
_weaponEvent = weaponEvent;
|
||||||
_headGearEvent = headGearEvent;
|
_headGearEvent = headGearEvent;
|
||||||
|
_visorEvent = visorEvent;
|
||||||
_hideHatGearHook = Hook<HideHatGearDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.HideHeadgear, HideHatDetour);
|
_hideHatGearHook = Hook<HideHatGearDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.HideHeadgear, HideHatDetour);
|
||||||
_hideWeaponsHook = Hook<HideWeaponsDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.HideWeapons, HideWeaponsDetour);
|
_hideWeaponsHook = Hook<HideWeaponsDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.HideWeapons, HideWeaponsDetour);
|
||||||
|
_toggleVisorHook = Hook<HideWeaponsDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.SetVisor, ToggleVisorDetour);
|
||||||
_hideHatGearHook.Enable();
|
_hideHatGearHook.Enable();
|
||||||
_hideWeaponsHook.Enable();
|
_hideWeaponsHook.Enable();
|
||||||
|
_toggleVisorHook.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_hideHatGearHook.Dispose();
|
_hideHatGearHook.Dispose();
|
||||||
_hideWeaponsHook.Dispose();
|
_hideWeaponsHook.Dispose();
|
||||||
|
_toggleVisorHook.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetHatState(Actor actor, bool value)
|
public void SetHatState(Actor actor, bool value)
|
||||||
|
|
@ -73,4 +79,12 @@ public unsafe class MetaService : IDisposable
|
||||||
Glamourer.Log.Verbose($"[MetaService] Hide Weapon triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
Glamourer.Log.Verbose($"[MetaService] Hide Weapon triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
||||||
_hideWeaponsHook.Original(drawData, value);
|
_hideWeaponsHook.Original(drawData, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleVisorDetour(DrawDataContainer* drawData, bool value)
|
||||||
|
{
|
||||||
|
Actor actor = drawData->Parent;
|
||||||
|
_visorEvent.Invoke(actor.Model, ref value);
|
||||||
|
Glamourer.Log.Verbose($"[MetaService] Toggle Visor triggered with 0x{(nint)drawData:X} {value} for {actor.Utf8Name}.");
|
||||||
|
_toggleVisorHook.Original(drawData, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ public class StateListener : IDisposable
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
private readonly ActorService _actors;
|
private readonly ActorService _actors;
|
||||||
private readonly StateManager _manager;
|
private readonly StateManager _manager;
|
||||||
|
private readonly StateApplier _applier;
|
||||||
private readonly ItemManager _items;
|
private readonly ItemManager _items;
|
||||||
private readonly PenumbraService _penumbra;
|
private readonly PenumbraService _penumbra;
|
||||||
private readonly SlotUpdating _slotUpdating;
|
private readonly SlotUpdating _slotUpdating;
|
||||||
|
|
@ -35,6 +36,9 @@ public class StateListener : IDisposable
|
||||||
private readonly FunModule _funModule;
|
private readonly FunModule _funModule;
|
||||||
private readonly HumanModelList _humans;
|
private readonly HumanModelList _humans;
|
||||||
|
|
||||||
|
private ActorIdentifier _creatingIdentifier = ActorIdentifier.Invalid;
|
||||||
|
private ActorState? _creatingState = null;
|
||||||
|
|
||||||
public bool Enabled
|
public bool Enabled
|
||||||
{
|
{
|
||||||
get => _config.Enabled;
|
get => _config.Enabled;
|
||||||
|
|
@ -44,7 +48,7 @@ public class StateListener : IDisposable
|
||||||
public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorService actors, Configuration config,
|
public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorService actors, Configuration config,
|
||||||
SlotUpdating slotUpdating, WeaponLoading weaponLoading, VisorStateChanged visorState, WeaponVisibilityChanged weaponVisibility,
|
SlotUpdating slotUpdating, WeaponLoading weaponLoading, VisorStateChanged visorState, WeaponVisibilityChanged weaponVisibility,
|
||||||
HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier, FunModule funModule, HumanModelList humans,
|
HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier, FunModule funModule, HumanModelList humans,
|
||||||
EquipmentLoading equipmentLoading)
|
EquipmentLoading equipmentLoading, StateApplier applier)
|
||||||
{
|
{
|
||||||
_manager = manager;
|
_manager = manager;
|
||||||
_items = items;
|
_items = items;
|
||||||
|
|
@ -60,6 +64,7 @@ public class StateListener : IDisposable
|
||||||
_funModule = funModule;
|
_funModule = funModule;
|
||||||
_humans = humans;
|
_humans = humans;
|
||||||
_equipmentLoading = equipmentLoading;
|
_equipmentLoading = equipmentLoading;
|
||||||
|
_applier = applier;
|
||||||
|
|
||||||
if (Enabled)
|
if (Enabled)
|
||||||
Subscribe();
|
Subscribe();
|
||||||
|
|
@ -106,37 +111,37 @@ public class StateListener : IDisposable
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private unsafe void OnCreatingCharacterBase(nint actorPtr, string _, nint modelPtr, nint customizePtr, nint equipDataPtr)
|
private unsafe void OnCreatingCharacterBase(nint actorPtr, string _, nint modelPtr, nint customizePtr, nint equipDataPtr)
|
||||||
{
|
{
|
||||||
var actor = (Actor)actorPtr;
|
var actor = (Actor)actorPtr;
|
||||||
var identifier = actor.GetIdentifier(_actors.AwaitedService);
|
_creatingIdentifier = actor.GetIdentifier(_actors.AwaitedService);
|
||||||
|
|
||||||
ref var modelId = ref *(uint*)modelPtr;
|
ref var modelId = ref *(uint*)modelPtr;
|
||||||
ref var customize = ref *(Customize*)customizePtr;
|
ref var customize = ref *(Customize*)customizePtr;
|
||||||
if (_autoDesignApplier.Reduce(actor, identifier, out var state))
|
if (_autoDesignApplier.Reduce(actor, _creatingIdentifier, out _creatingState))
|
||||||
{
|
{
|
||||||
switch (UpdateBaseData(actor, state, modelId, customizePtr, equipDataPtr))
|
switch (UpdateBaseData(actor, _creatingState, modelId, customizePtr, equipDataPtr))
|
||||||
{
|
{
|
||||||
// TODO handle right
|
// TODO handle right
|
||||||
case UpdateState.Change: break;
|
case UpdateState.Change: break;
|
||||||
case UpdateState.Transformed: break;
|
case UpdateState.Transformed: break;
|
||||||
case UpdateState.NoChange:
|
case UpdateState.NoChange:
|
||||||
|
|
||||||
modelId = state.ModelData.ModelId;
|
modelId = _creatingState.ModelData.ModelId;
|
||||||
switch (UpdateBaseData(actor, state, customize))
|
switch (UpdateBaseData(actor, _creatingState, customize))
|
||||||
{
|
{
|
||||||
case UpdateState.Transformed: break;
|
case UpdateState.Transformed: break;
|
||||||
case UpdateState.Change: break;
|
case UpdateState.Change: break;
|
||||||
case UpdateState.NoChange:
|
case UpdateState.NoChange:
|
||||||
customize = state.ModelData.Customize;
|
customize = _creatingState.ModelData.Customize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||||
HandleEquipSlot(actor, state, slot, ref ((CharacterArmor*)equipDataPtr)[slot.ToIndex()]);
|
HandleEquipSlot(actor, _creatingState, slot, ref ((CharacterArmor*)equipDataPtr)[slot.ToIndex()]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.TempUnlock();
|
_creatingState.TempUnlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
_funModule.ApplyFun(actor, new Span<CharacterArmor>((void*)equipDataPtr, 10), ref customize);
|
_funModule.ApplyFun(actor, new Span<CharacterArmor>((void*)equipDataPtr, 10), ref customize);
|
||||||
|
|
@ -173,7 +178,8 @@ public class StateListener : IDisposable
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!actor.Identifier(_actors.AwaitedService, out var identifier)
|
if (!actor.Identifier(_actors.AwaitedService, out var identifier)
|
||||||
|| !_manager.TryGetValue(identifier, out var state) || !state.BaseData.IsHuman)
|
|| !_manager.TryGetValue(identifier, out var state)
|
||||||
|
|| !state.BaseData.IsHuman)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (state.ModelData.Armor(slot) == armor)
|
if (state.ModelData.Armor(slot) == armor)
|
||||||
|
|
@ -183,10 +189,10 @@ public class StateListener : IDisposable
|
||||||
var setStain = state[slot, true] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc;
|
var setStain = state[slot, true] is not StateChanged.Source.Fixed and not StateChanged.Source.Ipc;
|
||||||
switch (setItem, setStain)
|
switch (setItem, setStain)
|
||||||
{
|
{
|
||||||
case (true, true):
|
case (true, true):
|
||||||
_manager.ChangeEquip(state, slot, state.BaseData.Item(slot), state.BaseData.Stain(slot), StateChanged.Source.Manual);
|
_manager.ChangeEquip(state, slot, state.BaseData.Item(slot), state.BaseData.Stain(slot), StateChanged.Source.Manual);
|
||||||
state[slot, false] = StateChanged.Source.Game;
|
state[slot, false] = StateChanged.Source.Game;
|
||||||
state[slot, true] = StateChanged.Source.Game;
|
state[slot, true] = StateChanged.Source.Game;
|
||||||
break;
|
break;
|
||||||
case (true, false):
|
case (true, false):
|
||||||
_manager.ChangeItem(state, slot, state.BaseData.Item(slot), StateChanged.Source.Manual);
|
_manager.ChangeItem(state, slot, state.BaseData.Item(slot), StateChanged.Source.Manual);
|
||||||
|
|
@ -194,7 +200,7 @@ public class StateListener : IDisposable
|
||||||
break;
|
break;
|
||||||
case (false, true):
|
case (false, true):
|
||||||
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Manual);
|
_manager.ChangeStain(state, slot, state.BaseData.Stain(slot), StateChanged.Source.Manual);
|
||||||
state[slot, true] = StateChanged.Source.Game;
|
state[slot, true] = StateChanged.Source.Game;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -483,6 +489,7 @@ public class StateListener : IDisposable
|
||||||
private void Subscribe()
|
private void Subscribe()
|
||||||
{
|
{
|
||||||
_penumbra.CreatingCharacterBase += OnCreatingCharacterBase;
|
_penumbra.CreatingCharacterBase += OnCreatingCharacterBase;
|
||||||
|
_penumbra.CreatedCharacterBase += OnCreatedCharacterBase;
|
||||||
_slotUpdating.Subscribe(OnSlotUpdating, SlotUpdating.Priority.StateListener);
|
_slotUpdating.Subscribe(OnSlotUpdating, SlotUpdating.Priority.StateListener);
|
||||||
_equipmentLoading.Subscribe(OnEquipmentLoading, EquipmentLoading.Priority.StateListener);
|
_equipmentLoading.Subscribe(OnEquipmentLoading, EquipmentLoading.Priority.StateListener);
|
||||||
_weaponLoading.Subscribe(OnWeaponLoading, WeaponLoading.Priority.StateListener);
|
_weaponLoading.Subscribe(OnWeaponLoading, WeaponLoading.Priority.StateListener);
|
||||||
|
|
@ -494,6 +501,7 @@ public class StateListener : IDisposable
|
||||||
private void Unsubscribe()
|
private void Unsubscribe()
|
||||||
{
|
{
|
||||||
_penumbra.CreatingCharacterBase -= OnCreatingCharacterBase;
|
_penumbra.CreatingCharacterBase -= OnCreatingCharacterBase;
|
||||||
|
_penumbra.CreatedCharacterBase -= OnCreatedCharacterBase;
|
||||||
_slotUpdating.Unsubscribe(OnSlotUpdating);
|
_slotUpdating.Unsubscribe(OnSlotUpdating);
|
||||||
_equipmentLoading.Unsubscribe(OnEquipmentLoading);
|
_equipmentLoading.Unsubscribe(OnEquipmentLoading);
|
||||||
_weaponLoading.Unsubscribe(OnWeaponLoading);
|
_weaponLoading.Unsubscribe(OnWeaponLoading);
|
||||||
|
|
@ -501,4 +509,13 @@ public class StateListener : IDisposable
|
||||||
_headGearVisibility.Unsubscribe(OnHeadGearVisibilityChange);
|
_headGearVisibility.Unsubscribe(OnHeadGearVisibilityChange);
|
||||||
_weaponVisibility.Unsubscribe(OnWeaponVisibilityChange);
|
_weaponVisibility.Unsubscribe(OnWeaponVisibilityChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnCreatedCharacterBase(nint gameObject, string _, nint drawObject)
|
||||||
|
{
|
||||||
|
if (_creatingState == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_applier.ChangeHatState(new ActorData(gameObject, _creatingIdentifier.ToName()), _creatingState.ModelData.IsHatVisible());
|
||||||
|
_applier.ChangeWeaponState(new ActorData(gameObject, _creatingIdentifier.ToName()), _creatingState.ModelData.IsWeaponVisible());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue