2010-10-07 15:35:36 +02:00
/*
2014-01-01 00:07:53 +01:00
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "Item.h"
#include "UpdateData.h"
#include "ObjectAccessor.h"
2011-07-26 23:09:28 +02:00
#include "SpellInfo.h"
2013-03-15 21:19:15 +01:00
#include "DB2Stores.h"
2012-07-24 00:59:55 +01:00
#include <vector>
2009-10-17 15:51:44 -07:00
2012-08-10 18:56:06 -05:00
void WorldSession :: HandleSplitItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
//TC_LOG_DEBUG("network", "WORLD: CMSG_SPLIT_ITEM");
2009-08-19 17:07:21 -05:00
uint8 srcbag , srcslot , dstbag , dstslot ;
uint32 count ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> srcbag >> srcslot >> dstbag >> dstslot >> count ;
2013-05-13 15:07:36 +02:00
//TC_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count);
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
uint16 src = (( srcbag << 8 ) | srcslot );
uint16 dst = (( dstbag << 8 ) | dstslot );
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( src == dst )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( count == 0 )
2008-10-11 14:16:25 -05:00
return ; //check count - if zero it's fake packet
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( srcbag , srcslot , true ))
2008-11-10 09:04:23 -06:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( dstbag , dstslot , false )) // can be autostore pos
2008-11-10 09:04:23 -06:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
_player -> SplitItem ( src , dst , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleSwapInvItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
//TC_LOG_DEBUG("network", "WORLD: CMSG_SWAP_INV_ITEM");
2008-10-11 14:16:25 -05:00
uint8 srcslot , dstslot ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> dstslot >> srcslot ;
2013-05-13 15:07:36 +02:00
//TC_LOG_DEBUG("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent attempt swap same item to current position generated by client at special checting sequence
2010-04-07 23:25:02 +02:00
if ( srcslot == dstslot )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( INVENTORY_SLOT_BAG_0 , srcslot , true ))
2008-11-10 09:04:23 -06:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( INVENTORY_SLOT_BAG_0 , dstslot , true ))
2008-11-10 09:04:23 -06:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-06-07 22:47:50 +02:00
if ( _player -> IsBankPos ( INVENTORY_SLOT_BAG_0 , srcslot ) && ! CanUseBank ())
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleSwapInvItemOpcode - Unit (%s) not found or you can't interact with him." , m_currentBankerGUID . ToString (). c_str ());
2014-06-07 22:47:50 +02:00
return ;
}
if ( _player -> IsBankPos ( INVENTORY_SLOT_BAG_0 , dstslot ) && ! CanUseBank ())
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleSwapInvItemOpcode - Unit (%s) not found or you can't interact with him." , m_currentBankerGUID . ToString (). c_str ());
2014-06-07 22:47:50 +02:00
return ;
}
2010-04-07 22:59:46 +02:00
uint16 src = (( INVENTORY_SLOT_BAG_0 << 8 ) | srcslot );
uint16 dst = (( INVENTORY_SLOT_BAG_0 << 8 ) | dstslot );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
_player -> SwapItem ( src , dst );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleAutoEquipItemSlotOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2014-09-14 16:14:12 +02:00
ObjectGuid itemguid ;
2008-10-11 14:16:25 -05:00
uint8 dstslot ;
2012-08-05 19:40:30 -05:00
recvData >> itemguid >> dstslot ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// cheating attempt, client should never send opcode in that case
2010-04-07 19:14:10 +02:00
if ( ! Player :: IsEquipmentPos ( INVENTORY_SLOT_BAG_0 , dstslot ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Item * item = _player -> GetItemByGuid ( itemguid );
uint16 dstpos = dstslot | ( INVENTORY_SLOT_BAG_0 << 8 );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! item || item -> GetPos () == dstpos )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> SwapItem ( item -> GetPos (), dstpos );
}
2009-10-17 15:51:44 -07:00
2012-08-09 18:46:59 -05:00
void WorldSession :: HandleSwapItem ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
//TC_LOG_DEBUG("network", "WORLD: CMSG_SWAP_ITEM");
2008-10-11 14:16:25 -05:00
uint8 dstbag , dstslot , srcbag , srcslot ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> dstbag >> dstslot >> srcbag >> srcslot ;
2013-05-13 15:07:36 +02:00
//TC_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot);
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
uint16 src = (( srcbag << 8 ) | srcslot );
uint16 dst = (( dstbag << 8 ) | dstslot );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent attempt swap same item to current position generated by client at special checting sequence
2010-04-07 23:25:02 +02:00
if ( src == dst )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( srcbag , srcslot , true ))
2008-11-10 09:04:23 -06:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( dstbag , dstslot , true ))
2008-11-10 09:04:23 -06:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-06-07 22:47:50 +02:00
if ( _player -> IsBankPos ( srcbag , srcslot ) && ! CanUseBank ())
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleSwapItem - Unit (%s) not found or you can't interact with him." , m_currentBankerGUID . ToString (). c_str ());
2014-06-07 22:47:50 +02:00
return ;
}
if ( _player -> IsBankPos ( dstbag , dstslot ) && ! CanUseBank ())
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleSwapItem - Unit (%s) not found or you can't interact with him." , m_currentBankerGUID . ToString (). c_str ());
2014-06-07 22:47:50 +02:00
return ;
}
2010-04-07 22:59:46 +02:00
_player -> SwapItem ( src , dst );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleAutoEquipItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
//TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOEQUIP_ITEM");
2008-10-11 14:16:25 -05:00
uint8 srcbag , srcslot ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> srcbag >> srcslot ;
2013-05-13 15:07:36 +02:00
//TC_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pSrcItem = _player -> GetItemByPos ( srcbag , srcslot );
2010-04-07 22:59:46 +02:00
if ( ! pSrcItem )
2008-10-11 14:16:25 -05:00
return ; // only at cheat
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint16 dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanEquipItem ( NULL_SLOT , dest , pSrcItem , ! pSrcItem -> IsBag ());
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pSrcItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint16 src = pSrcItem -> GetPos ();
2010-04-07 23:25:02 +02:00
if ( dest == src ) // prevent equip in same slot, only at cheat
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pDstItem = _player -> GetItemByPos ( dest );
2010-04-07 22:59:46 +02:00
if ( ! pDstItem ) // empty slot, simple case
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> RemoveItem ( srcbag , srcslot , true );
_player -> EquipItem ( dest , pSrcItem , true );
2008-10-11 14:16:25 -05:00
_player -> AutoUnequipOffhandIfNeed ();
}
else // have currently equipped item, not simple case
{
uint8 dstbag = pDstItem -> GetBagSlot ();
uint8 dstslot = pDstItem -> GetSlot ();
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
msg = _player -> CanUnequipItem ( dest , ! pSrcItem -> IsBag ());
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pDstItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check dest->src move possibility
ItemPosCountVec sSrc ;
2009-04-27 18:42:35 -05:00
uint16 eSrc = 0 ;
2010-04-07 22:59:46 +02:00
if ( _player -> IsInventoryPos ( src ))
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
msg = _player -> CanStoreItem ( srcbag , srcslot , sSrc , pDstItem , true );
if ( msg != EQUIP_ERR_OK )
msg = _player -> CanStoreItem ( srcbag , NULL_SLOT , sSrc , pDstItem , true );
if ( msg != EQUIP_ERR_OK )
msg = _player -> CanStoreItem ( NULL_BAG , NULL_SLOT , sSrc , pDstItem , true );
2008-10-11 14:16:25 -05:00
}
2010-04-07 22:59:46 +02:00
else if ( _player -> IsBankPos ( src ))
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
msg = _player -> CanBankItem ( srcbag , srcslot , sSrc , pDstItem , true );
if ( msg != EQUIP_ERR_OK )
msg = _player -> CanBankItem ( srcbag , NULL_SLOT , sSrc , pDstItem , true );
if ( msg != EQUIP_ERR_OK )
msg = _player -> CanBankItem ( NULL_BAG , NULL_SLOT , sSrc , pDstItem , true );
2008-10-11 14:16:25 -05:00
}
2010-04-07 22:59:46 +02:00
else if ( _player -> IsEquipmentPos ( src ))
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
msg = _player -> CanEquipItem ( srcslot , eSrc , pDstItem , true );
if ( msg == EQUIP_ERR_OK )
msg = _player -> CanUnequipItem ( eSrc , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pDstItem , pSrcItem );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// now do moves, remove...
_player -> RemoveItem ( dstbag , dstslot , false );
_player -> RemoveItem ( srcbag , srcslot , false );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// add to dest
_player -> EquipItem ( dest , pSrcItem , true );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// add to src
2010-04-07 22:59:46 +02:00
if ( _player -> IsInventoryPos ( src ))
2008-10-11 14:16:25 -05:00
_player -> StoreItem ( sSrc , pDstItem , true );
2010-04-07 22:59:46 +02:00
else if ( _player -> IsBankPos ( src ))
2008-10-11 14:16:25 -05:00
_player -> BankItem ( sSrc , pDstItem , true );
2010-04-07 22:59:46 +02:00
else if ( _player -> IsEquipmentPos ( src ))
2008-10-11 14:16:25 -05:00
_player -> EquipItem ( eSrc , pDstItem , true );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> AutoUnequipOffhandIfNeed ();
}
}
2009-10-17 15:51:44 -07:00
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleDestroyItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 11:12:17 +01:00
//TC_LOG_DEBUG("network", "WORLD: CMSG_DESTROY_ITEM");
2008-10-11 14:16:25 -05:00
uint8 bag , slot , count , data1 , data2 , data3 ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> bag >> slot >> count >> data1 >> data2 >> data3 ;
2013-05-13 15:07:36 +02:00
//TC_LOG_DEBUG("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint16 pos = ( bag << 8 ) | slot ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent drop unequipable items (in combat, for example) and non-empty bags
2010-04-07 19:14:10 +02:00
if ( _player -> IsEquipmentPos ( pos ) || _player -> IsBagPos ( pos ))
2008-10-11 14:16:25 -05:00
{
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanUnequipItem ( pos , false );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , _player -> GetItemByPos ( pos ), NULL );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemByPos ( bag , slot );
2010-04-07 19:14:10 +02:00
if ( ! pItem )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , NULL , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-04-28 22:42:33 +02:00
if ( pItem -> GetTemplate () -> Flags & ITEM_PROTO_FLAG_INDESTRUCTIBLE )
2010-07-11 23:53:48 +02:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_DROP_BOUND_ITEM , NULL , NULL );
2010-07-11 23:53:48 +02:00
return ;
}
2010-04-07 19:14:10 +02:00
if ( count )
2008-10-11 14:16:25 -05:00
{
uint32 i_count = count ;
2010-04-07 22:59:46 +02:00
_player -> DestroyItemCount ( pItem , i_count , true );
2008-10-11 14:16:25 -05:00
}
else
2010-04-07 22:59:46 +02:00
_player -> DestroyItem ( bag , slot , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 16:15:38 -05:00
void WorldSession :: HandleReadItem ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
uint8 bag , slot ;
2012-08-05 16:15:38 -05:00
recvData >> bag >> slot ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemByPos ( bag , slot );
2009-10-17 15:51:44 -07:00
2011-04-28 22:42:33 +02:00
if ( pItem && pItem -> GetTemplate () -> PageText )
2008-10-11 14:16:25 -05:00
{
WorldPacket data ;
2009-10-17 15:51:44 -07:00
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanUseItem ( pItem );
2010-04-07 22:59:46 +02:00
if ( msg == EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2012-01-07 12:28:09 +08:00
data . Initialize ( SMSG_READ_ITEM_OK , 8 );
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "network" , "STORAGE: Item page sent" );
2008-10-11 14:16:25 -05:00
}
else
{
2010-04-07 22:59:46 +02:00
data . Initialize ( SMSG_READ_ITEM_FAILED , 8 );
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "network" , "STORAGE: Unable to read item" );
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
}
data << pItem -> GetGUID ();
SendPacket ( & data );
}
else
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , NULL , NULL );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleSellItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_SELL_ITEM" );
2014-09-14 16:14:12 +02:00
ObjectGuid vendorguid , itemguid ;
2009-08-19 17:07:21 -05:00
uint32 count ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> vendorguid >> itemguid >> count ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! itemguid )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-10-07 11:08:09 -05:00
Creature * creature = GetPlayer () -> GetNPCIfCanInteractWith ( vendorguid , UNIT_NPC_FLAG_VENDOR );
if ( ! creature )
2008-10-11 14:16:25 -05:00
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleSellItemOpcode - %s not found or you can not interact with him." , vendorguid . ToString (). c_str ());
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_FIND_VENDOR , NULL , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// remove fake death
2012-02-03 19:12:41 +02:00
if ( GetPlayer () -> HasUnitState ( UNIT_STATE_DIED ))
2009-04-06 13:31:14 +02:00
GetPlayer () -> RemoveAurasByType ( SPELL_AURA_FEIGN_DEATH );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemByGuid ( itemguid );
2010-04-07 22:59:46 +02:00
if ( pItem )
2008-10-11 14:16:25 -05:00
{
// prevent sell not owner item
2010-04-08 08:20:08 +02:00
if ( _player -> GetGUID () != pItem -> GetOwnerGUID ())
2008-10-11 14:16:25 -05:00
{
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent sell non empty bag by drag-and-drop at vendor's item list
2011-03-18 15:58:08 +06:00
if ( pItem -> IsNotEmptyBag ())
2008-10-11 14:16:25 -05:00
{
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// prevent sell currently looted item
2010-04-07 23:25:02 +02:00
if ( _player -> GetLootGUID () == pItem -> GetGUID ())
2008-10-11 14:16:25 -05:00
{
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-01-24 23:10:08 +01:00
// prevent selling item for sellprice when the item is still refundable
// this probably happens when right clicking a refundable item, the client sends both
// CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified)
if ( pItem -> HasFlag ( ITEM_FIELD_FLAGS , ITEM_FLAG_REFUNDABLE ))
return ; // Therefore, no feedback to client
2008-10-11 14:16:25 -05:00
// special case at auto sell (sell all)
2010-04-07 23:25:02 +02:00
if ( count == 0 )
2008-10-11 14:16:25 -05:00
count = pItem -> GetCount ();
else
{
2008-11-14 16:28:45 -06:00
// prevent sell more items that exist in stack (possible only not from client)
2010-04-07 19:14:10 +02:00
if ( count > pItem -> GetCount ())
2008-10-11 14:16:25 -05:00
{
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
ItemTemplate const * pProto = pItem -> GetTemplate ();
2010-04-07 22:59:46 +02:00
if ( pProto )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( pProto -> SellPrice > 0 )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( count < pItem -> GetCount ()) // need split items
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Item * pNewItem = pItem -> CloneItem ( count , _player );
2008-10-11 14:16:25 -05:00
if ( ! pNewItem )
{
2013-11-08 10:50:51 +01:00
TC_LOG_ERROR ( "network" , "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u" , pItem -> GetEntry (), count );
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
pItem -> SetCount ( pItem -> GetCount () - count );
_player -> ItemRemovedQuestCheck ( pItem -> GetEntry (), count );
if ( _player -> IsInWorld ())
pItem -> SendUpdateToPlayer ( _player );
2008-10-11 14:16:25 -05:00
pItem -> SetState ( ITEM_CHANGED , _player );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
_player -> AddItemToBuyBackSlot ( pNewItem );
if ( _player -> IsInWorld ())
pNewItem -> SendUpdateToPlayer ( _player );
2008-10-11 14:16:25 -05:00
}
else
{
2010-04-07 22:59:46 +02:00
_player -> ItemRemovedQuestCheck ( pItem -> GetEntry (), pItem -> GetCount ());
_player -> RemoveItem ( pItem -> GetBagSlot (), pItem -> GetSlot (), true );
2008-10-11 14:16:25 -05:00
pItem -> RemoveFromUpdateQueueOf ( _player );
2010-04-07 22:59:46 +02:00
_player -> AddItemToBuyBackSlot ( pItem );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-05-21 16:49:19 -03:00
uint32 money = pProto -> SellPrice * count ;
_player -> ModifyMoney ( money );
2012-07-09 11:08:33 +02:00
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS , money );
2008-10-11 14:16:25 -05:00
}
else
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
}
2012-08-07 19:54:42 -05:00
_player -> SendSellError ( SELL_ERR_CANT_FIND_ITEM , creature , itemguid );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2012-08-05 15:21:52 -05:00
void WorldSession :: HandleBuybackItem ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_BUYBACK_ITEM" );
2014-09-14 16:14:12 +02:00
ObjectGuid vendorguid ;
2008-10-11 14:16:25 -05:00
uint32 slot ;
2009-10-17 15:51:44 -07:00
2012-08-05 15:21:52 -05:00
recvData >> vendorguid >> slot ;
2009-10-17 15:51:44 -07:00
2011-10-07 11:08:09 -05:00
Creature * creature = GetPlayer () -> GetNPCIfCanInteractWith ( vendorguid , UNIT_NPC_FLAG_VENDOR );
if ( ! creature )
2008-10-11 14:16:25 -05:00
{
2014-09-17 23:24:31 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleBuybackItem - Unit (%s) not found or you can not interact with him." , vendorguid . ToString (). c_str ());
2014-09-20 11:05:30 +02:00
_player -> SendSellError ( SELL_ERR_CANT_FIND_VENDOR , NULL , ObjectGuid :: Empty );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// remove fake death
2012-02-03 19:12:41 +02:00
if ( GetPlayer () -> HasUnitState ( UNIT_STATE_DIED ))
2009-04-06 13:31:14 +02:00
GetPlayer () -> RemoveAurasByType ( SPELL_AURA_FEIGN_DEATH );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemFromBuyBackSlot ( slot );
2010-04-07 22:59:46 +02:00
if ( pItem )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
uint32 price = _player -> GetUInt32Value ( PLAYER_FIELD_BUYBACK_PRICE_1 + slot - BUYBACK_SLOT_START );
2012-07-24 15:27:42 +01:00
if ( ! _player -> HasEnoughMoney ( uint64 ( price )))
2008-10-11 14:16:25 -05:00
{
2011-10-07 11:08:09 -05:00
_player -> SendBuyError ( BUY_ERR_NOT_ENOUGHT_MONEY , creature , pItem -> GetEntry (), 0 );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanStoreItem ( NULL_BAG , NULL_SLOT , dest , pItem , false );
2010-04-07 22:59:46 +02:00
if ( msg == EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> ModifyMoney ( - ( int32 ) price );
_player -> RemoveItemFromBuyBackSlot ( slot , false );
_player -> ItemAddedQuestCheck ( pItem -> GetEntry (), pItem -> GetCount ());
2012-07-09 11:08:33 +02:00
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM , pItem -> GetEntry (), pItem -> GetCount ());
2010-04-07 22:59:46 +02:00
_player -> StoreItem ( dest , pItem , true );
2008-10-11 14:16:25 -05:00
}
else
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
else
2011-10-07 11:08:09 -05:00
_player -> SendBuyError ( BUY_ERR_CANT_FIND_ITEM , creature , 0 , 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleBuyItemInSlotOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_BUY_ITEM_IN_SLOT" );
2014-09-14 16:14:12 +02:00
ObjectGuid vendorguid , bagguid ;
2009-06-11 00:45:59 -05:00
uint32 item , slot , count ;
uint8 bagslot ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> vendorguid >> item >> slot >> bagguid >> bagslot >> count ;
2009-10-17 15:51:44 -07:00
2010-04-30 22:35:37 +02:00
// client expects count starting at 1, and we send vendorslot+1 to client already
if ( slot > 0 )
-- slot ;
else
return ; // cheating
2009-07-07 07:08:36 +08:00
uint8 bag = NULL_BAG ; // init for case invalid bagGUID
2012-08-04 13:01:29 -05:00
Item * bagItem = NULL ;
2009-07-07 07:08:36 +08:00
// find bag slot by bag guid
if ( bagguid == _player -> GetGUID ())
bag = INVENTORY_SLOT_BAG_0 ;
else
2012-08-04 13:01:29 -05:00
bagItem = _player -> GetItemByGuid ( bagguid );
2012-08-04 19:11:13 +01:00
2012-08-04 13:01:29 -05:00
if ( bagItem && bagItem -> IsBag ())
bag = bagItem -> GetSlot ();
2009-10-17 15:51:44 -07:00
2009-07-07 07:08:36 +08:00
// bag not found, cheating?
if ( bag == NULL_BAG )
return ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
GetPlayer () -> BuyItemFromVendorSlot ( vendorguid , slot , item , count , bag , bagslot );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleBuyItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_BUY_ITEM" );
2014-09-20 11:05:30 +02:00
ObjectGuid vendorguid , bagGuid ;
2009-06-11 00:45:59 -05:00
uint32 item , slot , count ;
2012-08-14 18:11:06 +01:00
uint8 itemType ; // 1 = item, 2 = currency
2012-08-04 20:03:15 +01:00
uint8 bagSlot ;
2012-08-06 23:00:57 +02:00
2012-08-05 19:40:30 -05:00
recvData >> vendorguid >> itemType >> item >> slot >> count >> bagGuid >> bagSlot ;
2009-10-17 15:51:44 -07:00
2010-04-30 22:35:37 +02:00
// client expects count starting at 1, and we send vendorslot+1 to client already
if ( slot > 0 )
-- slot ;
else
return ; // cheating
2012-08-04 19:11:13 +01:00
2012-08-14 18:11:06 +01:00
if ( itemType == ITEM_VENDOR_TYPE_ITEM )
{
Item * bagItem = _player -> GetItemByGuid ( bagGuid );
2012-08-04 19:11:13 +01:00
2012-08-14 18:11:06 +01:00
uint8 bag = NULL_BAG ;
if ( bagItem && bagItem -> IsBag ())
bag = bagItem -> GetSlot ();
2012-10-16 14:41:13 -05:00
else if ( bagGuid == GetPlayer () -> GetGUID ()) // The client sends the player guid when trying to store an item in the default backpack
bag = INVENTORY_SLOT_BAG_0 ;
2012-08-04 19:11:13 +01:00
2012-08-14 18:11:06 +01:00
GetPlayer () -> BuyItemFromVendorSlot ( vendorguid , slot , item , count , bag , bagSlot );
}
else if ( itemType == ITEM_VENDOR_TYPE_CURRENCY )
GetPlayer () -> BuyCurrencyFromVendorSlot ( vendorguid , slot , item , count );
else
2013-11-08 11:12:17 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode ", itemType) ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleListInventoryOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2014-09-14 16:14:12 +02:00
ObjectGuid guid ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> guid ;
2009-10-17 15:51:44 -07:00
2013-06-11 19:54:27 -02:30
if ( ! GetPlayer () -> IsAlive ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Recvd CMSG_LIST_INVENTORY" );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
SendListInventory ( guid );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
void WorldSession :: SendListInventory ( ObjectGuid vendorGuid )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Sent SMSG_LIST_INVENTORY" );
2009-10-17 15:51:44 -07:00
2011-06-23 21:24:16 +02:00
Creature * vendor = GetPlayer () -> GetNPCIfCanInteractWith ( vendorGuid , UNIT_NPC_FLAG_VENDOR );
if ( ! vendor )
2008-10-11 14:16:25 -05:00
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: SendListInventory - %s not found or you can not interact with him." , vendorGuid . ToString (). c_str ());
2014-09-20 11:05:30 +02:00
_player -> SendSellError ( SELL_ERR_CANT_FIND_VENDOR , NULL , ObjectGuid :: Empty );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// remove fake death
2012-02-03 19:12:41 +02:00
if ( GetPlayer () -> HasUnitState ( UNIT_STATE_DIED ))
2009-04-06 13:31:14 +02:00
GetPlayer () -> RemoveAurasByType ( SPELL_AURA_FEIGN_DEATH );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Stop the npc if moving
2012-02-03 19:12:41 +02:00
if ( vendor -> HasUnitState ( UNIT_STATE_MOVING ))
2011-06-23 21:24:16 +02:00
vendor -> StopMoving ();
2009-10-17 15:51:44 -07:00
2012-07-24 00:06:49 +01:00
VendorItemData const * vendorItems = vendor -> GetVendorItems ();
2013-07-22 19:52:18 +02:00
uint32 rawItemCount = vendorItems ? vendorItems -> GetItemCount () : 0 ;
2012-01-31 14:02:59 +01:00
2012-08-01 14:31:09 +02:00
//if (rawItemCount > 300),
2012-07-24 00:06:49 +01:00
// rawItemCount = 300; // client cap but uint8 max value is 255
2009-10-17 15:51:44 -07:00
2012-07-24 00:59:55 +01:00
ByteBuffer itemsData ( 32 * rawItemCount );
std :: vector < bool > enablers ;
enablers . reserve ( 2 * rawItemCount );
2012-07-24 00:06:49 +01:00
const float discountMod = _player -> GetReputationPriceDiscount ( vendor );
2008-10-11 14:16:25 -05:00
uint8 count = 0 ;
2013-07-22 19:52:18 +02:00
for ( uint32 slot = 0 ; slot < rawItemCount ; ++ slot )
2012-07-24 00:06:49 +01:00
{
VendorItem const * vendorItem = vendorItems -> GetItem ( slot );
2013-07-22 19:52:18 +02:00
if ( ! vendorItem )
continue ;
2012-01-31 14:02:59 +01:00
2012-08-14 18:11:06 +01:00
if ( vendorItem -> Type == ITEM_VENDOR_TYPE_ITEM )
2012-07-24 00:06:49 +01:00
{
2012-08-14 18:11:06 +01:00
ItemTemplate const * itemTemplate = sObjectMgr -> GetItemTemplate ( vendorItem -> item );
2012-08-27 15:05:43 +02:00
if ( ! itemTemplate )
continue ;
2012-07-24 00:06:49 +01:00
2012-08-27 15:05:43 +02:00
uint32 leftInStock = ! vendorItem -> maxcount ? 0xFFFFFFFF : vendor -> GetVendorItemCurrentCount ( vendorItem );
2013-06-13 19:35:01 +02:00
if ( ! _player -> IsGameMaster ()) // ignore conditions if GM on
2012-08-14 18:11:06 +01:00
{
// Respect allowed class
2012-08-27 15:05:43 +02:00
if ( ! ( itemTemplate -> AllowableClass & _player -> getClassMask ()) && itemTemplate -> Bonding == BIND_WHEN_PICKED_UP )
2012-08-14 18:11:06 +01:00
continue ;
// Only display items in vendor lists for the team the player is on
if (( itemTemplate -> Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player -> GetTeam () == ALLIANCE ) ||
( itemTemplate -> Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player -> GetTeam () == HORDE ))
continue ;
// Items sold out are not displayed in list
if ( leftInStock == 0 )
continue ;
}
2012-07-24 00:06:49 +01:00
2012-12-07 09:22:43 +01:00
ConditionList conditions = sConditionMgr -> GetConditionsForNpcVendorEvent ( vendor -> GetEntry (), vendorItem -> item );
if ( ! sConditionMgr -> IsObjectMeetToConditions ( _player , vendor , conditions ))
{
2013-11-08 11:12:17 +01:00
TC_LOG_DEBUG ( "condition" , "SendListInventory: conditions not met for creature entry %u item %u" , vendor -> GetEntry (), vendorItem -> item );
2012-12-07 09:22:43 +01:00
continue ;
}
2012-12-01 01:49:44 +01:00
2012-08-14 18:11:06 +01:00
int32 price = vendorItem -> IsGoldRequired ( itemTemplate ) ? uint32 ( floor ( itemTemplate -> BuyPrice * discountMod )) : 0 ;
2012-09-05 19:01:28 +01:00
2012-09-04 17:52:10 +03:00
if ( int32 priceMod = _player -> GetTotalAuraModifier ( SPELL_AURA_MOD_VENDOR_ITEMS_PRICES ))
2012-10-04 13:33:04 +02:00
price -= CalculatePct ( price , priceMod );
2012-08-14 18:11:06 +01:00
2012-10-16 14:28:41 -05:00
itemsData << uint32 ( slot + 1 ); // client expects counting to start at 1
2012-08-14 18:11:06 +01:00
itemsData << uint32 ( itemTemplate -> MaxDurability );
2013-07-22 19:52:18 +02:00
if ( vendorItem -> ExtendedCost )
2012-08-14 18:11:06 +01:00
{
enablers . push_back ( 0 );
itemsData << uint32 ( vendorItem -> ExtendedCost );
}
else
enablers . push_back ( 1 );
2013-07-22 19:52:18 +02:00
enablers . push_back ( 1 ); // item is unlocked
2012-08-14 18:11:06 +01:00
itemsData << uint32 ( vendorItem -> item );
itemsData << uint32 ( vendorItem -> Type ); // 1 is items, 2 is currency
itemsData << uint32 ( price );
itemsData << uint32 ( itemTemplate -> DisplayInfoID );
// if (!unk "enabler") data << uint32(something);
itemsData << int32 ( leftInStock );
itemsData << uint32 ( itemTemplate -> BuyCount );
2013-07-22 19:52:18 +02:00
if ( ++ count >= MAX_VENDOR_ITEMS )
break ;
2012-07-24 00:06:49 +01:00
}
2012-08-14 18:11:06 +01:00
else if ( vendorItem -> Type == ITEM_VENDOR_TYPE_CURRENCY )
{
CurrencyTypesEntry const * currencyTemplate = sCurrencyTypesStore . LookupEntry ( vendorItem -> item );
2012-08-27 15:05:43 +02:00
if ( ! currencyTemplate )
continue ;
2012-08-01 14:31:09 +02:00
2013-07-22 19:52:18 +02:00
if ( ! vendorItem -> ExtendedCost )
2012-08-27 15:05:43 +02:00
continue ; // there's no price defined for currencies, only extendedcost is used
2012-07-24 00:59:55 +01:00
2012-11-07 23:21:19 +01:00
itemsData << uint32 ( slot + 1 ); // client expects counting to start at 1
2012-08-14 18:11:06 +01:00
itemsData << uint32 ( 0 ); // max durability
2013-07-22 19:52:18 +02:00
enablers . push_back ( 0 );
itemsData << uint32 ( vendorItem -> ExtendedCost );
2012-08-27 15:05:43 +02:00
2013-07-22 19:52:18 +02:00
enablers . push_back ( 1 ); // item is unlocked
2012-08-14 18:11:06 +01:00
itemsData << uint32 ( vendorItem -> item );
itemsData << uint32 ( vendorItem -> Type ); // 1 is items, 2 is currency
itemsData << uint32 ( 0 ); // price, only seen currency types that have Extended cost
itemsData << uint32 ( 0 ); // displayId
// if (!unk "enabler") data << uint32(something);
itemsData << int32 ( - 1 );
2013-01-30 20:40:02 +01:00
itemsData << uint32 ( vendorItem -> maxcount );
2013-07-22 19:52:18 +02:00
if ( ++ count >= MAX_VENDOR_ITEMS )
break ;
2012-07-24 00:59:55 +01:00
}
2012-08-14 18:11:06 +01:00
// else error
2012-07-24 00:06:49 +01:00
}
2012-01-31 14:02:59 +01:00
2012-08-27 15:05:43 +02:00
ObjectGuid guid = vendorGuid ;
2012-01-31 14:02:59 +01:00
2012-07-24 00:59:55 +01:00
WorldPacket data ( SMSG_LIST_INVENTORY , 12 + itemsData . size ());
2012-01-31 14:02:59 +01:00
2012-08-27 15:05:43 +02:00
data . WriteBit ( guid [ 1 ]);
data . WriteBit ( guid [ 0 ]);
2012-01-31 14:02:59 +01:00
2012-07-24 00:59:55 +01:00
data . WriteBits ( count , 21 ); // item count
2010-04-30 22:35:37 +02:00
2012-08-27 15:05:43 +02:00
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( guid [ 7 ]);
2009-10-17 15:51:44 -07:00
2012-07-24 00:59:55 +01:00
for ( std :: vector < bool >:: const_iterator itr = enablers . begin (); itr != enablers . end (); ++ itr )
data . WriteBit ( * itr );
2009-10-17 15:51:44 -07:00
2012-08-27 15:05:43 +02:00
data . WriteBit ( guid [ 4 ]);
2012-07-24 00:06:49 +01:00
2012-07-24 00:59:55 +01:00
data . FlushBits ();
data . append ( itemsData );
2009-10-17 15:51:44 -07:00
2012-08-27 15:05:43 +02:00
data . WriteByteSeq ( guid [ 5 ]);
data . WriteByteSeq ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 1 ]);
data . WriteByteSeq ( guid [ 0 ]);
data . WriteByteSeq ( guid [ 6 ]);
2012-07-24 00:06:49 +01:00
2013-07-22 19:52:18 +02:00
// It doesn't matter what value is used here (PROBABLY its full vendor size)
// What matters is that if count of items we can see is 0 and this field is 1
// then client will open the vendor list, otherwise it won't
if ( rawItemCount )
data << uint8 ( rawItemCount );
else
data << uint8 ( vendor -> IsArmorer ());
2012-07-24 00:06:49 +01:00
2012-08-27 15:05:43 +02:00
data . WriteByteSeq ( guid [ 2 ]);
data . WriteByteSeq ( guid [ 3 ]);
data . WriteByteSeq ( guid [ 7 ]);
2012-07-24 00:06:49 +01:00
2010-04-07 22:59:46 +02:00
SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleAutoStoreBagItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
//TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_BAG_ITEM");
2008-10-11 14:16:25 -05:00
uint8 srcbag , srcslot , dstbag ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> srcbag >> srcslot >> dstbag ;
2013-05-13 15:07:36 +02:00
//TC_LOG_DEBUG("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag);
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemByPos ( srcbag , srcslot );
2010-04-07 22:59:46 +02:00
if ( ! pItem )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( ! _player -> IsValidPos ( dstbag , NULL_SLOT , false )) // can be autostore pos
2008-11-10 09:04:23 -06:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT , NULL , NULL );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint16 src = pItem -> GetPos ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check unequip potability for equipped items and bank bags
2010-04-07 22:59:46 +02:00
if ( _player -> IsEquipmentPos ( src ) || _player -> IsBagPos ( src ))
2008-10-11 14:16:25 -05:00
{
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanUnequipItem ( src , ! _player -> IsBagPos ( src ));
2010-04-07 19:14:10 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanStoreItem ( dstbag , NULL_SLOT , dest , pItem , false );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// no-op: placed in same slot
2010-04-07 23:25:02 +02:00
if ( dest . size () == 1 && dest [ 0 ]. pos == src )
2008-10-11 14:16:25 -05:00
{
// just remove grey item state
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_INTERNAL_BAG_ERROR , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
_player -> RemoveItem ( srcbag , srcslot , true );
_player -> StoreItem ( dest , pItem , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-13 17:21:59 -05:00
void WorldSession :: HandleBuyBankSlotOpcode ( WorldPacket & recvPacket )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_BUY_BANK_SLOT" );
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
ObjectGuid guid ;
2009-04-13 17:21:59 -05:00
recvPacket >> guid ;
2009-10-17 15:51:44 -07:00
2014-06-28 13:36:16 +02:00
WorldPacket data ( SMSG_BUY_BANK_SLOT_RESULT , 4 );
2014-06-07 22:47:50 +02:00
if ( ! CanUseBank ( guid ))
2009-04-13 17:21:59 -05:00
{
2014-06-28 13:36:16 +02:00
data << uint32 ( ERR_BANKSLOT_NOTBANKER );
SendPacket ( & data );
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleBuyBankSlotOpcode - %s not found or you can't interact with him." , guid . ToString (). c_str ());
2009-04-13 17:21:59 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-05-24 11:17:03 -05:00
uint32 slot = _player -> GetBankBagSlotCount ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// next slot
++ slot ;
2009-10-17 15:51:44 -07:00
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "network" , "PLAYER: Buy bank bag slot, slot number = %u" , slot );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
BankBagSlotPricesEntry const * slotEntry = sBankBagSlotPricesStore . LookupEntry ( slot );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! slotEntry )
2010-04-11 11:18:20 +04:00
{
2010-04-11 20:20:38 +02:00
data << uint32 ( ERR_BANKSLOT_FAILED_TOO_MANY );
2010-04-11 11:18:20 +04:00
SendPacket ( & data );
2008-10-11 14:16:25 -05:00
return ;
2010-04-11 11:18:20 +04:00
}
2009-10-17 15:51:44 -07:00
2014-11-06 01:53:04 +02:00
uint32 price = slotEntry -> Cost ;
2009-10-17 15:51:44 -07:00
2012-07-24 15:27:42 +01:00
if ( ! _player -> HasEnoughMoney ( uint64 ( price )))
2010-04-11 11:18:20 +04:00
{
2010-04-11 20:20:38 +02:00
data << uint32 ( ERR_BANKSLOT_INSUFFICIENT_FUNDS );
2010-04-11 11:18:20 +04:00
SendPacket ( & data );
2008-10-11 14:16:25 -05:00
return ;
2010-04-11 11:18:20 +04:00
}
2009-10-17 15:51:44 -07:00
2009-05-24 11:17:03 -05:00
_player -> SetBankBagSlotCount ( slot );
2012-07-24 15:27:42 +01:00
_player -> ModifyMoney ( - int64 ( price ));
2009-10-17 15:51:44 -07:00
2010-04-11 11:18:20 +04:00
data << uint32 ( ERR_BANKSLOT_OK );
2010-04-11 20:20:38 +02:00
SendPacket ( & data );
2010-04-11 11:18:20 +04:00
2012-07-09 11:08:33 +02:00
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandleAutoBankItemOpcode ( WorldPacket & recvPacket )
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_AUTOBANK_ITEM" );
2008-10-11 14:16:25 -05:00
uint8 srcbag , srcslot ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
recvPacket >> srcbag >> srcslot ;
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "STORAGE: receive srcbag = %u, srcslot = %u" , srcbag , srcslot );
2009-10-17 15:51:44 -07:00
2014-06-07 22:47:50 +02:00
if ( ! CanUseBank ())
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleAutoBankItemOpcode - Unit (%s) not found or you can't interact with him." , m_currentBankerGUID . ToString (). c_str ());
2014-06-07 22:47:50 +02:00
return ;
}
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemByPos ( srcbag , srcslot );
2010-04-07 22:59:46 +02:00
if ( ! pItem )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanBankItem ( NULL_BAG , NULL_SLOT , dest , pItem , false );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-08-05 22:08:07 +06:00
if ( dest . size () == 1 && dest [ 0 ]. pos == pItem -> GetPos ())
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_SWAP , pItem , NULL );
2010-08-05 22:08:07 +06:00
return ;
}
2008-10-11 14:16:25 -05:00
_player -> RemoveItem ( srcbag , srcslot , true );
2011-12-18 16:24:10 +02:00
_player -> ItemRemovedQuestCheck ( pItem -> GetEntry (), pItem -> GetCount ());
2010-04-07 22:59:46 +02:00
_player -> BankItem ( dest , pItem , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldSession :: HandleAutoStoreBankItemOpcode ( WorldPacket & recvPacket )
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_AUTOSTORE_BANK_ITEM" );
2008-10-11 14:16:25 -05:00
uint8 srcbag , srcslot ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
recvPacket >> srcbag >> srcslot ;
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "STORAGE: receive srcbag = %u, srcslot = %u" , srcbag , srcslot );
2009-10-17 15:51:44 -07:00
2014-06-07 22:47:50 +02:00
if ( ! CanUseBank ())
{
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleAutoStoreBankItemOpcode - Unit (%s) not found or you can't interact with him." , m_currentBankerGUID . ToString (). c_str ());
2014-06-07 22:47:50 +02:00
return ;
}
2011-09-15 14:08:17 +02:00
Item * pItem = _player -> GetItemByPos ( srcbag , srcslot );
2010-04-07 22:59:46 +02:00
if ( ! pItem )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( _player -> IsBankPos ( srcbag , srcslot )) // moving from bank to inventory
2008-10-11 14:16:25 -05:00
{
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanStoreItem ( NULL_BAG , NULL_SLOT , dest , pItem , false );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> RemoveItem ( srcbag , srcslot , true );
2013-03-05 22:06:33 +01:00
if ( Item const * storedItem = _player -> StoreItem ( dest , pItem , true ))
_player -> ItemAddedQuestCheck ( storedItem -> GetEntry (), storedItem -> GetCount ());
2008-10-11 14:16:25 -05:00
}
else // moving from inventory to bank
{
ItemPosCountVec dest ;
2011-04-29 16:48:15 +06:00
InventoryResult msg = _player -> CanBankItem ( NULL_BAG , NULL_SLOT , dest , pItem , false );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( msg , pItem , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> RemoveItem ( srcbag , srcslot , true );
2010-04-07 22:59:46 +02:00
_player -> BankItem ( dest , pItem , true );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
void WorldSession :: SendEnchantmentLog ( ObjectGuid target , ObjectGuid caster , uint32 itemId , uint32 enchantId )
2008-10-11 14:16:25 -05:00
{
2013-05-30 20:57:07 +02:00
WorldPacket data ( SMSG_ENCHANTMENTLOG , ( 8 + 8 + 4 + 4 ));
2014-09-14 16:14:12 +02:00
data << target . WriteAsPacked ();
data << caster . WriteAsPacked ();
2013-05-25 11:09:21 +02:00
data << uint32 ( itemId );
data << uint32 ( enchantId );
GetPlayer () -> SendMessageToSet ( & data , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
void WorldSession :: SendItemEnchantTimeUpdate ( ObjectGuid Playerguid , ObjectGuid Itemguid , uint32 slot , uint32 Duration )
2008-10-11 14:16:25 -05:00
{
// last check 2.0.10
WorldPacket data ( SMSG_ITEM_ENCHANT_TIME_UPDATE , ( 8 + 4 + 4 + 8 ));
2014-10-21 21:09:15 +02:00
data << Itemguid ;
2008-10-11 14:16:25 -05:00
data << uint32 ( slot );
data << uint32 ( Duration );
2014-10-21 21:09:15 +02:00
data << Playerguid ;
2008-10-11 14:16:25 -05:00
SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleWrapItemOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "Received opcode CMSG_WRAP_ITEM" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint8 gift_bag , gift_slot , item_bag , item_slot ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> gift_bag >> gift_slot ; // paper
recvData >> item_bag >> item_slot ; // item
2009-10-17 15:51:44 -07:00
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u" , gift_bag , gift_slot , item_bag , item_slot );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * gift = _player -> GetItemByPos ( gift_bag , gift_slot );
2010-04-07 19:14:10 +02:00
if ( ! gift )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , gift , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-04-28 22:42:33 +02:00
if ( ! ( gift -> GetTemplate () -> Flags & ITEM_PROTO_FLAG_WRAPPER )) // cheating: non-wrapper wrapper
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , gift , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * item = _player -> GetItemByPos ( item_bag , item_slot );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( ! item )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( item == gift ) // not possable with pacjket from real client
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_WRAPPED , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( item -> IsEquipped ())
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_EQUIPPED , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
if ( ! item -> GetGuidValue ( ITEM_FIELD_GIFTCREATOR ). IsEmpty ()) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_WRAPPED , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( item -> IsBag ())
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_BAGS , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( item -> IsSoulBound ())
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_BOUND , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( item -> GetMaxStackCount () != 1 )
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_STACKABLE , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// maybe not correct check (it is better than nothing)
2012-08-20 15:54:55 +02:00
if ( item -> GetTemplate () -> MaxCount > 0 )
2008-10-11 14:16:25 -05:00
{
2012-08-20 15:54:55 +02:00
_player -> SendEquipError ( EQUIP_ERR_CANT_WRAP_UNIQUE , item , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
2012-05-30 08:01:02 +02:00
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_INS_CHAR_GIFT );
2014-10-23 23:04:16 +02:00
stmt -> setUInt64 ( 0 , item -> GetOwnerGUID (). GetCounter ());
stmt -> setUInt64 ( 1 , item -> GetGUID (). GetCounter ());
2012-05-30 08:01:02 +02:00
stmt -> setUInt32 ( 2 , item -> GetEntry ());
stmt -> setUInt32 ( 3 , item -> GetUInt32Value ( ITEM_FIELD_FLAGS ));
trans -> Append ( stmt );
2008-11-20 16:16:57 -06:00
item -> SetEntry ( gift -> GetEntry ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
switch ( item -> GetEntry ())
{
2010-04-07 22:59:46 +02:00
case 5042 : item -> SetEntry ( 5043 ); break ;
case 5048 : item -> SetEntry ( 5044 ); break ;
2008-11-20 16:16:57 -06:00
case 17303 : item -> SetEntry ( 17302 ); break ;
case 17304 : item -> SetEntry ( 17305 ); break ;
case 17307 : item -> SetEntry ( 17308 ); break ;
case 21830 : item -> SetEntry ( 21831 ); break ;
2008-10-11 14:16:25 -05:00
}
2014-09-14 16:14:12 +02:00
item -> SetGuidValue ( ITEM_FIELD_GIFTCREATOR , _player -> GetGUID ());
2010-08-04 10:34:30 +02:00
item -> SetUInt32Value ( ITEM_FIELD_FLAGS , ITEM_FLAG_WRAPPED );
2008-10-11 14:16:25 -05:00
item -> SetState ( ITEM_CHANGED , _player );
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( item -> GetState () == ITEM_NEW ) // save new item, to have alway for `character_gifts` record in `item_instance`
2008-10-11 14:16:25 -05:00
{
// after save it will be impossible to remove the item from the queue
item -> RemoveFromUpdateQueueOf ( _player );
2010-08-21 03:19:25 +02:00
item -> SaveToDB ( trans ); // item gave inventory record unchanged and can be save standalone
2008-10-11 14:16:25 -05:00
}
2010-08-21 03:19:25 +02:00
CharacterDatabase . CommitTransaction ( trans );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 1 ;
_player -> DestroyItemCount ( gift , count , true );
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleSocketOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_SOCKET_GEMS" );
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
ObjectGuid item_guid ;
ObjectGuid gem_guids [ MAX_GEM_SOCKETS ];
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> item_guid ;
2010-04-07 19:14:10 +02:00
if ( ! item_guid )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i )
2012-08-05 19:40:30 -05:00
recvData >> gem_guids [ i ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//cheat -> tried to socket same gem multiple times
2014-10-21 19:23:32 +02:00
if (( ! gem_guids [ 0 ]. IsEmpty () && ( gem_guids [ 0 ] == gem_guids [ 1 ] || gem_guids [ 0 ] == gem_guids [ 2 ])) ||
( ! gem_guids [ 1 ]. IsEmpty () && ( gem_guids [ 1 ] == gem_guids [ 2 ])))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * itemTarget = _player -> GetItemByGuid ( item_guid );
2010-04-07 19:14:10 +02:00
if ( ! itemTarget ) //missing item to socket
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-04-28 22:42:33 +02:00
ItemTemplate const * itemProto = itemTarget -> GetTemplate ();
2010-04-07 19:14:10 +02:00
if ( ! itemProto )
2009-02-03 19:12:17 -06:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//this slot is excepted when applying / removing meta gem bonus
2009-02-24 11:14:28 -06:00
uint8 slot = itemTarget -> IsEquipped () ? itemTarget -> GetSlot () : uint8 ( NULL_SLOT );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Item * Gems [ MAX_GEM_SOCKETS ];
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i )
2014-10-21 19:23:32 +02:00
Gems [ i ] = ! gem_guids [ i ]. IsEmpty () ? _player -> GetItemByGuid ( gem_guids [ i ]) : NULL ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
GemPropertiesEntry const * GemProps [ MAX_GEM_SOCKETS ];
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i ) //get geminfo from dbc storage
2011-04-28 22:42:33 +02:00
GemProps [ i ] = ( Gems [ i ]) ? sGemPropertiesStore . LookupEntry ( Gems [ i ] -> GetTemplate () -> GemProperties ) : NULL ;
2009-10-17 15:51:44 -07:00
2014-03-10 12:58:03 +01:00
// Find first prismatic socket
int32 firstPrismatic = 0 ;
while ( firstPrismatic < MAX_GEM_SOCKETS && itemProto -> Socket [ firstPrismatic ]. Color )
++ firstPrismatic ;
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i ) //check for hack maybe
2008-10-11 14:16:25 -05:00
{
2009-02-03 19:12:17 -06:00
if ( ! GemProps [ i ])
continue ;
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
// tried to put gem in socket where no socket exists (take care about prismatic sockets)
if ( ! itemProto -> Socket [ i ]. Color )
{
// no prismatic socket
2010-04-07 19:14:10 +02:00
if ( ! itemTarget -> GetEnchantmentId ( PRISMATIC_ENCHANTMENT_SLOT ))
2009-02-03 19:12:17 -06:00
return ;
2009-10-17 15:51:44 -07:00
2014-03-10 12:58:03 +01:00
if ( i != firstPrismatic )
2009-02-03 19:12:17 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
// tried to put normal gem in meta socket
if ( itemProto -> Socket [ i ]. Color == SOCKET_COLOR_META && GemProps [ i ] -> color != SOCKET_COLOR_META )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// tried to put meta gem in normal socket
2009-02-03 19:12:17 -06:00
if ( itemProto -> Socket [ i ]. Color != SOCKET_COLOR_META && GemProps [ i ] -> color == SOCKET_COLOR_META )
2008-10-11 14:16:25 -05:00
return ;
2012-08-06 23:00:57 +02:00
2012-08-05 19:40:30 -05:00
// tried to put normal gem in cogwheel socket
if ( itemProto -> Socket [ i ]. Color == SOCKET_COLOR_COGWHEEL && GemProps [ i ] -> color != SOCKET_COLOR_COGWHEEL )
return ;
// tried to put cogwheel gem in normal socket
if ( itemProto -> Socket [ i ]. Color != SOCKET_COLOR_COGWHEEL && GemProps [ i ] -> color == SOCKET_COLOR_COGWHEEL )
return ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-02-03 19:12:17 -06:00
uint32 GemEnchants [ MAX_GEM_SOCKETS ];
uint32 OldEnchants [ MAX_GEM_SOCKETS ];
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i ) //get new and old enchantments
2008-10-11 14:16:25 -05:00
{
GemEnchants [ i ] = ( GemProps [ i ]) ? GemProps [ i ] -> spellitemenchantement : 0 ;
OldEnchants [ i ] = itemTarget -> GetEnchantmentId ( EnchantmentSlot ( SOCK_ENCHANTMENT_SLOT + i ));
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check unique-equipped conditions
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! Gems [ i ])
2009-02-15 11:58:27 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2009-02-15 11:58:27 -06:00
// continue check for case when attempt add 2 similar unique equipped gems in one item.
2011-04-28 22:42:33 +02:00
ItemTemplate const * iGemProto = Gems [ i ] -> GetTemplate ();
2009-10-17 15:51:44 -07:00
2009-02-15 11:58:27 -06:00
// unique item (for new and already placed bit removed enchantments
2010-08-04 10:34:30 +02:00
if ( iGemProto -> Flags & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED )
2008-10-11 14:16:25 -05:00
{
2009-02-15 11:58:27 -06:00
for ( int j = 0 ; j < MAX_GEM_SOCKETS ; ++ j )
2008-10-11 14:16:25 -05:00
{
2010-04-07 23:25:02 +02:00
if ( i == j ) // skip self
2009-02-15 11:58:27 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2009-02-15 11:58:27 -06:00
if ( Gems [ j ])
2008-10-11 14:16:25 -05:00
{
2009-02-15 11:58:27 -06:00
if ( iGemProto -> ItemId == Gems [ j ] -> GetEntry ())
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED , itemTarget , NULL );
2009-02-15 11:58:27 -06:00
return ;
}
}
2010-04-07 19:14:10 +02:00
else if ( OldEnchants [ j ])
2009-02-15 11:58:27 -06:00
{
2010-04-07 19:14:10 +02:00
if ( SpellItemEnchantmentEntry const * enchantEntry = sSpellItemEnchantmentStore . LookupEntry ( OldEnchants [ j ]))
2009-02-15 11:58:27 -06:00
{
if ( iGemProto -> ItemId == enchantEntry -> GemID )
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED , itemTarget , NULL );
2009-02-15 11:58:27 -06:00
return ;
}
}
2008-10-11 14:16:25 -05:00
}
}
2009-02-15 11:58:27 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-15 11:58:27 -06:00
// unique limit type item
int32 limit_newcount = 0 ;
if ( iGemProto -> ItemLimitCategory )
{
2010-04-07 19:14:10 +02:00
if ( ItemLimitCategoryEntry const * limitEntry = sItemLimitCategoryStore . LookupEntry ( iGemProto -> ItemLimitCategory ))
2008-10-11 14:16:25 -05:00
{
2010-08-05 22:08:07 +06:00
// NOTE: limitEntry->mode is not checked because if item has limit then it is applied in equip case
2009-02-15 11:58:27 -06:00
for ( int j = 0 ; j < MAX_GEM_SOCKETS ; ++ j )
{
if ( Gems [ j ])
{
// new gem
2011-04-28 22:42:33 +02:00
if ( iGemProto -> ItemLimitCategory == Gems [ j ] -> GetTemplate () -> ItemLimitCategory )
2009-02-15 11:58:27 -06:00
++ limit_newcount ;
}
2010-04-07 19:14:10 +02:00
else if ( OldEnchants [ j ])
2009-02-15 11:58:27 -06:00
{
2010-11-08 17:11:05 +01:00
// existing gem
2010-04-07 19:14:10 +02:00
if ( SpellItemEnchantmentEntry const * enchantEntry = sSpellItemEnchantmentStore . LookupEntry ( OldEnchants [ j ]))
2011-04-28 22:42:33 +02:00
if ( ItemTemplate const * jProto = sObjectMgr -> GetItemTemplate ( enchantEntry -> GemID ))
2009-02-15 11:58:27 -06:00
if ( iGemProto -> ItemLimitCategory == jProto -> ItemLimitCategory )
++ limit_newcount ;
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( limit_newcount > 0 && uint32 ( limit_newcount ) > limitEntry -> maxCount )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED , itemTarget , NULL );
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-02-15 11:58:27 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-15 11:58:27 -06:00
// for equipped item check all equipment for duplicate equipped gems
2010-04-07 19:14:10 +02:00
if ( itemTarget -> IsEquipped ())
2009-02-15 11:58:27 -06:00
{
2011-04-29 16:48:15 +06:00
if ( InventoryResult res = _player -> CanEquipUniqueItem ( Gems [ i ], slot , std :: max ( limit_newcount , 0 )))
2009-02-15 11:58:27 -06:00
{
2010-04-07 22:59:46 +02:00
_player -> SendEquipError ( res , itemTarget , NULL );
2009-02-15 11:58:27 -06:00
return ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
bool SocketBonusActivated = itemTarget -> GemsFitSockets (); //save state of socketbonus
2008-10-11 14:16:25 -05:00
_player -> ToggleMetaGemsActive ( slot , false ); //turn off all metagems (except for the target item)
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//remove ALL enchants
2011-04-29 16:48:15 +06:00
for ( uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT ; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS ; ++ enchant_slot )
_player -> ApplyEnchantment ( itemTarget , EnchantmentSlot ( enchant_slot ), false );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < MAX_GEM_SOCKETS ; ++ i )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GemEnchants [ i ])
2008-10-11 14:16:25 -05:00
{
2013-05-25 11:09:21 +02:00
itemTarget -> SetEnchantment ( EnchantmentSlot ( SOCK_ENCHANTMENT_SLOT + i ), GemEnchants [ i ], 0 , 0 , _player -> GetGUID ());
2010-04-07 19:14:10 +02:00
if ( Item * guidItem = _player -> GetItemByGuid ( gem_guids [ i ]))
2013-05-30 20:57:07 +02:00
{
uint32 gemCount = 1 ;
2012-08-20 15:55:24 +02:00
_player -> DestroyItemCount ( guidItem , gemCount , true );
2013-05-30 20:57:07 +02:00
}
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT ; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS ; ++ enchant_slot )
2011-04-29 20:47:02 +02:00
_player -> ApplyEnchantment ( itemTarget , EnchantmentSlot ( enchant_slot ), true );
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
bool SocketBonusToBeActivated = itemTarget -> GemsFitSockets (); //current socketbonus state
2010-04-07 19:14:10 +02:00
if ( SocketBonusActivated ^ SocketBonusToBeActivated ) //if there was a change...
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
_player -> ApplyEnchantment ( itemTarget , BONUS_ENCHANTMENT_SLOT , false );
2013-05-25 11:09:21 +02:00
itemTarget -> SetEnchantment ( BONUS_ENCHANTMENT_SLOT , ( SocketBonusToBeActivated ? itemTarget -> GetTemplate () -> socketBonus : 0 ), 0 , 0 , _player -> GetGUID ());
2011-04-29 20:47:02 +02:00
_player -> ApplyEnchantment ( itemTarget , BONUS_ENCHANTMENT_SLOT , true );
2008-10-11 14:16:25 -05:00
//it is not displayed, client has an inbuilt system to determine if the bonus is activated
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
_player -> ToggleMetaGemsActive ( slot , true ); //turn on all metagems (except for target item)
2010-09-21 21:55:16 +02:00
2012-06-23 12:31:46 +02:00
_player -> RemoveTradeableItem ( itemTarget );
2011-10-18 10:44:45 +02:00
itemTarget -> ClearSoulboundTradeable ( _player ); // clear tradeable flag
2013-05-25 11:09:21 +02:00
itemTarget -> SendUpdateSockets ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleCancelTempEnchantmentOpcode ( WorldPacket & recvData )
2008-10-11 14:16:25 -05:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT" );
2009-10-17 15:51:44 -07:00
2012-01-11 21:54:28 -05:00
uint32 slot ;
2009-10-17 15:51:44 -07:00
2012-08-05 19:40:30 -05:00
recvData >> slot ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// apply only to equipped item
2012-01-11 21:54:28 -05:00
if ( ! Player :: IsEquipmentPos ( INVENTORY_SLOT_BAG_0 , slot ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2012-01-11 21:54:28 -05:00
Item * item = GetPlayer () -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , slot );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! item )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! item -> GetEnchantmentId ( TEMP_ENCHANTMENT_SLOT ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
GetPlayer () -> ApplyEnchantment ( item , TEMP_ENCHANTMENT_SLOT , false );
2008-10-11 14:16:25 -05:00
item -> ClearEnchantment ( TEMP_ENCHANTMENT_SLOT );
}
2009-02-17 20:07:49 -06:00
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleItemRefundInfoRequest ( WorldPacket & recvData )
2009-12-17 11:18:07 +01:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_ITEM_REFUND_INFO" );
2009-12-17 11:18:07 +01:00
2014-09-14 16:14:12 +02:00
ObjectGuid guid ;
2012-08-05 19:40:30 -05:00
recvData >> guid ; // item guid
2009-12-17 11:18:07 +01:00
2011-09-15 14:08:17 +02:00
Item * item = _player -> GetItemByGuid ( guid );
2010-03-18 17:27:40 +01:00
if ( ! item )
2009-12-17 11:18:07 +01:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "Item refund: item not found!" );
2009-12-17 11:18:07 +01:00
return ;
}
2010-04-30 19:20:59 +02:00
GetPlayer () -> SendRefundInfo ( item );
2009-12-17 18:35:59 +01:00
}
2012-08-05 19:40:30 -05:00
void WorldSession :: HandleItemRefund ( WorldPacket & recvData )
2009-12-17 18:35:59 +01:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_ITEM_REFUND" );
2014-09-14 16:14:12 +02:00
ObjectGuid guid ;
2012-08-05 19:40:30 -05:00
recvData >> guid ; // item guid
2009-12-17 18:35:59 +01:00
2011-09-15 14:08:17 +02:00
Item * item = _player -> GetItemByGuid ( guid );
2010-03-18 17:27:40 +01:00
if ( ! item )
2009-12-17 18:35:59 +01:00
{
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "Item refund: item not found!" );
2009-12-17 18:35:59 +01:00
return ;
}
2014-06-23 22:40:26 +02:00
// Don't try to refund item currently being disenchanted
if ( _player -> GetLootGUID () == guid )
return ;
2010-04-30 19:20:59 +02:00
GetPlayer () -> RefundItem ( item );
2009-12-17 11:18:07 +01:00
}
2010-04-14 12:43:42 +04:00
/**
* Handles the packet sent by the client when requesting information about item text.
*
* This function is called when player clicks on item which has some flag set
*/
2012-11-27 13:02:04 +01:00
void WorldSession :: HandleItemTextQuery ( WorldPacket & recvData )
2010-04-14 12:43:42 +04:00
{
2014-09-14 16:14:12 +02:00
ObjectGuid itemGuid ;
2012-08-05 19:40:30 -05:00
recvData >> itemGuid ;
2010-04-14 12:43:42 +04:00
2014-09-14 16:14:12 +02:00
TC_LOG_DEBUG ( "network" , "CMSG_ITEM_TEXT_QUERY %s" , itemGuid . ToString (). c_str ());
2010-04-14 12:43:42 +04:00
2012-01-14 22:32:39 +00:00
WorldPacket data ( SMSG_ITEM_TEXT_QUERY_RESPONSE , 14 ); // guess size
2010-04-14 12:43:42 +04:00
2011-09-15 14:08:17 +02:00
if ( Item * item = _player -> GetItemByGuid ( itemGuid ))
2010-04-14 12:43:42 +04:00
{
data << uint8 ( 0 ); // has text
2014-10-21 21:09:15 +02:00
data << itemGuid ; // item guid
2010-04-14 12:43:42 +04:00
data << item -> GetText ();
}
else
{
data << uint8 ( 1 ); // no text
}
SendPacket ( & data );
}
2012-08-01 02:46:32 +01:00
void WorldSession :: HandleTransmogrifyItems ( WorldPacket & recvData )
{
2013-11-08 11:12:17 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_TRANSMOGRIFY_ITEMS" );
2012-08-01 02:46:32 +01:00
Player * player = GetPlayer ();
// Read data
uint32 count = recvData . ReadBits ( 22 );
2012-10-16 09:35:15 +02:00
if ( count >= EQUIPMENT_SLOT_END )
2012-08-01 02:46:32 +01:00
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) sent a wrong count (%u) when transmogrifying items." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), count );
2012-08-01 02:46:32 +01:00
recvData . rfinish ();
return ;
}
2014-09-20 11:05:30 +02:00
std :: vector < ObjectGuid > itemGuids ( count , ObjectGuid ());
2012-08-10 02:57:16 +01:00
std :: vector < uint32 > newEntries ( count , 0 );
std :: vector < uint32 > slots ( count , 0 );
2012-08-01 14:31:09 +02:00
2012-08-01 02:46:32 +01:00
for ( uint8 i = 0 ; i < count ; ++ i )
{
itemGuids [ i ][ 0 ] = recvData . ReadBit ();
itemGuids [ i ][ 5 ] = recvData . ReadBit ();
itemGuids [ i ][ 6 ] = recvData . ReadBit ();
itemGuids [ i ][ 2 ] = recvData . ReadBit ();
itemGuids [ i ][ 3 ] = recvData . ReadBit ();
itemGuids [ i ][ 7 ] = recvData . ReadBit ();
itemGuids [ i ][ 4 ] = recvData . ReadBit ();
itemGuids [ i ][ 1 ] = recvData . ReadBit ();
}
ObjectGuid npcGuid ;
npcGuid [ 7 ] = recvData . ReadBit ();
npcGuid [ 3 ] = recvData . ReadBit ();
npcGuid [ 5 ] = recvData . ReadBit ();
npcGuid [ 6 ] = recvData . ReadBit ();
npcGuid [ 1 ] = recvData . ReadBit ();
npcGuid [ 4 ] = recvData . ReadBit ();
npcGuid [ 0 ] = recvData . ReadBit ();
npcGuid [ 2 ] = recvData . ReadBit ();
recvData . FlushBits ();
for ( uint32 i = 0 ; i < count ; ++ i )
{
2012-08-09 21:20:05 +01:00
recvData >> newEntries [ i ];
2012-08-01 02:46:32 +01:00
recvData . ReadByteSeq ( itemGuids [ i ][ 1 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 5 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 0 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 4 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 6 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 7 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 3 ]);
recvData . ReadByteSeq ( itemGuids [ i ][ 2 ]);
2012-08-09 21:20:05 +01:00
recvData >> slots [ i ];
2012-08-01 02:46:32 +01:00
}
recvData . ReadByteSeq ( npcGuid [ 7 ]);
recvData . ReadByteSeq ( npcGuid [ 2 ]);
recvData . ReadByteSeq ( npcGuid [ 5 ]);
recvData . ReadByteSeq ( npcGuid [ 4 ]);
recvData . ReadByteSeq ( npcGuid [ 3 ]);
recvData . ReadByteSeq ( npcGuid [ 1 ]);
recvData . ReadByteSeq ( npcGuid [ 6 ]);
recvData . ReadByteSeq ( npcGuid [ 0 ]);
// Validate
if ( ! player -> GetNPCIfCanInteractWith ( npcGuid , UNIT_NPC_FLAG_TRANSMOGRIFIER ))
{
2014-09-20 11:05:30 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - %s not found or player can't interact with it." , npcGuid . ToString (). c_str ());
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
int64 cost = 0 ;
std :: vector < Item *> transmogrifier ( count , NULL );
std :: vector < Item *> transmogrified ( count , NULL );
2012-08-01 02:46:32 +01:00
for ( uint8 i = 0 ; i < count ; ++ i )
{
// slot of the transmogrified item
2012-10-16 09:35:15 +02:00
if ( slots [ i ] >= EQUIPMENT_SLOT_END )
2012-08-01 02:46:32 +01:00
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify %s with a wrong slot (%u) when transmogrifying items." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), itemGuids [ i ]. ToString (). c_str (), slots [ i ]);
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
// transmogrified item
Item * itemTransmogrified = player -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , slots [ i ]);
if ( ! itemTransmogrified )
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), slots [ i ]);
2014-07-27 13:42:11 +03:00
return ;
}
// if not resetting look
Item * itemTransmogrifier = NULL ;
2012-08-01 02:46:32 +01:00
if ( newEntries [ i ])
{
2014-07-27 13:42:11 +03:00
// entry of the transmogrifier item
2012-08-01 02:46:32 +01:00
ItemTemplate const * proto = sObjectMgr -> GetItemTemplate ( newEntries [ i ]);
if ( ! proto )
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify to an invalid item (entry: %u)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), newEntries [ i ]);
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
// guid of the transmogrifier item
2012-08-01 02:46:32 +01:00
itemTransmogrifier = player -> GetItemByGuid ( itemGuids [ i ]);
if ( ! itemTransmogrifier )
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid item (%s)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), itemGuids [ i ]. ToString (). c_str ());
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
// entry of transmogrifier and from packet
2014-06-07 19:23:38 -05:00
if ( itemTransmogrifier -> GetEntry () != newEntries [ i ])
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid entry (entry: %u) for %s." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), newEntries [ i ], itemGuids [ i ]. ToString (). c_str ());
2014-06-07 19:23:38 -05:00
return ;
}
2014-07-27 13:42:11 +03:00
// validity of the transmogrification items
2012-08-01 02:46:32 +01:00
if ( ! Item :: CanTransmogrifyItemWithItem ( itemTransmogrified , itemTransmogrifier ))
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) failed CanTransmogrifyItemWithItem (%u with %u)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), itemTransmogrified -> GetEntry (), itemTransmogrifier -> GetEntry ());
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
// add cost
cost += itemTransmogrified -> GetSpecialPrice ();
}
2012-08-01 02:46:32 +01:00
2014-07-27 13:42:11 +03:00
transmogrifier [ i ] = itemTransmogrifier ;
transmogrified [ i ] = itemTransmogrified ;
}
2012-08-01 02:46:32 +01:00
2014-07-27 13:42:11 +03:00
if ( cost ) // 0 cost if reverting look
{
if ( ! player -> HasEnoughMoney ( cost ))
return ;
player -> ModifyMoney ( - cost );
}
2012-08-01 02:46:32 +01:00
2014-07-27 13:42:11 +03:00
// Everything is fine, proceed
2012-08-28 23:32:09 +02:00
2014-07-27 13:42:11 +03:00
for ( uint8 i = 0 ; i < count ; ++ i )
{
if ( transmogrifier [ i ])
{
// Transmogrify
transmogrified [ i ] -> SetEnchantment ( TRANSMOGRIFY_ENCHANTMENT_SLOT , newEntries [ i ], 0 , 0 );
player -> SetVisibleItemSlot ( slots [ i ], transmogrified [ i ]);
2012-08-02 01:16:45 +01:00
2014-07-27 13:42:11 +03:00
transmogrified [ i ] -> UpdatePlayedTime ( player );
transmogrified [ i ] -> SetOwnerGUID ( player -> GetGUID ());
transmogrified [ i ] -> SetNotRefundable ( player );
transmogrified [ i ] -> ClearSoulboundTradeable ( player );
if ( transmogrifier [ i ] -> GetTemplate () -> Bonding == BIND_WHEN_EQUIPED || transmogrifier [ i ] -> GetTemplate () -> Bonding == BIND_WHEN_USE )
transmogrifier [ i ] -> SetBinding ( true );
transmogrifier [ i ] -> SetOwnerGUID ( player -> GetGUID ());
transmogrifier [ i ] -> SetNotRefundable ( player );
transmogrifier [ i ] -> ClearSoulboundTradeable ( player );
}
else
{
// Reset
transmogrified [ i ] -> ClearEnchantment ( TRANSMOGRIFY_ENCHANTMENT_SLOT );
player -> SetVisibleItemSlot ( slots [ i ], transmogrified [ i ]);
2012-08-01 02:46:32 +01:00
}
}
}
2012-08-03 20:47:09 -05:00
void WorldSession :: SendReforgeResult ( bool success )
{
WorldPacket data ( SMSG_REFORGE_RESULT , 1 );
data . WriteBit ( success );
2012-08-04 11:33:49 -05:00
data . FlushBits ();
2012-08-03 20:47:09 -05:00
SendPacket ( & data );
}
void WorldSession :: HandleReforgeItemOpcode ( WorldPacket & recvData )
{
uint32 slot , reforgeEntry ;
ObjectGuid guid ;
uint32 bag ;
Player * player = GetPlayer ();
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
recvData >> reforgeEntry >> slot >> bag ;
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
guid [ 2 ] = recvData . ReadBit ();
guid [ 6 ] = recvData . ReadBit ();
guid [ 3 ] = recvData . ReadBit ();
guid [ 4 ] = recvData . ReadBit ();
guid [ 1 ] = recvData . ReadBit ();
guid [ 0 ] = recvData . ReadBit ();
guid [ 7 ] = recvData . ReadBit ();
guid [ 5 ] = recvData . ReadBit ();
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
recvData . ReadByteSeq ( guid [ 2 ]);
recvData . ReadByteSeq ( guid [ 3 ]);
recvData . ReadByteSeq ( guid [ 6 ]);
recvData . ReadByteSeq ( guid [ 4 ]);
recvData . ReadByteSeq ( guid [ 1 ]);
recvData . ReadByteSeq ( guid [ 0 ]);
recvData . ReadByteSeq ( guid [ 7 ]);
recvData . ReadByteSeq ( guid [ 5 ]);
if ( ! player -> GetNPCIfCanInteractWith ( guid , UNIT_NPC_FLAG_REFORGER ))
{
2014-09-20 11:05:30 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleReforgeItemOpcode - %s not found or player can't interact with it." , guid . ToString (). c_str ());
2012-08-03 20:47:09 -05:00
SendReforgeResult ( false );
return ;
}
2012-08-04 19:11:13 +01:00
Item * item = player -> GetItemByPos ( bag , slot );
2012-08-03 20:47:09 -05:00
if ( ! item )
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleReforgeItemOpcode - Player (%s Name: %s) tried to reforge an invalid/non-existant item." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str ());
2012-08-03 20:47:09 -05:00
SendReforgeResult ( false );
return ;
}
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
if ( ! reforgeEntry )
{
2014-06-07 19:18:54 -05:00
if ( ! item -> GetEnchantmentId ( REFORGE_ENCHANTMENT_SLOT ))
{
2014-10-22 19:33:06 +02:00
TC_LOG_ERROR ( "network" , "WORLD: HandleReforgeItemOpcode - Player (%s Name: %s) tried to remove reforge from non-reforged item (Entry: %u)" , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), item -> GetEntry ());
2014-06-07 19:18:54 -05:00
SendReforgeResult ( false );
return ;
}
2012-08-03 20:47:09 -05:00
// Reset the item
2012-08-06 23:00:57 +02:00
if ( item -> IsEquipped ())
player -> ApplyReforgeEnchantment ( item , false );
2012-08-03 20:47:09 -05:00
item -> ClearEnchantment ( REFORGE_ENCHANTMENT_SLOT );
SendReforgeResult ( true );
return ;
}
2012-08-04 19:11:13 +01:00
2014-06-07 19:18:54 -05:00
if ( item -> GetEnchantmentId ( REFORGE_ENCHANTMENT_SLOT ))
{
2014-10-22 19:33:06 +02:00
TC_LOG_ERROR ( "network" , "WORLD: HandleReforgeItemOpcode - Player (%s Name: %s) tried to reforge an already reforged item (Entry: %u)" , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), item -> GetEntry ());
2014-06-07 19:18:54 -05:00
SendReforgeResult ( false );
return ;
}
2012-08-06 23:00:57 +02:00
ItemReforgeEntry const * stats = sItemReforgeStore . LookupEntry ( reforgeEntry );
if ( ! stats )
2012-08-03 20:47:09 -05:00
{
2014-10-22 19:33:06 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleReforgeItemOpcode - Player (%s Name: %s) tried to reforge an item with invalid reforge entry (%u)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), reforgeEntry );
2012-08-03 20:47:09 -05:00
SendReforgeResult ( false );
return ;
}
2012-08-04 19:11:13 +01:00
2012-08-06 23:00:57 +02:00
if ( ! item -> GetReforgableStat ( ItemModType ( stats -> SourceStat )) || item -> GetReforgableStat ( ItemModType ( stats -> FinalStat ))) // Cheating, you cant reforge to a stat that the item already has, nor reforge from a stat that the item does not have
{
SendReforgeResult ( false );
return ;
}
2012-08-05 17:33:29 -05:00
if ( ! player -> HasEnoughMoney ( uint64 ( item -> GetSpecialPrice ()))) // cheating
2012-08-03 20:47:09 -05:00
{
SendReforgeResult ( false );
return ;
}
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
player -> ModifyMoney ( - int64 ( item -> GetSpecialPrice ()));
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
item -> SetEnchantment ( REFORGE_ENCHANTMENT_SLOT , reforgeEntry , 0 , 0 );
2012-08-04 19:11:13 +01:00
2012-08-03 20:47:09 -05:00
SendReforgeResult ( true );
2012-08-04 19:11:13 +01:00
2012-08-06 23:00:57 +02:00
if ( item -> IsEquipped ())
player -> ApplyReforgeEnchantment ( item , true );
2012-08-03 20:47:09 -05:00
}
2014-06-07 23:40:37 +02:00
2014-09-14 16:14:12 +02:00
bool WorldSession :: CanUseBank ( ObjectGuid bankerGUID ) const
2014-06-07 22:47:50 +02:00
{
// bankerGUID parameter is optional, set to 0 by default.
if ( ! bankerGUID )
bankerGUID = m_currentBankerGUID ;
bool isUsingBankCommand = ( bankerGUID == GetPlayer () -> GetGUID () && bankerGUID == m_currentBankerGUID );
if ( ! isUsingBankCommand )
{
Creature * creature = GetPlayer () -> GetNPCIfCanInteractWith ( bankerGUID , UNIT_NPC_FLAG_BANKER );
if ( ! creature )
return false ;
}
return true ;
2014-06-07 23:40:37 +02:00
}