diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 27 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 32 | ||||
-rw-r--r-- | src/server/game/Handlers/TradeHandler.cpp | 361 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 58 | ||||
-rw-r--r-- | src/server/game/Server/Packets/TradePackets.cpp | 129 | ||||
-rw-r--r-- | src/server/game/Server/Packets/TradePackets.h | 187 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 24 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 33 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 10 |
9 files changed, 511 insertions, 350 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1730b1d2eee..5968c7453c3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -97,6 +97,7 @@ #include "ItemPackets.h" #include "QuestPackets.h" #include "LootPackets.h" +#include "TradePackets.h" #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) @@ -315,6 +316,8 @@ void TradeData::SetItem(TradeSlots slot, Item* item) SetAccepted(false); GetTraderData()->SetAccepted(false); + UpdateServerStateIndex(); + Update(); // need remove possible trader spell applied to changed item @@ -338,6 +341,8 @@ void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= NULL*/) SetAccepted(false); GetTraderData()->SetAccepted(false); + UpdateServerStateIndex(); + Update(true); // send spell info to item owner Update(false); // send spell info to caster self } @@ -349,9 +354,9 @@ void TradeData::SetMoney(uint64 money) if (!m_player->HasEnoughMoney(money)) { - TradeStatusInfo info; - info.Status = TRADE_STATUS_CLOSE_WINDOW; - info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY; + WorldPackets::Trade::TradeStatus info; + info.Status = TRADE_STATUS_FAILED; + info.BagResult = EQUIP_ERR_NOT_ENOUGH_MONEY; m_player->GetSession()->SendTradeStatus(info); return; } @@ -361,6 +366,8 @@ void TradeData::SetMoney(uint64 money) SetAccepted(false); GetTraderData()->SetAccepted(false); + UpdateServerStateIndex(); + Update(true); } @@ -378,8 +385,8 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/) if (!state) { - TradeStatusInfo info; - info.Status = TRADE_STATUS_BACK_TO_TRADE; + WorldPackets::Trade::TradeStatus info; + info.Status = TRADE_STATUS_UNACCEPTED; if (crosssend) m_trader->GetSession()->SendTradeStatus(info); else @@ -10157,7 +10164,7 @@ bool Player::HasItemOrGemWithLimitCategoryEquipped(uint32 limitCategory, uint32 return false; } -InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count /*= NULL*/, uint32* itemLimitCategory /*= NULL*/) const +InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count /*= nullptr*/, uint32* offendingItemId /*= nullptr*/) const { ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(entry); if (!pProto) @@ -10203,8 +10210,8 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item { if (no_space_count) *no_space_count = count + curcount - limitEntry->Quantity; - if (itemLimitCategory) - *itemLimitCategory = pProto->GetItemLimitCategory(); + if (offendingItemId) + *offendingItemId = pProto->GetId(); return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS; } } @@ -10735,7 +10742,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des } ////////////////////////////////////////////////////////////////////////// -InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimitCategory) const +InventoryResult Player::CanStoreItems(Item** items, int count, uint32* offendingItemId) const { Item* item2; @@ -10789,7 +10796,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit ItemTemplate const* pBagProto; // item is 'one item only' - InventoryResult res = CanTakeMoreSimilarItems(item, itemLimitCategory); + InventoryResult res = CanTakeMoreSimilarItems(item, offendingItemId); if (res != EQUIP_ERR_OK) return res; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 3f94fc23fa9..83627ede64f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1148,19 +1148,6 @@ struct BGData bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; } }; -struct TradeStatusInfo -{ - TradeStatusInfo() : Status(TRADE_STATUS_BUSY), TraderGuid(), Result(EQUIP_ERR_OK), - IsTargetResult(false), ItemLimitCategoryId(0), Slot(0) { } - - TradeStatus Status; - ObjectGuid TraderGuid; - InventoryResult Result; - bool IsTargetResult; - uint32 ItemLimitCategoryId; - uint8 Slot; -}; - struct VoidStorageItem { VoidStorageItem() @@ -1192,7 +1179,7 @@ class TradeData public: // constructors TradeData(Player* player, Player* trader) : m_player(player), m_trader(trader), m_accepted(false), m_acceptProccess(false), - m_money(0), m_spell(0), m_spellCastItem() { } + m_money(0), m_spell(0), m_spellCastItem(), m_clientStateIndex(1), m_serverStateIndex(1) { } Player* GetTrader() const { return m_trader; } TradeData* GetTraderData() const; @@ -1217,6 +1204,12 @@ class TradeData bool IsInAcceptProcess() const { return m_acceptProccess; } void SetInAcceptProcess(bool state) { m_acceptProccess = state; } + uint32 GetClientStateIndex() const { return m_clientStateIndex; } + void UpdateClientStateIndex() { ++m_clientStateIndex; } + + uint32 GetServerStateIndex() const { return m_serverStateIndex; } + void UpdateServerStateIndex() { m_serverStateIndex = rand32(); } + private: // internal functions void Update(bool for_trader = true); @@ -1235,6 +1228,9 @@ class TradeData ObjectGuid m_spellCastItem; // applied spell cast by item use ObjectGuid m_items[TRADE_SLOT_COUNT]; // traded items from m_player side including non-traded slot + + uint32 m_clientStateIndex; + uint32 m_serverStateIndex; }; struct ResurrectionData @@ -1480,11 +1476,11 @@ class Player : public Unit, public GridObject<Player> bool CanNoReagentCast(SpellInfo const* spellInfo) const; bool HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_slot = NULL_SLOT) const; bool HasItemOrGemWithLimitCategoryEquipped(uint32 limitCategory, uint32 count, uint8 except_slot = NULL_SLOT) const; - InventoryResult CanTakeMoreSimilarItems(Item* pItem, uint32* itemLimitCategory = NULL) const { return CanTakeMoreSimilarItems(pItem->GetEntry(), pItem->GetCount(), pItem, NULL, itemLimitCategory); } - InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count, uint32* itemLimitCategory = NULL) const { return CanTakeMoreSimilarItems(entry, count, NULL, NULL, itemLimitCategory); } + InventoryResult CanTakeMoreSimilarItems(Item* pItem, uint32* offendingItemId = nullptr) const { return CanTakeMoreSimilarItems(pItem->GetEntry(), pItem->GetCount(), pItem, nullptr, offendingItemId); } + InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count, uint32* offendingItemId = nullptr) const { return CanTakeMoreSimilarItems(entry, count, nullptr, nullptr, offendingItemId); } InventoryResult CanStoreNewItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 item, uint32 count, uint32* no_space_count = NULL) const; InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, Item* pItem, bool swap = false) const; - InventoryResult CanStoreItems(Item** items, int count, uint32* itemLimitCategory) const; + InventoryResult CanStoreItems(Item** items, int count, uint32* offendingItemId) const; InventoryResult CanEquipNewItem(uint8 slot, uint16& dest, uint32 item, bool swap) const; InventoryResult CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading = true) const; @@ -1508,7 +1504,7 @@ class Player : public Unit, public GridObject<Player> void AutoStoreLoot(uint32 loot_id, LootStore const& store, bool broadcast = false) { AutoStoreLoot(NULL_BAG, NULL_SLOT, loot_id, store, broadcast); } void StoreLootItem(uint8 lootSlot, Loot* loot); - InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL, uint32* itemLimitCategory = NULL) const; + InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = nullptr, uint32* offendingItemId = nullptr) const; InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item* pItem = NULL, bool swap = false, uint32* no_space_count = NULL) const; void AddRefundReference(ObjectGuid it); diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index b06f89797cf..517d02f852a 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -31,65 +31,19 @@ #include "AccountMgr.h" #include "TradePackets.h" -void WorldSession::SendTradeStatus(TradeStatusInfo const& info) +void WorldSession::SendTradeStatus(WorldPackets::Trade::TradeStatus& info) { - Player* trader = GetPlayer()->GetTrader(); - - WorldPacket data(SMSG_TRADE_STATUS, 13); - data.WriteBit(trader ? (trader->GetSession()->GetBattlenetAccountId() == GetBattlenetAccountId()) : 0); // IsSameBnetAccount, used for trading heirlooms and other battle.net bound items with your other accounts - data.WriteBits(info.Status, 5); - - switch (info.Status) - { - case TRADE_STATUS_BEGIN_TRADE: - data.WriteBit(info.TraderGuid[2]); - data.WriteBit(info.TraderGuid[4]); - data.WriteBit(info.TraderGuid[6]); - data.WriteBit(info.TraderGuid[0]); - data.WriteBit(info.TraderGuid[1]); - data.WriteBit(info.TraderGuid[3]); - data.WriteBit(info.TraderGuid[7]); - data.WriteBit(info.TraderGuid[5]); - - data.WriteByteSeq(info.TraderGuid[4]); - data.WriteByteSeq(info.TraderGuid[1]); - data.WriteByteSeq(info.TraderGuid[2]); - data.WriteByteSeq(info.TraderGuid[3]); - data.WriteByteSeq(info.TraderGuid[0]); - data.WriteByteSeq(info.TraderGuid[7]); - data.WriteByteSeq(info.TraderGuid[6]); - data.WriteByteSeq(info.TraderGuid[5]); - break; - case TRADE_STATUS_OPEN_WINDOW: - data << uint32(0); // CGTradeInfo::m_tradeID - break; - case TRADE_STATUS_CLOSE_WINDOW: - data.WriteBit(info.IsTargetResult); // bool isTargetError; used for: EQUIP_ERR_BAG_FULL, EQUIP_ERR_CANT_CARRY_MORE_OF_THIS, EQUIP_ERR_MISSING_REAGENT, EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED - data << uint32(info.Result); // InventoryResult - data << uint32(info.ItemLimitCategoryId); // ItemLimitCategory.dbc entry - break; - case TRADE_STATUS_WRONG_REALM: - case TRADE_STATUS_NOT_ON_TAPLIST: - data << uint8(info.Slot); // Trade slot; -1 here clears CGTradeInfo::m_tradeMoney - break; - case TRADE_STATUS_CURRENCY: // Not implemented - case TRADE_STATUS_CURRENCY_NOT_TRADABLE: // Not implemented - // Blizzard never implemented these, you can only trade currency with the field9 & 1 in CurrencyTypes.DBC, and only two test currencies have that flag - data << uint32(0); // Trading Currency Id - data << uint32(0); // Trading Currency Amount - default: - data.FlushBits(); - break; - } - - SendPacket(&data); + info.Clear(); // reuse packet + Player* trader = _player->GetTrader(); + info.PartnerIsSameBnetAccount = trader && trader->GetSession()->GetBattlenetAccountId() == GetBattlenetAccountId(); + SendPacket(info.Write()); } -void WorldSession::HandleIgnoreTradeOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleIgnoreTradeOpcode(WorldPackets::Trade::IgnoreTrade& /*ignoreTrade*/) { } -void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleBusyTradeOpcode(WorldPackets::Trade::BusyTrade& /*busyTrade*/) { } @@ -97,106 +51,44 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/) { TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData(); - ByteBuffer itemData(7*2 + 7*4 + 3*4 + 3*4 + 1); - - uint8 count = 0; - for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) - if (view_trade->GetItem(TradeSlots(i))) - ++count; - - WorldPacket data(SMSG_TRADE_UPDATED, 4*6 + 8 + 1 + 3 + count * 70); - data << uint32(0); // CGTradeInfo::m_tradeID - data << uint32(0); // unk 2 - data << uint64(view_trade->GetMoney()); // trader gold - data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item - data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases - data << uint32(0); // unk 5 - data << uint8(trader_data); // 1 means traders data, 0 means own - data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases - data.WriteBits(count, 22); + WorldPackets::Trade::TradeUpdated tradeUpdated; + tradeUpdated.WhichPlayer = trader_data; + tradeUpdated.ClientStateIndex = view_trade->GetClientStateIndex(); + tradeUpdated.CurrentStateIndex = view_trade->GetServerStateIndex(); + tradeUpdated.Gold = view_trade->GetMoney(); + tradeUpdated.ProposedEnchantment = view_trade->GetSpell(); for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) { - Item* item = view_trade->GetItem(TradeSlots(i)); - if (!item) - continue; - - ObjectGuid giftCreatorGuid = item->GetGuidValue(ITEM_FIELD_GIFTCREATOR); - ObjectGuid creatorGuid = item->GetGuidValue(ITEM_FIELD_CREATOR); - - data.WriteBit(giftCreatorGuid[7]); - data.WriteBit(giftCreatorGuid[1]); - bool notWrapped = data.WriteBit(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)); - data.WriteBit(giftCreatorGuid[3]); - - if (notWrapped) + if (Item* item = view_trade->GetItem(TradeSlots(i))) { - data.WriteBit(creatorGuid[7]); - data.WriteBit(creatorGuid[1]); - data.WriteBit(creatorGuid[4]); - data.WriteBit(creatorGuid[6]); - data.WriteBit(creatorGuid[2]); - data.WriteBit(creatorGuid[3]); - data.WriteBit(creatorGuid[5]); - data.WriteBit(item->GetTemplate()->GetLockID() != 0); - data.WriteBit(creatorGuid[0]); - - itemData.WriteByteSeq(creatorGuid[1]); - - itemData << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)); - for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS /*3*/; ++enchant_slot) - itemData << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); - itemData << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); - - itemData.WriteByteSeq(creatorGuid[6]); - itemData.WriteByteSeq(creatorGuid[2]); - itemData.WriteByteSeq(creatorGuid[7]); - itemData.WriteByteSeq(creatorGuid[4]); - - itemData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY)); - itemData << uint32(item->GetItemRandomPropertyId()); - - itemData.WriteByteSeq(creatorGuid[3]); - - itemData << uint32(0); // unk7 - - itemData.WriteByteSeq(creatorGuid[0]); - - itemData << uint32(item->GetSpellCharges()); - itemData << uint32(item->GetItemSuffixFactor()); + WorldPackets::Trade::TradeUpdated::TradeItem tradeItem; + tradeItem.Slot = i; + tradeItem.EntryID = item->GetEntry(); + tradeItem.StackCount = item->GetCount(); + tradeItem.GiftCreator = item->GetGuidValue(ITEM_FIELD_GIFTCREATOR); + if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + { + WorldPackets::Trade::TradeUpdated::UnwrappedTradeItem* unwrappedItem = &tradeItem.Unwrapped.Value; + unwrappedItem->Item.Initalize(item); + unwrappedItem->EnchantID = item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); + unwrappedItem->OnUseEnchantmentID = item->GetEnchantmentId(USE_ENCHANTMENT_SLOT); + unwrappedItem->Creator = item->GetGuidValue(ITEM_FIELD_CREATOR); + unwrappedItem->Charges = item->GetSpellCharges(); + unwrappedItem->Lock = item->GetTemplate()->GetLockID() && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED); + unwrappedItem->MaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); + unwrappedItem->Durability = item->GetUInt32Value(ITEM_FIELD_DURABILITY); + for (uint32 s = SOCK_ENCHANTMENT_SLOT; s < MAX_GEM_SOCKETS; ++s) + unwrappedItem->SocketEnchant[s] = item->GetEnchantmentId(EnchantmentSlot(s + SOCK_ENCHANTMENT_SLOT)); + + tradeItem.Unwrapped.HasValue = true; + } - itemData.WriteByteSeq(creatorGuid[5]); + tradeUpdated.Items.push_back(tradeItem); } - - data.WriteBit(giftCreatorGuid[6]); - data.WriteBit(giftCreatorGuid[4]); - data.WriteBit(giftCreatorGuid[2]); - data.WriteBit(giftCreatorGuid[0]); - data.WriteBit(giftCreatorGuid[5]); - - itemData.WriteByteSeq(giftCreatorGuid[6]); - itemData.WriteByteSeq(giftCreatorGuid[1]); - itemData.WriteByteSeq(giftCreatorGuid[7]); - itemData.WriteByteSeq(giftCreatorGuid[4]); - - itemData << uint32(item->GetTemplate()->GetId()); - - itemData.WriteByteSeq(giftCreatorGuid[0]); - - itemData << uint32(item->GetCount()); - - itemData.WriteByteSeq(giftCreatorGuid[5]); - - itemData << uint8(i); - - itemData.WriteByteSeq(giftCreatorGuid[2]); - itemData.WriteByteSeq(giftCreatorGuid[3]); } - data.FlushBits(); - data.append(itemData); - - SendPacket(&data); + SendPacket(tradeUpdated.Write()); } //============================================================== @@ -328,7 +220,7 @@ static void clearAcceptTradeMode(Item* *myItems, Item* *hisItems) } } -void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleAcceptTradeOpcode(WorldPackets::Trade::AcceptTrade& acceptTrade) { TradeData* my_trade = _player->m_trade; if (!my_trade) @@ -346,10 +238,18 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) // set before checks for propertly undo at problems (it already set in to client) my_trade->SetAccepted(true); - TradeStatusInfo info; + WorldPackets::Trade::TradeStatus info; + if (his_trade->GetServerStateIndex() != acceptTrade.StateIndex) + { + info.Status = TRADE_STATUS_STATE_CHANGED; + SendTradeStatus(info); + my_trade->SetAccepted(false); + return; + } + if (!_player->IsWithinDistInMap(trader, TRADE_DISTANCE, false)) { - info.Status = TRADE_STATUS_TARGET_TO_FAR; + info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); my_trade->SetAccepted(false); return; @@ -358,8 +258,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) // not accept case incorrect money amount if (!_player->HasEnoughMoney(my_trade->GetMoney())) { - info.Status = TRADE_STATUS_CLOSE_WINDOW; - info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY; + info.Status = TRADE_STATUS_FAILED; + info.BagResult = EQUIP_ERR_NOT_ENOUGH_MONEY; SendTradeStatus(info); my_trade->SetAccepted(false, true); return; @@ -368,8 +268,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) // not accept case incorrect money amount if (!trader->HasEnoughMoney(his_trade->GetMoney())) { - info.Status = TRADE_STATUS_CLOSE_WINDOW; - info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY; + info.Status = TRADE_STATUS_FAILED; + info.BagResult = EQUIP_ERR_NOT_ENOUGH_MONEY; trader->GetSession()->SendTradeStatus(info); his_trade->SetAccepted(false, true); return; @@ -377,8 +277,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) if (_player->GetMoney() >= uint64(MAX_MONEY_AMOUNT) - his_trade->GetMoney()) { - info.Status = TRADE_STATUS_CLOSE_WINDOW; - info.Result = EQUIP_ERR_TOO_MUCH_GOLD; + info.Status = TRADE_STATUS_FAILED; + info.BagResult = EQUIP_ERR_TOO_MUCH_GOLD; SendTradeStatus(info); my_trade->SetAccepted(false, true); return; @@ -386,8 +286,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) if (trader->GetMoney() >= uint64(MAX_MONEY_AMOUNT) - my_trade->GetMoney()) { - info.Status = TRADE_STATUS_CLOSE_WINDOW; - info.Result = EQUIP_ERR_TOO_MUCH_GOLD; + info.Status = TRADE_STATUS_FAILED; + info.BagResult = EQUIP_ERR_TOO_MUCH_GOLD; trader->GetSession()->SendTradeStatus(info); his_trade->SetAccepted(false, true); return; @@ -400,15 +300,15 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) { if (!item->CanBeTraded(false, true)) { - info.Status = TRADE_STATUS_TRADE_CANCELED; + info.Status = TRADE_STATUS_CANCELLED; SendTradeStatus(info); return; } if (item->IsBindedNotWith(trader)) { - info.Status = TRADE_STATUS_CLOSE_WINDOW; - info.Result = EQUIP_ERR_TRADE_BOUND_ITEM; + info.Status = TRADE_STATUS_FAILED; + info.BagResult = EQUIP_ERR_TRADE_BOUND_ITEM; SendTradeStatus(info); return; } @@ -418,7 +318,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) { if (!item->CanBeTraded(false, true)) { - info.Status = TRADE_STATUS_TRADE_CANCELED; + info.Status = TRADE_STATUS_CANCELLED; SendTradeStatus(info); return; } @@ -514,36 +414,36 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) } // inform partner client - info.Status = TRADE_STATUS_TRADE_ACCEPT; + info.Status = TRADE_STATUS_ACCEPTED; trader->GetSession()->SendTradeStatus(info); // test if item will fit in each inventory - TradeStatusInfo myCanCompleteInfo, hisCanCompleteInfo; - hisCanCompleteInfo.Result = trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT, &hisCanCompleteInfo.ItemLimitCategoryId); - myCanCompleteInfo.Result = _player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT, &myCanCompleteInfo.ItemLimitCategoryId); + WorldPackets::Trade::TradeStatus myCanCompleteInfo, hisCanCompleteInfo; + hisCanCompleteInfo.BagResult = trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT, &hisCanCompleteInfo.ItemID); + myCanCompleteInfo.BagResult = _player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT, &myCanCompleteInfo.ItemID); clearAcceptTradeMode(myItems, hisItems); // in case of missing space report error - if (myCanCompleteInfo.Result != EQUIP_ERR_OK) + if (myCanCompleteInfo.BagResult != EQUIP_ERR_OK) { clearAcceptTradeMode(my_trade, his_trade); - myCanCompleteInfo.Status = TRADE_STATUS_CLOSE_WINDOW; + myCanCompleteInfo.Status = TRADE_STATUS_FAILED; trader->GetSession()->SendTradeStatus(myCanCompleteInfo); - myCanCompleteInfo.IsTargetResult = true; + myCanCompleteInfo.FailureForYou = true; SendTradeStatus(myCanCompleteInfo); my_trade->SetAccepted(false); his_trade->SetAccepted(false); return; } - else if (hisCanCompleteInfo.Result != EQUIP_ERR_OK) + else if (hisCanCompleteInfo.BagResult != EQUIP_ERR_OK) { clearAcceptTradeMode(my_trade, his_trade); - hisCanCompleteInfo.Status = TRADE_STATUS_CLOSE_WINDOW; + hisCanCompleteInfo.Status = TRADE_STATUS_FAILED; SendTradeStatus(hisCanCompleteInfo); - hisCanCompleteInfo.IsTargetResult = true; + hisCanCompleteInfo.FailureForYou = true; trader->GetSession()->SendTradeStatus(hisCanCompleteInfo); my_trade->SetAccepted(false); his_trade->SetAccepted(false); @@ -613,18 +513,18 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) trader->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); - info.Status = TRADE_STATUS_TRADE_COMPLETE; + info.Status = TRADE_STATUS_COMPLETE; trader->GetSession()->SendTradeStatus(info); SendTradeStatus(info); } else { - info.Status = TRADE_STATUS_TRADE_ACCEPT; + info.Status = TRADE_STATUS_ACCEPTED; trader->GetSession()->SendTradeStatus(info); } } -void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleUnacceptTradeOpcode(WorldPackets::Trade::UnacceptTrade& /*unacceptTrade*/) { TradeData* my_trade = _player->GetTradeData(); if (!my_trade) @@ -633,14 +533,14 @@ void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/) my_trade->SetAccepted(false, true); } -void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleBeginTradeOpcode(WorldPackets::Trade::BeginTrade& /*beginTrade*/) { TradeData* my_trade = _player->m_trade; if (!my_trade) return; - TradeStatusInfo info; - info.Status = TRADE_STATUS_OPEN_WINDOW; + WorldPackets::Trade::TradeStatus info; + info.Status = TRADE_STATUS_INITIATED; my_trade->GetTrader()->GetSession()->SendTradeStatus(info); SendTradeStatus(info); } @@ -650,8 +550,8 @@ void WorldSession::SendCancelTrade() if (PlayerRecentlyLoggedOut() || PlayerLogout()) return; - TradeStatusInfo info; - info.Status = TRADE_STATUS_TRADE_CANCELED; + WorldPackets::Trade::TradeStatus info; + info.Status = TRADE_STATUS_CANCELLED; SendTradeStatus(info); } @@ -662,56 +562,36 @@ void WorldSession::HandleCancelTradeOpcode(WorldPackets::Trade::CancelTrade& /*c _player->TradeCancel(true); } -void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) +void WorldSession::HandleInitiateTradeOpcode(WorldPackets::Trade::InitiateTrade& initiateTrade) { - ObjectGuid guid; - - guid[0] = recvPacket.ReadBit(); - guid[3] = recvPacket.ReadBit(); - guid[5] = recvPacket.ReadBit(); - guid[1] = recvPacket.ReadBit(); - guid[4] = recvPacket.ReadBit(); - guid[6] = recvPacket.ReadBit(); - guid[7] = recvPacket.ReadBit(); - guid[2] = recvPacket.ReadBit(); - - recvPacket.ReadByteSeq(guid[7]); - recvPacket.ReadByteSeq(guid[4]); - recvPacket.ReadByteSeq(guid[3]); - recvPacket.ReadByteSeq(guid[5]); - recvPacket.ReadByteSeq(guid[1]); - recvPacket.ReadByteSeq(guid[2]); - recvPacket.ReadByteSeq(guid[6]); - recvPacket.ReadByteSeq(guid[0]); - if (GetPlayer()->m_trade) return; - TradeStatusInfo info; + WorldPackets::Trade::TradeStatus info; if (!GetPlayer()->IsAlive()) { - info.Status = TRADE_STATUS_YOU_DEAD; + info.Status = TRADE_STATUS_DEAD; SendTradeStatus(info); return; } if (GetPlayer()->HasUnitState(UNIT_STATE_STUNNED)) { - info.Status = TRADE_STATUS_YOU_STUNNED; + info.Status = TRADE_STATUS_STUNNED; SendTradeStatus(info); return; } if (isLogingOut()) { - info.Status = TRADE_STATUS_YOU_LOGOUT; + info.Status = TRADE_STATUS_LOGGING_OUT; SendTradeStatus(info); return; } if (GetPlayer()->IsInFlight()) { - info.Status = TRADE_STATUS_TARGET_TO_FAR; + info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); return; } @@ -722,8 +602,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) return; } - Player* pOther = ObjectAccessor::FindPlayer(guid); - + Player* pOther = ObjectAccessor::FindPlayer(initiateTrade.Guid); if (!pOther) { info.Status = TRADE_STATUS_NO_TARGET; @@ -733,7 +612,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) if (pOther == GetPlayer() || pOther->m_trade) { - info.Status = TRADE_STATUS_BUSY; + info.Status = TRADE_STATUS_PLAYER_BUSY; SendTradeStatus(info); return; } @@ -747,7 +626,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) if (pOther->IsInFlight()) { - info.Status = TRADE_STATUS_TARGET_TO_FAR; + info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); return; } @@ -761,14 +640,14 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) if (pOther->GetSession()->isLogingOut()) { - info.Status = TRADE_STATUS_TARGET_LOGOUT; + info.Status = TRADE_STATUS_TARGET_LOGGING_OUT; SendTradeStatus(info); return; } if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUID())) { - info.Status = TRADE_STATUS_IGNORE_YOU; + info.Status = TRADE_STATUS_PLAYER_IGNORED; SendTradeStatus(info); return; } @@ -784,7 +663,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) if (!pOther->IsWithinDistInMap(_player, TRADE_DISTANCE, false)) { - info.Status = TRADE_STATUS_TARGET_TO_FAR; + info.Status = TRADE_STATUS_TOO_FAR_AWAY; SendTradeStatus(info); return; } @@ -799,52 +678,41 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) _player->m_trade = new TradeData(_player, pOther); pOther->m_trade = new TradeData(pOther, _player); - info.Status = TRADE_STATUS_BEGIN_TRADE; - info.TraderGuid = _player->GetGUID(); + info.Status = TRADE_STATUS_PROPOSED; + info.Partner = _player->GetGUID(); pOther->GetSession()->SendTradeStatus(info); } -void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket) +void WorldSession::HandleSetTradeGoldOpcode(WorldPackets::Trade::SetTradeGold& setTradeGold) { - uint64 gold; - recvPacket >> gold; - TradeData* my_trade = _player->GetTradeData(); if (!my_trade) return; - my_trade->SetMoney(gold); + my_trade->UpdateClientStateIndex(); + my_trade->SetMoney(setTradeGold.Coinage); } -void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) +void WorldSession::HandleSetTradeItemOpcode(WorldPackets::Trade::SetTradeItem& setTradeItem) { - // send update - uint8 tradeSlot; - uint8 bag; - uint8 slot; - - recvPacket >> slot; - recvPacket >> tradeSlot; - recvPacket >> bag; - TradeData* my_trade = _player->GetTradeData(); if (!my_trade) return; - TradeStatusInfo info; + WorldPackets::Trade::TradeStatus info; // invalid slot number - if (tradeSlot >= TRADE_SLOT_COUNT) + if (setTradeItem.TradeSlot >= TRADE_SLOT_COUNT) { - info.Status = TRADE_STATUS_TRADE_CANCELED; + info.Status = TRADE_STATUS_CANCELLED; SendTradeStatus(info); return; } // check cheating, can't fail with correct client operations - Item* item = _player->GetItemByPos(bag, slot); - if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded(false, true))) + Item* item = _player->GetItemByPos(setTradeItem.PackSlot, setTradeItem.ItemSlotInPack); + if (!item || (setTradeItem.TradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded(false, true))) { - info.Status = TRADE_STATUS_TRADE_CANCELED; + info.Status = TRADE_STATUS_CANCELLED; SendTradeStatus(info); return; } @@ -855,34 +723,39 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket) if (my_trade->HasItem(iGUID)) { // cheating attempt - info.Status = TRADE_STATUS_TRADE_CANCELED; + info.Status = TRADE_STATUS_CANCELLED; SendTradeStatus(info); return; } - if (tradeSlot != TRADE_SLOT_NONTRADED && item->IsBindedNotWith(my_trade->GetTrader())) + my_trade->UpdateClientStateIndex(); + + if (setTradeItem.TradeSlot != TRADE_SLOT_NONTRADED && item->IsBindedNotWith(my_trade->GetTrader())) { info.Status = TRADE_STATUS_NOT_ON_TAPLIST; - info.Slot = tradeSlot; + info.TradeSlot = setTradeItem.TradeSlot; SendTradeStatus(info); return; } - my_trade->SetItem(TradeSlots(tradeSlot), item); + my_trade->SetItem(TradeSlots(setTradeItem.TradeSlot), item); } -void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket) +void WorldSession::HandleClearTradeItemOpcode(WorldPackets::Trade::ClearTradeItem& clearTradeItem) { - uint8 tradeSlot; - recvPacket >> tradeSlot; - TradeData* my_trade = _player->m_trade; if (!my_trade) return; + my_trade->UpdateClientStateIndex(); + // invalid slot number - if (tradeSlot >= TRADE_SLOT_COUNT) + if (clearTradeItem.TradeSlot >= TRADE_SLOT_COUNT) return; - my_trade->SetItem(TradeSlots(tradeSlot), NULL); + my_trade->SetItem(TradeSlots(clearTradeItem.TradeSlot), NULL); +} + +void WorldSession::HandleSetTradeCurrencyOpcode(WorldPackets::Trade::SetTradeCurrency& /*setTradeCurrency*/) +{ } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 9a0714b105a..894e7624ca5 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -4659,38 +4659,32 @@ enum SpellFamilyNames enum TradeStatus { - TRADE_STATUS_OPEN_WINDOW = 0, - // 1 - Related to EVENT_PLAYER_MONEY - TRADE_STATUS_NOT_ON_TAPLIST = 2, // Related to trading soulbound loot items - TRADE_STATUS_YOU_LOGOUT = 3, - TRADE_STATUS_IGNORE_YOU = 4, - TRADE_STATUS_TARGET_DEAD = 5, - TRADE_STATUS_TRADE_ACCEPT = 6, - TRADE_STATUS_TARGET_LOGOUT = 7, - // 8 - nonexistent - TRADE_STATUS_TRADE_COMPLETE = 9, - TRADE_STATUS_TRIAL_ACCOUNT = 10, // Trial accounts can not perform that action - // 11 - nonexistent - TRADE_STATUS_BEGIN_TRADE = 12, - TRADE_STATUS_YOU_DEAD = 13, - // 14 - nonexistent - // 15 - nonexistent - TRADE_STATUS_TARGET_TO_FAR = 16, - TRADE_STATUS_NO_TARGET = 17, - TRADE_STATUS_BUSY_2 = 18, - TRADE_STATUS_CURRENCY_NOT_TRADABLE = 19, // new 4.x - TRADE_STATUS_WRONG_FACTION = 20, - TRADE_STATUS_BUSY = 21, - // 22 - equivalent to 335 unk status 9 - TRADE_STATUS_TRADE_CANCELED = 23, - TRADE_STATUS_CURRENCY = 24, // new 4.x - TRADE_STATUS_BACK_TO_TRADE = 25, - TRADE_STATUS_WRONG_REALM = 26, // You can only trade conjured items... (cross realm BG related). - TRADE_STATUS_YOU_STUNNED = 27, - // 28 - nonexistent - TRADE_STATUS_TARGET_STUNNED = 29, - // 30 - nonexistent - TRADE_STATUS_CLOSE_WINDOW = 31, + TRADE_STATUS_STUNNED = 0, + TRADE_STATUS_TARGET_DEAD = 2, + TRADE_STATUS_PLAYER_IGNORED = 3, + TRADE_STATUS_STATE_CHANGED = 4, + TRADE_STATUS_PETITION = 5, + TRADE_STATUS_FAILED = 6, + TRADE_STATUS_NOT_ENOUGH_CURRENCY = 7, + TRADE_STATUS_TARGET_LOGGING_OUT = 8, + TRADE_STATUS_PROPOSED = 9, + TRADE_STATUS_RESTRICTED_ACCOUNT = 10, + TRADE_STATUS_WRONG_REALM = 12, + TRADE_STATUS_ALREADY_TRADING = 14, + TRADE_STATUS_COMPLETE = 15, + TRADE_STATUS_TARGET_STUNNED = 16, + TRADE_STATUS_ACCEPTED = 17, + TRADE_STATUS_NO_TARGET = 18, + TRADE_STATUS_CURRENCY_NOT_TRADABLE = 19, + TRADE_STATUS_WRONG_FACTION = 20, + TRADE_STATUS_NOT_ON_TAPLIST = 21, + TRADE_STATUS_UNACCEPTED = 23, + TRADE_STATUS_LOGGING_OUT = 24, + TRADE_STATUS_CANCELLED = 26, + TRADE_STATUS_TOO_FAR_AWAY = 27, + TRADE_STATUS_DEAD = 28, + TRADE_STATUS_INITIATED = 29, + TRADE_STATUS_PLAYER_BUSY = 30 }; enum XPColorChar diff --git a/src/server/game/Server/Packets/TradePackets.cpp b/src/server/game/Server/Packets/TradePackets.cpp new file mode 100644 index 00000000000..ef5ebb13e20 --- /dev/null +++ b/src/server/game/Server/Packets/TradePackets.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "TradePackets.h" + +void WorldPackets::Trade::AcceptTrade::Read() +{ + _worldPacket >> StateIndex; +} + +void WorldPackets::Trade::ClearTradeItem::Read() +{ + _worldPacket >> TradeSlot; +} + +void WorldPackets::Trade::InitiateTrade::Read() +{ + _worldPacket >> Guid; +} + +void WorldPackets::Trade::SetTradeCurrency::Read() +{ + _worldPacket >> Type >> Quantity; +} + +void WorldPackets::Trade::SetTradeGold::Read() +{ + _worldPacket >> Coinage; +} + +void WorldPackets::Trade::SetTradeItem::Read() +{ + _worldPacket >> TradeSlot >> PackSlot >> ItemSlotInPack; +} + +WorldPacket const* WorldPackets::Trade::TradeStatus::Write() +{ + _worldPacket.WriteBit(PartnerIsSameBnetAccount); + _worldPacket.WriteBits(Status, 5); + switch (Status) + { + case TRADE_STATUS_FAILED: + _worldPacket.WriteBit(FailureForYou); + _worldPacket << int32(BagResult); + _worldPacket << int32(ItemID); + break; + case TRADE_STATUS_INITIATED: + _worldPacket << uint32(ID); + break; + case TRADE_STATUS_PROPOSED: + _worldPacket << Partner; + _worldPacket << PartnerAccount; + break; + case TRADE_STATUS_WRONG_REALM: + case TRADE_STATUS_NOT_ON_TAPLIST: + _worldPacket << uint8(TradeSlot); + break; + case TRADE_STATUS_NOT_ENOUGH_CURRENCY: + case TRADE_STATUS_CURRENCY_NOT_TRADABLE: + _worldPacket << int32(CurrencyType); + _worldPacket << int32(CurrencyQuantity); + break; + default: + _worldPacket.FlushBits(); + break; + } + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& buffer, WorldPackets::Trade::TradeUpdated::UnwrappedTradeItem const& unwrappedTradeItem) +{ + buffer << unwrappedTradeItem.Item; + buffer << int32(unwrappedTradeItem.EnchantID); + buffer << int32(unwrappedTradeItem.OnUseEnchantmentID); + buffer.append(unwrappedTradeItem.SocketEnchant, MAX_GEM_SOCKETS); + buffer << unwrappedTradeItem.Creator; + buffer << int32(unwrappedTradeItem.Charges); + buffer << uint32(unwrappedTradeItem.MaxDurability); + buffer << uint32(unwrappedTradeItem.Durability); + buffer.WriteBit(unwrappedTradeItem.Lock); + buffer.FlushBits(); + + return buffer; +} + +ByteBuffer& operator<<(ByteBuffer& buffer, WorldPackets::Trade::TradeUpdated::TradeItem const& tradeItem) +{ + buffer << uint8(tradeItem.Slot); + buffer << uint32(tradeItem.EntryID); + buffer << uint32(tradeItem.StackCount); + buffer << tradeItem.GiftCreator; + if (buffer.WriteBit(tradeItem.Unwrapped.HasValue)) + buffer << tradeItem.Unwrapped.Value; + + return buffer; +} + +WorldPacket const* WorldPackets::Trade::TradeUpdated::Write() +{ + _worldPacket << uint8(WhichPlayer); + _worldPacket << uint32(ID); + _worldPacket << uint32(ClientStateIndex); + _worldPacket << uint32(CurrentStateIndex); + _worldPacket << uint64(Gold); + _worldPacket << int32(CurrencyType); + _worldPacket << int32(CurrencyQuantity); + _worldPacket << int32(ProposedEnchantment); + _worldPacket << uint32(Items.size()); + + for (TradeItem const& item : Items) + _worldPacket << item; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/TradePackets.h b/src/server/game/Server/Packets/TradePackets.h index b964a24e6fe..8831135f4e5 100644 --- a/src/server/game/Server/Packets/TradePackets.h +++ b/src/server/game/Server/Packets/TradePackets.h @@ -1,29 +1,55 @@ /* -* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at your -* option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see <http://www.gnu.org/licenses/>. -*/ + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ #ifndef TradePackets_h__ #define TradePackets_h__ -#include "Packet.h" +#include "ItemPackets.h" namespace WorldPackets { namespace Trade { + class AcceptTrade final : public ClientPacket + { + public: + AcceptTrade(WorldPacket&& packet) : ClientPacket(CMSG_ACCEPT_TRADE, std::move(packet)) { } + + void Read() override; + + uint32 StateIndex = 0; + }; + + class BeginTrade final : public ClientPacket + { + public: + BeginTrade(WorldPacket&& packet) : ClientPacket(CMSG_BEGIN_TRADE, std::move(packet)) { } + + void Read() override { } + }; + + class BusyTrade final : public ClientPacket + { + public: + BusyTrade(WorldPacket&& packet) : ClientPacket(CMSG_BUSY_TRADE, std::move(packet)) { } + + void Read() override { } + }; + class CancelTrade final : public ClientPacket { public: @@ -31,6 +57,135 @@ namespace WorldPackets void Read() override { } }; + + class ClearTradeItem final : public ClientPacket + { + public: + ClearTradeItem(WorldPacket&& packet) : ClientPacket(CMSG_CLEAR_TRADE_ITEM, std::move(packet)) { } + + void Read() override; + + uint8 TradeSlot = 0; + }; + + class IgnoreTrade final : public ClientPacket + { + public: + IgnoreTrade(WorldPacket&& packet) : ClientPacket(CMSG_IGNORE_TRADE, std::move(packet)) { } + + void Read() override { } + }; + + class InitiateTrade final : public ClientPacket + { + public: + InitiateTrade(WorldPacket&& packet) : ClientPacket(CMSG_INITIATE_TRADE, std::move(packet)) { } + + void Read() override; + + ObjectGuid Guid; + }; + + class SetTradeCurrency final : public ClientPacket + { + public: + SetTradeCurrency(WorldPacket&& packet) : ClientPacket(CMSG_SET_TRADE_CURRENCY, std::move(packet)) { } + + void Read() override; + + uint32 Type = 0; + uint32 Quantity = 0; + }; + + class SetTradeGold final : public ClientPacket + { + public: + SetTradeGold(WorldPacket&& packet) : ClientPacket(CMSG_SET_TRADE_GOLD, std::move(packet)) { } + + void Read() override; + + uint64 Coinage = 0; + }; + + class SetTradeItem final : public ClientPacket + { + public: + SetTradeItem(WorldPacket&& packet) : ClientPacket(CMSG_SET_TRADE_ITEM, std::move(packet)) { } + + void Read() override; + + uint8 TradeSlot = 0; + uint8 PackSlot = 0; + uint8 ItemSlotInPack = 0; + }; + + class UnacceptTrade final : public ClientPacket + { + public: + UnacceptTrade(WorldPacket&& packet) : ClientPacket(CMSG_UNACCEPT_TRADE, std::move(packet)) { } + + void Read() override { } + }; + + class TradeStatus final : public ServerPacket + { + public: + TradeStatus() : ServerPacket(SMSG_TRADE_STATUS, 1 + 1 + 16 + 4 + 4 + 1 + 4 + 4 + 4 + 1) { } + + WorldPacket const* Write() override; + + ::TradeStatus Status = TRADE_STATUS_INITIATED; + uint8 TradeSlot = 0; + ObjectGuid PartnerAccount; + ObjectGuid Partner; + int32 CurrencyType = 0; + int32 CurrencyQuantity = 0; + bool FailureForYou = false; + int32 BagResult = 0; + uint32 ItemID = 0; + uint32 ID = 0; + bool PartnerIsSameBnetAccount = false; + }; + + class TradeUpdated final : public ServerPacket + { + public: + TradeUpdated() : ServerPacket(SMSG_TRADE_UPDATED) { } + + WorldPacket const* Write() override; + + struct UnwrappedTradeItem + { + WorldPackets::Item::ItemInstance Item; + int32 EnchantID = 0; + int32 OnUseEnchantmentID = 0; + ObjectGuid Creator; + int32 Charges = 0; + bool Lock = false; + uint32 MaxDurability = 0; + uint32 Durability = 0; + int32 SocketEnchant[MAX_GEM_SOCKETS] = { }; + }; + + struct TradeItem + { + uint8 Slot = 0; + int32 EntryID = 0; + int32 StackCount = 0; + ObjectGuid GiftCreator; + Optional<UnwrappedTradeItem> Unwrapped; + }; + + uint64 Gold = 0; + uint32 CurrentStateIndex = 0; + uint8 WhichPlayer = 0; + uint32 ClientStateIndex = 0; + std::vector<TradeItem> Items; + int32 CurrencyType = 0; + uint32 ID = 0; + int32 ProposedEnchantment = 0; + int32 CurrencyQuantity = 0; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index b000e29a15f..a637e8f8966 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -145,7 +145,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_ACCEPT_GUILD_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Guild::AcceptGuildInvite, &WorldSession::HandleGuildAcceptInvite); DEFINE_OPCODE_HANDLER_OLD(CMSG_ACCEPT_LEVEL_GRANT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptGrantLevel ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_ACCEPT_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode ); + DEFINE_HANDLER(CMSG_ACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::AcceptTrade, &WorldSession::HandleAcceptTradeOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_ACCEPT_WARGAME_INVITE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ACTIVATE_TAXI, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ADD_BATTLENET_FRIEND, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -200,7 +200,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PET_SET_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PET_SUMMON, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PET_UPDATE_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_BEGIN_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode ); + DEFINE_HANDLER(CMSG_BEGIN_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::BeginTrade, &WorldSession::HandleBeginTradeOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BF_MGR_ENTRY_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleBfEntryInviteResponse ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BF_MGR_QUEUE_EXIT_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleBfExitRequest); DEFINE_OPCODE_HANDLER_OLD(CMSG_BF_MGR_QUEUE_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleBfQueueInviteResponse ); @@ -210,7 +210,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_BLACK_MARKET_OPEN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::BlackMarket::BlackMarketOpen, &WorldSession::HandleBlackMarketOpen); DEFINE_OPCODE_HANDLER_OLD(CMSG_BLACK_MARKET_REQUEST_ITEMS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BUG_REPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBugReportOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_BUSY_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode ); + DEFINE_HANDLER(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::BusyTrade, &WorldSession::HandleBusyTradeOpcode); DEFINE_HANDLER(CMSG_BUY_BACK_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::BuyBackItem, &WorldSession::HandleBuybackItem); DEFINE_HANDLER(CMSG_BUY_BANK_SLOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Bank::BuyBankSlot, &WorldSession::HandleBuyBankSlotOpcode); DEFINE_HANDLER(CMSG_BUY_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::BuyItem, &WorldSession::HandleBuyItemOpcode); @@ -307,7 +307,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_CHECK_WOW_TOKEN_VETERAN_ELIGIBILITY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHOICE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CLEAR_RAID_MARKER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_CLEAR_TRADE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode ); + DEFINE_HANDLER(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::ClearTradeItem, &WorldSession::HandleClearTradeItemOpcode); DEFINE_HANDLER(CMSG_CLIENT_PORT_GRAVEYARD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Misc::PortGraveyard, &WorldSession::HandlePortGraveyard); DEFINE_OPCODE_HANDLER_OLD(CMSG_CLOSE_INTERACTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_COMMENTATOR_ENABLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -447,10 +447,10 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_GUILD_UPDATE_INFO_TEXT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildUpdateInfoText, &WorldSession::HandleGuildUpdateInfoText); DEFINE_HANDLER(CMSG_GUILD_UPDATE_MOTD_TEXT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildUpdateMotdText, &WorldSession::HandleGuildUpdateMotdText); DEFINE_OPCODE_HANDLER_OLD(CMSG_HEARTH_AND_RESURRECT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleHearthAndResurrect ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_IGNORE_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode ); + DEFINE_HANDLER(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::IgnoreTrade, &WorldSession::HandleIgnoreTradeOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_INCREASE_CAST_TIME_FOR_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_INITIATE_ROLE_POLL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRolePollBeginOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_INITIATE_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode ); + DEFINE_HANDLER(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::InitiateTrade, &WorldSession::HandleInitiateTradeOpcode); DEFINE_HANDLER(CMSG_INSPECT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Inspect::Inspect, &WorldSession::HandleInspectOpcode); DEFINE_HANDLER(CMSG_INSPECT_PVP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Inspect::InspectPVPRequest, &WorldSession::HandleInspectPVP); DEFINE_OPCODE_HANDLER_OLD(CMSG_INSTANCE_LOCK_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse); @@ -738,9 +738,9 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SET_SPECIALIZATION, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Talent::SetSpecialization, &WorldSession::HandleSetSpecializationOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode ); DEFINE_HANDLER(CMSG_SET_TITLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Character::SetTitle, &WorldSession::HandleSetTitleOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TRADE_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TRADE_GOLD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TRADE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode ); + DEFINE_HANDLER(CMSG_SET_TRADE_CURRENCY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::SetTradeCurrency, &WorldSession::HandleSetTradeCurrencyOpcode); + DEFINE_HANDLER(CMSG_SET_TRADE_GOLD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::SetTradeGold, &WorldSession::HandleSetTradeGoldOpcode); + DEFINE_HANDLER(CMSG_SET_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::SetTradeItem, &WorldSession::HandleSetTradeItemOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_USING_PARTY_GARRISON, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_WATCHED_FACTION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetWatchedFactionOpcode ); DEFINE_HANDLER(CMSG_SHOWING_CLOAK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Character::ShowingCloak, &WorldSession::HandleShowingCloakOpcode); @@ -792,7 +792,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_TWITTER_DISCONNECT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_TWITTER_POST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_HANDLER(CMSG_UI_TIME_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::UITimeRequest, &WorldSession::HandleUITimeRequest); - DEFINE_OPCODE_HANDLER_OLD(CMSG_UNACCEPT_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode ); + DEFINE_HANDLER(CMSG_UNACCEPT_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Trade::UnacceptTrade, &WorldSession::HandleUnacceptTradeOpcode); DEFINE_HANDLER(CMSG_UNDELETE_CHARACTER, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::UndeleteCharacter, &WorldSession::HandleCharUndeleteOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_UNLEARN_SKILL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnlearnSkillOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_UNLEARN_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1675,8 +1675,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOKEN_UNK1, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOTEM_CREATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOTEM_MOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_UPDATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_STATUS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 8ec5af98db7..9c2457e7b5e 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -55,7 +55,6 @@ struct AuctionEntry; struct DeclinedName; struct ItemTemplate; struct MovementInfo; -struct TradeStatusInfo; namespace lfg { @@ -393,7 +392,18 @@ namespace WorldPackets namespace Trade { + class AcceptTrade; + class BeginTrade; + class BusyTrade; class CancelTrade; + class ClearTradeItem; + class IgnoreTrade; + class InitiateTrade; + class SetTradeCurrency; + class SetTradeGold; + class SetTradeItem; + class UnacceptTrade; + class TradeStatus; } namespace Who @@ -658,7 +668,7 @@ class WorldSession void SendBattleGroundList(ObjectGuid guid, BattlegroundTypeId bgTypeId = BATTLEGROUND_RB); - void SendTradeStatus(TradeStatusInfo const& status); + void SendTradeStatus(WorldPackets::Trade::TradeStatus& status); void SendUpdateTrade(bool trader_data = true); void SendCancelTrade(); @@ -1033,16 +1043,17 @@ class WorldSession void HandleDuelAccepted(); void HandleDuelCancelled(); - void HandleAcceptTradeOpcode(WorldPacket& recvPacket); - void HandleBeginTradeOpcode(WorldPacket& recvPacket); - void HandleBusyTradeOpcode(WorldPacket& recvPacket); + void HandleAcceptTradeOpcode(WorldPackets::Trade::AcceptTrade& acceptTrade); + void HandleBeginTradeOpcode(WorldPackets::Trade::BeginTrade& beginTrade); + void HandleBusyTradeOpcode(WorldPackets::Trade::BusyTrade& busyTrade); void HandleCancelTradeOpcode(WorldPackets::Trade::CancelTrade& cancelTrade); - void HandleClearTradeItemOpcode(WorldPacket& recvPacket); - void HandleIgnoreTradeOpcode(WorldPacket& recvPacket); - void HandleInitiateTradeOpcode(WorldPacket& recvPacket); - void HandleSetTradeGoldOpcode(WorldPacket& recvPacket); - void HandleSetTradeItemOpcode(WorldPacket& recvPacket); - void HandleUnacceptTradeOpcode(WorldPacket& recvPacket); + void HandleClearTradeItemOpcode(WorldPackets::Trade::ClearTradeItem& clearTradeItem); + void HandleIgnoreTradeOpcode(WorldPackets::Trade::IgnoreTrade& ignoreTrade); + void HandleInitiateTradeOpcode(WorldPackets::Trade::InitiateTrade& initiateTrade); + void HandleSetTradeCurrencyOpcode(WorldPackets::Trade::SetTradeCurrency& setTradeCurrency); + void HandleSetTradeGoldOpcode(WorldPackets::Trade::SetTradeGold& setTradeGold); + void HandleSetTradeItemOpcode(WorldPackets::Trade::SetTradeItem& setTradeItem); + void HandleUnacceptTradeOpcode(WorldPackets::Trade::UnacceptTrade& unacceptTrade); void HandleAuctionHelloOpcode(WorldPackets::AuctionHouse::AuctionHelloRequest& packet); void HandleAuctionListItems(WorldPacket& recvData); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index a5c143f1c63..a4b84e6a2eb 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -365,7 +365,7 @@ void SpellCastTargets::SetItemTarget(Item* item) void SpellCastTargets::SetTradeItemTarget(Player* caster) { - m_itemTargetGUID.SetRawValue({ uint8(TRADE_SLOT_NONTRADED), 0, 0, 0, 0, 0, 0, 0 }); + m_itemTargetGUID = ObjectGuid::TradeItem; m_itemTargetEntry = 0; m_targetMask |= TARGET_FLAG_TRADE_ITEM; @@ -489,9 +489,7 @@ void SpellCastTargets::Update(Unit* caster) m_itemTarget = player->GetItemByGuid(m_itemTargetGUID); else if (m_targetMask & TARGET_FLAG_TRADE_ITEM) { - ObjectGuid nonTradedGuid; - nonTradedGuid.SetRawValue(uint64(0), uint64(TRADE_SLOT_NONTRADED)); - if (m_itemTargetGUID == nonTradedGuid) // here it is not guid but slot. Also prevents hacking slots + if (m_itemTargetGUID == ObjectGuid::TradeItem) if (TradeData* pTrade = player->GetTradeData()) m_itemTarget = pTrade->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED); } @@ -5543,9 +5541,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (!my_trade) return SPELL_FAILED_NOT_TRADING; - // Item target guid contains trade slot until m_targets.UpdateTradeSlotItem() is called - TradeSlots slot = TradeSlots(m_targets.GetItemTargetGUID().GetRawValue().at(0)); - if (slot != TRADE_SLOT_NONTRADED) + if (m_targets.GetItemTargetGUID() != ObjectGuid::TradeItem) return SPELL_FAILED_BAD_TARGETS; if (!IsTriggered()) |