fix(items): finish corpse pickup and combat switching
Port retail's first-slot ShowPendingInPlayer path for double-click loot and carry the current owned-container destination through deferred pickup. Retire the previous ground-container view as soon as a replacement is requested so its range close cannot cancel ACE's active MoveTo chain. Preserve active-combat weapon intent across ACE's authoritative wand-to-missile stance tail while leaving peace-mode switches unchanged. Release build succeeds and all 5,885 tests pass with five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
d51a0fc825
commit
0392c6d721
17 changed files with 631 additions and 81 deletions
|
|
@ -22,6 +22,10 @@ Named Sept-2013 retail symbols:
|
|||
- `UIElement_ItemList::ListenToElementMessage @ 0x004E4D50`
|
||||
- `ClientUISystem::SetGroundObject @ 0x00564510`
|
||||
- `ClientUISystem::OnViewContents @ 0x00565870`
|
||||
- `CPlayerSystem::PlaceInBackpack @ 0x0055D8C0`
|
||||
- `gmInventoryUI::RecvNotice_ShowPendingInPlayer @ 0x004A6B50`
|
||||
- `gmInventoryUI::RecvNotice_EndPendingInPlayer @ 0x004A68B0`
|
||||
- `UIElement_ItemList::ItemList_InsertItem @ 0x004E3F40`
|
||||
- `ACCWeenieObject::UIAttemptPutInContainer @ 0x0058D680`
|
||||
- `ACCWeenieObject::UIAttemptSplitToContainer @ 0x0058D7D0`
|
||||
- `ItemHolder::AttemptToPlaceInContainer @ 0x00588140`
|
||||
|
|
@ -69,9 +73,22 @@ thumb, and arrow sprites from LayoutDesc `0x2100003E`.
|
|||
```text
|
||||
UseWorldObject(objectId):
|
||||
decision = ItemHolder policy
|
||||
if decision is SetGroundObject:
|
||||
expectedExternalRoot = objectId
|
||||
send Use(objectId)
|
||||
if decision is SetGroundObject:
|
||||
SetGroundObject(objectId, notifyServer = true)
|
||||
|
||||
SetGroundObject(newRoot, notifyServer):
|
||||
if currentExternalRoot == newRoot:
|
||||
return
|
||||
oldRoot = currentExternalRoot
|
||||
if oldRoot != 0:
|
||||
retire oldRoot's temporary contents tree
|
||||
publish SetGroundObject(0) to the external panel
|
||||
if notifyServer:
|
||||
send NoLongerViewingContents(oldRoot)
|
||||
currentExternalRoot = newRoot
|
||||
expectedExternalRoot = newRoot
|
||||
// The panel remains empty until ViewContents for newRoot is accepted.
|
||||
|
||||
UseCorpse(corpseId):
|
||||
// A corpse is a TYPE_CONTAINER carrying BF_STUCK | BF_CORPSE.
|
||||
|
|
@ -86,11 +103,6 @@ OnViewContents(containerId, orderedEntries):
|
|||
if containerId != expectedExternalRoot:
|
||||
return
|
||||
|
||||
old = currentExternalRoot
|
||||
if old != 0 and old != containerId:
|
||||
objectTable.StopViewingContentsTree(old)
|
||||
send NoLongerViewingContents(old) exactly once
|
||||
|
||||
currentExternalRoot = containerId
|
||||
expectedExternalRoot = containerId
|
||||
externalPanel.SetGroundObject(containerId)
|
||||
|
|
@ -138,6 +150,14 @@ OnExternalItemDoubleClick(itemId):
|
|||
ItemHolder.UseObject(itemId)
|
||||
// Because item.ContainerId is currentExternalRoot, retail policy emits
|
||||
// PlaceInBackpack; the server remains authoritative for the move.
|
||||
destination = current open owned pack
|
||||
destinationList.RemoveTrailingEmptyItem()
|
||||
destinationList.AddEmptySlot(at index 0)
|
||||
destinationList.AddItem(itemId)
|
||||
destinationList.pendingItem.SetWaitingState(true)
|
||||
send PutItemInContainer(itemId, destination, placement = 0)
|
||||
// The pending item therefore reserves the FIRST slot and shifts the
|
||||
// existing packed list to the right until the server confirms or rejects.
|
||||
|
||||
DragExternalItemToOwnedInventory(itemId, placement, splitAmount):
|
||||
if splitAmount < full stack:
|
||||
|
|
@ -171,8 +191,10 @@ DragOwnedItemToExternalContainer(itemId, placement, splitAmount):
|
|||
## Architectural mapping
|
||||
|
||||
- `ExternalContainerState` in Core owns only expected/current external-root
|
||||
identity and transition ordering. It filters ACE's nested `ViewContents`
|
||||
packets so they cannot replace the visible root.
|
||||
identity and transition ordering. A replacement request retires current
|
||||
presentation immediately, matching `SetGroundObject`; accepted
|
||||
`ViewContents` later opens the requested root. It filters ACE's nested
|
||||
`ViewContents` packets so they cannot replace the visible root.
|
||||
- `ExternalContainerLifecycleController` in App observes those transitions,
|
||||
retires the replaced root's temporary preview tree, then owns the
|
||||
replacement-only `NoLongerViewingContents` network side effect. The wire
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue