diff options
| author | Shauren <none@none> | 2010-06-25 13:15:51 +0200 |
|---|---|---|
| committer | Shauren <none@none> | 2010-06-25 13:15:51 +0200 |
| commit | 456c6291ab70f2f3182a4d63408c45099eedbbdd (patch) | |
| tree | 21aa76d9107d54a70572d5ac450362fce276ce74 /src/server/game/Server | |
| parent | eb79fb91a6eb410a5a5ceb6259b9d4bc5569c2ae (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.cpp | 499 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 4 |
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); |
