From b0fee80e6f02ce40f60fae5aa598931ffd624b66 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2026 13:46:22 +0200 Subject: [PATCH] =?UTF-8?q?fix(vtank):=20slice=207=20fix=20round=20B=20ite?= =?UTF-8?q?m=2014=20=E2=80=94=20persist=20Extra=20Buff=20Spells=20/=20Blac?= =?UTF-8?q?klisted=20Buff=20Families,=20reword=20tooltips?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ExtraBuffSpellNames/BlacklistedBuffFamilyNames (Buffs tab, Campaign VT S7.4) were never captured by SideCarDocument (the active JSON persistence alongside the real VTank .usd) — a restart or profile switch silently dropped them. BuffPlan.Build still does not READ either set when choosing what to cast — that remains a real, separately tracked wiring gap (see BuffSettings' own doc comments); this only fixes the storage/display honesty the owner asked for. - SideCarDocument gained BuffExtraSpellNames/BuffBlacklistedFamilyNames (string[]), captured via the same Sorted() helper CombatItemNames/ ConsumableNames use, and applied via the same Replace() clear-then- repopulate helper — a profile switch can't carry a stale entry over from whichever profile was loaded before. - PickBuffAtCore and DeleteExtraBuffAt/DeleteBlacklistedBuffFamilyAt now call SaveProfile(), matching every other Add/Delete mutator in this file — without this the newly-wired capture/apply would only fire opportunistically on some unrelated save. - Reworded both tab tooltips ("Named spell exemplars added beyond the school-driven picks" / "Named buff families never cast, even if otherwise wanted") to state plainly that the lists are stored and shown but not yet used for casting, instead of implying they already affect cast selection. - (False start, reverted: an earlier pass edited LegacyBuffProfileDocument, which the file's own comment marks migration-only dead code that nothing else writes any more — the real fix belongs in SideCarDocument, the active format SaveCurrent/LoadCurrent actually round-trip.) New test: ExtraBuffAndBlacklistedFamilyNamesPersistAcrossSessions (add via the picker in one panel, confirm both survive in a second panel sharing the same storage). Mutation check: commenting out the two Replace() calls in SideCarDocument.Apply turned it red ("Expected: [Spell 1], Actual: []"); restoring them turns it green. tests/AcDream.Plugins.MossTank.Tests: 675/675 (was 674/674, +1). tests/AcDream.App.Tests --filter Markup|Plugin|UiMenu|Slider: 278/3 skipped/281 (unchanged). Co-Authored-By: Claude Fable 5.1 --- src/AcDream.Plugins.MossTank/MossTankPanel.cs | 7 ++++ .../MossTankProfileStore.cs | 19 +++++++++++ src/AcDream.Plugins.MossTank/mosstank.xml | 11 +++++-- .../MossTankPanelTests.cs | 33 +++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/AcDream.Plugins.MossTank/MossTankPanel.cs b/src/AcDream.Plugins.MossTank/MossTankPanel.cs index deed0f26..11f67c76 100644 --- a/src/AcDream.Plugins.MossTank/MossTankPanel.cs +++ b/src/AcDream.Plugins.MossTank/MossTankPanel.cs @@ -1433,11 +1433,13 @@ internal sealed partial class MossTankPanel { _selectedExtraBuffRow = row; DeleteFromNamedSet(_buffSettings.ExtraBuffSpellNames, row); + SaveProfile(); }; public Action DeleteBlacklistedBuffFamilyAt => row => { _selectedBlacklistedBuffRow = row; DeleteFromNamedSet(_buffSettings.BlacklistedBuffFamilyNames, row); + SaveProfile(); }; public Action ShowExtraBuffPicker => () => ShowBuffPickerCore(forBlacklist: false); public Action ShowBlacklistedBuffPicker => () => ShowBuffPickerCore(forBlacklist: true); @@ -1900,6 +1902,11 @@ internal sealed partial class MossTankPanel else _buffSettings.ExtraBuffSpellNames.Add(name); _buffPickerVisible = false; + // Fix round B item 14: these two sets are now captured/applied by + // LegacyBuffProfileDocument — an explicit save is needed here (same + // as every other Add/Delete mutator in this file) for a pick to + // actually survive past this session. + SaveProfile(); } private static int ClampRow(int index, int count) => count == 0 diff --git a/src/AcDream.Plugins.MossTank/MossTankProfileStore.cs b/src/AcDream.Plugins.MossTank/MossTankProfileStore.cs index 9de10c84..9adb3051 100644 --- a/src/AcDream.Plugins.MossTank/MossTankProfileStore.cs +++ b/src/AcDream.Plugins.MossTank/MossTankProfileStore.cs @@ -762,6 +762,17 @@ internal sealed class MossTankProfileStore public bool BuffRegeneration { get; set; } = true; public bool BuffOther { get; set; } public bool BuffTrainedSkillsOnly { get; set; } = true; + // Fix round B item 14: these two Buffs-tab sets (Campaign VT S7.4) + // had no VTank Settings-table row of their own (VTank's + // ExtraBuffSpells/AntiExtraBuffSpells are separate tables, not + // scalar Settings rows) and were never captured by this side-car + // either — a restart or profile switch silently dropped them. + // BuffPlan.Build still does not READ either set when choosing what + // to cast (a real, separately tracked wiring gap — see + // BuffSettings' own doc comments); this only fixes the storage/ + // display honesty. + public string[] BuffExtraSpellNames { get; set; } = []; + public string[] BuffBlacklistedFamilyNames { get; set; } = []; public bool VitalsEnabled { get; set; } = true; public double InventoryScanIntervalSeconds { get; set; } = 0.25d; // InventoryEnableLooting was deleted here (round 3, item 1): it @@ -802,6 +813,8 @@ internal sealed class MossTankProfileStore BuffRegeneration = settings.Buffs.BuffRegeneration, BuffOther = settings.Buffs.BuffOther, BuffTrainedSkillsOnly = settings.Buffs.BuffTrainedSkillsOnly, + BuffExtraSpellNames = Sorted(settings.Buffs.ExtraBuffSpellNames), + BuffBlacklistedFamilyNames = Sorted(settings.Buffs.BlacklistedBuffFamilyNames), VitalsEnabled = settings.Vitals.Enabled, InventoryScanIntervalSeconds = settings.Inventory.ScanIntervalSeconds, InventoryLootClassifierId = settings.Inventory.Loot.ExternalClassifierId, @@ -870,6 +883,12 @@ internal sealed class MossTankProfileStore settings.Buffs.BuffRegeneration = BuffRegeneration; settings.Buffs.BuffOther = BuffOther; settings.Buffs.BuffTrainedSkillsOnly = BuffTrainedSkillsOnly; + // Fix round B item 14: clear-then-repopulate (Replace, same + // helper CombatItemNames/ConsumableNames/NoBuffItemNames use) — + // a profile switch must not carry a stale entry over from + // whichever profile was loaded before. + Replace(settings.Buffs.ExtraBuffSpellNames, BuffExtraSpellNames); + Replace(settings.Buffs.BlacklistedBuffFamilyNames, BuffBlacklistedFamilyNames); settings.Vitals.Enabled = VitalsEnabled; diff --git a/src/AcDream.Plugins.MossTank/mosstank.xml b/src/AcDream.Plugins.MossTank/mosstank.xml index 5df884aa..431d5051 100644 --- a/src/AcDream.Plugins.MossTank/mosstank.xml +++ b/src/AcDream.Plugins.MossTank/mosstank.xml @@ -508,15 +508,22 @@ compromise fitting a real 184x194 box, not a pixel-for-pixel VVS port (owner's bar: "looks basically the same", never VVS pixels). --> +