diff --git a/Glamourer/Automation/AutoDesignApplier.cs b/Glamourer/Automation/AutoDesignApplier.cs index baf2e7e..256a8a7 100644 --- a/Glamourer/Automation/AutoDesignApplier.cs +++ b/Glamourer/Automation/AutoDesignApplier.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; +using Dalamud.Plugin.Services; using Glamourer.Customization; using Glamourer.Designs; using Glamourer.Events; @@ -31,6 +32,7 @@ public class AutoDesignApplier : IDisposable private readonly ObjectManager _objects; private readonly WeaponLoading _weapons; private readonly HumanModelList _humans; + private readonly IClientState _clientState; private ActorState? _jobChangeState; private EquipItem _jobChangeMainhand; @@ -38,7 +40,7 @@ public class AutoDesignApplier : IDisposable public AutoDesignApplier(Configuration config, AutoDesignManager manager, StateManager state, JobService jobs, CustomizationService customizations, ActorService actors, ItemUnlockManager itemUnlocks, CustomizeUnlockManager customizeUnlocks, - AutomationChanged @event, ObjectManager objects, WeaponLoading weapons, HumanModelList humans) + AutomationChanged @event, ObjectManager objects, WeaponLoading weapons, HumanModelList humans, IClientState clientState) { _config = config; _manager = manager; @@ -52,6 +54,7 @@ public class AutoDesignApplier : IDisposable _objects = objects; _weapons = weapons; _humans = humans; + _clientState = clientState; _jobs.JobChanged += OnJobChange; _event.Subscribe(OnAutomationChange, AutomationChanged.Priority.AutoDesignApplier); _weapons.Subscribe(OnWeaponLoading, WeaponLoading.Priority.AutoDesignApplier); @@ -227,10 +230,15 @@ public class AutoDesignApplier : IDisposable } else if (!GetPlayerSet(identifier, out set!)) { + if (state.UpdateTerritory(_clientState.TerritoryType) && _config.RevertManualChangesOnZoneChange) + _state.ResetState(state, StateChanged.Source.Game); return true; } - Reduce(actor, state, set, true, false); + var respectManual = !state.UpdateTerritory(_clientState.TerritoryType) || !_config.RevertManualChangesOnZoneChange; + if (!respectManual) + _state.ResetState(state, StateChanged.Source.Game); + Reduce(actor, state, set, respectManual, false); return true; } diff --git a/Glamourer/Configuration.cs b/Glamourer/Configuration.cs index 0d0573e..1c1f49d 100644 --- a/Glamourer/Configuration.cs +++ b/Glamourer/Configuration.cs @@ -34,6 +34,7 @@ public class Configuration : IPluginConfiguration, ISavable public bool ShowAutomationSetEditing { get; set; } = true; public bool ShowAllAutomatedApplicationRules { get; set; } = true; public bool ShowUnlockedItemWarnings { get; set; } = true; + public bool RevertManualChangesOnZoneChange { get; set; } = false; public MainWindow.TabType SelectedTab { get; set; } = MainWindow.TabType.Settings; public DoubleModifier DeleteDesignModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift); diff --git a/Glamourer/Gui/Tabs/SettingsTab.cs b/Glamourer/Gui/Tabs/SettingsTab.cs index cf8b9b6..ba3720e 100644 --- a/Glamourer/Gui/Tabs/SettingsTab.cs +++ b/Glamourer/Gui/Tabs/SettingsTab.cs @@ -82,6 +82,9 @@ public class SettingsTab : ITab Checkbox("Auto-Reload Gear", "Automatically reload equipment pieces on your own character when changing any mod options in Penumbra in their associated collection.", _config.AutoRedrawEquipOnChanges, _autoRedraw.SetState); + Checkbox("Revert Manual Changes on Zone Change", + "Restores the old behaviour of reverting your character to its game or automation base whenever you change the zone.", + _config.RevertManualChangesOnZoneChange, v => _config.RevertManualChangesOnZoneChange = v); ImGui.NewLine(); } diff --git a/Glamourer/State/ActorState.cs b/Glamourer/State/ActorState.cs index 26ef505..037d465 100644 --- a/Glamourer/State/ActorState.cs +++ b/Glamourer/State/ActorState.cs @@ -38,6 +38,9 @@ public class ActorState /// The Lock-Key locking this state. public uint Combination; + /// The territory the draw object was created last. + public ushort LastTerritory; + /// Whether the State is locked at all. public bool IsLocked => Combination != 0; @@ -98,4 +101,13 @@ public class ActorState _sources[i] = StateChanged.Source.Manual; } } + + public bool UpdateTerritory(ushort territory) + { + if (territory == LastTerritory) + return false; + + LastTerritory = territory; + return true; + } } diff --git a/Glamourer/State/StateManager.cs b/Glamourer/State/StateManager.cs index 8be11a5..7adbb37 100644 --- a/Glamourer/State/StateManager.cs +++ b/Glamourer/State/StateManager.cs @@ -3,7 +3,9 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Conditions; +using Dalamud.Plugin.Services; using Glamourer.Customization; using Glamourer.Designs; using Glamourer.Events; @@ -26,19 +28,21 @@ public class StateManager : IReadOnlyDictionary private readonly StateApplier _applier; private readonly StateEditor _editor; private readonly Condition _condition; + private readonly IClientState _clientState; private readonly Dictionary _states = new(); public StateManager(ActorService actors, ItemManager items, StateChanged @event, StateApplier applier, StateEditor editor, - HumanModelList humans, Condition condition) + HumanModelList humans, Condition condition, IClientState clientState) { - _actors = actors; - _items = items; - _event = @event; - _applier = applier; - _editor = editor; - _humans = humans; - _condition = condition; + _actors = actors; + _items = items; + _event = @event; + _applier = applier; + _editor = editor; + _humans = humans; + _condition = condition; + _clientState = clientState; } public IEnumerator> GetEnumerator() @@ -81,9 +85,10 @@ public class StateManager : IReadOnlyDictionary // and the draw objects data for the model data (where possible). state = new ActorState(identifier) { - ModelData = FromActor(actor, true), - BaseData = FromActor(actor, false), - LastJob = (byte)(actor.IsCharacter ? actor.AsCharacter->CharacterData.ClassJob : 0), + ModelData = FromActor(actor, true), + BaseData = FromActor(actor, false), + LastJob = (byte)(actor.IsCharacter ? actor.AsCharacter->CharacterData.ClassJob : 0), + LastTerritory = _clientState.TerritoryType, }; // state.Identifier is owned. _states.Add(state.Identifier, state); @@ -381,7 +386,9 @@ public class StateManager : IReadOnlyDictionary if (design.DoApplyVisorToggle()) _editor.ChangeMetaState(state, ActorState.MetaIndex.VisorState, design.DesignData.IsVisorToggled(), source, out _, key); - var flags = state.AllowsRedraw(_condition) ? design.ApplyCustomize : design.ApplyCustomize & ~CustomizeFlagExtensions.RedrawRequired; + var flags = state.AllowsRedraw(_condition) + ? design.ApplyCustomize + : design.ApplyCustomize & ~CustomizeFlagExtensions.RedrawRequired; _editor.ChangeHumanCustomize(state, design.DesignData.Customize, flags, source, out _, out var applied, key); redraw |= applied.RequiresRedraw(); @@ -408,7 +415,8 @@ public class StateManager : IReadOnlyDictionary { _applier.ChangeCustomize(actors, state.ModelData.Customize); foreach (var slot in EquipSlotExtensions.EqdpSlots) - _applier.ChangeArmor(actors, slot, state.ModelData.Armor(slot), state[slot, false] is not StateChanged.Source.Ipc, state.ModelData.IsHatVisible()); + _applier.ChangeArmor(actors, slot, state.ModelData.Armor(slot), state[slot, false] is not StateChanged.Source.Ipc, + state.ModelData.IsHatVisible()); var mainhandActors = state.ModelData.MainhandType != state.BaseData.MainhandType ? actors.OnlyGPose() : actors; _applier.ChangeMainhand(mainhandActors, state.ModelData.Item(EquipSlot.MainHand), state.ModelData.Stain(EquipSlot.MainHand)); var offhandActors = state.ModelData.OffhandType != state.BaseData.OffhandType ? actors.OnlyGPose() : actors;