fix(ui): restore retail vitals and window interactions
All checks were successful
CI / linux-portable (push) Successful in 3m16s
CI / windows-gate (push) Successful in 5m41s
CI / release (push) Successful in 2m5s

This commit is contained in:
Erik 2026-08-20 13:26:35 +02:00
parent 4d84456c21
commit 1bd2b30291
36 changed files with 1462 additions and 86 deletions

View file

@ -571,8 +571,10 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
_selection.Select(payload.ObjId, SelectionChangeSource.Inventory);
}
/// <summary>Advisory neutral/accept/reject overlay. Shortcut aliases stay neutral; physical grid
/// drops accept; a side-bag/main-pack drop rejects only when that container is known full.</summary>
/// <summary>Advisory neutral/accept/reject overlay. Shortcut aliases stay neutral. Retail keeps
/// loose-item slots and contained-container slots as different drag classes: a pack is rejected
/// by the contents grid and accepted by the player's pack-slot list, while an ordinary item is
/// accepted by the contents grid or by a non-full occupied pack.</summary>
public ItemDragAcceptance OnDragOver(UiItemList targetList, UiItemSlot targetCell, ItemDragPayload payload)
{
// UIElement_ItemList::ItemList_DragOver @ 0x004E3400 only evaluates
@ -583,10 +585,22 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
return ItemDragAcceptance.None;
if (payload.ObjId == 0)
return ItemDragAcceptance.Reject;
bool sourceIsBag = _objects.Get(payload.ObjId) is { } source && IsBag(source);
if (targetList == _contentsGrid)
return ItemDragAcceptance.Accept;
return sourceIsBag
? ItemDragAcceptance.Reject
: ItemDragAcceptance.Accept;
if (targetList == _containerList || targetList == _topContainer)
{
// UIElement_ItemList::ItemList_DragOver @0x004E3400 checks the
// dragged object's container flag before interpreting this list.
// A container drag addresses the player's contained-container
// list itself; an empty authored slot is therefore a valid pack
// destination rather than "no target".
if (sourceIsBag)
return targetCell.ItemId == payload.ObjId
? ItemDragAcceptance.Reject
: ItemDragAcceptance.Accept;
if (targetCell.ItemId == 0 || targetCell.ItemId == payload.ObjId)
return ItemDragAcceptance.Reject;
return IsContainerFull(targetCell.ItemId)
@ -610,6 +624,12 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
uint item = payload.ObjId;
if (item == 0) return;
// DropReleased is still delivered to the list after a reject overlay;
// pin the release to the same retail policy instead of relying on the
// advisory color alone.
if (OnDragOver(targetList, targetCell, payload) != ItemDragAcceptance.Accept)
return;
// UIElement_ItemList::AcceptDragObject @ 0x004E4250 rejects every
// release while m_pendingItem exists, before merge, split, or ordinary
// placement. ItemList_DragOver has no equivalent gate, so hover may
@ -635,6 +655,7 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
&& TryMergeStacks(item, targetCell.ItemId))
return;
bool sourceIsBag = _objects.Get(item) is { } dragged && IsBag(dragged);
uint container; int placement;
if (targetList == _contentsGrid)
{
@ -645,10 +666,23 @@ public sealed class InventoryController : IItemListDragHandler, IRetainedPanelCo
}
else if (targetList == _containerList || targetList == _topContainer)
{
if (targetCell.ItemId == 0 || targetCell.ItemId == item) return;
container = targetCell.ItemId; // the bag / main pack
if (IsContainerFull(container)) return; // red already shown
placement = _objects.GetContents(container).Count; // append into it
if (sourceIsBag)
{
// A pack dropped on the pack selector is inserted into the
// player's contained-container list at that selector slot.
// Sending the open item container here makes ACE correctly
// reject the pickup with "can't be picked up".
container = _playerGuid();
if (container == 0u) return;
placement = Math.Max(0, targetCell.SlotIndex);
}
else
{
if (targetCell.ItemId == 0 || targetCell.ItemId == item) return;
container = targetCell.ItemId; // the bag / main pack
if (IsContainerFull(container)) return; // red already shown
placement = _objects.GetContents(container).Count; // append into it
}
}
else return;