aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Player/Player.cpp121
-rw-r--r--src/server/game/Entities/Player/Player.h21
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp176
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h6
-rw-r--r--src/server/game/Server/WorldSession.h3
5 files changed, 193 insertions, 134 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index b11d2d03a13..e05553aa454 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -369,7 +369,10 @@ void TradeData::SetMoney(uint32 money)
if (!m_player->HasEnoughMoney(money))
{
- m_player->GetSession()->SendTradeStatus(TRADE_STATUS_BUSY);
+ TradeStatusInfo info;
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY;
+ m_player->GetSession()->SendTradeStatus(info);
return;
}
@@ -395,10 +398,12 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
if (!state)
{
+ TradeStatusInfo info;
+ info.Status = TRADE_STATUS_BACK_TO_TRADE;
if (crosssend)
- m_trader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
+ m_trader->GetSession()->SendTradeStatus(info);
else
- m_player->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
+ m_player->GetSession()->SendTradeStatus(info);
}
}
@@ -10524,7 +10529,7 @@ bool Player::HasItemOrGemWithLimitCategoryEquipped(uint32 limitCategory, uint32
return false;
}
-InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count) const
+InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count /*= NULL*/, uint32* itemLimitCategory /*= NULL*/) const
{
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(entry);
if (!pProto)
@@ -10570,6 +10575,8 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item
{
if (no_space_count)
*no_space_count = count + curcount - limitEntry->maxCount;
+ if (itemLimitCategory)
+ *itemLimitCategory = pProto->ItemLimitCategory;
return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED;
}
}
@@ -11249,79 +11256,79 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des
}
//////////////////////////////////////////////////////////////////////////
-InventoryResult Player::CanStoreItems(Item** pItems, int count) const
+InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimitCategory) const
{
- Item* pItem2;
+ Item* item2;
// fill space table
- int inv_slot_items[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START];
- int inv_bags[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE];
- int inv_keys[KEYRING_SLOT_END - KEYRING_SLOT_START];
- int inv_tokens[CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START];
+ uint32 inventoryCounts[INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START];
+ uint32 bagCounts[INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE];
+ uint32 keyringCounts[KEYRING_SLOT_END - KEYRING_SLOT_START];
+ uint32 currencyCounts[CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START];
- memset(inv_slot_items, 0, sizeof(int) * (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
- memset(inv_bags, 0, sizeof(int) * (INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START) * MAX_BAG_SIZE);
- memset(inv_keys, 0, sizeof(int) * (KEYRING_SLOT_END - KEYRING_SLOT_START));
- memset(inv_tokens, 0, sizeof(int) * (CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START));
+ memset(inventoryCounts, 0, sizeof(uint32) * (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
+ memset(bagCounts, 0, sizeof(uint32) * (INVENTORY_SLOT_BAG_END - INVENTORY_SLOT_BAG_START) * MAX_BAG_SIZE);
+ memset(keyringCounts, 0, sizeof(uint32) * (KEYRING_SLOT_END - KEYRING_SLOT_START));
+ memset(currencyCounts, 0, sizeof(uint32) * (CURRENCYTOKEN_SLOT_END - CURRENCYTOKEN_SLOT_START));
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++)
{
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsInTrade())
- inv_slot_items[i - INVENTORY_SLOT_ITEM_START] = pItem2->GetCount();
+ item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
+ if (item2 && !item2->IsInTrade())
+ inventoryCounts[i - INVENTORY_SLOT_ITEM_START] = item2->GetCount();
}
for (uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++)
{
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsInTrade())
- inv_keys[i - KEYRING_SLOT_START] = pItem2->GetCount();
+ item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
+ if (item2 && !item2->IsInTrade())
+ keyringCounts[i - KEYRING_SLOT_START] = item2->GetCount();
}
for (uint8 i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; i++)
{
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsInTrade())
- inv_tokens[i - CURRENCYTOKEN_SLOT_START] = pItem2->GetCount();
+ item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
+ if (item2 && !item2->IsInTrade())
+ currencyCounts[i - CURRENCYTOKEN_SLOT_START] = item2->GetCount();
}
for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
{
- pItem2 = GetItemByPos(i, j);
- if (pItem2 && !pItem2->IsInTrade())
- inv_bags[i - INVENTORY_SLOT_BAG_START][j] = pItem2->GetCount();
+ item2 = GetItemByPos(i, j);
+ if (item2 && !item2->IsInTrade())
+ bagCounts[i - INVENTORY_SLOT_BAG_START][j] = item2->GetCount();
}
// check free space for all items
for (int k = 0; k < count; ++k)
{
- Item* pItem = pItems[k];
+ Item* item = items[k];
// no item
- if (!pItem)
+ if (!item)
continue;
- TC_LOG_DEBUG("entities.player.items", "STORAGE: CanStoreItems %i. item = %u, count = %u", k + 1, pItem->GetEntry(), pItem->GetCount());
- ItemTemplate const* pProto = pItem->GetTemplate();
+ TC_LOG_DEBUG("entities.player.items", "STORAGE: CanStoreItems %i. item = %u, count = %u", k + 1, item->GetEntry(), item->GetCount());
+ ItemTemplate const* pProto = item->GetTemplate();
// strange item
if (!pProto)
return EQUIP_ERR_ITEM_NOT_FOUND;
// item used
- if (pItem->m_lootGenerated)
+ if (item->m_lootGenerated)
return EQUIP_ERR_ALREADY_LOOTED;
// item it 'bind'
- if (pItem->IsBindedNotWith(this))
+ if (item->IsBindedNotWith(this))
return EQUIP_ERR_DONT_OWN_THAT_ITEM;
ItemTemplate const* pBagProto;
// item is 'one item only'
- InventoryResult res = CanTakeMoreSimilarItems(pItem);
+ InventoryResult res = CanTakeMoreSimilarItems(item, itemLimitCategory);
if (res != EQUIP_ERR_OK)
return res;
@@ -11332,10 +11339,10 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
for (uint8 t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; ++t)
{
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
+ item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
+ if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && keyringCounts[t-KEYRING_SLOT_START] + item->GetCount() <= pProto->GetMaxStackSize())
{
- inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount();
+ keyringCounts[t-KEYRING_SLOT_START] += item->GetCount();
b_found = true;
break;
}
@@ -11345,10 +11352,10 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
for (int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
{
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
+ item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
+ if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && currencyCounts[t-CURRENCYTOKEN_SLOT_START] + item->GetCount() <= pProto->GetMaxStackSize())
{
- inv_tokens[t-CURRENCYTOKEN_SLOT_START] += pItem->GetCount();
+ currencyCounts[t-CURRENCYTOKEN_SLOT_START] += item->GetCount();
b_found = true;
break;
}
@@ -11358,10 +11365,10 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
for (int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; ++t)
{
- pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->GetMaxStackSize())
+ item2 = GetItemByPos(INVENTORY_SLOT_BAG_0, t);
+ if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inventoryCounts[t-INVENTORY_SLOT_ITEM_START] + item->GetCount() <= pProto->GetMaxStackSize())
{
- inv_slot_items[t-INVENTORY_SLOT_ITEM_START] += pItem->GetCount();
+ inventoryCounts[t-INVENTORY_SLOT_ITEM_START] += item->GetCount();
b_found = true;
break;
}
@@ -11373,14 +11380,14 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
{
if (Bag* bag = GetBagByPos(t))
{
- if (ItemCanGoIntoBag(pItem->GetTemplate(), bag->GetTemplate()))
+ if (ItemCanGoIntoBag(item->GetTemplate(), bag->GetTemplate()))
{
for (uint32 j = 0; j < bag->GetBagSize(); j++)
{
- pItem2 = GetItemByPos(t, j);
- if (pItem2 && pItem2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->GetMaxStackSize())
+ item2 = GetItemByPos(t, j);
+ if (item2 && item2->CanBeMergedPartlyWith(pProto) == EQUIP_ERR_OK && bagCounts[t-INVENTORY_SLOT_BAG_START][j] + item->GetCount() <= pProto->GetMaxStackSize())
{
- inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount();
+ bagCounts[t-INVENTORY_SLOT_BAG_START][j] += item->GetCount();
b_found = true;
break;
}
@@ -11401,9 +11408,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
uint32 keyringSize = GetMaxKeyringSize();
for (uint32 t = KEYRING_SLOT_START; t < KEYRING_SLOT_START+keyringSize; ++t)
{
- if (inv_keys[t-KEYRING_SLOT_START] == 0)
+ if (keyringCounts[t-KEYRING_SLOT_START] == 0)
{
- inv_keys[t-KEYRING_SLOT_START] = 1;
+ keyringCounts[t-KEYRING_SLOT_START] = 1;
b_found = true;
break;
}
@@ -11417,9 +11424,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
{
for (uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
{
- if (inv_tokens[t-CURRENCYTOKEN_SLOT_START] == 0)
+ if (currencyCounts[t-CURRENCYTOKEN_SLOT_START] == 0)
{
- inv_tokens[t-CURRENCYTOKEN_SLOT_START] = 1;
+ currencyCounts[t-CURRENCYTOKEN_SLOT_START] = 1;
b_found = true;
break;
}
@@ -11441,9 +11448,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
{
for (uint32 j = 0; j < bag->GetBagSize(); j++)
{
- if (inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0)
+ if (bagCounts[t-INVENTORY_SLOT_BAG_START][j] == 0)
{
- inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1;
+ bagCounts[t-INVENTORY_SLOT_BAG_START][j] = 1;
b_found = true;
break;
}
@@ -11459,9 +11466,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
bool b_found = false;
for (int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; ++t)
{
- if (inv_slot_items[t-INVENTORY_SLOT_ITEM_START] == 0)
+ if (inventoryCounts[t-INVENTORY_SLOT_ITEM_START] == 0)
{
- inv_slot_items[t-INVENTORY_SLOT_ITEM_START] = 1;
+ inventoryCounts[t-INVENTORY_SLOT_ITEM_START] = 1;
b_found = true;
break;
}
@@ -11482,9 +11489,9 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
for (uint32 j = 0; j < bag->GetBagSize(); j++)
{
- if (inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0)
+ if (bagCounts[t-INVENTORY_SLOT_BAG_START][j] == 0)
{
- inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1;
+ bagCounts[t-INVENTORY_SLOT_BAG_START][j] = 1;
b_found = true;
break;
}
@@ -11494,7 +11501,7 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const
// no free slot found?
if (!b_found)
- return EQUIP_ERR_INVENTORY_FULL;
+ return EQUIP_ERR_BAG_FULL;
}
return EQUIP_ERR_OK;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 6510d7f2f26..0c1ddcd69d9 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -989,6 +989,19 @@ struct BGData
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
};
+struct TradeStatusInfo
+{
+ TradeStatusInfo() : Status(TRADE_STATUS_BUSY), TraderGuid(0), Result(EQUIP_ERR_OK),
+ IsTargetResult(false), ItemLimitCategoryId(0), Slot(0) { }
+
+ TradeStatus Status;
+ uint64 TraderGuid;
+ InventoryResult Result;
+ bool IsTargetResult;
+ uint32 ItemLimitCategoryId;
+ uint8 Slot;
+};
+
class TradeData
{
public: // constructors
@@ -1237,11 +1250,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) const { return CanTakeMoreSimilarItems(pItem->GetEntry(), pItem->GetCount(), pItem); }
- InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return CanTakeMoreSimilarItems(entry, count, NULL); }
+ 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 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** pItem, int count) const;
+ InventoryResult CanStoreItems(Item** items, int count, uint32* itemLimitCategory) 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;
@@ -1265,7 +1278,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) const;
+ InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL, uint32* itemLimitCategory = NULL) 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(uint32 it);
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 884c4a83b15..e8acef83ee2 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -30,38 +30,27 @@
#include "Language.h"
#include "AccountMgr.h"
-void WorldSession::SendTradeStatus(TradeStatus status)
+void WorldSession::SendTradeStatus(TradeStatusInfo const& info)
{
- WorldPacket data;
+ WorldPacket data(SMSG_TRADE_STATUS, 13);
+ data << uint32(info.Status);
- switch (status)
+ switch (info.Status)
{
case TRADE_STATUS_BEGIN_TRADE:
- data.Initialize(SMSG_TRADE_STATUS, 4+8);
- data << uint32(status);
- data << uint64(0);
+ data << uint64(info.TraderGuid); // CGTradeInfo::m_tradingPlayer
break;
case TRADE_STATUS_OPEN_WINDOW:
- data.Initialize(SMSG_TRADE_STATUS, 4+4);
- data << uint32(status);
- data << uint32(0); // added in 2.4.0
+ data << uint32(0); // CGTradeInfo::m_tradeID
break;
case TRADE_STATUS_CLOSE_WINDOW:
- data.Initialize(SMSG_TRADE_STATUS, 4+4+1+4);
- data << uint32(status);
- data << uint32(0);
- data << uint8(0);
- data << uint32(0);
+ data << uint32(info.Result); // InventoryResult
+ data << uint8(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.ItemLimitCategoryId); // ItemLimitCategory.dbc entry
break;
- case TRADE_STATUS_ONLY_CONJURED:
- case TRADE_STATUS_NOT_ELIGIBLE:
- data.Initialize(SMSG_TRADE_STATUS, 4+1);
- data << uint32(status);
- data << uint8(0);
- break;
- default:
- data.Initialize(SMSG_TRADE_STATUS, 4);
- data << uint32(status);
+ case TRADE_STATUS_WRONG_REALM:
+ case TRADE_STATUS_NOT_ON_TAPLIST:
+ data << uint8(info.Slot); // Trade slot; -1 here clears CGTradeInfo::m_tradeMoney
break;
}
@@ -86,7 +75,7 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 1+4+4+4+4+4+7*(1+4+4+4+4+8+4+4+4+4+8+4+4+4+4+4+4));
data << uint8(trader_data); // 1 means traders data, 0 means own
- data << uint32(0); // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
+ data << uint32(0); // CGTradeInfo::m_tradeID
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases
data << uint32(view_trade->GetMoney()); // trader gold
@@ -271,14 +260,15 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
Item* myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL };
Item* hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL };
- bool myCanCompleteTrade = true, hisCanCompleteTrade = true;
// set before checks for propertly undo at problems (it already set in to client)
my_trade->SetAccepted(true);
+ TradeStatusInfo info;
if (!_player->IsWithinDistInMap(trader, TRADE_DISTANCE, false))
{
- SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
+ info.Status = TRADE_STATUS_TARGET_TO_FAR;
+ SendTradeStatus(info);
my_trade->SetAccepted(false);
return;
}
@@ -286,7 +276,9 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
// not accept case incorrect money amount
if (!_player->HasEnoughMoney(my_trade->GetMoney()))
{
- SendNotification(LANG_NOT_ENOUGH_GOLD);
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY;
+ SendTradeStatus(info);
my_trade->SetAccepted(false, true);
return;
}
@@ -294,21 +286,27 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
// not accept case incorrect money amount
if (!trader->HasEnoughMoney(his_trade->GetMoney()))
{
- trader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD);
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_NOT_ENOUGH_MONEY;
+ trader->GetSession()->SendTradeStatus(info);
his_trade->SetAccepted(false, true);
return;
}
if (_player->GetMoney() >= MAX_MONEY_AMOUNT - his_trade->GetMoney())
{
- _player->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_TOO_MUCH_GOLD;
+ SendTradeStatus(info);
my_trade->SetAccepted(false, true);
return;
}
if (trader->GetMoney() >= MAX_MONEY_AMOUNT - my_trade->GetMoney())
{
- trader->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_TOO_MUCH_GOLD;
+ trader->GetSession()->SendTradeStatus(info);
his_trade->SetAccepted(false, true);
return;
}
@@ -320,14 +318,16 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
if (!item->CanBeTraded(false, true))
{
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ info.Status = TRADE_STATUS_TRADE_CANCELED;
+ SendTradeStatus(info);
return;
}
if (item->IsBindedNotWith(trader))
{
- SendTradeStatus(TRADE_STATUS_NOT_ELIGIBLE);
- SendTradeStatus(TRADE_STATUS_CLOSE_WINDOW/*TRADE_STATUS_TRADE_CANCELED*/);
+ info.Status = TRADE_STATUS_CLOSE_WINDOW;
+ info.Result = EQUIP_ERR_CANNOT_TRADE_THAT;
+ SendTradeStatus(info);
return;
}
}
@@ -336,7 +336,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
if (!item->CanBeTraded(false, true))
{
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ info.Status = TRADE_STATUS_TRADE_CANCELED;
+ SendTradeStatus(info);
return;
}
//if (item->IsBindedNotWith(_player)) // dont mark as invalid when his item isnt good (not exploitable because if item is invalid trade will fail anyway later on the same check)
@@ -431,31 +432,37 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
}
// inform partner client
- trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
+ info.Status = TRADE_STATUS_TRADE_ACCEPT;
+ trader->GetSession()->SendTradeStatus(info);
// test if item will fit in each inventory
- hisCanCompleteTrade = (trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
- myCanCompleteTrade = (_player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
+ 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);
clearAcceptTradeMode(myItems, hisItems);
// in case of missing space report error
- if (!myCanCompleteTrade)
+ if (myCanCompleteInfo.Result != EQUIP_ERR_OK)
{
clearAcceptTradeMode(my_trade, his_trade);
- SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
- trader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
+ myCanCompleteInfo.Status = TRADE_STATUS_CLOSE_WINDOW;
+ trader->GetSession()->SendTradeStatus(myCanCompleteInfo);
+ myCanCompleteInfo.IsTargetResult = true;
+ SendTradeStatus(myCanCompleteInfo);
my_trade->SetAccepted(false);
his_trade->SetAccepted(false);
return;
}
- else if (!hisCanCompleteTrade)
+ else if (hisCanCompleteInfo.Result != EQUIP_ERR_OK)
{
clearAcceptTradeMode(my_trade, his_trade);
- SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
- trader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
+ hisCanCompleteInfo.Status = TRADE_STATUS_CLOSE_WINDOW;
+ SendTradeStatus(hisCanCompleteInfo);
+ hisCanCompleteInfo.IsTargetResult = true;
+ trader->GetSession()->SendTradeStatus(hisCanCompleteInfo);
my_trade->SetAccepted(false);
his_trade->SetAccepted(false);
return;
@@ -524,12 +531,14 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
trader->SaveInventoryAndGoldToDB(trans);
CharacterDatabase.CommitTransaction(trans);
- trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
- SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
+ info.Status = TRADE_STATUS_TRADE_COMPLETE;
+ trader->GetSession()->SendTradeStatus(info);
+ SendTradeStatus(info);
}
else
{
- trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
+ info.Status = TRADE_STATUS_TRADE_ACCEPT;
+ trader->GetSession()->SendTradeStatus(info);
}
}
@@ -548,8 +557,10 @@ void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/)
if (!my_trade)
return;
- my_trade->GetTrader()->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
- SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
+ TradeStatusInfo info;
+ info.Status = TRADE_STATUS_OPEN_WINDOW;
+ my_trade->GetTrader()->GetSession()->SendTradeStatus(info);
+ SendTradeStatus(info);
}
void WorldSession::SendCancelTrade()
@@ -557,7 +568,9 @@ void WorldSession::SendCancelTrade()
if (PlayerRecentlyLoggedOut() || PlayerLogout())
return;
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ TradeStatusInfo info;
+ info.Status = TRADE_STATUS_TRADE_CANCELED;
+ SendTradeStatus(info);
}
void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/)
@@ -575,27 +588,32 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
if (GetPlayer()->m_trade)
return;
+ TradeStatusInfo info;
if (!GetPlayer()->IsAlive())
{
- SendTradeStatus(TRADE_STATUS_YOU_DEAD);
+ info.Status = TRADE_STATUS_YOU_DEAD;
+ SendTradeStatus(info);
return;
}
if (GetPlayer()->HasUnitState(UNIT_STATE_STUNNED))
{
- SendTradeStatus(TRADE_STATUS_YOU_STUNNED);
+ info.Status = TRADE_STATUS_YOU_STUNNED;
+ SendTradeStatus(info);
return;
}
if (isLogingOut())
{
- SendTradeStatus(TRADE_STATUS_YOU_LOGOUT);
+ info.Status = TRADE_STATUS_YOU_LOGOUT;
+ SendTradeStatus(info);
return;
}
if (GetPlayer()->IsInFlight())
{
- SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
+ info.Status = TRADE_STATUS_TARGET_TO_FAR;
+ SendTradeStatus(info);
return;
}
@@ -609,55 +627,64 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
if (!pOther)
{
- SendTradeStatus(TRADE_STATUS_NO_TARGET);
+ info.Status = TRADE_STATUS_NO_TARGET;
+ SendTradeStatus(info);
return;
}
if (pOther == GetPlayer() || pOther->m_trade)
{
- SendTradeStatus(TRADE_STATUS_BUSY);
+ info.Status = TRADE_STATUS_BUSY;
+ SendTradeStatus(info);
return;
}
if (!pOther->IsAlive())
{
- SendTradeStatus(TRADE_STATUS_TARGET_DEAD);
+ info.Status = TRADE_STATUS_TARGET_DEAD;
+ SendTradeStatus(info);
return;
}
if (pOther->IsInFlight())
{
- SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
+ info.Status = TRADE_STATUS_TARGET_TO_FAR;
+ SendTradeStatus(info);
return;
}
if (pOther->HasUnitState(UNIT_STATE_STUNNED))
{
- SendTradeStatus(TRADE_STATUS_TARGET_STUNNED);
+ info.Status = TRADE_STATUS_TARGET_STUNNED;
+ SendTradeStatus(info);
return;
}
if (pOther->GetSession()->isLogingOut())
{
- SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT);
+ info.Status = TRADE_STATUS_TARGET_LOGOUT;
+ SendTradeStatus(info);
return;
}
if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
{
- SendTradeStatus(TRADE_STATUS_IGNORE_YOU);
+ info.Status = TRADE_STATUS_IGNORE_YOU;
+ SendTradeStatus(info);
return;
}
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam())
{
- SendTradeStatus(TRADE_STATUS_WRONG_FACTION);
+ info.Status = TRADE_STATUS_WRONG_FACTION;
+ SendTradeStatus(info);
return;
}
if (!pOther->IsWithinDistInMap(_player, TRADE_DISTANCE, false))
{
- SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR);
+ info.Status = TRADE_STATUS_TARGET_TO_FAR;
+ SendTradeStatus(info);
return;
}
@@ -671,10 +698,9 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
_player->m_trade = new TradeData(_player, pOther);
pOther->m_trade = new TradeData(pOther, _player);
- WorldPacket data(SMSG_TRADE_STATUS, 12);
- data << uint32(TRADE_STATUS_BEGIN_TRADE);
- data << uint64(_player->GetGUID());
- pOther->GetSession()->SendPacket(&data);
+ info.Status = TRADE_STATUS_BEGIN_TRADE;
+ info.TraderGuid = _player->GetGUID();
+ pOther->GetSession()->SendTradeStatus(info);
}
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
@@ -704,10 +730,12 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
if (!my_trade)
return;
+ TradeStatusInfo info;
// invalid slot number
if (tradeSlot >= TRADE_SLOT_COUNT)
{
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ info.Status = TRADE_STATUS_TRADE_CANCELED;
+ SendTradeStatus(info);
return;
}
@@ -715,7 +743,8 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
Item* item = _player->GetItemByPos(bag, slot);
if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded(false, true)))
{
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ info.Status = TRADE_STATUS_TRADE_CANCELED;
+ SendTradeStatus(info);
return;
}
@@ -725,7 +754,16 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
if (my_trade->HasItem(iGUID))
{
// cheating attempt
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ info.Status = TRADE_STATUS_TRADE_CANCELED;
+ SendTradeStatus(info);
+ return;
+ }
+
+ if (item->IsBindedNotWith(my_trade->GetTrader()))
+ {
+ info.Status = TRADE_STATUS_NOT_ON_TAPLIST;
+ info.Slot = tradeSlot;
+ SendTradeStatus(info);
return;
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 7a48e016af0..ed3bb74ae9d 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -3400,7 +3400,7 @@ enum TradeStatus
TRADE_STATUS_NO_TARGET = 6,
TRADE_STATUS_BACK_TO_TRADE = 7,
TRADE_STATUS_TRADE_COMPLETE = 8,
- // 9?
+ TRADE_STATUS_TRADE_REJECTED = 9,
TRADE_STATUS_TARGET_TO_FAR = 10,
TRADE_STATUS_WRONG_FACTION = 11,
TRADE_STATUS_CLOSE_WINDOW = 12,
@@ -3413,8 +3413,8 @@ enum TradeStatus
TRADE_STATUS_YOU_LOGOUT = 19,
TRADE_STATUS_TARGET_LOGOUT = 20,
TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action
- TRADE_STATUS_ONLY_CONJURED = 22, // You can only trade conjured items... (cross realm BG related).
- TRADE_STATUS_NOT_ELIGIBLE = 23 // Related to trading soulbound loot items
+ TRADE_STATUS_WRONG_REALM = 22, // You can only trade conjured items... (cross realm BG related).
+ TRADE_STATUS_NOT_ON_TAPLIST = 23 // Related to trading soulbound loot items
};
enum XPColorChar
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index d5b2146ae79..5cf85596a3a 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -52,6 +52,7 @@ struct AuctionEntry;
struct DeclinedName;
struct ItemTemplate;
struct MovementInfo;
+struct TradeStatusInfo;
namespace lfg
{
@@ -297,7 +298,7 @@ class WorldSession
void SendBattleGroundList(uint64 guid, BattlegroundTypeId bgTypeId = BATTLEGROUND_RB);
- void SendTradeStatus(TradeStatus status);
+ void SendTradeStatus(TradeStatusInfo const& status);
void SendUpdateTrade(bool trader_data = true);
void SendCancelTrade();