fix(ui): night-round review — F11/F13/F14/F15 one-liners
F11: logs when a Map tab town-marker's template resolves to something other than a UiButton — that path previously silently skipped the TooltipText write with no diagnostic, leaving a mounted-but-empty tooltip popup indistinguishable from "no template configured". F13: RetailSkillFormula.FormatFormula now reads Attribute1Multiplier/ Attribute2Multiplier/AdditiveBonus/Divisor through the SAME unsigned reinterpretation TryCalculate already uses (this class's own doc comment already stated the invariant; FormatFormula just didn't follow it). A high-bit-set value would previously both mis-gate hasAttr1/ hasAttr2 and print a negative number, out of sync with what TryCalculate actually computes with for the same formula. Added regression tests, empirically verified to fail without the fix. F14: documented the RefreshHouseMarker gap rather than guessing at the byte-decode — Position::get_outside_cell_id @0x004527b0 is itself BN-mangled (its `(eax_2 - eax_2) & objcell_id` return is the same decompiler-obscures-a-real-conditional artifact class this round hit elsewhere) and depends on LandDefs::adjust_to_outside, a genuinely larger port than this round's other findings. HousePosition is wired () => null in production today (ISSUES #413's remaining scope), so this method is currently unreachable; left a TODO citing the retail call chain for whenever that lands. F15: fixed RefreshCoordinatesAndPlayerMarker's gate to AND-on-both- present, matching gmMapUI::Update @0x004a2078's exact `if (m_pCoordinateText != 0 && m_pPlayerLocationIcon != 0)` condition. The prior `_coordinateText is null && _playerIcon is null` check only skipped when BOTH were absent (proceeding whenever EITHER was present), letting coordinate text and the player marker update independently instead of as the single gated unit retail treats them as. Added a regression test (player-icon template resolution failure must also skip the coordinate-text write), empirically verified to fail without the fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c403f57815
commit
0b0c7aa485
4 changed files with 172 additions and 18 deletions
|
|
@ -229,6 +229,49 @@ public sealed class MapPageControllerTests
|
|||
Assert.False(playerIcon!.Visible);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Refresh_PlayerIconTemplateResolutionFails_CoordinateTextStaysEmptyToo()
|
||||
{
|
||||
// F15 (night-round review): gmMapUI::Update @0x004a2078's gate is
|
||||
// `if (m_pCoordinateText != 0 && m_pPlayerLocationIcon != 0)` — BOTH
|
||||
// widgets present, not "at least one". A player-icon template
|
||||
// resolution failure (leaving _playerIcon null, e.g. a future DAT
|
||||
// regression) must skip the coordinate-text write too, not just the
|
||||
// marker placement — the OLD `_coordinateText is null &&
|
||||
// _playerIcon is null` gate only skipped when BOTH were absent, so
|
||||
// it would have written coordinate text here even with a missing
|
||||
// player icon.
|
||||
const uint cellId = 0x11CE0001u; // outdoor: TryFromCell succeeds.
|
||||
Assert.True(RadarCoordinates.TryFromCell(cellId, out _));
|
||||
|
||||
ElementInfo rootInfo = FixtureLoader.LoadMapHouseHostInfos();
|
||||
ImportedLayout layout = FixtureLoader.LoadMapHouseHost();
|
||||
var callbacks = new MapHousePanelController.Callbacks(
|
||||
Toggle: () => { },
|
||||
Map: new MapPageController.Bindings(
|
||||
CurrentCalendar: static () => default,
|
||||
PlayerCellId: () => cellId,
|
||||
HousePosition: static () => (CreateObject.ServerPosition?)null,
|
||||
// Simulates the player icon's own standalone template
|
||||
// resolution failing (ResolveSwallowedIcon's own null path)
|
||||
// while every other swallowed-icon/town-marker resolution
|
||||
// still succeeds normally.
|
||||
TemplateResolver: (_, e) => e == MapPageController.PlayerIconId
|
||||
? null
|
||||
: new UiText { Width = 10f, Height = 10f, DatElementId = e }),
|
||||
House: new HousePageController.Bindings(Lines: static () => Array.Empty<string>()));
|
||||
|
||||
MapHousePanelController? controller = MapHousePanelController.Bind(rootInfo, layout, callbacks);
|
||||
Assert.NotNull(controller);
|
||||
|
||||
Assert.Null(
|
||||
UiElement.FindDescendant(controller!.Root, MapPageController.PlayerIconId));
|
||||
|
||||
var coordinateText = Assert.IsType<UiText>(
|
||||
UiElement.FindDescendant(controller.Root, MapPageController.CoordinateTextId));
|
||||
Assert.Empty(coordinateText.LinesProvider());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Bind_HouseMarker_NullPosition_StaysHidden()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue