aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Server
diff options
context:
space:
mode:
authorShauren <none@none>2010-06-25 13:15:51 +0200
committerShauren <none@none>2010-06-25 13:15:51 +0200
commit456c6291ab70f2f3182a4d63408c45099eedbbdd (patch)
tree21aa76d9107d54a70572d5ac450362fce276ce74 /src/server/game/Server
parenteb79fb91a6eb410a5a5ceb6259b9d4bc5569c2ae (diff)
Move trade data to dynamic structure and added support for applying enchant after trade ends, based on Vladimir's commits
--HG-- branch : trunk
Diffstat (limited to 'src/server/game/Server')
-rw-r--r--src/server/game/Server/Protocol/Handlers/TradeHandler.cpp499
-rw-r--r--src/server/game/Server/WorldSession.h4
2 files changed, 280 insertions, 223 deletions
diff --git a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp
index 448a6e0520d..6191b88587e 100644
--- a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp
@@ -27,37 +27,11 @@
#include "Opcodes.h"
#include "Player.h"
#include "Item.h"
+#include "Spell.h"
#include "SocialMgr.h"
#include "Language.h"
-enum TradeStatus
-{
- TRADE_STATUS_BUSY = 0,
- TRADE_STATUS_BEGIN_TRADE = 1,
- TRADE_STATUS_OPEN_WINDOW = 2,
- TRADE_STATUS_TRADE_CANCELED = 3,
- TRADE_STATUS_TRADE_ACCEPT = 4,
- TRADE_STATUS_BUSY_2 = 5,
- TRADE_STATUS_NO_TARGET = 6,
- TRADE_STATUS_BACK_TO_TRADE = 7,
- TRADE_STATUS_TRADE_COMPLETE = 8,
- // 9?
- TRADE_STATUS_TARGET_TO_FAR = 10,
- TRADE_STATUS_WRONG_FACTION = 11,
- TRADE_STATUS_CLOSE_WINDOW = 12,
- // 13?
- TRADE_STATUS_IGNORE_YOU = 14,
- TRADE_STATUS_YOU_STUNNED = 15,
- TRADE_STATUS_TARGET_STUNNED = 16,
- TRADE_STATUS_YOU_DEAD = 17,
- TRADE_STATUS_TARGET_DEAD = 18,
- 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).
-};
-
-void WorldSession::SendTradeStatus(uint32 status)
+void WorldSession::SendTradeStatus(TradeStatus status)
{
WorldPacket data;
@@ -106,68 +80,50 @@ void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/)
// recvPacket.print_storage();
}
-void WorldSession::SendUpdateTrade()
+void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
{
- Item *item = NULL;
+ TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData();
- if (!_player || !_player->pTrader)
- return;
+ 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(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
+ data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item
- // reset trade status
- if (_player->acceptTrade)
- {
- _player->acceptTrade = false;
- SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- }
-
- if (_player->pTrader->acceptTrade)
- {
- _player->pTrader->acceptTrade = false;
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- }
-
- WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100)); // guess size
- data << (uint8) 1; // can be different (only seen 0 and 1)
- 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) 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) _player->pTrader->tradeGold; // trader gold
- data << (uint32) 0; // spell casted on lowest slot item
+ Item *item = NULL;
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
{
- item = (_player->pTrader->tradeItems[i] != 0 ? _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]) : NULL);
+ data << uint8(i); // trade slot number, if not specified, then end of packet
- data << (uint8) i; // trade slot number, if not specified, then end of packet
-
- if (item)
+ if (Item* item = view_trade->GetItem(TradeSlots(i)))
{
- data << (uint32) item->GetProto()->ItemId; // entry
- // display id
- data << (uint32) item->GetProto()->DisplayInfoID;
- // stack count
- data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
- data << (uint32) 0; // probably gift=1, created_by=0?
- // gift creator
- data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR);
- data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT);
- for (uint8 j = 0; j < 3; ++j)
- data << (uint32) 0; // enchantment id (permanent/gems?)
+ data << uint32(item->GetProto()->ItemId); // entry
+ data << uint32(item->GetProto()->DisplayInfoID);// display id
+ data << uint32(item->GetCount()); // stack count
+ // wrapped: hide stats but show giftcreator name
+ data << uint32(item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED) ? 1 : 0);
+ data << uint64(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR));
+ // perm. enchantment and gems
+ data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
+ for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
+ data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
// creator
- data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR);
- data << (uint32) item->GetSpellCharges(); // charges
- data << (uint32) item->GetItemSuffixFactor(); // SuffixFactor
- // random properties id
- data << (int32) item->GetItemRandomPropertyId();
- data << (uint32) item->GetProto()->LockID; // lock id
+ data << uint64(item->GetUInt64Value(ITEM_FIELD_CREATOR));
+ data << uint32(item->GetSpellCharges()); // charges
+ data << uint32(item->GetItemSuffixFactor()); // SuffixFactor
+ data << uint32(item->GetItemRandomPropertyId());// random properties id
+ data << uint32(item->GetProto()->LockID); // lock id
// max durability
- data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
+ data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
// durability
- data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY);
+ data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
}
else
{
- for (uint8 j = 0; j < 18; j++)
+ for (uint8 j = 0; j < 18; ++j)
data << uint32(0);
}
}
@@ -179,11 +135,15 @@ void WorldSession::SendUpdateTrade()
void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
{
- for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
+ Player* trader = _player->GetTrader();
+ if (!trader)
+ return;
+
+ for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
ItemPosCountVec traderDst;
ItemPosCountVec playerDst;
- bool traderCanTrade = (myItems[i] == NULL || _player->pTrader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, myItems[i], false) == EQUIP_ERR_OK);
+ bool traderCanTrade = (myItems[i] == NULL || trader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, myItems[i], false) == EQUIP_ERR_OK);
bool playerCanTrade = (hisItems[i] == NULL || _player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, hisItems[i], false) == EQUIP_ERR_OK);
if (traderCanTrade && playerCanTrade)
{
@@ -196,25 +156,25 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
sLog.outDebug("partner storing: %u",myItems[i]->GetGUIDLow());
if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
- sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
- _player->GetName(),_player->GetSession()->GetAccountId(),
- myItems[i]->GetProto()->Name1,myItems[i]->GetEntry(),myItems[i]->GetCount(),
- _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId());
+ sLog.outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
+ _player->GetName(), _player->GetSession()->GetAccountId(),
+ myItems[i]->GetProto()->Name1, myItems[i]->GetEntry(), myItems[i]->GetCount(),
+ trader->GetName(), trader->GetSession()->GetAccountId());
}
// store
- _player->pTrader->MoveItemToInventory(traderDst, myItems[i], true, true);
+ trader->MoveItemToInventory(traderDst, myItems[i], true, true);
}
if (hisItems[i])
{
// logging
sLog.outDebug("player storing: %u",hisItems[i]->GetGUIDLow());
- if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
+ if (trader->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
- sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
- _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(),
- hisItems[i]->GetProto()->Name1,hisItems[i]->GetEntry(),hisItems[i]->GetCount(),
- _player->GetName(),_player->GetSession()->GetAccountId());
+ sLog.outCommand(trader->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
+ trader->GetName(), trader->GetSession()->GetAccountId(),
+ hisItems[i]->GetProto()->Name1, hisItems[i]->GetEntry(), hisItems[i]->GetCount(),
+ _player->GetName(), _player->GetSession()->GetAccountId());
}
// store
@@ -239,8 +199,8 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
{
if (!playerCanTrade)
sLog.outError("player can't store item: %u",hisItems[i]->GetGUIDLow());
- if (_player->pTrader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK)
- _player->pTrader->MoveItemToInventory(traderDst, hisItems[i], true, true);
+ if (trader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK)
+ trader->MoveItemToInventory(traderDst, hisItems[i], true, true);
else
sLog.outError("trader can't take item back: %u",hisItems[i]->GetGUIDLow());
}
@@ -250,135 +210,231 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
//==============================================================
+static void setAcceptTradeMode(TradeData* myTrade, TradeData* hisTrade, Item **myItems, Item **hisItems)
+{
+ myTrade->SetInAcceptProcess(true);
+ hisTrade->SetInAcceptProcess(true);
+
+ // store items in local list and set 'in-trade' flag
+ for(uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
+ {
+ if (Item* item = myTrade->GetItem(TradeSlots(i)))
+ {
+ DEBUG_LOG("player trade item %u bag: %u slot: %u", item->GetGUIDLow(), item->GetBagSlot(), item->GetSlot());
+ //Can return NULL
+ myItems[i] = item;
+ myItems[i]->SetInTrade();
+ }
+
+ if (Item* item = hisTrade->GetItem(TradeSlots(i)))
+ {
+ DEBUG_LOG("partner trade item %u bag: %u slot: %u", item->GetGUIDLow(), item->GetBagSlot(), item->GetSlot());
+ hisItems[i] = item;
+ hisItems[i]->SetInTrade();
+ }
+ }
+}
+
+static void clearAcceptTradeMode(TradeData* myTrade, TradeData* hisTrade)
+{
+ myTrade->SetInAcceptProcess(false);
+ hisTrade->SetInAcceptProcess(false);
+}
+
+static void clearAcceptTradeMode(Item **myItems, Item **hisItems)
+{
+ // clear 'in-trade' flag
+ for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
+ {
+ if (myItems[i])
+ myItems[i]->SetInTrade(false);
+ if (hisItems[i])
+ hisItems[i]->SetInTrade(false);
+ }
+}
+
void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
+ TradeData* my_trade = _player->m_trade;
+ if (!my_trade)
+ return;
+
+ Player* trader = my_trade->GetTrader();
+
+ TradeData* his_trade = trader->m_trade;
+ if (!his_trade)
+ return;
+
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;
+ bool myCanCompleteTrade = true, hisCanCompleteTrade = true;
- if (!GetPlayer()->pTrader)
- return;
+ // set before checks for propertly undo at problems (it already set in to client)
+ my_trade->SetAccepted(true);
// not accept case incorrect money amount
- if (_player->tradeGold > _player->GetMoney())
+ if (my_trade->GetMoney() > _player->GetMoney())
{
SendNotification(LANG_NOT_ENOUGH_GOLD);
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- _player->acceptTrade = false;
+ my_trade->SetAccepted(false, true);
return;
}
// not accept case incorrect money amount
- if (_player->pTrader->tradeGold > _player->pTrader->GetMoney())
+ if (his_trade->GetMoney() > trader->GetMoney())
{
- _player->pTrader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD);
- SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- _player->pTrader->acceptTrade = false;
+ trader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD);
+ his_trade->SetAccepted(false, true);
return;
}
// not accept if some items now can't be trade (cheating)
- for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
+ for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
- if (_player->tradeItems[i] != 0)
+ if (Item* item = my_trade->GetItem(TradeSlots(i)))
{
- if (Item* item =_player->GetItemByGuid(_player->tradeItems[i]))
+ if (!item->CanBeTraded())
{
- if (!item->CanBeTraded())
- {
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
- return;
- }
+ SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ return;
}
}
- if (_player->pTrader->tradeItems[i] != 0)
+
+ if (Item* item = his_trade->GetItem(TradeSlots(i)))
{
- if (Item* item =_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]))
+ if (!item->CanBeTraded())
{
- if (!item->CanBeTraded())
- {
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
- return;
- }
+ SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ return;
}
}
}
- _player->acceptTrade = true;
- if (_player->pTrader->acceptTrade)
+ if (his_trade->IsAccepted())
{
- // inform partner client
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
+ setAcceptTradeMode(my_trade, his_trade, myItems, hisItems);
+
+ Spell* my_spell = NULL;
+ SpellCastTargets my_targets;
+
+ Spell* his_spell = NULL;
+ SpellCastTargets his_targets;
- // store items in local list and set 'in-trade' flag
- for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
+ // not accept if spell can't be casted now (cheating)
+ if (uint32 my_spell_id = my_trade->GetSpell())
{
- if (_player->tradeItems[i] != 0)
+ SpellEntry const* spellEntry = sSpellStore.LookupEntry(my_spell_id);
+ Item* castItem = my_trade->GetSpellCastItem();
+
+ if (!spellEntry || !his_trade->GetItem(TRADE_SLOT_NONTRADED) ||
+ my_trade->HasSpellCastItem() && !castItem)
{
- //Can return NULL
- myItems[i] = _player->GetItemByGuid(_player->tradeItems[i]);
- if (myItems[i])
- {
- myItems[i]->SetInTrade();
- sLog.outDebug("Player trade item bag: %u slot: %u", myItems[i]->GetBagSlot(), myItems[i]->GetSlot());
- }
+ clearAcceptTradeMode(my_trade, his_trade);
+ clearAcceptTradeMode(myItems, hisItems);
+
+ my_trade->SetSpell(0);
+ return;
}
- if (_player->pTrader->tradeItems[i] != 0)
+
+ my_spell = new Spell(_player, spellEntry, true);
+ my_spell->m_CastItem = castItem;
+ my_targets.setTradeItemTarget(_player);
+ my_spell->m_targets = my_targets;
+
+ SpellCastResult res = my_spell->CheckCast(true);
+ if (res != SPELL_CAST_OK)
{
- //Can return NULL
- hisItems[i]=_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]);
- if (hisItems[i])
- {
- hisItems[i]->SetInTrade();
- sLog.outDebug("Player trade item bag: %u slot: %u", hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot());
- }
+ my_spell->SendCastResult(res);
+
+ clearAcceptTradeMode(my_trade, his_trade);
+ clearAcceptTradeMode(myItems, hisItems);
+
+ delete my_spell;
+ my_trade->SetSpell(0);
+ return;
}
}
- // test if item will fit in each inventory
- hisCanCompleteTrade = (_player->pTrader->CanStoreItems(myItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
- myCanCompleteTrade = (_player->CanStoreItems(hisItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
-
- // clear 'in-trade' flag
- for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
+ // not accept if spell can't be casted now (cheating)
+ if (uint32 his_spell_id = his_trade->GetSpell())
{
- if (myItems[i]) myItems[i]->SetInTrade(false);
- if (hisItems[i]) hisItems[i]->SetInTrade(false);
+ SpellEntry const* spellEntry = sSpellStore.LookupEntry(his_spell_id);
+ Item* castItem = his_trade->GetSpellCastItem();
+
+ if (!spellEntry || !my_trade->GetItem(TRADE_SLOT_NONTRADED) || his_trade->HasSpellCastItem() && !castItem)
+ {
+ delete my_spell;
+ his_trade->SetSpell(0);
+
+ clearAcceptTradeMode(my_trade, his_trade);
+ clearAcceptTradeMode(myItems, hisItems);
+ return;
+ }
+
+ his_spell = new Spell(trader, spellEntry, true);
+ his_spell->m_CastItem = castItem;
+ his_targets.setTradeItemTarget(trader);
+ his_spell->m_targets = his_targets;
+
+ SpellCastResult res = his_spell->CheckCast(true);
+ if (res != SPELL_CAST_OK)
+ {
+ his_spell->SendCastResult(res);
+
+ clearAcceptTradeMode(my_trade, his_trade);
+ clearAcceptTradeMode(myItems, hisItems);
+
+ delete my_spell;
+ delete his_spell;
+
+ his_trade->SetSpell(0);
+ return;
+ }
}
+ // inform partner client
+ trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
+
+ // 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);
+
+ clearAcceptTradeMode(myItems, hisItems);
+
// in case of missing space report error
if (!myCanCompleteTrade)
{
+ clearAcceptTradeMode(my_trade, his_trade);
+
SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
- GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
- SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
+ trader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
+ my_trade->SetAccepted(false);
+ his_trade->SetAccepted(false);
return;
}
else if (!hisCanCompleteTrade)
{
+ clearAcceptTradeMode(my_trade, his_trade);
+
SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
- GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
- SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
+ trader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
+ my_trade->SetAccepted(false);
+ his_trade->SetAccepted(false);
return;
}
// execute trade: 1. remove
- for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
+ for (uint8 i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i)
{
- Item* iPtr = NULL;
if (myItems[i])
{
myItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
- iPtr = _player->GetItemByGuid(_player->tradeItems[i]);
- _player->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true);
+ _player->MoveItemFromInventory(myItems[i]->GetBagSlot(), myItems[i]->GetSlot(), true);
}
if (hisItems[i])
{
- hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR,_player->pTrader->GetGUID());
- iPtr = _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]);
- _player->pTrader->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true);
+ hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, trader->GetGUID());
+ trader->MoveItemFromInventory(hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot(), true);
}
}
@@ -388,72 +444,80 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
// logging money
if (sWorld.getConfig(CONFIG_GM_LOG_TRADE))
{
- if (_player->GetSession()->GetSecurity() > SEC_PLAYER && _player->tradeGold > 0)
+ if (_player->GetSession()->GetSecurity() > SEC_PLAYER && my_trade->GetMoney() > 0)
{
sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
- _player->GetName(),_player->GetSession()->GetAccountId(),
- _player->tradeGold,
- _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId());
+ _player->GetName(), _player->GetSession()->GetAccountId(),
+ my_trade->GetMoney(),
+ trader->GetName(), trader->GetSession()->GetAccountId());
}
- if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && _player->pTrader->tradeGold > 0)
+ if (trader->GetSession()->GetSecurity() > SEC_PLAYER && his_trade->GetMoney() > 0)
{
- sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
- _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(),
- _player->pTrader->tradeGold,
- _player->GetName(),_player->GetSession()->GetAccountId());
+ sLog.outCommand(trader->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
+ trader->GetName(), trader->GetSession()->GetAccountId(),
+ his_trade->GetMoney(),
+ _player->GetName(), _player->GetSession()->GetAccountId());
}
}
// update money
- _player->ModifyMoney(-int32(_player->tradeGold));
- _player->ModifyMoney(_player->pTrader->tradeGold);
- _player->pTrader->ModifyMoney(-int32(_player->pTrader->tradeGold));
- _player->pTrader->ModifyMoney(_player->tradeGold);
+ _player->ModifyMoney(-int32(my_trade->GetMoney()));
+ _player->ModifyMoney(his_trade->GetMoney());
+ trader->ModifyMoney(-int32(his_trade->GetMoney()));
+ trader->ModifyMoney(my_trade->GetMoney());
+
+ if (my_spell)
+ my_spell->prepare(&my_targets);
+
+ if (his_spell)
+ his_spell->prepare(&his_targets);
- _player->ClearTrade();
- _player->pTrader->ClearTrade();
+ // cleanup
+ clearAcceptTradeMode(my_trade, his_trade);
+ delete _player->m_trade;
+ _player->m_trade = NULL;
+ delete trader->m_trade;
+ trader->m_trade = NULL;
// desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards)
CharacterDatabase.BeginTransaction();
_player->SaveInventoryAndGoldToDB();
- _player->pTrader->SaveInventoryAndGoldToDB();
+ trader->SaveInventoryAndGoldToDB();
CharacterDatabase.CommitTransaction();
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
+ trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
-
- _player->pTrader->pTrader = NULL;
- _player->pTrader = NULL;
}
else
{
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
+ trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
}
}
void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/)
{
- if (!GetPlayer()->pTrader)
+ TradeData* my_trade = _player->GetTradeData();
+ if (!my_trade)
return;
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
- _player->acceptTrade = false;
+ my_trade->SetAccepted(false, true);
}
void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/)
{
- if (!_player->pTrader)
+ TradeData* my_trade = _player->m_trade;
+ if (!my_trade)
return;
- _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
- _player->pTrader->ClearTrade();
-
+ my_trade->GetTrader()->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
- _player->ClearTrade();
}
void WorldSession::SendCancelTrade()
{
+ if (m_playerRecentlyLogout)
+ return;
+
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
}
@@ -466,7 +530,7 @@ void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
{
- if (GetPlayer()->pTrader)
+ if (GetPlayer()->m_trade)
return;
uint64 ID;
@@ -511,7 +575,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
- if (pOther == GetPlayer() || pOther->pTrader)
+ if (pOther == GetPlayer() || pOther->m_trade)
{
SendTradeStatus(TRADE_STATUS_BUSY);
return;
@@ -566,35 +630,30 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
}
// OK start trade
- _player->pTrader = pOther;
- pOther->pTrader =_player;
+ _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();
- _player->pTrader->GetSession()->SendPacket(&data);
+ data << uint32(TRADE_STATUS_BEGIN_TRADE);
+ data << uint64(_player->GetGUID());
+ pOther->GetSession()->SendPacket(&data);
}
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
{
- if (!_player->pTrader)
- return;
-
uint32 gold;
-
recvPacket >> gold;
- // gold can be incorrect, but this is checked at trade finished.
- _player->tradeGold = gold;
+ TradeData* my_trade = _player->GetTradeData();
+ if (!my_trade)
+ return;
- _player->pTrader->GetSession()->SendUpdateTrade();
+ // gold can be incorrect, but this is checked at trade finished.
+ my_trade->SetMoney(gold);
}
void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
{
- if (!_player->pTrader)
- return;
-
// send update
uint8 tradeSlot;
uint8 bag;
@@ -604,6 +663,10 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
recvPacket >> bag;
recvPacket >> slot;
+ TradeData* my_trade = _player->GetTradeData();
+ if (!my_trade)
+ return;
+
// invalid slot number
if (tradeSlot >= TRADE_SLOT_COUNT)
{
@@ -612,7 +675,7 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
}
// check cheating, can't fail with correct client operations
- Item* item = _player->GetItemByPos(bag,slot);
+ Item* item = _player->GetItemByPos(bag, slot);
if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded()))
{
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
@@ -622,35 +685,29 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
uint64 iGUID = item->GetGUID();
// prevent place single item into many trade slots using cheating and client bugs
- for (int i = 0; i < TRADE_SLOT_COUNT; ++i)
+ if (my_trade->HasItem(iGUID))
{
- if (_player->tradeItems[i] == iGUID)
- {
- // cheating attempt
- SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
- return;
- }
+ // cheating attempt
+ SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+ return;
}
- _player->tradeItems[tradeSlot] = iGUID;
-
- _player->pTrader->GetSession()->SendUpdateTrade();
+ my_trade->SetItem(TradeSlots(tradeSlot), item);
}
void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket)
{
- if (!_player->pTrader)
- return;
-
uint8 tradeSlot;
recvPacket >> tradeSlot;
+ TradeData* my_trade = _player->m_trade;
+ if (!my_trade)
+ return;
+
// invalid slot number
if (tradeSlot >= TRADE_SLOT_COUNT)
return;
- _player->tradeItems[tradeSlot] = 0;
-
- _player->pTrader->GetSession()->SendUpdateTrade();
+ my_trade->SetItem(TradeSlots(tradeSlot), NULL);
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index c17f3e3f3e6..dbcc94f071b 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -205,12 +205,12 @@ class WorldSession
void SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId);
- void SendTradeStatus(uint32 status);
+ void SendTradeStatus(TradeStatus status);
void SendCancelTrade();
void SendStablePet(uint64 guid);
void SendPetitionQueryOpcode(uint64 petitionguid);
- void SendUpdateTrade();
+ void SendUpdateTrade(bool trader_data = true);
//pet
void SendPetNameQuery(uint64 guid, uint32 petnumber);