Move trade data to dynamic structure and added support for applying enchant after trade ends, based on Vladimir's commits
--HG-- branch : trunk
This commit is contained in:
@@ -280,6 +280,105 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
|
|||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//== TradeData =================================================
|
||||||
|
|
||||||
|
TradeData* TradeData::GetTraderData() const
|
||||||
|
{
|
||||||
|
return m_trader->GetTradeData();
|
||||||
|
}
|
||||||
|
|
||||||
|
Item* TradeData::GetItem(TradeSlots slot) const
|
||||||
|
{
|
||||||
|
return m_items[slot] ? m_player->GetItemByGuid(m_items[slot]) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TradeData::HasItem(uint64 item_guid) const
|
||||||
|
{
|
||||||
|
for(uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
|
||||||
|
if (m_items[i] == item_guid)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item* TradeData::GetSpellCastItem() const
|
||||||
|
{
|
||||||
|
return m_spellCastItem ? m_player->GetItemByGuid(m_spellCastItem) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TradeData::SetItem(TradeSlots slot, Item* item)
|
||||||
|
{
|
||||||
|
uint64 itemGuid = item ? item->GetGUID() : 0;
|
||||||
|
|
||||||
|
if (m_items[slot] == itemGuid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_items[slot] = itemGuid;
|
||||||
|
|
||||||
|
SetAccepted(false);
|
||||||
|
GetTraderData()->SetAccepted(false);
|
||||||
|
|
||||||
|
Update();
|
||||||
|
|
||||||
|
// need remove possible trader spell applied to changed item
|
||||||
|
if (slot == TRADE_SLOT_NONTRADED)
|
||||||
|
GetTraderData()->SetSpell(0);
|
||||||
|
|
||||||
|
// need remove possible player spell applied (possible move reagent)
|
||||||
|
SetSpell(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= NULL*/)
|
||||||
|
{
|
||||||
|
uint64 itemGuid = castItem ? castItem->GetGUID() : 0;
|
||||||
|
|
||||||
|
if (m_spell == spell_id && m_spellCastItem == itemGuid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_spell = spell_id;
|
||||||
|
m_spellCastItem = itemGuid;
|
||||||
|
|
||||||
|
SetAccepted(false);
|
||||||
|
GetTraderData()->SetAccepted(false);
|
||||||
|
|
||||||
|
Update(true); // send spell info to item owner
|
||||||
|
Update(false); // send spell info to caster self
|
||||||
|
}
|
||||||
|
|
||||||
|
void TradeData::SetMoney(uint32 money)
|
||||||
|
{
|
||||||
|
if (m_money == money)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_money = money;
|
||||||
|
|
||||||
|
SetAccepted(false);
|
||||||
|
GetTraderData()->SetAccepted(false);
|
||||||
|
|
||||||
|
Update(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TradeData::Update(bool forTarget /*= true*/)
|
||||||
|
{
|
||||||
|
if (forTarget)
|
||||||
|
m_trader->GetSession()->SendUpdateTrade(true); // player state for trader
|
||||||
|
else
|
||||||
|
m_player->GetSession()->SendUpdateTrade(false); // player state for player
|
||||||
|
}
|
||||||
|
|
||||||
|
void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
|
||||||
|
{
|
||||||
|
m_accepted = state;
|
||||||
|
|
||||||
|
if (!state)
|
||||||
|
{
|
||||||
|
if (crosssend)
|
||||||
|
m_trader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
||||||
|
else
|
||||||
|
m_player->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// == Player ====================================================
|
// == Player ====================================================
|
||||||
|
|
||||||
UpdateMask Player::updateVisualBits;
|
UpdateMask Player::updateVisualBits;
|
||||||
@@ -354,8 +453,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
|
|||||||
m_bHasDelayedTeleport = false;
|
m_bHasDelayedTeleport = false;
|
||||||
m_teleport_options = 0;
|
m_teleport_options = 0;
|
||||||
|
|
||||||
pTrader = 0;
|
m_trade = NULL;
|
||||||
ClearTrade();
|
|
||||||
|
|
||||||
m_cinematic = 0;
|
m_cinematic = 0;
|
||||||
|
|
||||||
@@ -9539,7 +9637,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
|
|||||||
for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++)
|
for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; i++)
|
||||||
{
|
{
|
||||||
Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||||
if (pItem && pItem->GetEntry() == item)
|
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
tempcount += pItem->GetCount();
|
tempcount += pItem->GetCount();
|
||||||
if (tempcount >= count)
|
if (tempcount >= count)
|
||||||
@@ -9549,7 +9647,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
|
|||||||
for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
|
for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i)
|
||||||
{
|
{
|
||||||
Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||||
if (pItem && pItem->GetEntry() == item)
|
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
tempcount += pItem->GetCount();
|
tempcount += pItem->GetCount();
|
||||||
if (tempcount >= count)
|
if (tempcount >= count)
|
||||||
@@ -9563,7 +9661,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
|
|||||||
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
||||||
{
|
{
|
||||||
Item* pItem = GetItemByPos(i, j);
|
Item* pItem = GetItemByPos(i, j);
|
||||||
if (pItem && pItem->GetEntry() == item)
|
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
tempcount += pItem->GetCount();
|
tempcount += pItem->GetCount();
|
||||||
if (tempcount >= count)
|
if (tempcount >= count)
|
||||||
@@ -9578,7 +9676,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
|
|||||||
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
|
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
|
||||||
{
|
{
|
||||||
Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
Item *pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
|
||||||
if (pItem && pItem->GetEntry() == item)
|
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
tempcount += pItem->GetCount();
|
tempcount += pItem->GetCount();
|
||||||
if (tempcount >= count)
|
if (tempcount >= count)
|
||||||
@@ -9592,7 +9690,7 @@ bool Player::HasItemCount(uint32 item, uint32 count, bool inBankAlso) const
|
|||||||
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
||||||
{
|
{
|
||||||
Item* pItem = GetItemByPos(i, j);
|
Item* pItem = GetItemByPos(i, j);
|
||||||
if (pItem && pItem->GetEntry() == item)
|
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
tempcount += pItem->GetCount();
|
tempcount += pItem->GetCount();
|
||||||
if (tempcount >= count)
|
if (tempcount >= count)
|
||||||
@@ -11813,7 +11911,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ
|
|||||||
{
|
{
|
||||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
{
|
{
|
||||||
if (pItem->GetEntry() == item)
|
if (pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
if (pItem->GetCount() + remcount <= count)
|
if (pItem->GetCount() + remcount <= count)
|
||||||
{
|
{
|
||||||
@@ -11841,7 +11939,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ
|
|||||||
{
|
{
|
||||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
{
|
{
|
||||||
if (pItem->GetEntry() == item)
|
if (pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
if (pItem->GetCount() + remcount <= count)
|
if (pItem->GetCount() + remcount <= count)
|
||||||
{
|
{
|
||||||
@@ -11874,7 +11972,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ
|
|||||||
{
|
{
|
||||||
if (Item* pItem = pBag->GetItemByPos(j))
|
if (Item* pItem = pBag->GetItemByPos(j))
|
||||||
{
|
{
|
||||||
if (pItem->GetEntry() == item)
|
if (pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
// all items in bags can be unequipped
|
// all items in bags can be unequipped
|
||||||
if (pItem->GetCount() + remcount <= count)
|
if (pItem->GetCount() + remcount <= count)
|
||||||
@@ -11905,7 +12003,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ
|
|||||||
{
|
{
|
||||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||||
{
|
{
|
||||||
if (pItem && pItem->GetEntry() == item)
|
if (pItem && pItem->GetEntry() == item && !pItem->IsInTrade())
|
||||||
{
|
{
|
||||||
if (pItem->GetCount() + remcount <= count)
|
if (pItem->GetCount() + remcount <= count)
|
||||||
{
|
{
|
||||||
@@ -12663,33 +12761,23 @@ void Player::SendSellError(uint8 msg, Creature* pCreature, uint64 guid, uint32 p
|
|||||||
GetSession()->SendPacket(&data);
|
GetSession()->SendPacket(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::ClearTrade()
|
|
||||||
{
|
|
||||||
tradeGold = 0;
|
|
||||||
acceptTrade = false;
|
|
||||||
for (uint8 i = 0; i < TRADE_SLOT_COUNT; i++)
|
|
||||||
tradeItems[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::TradeCancel(bool sendback)
|
void Player::TradeCancel(bool sendback)
|
||||||
{
|
{
|
||||||
if (pTrader)
|
if (m_trade)
|
||||||
{
|
{
|
||||||
|
Player* trader = m_trade->GetTrader();
|
||||||
|
|
||||||
// send yellow "Trade canceled" message to both traders
|
// send yellow "Trade canceled" message to both traders
|
||||||
WorldSession* ws;
|
|
||||||
ws = GetSession();
|
|
||||||
if (sendback)
|
if (sendback)
|
||||||
ws->SendCancelTrade();
|
GetSession()->SendCancelTrade();
|
||||||
ws = pTrader->GetSession();
|
|
||||||
if (!ws->PlayerLogout())
|
trader->GetSession()->SendCancelTrade();
|
||||||
ws->SendCancelTrade();
|
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
ClearTrade();
|
delete m_trade;
|
||||||
pTrader->ClearTrade();
|
m_trade = NULL;
|
||||||
// prevent loss of reference
|
delete trader->m_trade;
|
||||||
pTrader->pTrader = NULL;
|
trader->m_trade = NULL;
|
||||||
pTrader = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -920,6 +920,55 @@ struct BGData
|
|||||||
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
|
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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) {}
|
||||||
|
|
||||||
|
Player* GetTrader() const { return m_trader; }
|
||||||
|
TradeData* GetTraderData() const;
|
||||||
|
|
||||||
|
Item* GetItem(TradeSlots slot) const;
|
||||||
|
bool HasItem(uint64 item_guid) const;
|
||||||
|
void SetItem(TradeSlots slot, Item* item);
|
||||||
|
|
||||||
|
uint32 GetSpell() const { return m_spell; }
|
||||||
|
void SetSpell(uint32 spell_id, Item* castItem = NULL);
|
||||||
|
|
||||||
|
Item* GetSpellCastItem() const;
|
||||||
|
bool HasSpellCastItem() const { return m_spellCastItem != 0; }
|
||||||
|
|
||||||
|
uint32 GetMoney() const { return m_money; }
|
||||||
|
void SetMoney(uint32 money);
|
||||||
|
|
||||||
|
bool IsAccepted() const { return m_accepted; }
|
||||||
|
void SetAccepted(bool state, bool crosssend = false);
|
||||||
|
|
||||||
|
bool IsInAcceptProcess() const { return m_acceptProccess; }
|
||||||
|
void SetInAcceptProcess(bool state) { m_acceptProccess = state; }
|
||||||
|
|
||||||
|
private: // internal functions
|
||||||
|
|
||||||
|
void Update(bool for_trader = true);
|
||||||
|
|
||||||
|
private: // fields
|
||||||
|
|
||||||
|
Player* m_player; // Player who own of this TradeData
|
||||||
|
Player* m_trader; // Player who trade with m_player
|
||||||
|
|
||||||
|
bool m_accepted; // m_player press accept for trade list
|
||||||
|
bool m_acceptProccess; // one from player/trader press accept and this processed
|
||||||
|
|
||||||
|
uint32 m_money; // m_player place money to trade
|
||||||
|
|
||||||
|
uint32 m_spell; // m_player apply spell to non-traded slot item
|
||||||
|
uint64 m_spellCastItem; // applied spell casted by item use
|
||||||
|
|
||||||
|
uint64 m_items[TRADE_SLOT_COUNT]; // traded itmes from m_player side including non-traded slot
|
||||||
|
};
|
||||||
|
|
||||||
class Player : public Unit, public GridObject<Player>
|
class Player : public Unit, public GridObject<Player>
|
||||||
{
|
{
|
||||||
friend class WorldSession;
|
friend class WorldSession;
|
||||||
@@ -1191,15 +1240,10 @@ class Player : public Unit, public GridObject<Player>
|
|||||||
bool BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
|
bool BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
|
||||||
|
|
||||||
float GetReputationPriceDiscount(Creature const* pCreature) const;
|
float GetReputationPriceDiscount(Creature const* pCreature) const;
|
||||||
Player* GetTrader() const { return pTrader; }
|
|
||||||
void ClearTrade();
|
Player* GetTrader() const { return m_trade ? m_trade->GetTrader() : NULL; }
|
||||||
|
TradeData* GetTradeData() const { return m_trade; }
|
||||||
void TradeCancel(bool sendback);
|
void TradeCancel(bool sendback);
|
||||||
Item *GetItemByTradeSlot(uint8 slot) const
|
|
||||||
{
|
|
||||||
if (slot < TRADE_SLOT_COUNT && tradeItems[slot])
|
|
||||||
return GetItemByGuid(tradeItems[slot]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateEnchantTime(uint32 time);
|
void UpdateEnchantTime(uint32 time);
|
||||||
void UpdateItemDuration(uint32 time, bool realtimeonly=false);
|
void UpdateItemDuration(uint32 time, bool realtimeonly=false);
|
||||||
@@ -2460,10 +2504,7 @@ class Player : public Unit, public GridObject<Player>
|
|||||||
|
|
||||||
int m_cinematic;
|
int m_cinematic;
|
||||||
|
|
||||||
Player *pTrader;
|
TradeData* m_trade;
|
||||||
bool acceptTrade;
|
|
||||||
uint64 tradeItems[TRADE_SLOT_COUNT];
|
|
||||||
uint32 tradeGold;
|
|
||||||
|
|
||||||
bool m_DailyQuestChanged;
|
bool m_DailyQuestChanged;
|
||||||
bool m_WeeklyQuestChanged;
|
bool m_WeeklyQuestChanged;
|
||||||
|
|||||||
@@ -2769,4 +2769,31 @@ enum SpellFamilyNames
|
|||||||
SPELLFAMILY_PET = 17
|
SPELLFAMILY_PET = 17
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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).
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,37 +27,11 @@
|
|||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
|
#include "Spell.h"
|
||||||
#include "SocialMgr.h"
|
#include "SocialMgr.h"
|
||||||
#include "Language.h"
|
#include "Language.h"
|
||||||
|
|
||||||
enum TradeStatus
|
void WorldSession::SendTradeStatus(TradeStatus status)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
WorldPacket data;
|
WorldPacket data;
|
||||||
|
|
||||||
@@ -106,68 +80,50 @@ void WorldSession::HandleBusyTradeOpcode(WorldPacket& /*recvPacket*/)
|
|||||||
// recvPacket.print_storage();
|
// recvPacket.print_storage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::SendUpdateTrade()
|
void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
|
||||||
{
|
{
|
||||||
|
TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData();
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
Item *item = NULL;
|
Item *item = NULL;
|
||||||
|
|
||||||
if (!_player || !_player->pTrader)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
|
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* item = view_trade->GetItem(TradeSlots(i)))
|
||||||
|
|
||||||
if (item)
|
|
||||||
{
|
{
|
||||||
data << (uint32) item->GetProto()->ItemId; // entry
|
data << uint32(item->GetProto()->ItemId); // entry
|
||||||
// display id
|
data << uint32(item->GetProto()->DisplayInfoID);// display id
|
||||||
data << (uint32) item->GetProto()->DisplayInfoID;
|
data << uint32(item->GetCount()); // stack count
|
||||||
// stack count
|
// wrapped: hide stats but show giftcreator name
|
||||||
data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT);
|
data << uint32(item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED) ? 1 : 0);
|
||||||
data << (uint32) 0; // probably gift=1, created_by=0?
|
data << uint64(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR));
|
||||||
// gift creator
|
// perm. enchantment and gems
|
||||||
data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR);
|
data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
|
||||||
data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT);
|
for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
|
||||||
for (uint8 j = 0; j < 3; ++j)
|
data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
|
||||||
data << (uint32) 0; // enchantment id (permanent/gems?)
|
|
||||||
// creator
|
// creator
|
||||||
data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR);
|
data << uint64(item->GetUInt64Value(ITEM_FIELD_CREATOR));
|
||||||
data << (uint32) item->GetSpellCharges(); // charges
|
data << uint32(item->GetSpellCharges()); // charges
|
||||||
data << (uint32) item->GetItemSuffixFactor(); // SuffixFactor
|
data << uint32(item->GetItemSuffixFactor()); // SuffixFactor
|
||||||
// random properties id
|
data << uint32(item->GetItemRandomPropertyId());// random properties id
|
||||||
data << (int32) item->GetItemRandomPropertyId();
|
data << uint32(item->GetProto()->LockID); // lock id
|
||||||
data << (uint32) item->GetProto()->LockID; // lock id
|
|
||||||
// max durability
|
// max durability
|
||||||
data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
|
data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
|
||||||
// durability
|
// durability
|
||||||
data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY);
|
data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (uint8 j = 0; j < 18; j++)
|
for (uint8 j = 0; j < 18; ++j)
|
||||||
data << uint32(0);
|
data << uint32(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,11 +135,15 @@ void WorldSession::SendUpdateTrade()
|
|||||||
|
|
||||||
void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
|
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 traderDst;
|
||||||
ItemPosCountVec playerDst;
|
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);
|
bool playerCanTrade = (hisItems[i] == NULL || _player->CanStoreItem(NULL_BAG, NULL_SLOT, playerDst, hisItems[i], false) == EQUIP_ERR_OK);
|
||||||
if (traderCanTrade && playerCanTrade)
|
if (traderCanTrade && playerCanTrade)
|
||||||
{
|
{
|
||||||
@@ -196,25 +156,25 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
|
|||||||
sLog.outDebug("partner storing: %u",myItems[i]->GetGUIDLow());
|
sLog.outDebug("partner storing: %u",myItems[i]->GetGUIDLow());
|
||||||
if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
|
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)",
|
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(),
|
_player->GetName(), _player->GetSession()->GetAccountId(),
|
||||||
myItems[i]->GetProto()->Name1,myItems[i]->GetEntry(),myItems[i]->GetCount(),
|
myItems[i]->GetProto()->Name1, myItems[i]->GetEntry(), myItems[i]->GetCount(),
|
||||||
_player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId());
|
trader->GetName(), trader->GetSession()->GetAccountId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// store
|
// store
|
||||||
_player->pTrader->MoveItemToInventory(traderDst, myItems[i], true, true);
|
trader->MoveItemToInventory(traderDst, myItems[i], true, true);
|
||||||
}
|
}
|
||||||
if (hisItems[i])
|
if (hisItems[i])
|
||||||
{
|
{
|
||||||
// logging
|
// logging
|
||||||
sLog.outDebug("player storing: %u",hisItems[i]->GetGUIDLow());
|
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)",
|
sLog.outCommand(trader->GetSession()->GetAccountId(),"GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)",
|
||||||
_player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(),
|
trader->GetName(), trader->GetSession()->GetAccountId(),
|
||||||
hisItems[i]->GetProto()->Name1,hisItems[i]->GetEntry(),hisItems[i]->GetCount(),
|
hisItems[i]->GetProto()->Name1, hisItems[i]->GetEntry(), hisItems[i]->GetCount(),
|
||||||
_player->GetName(),_player->GetSession()->GetAccountId());
|
_player->GetName(), _player->GetSession()->GetAccountId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// store
|
// store
|
||||||
@@ -239,8 +199,8 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
|
|||||||
{
|
{
|
||||||
if (!playerCanTrade)
|
if (!playerCanTrade)
|
||||||
sLog.outError("player can't store item: %u",hisItems[i]->GetGUIDLow());
|
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)
|
if (trader->CanStoreItem(NULL_BAG, NULL_SLOT, traderDst, hisItems[i], false) == EQUIP_ERR_OK)
|
||||||
_player->pTrader->MoveItemToInventory(traderDst, hisItems[i], true, true);
|
trader->MoveItemToInventory(traderDst, hisItems[i], true, true);
|
||||||
else
|
else
|
||||||
sLog.outError("trader can't take item back: %u",hisItems[i]->GetGUIDLow());
|
sLog.outError("trader can't take item back: %u",hisItems[i]->GetGUIDLow());
|
||||||
}
|
}
|
||||||
@@ -250,39 +210,88 @@ 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*/)
|
void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
|
||||||
{
|
{
|
||||||
Item *myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
TradeData* my_trade = _player->m_trade;
|
||||||
Item *hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
if (!my_trade)
|
||||||
bool myCanCompleteTrade=true,hisCanCompleteTrade=true;
|
|
||||||
|
|
||||||
if (!GetPlayer()->pTrader)
|
|
||||||
return;
|
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;
|
||||||
|
|
||||||
|
// set before checks for propertly undo at problems (it already set in to client)
|
||||||
|
my_trade->SetAccepted(true);
|
||||||
|
|
||||||
// not accept case incorrect money amount
|
// not accept case incorrect money amount
|
||||||
if (_player->tradeGold > _player->GetMoney())
|
if (my_trade->GetMoney() > _player->GetMoney())
|
||||||
{
|
{
|
||||||
SendNotification(LANG_NOT_ENOUGH_GOLD);
|
SendNotification(LANG_NOT_ENOUGH_GOLD);
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
my_trade->SetAccepted(false, true);
|
||||||
_player->acceptTrade = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not accept case incorrect money amount
|
// 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);
|
trader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD);
|
||||||
SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
his_trade->SetAccepted(false, true);
|
||||||
_player->pTrader->acceptTrade = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not accept if some items now can't be trade (cheating)
|
// 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())
|
||||||
{
|
{
|
||||||
@@ -290,10 +299,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
|
|||||||
return;
|
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())
|
||||||
{
|
{
|
||||||
@@ -302,83 +309,132 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_player->acceptTrade = true;
|
if (his_trade->IsAccepted())
|
||||||
if (_player->pTrader->acceptTrade)
|
|
||||||
{
|
{
|
||||||
|
setAcceptTradeMode(my_trade, his_trade, myItems, hisItems);
|
||||||
|
|
||||||
|
Spell* my_spell = NULL;
|
||||||
|
SpellCastTargets my_targets;
|
||||||
|
|
||||||
|
Spell* his_spell = NULL;
|
||||||
|
SpellCastTargets his_targets;
|
||||||
|
|
||||||
|
// not accept if spell can't be casted now (cheating)
|
||||||
|
if (uint32 my_spell_id = my_trade->GetSpell())
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
clearAcceptTradeMode(my_trade, his_trade);
|
||||||
|
clearAcceptTradeMode(myItems, hisItems);
|
||||||
|
|
||||||
|
my_trade->SetSpell(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
my_spell->SendCastResult(res);
|
||||||
|
|
||||||
|
clearAcceptTradeMode(my_trade, his_trade);
|
||||||
|
clearAcceptTradeMode(myItems, hisItems);
|
||||||
|
|
||||||
|
delete my_spell;
|
||||||
|
my_trade->SetSpell(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not accept if spell can't be casted now (cheating)
|
||||||
|
if (uint32 his_spell_id = his_trade->GetSpell())
|
||||||
|
{
|
||||||
|
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
|
// inform partner client
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
|
trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
|
||||||
|
|
||||||
// store items in local list and set 'in-trade' flag
|
|
||||||
for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
|
|
||||||
{
|
|
||||||
if (_player->tradeItems[i] != 0)
|
|
||||||
{
|
|
||||||
//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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_player->pTrader->tradeItems[i] != 0)
|
|
||||||
{
|
|
||||||
//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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// test if item will fit in each inventory
|
// test if item will fit in each inventory
|
||||||
hisCanCompleteTrade = (_player->pTrader->CanStoreItems(myItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
|
hisCanCompleteTrade = (trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
|
||||||
myCanCompleteTrade = (_player->CanStoreItems(hisItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
|
myCanCompleteTrade = (_player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK);
|
||||||
|
|
||||||
// clear 'in-trade' flag
|
clearAcceptTradeMode(myItems, hisItems);
|
||||||
for (int i=0; i<TRADE_SLOT_TRADED_COUNT; ++i)
|
|
||||||
{
|
|
||||||
if (myItems[i]) myItems[i]->SetInTrade(false);
|
|
||||||
if (hisItems[i]) hisItems[i]->SetInTrade(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case of missing space report error
|
// in case of missing space report error
|
||||||
if (!myCanCompleteTrade)
|
if (!myCanCompleteTrade)
|
||||||
{
|
{
|
||||||
|
clearAcceptTradeMode(my_trade, his_trade);
|
||||||
|
|
||||||
SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
|
SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
|
||||||
GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
|
trader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
|
||||||
SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
my_trade->SetAccepted(false);
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
his_trade->SetAccepted(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!hisCanCompleteTrade)
|
else if (!hisCanCompleteTrade)
|
||||||
{
|
{
|
||||||
|
clearAcceptTradeMode(my_trade, his_trade);
|
||||||
|
|
||||||
SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
|
SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS);
|
||||||
GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
|
trader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS);
|
||||||
SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
my_trade->SetAccepted(false);
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
his_trade->SetAccepted(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute trade: 1. remove
|
// 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])
|
if (myItems[i])
|
||||||
{
|
{
|
||||||
myItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
|
myItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
|
||||||
iPtr = _player->GetItemByGuid(_player->tradeItems[i]);
|
_player->MoveItemFromInventory(myItems[i]->GetBagSlot(), myItems[i]->GetSlot(), true);
|
||||||
_player->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true);
|
|
||||||
}
|
}
|
||||||
if (hisItems[i])
|
if (hisItems[i])
|
||||||
{
|
{
|
||||||
hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR,_player->pTrader->GetGUID());
|
hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, trader->GetGUID());
|
||||||
iPtr = _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]);
|
trader->MoveItemFromInventory(hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot(), true);
|
||||||
_player->pTrader->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,72 +444,80 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
|
|||||||
// logging money
|
// logging money
|
||||||
if (sWorld.getConfig(CONFIG_GM_LOG_TRADE))
|
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)",
|
sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
|
||||||
_player->GetName(),_player->GetSession()->GetAccountId(),
|
_player->GetName(), _player->GetSession()->GetAccountId(),
|
||||||
_player->tradeGold,
|
my_trade->GetMoney(),
|
||||||
_player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId());
|
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)",
|
sLog.outCommand(trader->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)",
|
||||||
_player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(),
|
trader->GetName(), trader->GetSession()->GetAccountId(),
|
||||||
_player->pTrader->tradeGold,
|
his_trade->GetMoney(),
|
||||||
_player->GetName(),_player->GetSession()->GetAccountId());
|
_player->GetName(), _player->GetSession()->GetAccountId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update money
|
// update money
|
||||||
_player->ModifyMoney(-int32(_player->tradeGold));
|
_player->ModifyMoney(-int32(my_trade->GetMoney()));
|
||||||
_player->ModifyMoney(_player->pTrader->tradeGold);
|
_player->ModifyMoney(his_trade->GetMoney());
|
||||||
_player->pTrader->ModifyMoney(-int32(_player->pTrader->tradeGold));
|
trader->ModifyMoney(-int32(his_trade->GetMoney()));
|
||||||
_player->pTrader->ModifyMoney(_player->tradeGold);
|
trader->ModifyMoney(my_trade->GetMoney());
|
||||||
|
|
||||||
_player->ClearTrade();
|
if (my_spell)
|
||||||
_player->pTrader->ClearTrade();
|
my_spell->prepare(&my_targets);
|
||||||
|
|
||||||
|
if (his_spell)
|
||||||
|
his_spell->prepare(&his_targets);
|
||||||
|
|
||||||
|
// 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)
|
// desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards)
|
||||||
CharacterDatabase.BeginTransaction();
|
CharacterDatabase.BeginTransaction();
|
||||||
_player->SaveInventoryAndGoldToDB();
|
_player->SaveInventoryAndGoldToDB();
|
||||||
_player->pTrader->SaveInventoryAndGoldToDB();
|
trader->SaveInventoryAndGoldToDB();
|
||||||
CharacterDatabase.CommitTransaction();
|
CharacterDatabase.CommitTransaction();
|
||||||
|
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
|
trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
|
||||||
SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
|
SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE);
|
||||||
|
|
||||||
_player->pTrader->pTrader = NULL;
|
|
||||||
_player->pTrader = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
|
trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/)
|
void WorldSession::HandleUnacceptTradeOpcode(WorldPacket& /*recvPacket*/)
|
||||||
{
|
{
|
||||||
if (!GetPlayer()->pTrader)
|
TradeData* my_trade = _player->GetTradeData();
|
||||||
|
if (!my_trade)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE);
|
my_trade->SetAccepted(false, true);
|
||||||
_player->acceptTrade = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/)
|
void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/)
|
||||||
{
|
{
|
||||||
if (!_player->pTrader)
|
TradeData* my_trade = _player->m_trade;
|
||||||
|
if (!my_trade)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
|
my_trade->GetTrader()->GetSession()->SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
|
||||||
_player->pTrader->ClearTrade();
|
|
||||||
|
|
||||||
SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
|
SendTradeStatus(TRADE_STATUS_OPEN_WINDOW);
|
||||||
_player->ClearTrade();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::SendCancelTrade()
|
void WorldSession::SendCancelTrade()
|
||||||
{
|
{
|
||||||
|
if (m_playerRecentlyLogout)
|
||||||
|
return;
|
||||||
|
|
||||||
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
|
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +530,7 @@ void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/)
|
|||||||
|
|
||||||
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
if (GetPlayer()->pTrader)
|
if (GetPlayer()->m_trade)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint64 ID;
|
uint64 ID;
|
||||||
@@ -511,7 +575,7 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pOther == GetPlayer() || pOther->pTrader)
|
if (pOther == GetPlayer() || pOther->m_trade)
|
||||||
{
|
{
|
||||||
SendTradeStatus(TRADE_STATUS_BUSY);
|
SendTradeStatus(TRADE_STATUS_BUSY);
|
||||||
return;
|
return;
|
||||||
@@ -566,35 +630,30 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OK start trade
|
// OK start trade
|
||||||
_player->pTrader = pOther;
|
_player->m_trade = new TradeData(_player, pOther);
|
||||||
pOther->pTrader =_player;
|
pOther->m_trade = new TradeData(pOther, _player);
|
||||||
|
|
||||||
WorldPacket data(SMSG_TRADE_STATUS, 12);
|
WorldPacket data(SMSG_TRADE_STATUS, 12);
|
||||||
data << (uint32) TRADE_STATUS_BEGIN_TRADE;
|
data << uint32(TRADE_STATUS_BEGIN_TRADE);
|
||||||
data << (uint64)_player->GetGUID();
|
data << uint64(_player->GetGUID());
|
||||||
_player->pTrader->GetSession()->SendPacket(&data);
|
pOther->GetSession()->SendPacket(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
if (!_player->pTrader)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32 gold;
|
uint32 gold;
|
||||||
|
|
||||||
recvPacket >> gold;
|
recvPacket >> gold;
|
||||||
|
|
||||||
// gold can be incorrect, but this is checked at trade finished.
|
TradeData* my_trade = _player->GetTradeData();
|
||||||
_player->tradeGold = gold;
|
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)
|
void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
if (!_player->pTrader)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// send update
|
// send update
|
||||||
uint8 tradeSlot;
|
uint8 tradeSlot;
|
||||||
uint8 bag;
|
uint8 bag;
|
||||||
@@ -604,6 +663,10 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
|
|||||||
recvPacket >> bag;
|
recvPacket >> bag;
|
||||||
recvPacket >> slot;
|
recvPacket >> slot;
|
||||||
|
|
||||||
|
TradeData* my_trade = _player->GetTradeData();
|
||||||
|
if (!my_trade)
|
||||||
|
return;
|
||||||
|
|
||||||
// invalid slot number
|
// invalid slot number
|
||||||
if (tradeSlot >= TRADE_SLOT_COUNT)
|
if (tradeSlot >= TRADE_SLOT_COUNT)
|
||||||
{
|
{
|
||||||
@@ -612,7 +675,7 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check cheating, can't fail with correct client operations
|
// 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()))
|
if (!item || (tradeSlot != TRADE_SLOT_NONTRADED && !item->CanBeTraded()))
|
||||||
{
|
{
|
||||||
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
|
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
|
||||||
@@ -622,35 +685,29 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
|
|||||||
uint64 iGUID = item->GetGUID();
|
uint64 iGUID = item->GetGUID();
|
||||||
|
|
||||||
// prevent place single item into many trade slots using cheating and client bugs
|
// 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
|
// cheating attempt
|
||||||
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
|
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_player->tradeItems[tradeSlot] = iGUID;
|
my_trade->SetItem(TradeSlots(tradeSlot), item);
|
||||||
|
|
||||||
_player->pTrader->GetSession()->SendUpdateTrade();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket)
|
void WorldSession::HandleClearTradeItemOpcode(WorldPacket& recvPacket)
|
||||||
{
|
{
|
||||||
if (!_player->pTrader)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint8 tradeSlot;
|
uint8 tradeSlot;
|
||||||
recvPacket >> tradeSlot;
|
recvPacket >> tradeSlot;
|
||||||
|
|
||||||
|
TradeData* my_trade = _player->m_trade;
|
||||||
|
if (!my_trade)
|
||||||
|
return;
|
||||||
|
|
||||||
// invalid slot number
|
// invalid slot number
|
||||||
if (tradeSlot >= TRADE_SLOT_COUNT)
|
if (tradeSlot >= TRADE_SLOT_COUNT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_player->tradeItems[tradeSlot] = 0;
|
my_trade->SetItem(TradeSlots(tradeSlot), NULL);
|
||||||
|
|
||||||
_player->pTrader->GetSession()->SendUpdateTrade();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -205,12 +205,12 @@ class WorldSession
|
|||||||
|
|
||||||
void SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId);
|
void SendBattlegGroundList(uint64 guid, BattleGroundTypeId bgTypeId);
|
||||||
|
|
||||||
void SendTradeStatus(uint32 status);
|
void SendTradeStatus(TradeStatus status);
|
||||||
void SendCancelTrade();
|
void SendCancelTrade();
|
||||||
|
|
||||||
void SendStablePet(uint64 guid);
|
void SendStablePet(uint64 guid);
|
||||||
void SendPetitionQueryOpcode(uint64 petitionguid);
|
void SendPetitionQueryOpcode(uint64 petitionguid);
|
||||||
void SendUpdateTrade();
|
void SendUpdateTrade(bool trader_data = true);
|
||||||
|
|
||||||
//pet
|
//pet
|
||||||
void SendPetNameQuery(uint64 guid, uint32 petnumber);
|
void SendPetNameQuery(uint64 guid, uint32 petnumber);
|
||||||
|
|||||||
@@ -148,6 +148,15 @@ void SpellCastTargets::setItemTarget(Item* item)
|
|||||||
m_targetMask |= TARGET_FLAG_ITEM;
|
m_targetMask |= TARGET_FLAG_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpellCastTargets::setTradeItemTarget(Player* caster)
|
||||||
|
{
|
||||||
|
m_itemTargetGUID = uint64(TRADE_SLOT_NONTRADED);
|
||||||
|
m_itemTargetEntry = 0;
|
||||||
|
m_targetMask |= TARGET_FLAG_TRADE_ITEM;
|
||||||
|
|
||||||
|
Update(caster);
|
||||||
|
}
|
||||||
|
|
||||||
void SpellCastTargets::setCorpseTarget(Corpse* corpse)
|
void SpellCastTargets::setCorpseTarget(Corpse* corpse)
|
||||||
{
|
{
|
||||||
m_CorpseTargetGUID = corpse->GetGUID();
|
m_CorpseTargetGUID = corpse->GetGUID();
|
||||||
@@ -163,12 +172,13 @@ void SpellCastTargets::Update(Unit* caster)
|
|||||||
m_itemTarget = NULL;
|
m_itemTarget = NULL;
|
||||||
if (caster->GetTypeId() == TYPEID_PLAYER)
|
if (caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
|
Player *player = caster->ToPlayer();
|
||||||
if (m_targetMask & TARGET_FLAG_ITEM)
|
if (m_targetMask & TARGET_FLAG_ITEM)
|
||||||
m_itemTarget = caster->ToPlayer()->GetItemByGuid(m_itemTargetGUID);
|
m_itemTarget = player->GetItemByGuid(m_itemTargetGUID);
|
||||||
else if (m_targetMask & TARGET_FLAG_TRADE_ITEM)
|
else if (m_targetMask & TARGET_FLAG_TRADE_ITEM)
|
||||||
if (m_itemTargetGUID == TRADE_SLOT_NONTRADED) // here it is not guid but slot. Also prevent hacking slots
|
if (m_itemTargetGUID == TRADE_SLOT_NONTRADED) // here it is not guid but slot. Also prevents hacking slots
|
||||||
if (Player* pTrader = caster->ToPlayer()->GetTrader())
|
if (TradeData* pTrade = player->GetTradeData())
|
||||||
m_itemTarget = pTrader->GetItemByTradeSlot(m_itemTargetGUID);
|
m_itemTarget = pTrade->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED);
|
||||||
|
|
||||||
if (m_itemTarget)
|
if (m_itemTarget)
|
||||||
m_itemTargetEntry = m_itemTarget->GetEntry();
|
m_itemTargetEntry = m_itemTarget->GetEntry();
|
||||||
@@ -2900,6 +2910,32 @@ void Spell::cast(bool skipCheck)
|
|||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// additional check after cast bar completes (must not be in CheckCast)
|
||||||
|
// if trade not complete then remember it in trade data
|
||||||
|
if (m_targets.getTargetMask() & TARGET_FLAG_TRADE_ITEM)
|
||||||
|
{
|
||||||
|
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
if (TradeData* my_trade = m_caster->ToPlayer()->GetTradeData())
|
||||||
|
{
|
||||||
|
if (!my_trade->IsInAcceptProcess())
|
||||||
|
{
|
||||||
|
// Spell will be casted at completing the trade. Silently ignore at this place
|
||||||
|
my_trade->SetSpell(m_spellInfo->Id, m_CastItem);
|
||||||
|
SendCastResult(SPELL_FAILED_DONT_REPORT);
|
||||||
|
SendInterrupted(0);
|
||||||
|
m_caster->ToPlayer()->RestoreSpellMods(this);
|
||||||
|
// cleanup after mod system
|
||||||
|
// triggered spell pointer can be not removed in some cases
|
||||||
|
m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
|
||||||
|
finish(false);
|
||||||
|
SetExecutedCurrently(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectSpellTargets();
|
SelectSpellTargets();
|
||||||
@@ -2965,6 +3001,12 @@ void Spell::cast(bool skipCheck)
|
|||||||
TakePower();
|
TakePower();
|
||||||
TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot
|
TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot
|
||||||
}
|
}
|
||||||
|
else if (Item* targetItem = m_targets.getItemTarget())
|
||||||
|
{
|
||||||
|
/// Not own traded item (in trader trade slot) req. reagents including triggered spell case
|
||||||
|
if (targetItem->GetOwnerGUID() != m_caster->GetGUID())
|
||||||
|
TakeReagents();
|
||||||
|
}
|
||||||
|
|
||||||
// are there any spells need to be triggered after hit?
|
// are there any spells need to be triggered after hit?
|
||||||
// handle SPELL_AURA_ADD_TARGET_TRIGGER auras
|
// handle SPELL_AURA_ADD_TARGET_TRIGGER auras
|
||||||
@@ -4330,7 +4372,12 @@ void Spell::TakeRunePower()
|
|||||||
void Spell::TakeReagents()
|
void Spell::TakeReagents()
|
||||||
{
|
{
|
||||||
if (m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed.
|
if (m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed.
|
||||||
|
{
|
||||||
|
Item* targetItem = m_targets.getItemTarget();
|
||||||
|
/// Not own traded item (in trader trade slot) req. reagents including triggered spell case
|
||||||
|
if (!(targetItem && targetItem->GetOwnerGUID() != m_caster->GetGUID()))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
return;
|
return;
|
||||||
@@ -5430,6 +5477,26 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check trade slot case (last, for allow catch any another cast problems)
|
||||||
|
if (m_targets.getTargetMask() & TARGET_FLAG_TRADE_ITEM)
|
||||||
|
{
|
||||||
|
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||||
|
return SPELL_FAILED_NOT_TRADING;
|
||||||
|
|
||||||
|
TradeData* my_trade = m_caster->ToPlayer()->GetTradeData();
|
||||||
|
|
||||||
|
if (!my_trade)
|
||||||
|
return SPELL_FAILED_NOT_TRADING;
|
||||||
|
|
||||||
|
TradeSlots slot = TradeSlots(m_targets.getItemTargetGUID());
|
||||||
|
if (slot != TRADE_SLOT_NONTRADED)
|
||||||
|
return SPELL_FAILED_ITEM_NOT_READY;
|
||||||
|
|
||||||
|
if (!m_IsTriggeredSpell)
|
||||||
|
if (my_trade->GetSpell())
|
||||||
|
return SPELL_FAILED_ITEM_ALREADY_ENCHANTED;
|
||||||
|
}
|
||||||
|
|
||||||
// all ok
|
// all ok
|
||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ class SpellCastTargets
|
|||||||
Item* getItemTarget() const { return m_itemTarget; }
|
Item* getItemTarget() const { return m_itemTarget; }
|
||||||
uint32 getItemTargetEntry() const { return m_itemTargetEntry; }
|
uint32 getItemTargetEntry() const { return m_itemTargetEntry; }
|
||||||
void setItemTarget(Item* item);
|
void setItemTarget(Item* item);
|
||||||
|
void setTradeItemTarget(Player* caster);
|
||||||
void updateTradeSlotItem()
|
void updateTradeSlotItem()
|
||||||
{
|
{
|
||||||
if (m_itemTarget && (m_targetMask & TARGET_FLAG_TRADE_ITEM))
|
if (m_itemTarget && (m_targetMask & TARGET_FLAG_TRADE_ITEM))
|
||||||
|
|||||||
Reference in New Issue
Block a user