From 3c68124b29e96d846a5b274344403eeaa47a6424 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 19 Dec 2025 14:15:14 +0100 Subject: [PATCH 01/10] Ny --- Glamourer/Gui/Tabs/SettingsTab/SettingsTab.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Glamourer/Gui/Tabs/SettingsTab/SettingsTab.cs b/Glamourer/Gui/Tabs/SettingsTab/SettingsTab.cs index 6432811..e559841 100644 --- a/Glamourer/Gui/Tabs/SettingsTab/SettingsTab.cs +++ b/Glamourer/Gui/Tabs/SettingsTab/SettingsTab.cs @@ -119,7 +119,7 @@ public class SettingsTab( config.AutoRedrawEquipOnChanges = v; autoRedraw.Invoke(v); }); - Checkbox("Attach to PCP-Handling"u8, + Checkbox("Attach to PCP Handling"u8, "Add the actor's glamourer state when a PCP is created by Penumbra, and create a design and apply it if possible when a PCP is installed by Penumbra."u8, config.AttachToPcp, pcpService.Set); var active = config.DeleteDesignModifier.IsActive(); From 98b702d6e663f4affe8df479683ed80f0bd65ab1 Mon Sep 17 00:00:00 2001 From: Actions User Date: Fri, 19 Dec 2025 13:16:42 +0000 Subject: [PATCH 02/10] [CI] Updating repo.json for 1.5.1.6 --- repo.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/repo.json b/repo.json index d2c030b..73f3e21 100644 --- a/repo.json +++ b/repo.json @@ -17,8 +17,8 @@ "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "1.5.1.5", - "TestingAssemblyVersion": "1.5.1.5", + "AssemblyVersion": "1.5.1.6", + "TestingAssemblyVersion": "1.5.1.6", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 14, @@ -27,9 +27,9 @@ "IsTestingExclusive": "False", "DownloadCount": 1, "LastUpdate": 1618608322, - "DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.5/Glamourer.zip", - "DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.5/Glamourer.zip", - "DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.5/Glamourer.zip", + "DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.6/Glamourer.zip", + "DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.6/Glamourer.zip", + "DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.6/Glamourer.zip", "IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/main/images/icon.png" } ] From 96f825e29851acab5374bf15c4ee877803111b93 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sat, 20 Dec 2025 16:01:00 +0100 Subject: [PATCH 03/10] Update Penumbra API. --- Penumbra.Api | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Penumbra.Api b/Penumbra.Api index 1750c41..52a3216 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 1750c41b53e1000c99a7fb9d8a0f082aef639a41 +Subproject commit 52a3216a525592205198303df2844435e382cf87 From 0d9a0d49aba6f04f3eb20f56037c46327614d57d Mon Sep 17 00:00:00 2001 From: Actions User Date: Sat, 20 Dec 2025 15:03:30 +0000 Subject: [PATCH 04/10] [CI] Updating repo.json for 1.5.1.7 --- repo.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/repo.json b/repo.json index 73f3e21..31b4c6e 100644 --- a/repo.json +++ b/repo.json @@ -17,8 +17,8 @@ "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "1.5.1.6", - "TestingAssemblyVersion": "1.5.1.6", + "AssemblyVersion": "1.5.1.7", + "TestingAssemblyVersion": "1.5.1.7", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 14, @@ -27,9 +27,9 @@ "IsTestingExclusive": "False", "DownloadCount": 1, "LastUpdate": 1618608322, - "DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.6/Glamourer.zip", - "DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.6/Glamourer.zip", - "DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.6/Glamourer.zip", + "DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.7/Glamourer.zip", + "DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.7/Glamourer.zip", + "DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.7/Glamourer.zip", "IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/main/images/icon.png" } ] From 59c9601a9bc8743eee7dd6ea0ad6080b611cc394 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 26 Dec 2025 18:20:44 +0100 Subject: [PATCH 05/10] Fix issue with material value in history. --- Glamourer/Designs/History/DesignTransaction.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Glamourer/Designs/History/DesignTransaction.cs b/Glamourer/Designs/History/DesignTransaction.cs index 98e3eec..65086db 100644 --- a/Glamourer/Designs/History/DesignTransaction.cs +++ b/Glamourer/Designs/History/DesignTransaction.cs @@ -1,6 +1,7 @@ using Glamourer.GameData; using Glamourer.Interop.Material; using Glamourer.Interop.Penumbra; +using Glamourer.State; using Penumbra.GameData.Enums; namespace Glamourer.Designs.History; @@ -125,7 +126,10 @@ public readonly record struct MaterialTransaction(MaterialValueIndex Index, Colo => older is MaterialTransaction other && Index == other.Index ? new MaterialTransaction(Index, other.Old, New) : null; public void Revert(IDesignEditor editor, object data) - => ((DesignManager)editor).ChangeMaterialValue((Design)data, Index, Old); + { + if (editor is DesignManager e) + e.ChangeMaterialValue((Design)data, Index, Old); + } } /// Only Designs. From f8ca572d380da3e71b761e6b955e106898109801 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 26 Dec 2025 18:21:47 +0100 Subject: [PATCH 06/10] Fix issue in unlocks tab. --- Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs b/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs index d75f2dc..2323ca2 100644 --- a/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs +++ b/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs @@ -194,7 +194,7 @@ public class UnlockTable : Table, IDisposable ImGui.Dummy(new Vector2(ImGui.GetFrameHeight())); ImGui.SameLine(); ImGui.AlignTextToFramePadding(); - if (ImGui.Selectable(item.Name)) + if (ImGui.Selectable(item.Name) && !item.Id.IsBonusItem) Glamourer.Messager.Chat.Print(new SeStringBuilder().AddItemLink(item.ItemId.Id, false).BuiltString); if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _tooltip.Player(out var state)) From 4d466fb7eb50b2466db287fc9beb6c865f5ee926 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sat, 24 Jan 2026 15:22:56 +0100 Subject: [PATCH 07/10] Fix minor issues. --- Glamourer/Designs/Design.cs | 6 +++--- Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Glamourer/Designs/Design.cs b/Glamourer/Designs/Design.cs index 848e7d6..cf7af5d 100644 --- a/Glamourer/Designs/Design.cs +++ b/Glamourer/Designs/Design.cs @@ -280,8 +280,8 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn { var name = tok["Name"]?.ToObject(); var directory = tok["Directory"]?.ToObject(); - var enabled = tok["Enabled"]?.ToObject(); - if (name == null || directory == null || enabled == null) + var enabled = tok["Enabled"]?.ToObject() ?? false; + if (name == null || directory == null) { Glamourer.Messager.NotificationMessage("The loaded design contains an invalid mod, skipped.", NotificationType.Warning); continue; @@ -295,7 +295,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn settings.Add(key, value); var priority = tok["Priority"]?.ToObject() ?? 0; if (!design.AssociatedMods.TryAdd(new Mod(name, directory), - new ModSettings(settings, priority, enabled.Value, forceInherit, removeSetting))) + new ModSettings(settings, priority, enabled, forceInherit, removeSetting))) Glamourer.Messager.NotificationMessage("The loaded design contains a mod more than once, skipped.", NotificationType.Warning); } } diff --git a/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs b/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs index 2323ca2..d2297ca 100644 --- a/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs +++ b/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs @@ -194,7 +194,7 @@ public class UnlockTable : Table, IDisposable ImGui.Dummy(new Vector2(ImGui.GetFrameHeight())); ImGui.SameLine(); ImGui.AlignTextToFramePadding(); - if (ImGui.Selectable(item.Name) && !item.Id.IsBonusItem) + if (ImGui.Selectable(item.Name) && item.Id is { IsBonusItem: false, IsCustom: false }) Glamourer.Messager.Chat.Print(new SeStringBuilder().AddItemLink(item.ItemId.Id, false).BuiltString); if (ImGui.IsItemClicked(ImGuiMouseButton.Right) && _tooltip.Player(out var state)) From 74517d8ec5dc17e3a2023782cd5d55f441797b1f Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sat, 24 Jan 2026 15:23:20 +0100 Subject: [PATCH 08/10] Add ModUsage subscription. --- .../Interop/Penumbra/ModUsageInformer.cs | 58 +++++++++++++++++++ Glamourer/Interop/Penumbra/PenumbraService.cs | 28 +++++---- Penumbra.Api | 2 +- 3 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 Glamourer/Interop/Penumbra/ModUsageInformer.cs diff --git a/Glamourer/Interop/Penumbra/ModUsageInformer.cs b/Glamourer/Interop/Penumbra/ModUsageInformer.cs new file mode 100644 index 0000000..f6d992e --- /dev/null +++ b/Glamourer/Interop/Penumbra/ModUsageInformer.cs @@ -0,0 +1,58 @@ +using Glamourer.Automation; +using Glamourer.Designs; +using OtterGui.Services; + +namespace Glamourer.Interop.Penumbra; + +public sealed class ModUsageInformer : IDisposable, IRequiredService +{ + private readonly PenumbraService _penumbra; + private readonly DesignManager _designs; + private readonly AutoDesignManager _automation; + + public ModUsageInformer(PenumbraService penumbra, DesignManager designs, AutoDesignManager automation) + { + _penumbra = penumbra; + _designs = designs; + _automation = automation; + + _penumbra.ModUsageQueried += OnModUsageQueried; + } + + private void OnModUsageQueried(string modPath, string modName, Dictionary notes) + { + var sb = new StringBuilder(); + var inUse = false; + foreach (var design in _designs.Designs) + { + if (!design.AssociatedMods.Any(p => ModMatches(modPath, modName, p.Key))) + continue; + + sb.AppendLine($"Contained in Design {design.Name}."); + if (_automation.EnabledSets.Values.Any(s => s.Designs.Any(d => d.Type is not 0 && d.Design == design))) + { + inUse = true; + break; + } + } + + if (inUse) + notes.TryAdd(Assembly.GetAssembly(typeof(ModUsageInformer))!, (true, string.Empty)); + else if (sb.Length > 0) + notes.TryAdd(Assembly.GetAssembly(typeof(ModUsageInformer))!, (false, sb.ToString())); + } + + private static bool ModMatches(string modPath, string modName, in Mod mod) + { + if (mod.DirectoryName.Equals(modPath, StringComparison.OrdinalIgnoreCase)) + return true; + + if (mod.Name.Equals(modName, StringComparison.OrdinalIgnoreCase)) + return true; + + return false; + } + + public void Dispose() + => _penumbra.ModUsageQueried -= OnModUsageQueried; +} diff --git a/Glamourer/Interop/Penumbra/PenumbraService.cs b/Glamourer/Interop/Penumbra/PenumbraService.cs index b2813cd..b43a0b5 100644 --- a/Glamourer/Interop/Penumbra/PenumbraService.cs +++ b/Glamourer/Interop/Penumbra/PenumbraService.cs @@ -44,15 +44,16 @@ public class PenumbraService : IDisposable private const int KeyManual = -6160; private const string NameManual = "Glamourer (Manually)"; - private readonly IDalamudPluginInterface _pluginInterface; - private readonly Configuration _config; - private readonly EventSubscriber _tooltipSubscriber; - private readonly EventSubscriber _clickSubscriber; - private readonly EventSubscriber _creatingCharacterBase; - private readonly EventSubscriber _createdCharacterBase; - private readonly EventSubscriber _modSettingChanged; - private readonly EventSubscriber _pcpParsed; - private readonly EventSubscriber _pcpCreated; + private readonly IDalamudPluginInterface _pluginInterface; + private readonly Configuration _config; + private readonly EventSubscriber _tooltipSubscriber; + private readonly EventSubscriber _clickSubscriber; + private readonly EventSubscriber _creatingCharacterBase; + private readonly EventSubscriber _createdCharacterBase; + private readonly EventSubscriber _modSettingChanged; + private readonly EventSubscriber _pcpParsed; + private readonly EventSubscriber _pcpCreated; + private readonly EventSubscriber> _modUsageQueried; private global::Penumbra.Api.IpcSubscribers.GetCollectionsByIdentifier? _collectionByIdentifier; private global::Penumbra.Api.IpcSubscribers.GetCollections? _collections; @@ -109,6 +110,7 @@ public class PenumbraService : IDisposable _modSettingChanged = global::Penumbra.Api.IpcSubscribers.ModSettingChanged.Subscriber(pi); _pcpCreated = global::Penumbra.Api.IpcSubscribers.CreatingPcp.Subscriber(pi); _pcpParsed = global::Penumbra.Api.IpcSubscribers.ParsingPcp.Subscriber(pi); + _modUsageQueried = global::Penumbra.Api.IpcSubscribers.ModUsageQueried.Subscriber(pi); Reattach(); } @@ -155,6 +157,12 @@ public class PenumbraService : IDisposable remove => _pcpParsed.Event -= value; } + public event Action> ModUsageQueried + { + add => _modUsageQueried.Event += value; + remove => _modUsageQueried.Event -= value; + } + public event Action? DrawSettingsSection; private void InvokeDrawSettingsSection() @@ -573,7 +581,7 @@ public class PenumbraService : IDisposable _changedItems = new global::Penumbra.Api.IpcSubscribers.GetChangedItemAdapterList(_pluginInterface).Invoke(); _checkCurrentChangedItems = new global::Penumbra.Api.IpcSubscribers.CheckCurrentChangedItemFunc(_pluginInterface).Invoke(); - _registerSettingsSection = new global::Penumbra.Api.IpcSubscribers.RegisterSettingsSection(_pluginInterface); + _registerSettingsSection = new global::Penumbra.Api.IpcSubscribers.RegisterSettingsSection(_pluginInterface); _unregisterSettingsSection = new global::Penumbra.Api.IpcSubscribers.UnregisterSettingsSection(_pluginInterface); _registerSettingsSection.Invoke(InvokeDrawSettingsSection); diff --git a/Penumbra.Api b/Penumbra.Api index 52a3216..a79ff8d 160000 --- a/Penumbra.Api +++ b/Penumbra.Api @@ -1 +1 @@ -Subproject commit 52a3216a525592205198303df2844435e382cf87 +Subproject commit a79ff8d87c5b1ac12192f18563fb4247173ff4f0 From e96134a134ce4770163375aad106ba0a2e13d24c Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Wed, 28 Jan 2026 17:58:14 +0100 Subject: [PATCH 09/10] Fix offhand changes with empty offhand. --- Glamourer/State/StateListener.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Glamourer/State/StateListener.cs b/Glamourer/State/StateListener.cs index 4b70718..16e9a70 100644 --- a/Glamourer/State/StateListener.cs +++ b/Glamourer/State/StateListener.cs @@ -9,7 +9,6 @@ using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Dalamud.Game.ClientState.Conditions; using Dalamud.Plugin.Services; -using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Glamourer.GameData; using Penumbra.GameData.DataContainers; @@ -602,14 +601,21 @@ public class StateListener : IDisposable change = UpdateState.Change; } - if (baseData.Skeleton.Id != weapon.Skeleton.Id || baseData.Weapon.Id != weapon.Weapon.Id || baseData.Variant != weapon.Variant) + var idsDiffer = baseData.Skeleton.Id != weapon.Skeleton.Id + || baseData.Weapon.Id != weapon.Weapon.Id + || baseData.Variant != weapon.Variant; + // Special case when nothing is equipped to the offhand which is already nothing, but we need to update the type. + var nothingDiffers = baseData.Skeleton.Id is 0 && slot is EquipSlot.OffHand; + + if (idsDiffer || nothingDiffers) { if (_isPlayerNpc) return UpdateState.Transformed; var item = _items.Identify(slot, weapon.Skeleton, weapon.Weapon, weapon.Variant, slot is EquipSlot.OffHand ? state.BaseData.MainhandType : FullEquipType.Unknown); - state.BaseData.SetItem(slot, item); + if (idsDiffer || item.Type != state.BaseData.OffhandType) + state.BaseData.SetItem(slot, item); change = UpdateState.Change; } From 360c8bb92a8afa0c234b3e6b06431d83402b60ac Mon Sep 17 00:00:00 2001 From: Actions User Date: Wed, 28 Jan 2026 23:06:33 +0000 Subject: [PATCH 10/10] [CI] Updating repo.json for 1.5.1.8 --- repo.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/repo.json b/repo.json index 31b4c6e..5254ecb 100644 --- a/repo.json +++ b/repo.json @@ -17,8 +17,8 @@ "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "1.5.1.7", - "TestingAssemblyVersion": "1.5.1.7", + "AssemblyVersion": "1.5.1.8", + "TestingAssemblyVersion": "1.5.1.8", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 14, @@ -27,9 +27,9 @@ "IsTestingExclusive": "False", "DownloadCount": 1, "LastUpdate": 1618608322, - "DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.7/Glamourer.zip", - "DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.7/Glamourer.zip", - "DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.7/Glamourer.zip", + "DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.8/Glamourer.zip", + "DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.8/Glamourer.zip", + "DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.8/Glamourer.zip", "IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/main/images/icon.png" } ]