feat: implement trade window UI with item slots and gold offering

Previously trade only showed an accept/decline popup with no way to
actually offer items or gold. This commit adds the complete trade flow:

Packets:
- CMSG_SET_TRADE_ITEM (tradeSlot, bag, bagSlot) — add item to slot
- CMSG_CLEAR_TRADE_ITEM (tradeSlot) — remove item from slot
- CMSG_SET_TRADE_GOLD (uint64 copper) — set gold offered
- CMSG_UNACCEPT_TRADE — unaccept without cancelling
- SMSG_TRADE_STATUS_EXTENDED parser — updates trade slot/gold state

State:
- TradeSlot struct: itemId, displayId, stackCount, bag, bagSlot
- myTradeSlots_/peerTradeSlots_ arrays (6 slots each)
- myTradeGold_/peerTradeGold_ (copper)
- resetTradeState() helper clears all state on cancel/complete/close

UI (renderTradeWindow):
- Two-column layout: my offer | peer offer
- Each column shows 6 item slots with item names
- Double-click own slot to remove; right-click empty slot to open
  backpack picker popup
- Gold input field (copper, Enter to set)
- Accept Trade / Cancel buttons
- Window close button triggers cancel trade
This commit is contained in:
Kelsi 2026-03-11 00:44:07 -07:00
parent 7c5d688c00
commit 06facc0060
6 changed files with 337 additions and 5 deletions

View file

@ -1356,6 +1356,33 @@ public:
static network::Packet build();
};
/** CMSG_SET_TRADE_ITEM packet builder (tradeSlot, bag, bagSlot) */
class SetTradeItemPacket {
public:
// tradeSlot: 0-5 (normal) or 6 (backpack money-only slot)
// bag: 255 = main backpack, 19-22 = bag slots
// bagSlot: slot within bag
static network::Packet build(uint8_t tradeSlot, uint8_t bag, uint8_t bagSlot);
};
/** CMSG_CLEAR_TRADE_ITEM packet builder (remove item from trade slot) */
class ClearTradeItemPacket {
public:
static network::Packet build(uint8_t tradeSlot);
};
/** CMSG_SET_TRADE_GOLD packet builder (gold offered, in copper) */
class SetTradeGoldPacket {
public:
static network::Packet build(uint64_t copper);
};
/** CMSG_UNACCEPT_TRADE packet builder (unaccept without cancelling) */
class UnacceptTradePacket {
public:
static network::Packet build();
};
/** CMSG_ATTACKSWING packet builder */
class AttackSwingPacket {
public: