feat(ui): complete retail quick-slot input

Port global toolbar use/select/create actions, migrate the collapsed Ctrl-number bindings, and route them through a focused retained-UI controller. Preserve shortcut aliases as aliases across inventory and paperdoll drops with retail's neutral/accept/reject drag states, preventing physical item moves such as unwielding an equipped helmet.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-11 08:59:49 +02:00
parent 6fcc510d5d
commit e65119f0c6
24 changed files with 650 additions and 69 deletions

View file

@ -259,11 +259,18 @@ public sealed class PaperdollController : IItemListDragHandler, IRetainedPanelCo
/// <summary>Accept iff the dragged item can be worn here (its ValidLocations intersects the slot mask).
/// Retail: gmPaperDollUI::OnItemListDragOver (decomp 174302).</summary>
public bool OnDragOver(UiItemList targetList, UiItemSlot targetCell, ItemDragPayload payload)
public ItemDragAcceptance OnDragOver(UiItemList targetList, UiItemSlot targetCell, ItemDragPayload payload)
{
// gmPaperDollUI::OnItemListDragOver @ 0x004A4270 ignores shortcut
// aliases through its (DropItemFlags & 0xE) == 0 gate.
if (payload.SourceKind == ItemDragSource.ShortcutBar)
return ItemDragAcceptance.None;
var item = _objects.Get(payload.ObjId);
if (item is null) return false;
return (item.ValidLocations & MaskFor(targetList)) != EquipMask.None;
if (item is null)
return ItemDragAcceptance.Reject;
return (item.ValidLocations & MaskFor(targetList)) != EquipMask.None
? ItemDragAcceptance.Accept
: ItemDragAcceptance.Reject;
}
/// <summary>Wield the dropped item: optimistic local equip (instant) + GetAndWieldItem 0x001A.
@ -271,6 +278,10 @@ public sealed class PaperdollController : IItemListDragHandler, IRetainedPanelCo
/// chosen finger). Retail: gmPaperDollUI HandleDropRelease → GetAndWieldItem.</summary>
public void HandleDropRelease(UiItemList targetList, UiItemSlot targetCell, ItemDragPayload payload)
{
// gmPaperDollUI::HandleDropRelease @ 0x004A4D80 applies the same flag
// gate before accepting/wielding the physical object.
if (payload.SourceKind == ItemDragSource.ShortcutBar)
return;
var item = _objects.Get(payload.ObjId);
if (item is null) return;
EquipMask wieldMask = ItemEquipRules.ResolvePaperdollDropWieldMask(item, MaskFor(targetList));