mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Make AutoDesignApplier use MergedDesign.
This commit is contained in:
parent
2422295e67
commit
96c4ae762e
3 changed files with 101 additions and 65 deletions
|
|
@ -35,20 +35,18 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
private readonly IClientState _clientState;
|
||||
|
||||
private ActorState? _jobChangeState;
|
||||
private readonly Dictionary<FullEquipType, (EquipItem, StateChanged.Source)> _jobChangeMainhand = [];
|
||||
private readonly Dictionary<FullEquipType, (EquipItem, StateChanged.Source)> _jobChangeOffhand = [];
|
||||
private readonly Dictionary<FullEquipType, (EquipItem, StateChanged.Source)> _jobChange = [];
|
||||
|
||||
private void ResetJobChange()
|
||||
{
|
||||
_jobChangeState = null;
|
||||
_jobChangeMainhand.Clear();
|
||||
_jobChangeOffhand.Clear();
|
||||
_jobChange.Clear();
|
||||
}
|
||||
|
||||
public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs,
|
||||
CustomizeService customizations, ActorManager actors, ItemUnlockManager itemUnlocks, CustomizeUnlockManager customizeUnlocks,
|
||||
AutomationChanged @event, ObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState,
|
||||
EquippedGearset equippedGearset)
|
||||
EquippedGearset equippedGearset, DesignMerger designMerger)
|
||||
{
|
||||
_config = config;
|
||||
_manager = manager;
|
||||
|
|
@ -64,6 +62,7 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
_humans = humans;
|
||||
_clientState = clientState;
|
||||
_equippedGearset = equippedGearset;
|
||||
_designMerger = designMerger;
|
||||
_jobs.JobChanged += OnJobChange;
|
||||
_event.Subscribe(OnAutomationChange, AutomationChanged.Priority.AutoDesignApplier);
|
||||
_weapons.Subscribe(OnWeaponLoading, WeaponLoading.Priority.AutoDesignApplier);
|
||||
|
|
@ -91,7 +90,7 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
{
|
||||
case EquipSlot.MainHand:
|
||||
{
|
||||
if (_jobChangeMainhand.TryGetValue(current.Type, out var data))
|
||||
if (_jobChange.TryGetValue(current.Type, out var data))
|
||||
{
|
||||
Glamourer.Log.Verbose(
|
||||
$"Changing Mainhand from {_jobChangeState.ModelData.Weapon(EquipSlot.MainHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
||||
|
|
@ -103,7 +102,7 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
}
|
||||
case EquipSlot.OffHand when current.Type == _jobChangeState.BaseData.MainhandType.Offhand():
|
||||
{
|
||||
if (_jobChangeOffhand.TryGetValue(current.Type, out var data))
|
||||
if (_jobChange.TryGetValue(current.Type, out var data))
|
||||
{
|
||||
Glamourer.Log.Verbose(
|
||||
$"Changing Offhand from {_jobChangeState.ModelData.Weapon(EquipSlot.OffHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{actor.Address:X}.");
|
||||
|
|
@ -270,11 +269,6 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
|
||||
private unsafe void Reduce(Actor actor, ActorState state, AutoDesignSet set, bool respectManual, bool fromJobChange)
|
||||
{
|
||||
EquipFlag totalEquipFlags = 0;
|
||||
CustomizeFlag totalCustomizeFlags = 0;
|
||||
CrestFlag totalCrestFlags = 0;
|
||||
CustomizeParameterFlag totalParameterFlags = 0;
|
||||
byte totalMetaFlags = 0;
|
||||
if (set.BaseState == AutoDesignSet.Base.Game)
|
||||
_state.ResetStateFixed(state, respectManual);
|
||||
else if (!respectManual)
|
||||
|
|
@ -283,30 +277,8 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
if (!_humans.IsHuman((uint)actor.AsCharacter->CharacterData.ModelCharaId))
|
||||
return;
|
||||
|
||||
foreach (var design in set.Designs)
|
||||
{
|
||||
if (!design.IsActive(actor))
|
||||
continue;
|
||||
|
||||
if (design.Type is 0)
|
||||
continue;
|
||||
|
||||
ref readonly var data = ref design.GetDesignData(state);
|
||||
var source = design.Revert ? StateChanged.Source.Game : StateChanged.Source.Fixed;
|
||||
|
||||
if (!data.IsHuman)
|
||||
continue;
|
||||
|
||||
var (equipFlags, customizeFlags, crestFlags, parameterFlags, applyHat, applyVisor, applyWeapon, applyWet) = design.ApplyWhat();
|
||||
ReduceMeta(state, data, applyHat, applyVisor, applyWeapon, applyWet, ref totalMetaFlags, respectManual, source);
|
||||
ReduceCustomize(state, data, customizeFlags, ref totalCustomizeFlags, respectManual, source);
|
||||
ReduceEquip(state, data, equipFlags, ref totalEquipFlags, respectManual, source, fromJobChange);
|
||||
ReduceCrests(state, data, crestFlags, ref totalCrestFlags, respectManual, source);
|
||||
ReduceParameters(state, data, parameterFlags, ref totalParameterFlags, respectManual, source);
|
||||
}
|
||||
|
||||
if (totalCustomizeFlags != 0)
|
||||
state.ModelData.ModelId = 0;
|
||||
var mergedDesign = _designMerger.Merge(set.Designs.Where(d => d.IsActive(actor)).Select(d => ((DesignBase?) d.Design, d.Type)), state.ModelData, true);
|
||||
ApplyToState(state, mergedDesign, respectManual, fromJobChange, StateChanged.Source.Fixed);
|
||||
}
|
||||
|
||||
/// <summary> Get world-specific first and all-world afterward. </summary>
|
||||
|
|
@ -332,39 +304,57 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void ReduceCrests(ActorState state, in DesignData design, CrestFlag crestFlags, ref CrestFlag totalCrestFlags, bool respectManual,
|
||||
StateChanged.Source source)
|
||||
private void ApplyToState(ActorState state, MergedDesign mergedDesign, bool respectManual, bool fromJobChange, StateChanged.Source source)
|
||||
{
|
||||
crestFlags &= ~totalCrestFlags;
|
||||
if (crestFlags == 0)
|
||||
return;
|
||||
|
||||
foreach (var slot in CrestExtensions.AllRelevantSet)
|
||||
{
|
||||
if (!crestFlags.HasFlag(slot))
|
||||
continue;
|
||||
|
||||
foreach (var slot in CrestExtensions.AllRelevantSet.Where(mergedDesign.Design.DoApplyCrest))
|
||||
if (!respectManual || state.Source[slot] is not StateChanged.Source.Manual)
|
||||
_state.ChangeCrest(state, slot, design.Crest(slot), source);
|
||||
totalCrestFlags |= slot;
|
||||
}
|
||||
}
|
||||
_state.ChangeCrest(state, slot, mergedDesign.Design.DesignData.Crest(slot), mergedDesign.GetSource(slot, source));
|
||||
|
||||
private void ReduceParameters(ActorState state, in DesignData design, CustomizeParameterFlag parameterFlags,
|
||||
ref CustomizeParameterFlag totalParameterFlags, bool respectManual, StateChanged.Source source)
|
||||
{
|
||||
parameterFlags &= ~totalParameterFlags;
|
||||
if (parameterFlags == 0)
|
||||
return;
|
||||
foreach (var parameter in mergedDesign.Design.ApplyParameters.Iterate())
|
||||
if (!respectManual || state.Source[parameter] is not StateChanged.Source.Manual and not StateChanged.Source.Pending)
|
||||
_state.ChangeCustomizeParameter(state, parameter, mergedDesign.Design.DesignData.Parameters[parameter], mergedDesign.GetSource(parameter, source));
|
||||
|
||||
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
if (!parameterFlags.HasFlag(flag))
|
||||
if (mergedDesign.Design.DoApplyEquip(slot))
|
||||
{
|
||||
if (!respectManual || state.Source[slot, false] is not StateChanged.Source.Manual)
|
||||
_state.ChangeItem(state, slot, mergedDesign.Design.DesignData.Item(slot), mergedDesign.GetSource(slot, false, source));
|
||||
}
|
||||
|
||||
if (mergedDesign.Design.DoApplyStain(slot))
|
||||
{
|
||||
if (!respectManual || state.Source[slot, true] is not StateChanged.Source.Manual)
|
||||
_state.ChangeStain(state, slot, mergedDesign.Design.DesignData.Stain(slot), mergedDesign.GetSource(slot, true, source));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var weaponSlot in EquipSlotExtensions.WeaponSlots)
|
||||
{
|
||||
if (mergedDesign.Design.DoApplyStain(weaponSlot))
|
||||
{
|
||||
if (!respectManual || state.Source[weaponSlot, true] is not StateChanged.Source.Manual)
|
||||
_state.ChangeStain(state, weaponSlot, mergedDesign.Design.DesignData.Stain(weaponSlot), mergedDesign.GetSource(weaponSlot, true, source));
|
||||
}
|
||||
|
||||
if (!mergedDesign.Design.DoApplyEquip(weaponSlot))
|
||||
continue;
|
||||
|
||||
if (!respectManual || state.Source[flag] is not StateChanged.Source.Manual and not StateChanged.Source.Pending)
|
||||
_state.ChangeCustomizeParameter(state, flag, design.Parameters[flag], source);
|
||||
totalParameterFlags |= flag;
|
||||
if (respectManual && state.Source[weaponSlot, false] is StateChanged.Source.Manual)
|
||||
continue;
|
||||
|
||||
var currentType = state.ModelData.Item(weaponSlot).Type;
|
||||
if (fromJobChange)
|
||||
{
|
||||
foreach (var (key, (weapon, weaponSource)) in mergedDesign.Weapons)
|
||||
if (key.ToSlot() == weaponSlot)
|
||||
_jobChange.TryAdd(key, (weapon, MergedDesign.GetSource(weaponSource, source)));
|
||||
_jobChangeState = state;
|
||||
}
|
||||
else if (mergedDesign.Weapons.TryGetValue(currentType, out var weapon))
|
||||
{
|
||||
_state.ChangeItem(state, weaponSlot, weapon.Item1, MergedDesign.GetSource(weapon.Item2, source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,7 +397,7 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
{
|
||||
if (fromJobChange)
|
||||
{
|
||||
_jobChangeMainhand.TryAdd(item.Type, (item, source));
|
||||
_jobChange.TryAdd(item.Type, (item, source));
|
||||
_jobChangeState = state;
|
||||
}
|
||||
else if (state.ModelData.Item(EquipSlot.MainHand).Type == item.Type)
|
||||
|
|
@ -427,7 +417,7 @@ public sealed class AutoDesignApplier : IDisposable
|
|||
{
|
||||
if (fromJobChange)
|
||||
{
|
||||
_jobChangeOffhand.TryAdd(item.Type, (item, source));
|
||||
_jobChange.TryAdd(item.Type, (item, source));
|
||||
_jobChangeState = state;
|
||||
}
|
||||
else if (state.ModelData.Item(EquipSlot.OffHand).Type == item.Type)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using Glamourer.GameData;
|
|||
using Glamourer.Services;
|
||||
using Glamourer.State;
|
||||
using Glamourer.Unlocks;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ public class DesignMerger(
|
|||
CustomizeService _customize,
|
||||
Configuration _config,
|
||||
ItemUnlockManager _itemUnlocks,
|
||||
CustomizeUnlockManager _customizeUnlocks)
|
||||
CustomizeUnlockManager _customizeUnlocks) : IService
|
||||
{
|
||||
public MergedDesign Merge(IEnumerable<(DesignBase?, ApplicationType)> designs, in DesignData baseRef, bool respectOwnership)
|
||||
{
|
||||
|
|
|
|||
45
Glamourer/Designs/Links/MergedDesign.cs
Normal file
45
Glamourer/Designs/Links/MergedDesign.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using Glamourer.Events;
|
||||
using Glamourer.GameData;
|
||||
using Glamourer.State;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Designs.Links;
|
||||
|
||||
public sealed class MergedDesign
|
||||
{
|
||||
public MergedDesign(DesignManager designManager)
|
||||
{
|
||||
Design = designManager.CreateTemporary();
|
||||
Design.ApplyEquip = 0;
|
||||
Design.ApplyCustomize = 0;
|
||||
Design.ApplyCrest = 0;
|
||||
Design.ApplyParameters = 0;
|
||||
Design.SetApplyWetness(false);
|
||||
Design.SetApplyVisorToggle(false);
|
||||
Design.SetApplyWeaponVisible(false);
|
||||
Design.SetApplyHatVisible(false);
|
||||
}
|
||||
|
||||
public readonly DesignBase Design;
|
||||
public readonly Dictionary<FullEquipType, (EquipItem, StateChanged.Source)> Weapons = new(4);
|
||||
public readonly StateSource Source = new();
|
||||
|
||||
public StateChanged.Source GetSource(EquipSlot slot, bool stain, StateChanged.Source actualSource)
|
||||
=> GetSource(Source[slot, stain], actualSource);
|
||||
|
||||
public StateChanged.Source GetSource(CrestFlag slot, StateChanged.Source actualSource)
|
||||
=> GetSource(Source[slot], actualSource);
|
||||
|
||||
public StateChanged.Source GetSource(CustomizeIndex type, StateChanged.Source actualSource)
|
||||
=> GetSource(Source[type], actualSource);
|
||||
|
||||
public StateChanged.Source GetSource(MetaIndex index, StateChanged.Source actualSource)
|
||||
=> GetSource(Source[index], actualSource);
|
||||
|
||||
public StateChanged.Source GetSource(CustomizeParameterFlag flag, StateChanged.Source actualSource)
|
||||
=> GetSource(Source[flag], actualSource);
|
||||
|
||||
public static StateChanged.Source GetSource(StateChanged.Source given, StateChanged.Source actualSource)
|
||||
=> given is StateChanged.Source.Game ? StateChanged.Source.Game : actualSource;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue