fix(inventory): complete switches on wield response

Clear retail AutoWield on the matching authoritative WieldObject instead of waiting for unrelated rollback bookkeeping to drain. This prevents a completed switch from consuming the next weapon activation locally, including crossbows.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 09:00:54 +02:00
parent ea5cf5b842
commit 3e84027885
9 changed files with 47 additions and 21 deletions

View file

@ -86,11 +86,12 @@ public sealed class ClientObjectTable
public event Action<ClientObject>? MoveRolledBack;
/// <summary>
/// Fires after the server has confirmed the final outstanding request for
/// an optimistically moved item. This is later than <see cref="ObjectMoved"/>,
/// which also fires for the initial local projection.
/// Fires for an authoritative WieldObject response after its object state
/// has been applied. This is deliberately independent of optimistic-move
/// rollback bookkeeping: retail clears IR_WIELD on the matching server
/// response even when separate reconciliation state exists for the item.
/// </summary>
public event Action<ClientObject>? MoveRequestConfirmed;
public event Action<ClientObject>? WieldConfirmed;
/// <summary>
/// Fires for every InventoryServerSaveFailed response, including requests
@ -268,8 +269,6 @@ public sealed class ClientObjectTable
if (p.outstanding <= 1)
{
_pendingMoves.Remove(itemId);
if (_objects.TryGetValue(itemId, out ClientObject? item))
MoveRequestConfirmed?.Invoke(item);
}
else
{
@ -277,6 +276,20 @@ public sealed class ClientObjectTable
}
}
/// <summary>
/// Reconcile an authoritative WieldObject response and publish the exact
/// retail inventory-request completion boundary. The notification is not
/// conditional on the optimistic rollback counter reaching zero.
/// Retail: ACCWeenieObject::ServerSaysMoveItem @ 0x0058DBB0 clears the
/// matching prevRequestObjectID directly.
/// </summary>
public void ConfirmWield(uint itemId)
{
ConfirmMove(itemId);
if (_objects.TryGetValue(itemId, out ClientObject? item))
WieldConfirmed?.Invoke(item);
}
/// <summary>The server rejected a move (InventoryServerSaveFailed 0x00A0) — restore the item to its
/// pre-move (container, slot) and drop the snapshot entirely (the server's next snapshot reconciles
/// any still-outstanding moves). False if nothing was pending.</summary>