fix #212: preserve shortcut tint in physical combat
Port the retail m_bShortcutGhosted meaning instead of treating SetShortcutNum's boolean as peace versus war. Keep occupied shortcut numbers on the gold sheet in NonCombat, Melee, and Missile, reserve the gray sheet for Magic, and lock the four-mode matrix with conformance tests and corrected research. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
ab98cda26b
commit
5090aa7217
9 changed files with 197 additions and 112 deletions
|
|
@ -166,7 +166,7 @@ public sealed class UiItemSlot : UiElement
|
|||
// ── Shortcut number (slot label) ─────────────────────────────────────────
|
||||
// Port of UIElement_UIItem::SetShortcutNum (acclient_2013_pseudo_c.txt:229465).
|
||||
// Retail draws the digit on the cell's ShortcutNum sub-element, picking the
|
||||
// digit image from a DID-array property: 0x10000042 (peace) / 0x10000043 (war),
|
||||
// digit image from a DID-array property: 0x10000042 (regular) / 0x10000043 (ghosted),
|
||||
// indexed by slot position. Each digit is a 32×32 PFID_A8R8G8B8 RenderSurface
|
||||
// with the digit baked into the top-left corner (rest alpha=0), drawn Alphablend.
|
||||
|
||||
|
|
@ -174,30 +174,30 @@ public sealed class UiItemSlot : UiElement
|
|||
/// SetVisible(0) when edi < 0). Top row: 0..8 → digits 1..9. Bottom row: -1.</summary>
|
||||
public int ShortcutNum { get; private set; } = -1;
|
||||
|
||||
/// <summary>True = draw peace digit set; false = war digit set.</summary>
|
||||
public bool ShortcutPeace { get; private set; } = true;
|
||||
/// <summary>True when retail marks the physical-item shortcut as ghosted.</summary>
|
||||
public bool ShortcutGhosted { get; private set; }
|
||||
|
||||
/// <summary>Peace digit DID array. Index i → digit (i+1) sprite RenderSurface id.
|
||||
/// <summary>Regular digit DID array. Index i → digit (i+1) sprite RenderSurface id.
|
||||
/// Injected by the controller after reading LayoutDesc 0x21000037.
|
||||
/// Retail ref: UIElement_UIItem::SetShortcutNum (decomp 229481) — occupied slot picks
|
||||
/// property 0x10000042 (peace) or 0x10000043 (war) by stance.</summary>
|
||||
public uint[]? PeaceDigits { get; set; }
|
||||
/// property 0x10000042 when the shortcut is not ghosted.</summary>
|
||||
public uint[]? RegularDigits { get; set; }
|
||||
|
||||
/// <summary>War digit DID array. Same layout as PeaceDigits.
|
||||
/// Retail ref: UIElement_UIItem::SetShortcutNum (decomp 229493) — war stance.</summary>
|
||||
public uint[]? WarDigits { get; set; }
|
||||
/// <summary>Ghosted digit DID array. Same layout as RegularDigits.
|
||||
/// Retail ref: UIElement_UIItem::SetShortcutNum (decomp 229485-229488).</summary>
|
||||
public uint[]? GhostedDigits { get; set; }
|
||||
|
||||
/// <summary>Empty-slot digit DID array (property 0x1000005e, stance-independent).
|
||||
/// Used when the slot is EMPTY (ItemId == 0). Retail ref: UIElement_UIItem::SetShortcutNum
|
||||
/// (decomp 229481) — else branch when m_elem_Icon->m_state == 0x1000001c (empty).</summary>
|
||||
public uint[]? EmptyDigits { get; set; }
|
||||
|
||||
/// <summary>Set the slot's shortcut position and combat stance so the correct digit
|
||||
/// is drawn. Call with index 0..8 for the top row; pass peace=true for NonCombat.</summary>
|
||||
public void SetShortcutNum(int index, bool peace)
|
||||
/// <summary>Set the slot's shortcut position and ghosted state so the correct digit
|
||||
/// is drawn. Call with index 0..8 for the top row.</summary>
|
||||
public void SetShortcutNum(int index, bool ghosted)
|
||||
{
|
||||
ShortcutNum = index;
|
||||
ShortcutPeace = peace;
|
||||
ShortcutNum = index;
|
||||
ShortcutGhosted = ghosted;
|
||||
}
|
||||
|
||||
/// <summary>Clear the shortcut number label (hides the digit).</summary>
|
||||
|
|
@ -206,7 +206,7 @@ public sealed class UiItemSlot : UiElement
|
|||
/// <summary>
|
||||
/// Returns the digit DID array that OnDraw will use, following the retail occupancy
|
||||
/// branch in UIElement_UIItem::SetShortcutNum (decomp 229481):
|
||||
/// occupied (ItemId != 0) → ShortcutPeace ? PeaceDigits : WarDigits (0x10000042/43)
|
||||
/// occupied (ItemId != 0) → ShortcutGhosted ? GhostedDigits : RegularDigits (0x10000043/42)
|
||||
/// empty (ItemId == 0) → EmptyDigits (0x1000005e, stance-independent)
|
||||
/// Exposed as an internal method so unit tests can assert array selection without
|
||||
/// needing a real render context.
|
||||
|
|
@ -214,7 +214,7 @@ public sealed class UiItemSlot : UiElement
|
|||
internal uint[]? ActiveDigitArray()
|
||||
{
|
||||
bool occupied = ItemId != 0;
|
||||
return occupied ? (ShortcutPeace ? PeaceDigits : WarDigits) : EmptyDigits;
|
||||
return occupied ? (ShortcutGhosted ? GhostedDigits : RegularDigits) : EmptyDigits;
|
||||
}
|
||||
|
||||
// ── Events / draw ─────────────────────────────────────────────────────────
|
||||
|
|
@ -292,7 +292,7 @@ public sealed class UiItemSlot : UiElement
|
|||
|
||||
// Digit overlay: UIElement_UIItem::SetShortcutNum (acclient_2013_pseudo_c.txt:229465).
|
||||
// Occupancy branch (decomp 229481):
|
||||
// occupied (ItemId != 0) → peace/war digit set 0x10000042/43, split by stance
|
||||
// occupied (ItemId != 0) → regular/ghosted digit set 0x10000042/43
|
||||
// empty (ItemId == 0) → background digit set 0x1000005e, stance-independent
|
||||
// Each digit image is corner-baked (glyph in top-left, rest alpha=0); drawn
|
||||
// full-cell Alphablend so the transparent region is invisible.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue