fix(D.2b): vitals from the real stacked-window LayoutDesc (0x2100006C)

The vitals bars were rendered from the WRONG layout. The ids in vitals.xml
(0x0600113x) belong to LayoutDesc 0x21000014 -- the 800x28 floaty side-vitals
ROW. The stacked vitals window the user sees is LayoutDesc 0x2100006C
(160x58), which uses a different sprite set and geometry. Dumped the real
tree (new dump-vitals-layout CLI, reflective) and ported it:

- Sprites (#2): the stacked-window set 0x0600747E-0x0600748F (health/stamina/
  mana, each back+front 3-slice; caps 10px, mid 130px).
- Right cap (#1) + fill model: retail UIElement_Meter::DrawChildren draws the
  back 3-slice full then the front 3-slice CLIPPED to the fill fraction (its
  own right-cap shows at 100%, the back's shows through when partial). UiMeter
  now clips the front per-slice (UV-crop) instead of growing a capless slice.
- Spacing (#5): three flush 150x16 bars at y=5/21/37 in a 160x58 window
  (16px pitch, zero gap), per the dat rects -- not the old 20px-apart guess.
- Border (#3): the window is the 8-piece chrome frame (corners 0x060074C3-C6,
  edges 0x060074BF-C2, 5px) -- dat-confirmed identical to RetailChromeSprites.

The headless render-vitals-mockup now composites this exact window
(0x2100006C) from the real sprites with the same clipped-fill model, so the
look was verified before launch. Font (#4, dat Font 0x40000000) is the next
commit.

Decomp refs: gmVitalsUI::PostInit @0x4bfce0; UIElement_Meter::DrawChildren
@0x46fbd0 (scissor-fill); geometry from LayoutDesc 0x2100006C.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-14 22:50:17 +02:00
parent ada863980c
commit ff29787f12
5 changed files with 293 additions and 89 deletions

View file

@ -1,8 +1,13 @@
<panel id="acdream.vitals" x="10" y="30" w="220" h="96" resize="x">
<meter id="health" x="8" y="24" w="200" h="14" fill="{HealthPercent}" cur="{HealthCurrent}" max="{HealthMax}" color="#FFC70D0D" anchor="left,top,right"
backleft="0x06001141" backtile="0x06001140" backright="0x0600113F" frontleft="0x06001131" fronttile="0x06001132" frontright="0x06001133"/>
<meter id="stamina" x="8" y="44" w="200" h="14" fill="{StaminaPercent}" cur="{StaminaCurrent}" max="{StaminaMax}" color="#FFD49E1F" anchor="left,top,right"
backleft="0x06001147" backtile="0x06001146" backright="0x06001145" frontleft="0x06001137" fronttile="0x06001138" frontright="0x06001139"/>
<meter id="mana" x="8" y="64" w="200" h="14" fill="{ManaPercent}" cur="{ManaCurrent}" max="{ManaMax}" color="#FF1F33D9" anchor="left,top,right"
backleft="0x06001144" backtile="0x06001143" backright="0x06001142" frontleft="0x06001134" fronttile="0x06001135" frontright="0x06001136"/>
<!-- Retail stacked vitals window, geometry + sprite ids dat-verified from
LayoutDesc 0x2100006C (160x58, 5px chrome border, three flush 150x16 bars
at y=5/21/37). Each bar: back 3-slice (empty track) + front 3-slice (fill,
clipped to the fraction). Sprite ids are the STACKED-window set
(0x0600747E-0x0600748F), NOT the floaty-row set. -->
<panel id="acdream.vitals" x="10" y="30" w="160" h="58" resize="x">
<meter id="health" x="5" y="5" w="150" h="16" fill="{HealthPercent}" cur="{HealthCurrent}" max="{HealthMax}" color="#FFC70D0D" anchor="left,top,right"
backleft="0x0600747E" backtile="0x0600747F" backright="0x06007480" frontleft="0x06007481" fronttile="0x06007482" frontright="0x06007483"/>
<meter id="stamina" x="5" y="21" w="150" h="16" fill="{StaminaPercent}" cur="{StaminaCurrent}" max="{StaminaMax}" color="#FFD49E1F" anchor="left,top,right"
backleft="0x06007484" backtile="0x06007485" backright="0x06007486" frontleft="0x06007487" fronttile="0x06007488" frontright="0x06007489"/>
<meter id="mana" x="5" y="37" w="150" h="16" fill="{ManaPercent}" cur="{ManaCurrent}" max="{ManaMax}" color="#FF1F33D9" anchor="left,top,right"
backleft="0x0600748A" backtile="0x0600748B" backright="0x0600748C" frontleft="0x0600748D" fronttile="0x0600748E" frontright="0x0600748F"/>
</panel>