fix(D.5.1): occupancy-gated slot numbers (empty=0x1000005e bg digit) + bottom-right rect probe
FIX 1: UIElement_UIItem::SetShortcutNum (decomp 229481) has a three-way source branch: occupied+peace -> 0x10000042 (peace digit set), occupied+war -> 0x10000043 (war digit set), empty (ItemId==0) -> 0x1000005e (background digit, stance-independent). acdream previously only had the peace/war pair and drew them regardless of occupancy. Changes: - GameWindow.cs: read property 0x1000005e into toolbarEmptyDigits (no fallback; null is safe). Logs entry count. Passes emptyDigits to Bind. Adds [D.5.1 probe] block logging screen pos + size of 7 bottom-right element ids via ScreenPosition. - ToolbarController.cs: adds _emptyDigits field, emptyDigits ctor+Bind param (null default). RestampShortcutNumbers sets cell.EmptyDigits. Comments cite decomp 229481. - UiItemSlot.cs: adds EmptyDigits property + ActiveDigitArray() internal testable seam (occupied -> peace/war by stance; empty -> EmptyDigits). OnDraw uses it. Comment updated with three-way source table. - Tests: 5 new UiItemSlotTests (ActiveDigitArray occupancy), 2 new ToolbarControllerTests (emptyDigits injection + null-safe). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d5a88cd15
commit
a7cad5566b
5 changed files with 200 additions and 24 deletions
|
|
@ -55,12 +55,15 @@ public sealed class ToolbarController
|
|||
private readonly Action<uint> _useItem; // guid → fire UseObject
|
||||
|
||||
// Digit sprite DID arrays for slot labels (top row, numbers 1-9).
|
||||
// Peace set: property 0x10000042; war set: property 0x10000043.
|
||||
// Read from LayoutDesc 0x21000037, element 0x1000034A under composite 0x10000346.
|
||||
// Retail ref: UIElement_UIItem::SetShortcutNum (acclient_2013_pseudo_c.txt:229465);
|
||||
// gmToolbarUI::RecvNotice_SetCombatMode (196610-196621) re-stamps per stance.
|
||||
// Occupancy branch (decomp 229481):
|
||||
// occupied → peace 0x10000042 / war 0x10000043 (split by stance)
|
||||
// empty → background digit 0x1000005e (stance-independent)
|
||||
private uint[]? _peaceDigits;
|
||||
private uint[]? _warDigits;
|
||||
private uint[]? _emptyDigits;
|
||||
private bool _peace = true; // true = NonCombat (peace), false = any war stance
|
||||
|
||||
private ToolbarController(
|
||||
|
|
@ -71,7 +74,8 @@ public sealed class ToolbarController
|
|||
Action<uint> useItem,
|
||||
CombatState? combatState,
|
||||
uint[]? peaceDigits,
|
||||
uint[]? warDigits)
|
||||
uint[]? warDigits,
|
||||
uint[]? emptyDigits)
|
||||
{
|
||||
_repo = repo;
|
||||
_shortcuts = shortcuts;
|
||||
|
|
@ -79,6 +83,7 @@ public sealed class ToolbarController
|
|||
_useItem = useItem;
|
||||
_peaceDigits = peaceDigits;
|
||||
_warDigits = warDigits;
|
||||
_emptyDigits = emptyDigits;
|
||||
|
||||
for (int i = 0; i < SlotIds.Length; i++)
|
||||
{
|
||||
|
|
@ -133,6 +138,12 @@ public sealed class ToolbarController
|
|||
/// UIElement_UIItem::SetShortcutNum (acclient_2013_pseudo_c.txt:229465).
|
||||
/// </param>
|
||||
/// <param name="warDigits">War-mode digit DID array (property 0x10000043, same element).</param>
|
||||
/// <param name="emptyDigits">
|
||||
/// Empty-slot background digit DID array (property 0x1000005e, stance-independent).
|
||||
/// Used when a slot is EMPTY (ItemId == 0). Retail ref: UIElement_UIItem::SetShortcutNum
|
||||
/// (decomp 229481) — else branch when m_elem_Icon->m_state == 0x1000001c (empty state).
|
||||
/// Null if the dat lookup failed (empty slots draw no digit, which is safe).
|
||||
/// </param>
|
||||
public static ToolbarController Bind(
|
||||
ImportedLayout layout,
|
||||
ItemRepository repo,
|
||||
|
|
@ -141,10 +152,11 @@ public sealed class ToolbarController
|
|||
Action<uint> useItem,
|
||||
CombatState? combatState = null,
|
||||
uint[]? peaceDigits = null,
|
||||
uint[]? warDigits = null)
|
||||
uint[]? warDigits = null,
|
||||
uint[]? emptyDigits = null)
|
||||
{
|
||||
var c = new ToolbarController(layout, repo, shortcuts, iconIds, useItem, combatState,
|
||||
peaceDigits, warDigits);
|
||||
peaceDigits, warDigits, emptyDigits);
|
||||
c.Populate();
|
||||
return c;
|
||||
}
|
||||
|
|
@ -176,8 +188,9 @@ public sealed class ToolbarController
|
|||
}
|
||||
|
||||
// Re-stamp slot number labels after any item change.
|
||||
// Numbers show on ALL top-row slots regardless of item occupancy —
|
||||
// the user's retail screenshot confirms numbers on empty top-row slots.
|
||||
// Digit SPRITE SOURCE depends on occupancy (decomp UIElement_UIItem::SetShortcutNum:229481):
|
||||
// occupied → peace 0x10000042 / war 0x10000043; empty → background 0x1000005e.
|
||||
// The digit is ALWAYS shown on top-row slots (SetVisible(1) at decomp 229511).
|
||||
RestampShortcutNumbers();
|
||||
}
|
||||
|
||||
|
|
@ -215,12 +228,14 @@ public sealed class ToolbarController
|
|||
|
||||
/// <summary>
|
||||
/// Push digit-array references and shortcut-number state into every slot cell.
|
||||
/// Top row (indices 0–8): SetShortcutNum(i, _peace) — numbers 1–9 on ALL slots
|
||||
/// including empty ones (confirmed from user's retail screenshot; the numbers are
|
||||
/// slot LABELS, not item indicators).
|
||||
/// Top row (indices 0–8): SetShortcutNum(i, _peace) — numbers 1–9 always shown
|
||||
/// (the digit is ALWAYS visible, SetVisible(1) at decomp 229511; only the sprite
|
||||
/// SOURCE differs by occupancy — see UIElement_UIItem::SetShortcutNum decomp 229481).
|
||||
/// Bottom row (indices 9–17): ClearShortcutNum() — retail shows no numbers there.
|
||||
/// Retail ref: UIElement_UIItem::SetShortcutNum (acclient_2013_pseudo_c.txt:229465);
|
||||
/// gmToolbarUI::RecvNotice_SetCombatMode (196610-196621).
|
||||
/// Occupancy → source: occupied → peace 0x10000042 / war 0x10000043;
|
||||
/// empty → background 0x1000005e (decomp 229481/229493).
|
||||
/// </summary>
|
||||
private void RestampShortcutNumbers()
|
||||
{
|
||||
|
|
@ -230,6 +245,7 @@ public sealed class ToolbarController
|
|||
if (cell is null) continue;
|
||||
cell.PeaceDigits = _peaceDigits;
|
||||
cell.WarDigits = _warDigits;
|
||||
cell.EmptyDigits = _emptyDigits;
|
||||
if (i < 9)
|
||||
cell.SetShortcutNum(i, _peace); // top row: slot label digits 1–9 always shown
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue