merge(vt): slice 7 round G — Buffs tab is VTank's six controls; no tooltips in Advanced Options (owner's third look)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> # Conflicts: # docs/plans/2026-09-07-campaign-vt-slice7-tabs.md
This commit is contained in:
commit
43582efc4e
7 changed files with 144 additions and 271 deletions
|
|
@ -154,3 +154,4 @@ re-review, merge to the campaign branch, then the owner's visual gate.
|
|||
## Closeout
|
||||
- 2026-09-07 21:10 final combined re-check (E+F, both lenses): all twelve items CLOSED with failable tests, no per-frame allocation regression, the three recall tables agree pairwise, plugin references BCL + Abstractions only — MERGE-READY. **Merged into the campaign branch at `4a825c23c`.** Owner's second-look items all closed (Advanced Options bottom block gone; string settings hidden; Items tab VTank-only). Accepted, documented deviations: the Buffs extras strip centres at the 856 floor only (anchors have no "centre"); the recall combo lists "Marketplace" in place of VTank's duplicated "Fac. Hub"; dead margins on six tabs at the 984 default. Carried polish (owner: "we do that later"): strip the retired `scroll="true"` from five markup sites and make its test failable or document that unknown attributes are ignored; delete the ~20 bindings round F orphaned; cache the two Buffs row sources like every other column; two comment corrections; Meta's delete cell as an icon. Open issues from this slice: #490 part 1 (host: `StartVisible=false` + `ShowInSidePanel=false` unshowable), #491 (buff lists not consumed by `BuffPlan.Build`), #492 (Vulkan device-loss crash + shutdown re-throw), #493 (in-game meta/loot rule editors, deferred). Owner's visual gate: the merged build launched from the gate worktree for the final look.
|
||||
- 2026-09-07 21:30 OWNER THIRD LIVE LOOK at the merged build (`4a825c23c`): (1) the Buffs tab's middle block (seven category toggles, difficulty/rebuff spinners, Stop/Force buffing + status, the counts line) is "made up — remove them from here": VTank's Buffs tab is exactly two lists + two Add… buttons; the real settings behind two of them (`SpellDiffExcessThreshold-Buff`, `RebuffTimeRemainingSeconds`) stay editable in Advanced Options, Force Buff stays on Options; the MossTank-only category bools stay in the model only. (2) Advanced Options still shows tooltips — remove them (VTank's popup has none; the description box is the info channel). Round G dispatched on a fresh worktree off `a2df6efae`; merge + relaunch follow.
|
||||
- 2026-09-07 owner's third live look, post-closeout: (1) "Screenshot shows options under the buffing tab circled in red. Those are made up, remove them from here" — the whole MossTank-extras middle strip fix round B item 2 added between the Buffs tab's two lists (7 category toggles, difficulty/rebuff spinners, a second Force/Stop buffing button + status, the coverage counts) is gone outright; the Buffs tab is now VTank's own exact six controls (2 labels, 2 lists, 2 "Add..." buttons), matching the Items-tab precedent from round F item 3. The underlying BuffSettings fields (seven category bools, SkillExcessOverDifficulty, RebuffWhenUnderSeconds) stay in the model/side-car and remain editable through Advanced Options (SpellDiffExcessThreshold-Buff / RebuffTimeRemainingSeconds); Force Buff / Cancel Force Buff stay on the Options tab. Twenty-two now-orphaned XML-only bindings deleted from MossTankPanel.cs (the seven Enabled/Toggle pairs, DifficultyText/Up/Down, RebuffText/Up/Down, BuffButtonText, the Buff action) — this is the "delete the ~20 bindings round F orphaned" carried-polish item from the closeout, done as part of this fix rather than separately; BuffStatus/Coverage stay since MossTankPanelTests still exercises both directly. Commit `6be555ad4`. (2) "Also still have tooltips in the advanced options, remove please" — the three tooltip= attributes mosstank-advanced.xml had grown (option list, category checklist, value field) are removed; VTank's real AdvancedOptionsView has no tooltip mechanism, only its own description readout. New whole-tree test AdvancedOptionsPopupHasNoElementWithATooltip guards against any future re-addition. Commit `617a9c221`. Both fixes' new/changed tests shown to fail first against targeted mutations (a stray toggle re-added to the Buffs group; a tooltip= reintroduced on the option list), then reverted and restored green. MossTank suite 726 -> 726 (one Fact replaced); App markup/plugin filter 262 -> 261 (item 1, one Fact removed) -> 262 (item 2, one Fact added). Full solution Release build green throughout.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,11 @@ public sealed class BuffSettings
|
|||
/// <summary>
|
||||
/// How far the casting skill must exceed a spell's difficulty before the
|
||||
/// tier is considered reliable — VTank's
|
||||
/// <c>SpellDiffExcessThreshold-Buff</c>.
|
||||
/// <c>SpellDiffExcessThreshold-Buff</c>, editable through Advanced
|
||||
/// Options (VtankOptionCatalog). Signed on purpose — the wiki is
|
||||
/// explicit that "a positive number raises the skill necessary to cast
|
||||
/// spells, a negative number lowers it", so a lower-level character can
|
||||
/// reach for higher tiers by going negative.
|
||||
/// </summary>
|
||||
public int SkillExcessOverDifficulty { get; set; } = 5;
|
||||
|
||||
|
|
|
|||
|
|
@ -426,7 +426,11 @@ internal sealed partial class MossTankPanel
|
|||
}
|
||||
|
||||
// ── main panel bindings ───────────────────────────────────────────────
|
||||
public Action Buff => StartOrStop;
|
||||
// Campaign VT slice 7 — owner's third live look (2026-09-07): the
|
||||
// Buffs tab's own "{Buff}"/"{BuffButtonText}" button (a redundant
|
||||
// second Force/Stop control with no VTank counterpart) was deleted
|
||||
// from mosstank.xml; StartOrStop itself stays, still reachable from
|
||||
// the `/mt buff` slash command (MossTankCommands.cs).
|
||||
public Action ForceBuff => StartForceBuff;
|
||||
public Action CancelForceBuff => CancelForceBuffCore;
|
||||
public Action ToggleCombat => ToggleMacro;
|
||||
|
|
@ -695,8 +699,13 @@ internal sealed partial class MossTankPanel
|
|||
ApplyAdvancedOptionCore();
|
||||
};
|
||||
|
||||
/// <summary>The button is Force Buff; while a pass runs it cancels.</summary>
|
||||
public string BuffButtonText => _running ? "Stop buffing" : "Force buff";
|
||||
/// <summary>
|
||||
/// The force-buff status. No longer read by any Buffs-tab control
|
||||
/// (owner's third live look, 2026-09-07 — the Buffs tab's own
|
||||
/// "{BuffStatus}" label had no VTank counterpart and is gone), but the
|
||||
/// underlying <c>_status</c> state stays real and is exercised directly
|
||||
/// by <c>MossTankPanelTests</c>.
|
||||
/// </summary>
|
||||
public string BuffStatus => _status;
|
||||
public string CombatButtonText => _combat.ButtonText;
|
||||
/// <summary>
|
||||
|
|
@ -1578,7 +1587,13 @@ internal sealed partial class MossTankPanel
|
|||
/// <summary>Vitals line, using the same numbers the character panel shows.</summary>
|
||||
public string Vitals => _vitals;
|
||||
|
||||
/// <summary>What a buff pass would cover, named from the retail tables.</summary>
|
||||
/// <summary>
|
||||
/// What a buff pass would cover, named from the retail tables. No
|
||||
/// longer read by any Buffs-tab control (owner's third live look,
|
||||
/// 2026-09-07 — the count had no VTank counterpart and is gone), but
|
||||
/// still exercised directly by <c>MossTankPanelTests</c>' allocation
|
||||
/// and throttle pins.
|
||||
/// </summary>
|
||||
public string Coverage => _coverage;
|
||||
|
||||
// ── settings bindings ─────────────────────────────────────────────────
|
||||
|
|
@ -1586,18 +1601,6 @@ internal sealed partial class MossTankPanel
|
|||
// in plugin markup, whereas an editable field would need keyboard routing
|
||||
// plumbed through to plugin panels first.
|
||||
|
||||
/// <summary>
|
||||
/// VTank's <c>SpellDiffExcessThreshold-Buff</c>. Signed on purpose — the
|
||||
/// wiki is explicit that "a positive number raises the skill necessary to
|
||||
/// cast spells, a negative number lowers it", so a lower-level character
|
||||
/// can reach for higher tiers by going negative.
|
||||
/// </summary>
|
||||
public string DifficultyText =>
|
||||
$"Spell difficulty margin: {_buffSettings.SkillExcessOverDifficulty:+0;-0;0}";
|
||||
|
||||
public string RebuffText =>
|
||||
$"Rebuff when under: {_buffSettings.RebuffWhenUnderSeconds / 60.0:0.#} min";
|
||||
|
||||
public string NormalHealthText => Percent(_vitalSettings.NormalHealth);
|
||||
public string NormalStaminaText => Percent(_vitalSettings.NormalStamina);
|
||||
public string NormalManaText => Percent(_vitalSettings.NormalMana);
|
||||
|
|
@ -1626,13 +1629,6 @@ internal sealed partial class MossTankPanel
|
|||
|
||||
public bool VitalUpkeepEnabled => _vitalSettings.Enabled;
|
||||
public bool HelpOthersEnabled => _vitalSettings.HelpOthers;
|
||||
public bool TrainedOnlyEnabled => _buffSettings.BuffTrainedSkillsOnly;
|
||||
public bool AttributesEnabled => _buffSettings.BuffAttributes;
|
||||
public bool ProtectionsEnabled => _buffSettings.BuffProtections;
|
||||
public bool AurasEnabled => _buffSettings.BuffAuras;
|
||||
public bool BanesEnabled => _buffSettings.BuffBanes;
|
||||
public bool RegenerationEnabled => _buffSettings.BuffRegeneration;
|
||||
public bool OtherEnabled => _buffSettings.BuffOther;
|
||||
|
||||
// ── Buffs tab Extra/Blacklisted lists + picker (Campaign VT S7.4:
|
||||
// VTank's own lstBuffSpells/lstAntiBuffSpells, docs/research/vtank-kb/
|
||||
|
|
@ -1774,20 +1770,6 @@ internal sealed partial class MossTankPanel
|
|||
public Action<float> SetHelperStaminaPercent => value => SetHelperStamina(value / 100f);
|
||||
public Action<float> SetHelperManaPercent => value => SetHelperMana(value / 100f);
|
||||
|
||||
public Action DifficultyDown => () => UpdateProfile(() =>
|
||||
_buffSettings.SkillExcessOverDifficulty =
|
||||
Math.Max(-100, _buffSettings.SkillExcessOverDifficulty - 5));
|
||||
public Action DifficultyUp => () => UpdateProfile(() =>
|
||||
_buffSettings.SkillExcessOverDifficulty =
|
||||
Math.Min(100, _buffSettings.SkillExcessOverDifficulty + 5));
|
||||
|
||||
public Action RebuffDown => () => UpdateProfile(() =>
|
||||
_buffSettings.RebuffWhenUnderSeconds =
|
||||
Math.Max(30, _buffSettings.RebuffWhenUnderSeconds - 30));
|
||||
public Action RebuffUp => () => UpdateProfile(() =>
|
||||
_buffSettings.RebuffWhenUnderSeconds =
|
||||
Math.Min(1800, _buffSettings.RebuffWhenUnderSeconds + 30));
|
||||
|
||||
public Action ToggleVitalUpkeep => () =>
|
||||
{
|
||||
_vitalSettings.Enabled = !_vitalSettings.Enabled;
|
||||
|
|
@ -1809,20 +1791,6 @@ internal sealed partial class MossTankPanel
|
|||
ExpressionValue.Boolean(!_inventorySettings.ManaChargesWhenOff));
|
||||
public Action ToggleHelpOthers => () => UpdateVital(() =>
|
||||
_vitalSettings.HelpOthers = !_vitalSettings.HelpOthers);
|
||||
public Action ToggleTrainedOnly => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffTrainedSkillsOnly = !_buffSettings.BuffTrainedSkillsOnly);
|
||||
public Action ToggleAttributes => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffAttributes = !_buffSettings.BuffAttributes);
|
||||
public Action ToggleProtections => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffProtections = !_buffSettings.BuffProtections);
|
||||
public Action ToggleAuras => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffAuras = !_buffSettings.BuffAuras);
|
||||
public Action ToggleBanes => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffBanes = !_buffSettings.BuffBanes);
|
||||
public Action ToggleRegeneration => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffRegeneration = !_buffSettings.BuffRegeneration);
|
||||
public Action ToggleOther => () => UpdateProfile(() =>
|
||||
_buffSettings.BuffOther = !_buffSettings.BuffOther);
|
||||
public Action CycleTargetMethod => () => UpdateProfile(() =>
|
||||
_combatSettings.SelectionMethod = _combatSettings.SelectionMethod switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,12 +167,19 @@
|
|||
AddRouteCheckpoint/AddRouteJump themselves) — nothing was deleted from
|
||||
the plugin, only the second, redundant UI surface for it. Panel height
|
||||
shrinks 450->300 to match VTank's real 392x300 AdvancedOptionsView
|
||||
footprint (minh follows); minw stays 392. -->
|
||||
footprint (minh follows); minw stays 392.
|
||||
|
||||
Owner's third live look (2026-09-07): "Also still have tooltips in the
|
||||
advanced options, remove please." VTank's own AdvancedOptionsView has no
|
||||
tooltip mechanism at all — its own description readout
|
||||
(AdvancedOptionDescription, the label at the bottom) is the retail
|
||||
in-popup info channel, not a hover tooltip. The three tooltip= attributes
|
||||
this popup had grown (the option list, the category checklist, the value
|
||||
field) are removed; nothing else in this file ever set one. -->
|
||||
<panel x="253" y="405" w="392" h="300" title="MossTank Advanced Options"
|
||||
visible="{AdvancedOptionsVisible}" resizable="true" minw="392" minh="300">
|
||||
<list x="4" y="4" w="256" h="160" rowheight="17" anchor="left top right"
|
||||
selected="{SelectedAdvancedOptionIndex}" onchange="{SelectAdvancedOption}"
|
||||
tooltip="Select one of Virindi Tank's 137 advanced options.">
|
||||
selected="{SelectedAdvancedOptionIndex}" onchange="{SelectAdvancedOption}">
|
||||
<column type="text" width="187" items="{AdvancedOptionNames}" onclick="{SelectAdvancedOption}" />
|
||||
<column type="text" width="69" items="{AdvancedOptionValueColumn}" onclick="{ClickAdvancedOptionValue}" />
|
||||
</list>
|
||||
|
|
@ -181,15 +188,13 @@
|
|||
pure checklist with no real selection concept — see
|
||||
SelectedAdvancedOptionCategoryIndex's own doc comment. -->
|
||||
<list x="268" y="4" w="120" h="180" rowheight="18" anchor="right"
|
||||
selected="{SelectedAdvancedOptionCategoryIndex}"
|
||||
tooltip="Uncheck a category to hide its settings from the list on the left.">
|
||||
selected="{SelectedAdvancedOptionCategoryIndex}">
|
||||
<column type="check" width="20" values="{AdvancedOptionCategoryEnabled}" onchange="{ToggleAdvancedOptionCategoryAt}" />
|
||||
<column type="text" width="*" items="{AdvancedOptionCategoryNames}" onclick="{ToggleAdvancedOptionCategoryAt}" />
|
||||
</list>
|
||||
<field x="4" y="168" w="260" h="16" text="{AdvancedOptionValueDraft}"
|
||||
onchange="{SetAdvancedOptionValueDraft}" onsubmit="{SubmitAdvancedOption}"
|
||||
maxlength="160" clearonsubmit="false" background="#E6000000"
|
||||
tooltip="Edit the selected advanced-option value and press Enter to apply." />
|
||||
maxlength="160" clearonsubmit="false" background="#E6000000" />
|
||||
<label x="4" y="188" w="384" h="80" text="{AdvancedOptionDescription}" color="#FFE8DEC3"
|
||||
anchor="left top right" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -566,58 +566,37 @@
|
|||
|
||||
<!-- Buffs: VTank's REAL Buffs tab (docs/research/vtank-kb/08-ui-views.md
|
||||
§1 "Tab: Buffs") is ONLY two lists + two "Add..." buttons — Extra Buff
|
||||
Spells and Blacklisted Buff Families, each VTank's own 320x116, at the
|
||||
far left and far right of the 848-wide canvas (PluginCore.cs:
|
||||
Spells and Blacklisted Buff Families, each VTank's own 320x116 (grown
|
||||
+35 tall per Round D item 4's own font-driven scaling, matching every
|
||||
other tab), at the far left and far right of the panel (PluginCore.cs:
|
||||
7323-7355 — any cell click removes that row; "Add..." opens the
|
||||
shared SelfBuffChoiceView-style picker, mosstank-buffpicker.xml).
|
||||
|
||||
Fix round B item 2 (owner's silhouette rule: VTank's own controls are
|
||||
never shrunk/moved/reordered to make room for MossTank extras): the
|
||||
category toggles / difficulty / rebuff / Buff-cast-now block below
|
||||
(MossTank's own pre-existing extension, no VTank Buffs-tab
|
||||
counterpart) used to live in the same two columns as the narrowed
|
||||
lists, and its Difficulty "+" button (338,108) overlapped the Extra
|
||||
Buff Spells "Add..." button (336,102) — a real sibling-overlap bug
|
||||
the new AuthoredControlsInTheSameGroupNeverOverlap pin below now
|
||||
catches. Both lists are restored to VTank's full 320x116 at the far
|
||||
left (x=4) and far right (x=524, 848-4-320) with their own
|
||||
120-wide "Add..." row below each list; the whole MossTank-extras
|
||||
block moves into the EMPTY MIDDLE strip between the two lists,
|
||||
stacked compactly: 7 toggles at a 16px pitch, then Difficulty +/-,
|
||||
then Rebuff +/-, then the Buff button + status, then Coverage
|
||||
right under it — a proportion-preserving compromise fitting a
|
||||
real box, not a pixel-for-pixel VVS port (owner's bar: "looks
|
||||
basically the same", never VVS pixels).
|
||||
|
||||
Round F item 6 (resemblance re-check: "Buffs' 136 px middle gap
|
||||
and the orphaned Coverage label"). Coverage moved from y=213
|
||||
(anchored to the group's bottom edge, a real 55px empty hole
|
||||
above it once the panel grew past its original 194-tall size) to
|
||||
sit directly under the Buff button row instead — no anchor, since
|
||||
nothing below it needs the space that anchor used to protect.
|
||||
|
||||
The middle-gap half of this item turned out to have a hard
|
||||
geometric ceiling: Extra Buff Spells never moves (anchor="left
|
||||
top bottom", pinned at x=4..324) but Blacklisted Buff Families
|
||||
tracks the growing right edge (anchor="right"), sitting at
|
||||
x=524 at the panel's own tested floor (856x236, PanelIsResizable
|
||||
FlooredAtThePreRoundDAuthoredSize) and x=652 at the 984-wide
|
||||
enlarged default — a 128px swing. The extras strip (182px wide)
|
||||
is a single FIXED position, so it can only be centered relative
|
||||
to ONE of those two widths; centering it against the 984 default
|
||||
(x=397) put its right edge at 579, 55px INSIDE where the same
|
||||
list sits at the floor (524) — a real overlap
|
||||
ResolvedMainPanelHasNoOverlapOrOutOfBoundsChildAtThisSize's own
|
||||
856x236 case catches. x=333 is the strip's floor-centered
|
||||
position (9px margin on both sides against the floor's 324..524
|
||||
gap, the widest safe position a fixed strip can take) — the same
|
||||
position fix round B item 2 effectively already used (x=332, 1px
|
||||
off from exactly centered) before Round D's enlargement existed.
|
||||
The residual asymmetric gap at the 984 default (previously ~8/138,
|
||||
now ~9/137) is therefore an accepted, unavoidable-without-a-
|
||||
redesign limitation — the same "dead margin, polish later" trade
|
||||
the resemblance re-check already accepted for six other tabs at
|
||||
this same enlarged size. -->
|
||||
Owner's third live look (2026-09-07): "Screenshot shows options under
|
||||
the buffing tab circled in red. Those are made up, remove them from
|
||||
here." The MossTank-only extras block that used to sit in the empty
|
||||
middle strip between the two lists (7 category toggles, the
|
||||
difficulty-margin and rebuff-under spinners, the Force/Stop buffing
|
||||
button + status, and the "N attributes, N trained skills, N buff
|
||||
lines" coverage counts — added by fix round B item 2, then repolished
|
||||
by round F item 6) is gone outright: VTank's real Buffs tab has no
|
||||
such block, and this campaign's own silhouette rule (fix round B item
|
||||
2's own reasoning) cuts both ways — a VTank-authentic tab gets no
|
||||
MossTank-only middle strip either. The underlying settings are not
|
||||
lost: BuffSettings' seven category bools, SkillExcessOverDifficulty
|
||||
and RebuffWhenUnderSeconds all stay in the model and its JSON
|
||||
side-car, and the same two numbers are real, already-editable
|
||||
VtankOptionCatalog entries (SpellDiffExcessThreshold-Buff,
|
||||
RebuffTimeRemainingSeconds) reachable from Advanced Options. Force
|
||||
Buff / Cancel Force Buff stay right where VTank has them, on the
|
||||
Options tab (ForceBuff/CancelForceBuff, unchanged by this edit). The
|
||||
XML-only bindings that fed the removed controls (the seven
|
||||
*Enabled/Toggle* pairs, DifficultyText/Up/Down, RebuffText/Up/Down,
|
||||
BuffButtonText, and the Buff action — StartOrStop itself stays, still
|
||||
reachable from the `/mt buff` slash command) are deleted from
|
||||
MossTankPanel.cs as orphans; BuffStatus and Coverage stay (both are
|
||||
still exercised directly by MossTankPanelTests, independent of any
|
||||
control reading them). -->
|
||||
<group x="8" y="42" w="976" h="229" visible="{BuffsVisible}" anchor="left top right bottom">
|
||||
<!-- Fix round B item 14 (owner honesty rule): BuffPlan.Build does not
|
||||
read this set at all yet — a real, tracked wiring gap (see
|
||||
|
|
@ -644,40 +623,6 @@
|
|||
items="{BlacklistedBuffFamilyRows}" selected="{SelectedBlacklistedBuffIndex}"
|
||||
onchange="{DeleteBlacklistedBuffFamilyAt}" tooltip="Click a row to remove it." />
|
||||
<button x="652" y="173" w="120" h="18" text="Add..." onclick="{ShowBlacklistedBuffPicker}" anchor="right bottom" />
|
||||
|
||||
<toggle x="333" y="0" w="180" h="16" text="Trained skills only"
|
||||
checked="{TrainedOnlyEnabled}" onclick="{ToggleTrainedOnly}" />
|
||||
<toggle x="333" y="16" w="180" h="16" text="Attributes"
|
||||
checked="{AttributesEnabled}" onclick="{ToggleAttributes}" />
|
||||
<toggle x="333" y="32" w="180" h="16" text="Protections"
|
||||
checked="{ProtectionsEnabled}" onclick="{ToggleProtections}" />
|
||||
<toggle x="333" y="48" w="180" h="16" text="Weapon auras"
|
||||
checked="{AurasEnabled}" onclick="{ToggleAuras}" />
|
||||
<toggle x="333" y="64" w="180" h="16" text="Armor banes"
|
||||
checked="{BanesEnabled}" onclick="{ToggleBanes}" />
|
||||
<toggle x="333" y="80" w="180" h="16" text="Regeneration"
|
||||
checked="{RegenerationEnabled}" onclick="{ToggleRegeneration}" />
|
||||
<toggle x="333" y="96" w="180" h="16" text="Other self-spells"
|
||||
checked="{OtherEnabled}" onclick="{ToggleOther}" />
|
||||
|
||||
<label x="333" y="116" w="140" text="{DifficultyText}" color="#FFE8DEC3" />
|
||||
<button x="473" y="112" w="20" h="18" text="-" onclick="{DifficultyDown}"
|
||||
tooltip="Decrease the skill-over-difficulty margin." />
|
||||
<button x="495" y="112" w="20" h="18" text="+" onclick="{DifficultyUp}"
|
||||
tooltip="Increase the skill-over-difficulty margin." />
|
||||
<label x="333" y="136" w="140" text="{RebuffText}" color="#FFE8DEC3" />
|
||||
<button x="473" y="132" w="20" h="18" text="-" onclick="{RebuffDown}"
|
||||
tooltip="Rebuff later." />
|
||||
<button x="495" y="132" w="20" h="18" text="+" onclick="{RebuffUp}"
|
||||
tooltip="Rebuff earlier." />
|
||||
|
||||
<button x="333" y="154" w="110" h="18" text="{BuffButtonText}" onclick="{Buff}" />
|
||||
<label x="447" y="158" w="70" text="{BuffStatus}" color="#FFC7B98F" />
|
||||
<!-- Round F item 6: sits right under the button row above (154+18=172,
|
||||
+4px) instead of anchored to the group's bottom edge — the
|
||||
anchor used to leave a growing empty hole (55px at the enlarged
|
||||
984-wide default) between this label and the row it belongs to. -->
|
||||
<label x="333" y="176" w="184" h="16" text="{Coverage}" color="#FF9B9072" />
|
||||
</group>
|
||||
|
||||
<!-- Route: VTank's own 2-across button grid, row order, and bottom
|
||||
|
|
|
|||
|
|
@ -184,6 +184,43 @@ public sealed class MossTankMarkupBuildOverRealFilesTests
|
|||
+ $"the repositioned category list (left edge {categoryList.Left}).");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Owner's third live look (2026-09-07): "Also still have tooltips in
|
||||
/// the advanced options, remove please." VTank's own AdvancedOptionsView
|
||||
/// has no tooltip mechanism at all — its description readout is the
|
||||
/// retail in-popup info channel, not a hover tooltip. Builds the real
|
||||
/// mosstank-advanced.xml against a real panel (the same shape every
|
||||
/// other test in this file uses) and walks the WHOLE resolved tree —
|
||||
/// not just the three elements that used to carry tooltip= — so a
|
||||
/// tooltip added anywhere else in this popup in the future fails this
|
||||
/// pin too. <see cref="MarkupDocument.Build"/> only ever sets
|
||||
/// <see cref="UiElement.RuntimeTooltipTextSource"/> when the source
|
||||
/// element declared a real tooltip= attribute (MarkupDocument.cs's own
|
||||
/// ApplyCommonAttributes), so a null source function here means no
|
||||
/// tooltip was ever bound for that element.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void AdvancedOptionsPopupHasNoElementWithATooltip()
|
||||
{
|
||||
string xml = File.ReadAllText(
|
||||
Path.Combine(MossTankMarkupDirectory, "mosstank-advanced.xml"));
|
||||
var panel = new MossTankPanel(new StubHost());
|
||||
|
||||
UiNineSlicePanel built = MarkupDocument.Build(xml, panel, static id => (id, 32, 32));
|
||||
|
||||
AssertNoElementHasATooltip(built);
|
||||
}
|
||||
|
||||
private static void AssertNoElementHasATooltip(UiElement element)
|
||||
{
|
||||
Assert.True(
|
||||
element.RuntimeTooltipTextSource is null,
|
||||
$"{element.GetType().Name} carries a tooltip — the Advanced "
|
||||
+ "Options popup must have none (owner's third live look).");
|
||||
foreach (UiElement child in element.Children)
|
||||
AssertNoElementHasATooltip(child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// D-6 (round E architecture re-check): every real-file re-layout pin
|
||||
/// so far only inspects ONE named element after a resize (the
|
||||
|
|
@ -254,73 +291,17 @@ public sealed class MossTankMarkupBuildOverRealFilesTests
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Round F item 6 (resemblance re-check: "Buffs' 136 px middle gap").
|
||||
/// <see cref="ResolvedMainPanelHasNoOverlapOrOutOfBoundsChildAtThisSize"/>
|
||||
/// already proves the extras strip never overlaps the Blacklisted
|
||||
/// Buff Families list at the floor or the enlarged size (that generic
|
||||
/// sibling-overlap pass is exactly what caught the original x=397
|
||||
/// attempt at true 984-default centering colliding with the list's
|
||||
/// own floor position, x=524). This is the narrower, POSITIVE claim
|
||||
/// that overlap pass alone doesn't make: the strip is actually
|
||||
/// CENTERED at the panel's floor (856x236) — the one width at which
|
||||
/// centering and non-overlap can both hold, since Extra Buff Spells
|
||||
/// never moves but Blacklisted Buff Families tracks the growing
|
||||
/// right edge.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BuffsExtrasStripStaysCenteredAndNonOverlappingAtTheFloor()
|
||||
{
|
||||
string xml = File.ReadAllText(
|
||||
Path.Combine(MossTankMarkupDirectory, "mosstank.xml"));
|
||||
var panel = new MossTankPanel(new StubHost());
|
||||
|
||||
UiNineSlicePanel built = MarkupDocument.Build(xml, panel, static id => (id, 32, 32));
|
||||
|
||||
UiPanel[] tabGroups = built.Children
|
||||
.Where(static child => child.GetType() == typeof(UiPanel))
|
||||
.Cast<UiPanel>()
|
||||
.ToArray();
|
||||
Assert.Equal(9, tabGroups.Length);
|
||||
foreach (UiPanel group in tabGroups)
|
||||
group.Visible = false;
|
||||
UiPanel buffsGroup = tabGroups[6];
|
||||
buffsGroup.Visible = true;
|
||||
|
||||
var device = new RecordingGpuDevice();
|
||||
var renderer = new TextRenderer(device, new NullGpuFrameSource(), "unused");
|
||||
renderer.Begin(new Vector2(1400f, 900f));
|
||||
var ctx = new UiRenderContext(renderer, new Vector2(1400f, 900f));
|
||||
|
||||
// First draw at the authored default captures anchor baselines;
|
||||
// only then resize down to the panel's own tested floor.
|
||||
built.DrawSelfAndChildren(ctx);
|
||||
built.Width = 856f;
|
||||
built.Height = 236f;
|
||||
built.DrawSelfAndChildren(ctx);
|
||||
|
||||
UiMarkupList[] lists = buffsGroup.Children.OfType<UiMarkupList>().ToArray();
|
||||
Assert.Equal(2, lists.Length);
|
||||
UiMarkupList leftList = lists.Single(static l => l.Left < 300f);
|
||||
UiMarkupList rightList = lists.Single(static l => l.Left >= 300f);
|
||||
|
||||
UiMarkupToggle trainedToggle = Assert.Single(
|
||||
buffsGroup.Children.OfType<UiMarkupToggle>(), static t => t.Text == "Trained skills only");
|
||||
UiSimpleButton rebuffUpButton = Assert.Single(
|
||||
buffsGroup.Children.OfType<UiSimpleButton>(), static b => b.Text == "+" && b.Top > 120f);
|
||||
|
||||
float leftMargin = trainedToggle.Left - (leftList.Left + leftList.Width);
|
||||
float rightMargin = rightList.Left - (rebuffUpButton.Left + rebuffUpButton.Width);
|
||||
Assert.True(
|
||||
rightMargin >= 0f,
|
||||
$"Extras strip (right edge {rebuffUpButton.Left + rebuffUpButton.Width}) "
|
||||
+ $"overlaps the right list (left edge {rightList.Left}) at the floor.");
|
||||
Assert.True(
|
||||
MathF.Abs(leftMargin - rightMargin) <= 4f,
|
||||
$"Extras strip not centered at the floor: left margin "
|
||||
+ $"{leftMargin}px, right margin {rightMargin}px.");
|
||||
}
|
||||
|
||||
// Owner's third live look (2026-09-07) deleted the MossTank-only extras
|
||||
// strip that used to sit between the Buffs tab's two lists (7 category
|
||||
// toggles, the difficulty/rebuff spinners, the Force/Stop buffing
|
||||
// button + status, the coverage counts) outright — VTank's real Buffs
|
||||
// tab has no such block (see MossTankMarkupContractTests'
|
||||
// BuffsTabIsVtankOnlySixControls for the authored-tree pin). The
|
||||
// former BuffsExtrasStripStaysCenteredAndNonOverlappingAtTheFloor test
|
||||
// that proved the (now-deleted) strip stayed centered at the panel's
|
||||
// floor is gone with it; the two remaining lists' own non-overlap/
|
||||
// within-bounds behavior at both the floor and the enlarged size stays
|
||||
// covered generically by ResolvedMainPanelHasNoOverlapOrOutOfBoundsChildAtThisSize.
|
||||
private static void AssertResolvedWithinParent(UiElement parent)
|
||||
{
|
||||
foreach (UiElement child in parent.Children)
|
||||
|
|
|
|||
|
|
@ -302,32 +302,21 @@ public sealed class MossTankMarkupContractTests
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Round F item 6 (resemblance re-check nits: "Buffs' 136 px middle
|
||||
/// gap and the orphaned Coverage label"). Coverage sits right under
|
||||
/// the Buff button row instead of anchored to the group's bottom
|
||||
/// edge, which used to leave a 55px empty hole above it as the panel
|
||||
/// grew.
|
||||
///
|
||||
/// The middle-gap half has a hard geometric ceiling documented at
|
||||
/// mosstank.xml's own Buffs comment: Extra Buff Spells never moves
|
||||
/// (x=4..324) but Blacklisted Buff Families tracks the growing right
|
||||
/// edge (anchor="right"), sitting at x=524 at the panel's own tested
|
||||
/// FLOOR (856x236) and x=652 (its authored declaration below) at the
|
||||
/// 984-wide enlarged default — a 128px swing this campaign's own
|
||||
/// Round D item 4 introduced. A single FIXED-position strip can only
|
||||
/// be centered relative to ONE of those two widths; centering
|
||||
/// against the 984 default would put the strip's right edge INSIDE
|
||||
/// where the list sits at the floor — a real overlap
|
||||
/// ResolvedMainPanelHasNoOverlapOrOutOfBoundsChildAtThisSize's own
|
||||
/// 856x236 case would catch. This pins centering against the FLOOR
|
||||
/// value instead (declared x minus the 128px Round D growth delta —
|
||||
/// 984-856) — the widest safe position a fixed strip can take,
|
||||
/// verified against the real-file resolved tree at both sizes by
|
||||
/// <c>MossTankMarkupBuildOverRealFilesTests.BuffsExtrasStripStaysCenteredAndNonOverlappingAtTheFloor</c>
|
||||
/// in the App test project.
|
||||
/// Owner's third live look (2026-09-07): "Screenshot shows options
|
||||
/// under the buffing tab circled in red. Those are made up, remove
|
||||
/// them from here." VTank's real Buffs tab
|
||||
/// (docs/research/vtank-kb/08-ui-views.md §1 "Tab: Buffs") is exactly
|
||||
/// two labels + two lists + two "Add..." buttons, nothing in the empty
|
||||
/// middle strip between the lists. The MossTank-only extras block that
|
||||
/// used to live there (7 category toggles, the difficulty/rebuff
|
||||
/// spinners, the Force/Stop buffing button + status, the coverage
|
||||
/// counts — added by fix round B item 2, repolished by round F item 6)
|
||||
/// is gone outright, matching this same file's
|
||||
/// <see cref="ItemsTabIsVtankOnlyPlusTheAcceptedSliceOneRemoveButton"/>
|
||||
/// precedent for the Items tab's own round-F removal.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BuffsExtrasStripIsCenteredAtThePanelsFloorAndCoverageSitsUnderTheButtonRow()
|
||||
public void BuffsTabIsVtankOnlySixControls()
|
||||
{
|
||||
XDocument document = XDocument.Load(
|
||||
Path.Combine(AppContext.BaseDirectory, "mosstank.xml"));
|
||||
|
|
@ -335,45 +324,25 @@ public sealed class MossTankMarkupContractTests
|
|||
XElement buffsGroup = root.Elements("group")
|
||||
.Single(static g => (string?)g.Attribute("visible") == "{BuffsVisible}");
|
||||
|
||||
XElement[] lists = buffsGroup.Elements("list").ToArray();
|
||||
Assert.Equal(2, lists.Length);
|
||||
float leftListRightEdge = Number(lists[0], "x") + Number(lists[0], "w");
|
||||
// Round D item 4's own +128 growth: the declared x below is the
|
||||
// 984-wide authored default; subtracting it back out gives the
|
||||
// resolved position at the panel's tested floor (856x236).
|
||||
const float roundDGrowthDelta = 984f - 856f;
|
||||
float rightListLeftEdgeAtFloor = Number(lists[1], "x") - roundDGrowthDelta;
|
||||
Assert.Equal(2, buffsGroup.Elements("list").Count());
|
||||
string[] buttonTexts = buffsGroup.Elements("button")
|
||||
.Select(static b => (string?)b.Attribute("text") ?? string.Empty)
|
||||
.ToArray();
|
||||
Assert.Equal(["Add...", "Add..."], buttonTexts);
|
||||
string[] labelTexts = buffsGroup.Elements("label")
|
||||
.Select(static l => (string?)l.Attribute("text") ?? string.Empty)
|
||||
.ToArray();
|
||||
Assert.Equal(["Extra Buff Spells", "Blacklisted Buff Families"], labelTexts);
|
||||
|
||||
XElement trainedToggle = buffsGroup.Elements("toggle")
|
||||
.Single(static t => (string?)t.Attribute("onclick") == "{ToggleTrainedOnly}");
|
||||
XElement rebuffUpButton = buffsGroup.Elements("button")
|
||||
.Single(static b => (string?)b.Attribute("onclick") == "{RebuffUp}");
|
||||
float extrasLeft = Number(trainedToggle, "x");
|
||||
float extrasRight = Number(rebuffUpButton, "x") + Number(rebuffUpButton, "w");
|
||||
|
||||
float leftMargin = extrasLeft - leftListRightEdge;
|
||||
float rightMarginAtFloor = rightListLeftEdgeAtFloor - extrasRight;
|
||||
Assert.True(
|
||||
rightMarginAtFloor >= 0f,
|
||||
$"Extras strip (right edge {extrasRight}) overlaps the "
|
||||
+ $"Blacklisted Buff Families list at the panel's floor "
|
||||
+ $"(left edge {rightListLeftEdgeAtFloor}).");
|
||||
Assert.True(
|
||||
MathF.Abs(leftMargin - rightMarginAtFloor) <= 4f,
|
||||
$"Extras strip not centered at the panel's floor: left margin "
|
||||
+ $"{leftMargin}px, right margin {rightMarginAtFloor}px.");
|
||||
|
||||
XElement buffButton = buffsGroup.Elements("button")
|
||||
.Single(static b => (string?)b.Attribute("onclick") == "{Buff}");
|
||||
XElement coverage = buffsGroup.Elements("label")
|
||||
.Single(static l => (string?)l.Attribute("text") == "{Coverage}");
|
||||
float rowBottom = Number(buffButton, "y") + Number(buffButton, "h");
|
||||
float coverageGap = Number(coverage, "y") - rowBottom;
|
||||
Assert.True(
|
||||
coverageGap is >= 0f and <= 12f,
|
||||
$"Coverage sits {coverageGap}px below the Buff button row — "
|
||||
+ "expected <=12px, not the old 55px hole from anchoring it to "
|
||||
+ "the group's bottom edge instead.");
|
||||
// Nothing else — no toggle, no slider, no MossTank-only status/
|
||||
// difficulty/rebuff/coverage label ever made it back in.
|
||||
Assert.Empty(buffsGroup.Elements("toggle"));
|
||||
Assert.Empty(buffsGroup.Elements("slider"));
|
||||
Assert.DoesNotContain("{BuffButtonText}", labelTexts);
|
||||
Assert.DoesNotContain("{BuffStatus}", labelTexts);
|
||||
Assert.DoesNotContain("{DifficultyText}", labelTexts);
|
||||
Assert.DoesNotContain("{RebuffText}", labelTexts);
|
||||
Assert.DoesNotContain("{Coverage}", labelTexts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue