feat(combat): port retail basic combat bar

Mount authored gmCombatUI, share one press/hold/release request state machine across DAT buttons and keybindings, and recover the exact 1.0s/0.8s power timing from matching retail x86. The same timer fixes jump charge, while ready-stance, response queueing, auto-repeat, layout binding, migration, and conformance coverage keep behavior architectural rather than panel-local.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-11 14:03:28 +02:00
parent 9958458318
commit 2215c76c7e
22 changed files with 1265 additions and 46 deletions

View file

@ -160,6 +160,19 @@ public static class DatWidgetFactory
.FirstOrDefault();
bar.TrackSprite = track is null ? 0u : DefaultImage(track);
bar.ThumbSprite = scalarThumb is null ? 0u : DefaultImage(scalarThumb);
// gmCombatUI's desired-power slider (0x1000004F) authors the
// live charge as a nested Type-7 meter. UiScrollbar consumes its
// DAT children, so retain the meter's fill image on the scalar
// widget itself. The fill container is element 2; the Recklessness
// overlay (0x100005EF) is deliberately not the charge image.
ElementInfo? meter = info.Children.FirstOrDefault(child => child.Type == 7u);
ElementInfo? fill = meter?.Children.FirstOrDefault(child => child.Id == 2u)
?? meter?.Children
.Where(child => DefaultImage(child) != 0u)
.OrderByDescending(child => child.ReadOrder)
.FirstOrDefault();
bar.ScalarFillSprite = fill is null ? 0u : DefaultImage(fill);
return bar;
}