fix(ui): port live experience quality updates (#217)
Parse retail PrivateUpdatePropertyInt64 and route authoritative Total/Available Experience through both local-player projections so Attributes, the level meter, and Skills refresh together. Preserve the existing retail XP curve and right-align the Total XP value. Close the user-confirmed item-give gate for #216 and record the named-retail/ACE/holtburger conformance evidence. Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
parent
30d294506c
commit
84b7d2d7cd
15 changed files with 391 additions and 29 deletions
|
|
@ -44,38 +44,40 @@ Copy this block when adding a new issue:
|
|||
|
||||
---
|
||||
|
||||
## #216 — Inventory drags into the 3-D world could only drop items
|
||||
## #217 — Character windows did not receive live 64-bit experience updates
|
||||
|
||||
**Status:** IN-PROGRESS
|
||||
**Status:** IN-PROGRESS — implementation complete; connected visual gate pending
|
||||
**Severity:** HIGH
|
||||
**Filed:** 2026-07-13
|
||||
**Component:** retained UI / inventory / interaction / net
|
||||
**Component:** retained UI / character sheet / net / player state
|
||||
|
||||
**Description:** Releasing a physical inventory item over an NPC always sent
|
||||
the ground-drop path. A starter-dungeon character therefore could not hand the
|
||||
exit token to the exit NPC and could not complete the dungeon.
|
||||
**Description:** The Attributes window always displayed Total Experience as 0
|
||||
and an empty level-progress meter after the player earned XP. The Skills footer
|
||||
also displayed Unassigned Experience as 0, preventing an accurate raise-cost
|
||||
decision. The Total Experience number was centered instead of right-aligned.
|
||||
|
||||
**Root cause / status:** Implementation complete; connected live gate pending.
|
||||
The exact `AttemptPlaceIn3D` policy and the `0x00CD`
|
||||
packet builder already existed, but `GameWindow.OnUiDragReleasedOutside`
|
||||
discarded the release coordinates and always called `DropToWorld`, hard-coding
|
||||
`TargetId=0`. The release path now world-picks at the actual release point,
|
||||
the controller executes its existing `GiveToTarget` action without optimistic
|
||||
mutation, `WorldSession` sends the exact request, and PlayerDescription drives
|
||||
the retail player secure-trade preference.
|
||||
**Root cause / status:** acdream parsed the neighboring private/public Int32
|
||||
quality messages (`0x02CD`/`0x02CE`) but omitted retail
|
||||
`PrivateUpdatePropertyInt64 (0x02CF)`. Both TotalExperience (quality 1) and
|
||||
AvailableExperience (quality 2) use that message. The exact parser/event/state
|
||||
path is now ported, both local-player projections are synchronized in one
|
||||
wiring owner, the existing retail XP-band formula receives live data, and only
|
||||
the value element `0x10000235` is explicitly right-aligned.
|
||||
|
||||
**Files:** `src/AcDream.App/UI/ItemInteractionController.cs`;
|
||||
`src/AcDream.App/Rendering/GameWindow.cs`;
|
||||
`src/AcDream.Core.Net/WorldSession.cs`.
|
||||
**Files:** `src/AcDream.Core.Net/Messages/PrivateUpdatePropertyInt64.cs`;
|
||||
`src/AcDream.Core.Net/WorldSession.cs`;
|
||||
`src/AcDream.Core.Net/ObjectTableWiring.cs`;
|
||||
`src/AcDream.Core/Player/LocalPlayerState.cs`;
|
||||
`src/AcDream.App/UI/Layout/CharacterStatController.cs`.
|
||||
|
||||
**Research:** `docs/research/2026-07-13-retail-give-item-pseudocode.md`;
|
||||
`ItemHolder::AttemptPlaceIn3D @ 0x00588600`;
|
||||
`ACCWeenieObject::UIAttemptGive @ 0x0058D620`;
|
||||
`CM_Inventory::Event_GiveObjectRequest @ 0x006ABB00`.
|
||||
**Research:** `docs/research/2026-07-13-retail-experience-update-pseudocode.md`;
|
||||
`CM_Qualities::DispatchUI_PrivateUpdateInt64 @ 0x006AEAD0`;
|
||||
`ClientObjMaintSystem::Handle_Qualities__PrivateUpdateInt64 @ 0x00559000`;
|
||||
`gmStatManagementUI::UpdateExperience @ 0x004F0A70`.
|
||||
|
||||
**Acceptance:** Drag the starter-dungeon exit token from the backpack onto the
|
||||
exit NPC. ACE accepts the token, the inventory removes/decrements it only from
|
||||
the authoritative server response, and the quest teleport exits the dungeon.
|
||||
**Acceptance:** Earn XP while logged in. Attributes immediately shows the new
|
||||
right-aligned total and red progress fill; Skills immediately shows the same
|
||||
server-authoritative unassigned XP available for raises.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -8225,6 +8227,18 @@ Fixed by the A7 lighting rework, specifically A7 Fix D (`0980bea4`, `cf627933`,
|
|||
**Status:** DONE (2026-07-09, investigated this session).
|
||||
The described mechanism (live entities collapsing to one root-centered cylinder) no longer exists. `RegisterLiveEntityCollision` (`GameWindow.cs:4244`) now builds a multi-shape list via `ShadowShapeBuilder.FromSetup` — one shape per CylSphere, Sphere, and BSP-bearing Part — and registers via `RegisterMultiPart` (A6.P4 Task 7, `ca9341c2`). The retail `CSphere` and `CCylSphere` collision families were ported verbatim in `78e57581` (sphere primitive), `6ab26989` (fix #172, CCylSphere family), and `96ae2740` (fix #182, CSphere family, retires TS-45). The remaining `setup.Radius` single-cylinder path is now a deliberately-audited fallback used only when no other shape data exists. `tests/AcDream.Core.Tests/Physics/ShadowShapeBuilderShapeSourceTests.cs` covers both a multi-shape object and a live-creature case.
|
||||
|
||||
---
|
||||
|
||||
## #216 — Inventory drags into the 3-D world could only drop items
|
||||
|
||||
**Status:** DONE (2026-07-13, `30d29450`, user-confirmed connected gate).
|
||||
Dragging the starter-dungeon exit token onto its NPC now world-picks at the
|
||||
actual release point, executes the retail `GiveToTarget` path without optimistic
|
||||
inventory mutation, receives ACE's authoritative removal, and completes the
|
||||
quest teleport out of the dungeon.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Example:
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue