2010-10-07 15:35:36 +02:00
/*
2016-01-01 00:34:25 +01:00
* Copyright (C) 2008-2016 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"
2013-03-15 21:19:15 +01:00
#include "DB2Stores.h"
2014-11-24 20:50:19 +02:00
#include "NPCPackets.h"
#include "ItemPackets.h"
2015-09-09 14:52:32 +02:00
#include "BattlePetMgr.h"
2009-10-17 15:51:44 -07:00
2014-12-21 19:11:39 +01:00
void WorldSession :: HandleSplitItemOpcode ( WorldPackets :: Item :: SplitItem & splitItem )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
if ( ! splitItem . Inv . Items . empty ())
2014-12-20 22:29:06 +01:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_ERROR ( "network" , "HandleSplitItemOpcode - Invalid ItemCount (" SZFMTD ")" , splitItem . Inv . Items . size ());
2014-12-20 22:29:06 +01:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "HandleSplitItemOpcode: receive FromPackSlot: %u, FromSlot: %u, ToPackSlot: %u, ToSlot: %u, Quantity: %u" ,
splitItem . FromPackSlot , splitItem . FromSlot , splitItem . ToPackSlot , splitItem . ToSlot , splitItem . Quantity );
2014-12-23 00:25:43 +01:00
2014-12-30 00:39:51 +01:00
uint16 src = (( splitItem . FromPackSlot << 8 ) | splitItem . FromSlot );
uint16 dst = (( splitItem . ToPackSlot << 8 ) | splitItem . ToSlot );
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
2014-12-30 00:39:51 +01:00
// check count - if zero it's fake packet
if ( ! splitItem . Quantity )
return ;
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( ! _player -> IsValidPos ( splitItem . FromPackSlot , splitItem . FromSlot , true ))
2008-11-10 09:04:23 -06:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( ! _player -> IsValidPos ( splitItem . ToPackSlot , splitItem . ToSlot , false )) // can be autostore pos
2008-11-10 09:04:23 -06:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
_player -> SplitItem ( src , dst , splitItem . Quantity );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2014-12-21 19:11:39 +01:00
void WorldSession :: HandleSwapInvItemOpcode ( WorldPackets :: Item :: SwapInvItem & swapInvItem )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
if ( swapInvItem . Inv . Items . size () != 2 )
2014-12-20 22:29:06 +01:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_ERROR ( "network" , "HandleSwapInvItemOpcode - Invalid itemCount (" SZFMTD ")" , swapInvItem . Inv . Items . size ());
2014-12-20 22:29:06 +01:00
return ;
}
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "HandleSwapInvItemOpcode: receive Slot1: %u, Slot2: %u" ,
swapInvItem . Slot1 , swapInvItem . Slot2 );
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
2014-12-30 00:39:51 +01:00
if ( swapInvItem . Slot1 == swapInvItem . Slot2 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( ! _player -> IsValidPos ( INVENTORY_SLOT_BAG_0 , swapInvItem . Slot1 , true ))
2008-11-10 09:04:23 -06:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( ! _player -> IsValidPos ( INVENTORY_SLOT_BAG_0 , swapInvItem . Slot2 , true ))
2008-11-10 09:04:23 -06:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( _player -> IsBankPos ( INVENTORY_SLOT_BAG_0 , swapInvItem . Slot1 ) && ! CanUseBank ())
2014-06-07 22:47:50 +02:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "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 ;
}
2014-12-30 00:39:51 +01:00
if ( _player -> IsBankPos ( INVENTORY_SLOT_BAG_0 , swapInvItem . Slot2 ) && ! CanUseBank ())
2014-06-07 22:47:50 +02:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "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 ;
}
2014-12-30 00:39:51 +01:00
uint16 src = (( INVENTORY_SLOT_BAG_0 << 8 ) | swapInvItem . Slot1 );
uint16 dst = (( INVENTORY_SLOT_BAG_0 << 8 ) | swapInvItem . Slot2 );
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
2015-04-11 00:07:38 +02:00
void WorldSession :: HandleAutoEquipItemSlotOpcode ( WorldPackets :: Item :: AutoEquipItemSlot & autoEquipItemSlot )
2008-10-11 14:16:25 -05:00
{
// cheating attempt, client should never send opcode in that case
2015-04-11 00:07:38 +02:00
if ( autoEquipItemSlot . Inv . Items . size () != 1 || ! Player :: IsEquipmentPos ( INVENTORY_SLOT_BAG_0 , autoEquipItemSlot . ItemDstSlot ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-04-11 00:07:38 +02:00
Item * item = _player -> GetItemByGuid ( autoEquipItemSlot . Item );
uint16 dstPos = autoEquipItemSlot . ItemDstSlot | ( INVENTORY_SLOT_BAG_0 << 8 );
uint16 srcPos = autoEquipItemSlot . Inv . Items [ 0 ]. Slot | ( uint32 ( autoEquipItemSlot . Inv . Items [ 0 ]. ContainerSlot ) << 8 );
2009-10-17 15:51:44 -07:00
2015-04-11 00:07:38 +02:00
if ( ! item || item -> GetPos () != srcPos || srcPos == dstPos )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-04-11 00:07:38 +02:00
_player -> SwapItem ( srcPos , dstPos );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2014-12-21 19:11:39 +01:00
void WorldSession :: HandleSwapItem ( WorldPackets :: Item :: SwapItem & swapItem )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
if ( swapItem . Inv . Items . size () != 2 )
2014-12-20 17:25:15 +01:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_ERROR ( "network" , "HandleSwapItem - Invalid itemCount (" SZFMTD ")" , swapItem . Inv . Items . size ());
2014-12-20 17:25:15 +01:00
return ;
}
2014-12-20 22:29:06 +01:00
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "HandleSwapItem: receive ContainerSlotA: %u, SlotA: %u, ContainerSlotB: %u, SlotB: %u" ,
swapItem . ContainerSlotA , swapItem . SlotA , swapItem . ContainerSlotB , swapItem . SlotB );
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
uint16 src = (( swapItem . ContainerSlotA << 8 ) | swapItem . SlotA );
uint16 dst = (( swapItem . ContainerSlotB << 8 ) | swapItem . SlotB );
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
2014-12-30 00:39:51 +01:00
if ( ! _player -> IsValidPos ( swapItem . ContainerSlotA , swapItem . SlotA , true ))
2008-11-10 09:04:23 -06:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( ! _player -> IsValidPos ( swapItem . ContainerSlotB , swapItem . SlotB , true ))
2008-11-10 09:04:23 -06:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
if ( _player -> IsBankPos ( swapItem . ContainerSlotA , swapItem . SlotA ) && ! CanUseBank ())
2014-06-07 22:47:50 +02:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "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 ;
}
2014-12-30 00:39:51 +01:00
if ( _player -> IsBankPos ( swapItem . ContainerSlotB , swapItem . SlotB ) && ! CanUseBank ())
2014-06-07 22:47:50 +02:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "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
2014-12-21 19:11:39 +01:00
void WorldSession :: HandleAutoEquipItemOpcode ( WorldPackets :: Item :: AutoEquipItem & autoEquipItem )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
if ( autoEquipItem . Inv . Items . size () != 1 )
2014-12-20 17:25:15 +01:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_ERROR ( "network" , "HandleAutoEquipItemOpcode - Invalid itemCount (" SZFMTD ")" , autoEquipItem . Inv . Items . size ());
2014-12-20 17:25:15 +01:00
return ;
}
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "HandleAutoEquipItemOpcode: receive PackSlot: %u, Slot: %u" ,
autoEquipItem . PackSlot , autoEquipItem . Slot );
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
Item * srcItem = _player -> GetItemByPos ( autoEquipItem . PackSlot , autoEquipItem . Slot );
if ( ! srcItem )
return ; // only at cheat
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint16 dest ;
2014-12-30 00:39:51 +01:00
InventoryResult msg = _player -> CanEquipItem ( NULL_SLOT , dest , srcItem , ! srcItem -> IsBag ());
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( msg , srcItem );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
uint16 src = srcItem -> GetPos ();
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
2014-12-30 00:39:51 +01:00
Item * dstItem = _player -> GetItemByPos ( dest );
if ( ! dstItem ) // empty slot, simple case
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
_player -> RemoveItem ( autoEquipItem . PackSlot , autoEquipItem . Slot , true );
_player -> EquipItem ( dest , srcItem , true );
2008-10-11 14:16:25 -05:00
_player -> AutoUnequipOffhandIfNeed ();
}
else // have currently equipped item, not simple case
{
2014-12-30 00:39:51 +01:00
uint8 dstbag = dstItem -> GetBagSlot ();
uint8 dstslot = dstItem -> GetSlot ();
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
msg = _player -> CanUnequipItem ( dest , ! srcItem -> IsBag ());
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( msg , dstItem );
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
{
2014-12-30 00:39:51 +01:00
msg = _player -> CanStoreItem ( autoEquipItem . PackSlot , autoEquipItem . Slot , sSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2014-12-30 00:39:51 +01:00
msg = _player -> CanStoreItem ( autoEquipItem . PackSlot , NULL_SLOT , sSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2014-12-30 00:39:51 +01:00
msg = _player -> CanStoreItem ( NULL_BAG , NULL_SLOT , sSrc , dstItem , 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
{
2014-12-30 00:39:51 +01:00
msg = _player -> CanBankItem ( autoEquipItem . PackSlot , autoEquipItem . Slot , sSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2014-12-30 00:39:51 +01:00
msg = _player -> CanBankItem ( autoEquipItem . PackSlot , NULL_SLOT , sSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2014-12-30 00:39:51 +01:00
msg = _player -> CanBankItem ( NULL_BAG , NULL_SLOT , sSrc , dstItem , 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
{
2014-12-30 00:39:51 +01:00
msg = _player -> CanEquipItem ( autoEquipItem . Slot , eSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
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
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( msg , dstItem , srcItem );
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 );
2014-12-30 00:39:51 +01:00
_player -> RemoveItem ( autoEquipItem . PackSlot , autoEquipItem . Slot , false );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// add to dest
2014-12-30 00:39:51 +01:00
_player -> EquipItem ( dest , srcItem , 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 ))
2014-12-30 00:39:51 +01:00
_player -> StoreItem ( sSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
else if ( _player -> IsBankPos ( src ))
2014-12-30 00:39:51 +01:00
_player -> BankItem ( sSrc , dstItem , true );
2010-04-07 22:59:46 +02:00
else if ( _player -> IsEquipmentPos ( src ))
2014-12-30 00:39:51 +01:00
_player -> EquipItem ( eSrc , dstItem , 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
2014-12-21 19:11:39 +01:00
void WorldSession :: HandleDestroyItemOpcode ( WorldPackets :: Item :: DestroyItem & destroyItem )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
TC_LOG_DEBUG ( "network" , "HandleDestroyItemOpcode: receive ContainerId: %u, SlotNum: %u, Count: %u" ,
destroyItem . ContainerId , destroyItem . SlotNum , destroyItem . Count );
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
uint16 pos = ( destroyItem . ContainerId << 8 ) | destroyItem . SlotNum ;
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
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( msg , _player -> GetItemByPos ( pos ));
2008-10-11 14:16:25 -05:00
return ;
}
}
2009-10-17 15:51:44 -07:00
2014-12-30 00:39:51 +01:00
Item * item = _player -> GetItemByPos ( destroyItem . ContainerId , destroyItem . SlotNum );
if ( ! item )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_NOT_FOUND );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2015-05-01 21:56:33 -04:00
if ( item -> GetTemplate () -> GetFlags () & ITEM_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 ;
}
2014-12-30 00:39:51 +01:00
if ( destroyItem . Count )
2008-10-11 14:16:25 -05:00
{
2014-12-30 00:39:51 +01:00
uint32 i_count = destroyItem . Count ;
_player -> DestroyItemCount ( item , i_count , true );
2008-10-11 14:16:25 -05:00
}
else
2014-12-30 00:39:51 +01:00
_player -> DestroyItem ( destroyItem . ContainerId , destroyItem . SlotNum , true );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2015-04-11 21:05:41 +02:00
void WorldSession :: HandleReadItem ( WorldPackets :: Item :: ReadItem & readItem )
2008-10-11 14:16:25 -05:00
{
2015-04-11 21:05:41 +02:00
Item * item = _player -> GetItemByPos ( readItem . PackSlot , readItem . Slot );
if ( item && item -> GetTemplate () -> GetPageText ())
2008-10-11 14:16:25 -05:00
{
2015-04-11 21:05:41 +02:00
InventoryResult msg = _player -> CanUseItem ( item );
2010-04-07 22:59:46 +02:00
if ( msg == EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2015-04-11 21:05:41 +02:00
WorldPackets :: Item :: ReadItemResultOK packet ;
packet . Item = item -> GetGUID ();
SendPacket ( packet . Write ());
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
{
2015-04-11 21:05:41 +02:00
/// @todo: 6.x research new values
/*WorldPackets::Item::ReadItemResultFailed packet;
packet.Item = item->GetGUID();
packet.Subcode = ??;
packet.Delay = ??;
SendPacket(packet.Write());*/
2013-11-08 10:50:51 +01:00
TC_LOG_INFO ( "network" , "STORAGE: Unable to read item" );
2015-04-11 21:05:41 +02:00
_player -> SendEquipError ( msg , item , NULL );
2008-10-11 14:16:25 -05:00
}
}
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
2015-01-04 20:22:42 +01:00
void WorldSession :: HandleSellItemOpcode ( WorldPackets :: Item :: SellItem & packet )
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_SELL_ITEM: Vendor %s, Item %s, Amount: %u" ,
packet . VendorGUID . ToString (). c_str (), packet . ItemGUID . ToString (). c_str (), packet . Amount );
2009-10-17 15:51:44 -07:00
2015-01-04 20:22:42 +01:00
if ( packet . ItemGUID . IsEmpty ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-01-04 20:22:42 +01:00
Creature * creature = GetPlayer () -> GetNPCIfCanInteractWith ( packet . VendorGUID , UNIT_NPC_FLAG_VENDOR );
2011-10-07 11:08:09 -05:00
if ( ! creature )
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleSellItemOpcode - %s not found or you can not interact with him." , packet . VendorGUID . ToString (). c_str ());
_player -> SendSellError ( SELL_ERR_CANT_FIND_VENDOR , nullptr , packet . 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
2015-01-04 20:22:42 +01:00
Item * pItem = _player -> GetItemByGuid ( packet . 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
{
2015-01-04 20:22:42 +01:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , packet . 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
{
2015-01-04 20:22:42 +01:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , packet . 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
{
2015-01-04 20:22:42 +01:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , packet . 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)
2015-05-02 15:38:24 -04:00
if ( pItem -> HasFlag ( ITEM_FIELD_FLAGS , ITEM_FIELD_FLAG_REFUNDABLE ))
2011-01-24 23:10:08 +01:00
return ; // Therefore, no feedback to client
2008-10-11 14:16:25 -05:00
// special case at auto sell (sell all)
2015-01-04 20:22:42 +01:00
if ( packet . Amount == 0 )
packet . Amount = pItem -> GetCount ();
2008-10-11 14:16:25 -05:00
else
{
2008-11-14 16:28:45 -06:00
// prevent sell more items that exist in stack (possible only not from client)
2015-01-04 20:22:42 +01:00
if ( packet . Amount > pItem -> GetCount ())
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , packet . 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
{
2014-12-21 13:35:43 +01:00
if ( pProto -> GetSellPrice () > 0 )
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
if ( packet . Amount < pItem -> GetCount ()) // need split items
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
Item * pNewItem = pItem -> CloneItem ( packet . Amount , _player );
2008-10-11 14:16:25 -05:00
if ( ! pNewItem )
{
2015-01-04 20:22:42 +01:00
TC_LOG_ERROR ( "network" , "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u" , pItem -> GetEntry (), packet . Amount );
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , packet . ItemGUID );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2015-01-04 20:22:42 +01:00
pItem -> SetCount ( pItem -> GetCount () - packet . Amount );
_player -> ItemRemovedQuestCheck ( pItem -> GetEntry (), packet . Amount );
2010-04-07 22:59:46 +02:00
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
2015-01-04 20:22:42 +01:00
uint32 money = pProto -> GetSellPrice () * packet . Amount ;
2010-05-21 16:49:19 -03:00
_player -> ModifyMoney ( money );
2016-05-07 01:16:29 +02:00
_player -> UpdateCriteria ( CRITERIA_TYPE_MONEY_FROM_VENDORS , money );
2008-10-11 14:16:25 -05:00
}
else
2015-01-04 20:22:42 +01:00
_player -> SendSellError ( SELL_ERR_CANT_SELL_ITEM , creature , packet . ItemGUID );
2008-10-11 14:16:25 -05:00
return ;
}
}
2015-01-04 20:22:42 +01:00
_player -> SendSellError ( SELL_ERR_CANT_FIND_ITEM , creature , packet . ItemGUID );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2015-01-04 20:22:42 +01:00
void WorldSession :: HandleBuybackItem ( WorldPackets :: Item :: BuyBackItem & packet )
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: Received CMSG_BUYBACK_ITEM: Vendor %s, Slot: %u" , packet . VendorGUID . ToString (). c_str (), packet . Slot );
2009-10-17 15:51:44 -07:00
2015-01-04 20:22:42 +01:00
Creature * creature = GetPlayer () -> GetNPCIfCanInteractWith ( packet . VendorGUID , UNIT_NPC_FLAG_VENDOR );
2011-10-07 11:08:09 -05:00
if ( ! creature )
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleBuybackItem - Unit (%s) not found or you can not interact with him." , packet . 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
2015-01-04 20:22:42 +01:00
Item * pItem = _player -> GetItemFromBuyBackSlot ( packet . Slot );
2010-04-07 22:59:46 +02:00
if ( pItem )
2008-10-11 14:16:25 -05:00
{
2015-01-04 20:22:42 +01:00
uint32 price = _player -> GetUInt32Value ( PLAYER_FIELD_BUYBACK_PRICE_1 + packet . 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 );
2015-01-04 20:22:42 +01:00
_player -> RemoveItemFromBuyBackSlot ( packet . Slot , false );
2010-04-07 22:59:46 +02:00
_player -> ItemAddedQuestCheck ( pItem -> GetEntry (), pItem -> GetCount ());
2016-05-07 01:16:29 +02:00
_player -> UpdateCriteria ( 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
2015-02-13 00:45:13 +00:00
void WorldSession :: HandleBuyItemOpcode ( WorldPackets :: Item :: BuyItem & packet )
2008-10-11 14:16:25 -05:00
{
2010-04-30 22:35:37 +02:00
// client expects count starting at 1, and we send vendorslot+1 to client already
2015-02-13 00:45:13 +00:00
if ( packet . Muid > 0 )
-- packet . Muid ;
2010-04-30 22:35:37 +02:00
else
return ; // cheating
2012-08-04 19:11:13 +01:00
2015-02-13 00:45:13 +00:00
switch ( packet . ItemType )
2012-08-14 18:11:06 +01:00
{
2015-02-13 00:45:13 +00:00
case ITEM_VENDOR_TYPE_ITEM :
{
Item * bagItem = _player -> GetItemByGuid ( packet . ContainerGUID );
2012-08-04 19:11:13 +01:00
2015-02-13 00:45:13 +00:00
uint8 bag = NULL_BAG ;
if ( bagItem && bagItem -> IsBag ())
bag = bagItem -> GetSlot ();
else if ( packet . ContainerGUID == 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
2015-02-13 00:45:13 +00:00
GetPlayer () -> BuyItemFromVendorSlot ( packet . VendorGUID , packet . Muid , packet . Item . ItemID ,
packet . Quantity , bag , packet . Slot );
break ;
}
case ITEM_VENDOR_TYPE_CURRENCY :
{
GetPlayer () -> BuyCurrencyFromVendorSlot ( packet . VendorGUID , packet . Muid , packet . Item . ItemID , packet . Quantity );
break ;
}
default :
{
TC_LOG_DEBUG ( "network" , "WORLD: received wrong itemType (%u) in HandleBuyItemOpcode" , packet . ItemType );
break ;
}
2012-08-14 18:11:06 +01:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2014-11-24 20:50:19 +02:00
void WorldSession :: HandleListInventoryOpcode ( WorldPackets :: NPC :: Hello & packet )
2008-10-11 14:16:25 -05: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
2014-11-24 20:50:19 +02:00
SendListInventory ( packet . Unit );
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
2014-11-24 20:50:19 +02:00
WorldPackets :: NPC :: VendorInventory packet ;
packet . Vendor = vendor -> GetGUID ();
2009-10-17 15:51:44 -07:00
2014-11-24 20:50:19 +02:00
packet . Items . resize ( rawItemCount );
2012-07-24 00:59:55 +01:00
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
2014-11-24 20:50:19 +02:00
WorldPackets :: NPC :: VendorItem & item = packet . Items [ count ];
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
2014-11-24 20:50:19 +02:00
int32 leftInStock = ! vendorItem -> maxcount ? - 1 : 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
2014-12-21 13:35:43 +01:00
if ( ! ( itemTemplate -> GetAllowableClass () & _player -> getClassMask ()) && itemTemplate -> GetBonding () == 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
2015-05-01 21:56:33 -04:00
if (( itemTemplate -> GetFlags2 () & ITEM_FLAG2_HORDE_ONLY && _player -> GetTeam () == ALLIANCE ) ||
( itemTemplate -> GetFlags2 () & ITEM_FLAG2_ALLIANCE_ONLY && _player -> GetTeam () == HORDE ))
2012-08-14 18:11:06 +01:00
continue ;
// Items sold out are not displayed in list
if ( leftInStock == 0 )
continue ;
}
2012-07-24 00:06:49 +01:00
2015-10-25 13:20:28 +01:00
if ( ! sConditionMgr -> IsObjectMeetingVendorItemConditions ( vendor -> GetEntry (), vendorItem -> item , _player , vendor ))
2012-12-07 09:22:43 +01:00
{
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
2014-12-21 13:35:43 +01:00
int32 price = vendorItem -> IsGoldRequired ( itemTemplate ) ? uint32 ( floor ( itemTemplate -> GetBuyPrice () * 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
2014-11-24 20:50:19 +02:00
item . MuID = slot + 1 ; // client expects counting to start at 1
item . Durability = itemTemplate -> MaxDurability ;
item . ExtendedCostID = vendorItem -> ExtendedCost ;
item . Type = vendorItem -> Type ;
item . Quantity = leftInStock ;
2014-12-21 13:35:43 +01:00
item . StackCount = itemTemplate -> GetBuyCount ();
2014-11-24 20:50:19 +02:00
item . Price = price ;
2012-08-14 18:11:06 +01:00
2014-11-24 20:50:19 +02:00
item . Item . ItemID = vendorItem -> item ;
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
2014-11-24 20:50:19 +02:00
item . MuID = slot + 1 ; // client expects counting to start at 1
item . ExtendedCostID = vendorItem -> ExtendedCost ;
item . Item . ItemID = vendorItem -> item ;
item . Type = vendorItem -> Type ;
item . StackCount = vendorItem -> maxcount ;
2012-07-24 00:59:55 +01:00
}
2014-11-24 20:50:19 +02:00
else
continue ;
2012-07-24 00:06:49 +01:00
2014-11-24 20:50:19 +02:00
if ( ++ count >= MAX_VENDOR_ITEMS )
break ;
}
2012-07-24 00:06:49 +01:00
2014-11-24 20:50:19 +02:00
// Resize vector to real size (some items can be skipped due to checks)
packet . Items . resize ( count );
2012-07-24 00:06:49 +01:00
2014-11-24 20:50:19 +02:00
SendPacket ( packet . Write ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2015-01-26 12:59:18 +01:00
void WorldSession :: HandleAutoStoreBagItemOpcode ( WorldPackets :: Item :: AutoStoreBagItem & packet )
2008-10-11 14:16:25 -05:00
{
2015-01-26 12:59:18 +01:00
if ( ! packet . Inv . Items . empty ())
2014-12-20 22:29:06 +01:00
{
2015-01-26 12:59:18 +01:00
TC_LOG_ERROR ( "network" , "HandleAutoStoreBagItemOpcode - Invalid itemCount (" SZFMTD ")" , packet . Inv . Items . size ());
2014-12-20 22:29:06 +01:00
return ;
}
2015-01-26 12:59:18 +01:00
TC_LOG_DEBUG ( "network" , "HandleAutoStoreBagItemOpcode: receive ContainerSlotA: %u, SlotA: %u, ContainerSlotB: %u" ,
packet . ContainerSlotA , packet . SlotA , packet . ContainerSlotB );
2009-10-17 15:51:44 -07:00
2015-01-26 12:59:18 +01:00
Item * item = _player -> GetItemByPos ( packet . ContainerSlotA , packet . SlotA );
if ( ! item )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-01-26 12:59:18 +01:00
if ( ! _player -> IsValidPos ( packet . ContainerSlotB , NULL_SLOT , false )) // can be autostore pos
2008-11-10 09:04:23 -06:00
{
2015-01-26 12:59:18 +01:00
_player -> SendEquipError ( EQUIP_ERR_WRONG_SLOT );
2008-11-10 09:04:23 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2015-01-26 12:59:18 +01:00
uint16 src = item -> 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
2015-01-26 12:59:18 +01:00
if ( _player -> IsEquipmentPos ( src ) || _player -> IsBagPos ( src ))
2008-10-11 14:16:25 -05:00
{
2015-01-26 12:59:18 +01: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
{
2015-01-26 12:59:18 +01:00
_player -> SendEquipError ( msg , item );
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 ;
2015-01-26 12:59:18 +01:00
InventoryResult msg = _player -> CanStoreItem ( packet . ContainerSlotB , NULL_SLOT , dest , item , false );
2010-04-07 22:59:46 +02:00
if ( msg != EQUIP_ERR_OK )
2008-10-11 14:16:25 -05:00
{
2015-01-26 12:59:18 +01:00
_player -> SendEquipError ( msg , item );
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
2015-01-26 12:59:18 +01:00
_player -> SendEquipError ( EQUIP_ERR_INTERNAL_BAG_ERROR , item );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2015-01-26 12:59:18 +01:00
_player -> RemoveItem ( packet . ContainerSlotA , packet . SlotA , true );
_player -> StoreItem ( dest , item , 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
{
2015-01-17 03:55:29 +01:00
WorldPacket data ( SMSG_ENCHANTMENT_LOG , ( 8 + 8 + 4 + 4 ));
2015-07-25 10:38:45 +02:00
data << target ;
data << caster ;
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
{
2015-05-24 22:06:58 +02:00
WorldPackets :: Item :: ItemEnchantTimeUpdate data ;
data . ItemGuid = Itemguid ;
data . DurationLeft = Duration ;
data . Slot = slot ;
data . OwnerGuid = Playerguid ;
SendPacket ( data . Write ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2015-04-18 23:50:51 +02:00
void WorldSession :: HandleWrapItem ( WorldPackets :: Item :: WrapItem & packet )
2008-10-11 14:16:25 -05:00
{
2015-04-18 23:50:51 +02:00
if ( packet . Inv . Items . size () != 2 )
{
TC_LOG_ERROR ( "network" , "HandleWrapItem - Invalid itemCount (" SZFMTD ")" , packet . Inv . Items . size ());
return ;
}
2009-10-17 15:51:44 -07:00
2015-04-18 23:50:51 +02:00
/// @todo: 6.x find better way for read
// Gift
uint8 giftContainerSlot = packet . Inv . Items [ 0 ]. ContainerSlot ;
uint8 giftSlot = packet . Inv . Items [ 0 ]. Slot ;
// Item
uint8 itemContainerSlot = packet . Inv . Items [ 1 ]. ContainerSlot ;
uint8 itemSlot = packet . Inv . Items [ 1 ]. Slot ;
2009-10-17 15:51:44 -07:00
2015-04-18 23:50:51 +02:00
TC_LOG_DEBUG ( "network" , "HandleWrapItem - Receive giftContainerSlot = %u, giftSlot = %u, itemContainerSlot = %u, itemSlot = %u" , giftContainerSlot , giftSlot , itemContainerSlot , itemSlot );
2009-10-17 15:51:44 -07:00
2015-04-18 23:50:51 +02:00
Item * gift = _player -> GetItemByPos ( giftContainerSlot , giftSlot );
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
2015-05-01 21:56:33 -04:00
if ( ! ( gift -> GetTemplate () -> GetFlags () & ITEM_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
2015-04-18 23:50:51 +02:00
Item * item = _player -> GetItemByPos ( itemContainerSlot , itemSlot );
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
2015-04-18 23:50:51 +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
2015-04-18 23:50:51 +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)
2014-12-21 13:35:43 +01:00
if ( item -> GetTemplate () -> GetMaxCount () > 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 ())
{
2015-04-18 23:50:51 +02:00
case 5042 :
item -> SetEntry ( 5043 );
break ;
case 5048 :
item -> SetEntry ( 5044 );
break ;
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
}
2015-04-18 23:50:51 +02:00
2014-09-14 16:14:12 +02:00
item -> SetGuidValue ( ITEM_FIELD_GIFTCREATOR , _player -> GetGUID ());
2015-05-01 21:56:33 -04:00
item -> SetUInt32Value ( ITEM_FIELD_FLAGS , ITEM_FIELD_FLAG_WRAPPED );
2008-10-11 14:16:25 -05:00
item -> SetState ( ITEM_CHANGED , _player );
2009-10-17 15:51:44 -07:00
2015-04-18 23:50:51 +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 );
2015-04-18 23:50:51 +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
2016-01-18 19:52:49 +01:00
void WorldSession :: HandleSocketGems ( WorldPackets :: Item :: SocketGems & socketGems )
2008-10-11 14:16:25 -05:00
{
2016-01-18 19:52:49 +01:00
if ( ! socketGems . 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
//cheat -> tried to socket same gem multiple times
2016-01-18 19:52:49 +01:00
if (( ! socketGems . GemItem [ 0 ]. IsEmpty () && ( socketGems . GemItem [ 0 ] == socketGems . GemItem [ 1 ] || socketGems . GemItem [ 0 ] == socketGems . GemItem [ 2 ])) ||
( ! socketGems . GemItem [ 1 ]. IsEmpty () && ( socketGems . GemItem [ 1 ] == socketGems . GemItem [ 2 ])))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2016-01-18 19:52:49 +01:00
Item * itemTarget = _player -> GetItemByGuid ( socketGems . ItemGuid );
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 )
2016-01-18 19:52:49 +01:00
Gems [ i ] = ! socketGems . GemItem [ i ]. IsEmpty () ? _player -> GetItemByGuid ( socketGems . GemItem [ 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
2014-12-21 13:35:43 +01:00
GemProps [ i ] = ( Gems [ i ]) ? sGemPropertiesStore . LookupEntry ( Gems [ i ] -> GetTemplate () -> GetGemProperties ()) : NULL ;
2009-10-17 15:51:44 -07:00
2014-03-10 12:58:03 +01:00
// Find first prismatic socket
int32 firstPrismatic = 0 ;
2016-01-18 19:52:49 +01:00
while ( firstPrismatic < MAX_GEM_SOCKETS && itemTarget -> GetSocketColor ( firstPrismatic ))
2014-03-10 12:58:03 +01:00
++ 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)
2016-01-18 19:52:49 +01:00
if ( ! itemTarget -> GetSocketColor ( i ))
2009-02-03 19:12:17 -06:00
{
// 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
2016-01-24 15:56:10 +01:00
// Gem must match socket color
if ( SocketColorToGemTypeMask [ itemTarget -> GetSocketColor ( i )] != GemProps [ i ] -> Type )
{
// unless its red, blue, yellow or prismatic
if ( ! ( SocketColorToGemTypeMask [ itemTarget -> GetSocketColor ( i )] & SOCKET_COLOR_PRISMATIC ) || ! ( GemProps [ i ] -> Type & SOCKET_COLOR_PRISMATIC ))
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 ];
2016-01-24 15:56:10 +01:00
uint32 oldGemItemIds [ 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
{
2014-11-08 20:21:17 +02:00
GemEnchants [ i ] = ( GemProps [ i ]) ? GemProps [ i ] -> EnchantID : 0 ;
2016-01-24 15:56:10 +01:00
oldGemItemIds [ i ] = itemTarget -> GetDynamicValues ( ITEM_DYNAMIC_FIELD_GEMS ). size () > i ? itemTarget -> GetDynamicValues ( ITEM_DYNAMIC_FIELD_GEMS )[ i ] : 0 ;
2008-10-11 14:16:25 -05:00
}
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
2015-05-01 21:56:33 -04:00
if ( iGemProto -> GetFlags () & ITEM_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
{
2014-12-21 13:35:43 +01:00
if ( iGemProto -> GetId () == Gems [ j ] -> GetEntry ())
2009-02-15 11:58:27 -06:00
{
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 ;
}
}
2016-01-24 15:56:10 +01:00
else if ( oldGemItemIds [ j ])
2009-02-15 11:58:27 -06:00
{
2016-01-24 15:56:10 +01:00
if ( iGemProto -> GetId () == oldGemItemIds [ j ])
2009-02-15 11:58:27 -06:00
{
2016-01-24 15:56:10 +01:00
_player -> SendEquipError ( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED , itemTarget , NULL );
return ;
2009-02-15 11:58:27 -06:00
}
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 ;
2014-12-21 13:35:43 +01:00
if ( iGemProto -> GetItemLimitCategory ())
2009-02-15 11:58:27 -06:00
{
2014-12-21 13:35:43 +01:00
if ( ItemLimitCategoryEntry const * limitEntry = sItemLimitCategoryStore . LookupEntry ( iGemProto -> GetItemLimitCategory ()))
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
2014-12-21 13:35:43 +01:00
if ( iGemProto -> GetItemLimitCategory () == Gems [ j ] -> GetTemplate () -> GetItemLimitCategory ())
2009-02-15 11:58:27 -06:00
++ limit_newcount ;
}
2016-01-24 15:56:10 +01:00
else if ( oldGemItemIds [ j ])
2009-02-15 11:58:27 -06:00
{
2010-11-08 17:11:05 +01:00
// existing gem
2016-01-24 15:56:10 +01:00
if ( ItemTemplate const * jProto = sObjectMgr -> GetItemTemplate ( oldGemItemIds [ j ]))
if ( iGemProto -> GetItemLimitCategory () == jProto -> GetItemLimitCategory ())
++ limit_newcount ;
2009-02-15 11:58:27 -06:00
}
}
2009-10-17 15:51:44 -07:00
2014-11-08 21:58:26 +02:00
if ( limit_newcount > 0 && uint32 ( limit_newcount ) > limitEntry -> Quantity )
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
2016-01-24 15:56:10 +01:00
uint32 reqGemSlots = 0 ;
for ( uint32 i = 0 ; i < MAX_GEM_SOCKETS ; ++ i )
if ( Gems [ i ])
reqGemSlots = i + 1 ;
while ( itemTarget -> GetDynamicValues ( ITEM_DYNAMIC_FIELD_GEMS ). size () < reqGemSlots )
itemTarget -> AddDynamicValue ( ITEM_DYNAMIC_FIELD_GEMS , 0 );
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
{
2016-01-24 15:56:10 +01:00
if ( Item * guidItem = _player -> GetItemByGuid ( socketGems . GemItem [ i ]))
2008-10-11 14:16:25 -05:00
{
2016-01-24 15:56:10 +01:00
itemTarget -> SetDynamicValue ( ITEM_DYNAMIC_FIELD_GEMS , i , guidItem -> GetEntry ());
if ( GemEnchants [ i ])
itemTarget -> SetEnchantment ( EnchantmentSlot ( SOCK_ENCHANTMENT_SLOT + i ), GemEnchants [ i ], 0 , 0 , _player -> GetGUID ());
uint32 gemCount = 1 ;
_player -> DestroyItemCount ( guidItem , gemCount , true );
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 );
2014-12-21 13:35:43 +01:00
itemTarget -> SetEnchantment ( BONUS_ENCHANTMENT_SLOT , ( SocketBonusToBeActivated ? itemTarget -> GetTemplate () -> GetSocketBonus () : 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
2015-05-01 00:20:41 +02:00
void WorldSession :: HandleCancelTempEnchantmentOpcode ( WorldPackets :: Item :: CancelTempEnchantment & cancelTempEnchantment )
2008-10-11 14:16:25 -05:00
{
// apply only to equipped item
2015-05-01 00:20:41 +02:00
if ( ! Player :: IsEquipmentPos ( INVENTORY_SLOT_BAG_0 , cancelTempEnchantment . Slot ))
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2015-05-01 00:20:41 +02:00
Item * item = GetPlayer () -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , cancelTempEnchantment . 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
2015-02-01 20:52:05 +01:00
void WorldSession :: HandleGetItemPurchaseData ( WorldPackets :: Item :: GetItemPurchaseData & packet )
2009-12-17 11:18:07 +01:00
{
2015-01-04 20:22:42 +01:00
Item * item = _player -> GetItemByGuid ( packet . ItemGUID );
2010-03-18 17:27:40 +01:00
if ( ! item )
2009-12-17 11:18:07 +01:00
{
2015-02-01 20:52:05 +01:00
TC_LOG_DEBUG ( "network" , "HandleGetItemPurchaseData: Item %s not found!" , packet . ItemGUID . ToString (). c_str ());
2009-12-17 11:18:07 +01:00
return ;
}
2015-02-01 20:52:05 +01:00
TC_LOG_DEBUG ( "network" , "HandleGetItemPurchaseData: Item %s" , packet . ItemGUID . ToString (). c_str ());
2010-04-30 19:20:59 +02:00
GetPlayer () -> SendRefundInfo ( item );
2009-12-17 18:35:59 +01:00
}
2016-02-02 01:06:44 +01:00
void WorldSession :: HandleItemRefund ( WorldPackets :: Item :: ItemPurchaseRefund & packet )
2009-12-17 18:35:59 +01:00
{
2016-02-02 01:06:44 +01:00
Item * item = _player -> GetItemByGuid ( packet . ItemGUID );
2010-03-18 17:27:40 +01:00
if ( ! item )
2009-12-17 18:35:59 +01:00
{
2016-02-02 01:06:44 +01:00
TC_LOG_DEBUG ( "network" , "WorldSession::HandleItemRefund: Item (%s) not found!" , packet . ItemGUID . ToString (). c_str ());
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
2016-02-02 01:06:44 +01:00
if ( _player -> GetLootGUID () == packet . ItemGUID )
2014-06-23 22:40:26 +02:00
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
2015-08-18 17:45:30 +02:00
void WorldSession :: HandleTransmogrifyItems ( WorldPackets :: Item :: TransmogrifyItems & transmogrifyItems )
2012-08-01 02:46:32 +01:00
{
Player * player = GetPlayer ();
// Validate
2015-08-18 17:45:30 +02:00
if ( ! player -> GetNPCIfCanInteractWith ( transmogrifyItems . Npc , UNIT_NPC_FLAG_TRANSMOGRIFIER ))
2012-08-01 02:46:32 +01:00
{
2015-08-18 17:45:30 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - %s not found or player can't interact with it." , transmogrifyItems . Npc . ToString (). c_str ());
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
int64 cost = 0 ;
2015-08-18 17:45:30 +02:00
std :: unordered_map < Item * , Item *> transmogItems ;
std :: unordered_map < Item * , std :: pair < VoidStorageItem * , BonusData >> transmogVoidItems ;
std :: vector < Item *> resetAppearanceItems ;
2014-07-27 13:42:11 +03:00
2015-08-18 17:45:30 +02:00
for ( WorldPackets :: Item :: TransmogrifyItem const & transmogItem : transmogrifyItems . Items )
2012-08-01 02:46:32 +01:00
{
// slot of the transmogrified item
2015-08-18 17:45:30 +02:00
if ( transmogItem . Slot >= EQUIPMENT_SLOT_END )
2012-08-01 02:46:32 +01:00
{
2015-08-18 17:45:30 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify wrong slot (%u) when transmogrifying items." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), transmogItem . Slot );
2012-08-01 02:46:32 +01:00
return ;
}
2014-07-27 13:42:11 +03:00
// transmogrified item
2015-08-18 17:45:30 +02:00
Item * itemTransmogrified = player -> GetItemByPos ( INVENTORY_SLOT_BAG_0 , transmogItem . Slot );
2014-07-27 13:42:11 +03:00
if ( ! itemTransmogrified )
{
2015-08-18 17:45:30 +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 (), transmogItem . Slot );
2014-07-27 13:42:11 +03:00
return ;
}
2016-01-11 18:29:28 +01:00
if ( player -> CanUseItem ( itemTransmogrified -> GetTemplate ()) != EQUIP_ERR_OK )
{
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify an unequippable item in a valid slot (slot: %u)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), transmogItem . Slot );
return ;
}
2014-07-27 13:42:11 +03:00
2015-08-18 17:45:30 +02:00
WorldPackets :: Item :: ItemInstance itemInstance ;
BonusData const * bonus = nullptr ;
if ( transmogItem . SrcItemGUID )
2012-08-01 02:46:32 +01:00
{
2015-08-18 17:45:30 +02:00
// guid of the transmogrifier item
Item * itemTransmogrifier = player -> GetItemByGuid ( * transmogItem . SrcItemGUID );
if ( ! itemTransmogrifier )
2012-08-01 02:46:32 +01:00
{
2015-08-18 17:45:30 +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 (), transmogItem . SrcItemGUID -> ToString (). c_str ());
2012-08-01 02:46:32 +01:00
return ;
}
2016-01-11 18:29:28 +01:00
if ( player -> CanUseItem ( itemTransmogrifier -> GetTemplate ()) != EQUIP_ERR_OK )
{
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an unequippable item (%s)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), transmogItem . SrcItemGUID -> ToString (). c_str ());
return ;
}
2012-08-01 02:46:32 +01:00
2015-08-18 17:45:30 +02:00
itemInstance . Initialize ( itemTransmogrifier );
bonus = itemTransmogrifier -> GetBonus ();
transmogItems [ itemTransmogrified ] = itemTransmogrifier ;
}
else if ( transmogItem . SrcVoidItemGUID )
{
2014-07-27 13:42:11 +03:00
// guid of the transmogrifier item
2015-08-18 17:45:30 +02:00
uint8 slot ;
VoidStorageItem * itemTransmogrifier = player -> GetVoidStorageItem ( transmogItem . SrcVoidItemGUID -> GetCounter (), slot );
2012-08-01 02:46:32 +01:00
if ( ! itemTransmogrifier )
{
2015-08-18 17:45:30 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid void storage item (%s)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), transmogItem . SrcVoidItemGUID -> ToString (). c_str ());
2012-08-01 02:46:32 +01:00
return ;
}
2016-01-11 18:29:28 +01:00
ItemTemplate const * transmogrifierTemplate = sObjectMgr -> GetItemTemplate ( itemTransmogrifier -> ItemEntry );
if ( player -> CanUseItem ( transmogrifierTemplate ) != EQUIP_ERR_OK )
{
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an unequippable void storage item (%s)." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), transmogItem . SrcVoidItemGUID -> ToString (). c_str ());
return ;
}
2012-08-01 02:46:32 +01:00
2015-08-18 17:45:30 +02:00
itemInstance . Initialize ( itemTransmogrifier );
std :: pair < VoidStorageItem * , BonusData >& transmogData = transmogVoidItems [ itemTransmogrified ];
transmogData . first = itemTransmogrifier ;
transmogData . second . Initialize ( itemInstance );
bonus = & transmogData . second ;
}
else
{
resetAppearanceItems . push_back ( itemTransmogrified );
continue ;
}
2014-06-07 19:23:38 -05:00
2015-08-18 17:45:30 +02:00
// entry of transmogrifier and from packet
if ( itemInstance != transmogItem . Item )
{
2015-08-19 17:16:33 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid item instance data for %s." , player -> GetGUID (). ToString (). c_str (), player -> GetName (). c_str (), transmogItem . SrcItemGUID -> ToString (). c_str ());
2015-08-18 17:45:30 +02:00
return ;
}
2012-08-01 02:46:32 +01:00
2015-08-18 17:45:30 +02:00
// validity of the transmogrification items
if ( ! Item :: CanTransmogrifyItemWithItem ( itemTransmogrified , transmogItem . Item , bonus ))
{
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 (), transmogItem . Item . ItemID );
return ;
2014-07-27 13:42:11 +03:00
}
2012-08-01 02:46:32 +01:00
2015-08-18 17:45:30 +02:00
// add cost
cost += itemTransmogrified -> GetSpecialPrice ();
2014-07-27 13:42:11 +03:00
}
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
2015-08-18 17:45:30 +02:00
for ( auto & transmogPair : transmogItems )
2014-07-27 13:42:11 +03:00
{
2015-08-18 17:45:30 +02:00
Item * transmogrified = transmogPair . first ;
Item * transmogrifier = transmogPair . second ;
2012-08-02 01:16:45 +01:00
2015-08-18 17:45:30 +02:00
transmogrified -> SetModifier ( ITEM_MODIFIER_TRANSMOG_ITEM_ID , transmogrifier -> GetEntry ());
transmogrified -> SetModifier ( ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD , transmogrifier -> GetAppearanceModId ());
player -> SetVisibleItemSlot ( transmogrified -> GetSlot (), transmogrified );
2014-07-27 13:42:11 +03:00
2015-08-18 17:45:30 +02:00
transmogrified -> SetNotRefundable ( player );
transmogrified -> ClearSoulboundTradeable ( player );
2014-07-27 13:42:11 +03:00
2015-08-18 17:45:30 +02:00
transmogrifier -> SetNotRefundable ( player );
transmogrifier -> ClearSoulboundTradeable ( player );
2014-07-27 13:42:11 +03:00
2015-08-18 17:45:30 +02:00
if ( transmogrifier -> GetTemplate () -> GetBonding () == BIND_WHEN_EQUIPED || transmogrifier -> GetTemplate () -> GetBonding () == BIND_WHEN_USE )
transmogrifier -> SetBinding ( true );
2016-04-08 16:47:56 +02:00
transmogrified -> SetState ( ITEM_CHANGED , player );
2015-08-18 17:45:30 +02:00
}
for ( auto & transmogVoirPair : transmogVoidItems )
{
Item * transmogrified = transmogVoirPair . first ;
VoidStorageItem * transmogrifier = transmogVoirPair . second . first ;
BonusData & bonus = transmogVoirPair . second . second ;
transmogrified -> SetModifier ( ITEM_MODIFIER_TRANSMOG_ITEM_ID , transmogrifier -> ItemEntry );
transmogrified -> SetModifier ( ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD , bonus . AppearanceModID );
player -> SetVisibleItemSlot ( transmogrified -> GetSlot (), transmogrified );
transmogrified -> SetNotRefundable ( player );
transmogrified -> ClearSoulboundTradeable ( player );
2016-04-08 16:47:56 +02:00
transmogrified -> SetState ( ITEM_CHANGED , player );
2015-08-18 17:45:30 +02:00
}
for ( Item * item : resetAppearanceItems )
{
item -> SetModifier ( ITEM_MODIFIER_TRANSMOG_ITEM_ID , 0 );
item -> SetModifier ( ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD , 0 );
2016-04-08 16:47:56 +02:00
item -> SetState ( ITEM_CHANGED , player );
2015-08-18 17:45:30 +02:00
player -> SetVisibleItemSlot ( item -> GetSlot (), item );
2012-08-01 02:46:32 +01:00
}
}
2012-08-03 20:47:09 -05: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
}
2015-09-09 14:52:32 +02:00
void WorldSession :: HandleUseCritterItem ( WorldPackets :: Item :: UseCritterItem & useCritterItem )
{
Item * item = _player -> GetItemByGuid ( useCritterItem . ItemGuid );
if ( ! item )
return ;
2016-04-25 22:03:34 +02:00
if ( item -> GetTemplate () -> Effects . size () < 2 )
2015-09-09 14:52:32 +02:00
return ;
2016-04-25 22:03:34 +02:00
uint32 spellToLearn = item -> GetTemplate () -> Effects [ 1 ] -> SpellID ;
for ( BattlePetSpeciesEntry const * entry : sBattlePetSpeciesStore )
{
if ( entry -> SummonSpellID == spellToLearn )
{
GetBattlePetMgr () -> AddPet ( entry -> ID , entry -> CreatureID , BattlePetMgr :: RollPetBreed ( entry -> ID ), BattlePetMgr :: GetDefaultPetQuality ( entry -> ID ));
_player -> UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT );
break ;
}
}
2015-09-09 14:52:32 +02:00
_player -> DestroyItem ( item -> GetBagSlot (), item -> GetSlot (), true );
}