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
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using AcDream.Core.Combat;
|
||||
using AcDream.Core.Items;
|
||||
|
||||
namespace AcDream.App.UI;
|
||||
|
|
@ -40,7 +41,8 @@ public sealed class ItemInteractionController : IDisposable
|
|||
private readonly Func<bool> _playerOnGround;
|
||||
private readonly Func<bool> _inNonCombatMode;
|
||||
private readonly Func<uint, bool> _isComponentPack;
|
||||
private readonly Action<uint>? _placeInBackpack;
|
||||
private readonly Action<uint, uint, int>? _placeInBackpack;
|
||||
private readonly Func<uint> _backpackContainerId;
|
||||
private readonly Action<uint>? _requestExternalContainer;
|
||||
private readonly Action<ItemPolicyAction>? _auxiliaryAction;
|
||||
private readonly InteractionState _interactionState;
|
||||
|
|
@ -73,7 +75,8 @@ public sealed class ItemInteractionController : IDisposable
|
|||
Func<bool>? playerOnGround = null,
|
||||
Func<bool>? inNonCombatMode = null,
|
||||
Func<uint, bool>? isComponentPack = null,
|
||||
Action<uint>? placeInBackpack = null,
|
||||
Action<uint, uint, int>? placeInBackpack = null,
|
||||
Func<uint>? backpackContainerId = null,
|
||||
Action<ItemPolicyAction>? auxiliaryAction = null,
|
||||
Action<uint, uint>? sendSplitToWorld = null,
|
||||
Func<uint>? selectedObjectId = null,
|
||||
|
|
@ -83,7 +86,9 @@ public sealed class ItemInteractionController : IDisposable
|
|||
Func<bool>? dragOnPlayerOpensSecureTrade = null,
|
||||
Action<string>? systemMessage = null,
|
||||
Action<uint, uint, uint, uint>? sendSplitToContainer = null,
|
||||
Action<uint>? requestExternalContainer = null)
|
||||
Action<uint>? requestExternalContainer = null,
|
||||
CombatState? combatState = null,
|
||||
Action<CombatMode>? sendChangeCombatMode = null)
|
||||
{
|
||||
_objects = objects ?? throw new ArgumentNullException(nameof(objects));
|
||||
_playerGuid = playerGuid ?? throw new ArgumentNullException(nameof(playerGuid));
|
||||
|
|
@ -105,6 +110,7 @@ public sealed class ItemInteractionController : IDisposable
|
|||
_inNonCombatMode = inNonCombatMode ?? (() => false);
|
||||
_isComponentPack = isComponentPack ?? (_ => false);
|
||||
_placeInBackpack = placeInBackpack;
|
||||
_backpackContainerId = backpackContainerId ?? _playerGuid;
|
||||
_requestExternalContainer = requestExternalContainer;
|
||||
_auxiliaryAction = auxiliaryAction;
|
||||
_selectedObjectId = selectedObjectId ?? (() => 0u);
|
||||
|
|
@ -119,11 +125,20 @@ public sealed class ItemInteractionController : IDisposable
|
|||
_sendWield,
|
||||
sendPutItemInContainer,
|
||||
_toast,
|
||||
_systemMessage);
|
||||
_systemMessage,
|
||||
combatState,
|
||||
sendChangeCombatMode);
|
||||
}
|
||||
|
||||
public event Action? StateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Retail <c>CM_Item::SendNotice_ShowPendingInPlayer</c>: the inventory
|
||||
/// panel inserts a waiting projection before the pickup request is sent.
|
||||
/// The destination and placement are the same values sent on the wire.
|
||||
/// </summary>
|
||||
public event Action<uint, uint, int>? PendingBackpackPlacementRequested;
|
||||
|
||||
public uint PlayerGuid => _playerGuid();
|
||||
|
||||
public InteractionState InteractionState => _interactionState;
|
||||
|
|
@ -399,8 +414,18 @@ public sealed class ItemInteractionController : IDisposable
|
|||
switch (action.Kind)
|
||||
{
|
||||
case ItemPolicyActionKind.PlaceInBackpack:
|
||||
_placeInBackpack?.Invoke(action.ObjectId);
|
||||
acted |= _placeInBackpack is not null;
|
||||
if (_placeInBackpack is null)
|
||||
break;
|
||||
uint containerId = _backpackContainerId();
|
||||
if (containerId == 0u)
|
||||
containerId = _playerGuid();
|
||||
const int placement = 0;
|
||||
PendingBackpackPlacementRequested?.Invoke(
|
||||
action.ObjectId,
|
||||
containerId,
|
||||
placement);
|
||||
_placeInBackpack(action.ObjectId, containerId, placement);
|
||||
acted = true;
|
||||
break;
|
||||
case ItemPolicyActionKind.WieldRight:
|
||||
case ItemPolicyActionKind.WieldLeft:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue