fix: powerbar mode captions - jump 'Height' + combat 'Power'/'Accuracy'
Retail authors ONE caption element per bar with per-mode state strings, switched by a PassToChildren state cascade (gmPowerbarUI:: RecvNotice_BeginPowerbar @0x004DA730 sets 0x10000042 Jump / 0x10000043 Melee / 0x10000044 Missile / 0x10000045 DDD; installed-DAT probe confirmed every string + PassToChildren flag). - Jump bar (user gate): the floaty powerbar's caption child (0x10000035: JumpMode 'Height', authored HJustify=Center over the bar) was dropped by UiMeter's child absorption. The stateful-fill meter build now absorbs it into per-state labels; TrySetRetailState latches the caption and OnDraw shows it when no live Label provider is bound. JumpPowerbarController's existing JumpMode flip now surfaces 'Height' with zero controller changes. The mount gained the string resolver the Build call never passed. - Combat bar (user gate): label 0x10000052 authors 'MeleeCombat' -> 'Power' and 'MissileCombat' -> 'Accuracy'; the controller latched the MELEE string once at bind. CombatUiLabels now resolves both authored strings and OnCombatModeChanged sets the mode's string - switching live when swapping melee <-> missile weapons in combat. Also fixed the mode-state flip target: the states live on the BASIC PANEL (0x1000005C, PassToChildren), not the layout root (Hide/ShowDetail only) - the old _root flip was a silent no-op. New env-gated ACDREAM_PROBE_POWERBAR layout probe (kept, house pattern). App suite 4,987/3 skips. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4943484eb9
commit
adf8335675
7 changed files with 233 additions and 14 deletions
|
|
@ -17,6 +17,8 @@ namespace AcDream.App.UI;
|
|||
public sealed class UiMeter : UiElement, IUiDatStateful
|
||||
{
|
||||
private readonly Dictionary<uint, uint> _stateFillSprites = new();
|
||||
private readonly Dictionary<uint, string> _stateLabels = new();
|
||||
private string? _activeStateLabel;
|
||||
|
||||
/// <summary>Dat element id, set by the layout importer so duplicated page copies can be scoped.</summary>
|
||||
public uint ElementId { get; set; }
|
||||
|
|
@ -72,6 +74,10 @@ public sealed class UiMeter : UiElement, IUiDatStateful
|
|||
/// <summary>The active numeric DAT state for a stateful fill meter.</summary>
|
||||
public uint ActiveRetailStateId { get; private set; }
|
||||
|
||||
/// <summary>The caption latched by the active retail state (null when the
|
||||
/// state authors none). Exposed for tests.</summary>
|
||||
internal string? ActiveStateLabel => _activeStateLabel;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a fill sprite carried by a child state of the imported meter.
|
||||
/// Used by the powerbar shape in LayoutDesc 0x21000072, whose track is on
|
||||
|
|
@ -83,15 +89,36 @@ public sealed class UiMeter : UiElement, IUiDatStateful
|
|||
_stateFillSprites[stateId] = spriteId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a caption carried by a state of the meter's absorbed Type-12
|
||||
/// child (gmPowerbarUI's 0x10000035: JumpMode 'Height' / MeleeMode 'Power'
|
||||
/// / MissileMode 'Accuracy'). Retail shows it via the meter's
|
||||
/// PassToChildren state cascade; the absorbed equivalent latches it in
|
||||
/// <see cref="TrySetRetailState"/> and draws it when no live
|
||||
/// <see cref="Label"/> provider supplies text. The child authors
|
||||
/// HJustify=Center — the same centered draw the label overlay uses.
|
||||
/// </summary>
|
||||
internal void ConfigureStateLabel(uint stateId, string text)
|
||||
{
|
||||
if (stateId != 0 && !string.IsNullOrEmpty(text))
|
||||
_stateLabels[stateId] = text;
|
||||
}
|
||||
|
||||
public bool TrySetRetailState(uint stateId)
|
||||
{
|
||||
if (!_stateFillSprites.TryGetValue(stateId, out uint spriteId))
|
||||
bool hasFill = _stateFillSprites.TryGetValue(stateId, out uint spriteId);
|
||||
bool hasLabel = _stateLabels.TryGetValue(stateId, out string? caption);
|
||||
if (!hasFill && !hasLabel)
|
||||
return false;
|
||||
|
||||
ActiveRetailStateId = stateId;
|
||||
FrontLeft = 0;
|
||||
FrontTile = spriteId;
|
||||
FrontRight = 0;
|
||||
if (hasFill)
|
||||
{
|
||||
FrontLeft = 0;
|
||||
FrontTile = spriteId;
|
||||
FrontRight = 0;
|
||||
}
|
||||
_activeStateLabel = hasLabel ? caption : null;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +196,9 @@ public sealed class UiMeter : UiElement, IUiDatStateful
|
|||
}
|
||||
}
|
||||
|
||||
string? label = Label();
|
||||
// A live provider (vitals "cur/max") wins; otherwise the active
|
||||
// retail-state caption ('Height'/'Power'/'Accuracy') shows.
|
||||
string? label = Label() ?? _activeStateLabel;
|
||||
if (!string.IsNullOrEmpty(label))
|
||||
{
|
||||
if (DatFont is { } datFont)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue