Implement basic trade request/accept/decline flow

- Parse SMSG_TRADE_STATUS for all 20+ status codes: incoming request,
  open/cancel/complete/accept notifications, error conditions (too far,
  wrong faction, stunned, dead, trial account, etc.)
- SMSG_TRADE_STATUS_EXTENDED consumed via shared handler (no full item
  window yet; state tracking sufficient for accept/decline flow)
- Add acceptTradeRequest() (CMSG_BEGIN_TRADE), declineTradeRequest(),
  acceptTrade() (CMSG_ACCEPT_TRADE), cancelTrade() (CMSG_CANCEL_TRADE)
- Add BeginTradePacket, CancelTradePacket, AcceptTradePacket builders
- Add renderTradeRequestPopup(): shows "X wants to trade" with
  Accept/Decline buttons when tradeStatus_ == PendingIncoming
- TradeStatus enum tracks None/PendingIncoming/Open/Accepted/Complete
This commit is contained in:
Kelsi 2026-03-09 14:05:42 -07:00
parent b4f6ca2ca7
commit f369fe9c6e
6 changed files with 178 additions and 0 deletions

View file

@ -707,6 +707,18 @@ public:
bool hasPendingGroupInvite() const { return pendingGroupInvite; }
const std::string& getPendingInviterName() const { return pendingInviterName; }
// ---- Trade ----
enum class TradeStatus : uint8_t {
None = 0, PendingIncoming, Open, Accepted, Complete
};
TradeStatus getTradeStatus() const { return tradeStatus_; }
bool hasPendingTradeRequest() const { return tradeStatus_ == TradeStatus::PendingIncoming; }
const std::string& getTradePeerName() const { return tradePeerName_; }
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
// ---- Duel ----
bool hasPendingDuelRequest() const { return pendingDuelRequest_; }
const std::string& getDuelChallengerName() const { return duelChallengerName_; }
@ -1268,6 +1280,7 @@ private:
// ---- Instance lockout handler ----
void handleRaidInstanceInfo(network::Packet& packet);
void handleTradeStatus(network::Packet& packet);
void handleDuelRequested(network::Packet& packet);
void handleDuelComplete(network::Packet& packet);
void handleDuelWinner(network::Packet& packet);
@ -1625,6 +1638,11 @@ private:
bool pendingGroupInvite = false;
std::string pendingInviterName;
// Trade state
TradeStatus tradeStatus_ = TradeStatus::None;
uint64_t tradePeerGuid_= 0;
std::string tradePeerName_;
// Duel state
bool pendingDuelRequest_ = false;
uint64_t duelChallengerGuid_= 0;

View file

@ -1326,6 +1326,24 @@ public:
static network::Packet build(uint64_t targetGuid);
};
/** CMSG_BEGIN_TRADE packet builder (no payload — accepts incoming trade request) */
class BeginTradePacket {
public:
static network::Packet build();
};
/** CMSG_CANCEL_TRADE packet builder (no payload) */
class CancelTradePacket {
public:
static network::Packet build();
};
/** CMSG_ACCEPT_TRADE packet builder (no payload — lock in current offer) */
class AcceptTradePacket {
public:
static network::Packet build();
};
/** CMSG_ATTACKSWING packet builder */
class AttackSwingPacket {
public: