fix(vtank): slice 7 fix round B item 14 — persist Extra Buff Spells / Blacklisted Buff Families, reword tooltips

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 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-07 13:46:22 +02:00
parent 169a6c6e32
commit b0fee80e6f
4 changed files with 68 additions and 2 deletions

View file

@ -1030,6 +1030,39 @@ public sealed class MossTankPanelTests
Assert.Equal(callsAfterAdd, automation.CaptureOwnedItemsCallCount);
}
[Fact]
public void ExtraBuffAndBlacklistedFamilyNamesPersistAcrossSessions()
{
// Fix round B item 14: these two Buffs-tab sets were never captured
// by LegacyBuffProfileDocument, so a restart or profile switch
// silently dropped them — a real display/storage honesty bug
// (BuffPlan.Build still doesn't READ either set for casting, a
// separately tracked wiring gap; this only fixes storage).
var storage = new MemoryStorage();
var automation = new FakeAutomation
{
Name = "Persist Check",
KnownSelfBuffs =
[
Spell(1, 10, "Increases the caster's Strength by 10 points."),
Spell(2, 20, "Increases the caster's Focus by 10 points."),
],
};
var first = new MossTankPanel(new FakeHost(automation, storage));
first.ShowExtraBuffPicker();
first.PickBuffAt(0); // "Spell 1"
first.ShowBlacklistedBuffPicker();
first.PickBuffAt(1); // "Spell 2"
Assert.Equal(["Spell 1"], first.ExtraBuffRows);
Assert.Equal(["Spell 2"], first.BlacklistedBuffFamilyRows);
var second = new MossTankPanel(new FakeHost(
new FakeAutomation { Name = "Persist Check" }, storage));
Assert.Equal(["Spell 1"], second.ExtraBuffRows);
Assert.Equal(["Spell 2"], second.BlacklistedBuffFamilyRows);
}
[Fact]
public void BuffPickerAddsToTheRequestedListAndAnyCellClickDeletes()
{