feat(ui): port retail selected-stack quantity
Bind the authored stack count entry and horizontal slider to one Core split-quantity owner, preserve retail count-first naming and exact 1000-step rounding, refresh on stack changes, and consume the selected amount during merges. Conformance covers the production DAT fixture and retained pointer/focus paths. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
dc1649c493
commit
a20e5c68c7
19 changed files with 595 additions and 51 deletions
|
|
@ -61,6 +61,7 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
|
|||
private readonly Action<uint, uint, uint>? _sendStackableMerge;
|
||||
private readonly Action<uint, uint>? _notifyMergeAttempt;
|
||||
private readonly ItemInteractionController? _itemInteraction;
|
||||
private readonly StackSplitQuantityState? _stackSplitQuantity;
|
||||
private bool _disposed;
|
||||
|
||||
// ACE PropertyInt ids read by retail InqLoad (decomp 0x0058f130: InqInt(5)/InqInt(0xe6)).
|
||||
|
|
@ -85,7 +86,8 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
|
|||
Action<uint, uint, uint>? sendStackableMerge,
|
||||
Action<uint, uint>? notifyMergeAttempt,
|
||||
ItemInteractionController? itemInteraction,
|
||||
Action? onClose)
|
||||
Action? onClose,
|
||||
StackSplitQuantityState? stackSplitQuantity)
|
||||
{
|
||||
_objects = objects;
|
||||
_playerGuid = playerGuid;
|
||||
|
|
@ -98,6 +100,7 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
|
|||
_sendStackableMerge = sendStackableMerge;
|
||||
_notifyMergeAttempt = notifyMergeAttempt;
|
||||
_itemInteraction = itemInteraction;
|
||||
_stackSplitQuantity = stackSplitQuantity;
|
||||
_selection = selection ?? throw new ArgumentNullException(nameof(selection));
|
||||
|
||||
WindowChromeController.BindCloseButton(layout, onClose);
|
||||
|
|
@ -206,13 +209,14 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
|
|||
Action<uint, uint, uint>? sendStackableMerge = null,
|
||||
Action<uint, uint>? notifyMergeAttempt = null,
|
||||
ItemInteractionController? itemInteraction = null,
|
||||
Action? onClose = null)
|
||||
Action? onClose = null,
|
||||
StackSplitQuantityState? stackSplitQuantity = null)
|
||||
=> new InventoryController(layout, objects, playerGuid, iconIds, strength, selection,
|
||||
ownerName, datFont,
|
||||
contentsEmptySprite, sideBagEmptySprite, mainPackEmptySprite,
|
||||
sendUse, sendNoLongerViewing, sendPutItemInContainer,
|
||||
sendStackableMerge, notifyMergeAttempt, itemInteraction,
|
||||
onClose);
|
||||
onClose, stackSplitQuantity);
|
||||
|
||||
private void OnObjectChanged(ClientObject o) { if (Concerns(o)) Populate(); }
|
||||
private void OnObjectRemoved(ClientObject o)
|
||||
|
|
@ -463,6 +467,10 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
|
|||
|| _objects.Get(targetId) is not { } target)
|
||||
return false;
|
||||
|
||||
int requestedAmount = _selection.SelectedObjectId == sourceId
|
||||
&& _stackSplitQuantity is not null
|
||||
? (int)Math.Min(_stackSplitQuantity.Value, int.MaxValue)
|
||||
: Math.Max(1, source.StackSize);
|
||||
StackMergePlan? plan = StackMergePlanner.Plan(
|
||||
new StackMergeItem(
|
||||
source.ObjectId,
|
||||
|
|
@ -477,7 +485,7 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
|
|||
target.StackSizeMax,
|
||||
target.TradeState),
|
||||
_itemInteraction?.CanMakeInventoryRequest ?? true,
|
||||
requestedAmount: Math.Max(1, source.StackSize));
|
||||
requestedAmount);
|
||||
if (plan is not { } merge)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue