diff --git a/Glamourer/Gui/Equipment/EquipmentDrawer.cs b/Glamourer/Gui/Equipment/EquipmentDrawer.cs index 1f8034a..533ba82 100644 --- a/Glamourer/Gui/Equipment/EquipmentDrawer.cs +++ b/Glamourer/Gui/Equipment/EquipmentDrawer.cs @@ -64,10 +64,10 @@ public class EquipmentDrawer _iconSize = new Vector2(2 * ImGui.GetFrameHeight() + ImGui.GetStyle().ItemSpacing.Y); _comboLength = DefaultWidth * ImGuiHelpers.GlobalScale; if (_requiredComboWidthUnscaled == 0) - { - _requiredComboWidthUnscaled = _items.ItemService.AwaitedService.AllItems(true).Concat(_items.ItemService.AwaitedService.AllItems(false)) - .Max(i => ImGui.CalcTextSize($"{i.Item2.Name} ({i.Item2.ModelString})").X) / ImGuiHelpers.GlobalScale; - } + _requiredComboWidthUnscaled = _items.ItemService.AwaitedService.AllItems(true) + .Concat(_items.ItemService.AwaitedService.AllItems(false)) + .Max(i => ImGui.CalcTextSize($"{i.Item2.Name} ({i.Item2.ModelString})").X) + / ImGuiHelpers.GlobalScale; _requiredComboWidth = _requiredComboWidthUnscaled * ImGuiHelpers.GlobalScale; } @@ -107,14 +107,15 @@ public class EquipmentDrawer } public DataChange DrawWeapons(in DesignData designData, out EquipItem rMainhand, out EquipItem rOffhand, out StainId rMainhandStain, - out StainId rOffhandStain, EquipFlag? cApply, out bool rApplyMainhand, out bool rApplyMainhandStain, out bool rApplyOffhand, - out bool rApplyOffhandStain, bool locked) + out StainId rOffhandStain, EquipFlag? cApply, bool allWeapons, out bool rApplyMainhand, out bool rApplyMainhandStain, + out bool rApplyOffhand, out bool rApplyOffhandStain, bool locked) => DrawWeapons(designData.Item(EquipSlot.MainHand), out rMainhand, designData.Item(EquipSlot.OffHand), out rOffhand, - designData.Stain(EquipSlot.MainHand), out rMainhandStain, designData.Stain(EquipSlot.OffHand), out rOffhandStain, cApply, - out rApplyMainhand, out rApplyMainhandStain, out rApplyOffhand, out rApplyOffhandStain, locked); + designData.Stain(EquipSlot.MainHand), out rMainhandStain, designData.Stain(EquipSlot.OffHand), out rOffhandStain, cApply, + allWeapons, out rApplyMainhand, out rApplyMainhandStain, out rApplyOffhand, out rApplyOffhandStain, locked); public DataChange DrawWeapons(EquipItem cMainhand, out EquipItem rMainhand, EquipItem cOffhand, out EquipItem rOffhand, StainId cMainhandStain, out StainId rMainhandStain, StainId cOffhandStain, out StainId rOffhandStain, EquipFlag? cApply, + bool allWeapons, out bool rApplyMainhand, out bool rApplyMainhandStain, out bool rApplyOffhand, out bool rApplyOffhandStain, bool locked) { if (cMainhand.ModelId.Value == 0) @@ -130,7 +131,6 @@ public class EquipmentDrawer return DataChange.None; } - var allWeapons = cApply.HasValue; if (_config.HideApplyCheckmarks) cApply = null; @@ -199,7 +199,7 @@ public class EquipmentDrawer label = combo.Label; using var disabled = ImRaii.Disabled(locked); - var change = combo.Draw(weapon.Name, weapon.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, _requiredComboWidth); + var change = combo.Draw(weapon.Name, weapon.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, _requiredComboWidth); if (change) weapon = combo.CurrentSelection; @@ -235,7 +235,7 @@ public class EquipmentDrawer label = combo.Label; armor = current; using var disabled = ImRaii.Disabled(locked); - var change = combo.Draw(armor.Name, armor.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, _requiredComboWidth); + var change = combo.Draw(armor.Name, armor.ItemId, small ? _comboLength - ImGui.GetFrameHeight() : _comboLength, _requiredComboWidth); if (change) armor = combo.CurrentSelection; diff --git a/Glamourer/Gui/Tabs/ActorTab/ActorPanel.cs b/Glamourer/Gui/Tabs/ActorTab/ActorPanel.cs index 7ad83a3..d00cf39 100644 --- a/Glamourer/Gui/Tabs/ActorTab/ActorPanel.cs +++ b/Glamourer/Gui/Tabs/ActorTab/ActorPanel.cs @@ -2,6 +2,8 @@ using System.Numerics; using Dalamud.Interface; using Dalamud.Interface.Internal.Notifications; +using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI; using Glamourer.Automation; using Glamourer.Customization; using Glamourer.Designs; @@ -157,9 +159,8 @@ public class ActorPanel } } - var weaponChanges = _equipmentDrawer.DrawWeapons(_state!.ModelData, out var newMainhand, out var newOffhand, - out var newMainhandStain, - out var newOffhandStain, null, out _, out _, out _, out _, _state.IsLocked); + var weaponChanges = _equipmentDrawer.DrawWeapons(_state!.ModelData, out var newMainhand, out var newOffhand, out var newMainhandStain, + out var newOffhandStain, null, GameMain.IsInGPose(), out _, out _, out _, out _, _state.IsLocked); if (weaponChanges.HasFlag(DataChange.Item)) if (weaponChanges.HasFlag(DataChange.Stain)) diff --git a/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs b/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs index 5f328e6..5307c73 100644 --- a/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs +++ b/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs @@ -120,7 +120,7 @@ public class DesignPanel } var weaponChanges = _equipmentDrawer.DrawWeapons(_selector.Selected!.DesignData, out var newMainhand, out var newOffhand, - out var newMainhandStain, out var newOffhandStain, _selector.Selected.ApplyEquip, out var applyMain, out var applyMainStain, + out var newMainhandStain, out var newOffhandStain, _selector.Selected.ApplyEquip, true, out var applyMain, out var applyMainStain, out var applyOff, out var applyOffStain, _selector.Selected!.WriteProtected()); if (weaponChanges.HasFlag(DataChange.Item)) @@ -264,7 +264,7 @@ public class DesignPanel ImGui.NewLine(); ApplyEquip("Dyes", AutoDesign.StainFlags, true, - EquipSlotExtensions.EqdpSlots.Prepend(EquipSlot.MainHand).Prepend(EquipSlot.OffHand)); + EquipSlotExtensions.FullSlots); ImGui.NewLine(); const uint all = 0x0Fu; diff --git a/Glamourer/State/StateApplier.cs b/Glamourer/State/StateApplier.cs index 9d61aca..b0fbba3 100644 --- a/Glamourer/State/StateApplier.cs +++ b/Glamourer/State/StateApplier.cs @@ -5,6 +5,7 @@ using Glamourer.Interop.Penumbra; using Glamourer.Interop.Structs; using Glamourer.Services; using Penumbra.Api.Enums; +using Penumbra.GameData.Actors; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; @@ -69,9 +70,7 @@ public class StateApplier var flags = Customize.Compare(mdl.GetCustomize(), customize); if (!flags.RequiresRedraw() || !mdl.IsHuman) - { _changeCustomize.UpdateCustomize(mdl, customize.Data); - } else _penumbra.RedrawObject(actor, RedrawType.Redraw); } @@ -165,11 +164,15 @@ public class StateApplier } /// - public ActorData ChangeWeapon(ActorState state, EquipSlot slot, bool apply) + public ActorData ChangeWeapon(ActorState state, EquipSlot slot, bool apply, bool onlyGPose) { var data = GetData(state); if (apply) + { + if (onlyGPose) + data.Objects.RemoveAll(a => a.Index is < (int)ScreenActor.GPosePlayer or >= (int)ScreenActor.CutsceneEnd); ChangeWeapon(data, slot, state.ModelData.Item(slot), state.ModelData.Stain(slot)); + } return data; } @@ -185,11 +188,15 @@ public class StateApplier } /// - public ActorData ChangeMainhand(ActorState state, bool apply) + public ActorData ChangeMainhand(ActorState state, bool apply, bool onlyGPose) { var data = GetData(state); if (apply) + { + if (onlyGPose) + data.Objects.RemoveAll(a => a.Index is < (int)ScreenActor.GPosePlayer or >= (int)ScreenActor.CutsceneEnd); ChangeMainhand(data, state.ModelData.Item(EquipSlot.MainHand), state.ModelData.Stain(EquipSlot.MainHand)); + } return data; } @@ -203,11 +210,16 @@ public class StateApplier } /// - public ActorData ChangeOffhand(ActorState state, bool apply) + public ActorData ChangeOffhand(ActorState state, bool apply, bool onlyGPose) { var data = GetData(state); if (apply) + { + if (onlyGPose) + data.Objects.RemoveAll(a => a.Index is < (int)ScreenActor.GPosePlayer or >= (int)ScreenActor.CutsceneEnd); ChangeOffhand(data, state.ModelData.Item(EquipSlot.OffHand), state.ModelData.Stain(EquipSlot.OffHand)); + } + return data; } diff --git a/Glamourer/State/StateEditor.cs b/Glamourer/State/StateEditor.cs index 62199f4..86650a2 100644 --- a/Glamourer/State/StateEditor.cs +++ b/Glamourer/State/StateEditor.cs @@ -122,6 +122,11 @@ public class StateEditor if (!state.CanUnlock(key)) return false; + // Can not change weapon type from expected type in state. + if (slot is EquipSlot.MainHand && item.Type != state.BaseData.MainhandType + || slot is EquipSlot.OffHand && item.Type != state.BaseData.MainhandType.ValidOffhand()) + return false; + state.ModelData.SetItem(slot, item); state[slot, false] = source; return true; diff --git a/Glamourer/State/StateListener.cs b/Glamourer/State/StateListener.cs index 5777311..cf4f8f7 100644 --- a/Glamourer/State/StateListener.cs +++ b/Glamourer/State/StateListener.cs @@ -269,7 +269,7 @@ public class StateListener : IDisposable return false; var offhand = actor.GetOffhand(); - return offhand.Variant == 0 && armor.Set.Value == offhand.Set.Value; + return offhand.Variant == 0 && offhand.Set.Value != 0 && armor.Set.Value == offhand.Set.Value; } var actorArmor = actor.GetArmor(slot); diff --git a/Glamourer/State/StateManager.cs b/Glamourer/State/StateManager.cs index f3aed60..1eacaa2 100644 --- a/Glamourer/State/StateManager.cs +++ b/Glamourer/State/StateManager.cs @@ -13,6 +13,7 @@ using Penumbra.GameData.Actors; using Penumbra.GameData.Data; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; +using Penumbra.String; namespace Glamourer.State; @@ -257,7 +258,7 @@ public class StateManager : IReadOnlyDictionary var type = slot.ToIndex() < 10 ? StateChanged.Type.Equip : StateChanged.Type.Weapon; var actors = type is StateChanged.Type.Equip ? _applier.ChangeArmor(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc) - : _applier.ChangeWeapon(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc); + : _applier.ChangeWeapon(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc, item.Type != old.Type); Glamourer.Log.Verbose( $"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}). [Affecting {actors.ToLazyString("nothing")}.]"); _event.Invoke(type, source, state, actors, (old, item, slot)); @@ -272,7 +273,7 @@ public class StateManager : IReadOnlyDictionary var type = slot.ToIndex() < 10 ? StateChanged.Type.Equip : StateChanged.Type.Weapon; var actors = type is StateChanged.Type.Equip ? _applier.ChangeArmor(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc) - : _applier.ChangeWeapon(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc); + : _applier.ChangeWeapon(state, slot, source is StateChanged.Source.Manual or StateChanged.Source.Ipc, item.Type != old.Type); Glamourer.Log.Verbose( $"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}) and its stain from {oldStain.Value} to {stain.Value}. [Affecting {actors.ToLazyString("nothing")}.]"); _event.Invoke(type, source, state, actors, (old, item, slot));