mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-13 19:27:43 +01:00
Implements true endpoints for all glamourer operations, also correctly marks reverts and gearsets. Replaced back excessive logging to maintain with logging formats expected by glamourer.
This commit is contained in:
parent
c605d19510
commit
e1a41b5f3c
21 changed files with 225 additions and 99 deletions
|
|
@ -17,6 +17,7 @@ public class StateEditor(
|
|||
InternalStateEditor editor,
|
||||
StateApplier applier,
|
||||
StateChanged stateChanged,
|
||||
StateUpdated stateUpdated,
|
||||
JobChangeState jobChange,
|
||||
Configuration config,
|
||||
ItemManager items,
|
||||
|
|
@ -27,6 +28,7 @@ public class StateEditor(
|
|||
protected readonly InternalStateEditor Editor = editor;
|
||||
protected readonly StateApplier Applier = applier;
|
||||
protected readonly StateChanged StateChanged = stateChanged;
|
||||
protected readonly StateUpdated StateUpdated = stateUpdated;
|
||||
protected readonly Configuration Config = config;
|
||||
protected readonly ItemManager Items = items;
|
||||
|
||||
|
|
@ -41,6 +43,7 @@ public class StateEditor(
|
|||
Glamourer.Log.Verbose(
|
||||
$"Set model id in state {state.Identifier.Incognito(null)} from {old} to {modelId}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
StateChanged.Invoke(StateChangeType.Model, source, state, actors, null);
|
||||
StateUpdated.Invoke(StateUpdateType.ModelChange, actors);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -419,6 +422,8 @@ public class StateEditor(
|
|||
|
||||
Glamourer.Log.Debug($"Applied design to {state.Identifier.Incognito(null)}. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
StateChanged.Invoke(StateChangeType.Design, state.Sources[MetaIndex.Wetness], state, actors, null); // FIXME: maybe later
|
||||
if(settings.SendStateUpdate)
|
||||
StateUpdated.Invoke(StateUpdateType.DesignApplied, actors);
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ using Penumbra.GameData.DataContainers;
|
|||
using Glamourer.Designs;
|
||||
using Penumbra.GameData.Interop;
|
||||
using ObjectManager = Glamourer.Interop.ObjectManager;
|
||||
using Glamourer.Api.Enums;
|
||||
|
||||
namespace Glamourer.State;
|
||||
|
||||
|
|
@ -34,10 +35,12 @@ public class StateListener : IDisposable
|
|||
private readonly PenumbraService _penumbra;
|
||||
private readonly EquipSlotUpdating _equipSlotUpdating;
|
||||
private readonly BonusSlotUpdating _bonusSlotUpdating;
|
||||
private readonly GearsetDataLoaded _gearsetDataLoaded;
|
||||
private readonly WeaponLoading _weaponLoading;
|
||||
private readonly HeadGearVisibilityChanged _headGearVisibility;
|
||||
private readonly VisorStateChanged _visorState;
|
||||
private readonly WeaponVisibilityChanged _weaponVisibility;
|
||||
private readonly StateUpdated _stateUpdated;
|
||||
private readonly AutoDesignApplier _autoDesignApplier;
|
||||
private readonly FunModule _funModule;
|
||||
private readonly HumanModelList _humans;
|
||||
|
|
@ -54,11 +57,11 @@ public class StateListener : IDisposable
|
|||
private ActorState? _customizeState;
|
||||
|
||||
public StateListener(StateManager manager, ItemManager items, PenumbraService penumbra, ActorManager actors, Configuration config,
|
||||
EquipSlotUpdating equipSlotUpdating, WeaponLoading weaponLoading, VisorStateChanged visorState,
|
||||
EquipSlotUpdating equipSlotUpdating, GearsetDataLoaded gearsetDataLoaded, WeaponLoading weaponLoading, VisorStateChanged visorState,
|
||||
WeaponVisibilityChanged weaponVisibility, HeadGearVisibilityChanged headGearVisibility, AutoDesignApplier autoDesignApplier,
|
||||
FunModule funModule, HumanModelList humans, StateApplier applier, MovedEquipment movedEquipment, ObjectManager objects,
|
||||
GPoseService gPose, ChangeCustomizeService changeCustomizeService, CustomizeService customizations, ICondition condition,
|
||||
CrestService crestService, BonusSlotUpdating bonusSlotUpdating)
|
||||
CrestService crestService, BonusSlotUpdating bonusSlotUpdating, StateUpdated stateUpdated)
|
||||
{
|
||||
_manager = manager;
|
||||
_items = items;
|
||||
|
|
@ -66,6 +69,7 @@ public class StateListener : IDisposable
|
|||
_actors = actors;
|
||||
_config = config;
|
||||
_equipSlotUpdating = equipSlotUpdating;
|
||||
_gearsetDataLoaded = gearsetDataLoaded;
|
||||
_weaponLoading = weaponLoading;
|
||||
_visorState = visorState;
|
||||
_weaponVisibility = weaponVisibility;
|
||||
|
|
@ -82,6 +86,7 @@ public class StateListener : IDisposable
|
|||
_condition = condition;
|
||||
_crestService = crestService;
|
||||
_bonusSlotUpdating = bonusSlotUpdating;
|
||||
_stateUpdated = stateUpdated;
|
||||
Subscribe();
|
||||
}
|
||||
|
||||
|
|
@ -259,6 +264,22 @@ public class StateListener : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void OnGearsetDataLoaded(Model model)
|
||||
{
|
||||
var actor = _penumbra.GameObjectFromDrawObject(model);
|
||||
if (_condition[ConditionFlag.CreatingCharacter] && actor.Index >= ObjectIndex.CutsceneStart)
|
||||
return;
|
||||
|
||||
// ensure actor and state are valid.
|
||||
if (!actor.Identifier(_actors, out var identifier))
|
||||
return;
|
||||
|
||||
_objects.Update();
|
||||
if (_objects.TryGetValue(identifier, out var actors) && actors.Valid)
|
||||
_stateUpdated.Invoke(StateUpdateType.Gearset, actors);
|
||||
}
|
||||
|
||||
|
||||
private void OnMovedEquipment((EquipSlot, uint, StainIds)[] items)
|
||||
{
|
||||
_objects.Update();
|
||||
|
|
@ -382,7 +403,7 @@ public class StateListener : IDisposable
|
|||
lastFistOffhand = new CharacterWeapon((PrimaryId)(weapon.Skeleton.Id + 50), weapon.Weapon, weapon.Variant,
|
||||
weapon.Stains);
|
||||
_fistOffhands[actor] = lastFistOffhand;
|
||||
Glamourer.Log.Verbose($"Storing fist weapon offhand {lastFistOffhand} for 0x{actor.Address:X}.");
|
||||
Glamourer.Log.Excessive($"Storing fist weapon offhand {lastFistOffhand} for 0x{actor.Address:X}.");
|
||||
}
|
||||
|
||||
_funModule.ApplyFunToWeapon(actor, ref weapon, slot);
|
||||
|
|
@ -765,6 +786,7 @@ public class StateListener : IDisposable
|
|||
_penumbra.CreatedCharacterBase += OnCreatedCharacterBase;
|
||||
_equipSlotUpdating.Subscribe(OnEquipSlotUpdating, EquipSlotUpdating.Priority.StateListener);
|
||||
_bonusSlotUpdating.Subscribe(OnBonusSlotUpdating, BonusSlotUpdating.Priority.StateListener);
|
||||
_gearsetDataLoaded.Subscribe(OnGearsetDataLoaded, GearsetDataLoaded.Priority.StateListener);
|
||||
_movedEquipment.Subscribe(OnMovedEquipment, MovedEquipment.Priority.StateListener);
|
||||
_weaponLoading.Subscribe(OnWeaponLoading, WeaponLoading.Priority.StateListener);
|
||||
_visorState.Subscribe(OnVisorChange, VisorStateChanged.Priority.StateListener);
|
||||
|
|
@ -782,6 +804,7 @@ public class StateListener : IDisposable
|
|||
_penumbra.CreatedCharacterBase -= OnCreatedCharacterBase;
|
||||
_equipSlotUpdating.Unsubscribe(OnEquipSlotUpdating);
|
||||
_bonusSlotUpdating.Unsubscribe(OnBonusSlotUpdating);
|
||||
_gearsetDataLoaded.Unsubscribe(OnGearsetDataLoaded);
|
||||
_movedEquipment.Unsubscribe(OnMovedEquipment);
|
||||
_weaponLoading.Unsubscribe(OnWeaponLoading);
|
||||
_visorState.Unsubscribe(OnVisorChange);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ public sealed class StateManager(
|
|||
ActorManager _actors,
|
||||
ItemManager items,
|
||||
StateChanged @event,
|
||||
StateUpdated @event2,
|
||||
StateApplier applier,
|
||||
InternalStateEditor editor,
|
||||
HumanModelList _humans,
|
||||
|
|
@ -30,7 +31,7 @@ public sealed class StateManager(
|
|||
DesignMerger merger,
|
||||
ModSettingApplier modApplier,
|
||||
GPoseService gPose)
|
||||
: StateEditor(editor, applier, @event, jobChange, config, items, merger, modApplier, gPose),
|
||||
: StateEditor(editor, applier, @event, @event2, jobChange, config, items, merger, modApplier, gPose),
|
||||
IReadOnlyDictionary<ActorIdentifier, ActorState>
|
||||
{
|
||||
private readonly Dictionary<ActorIdentifier, ActorState> _states = [];
|
||||
|
|
@ -235,7 +236,7 @@ public sealed class StateManager(
|
|||
public void TurnHuman(ActorState state, StateSource source, uint key = 0)
|
||||
=> ChangeModelId(state, 0, CustomizeArray.Default, nint.Zero, source, key);
|
||||
|
||||
public void ResetState(ActorState state, StateSource source, uint key = 0)
|
||||
public void ResetState(ActorState state, StateSource source, uint key = 0, bool stateUpdate = false)
|
||||
{
|
||||
if (!state.Unlock(key))
|
||||
return;
|
||||
|
|
@ -276,6 +277,9 @@ public sealed class StateManager(
|
|||
Glamourer.Log.Debug(
|
||||
$"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
StateChanged.Invoke(StateChangeType.Reset, source, state, actors, null);
|
||||
// only invoke if we define this reset call as the final call in our state update.
|
||||
if(stateUpdate)
|
||||
StateUpdated.Invoke(StateUpdateType.Revert, actors);
|
||||
}
|
||||
|
||||
public void ResetAdvancedState(ActorState state, StateSource source, uint key = 0)
|
||||
|
|
@ -301,6 +305,8 @@ public sealed class StateManager(
|
|||
Glamourer.Log.Debug(
|
||||
$"Reset advanced customization and dye state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
StateChanged.Invoke(StateChangeType.Reset, source, state, actors, null);
|
||||
// Update that we have completed a full operation. (We can do this directly as nothing else is linked)
|
||||
StateUpdated.Invoke(StateUpdateType.RevertAdvanced, actors);
|
||||
}
|
||||
|
||||
public void ResetCustomize(ActorState state, StateSource source, uint key = 0)
|
||||
|
|
@ -318,6 +324,8 @@ public sealed class StateManager(
|
|||
actors = Applier.ChangeCustomize(state, true);
|
||||
Glamourer.Log.Verbose(
|
||||
$"Reset customization state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
// Update that we have completed a full operation. (We can do this directly as nothing else is linked)
|
||||
StateUpdated.Invoke(StateUpdateType.RevertCustomize, actors);
|
||||
}
|
||||
|
||||
public void ResetEquip(ActorState state, StateSource source, uint key = 0)
|
||||
|
|
@ -367,6 +375,8 @@ public sealed class StateManager(
|
|||
|
||||
Glamourer.Log.Verbose(
|
||||
$"Reset equipment state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]");
|
||||
// Update that we have completed a full operation. (We can do this directly as nothing else is linked)
|
||||
StateUpdated.Invoke(StateUpdateType.RevertEquipment, actors);
|
||||
}
|
||||
|
||||
public void ResetStateFixed(ActorState state, bool respectManualPalettes, uint key = 0)
|
||||
|
|
@ -443,21 +453,44 @@ public sealed class StateManager(
|
|||
}
|
||||
}
|
||||
|
||||
public void ReapplyState(Actor actor, bool forceRedraw, StateSource source)
|
||||
public void ReapplyState(Actor actor, bool forceRedraw, StateSource source, bool isUpdate = false)
|
||||
{
|
||||
if (!GetOrCreate(actor, out var state))
|
||||
return;
|
||||
|
||||
ReapplyState(actor, state, forceRedraw, source);
|
||||
ReapplyState(actor, state, forceRedraw, source, isUpdate);
|
||||
}
|
||||
|
||||
public void ReapplyState(Actor actor, ActorState state, bool forceRedraw, StateSource source)
|
||||
public void ReapplyState(Actor actor, ActorState state, bool forceRedraw, StateSource source, bool isUpdate)
|
||||
{
|
||||
var data = Applier.ApplyAll(state,
|
||||
forceRedraw
|
||||
|| !actor.Model.IsHuman
|
||||
|| CustomizeArray.Compare(actor.Model.GetCustomize(), state.ModelData.Customize).RequiresRedraw(), false);
|
||||
StateChanged.Invoke(StateChangeType.Reapply, source, state, data, null);
|
||||
if(isUpdate)
|
||||
StateUpdated.Invoke(StateUpdateType.Reapply, data);
|
||||
}
|
||||
|
||||
/// <summary> Automation variant for reapply, to fire the correct StateUpdateType once reapplied. </summary>
|
||||
public void ReapplyAutomationState(Actor actor, bool forceRedraw, bool wasReset, StateSource source)
|
||||
{
|
||||
if (!GetOrCreate(actor, out var state))
|
||||
return;
|
||||
|
||||
ReapplyAutomationState(actor, state, forceRedraw, wasReset, source);
|
||||
}
|
||||
|
||||
/// <summary> Automation variant for reapply, to fire the correct StateUpdateType once reapplied. </summary>
|
||||
public void ReapplyAutomationState(Actor actor, ActorState state, bool forceRedraw, bool wasReset, StateSource source)
|
||||
{
|
||||
var data = Applier.ApplyAll(state,
|
||||
forceRedraw
|
||||
|| !actor.Model.IsHuman
|
||||
|| CustomizeArray.Compare(actor.Model.GetCustomize(), state.ModelData.Customize).RequiresRedraw(), false);
|
||||
StateChanged.Invoke(StateChangeType.Reapply, source, state, data, null);
|
||||
// invoke the automation update based on what reset is.
|
||||
StateUpdated.Invoke(wasReset ? StateUpdateType.RevertAutomation : StateUpdateType.ReapplyAutomation, data);
|
||||
}
|
||||
|
||||
public void DeleteState(ActorIdentifier identifier)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue