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:
parent
ea5cf5b842
commit
3e84027885
9 changed files with 47 additions and 21 deletions
|
|
@ -84,7 +84,7 @@ internal sealed class AutoWieldController : IDisposable
|
|||
_objects.ObjectMoved += OnObjectMoved;
|
||||
_objects.ObjectRemoved += OnObjectRemoved;
|
||||
_objects.MoveRequestFailed += OnMoveRequestFailed;
|
||||
_objects.MoveRequestConfirmed += OnMoveRequestConfirmed;
|
||||
_objects.WieldConfirmed += OnWieldConfirmed;
|
||||
_objects.Cleared += OnObjectsCleared;
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ internal sealed class AutoWieldController : IDisposable
|
|||
TryWield(requested);
|
||||
}
|
||||
|
||||
private void OnMoveRequestConfirmed(ClientObject item)
|
||||
private void OnWieldConfirmed(ClientObject item)
|
||||
{
|
||||
if (_pendingSwitch is { BlockingItemId: 0 } pending
|
||||
&& item.ObjectId == pending.RequestedItemId)
|
||||
|
|
@ -319,7 +319,7 @@ internal sealed class AutoWieldController : IDisposable
|
|||
_objects.ObjectMoved -= OnObjectMoved;
|
||||
_objects.ObjectRemoved -= OnObjectRemoved;
|
||||
_objects.MoveRequestFailed -= OnMoveRequestFailed;
|
||||
_objects.MoveRequestConfirmed -= OnMoveRequestConfirmed;
|
||||
_objects.WieldConfirmed -= OnWieldConfirmed;
|
||||
_objects.Cleared -= OnObjectsCleared;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ public static class GameEventWiring
|
|||
p.Value.ItemGuid,
|
||||
newContainerId: wielderGuid,
|
||||
newEquipLocation: (AcDream.Core.Items.EquipMask)p.Value.EquipLoc);
|
||||
items.ConfirmMove(p.Value.ItemGuid); // Slice 1: confirm an optimistic wield (mirrors the 0x0022 handler)
|
||||
items.ConfirmWield(p.Value.ItemGuid); // Exact IR_WIELD completion + optimistic reconciliation.
|
||||
});
|
||||
dispatcher.Register(GameEventType.InventoryPutObjInContainer, e =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue