Import gmFloatyPowerBarUI LayoutDesc 0x21000072, teach the meter factory its stateful single-image shape, and project the movement-owned retail jump charge through a focused retained controller. Preserve authored resize constraints and state-managed visibility, with named-decomp pseudocode plus controller, movement, and production-DAT conformance coverage. Co-Authored-By: Codex <codex@openai.com>
135 lines
4.9 KiB
Markdown
135 lines
4.9 KiB
Markdown
# Retail jump power bar — pseudocode and port map
|
||
|
||
Date: 2026-07-13
|
||
|
||
Binary: Sept. 2013 EoR `acclient.exe` v11.4186
|
||
|
||
Scope: the floating `gmPowerbarUI` presentation used while the player charges a jump
|
||
|
||
## Named retail sources
|
||
|
||
- `gmPowerbarUI::PostInit @ 0x004DA4E0`
|
||
- `gmPowerbarUI::RecvNotice_SetPowerbarLevel @ 0x004DA550`
|
||
- `gmPowerbarUI::RecvNotice_FinishPowerbar @ 0x004DA580`
|
||
- `gmPowerbarUI::RecvNotice_BeginPowerbar @ 0x004DA730`
|
||
- `gmFloatyPowerBarUI::PostInit @ 0x004D0F00`
|
||
- `gmFloatyPowerBarUI::UpdateFromPlayerModule @ 0x004D1200`
|
||
- `gmFloatyPowerBarUI::ResizeTo @ 0x004D1460`
|
||
- `gmFloatyPowerBarUI::MoveTo @ 0x004D15D0`
|
||
- `gmFloatyPowerBarUI::SetVisible @ 0x004D17D0`
|
||
- `ClientCombatSystem::FinishJump @ 0x0056A9B0`
|
||
- `ClientCombatSystem::StartPowerBarBuild @ 0x0056ADB0`
|
||
- `ClientCombatSystem::GetPowerBarLevel @ 0x0056ADE0`
|
||
- `ClientCombatSystem::CommenceJump @ 0x0056AF90`
|
||
- `ClientCombatSystem::DoJump @ 0x0056B110`
|
||
|
||
The symbols and addresses above are present in
|
||
`docs/research/named-retail/symbols.json`; the bodies are in
|
||
`docs/research/named-retail/acclient_2013_pseudo_c.txt`.
|
||
|
||
## Authored DAT layout
|
||
|
||
Portal DAT `LayoutDesc 0x21000072` is a `gmFloatyPowerBarUI` window:
|
||
|
||
| Element | ID | Geometry | Media/state |
|
||
|---|---:|---:|---|
|
||
| Root | `0x10000612` | 610×25 px | custom type `0x10000053` |
|
||
| Meter | `0x10000034` | x=5, y=5, 600×15 px | empty track `0x06004D0B` |
|
||
| Fill field | `0x00000002` | 600×15 px | JumpMode `0x10000042` → `0x06001354`; MeleeMode `0x10000043` and MissileMode `0x10000044` → `0x06001200`; DDDMode `0x10000045` → `0x0600195B` |
|
||
| Recklessness field | `0x100005EE` | x=60, 480×15 px | `0x0600715E`; hidden by `PostInit` |
|
||
|
||
The meter's fill is clipped horizontally. A level of 0.0 shows no fill; 0.5
|
||
shows the left 300 px; 1.0 shows the full 600 px. It does not stretch from the
|
||
center or from the right.
|
||
|
||
## Retail lifecycle pseudocode
|
||
|
||
```text
|
||
CommenceJump():
|
||
if jump_pending:
|
||
return
|
||
error = motion_interpreter.charge_jump()
|
||
if error != success:
|
||
report the matching jump error
|
||
return
|
||
cancel repeat attack if active
|
||
latest_powerbar_level = 0
|
||
jump_pending = true
|
||
powerbar_mode = JUMP
|
||
notify BeginPowerbar(JUMP)
|
||
StartPowerBarBuild()
|
||
|
||
StartPowerBarBuild():
|
||
build_in_progress = true
|
||
build_start_time = current_time
|
||
notify SetPowerbarLevel(powerbar_mode, 0)
|
||
latest_powerbar_level = 0
|
||
|
||
GetPowerBarLevel():
|
||
if not build_in_progress:
|
||
return 0
|
||
duration = 0.8 seconds in dual-wield style, otherwise 1.0 second
|
||
return clamp((current_time - build_start_time) / duration, 0, 1)
|
||
|
||
gmPowerbarUI.BeginPowerbar(JUMP):
|
||
set root state to JumpMode (0x10000042)
|
||
current_mode = JUMP
|
||
set meter 0x10000034 level to 0
|
||
show window
|
||
|
||
gmPowerbarUI.SetPowerbarLevel(mode, level):
|
||
if mode == current_mode:
|
||
set meter 0x10000034 level to level
|
||
|
||
DoJump(on release):
|
||
extent = max(GetPowerBarLevel(), MIN_JUMP_EXTENT)
|
||
FinishJump()
|
||
motion_interpreter.jump(extent)
|
||
send JumpPack(extent, velocity, position/update sequences)
|
||
|
||
FinishJump():
|
||
if jump_pending:
|
||
stop build and clear its time
|
||
notify FinishPowerbar(JUMP)
|
||
powerbar_mode = UNDEFINED
|
||
clear standing_longjump
|
||
jump_pending = false
|
||
|
||
gmPowerbarUI.FinishPowerbar(JUMP):
|
||
if JUMP == current_mode:
|
||
current_mode = UNDEFINED
|
||
set meter level to 0
|
||
hide window
|
||
```
|
||
|
||
`gmPowerbarUI::PostInit` also hides the recklessness field. The floaty subclass
|
||
restores and persists its position, size, lock chrome, and visibility through
|
||
the normal retail window preferences.
|
||
|
||
## Reference cross-checks
|
||
|
||
- ACE `ACE.Server/Network/Structure/JumpPack.cs` documents `Extent` as jump
|
||
power 0–1. `ACE.Server/WorldObjects/Player.cs::HandleActionJump` clamps the
|
||
received extent to that same interval before applying jump stamina/height.
|
||
- holtburger `crates/holtburger-core/src/client/commands.rs` carries the chosen
|
||
extent unchanged into the `JumpData` action. Its vendored ACViewer movement
|
||
implementation likewise stores jump extent as the power input to the jump
|
||
calculation.
|
||
|
||
These references corroborate the data range and its handoff. The named retail
|
||
decomp remains authoritative for charge timing, notices, visibility, and UI
|
||
state selection.
|
||
|
||
## acdream port map
|
||
|
||
- `PlayerMovementController` already owns the exact shared retail charge clock
|
||
and release transition. Expose it as a read-only `(IsCharging, Power)`
|
||
snapshot; do not add a UI timer.
|
||
- Teach `UiMeter`/`DatWidgetFactory` the DAT's stateful single-image meter shape:
|
||
meter direct media is the track, child state media is the selected fill.
|
||
- `JumpPowerbarController` selects JumpMode, binds fill to the movement snapshot,
|
||
and performs the begin/show and finish/reset/hide transitions.
|
||
- `RetailUiRuntime` imports and mounts `0x21000072` as a state-managed retained
|
||
window. `GameWindow` only supplies the movement snapshot delegate.
|
||
|
||
This port introduces no intentional retail divergence.
|