mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
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:
parent
7c5d688c00
commit
06facc0060
6 changed files with 337 additions and 5 deletions
|
|
@ -933,13 +933,38 @@ public:
|
|||
enum class TradeStatus : uint8_t {
|
||||
None = 0, PendingIncoming, Open, Accepted, Complete
|
||||
};
|
||||
|
||||
static constexpr int TRADE_SLOT_COUNT = 6; // WoW has 6 normal trade slots + slot 6 for non-trade item
|
||||
|
||||
struct TradeSlot {
|
||||
uint32_t itemId = 0;
|
||||
uint32_t displayId = 0;
|
||||
uint32_t stackCount = 0;
|
||||
uint64_t itemGuid = 0;
|
||||
uint8_t bag = 0xFF; // 0xFF = not set
|
||||
uint8_t bagSlot = 0xFF;
|
||||
bool occupied = false;
|
||||
};
|
||||
|
||||
TradeStatus getTradeStatus() const { return tradeStatus_; }
|
||||
bool hasPendingTradeRequest() const { return tradeStatus_ == TradeStatus::PendingIncoming; }
|
||||
bool isTradeOpen() const { return tradeStatus_ == TradeStatus::Open || tradeStatus_ == TradeStatus::Accepted; }
|
||||
const std::string& getTradePeerName() const { return tradePeerName_; }
|
||||
|
||||
// My trade slots (what I'm offering)
|
||||
const std::array<TradeSlot, TRADE_SLOT_COUNT>& getMyTradeSlots() const { return myTradeSlots_; }
|
||||
// Peer's trade slots (what they're offering)
|
||||
const std::array<TradeSlot, TRADE_SLOT_COUNT>& getPeerTradeSlots() const { return peerTradeSlots_; }
|
||||
uint64_t getMyTradeGold() const { return myTradeGold_; }
|
||||
uint64_t getPeerTradeGold() const { return peerTradeGold_; }
|
||||
|
||||
void acceptTradeRequest(); // respond to incoming SMSG_TRADE_STATUS(1) with CMSG_BEGIN_TRADE
|
||||
void declineTradeRequest(); // respond with CMSG_CANCEL_TRADE
|
||||
void acceptTrade(); // lock in offer: CMSG_ACCEPT_TRADE
|
||||
void cancelTrade(); // CMSG_CANCEL_TRADE
|
||||
void setTradeItem(uint8_t tradeSlot, uint8_t bag, uint8_t bagSlot);
|
||||
void clearTradeItem(uint8_t tradeSlot);
|
||||
void setTradeGold(uint64_t copper);
|
||||
|
||||
// ---- Duel ----
|
||||
bool hasPendingDuelRequest() const { return pendingDuelRequest_; }
|
||||
|
|
@ -1653,6 +1678,8 @@ private:
|
|||
void handleQuestConfirmAccept(network::Packet& packet);
|
||||
void handleSummonRequest(network::Packet& packet);
|
||||
void handleTradeStatus(network::Packet& packet);
|
||||
void handleTradeStatusExtended(network::Packet& packet);
|
||||
void resetTradeState();
|
||||
void handleDuelRequested(network::Packet& packet);
|
||||
void handleDuelComplete(network::Packet& packet);
|
||||
void handleDuelWinner(network::Packet& packet);
|
||||
|
|
@ -2077,6 +2104,10 @@ private:
|
|||
TradeStatus tradeStatus_ = TradeStatus::None;
|
||||
uint64_t tradePeerGuid_= 0;
|
||||
std::string tradePeerName_;
|
||||
std::array<TradeSlot, TRADE_SLOT_COUNT> myTradeSlots_{};
|
||||
std::array<TradeSlot, TRADE_SLOT_COUNT> peerTradeSlots_{};
|
||||
uint64_t myTradeGold_ = 0;
|
||||
uint64_t peerTradeGold_ = 0;
|
||||
|
||||
// Duel state
|
||||
bool pendingDuelRequest_ = false;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ private:
|
|||
void renderDuelRequestPopup(game::GameHandler& gameHandler);
|
||||
void renderLootRollPopup(game::GameHandler& gameHandler);
|
||||
void renderTradeRequestPopup(game::GameHandler& gameHandler);
|
||||
void renderTradeWindow(game::GameHandler& gameHandler);
|
||||
void renderSummonRequestPopup(game::GameHandler& gameHandler);
|
||||
void renderSharedQuestPopup(game::GameHandler& gameHandler);
|
||||
void renderItemTextWindow(game::GameHandler& gameHandler);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue