feat(ui): port retail jump power bar
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>
This commit is contained in:
parent
27619b2328
commit
db03b4bda8
18 changed files with 3045 additions and 10 deletions
135
docs/research/2026-07-13-retail-jump-powerbar-pseudocode.md
Normal file
135
docs/research/2026-07-13-retail-jump-powerbar-pseudocode.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue