2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "WorldPacket.h"
21 #include "WorldSession.h"
24 #include "ObjectMgr.h"
27 #include "UpdateData.h"
29 void WorldSession::HandleSplitItemOpcode( WorldPacket
& recv_data
)
31 //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM");
32 uint8 srcbag
, srcslot
, dstbag
, dstslot
;
35 recv_data
>> srcbag
>> srcslot
>> dstbag
>> dstslot
>> count
;
36 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count);
38 uint16 src
= ( (srcbag
<< 8) | srcslot
);
39 uint16 dst
= ( (dstbag
<< 8) | dstslot
);
45 return; //check count - if zero it's fake packet
47 if(!_player
->IsValidPos(srcbag
, srcslot
, true))
49 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
53 if(!_player
->IsValidPos(dstbag
, dstslot
, false)) // can be autostore pos
55 _player
->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT
, NULL
, NULL
);
59 _player
->SplitItem( src
, dst
, count
);
62 void WorldSession::HandleSwapInvItemOpcode( WorldPacket
& recv_data
)
64 //sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM");
65 uint8 srcslot
, dstslot
;
67 recv_data
>> dstslot
>> srcslot
;
68 //sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
70 // prevent attempt swap same item to current position generated by client at special cheating sequence
71 if(srcslot
== dstslot
)
74 if(!_player
->IsValidPos(INVENTORY_SLOT_BAG_0
, srcslot
, true))
76 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
80 if(!_player
->IsValidPos(INVENTORY_SLOT_BAG_0
, dstslot
, true))
82 _player
->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT
, NULL
, NULL
);
86 uint16 src
= ( (INVENTORY_SLOT_BAG_0
<< 8) | srcslot
);
87 uint16 dst
= ( (INVENTORY_SLOT_BAG_0
<< 8) | dstslot
);
89 _player
->SwapItem( src
, dst
);
92 void WorldSession::HandleAutoEquipItemSlotOpcode( WorldPacket
& recv_data
)
96 recv_data
>> itemguid
>> dstslot
;
98 // cheating attempt, client should never send opcode in that case
99 if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0
, dstslot
))
102 Item
* item
= _player
->GetItemByGuid(itemguid
);
103 uint16 dstpos
= dstslot
| (INVENTORY_SLOT_BAG_0
<< 8);
105 if(!item
|| item
->GetPos() == dstpos
)
108 _player
->SwapItem(item
->GetPos(), dstpos
);
111 void WorldSession::HandleSwapItem( WorldPacket
& recv_data
)
113 //sLog.outDebug("WORLD: CMSG_SWAP_ITEM");
114 uint8 dstbag
, dstslot
, srcbag
, srcslot
;
116 recv_data
>> dstbag
>> dstslot
>> srcbag
>> srcslot
;
117 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot);
119 uint16 src
= ( (srcbag
<< 8) | srcslot
);
120 uint16 dst
= ( (dstbag
<< 8) | dstslot
);
122 // prevent attempt swap same item to current position generated by client at special cheating sequence
126 if(!_player
->IsValidPos(srcbag
, srcslot
, true))
128 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
132 if(!_player
->IsValidPos(dstbag
, dstslot
, true))
134 _player
->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT
, NULL
, NULL
);
138 _player
->SwapItem( src
, dst
);
141 void WorldSession::HandleAutoEquipItemOpcode( WorldPacket
& recv_data
)
143 //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM");
144 uint8 srcbag
, srcslot
;
146 recv_data
>> srcbag
>> srcslot
;
147 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
149 Item
*pSrcItem
= _player
->GetItemByPos( srcbag
, srcslot
);
151 return; // only at cheat
153 if(pSrcItem
->m_lootGenerated
) // prevent swap looting item
155 //best error message found for attempting to swap while looting
156 _player
->SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW
, pSrcItem
, NULL
);
161 uint8 msg
= _player
->CanEquipItem( NULL_SLOT
, dest
, pSrcItem
, !pSrcItem
->IsBag() );
162 if( msg
!= EQUIP_ERR_OK
)
164 _player
->SendEquipError( msg
, pSrcItem
, NULL
);
168 uint16 src
= pSrcItem
->GetPos();
169 if(dest
== src
) // prevent equip in same slot, only at cheat
172 Item
*pDstItem
= _player
->GetItemByPos( dest
);
173 if( !pDstItem
) // empty slot, simple case
175 _player
->RemoveItem( srcbag
, srcslot
, true );
176 _player
->EquipItem( dest
, pSrcItem
, true );
177 _player
->AutoUnequipOffhandIfNeed();
179 else // have currently equipped item, not simple case
181 uint8 dstbag
= pDstItem
->GetBagSlot();
182 uint8 dstslot
= pDstItem
->GetSlot();
184 msg
= _player
->CanUnequipItem( dest
, !pSrcItem
->IsBag() );
185 if( msg
!= EQUIP_ERR_OK
)
187 _player
->SendEquipError( msg
, pDstItem
, NULL
);
191 // check dest->src move possibility
192 ItemPosCountVec sSrc
;
194 if( _player
->IsInventoryPos( src
) )
196 msg
= _player
->CanStoreItem( srcbag
, srcslot
, sSrc
, pDstItem
, true );
197 if( msg
!= EQUIP_ERR_OK
)
198 msg
= _player
->CanStoreItem( srcbag
, NULL_SLOT
, sSrc
, pDstItem
, true );
199 if( msg
!= EQUIP_ERR_OK
)
200 msg
= _player
->CanStoreItem( NULL_BAG
, NULL_SLOT
, sSrc
, pDstItem
, true );
202 else if( _player
->IsBankPos( src
) )
204 msg
= _player
->CanBankItem( srcbag
, srcslot
, sSrc
, pDstItem
, true );
205 if( msg
!= EQUIP_ERR_OK
)
206 msg
= _player
->CanBankItem( srcbag
, NULL_SLOT
, sSrc
, pDstItem
, true );
207 if( msg
!= EQUIP_ERR_OK
)
208 msg
= _player
->CanBankItem( NULL_BAG
, NULL_SLOT
, sSrc
, pDstItem
, true );
210 else if( _player
->IsEquipmentPos( src
) )
212 msg
= _player
->CanEquipItem( srcslot
, eSrc
, pDstItem
, true);
213 if( msg
== EQUIP_ERR_OK
)
214 msg
= _player
->CanUnequipItem( eSrc
, true);
217 if( msg
!= EQUIP_ERR_OK
)
219 _player
->SendEquipError( msg
, pDstItem
, pSrcItem
);
223 // now do moves, remove...
224 _player
->RemoveItem(dstbag
, dstslot
, false);
225 _player
->RemoveItem(srcbag
, srcslot
, false);
228 _player
->EquipItem(dest
, pSrcItem
, true);
231 if( _player
->IsInventoryPos( src
) )
232 _player
->StoreItem(sSrc
, pDstItem
, true);
233 else if( _player
->IsBankPos( src
) )
234 _player
->BankItem(sSrc
, pDstItem
, true);
235 else if( _player
->IsEquipmentPos( src
) )
236 _player
->EquipItem(eSrc
, pDstItem
, true);
238 _player
->AutoUnequipOffhandIfNeed();
242 void WorldSession::HandleDestroyItemOpcode( WorldPacket
& recv_data
)
244 //sLog.outDebug("WORLD: CMSG_DESTROYITEM");
245 uint8 bag
, slot
, count
, data1
, data2
, data3
;
247 recv_data
>> bag
>> slot
>> count
>> data1
>> data2
>> data3
;
248 //sLog.outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count);
250 uint16 pos
= (bag
<< 8) | slot
;
252 // prevent drop unequipable items (in combat, for example) and non-empty bags
253 if(_player
->IsEquipmentPos(pos
) || _player
->IsBagPos(pos
))
255 uint8 msg
= _player
->CanUnequipItem( pos
, false );
256 if( msg
!= EQUIP_ERR_OK
)
258 _player
->SendEquipError( msg
, _player
->GetItemByPos(pos
), NULL
);
263 Item
*pItem
= _player
->GetItemByPos( bag
, slot
);
266 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
272 uint32 i_count
= count
;
273 _player
->DestroyItemCount( pItem
, i_count
, true );
276 _player
->DestroyItem( bag
, slot
, true );
279 // Only _static_ data send in this packet !!!
280 void WorldSession::HandleItemQuerySingleOpcode( WorldPacket
& recv_data
)
282 //sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE");
286 sLog
.outDetail("STORAGE: Item Query = %u", item
);
288 ItemPrototype
const *pProto
= ObjectMgr::GetItemPrototype( item
);
291 std::string Name
= pProto
->Name1
;
292 std::string Description
= pProto
->Description
;
294 int loc_idx
= GetSessionDbLocaleIndex();
297 ItemLocale
const *il
= sObjectMgr
.GetItemLocale(pProto
->ItemId
);
300 if (il
->Name
.size() > size_t(loc_idx
) && !il
->Name
[loc_idx
].empty())
301 Name
= il
->Name
[loc_idx
];
302 if (il
->Description
.size() > size_t(loc_idx
) && !il
->Description
[loc_idx
].empty())
303 Description
= il
->Description
[loc_idx
];
307 WorldPacket
data( SMSG_ITEM_QUERY_SINGLE_RESPONSE
, 600);
308 data
<< pProto
->ItemId
;
309 data
<< pProto
->Class
;
310 data
<< pProto
->SubClass
;
311 data
<< int32(pProto
->Unk0
); // new 2.0.3, not exist in wdb cache?
313 data
<< uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
314 data
<< uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
315 data
<< uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
316 data
<< pProto
->DisplayInfoID
;
317 data
<< pProto
->Quality
;
318 data
<< pProto
->Flags
;
319 data
<< pProto
->Faction
; // 3.2 faction?
320 data
<< pProto
->BuyPrice
;
321 data
<< pProto
->SellPrice
;
322 data
<< pProto
->InventoryType
;
323 data
<< pProto
->AllowableClass
;
324 data
<< pProto
->AllowableRace
;
325 data
<< pProto
->ItemLevel
;
326 data
<< pProto
->RequiredLevel
;
327 data
<< pProto
->RequiredSkill
;
328 data
<< pProto
->RequiredSkillRank
;
329 data
<< pProto
->RequiredSpell
;
330 data
<< pProto
->RequiredHonorRank
;
331 data
<< pProto
->RequiredCityRank
;
332 data
<< pProto
->RequiredReputationFaction
;
333 data
<< pProto
->RequiredReputationRank
;
334 data
<< int32(pProto
->MaxCount
);
335 data
<< int32(pProto
->Stackable
);
336 data
<< pProto
->ContainerSlots
;
337 data
<< pProto
->StatsCount
; // item stats count
338 for(uint32 i
= 0; i
< pProto
->StatsCount
; ++i
)
340 data
<< pProto
->ItemStat
[i
].ItemStatType
;
341 data
<< pProto
->ItemStat
[i
].ItemStatValue
;
343 data
<< pProto
->ScalingStatDistribution
; // scaling stats distribution
344 data
<< pProto
->ScalingStatValue
; // some kind of flags used to determine stat values column
345 for(int i
= 0; i
< MAX_ITEM_PROTO_DAMAGES
; ++i
)
347 data
<< pProto
->Damage
[i
].DamageMin
;
348 data
<< pProto
->Damage
[i
].DamageMax
;
349 data
<< pProto
->Damage
[i
].DamageType
;
353 data
<< pProto
->Armor
;
354 data
<< pProto
->HolyRes
;
355 data
<< pProto
->FireRes
;
356 data
<< pProto
->NatureRes
;
357 data
<< pProto
->FrostRes
;
358 data
<< pProto
->ShadowRes
;
359 data
<< pProto
->ArcaneRes
;
361 data
<< pProto
->Delay
;
362 data
<< pProto
->AmmoType
;
363 data
<< pProto
->RangedModRange
;
365 for(int s
= 0; s
< MAX_ITEM_PROTO_SPELLS
; ++s
)
367 // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
368 // use `item_template` or if not set then only use spell cooldowns
369 SpellEntry
const* spell
= sSpellStore
.LookupEntry(pProto
->Spells
[s
].SpellId
);
372 bool db_data
= pProto
->Spells
[s
].SpellCooldown
>= 0 || pProto
->Spells
[s
].SpellCategoryCooldown
>= 0;
374 data
<< pProto
->Spells
[s
].SpellId
;
375 data
<< pProto
->Spells
[s
].SpellTrigger
;
376 data
<< uint32(-abs(pProto
->Spells
[s
].SpellCharges
));
380 data
<< uint32(pProto
->Spells
[s
].SpellCooldown
);
381 data
<< uint32(pProto
->Spells
[s
].SpellCategory
);
382 data
<< uint32(pProto
->Spells
[s
].SpellCategoryCooldown
);
386 data
<< uint32(spell
->RecoveryTime
);
387 data
<< uint32(spell
->Category
);
388 data
<< uint32(spell
->CategoryRecoveryTime
);
401 data
<< pProto
->Bonding
;
403 data
<< pProto
->PageText
;
404 data
<< pProto
->LanguageID
;
405 data
<< pProto
->PageMaterial
;
406 data
<< pProto
->StartQuest
;
407 data
<< pProto
->LockID
;
408 data
<< int32(pProto
->Material
);
409 data
<< pProto
->Sheath
;
410 data
<< pProto
->RandomProperty
;
411 data
<< pProto
->RandomSuffix
;
412 data
<< pProto
->Block
;
413 data
<< pProto
->ItemSet
;
414 data
<< pProto
->MaxDurability
;
415 data
<< pProto
->Area
;
416 data
<< pProto
->Map
; // Added in 1.12.x & 2.0.1 client branch
417 data
<< pProto
->BagFamily
;
418 data
<< pProto
->TotemCategory
;
419 for(int s
= 0; s
< MAX_ITEM_PROTO_SOCKETS
; ++s
)
421 data
<< pProto
->Socket
[s
].Color
;
422 data
<< pProto
->Socket
[s
].Content
;
424 data
<< pProto
->socketBonus
;
425 data
<< pProto
->GemProperties
;
426 data
<< pProto
->RequiredDisenchantSkill
;
427 data
<< pProto
->ArmorDamageModifier
;
428 data
<< abs(pProto
->Duration
); // added in 2.4.2.8209, duration (seconds)
429 data
<< pProto
->ItemLimitCategory
; // WotLK, ItemLimitCategory
430 data
<< pProto
->HolidayId
; // Holiday.dbc?
435 sLog
.outDebug( "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item
);
436 WorldPacket
data( SMSG_ITEM_QUERY_SINGLE_RESPONSE
, 4);
437 data
<< uint32(item
| 0x80000000);
442 void WorldSession::HandleReadItem( WorldPacket
& recv_data
)
444 //sLog.outDebug( "WORLD: CMSG_READ_ITEM");
447 recv_data
>> bag
>> slot
;
449 //sLog.outDetail("STORAGE: Read bag = %u, slot = %u", bag, slot);
450 Item
*pItem
= _player
->GetItemByPos( bag
, slot
);
452 if( pItem
&& pItem
->GetProto()->PageText
)
456 uint8 msg
= _player
->CanUseItem( pItem
);
457 if( msg
== EQUIP_ERR_OK
)
459 data
.Initialize (SMSG_READ_ITEM_OK
, 8);
460 sLog
.outDetail("STORAGE: Item page sent");
464 data
.Initialize( SMSG_READ_ITEM_FAILED
, 8 );
465 sLog
.outDetail("STORAGE: Unable to read item");
466 _player
->SendEquipError( msg
, pItem
, NULL
);
468 data
<< pItem
->GetGUID();
472 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, NULL
, NULL
);
475 void WorldSession::HandlePageQuerySkippedOpcode( WorldPacket
& recv_data
)
477 sLog
.outDebug( "WORLD: Received CMSG_PAGE_TEXT_QUERY" );
482 recv_data
>> itemid
>> guid
;
484 sLog
.outDetail( "Packet Info: itemid: %u guidlow: %u guidentry: %u guidhigh: %u",
485 itemid
, GUID_LOPART(guid
), GUID_ENPART(guid
), GUID_HIPART(guid
));
488 void WorldSession::HandleSellItemOpcode( WorldPacket
& recv_data
)
490 sLog
.outDebug( "WORLD: Received CMSG_SELL_ITEM" );
491 uint64 vendorguid
, itemguid
;
494 recv_data
>> vendorguid
>> itemguid
>> count
;
499 Creature
*pCreature
= GetPlayer()->GetNPCIfCanInteractWith(vendorguid
, UNIT_NPC_FLAG_VENDOR
);
502 sLog
.outDebug( "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid
)) );
503 _player
->SendSellError( SELL_ERR_CANT_FIND_VENDOR
, NULL
, itemguid
, 0);
508 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
509 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
511 Item
*pItem
= _player
->GetItemByGuid( itemguid
);
514 // prevent sell not owner item
515 if(_player
->GetGUID() != pItem
->GetOwnerGUID())
517 _player
->SendSellError( SELL_ERR_CANT_SELL_ITEM
, pCreature
, itemguid
, 0);
521 // prevent sell non empty bag by drag-and-drop at vendor's item list
522 if(pItem
->IsBag() && !((Bag
*)pItem
)->IsEmpty())
524 _player
->SendSellError( SELL_ERR_CANT_SELL_ITEM
, pCreature
, itemguid
, 0);
528 // prevent sell currently looted item
529 if(_player
->GetLootGUID() == pItem
->GetGUID())
531 _player
->SendSellError( SELL_ERR_CANT_SELL_ITEM
, pCreature
, itemguid
, 0);
535 // special case at auto sell (sell all)
538 count
= pItem
->GetCount();
542 // prevent sell more items that exist in stack (possible only not from client)
543 if(count
> pItem
->GetCount())
545 _player
->SendSellError( SELL_ERR_CANT_SELL_ITEM
, pCreature
, itemguid
, 0);
550 ItemPrototype
const *pProto
= pItem
->GetProto();
553 if( pProto
->SellPrice
> 0 )
555 if(count
< pItem
->GetCount()) // need split items
557 Item
*pNewItem
= pItem
->CloneItem( count
, _player
);
560 sLog
.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem
->GetEntry(), count
);
561 _player
->SendSellError( SELL_ERR_CANT_SELL_ITEM
, pCreature
, itemguid
, 0);
565 pItem
->SetCount( pItem
->GetCount() - count
);
566 _player
->ItemRemovedQuestCheck( pItem
->GetEntry(), count
);
567 if( _player
->IsInWorld() )
568 pItem
->SendCreateUpdateToPlayer( _player
);
569 pItem
->SetState(ITEM_CHANGED
, _player
);
571 _player
->AddItemToBuyBackSlot( pNewItem
);
572 if( _player
->IsInWorld() )
573 pNewItem
->SendCreateUpdateToPlayer( _player
);
577 _player
->ItemRemovedQuestCheck( pItem
->GetEntry(), pItem
->GetCount());
578 _player
->RemoveItem( pItem
->GetBagSlot(), pItem
->GetSlot(), true);
579 pItem
->RemoveFromUpdateQueueOf(_player
);
580 _player
->AddItemToBuyBackSlot( pItem
);
583 _player
->ModifyMoney( pProto
->SellPrice
* count
);
586 _player
->SendSellError( SELL_ERR_CANT_SELL_ITEM
, pCreature
, itemguid
, 0);
590 _player
->SendSellError( SELL_ERR_CANT_FIND_ITEM
, pCreature
, itemguid
, 0);
594 void WorldSession::HandleBuybackItem(WorldPacket
& recv_data
)
596 sLog
.outDebug( "WORLD: Received CMSG_BUYBACK_ITEM" );
600 recv_data
>> vendorguid
>> slot
;
602 Creature
*pCreature
= GetPlayer()->GetNPCIfCanInteractWith(vendorguid
, UNIT_NPC_FLAG_VENDOR
);
605 sLog
.outDebug( "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid
)) );
606 _player
->SendSellError( SELL_ERR_CANT_FIND_VENDOR
, NULL
, 0, 0);
611 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
612 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
614 Item
*pItem
= _player
->GetItemFromBuyBackSlot( slot
);
617 uint32 price
= _player
->GetUInt32Value( PLAYER_FIELD_BUYBACK_PRICE_1
+ slot
- BUYBACK_SLOT_START
);
618 if( _player
->GetMoney() < price
)
620 _player
->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY
, pCreature
, pItem
->GetEntry(), 0);
624 ItemPosCountVec dest
;
625 uint8 msg
= _player
->CanStoreItem( NULL_BAG
, NULL_SLOT
, dest
, pItem
, false );
626 if( msg
== EQUIP_ERR_OK
)
628 _player
->ModifyMoney( -(int32
)price
);
629 _player
->RemoveItemFromBuyBackSlot( slot
, false );
630 _player
->ItemAddedQuestCheck( pItem
->GetEntry(), pItem
->GetCount());
631 _player
->StoreItem( dest
, pItem
, true );
634 _player
->SendEquipError( msg
, pItem
, NULL
);
638 _player
->SendBuyError( BUY_ERR_CANT_FIND_ITEM
, pCreature
, 0, 0);
641 void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket
& recv_data
)
643 sLog
.outDebug( "WORLD: Received CMSG_BUY_ITEM_IN_SLOT" );
644 uint64 vendorguid
, bagguid
;
645 uint32 item
, slot
, count
;
648 recv_data
>> vendorguid
>> item
>> slot
>> bagguid
>> bagslot
>> count
;
650 uint8 bag
= NULL_BAG
; // init for case invalid bagGUID
652 // find bag slot by bag guid
653 if (bagguid
== _player
->GetGUID())
654 bag
= INVENTORY_SLOT_BAG_0
;
657 for (int i
= INVENTORY_SLOT_BAG_START
; i
< INVENTORY_SLOT_BAG_END
;++i
)
659 if (Bag
*pBag
= (Bag
*)_player
->GetItemByPos(INVENTORY_SLOT_BAG_0
,i
))
661 if (bagguid
== pBag
->GetGUID())
670 // bag not found, cheating?
674 GetPlayer()->BuyItemFromVendor(vendorguid
, item
, count
, bag
, bagslot
);
677 void WorldSession::HandleBuyItemOpcode( WorldPacket
& recv_data
)
679 sLog
.outDebug( "WORLD: Received CMSG_BUY_ITEM" );
681 uint32 item
, slot
, count
;
684 recv_data
>> vendorguid
>> item
>> slot
>> count
>> unk1
;
686 GetPlayer()->BuyItemFromVendor(vendorguid
, item
, count
, NULL_BAG
, NULL_SLOT
);
689 void WorldSession::HandleListInventoryOpcode( WorldPacket
& recv_data
)
695 if(!GetPlayer()->isAlive())
698 sLog
.outDebug( "WORLD: Recvd CMSG_LIST_INVENTORY" );
700 SendListInventory( guid
);
703 void WorldSession::SendListInventory(uint64 vendorguid
)
705 sLog
.outDebug("WORLD: Sent SMSG_LIST_INVENTORY");
707 Creature
*pCreature
= GetPlayer()->GetNPCIfCanInteractWith(vendorguid
, UNIT_NPC_FLAG_VENDOR
);
711 sLog
.outDebug("WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid
)));
712 _player
->SendSellError(SELL_ERR_CANT_FIND_VENDOR
, NULL
, 0, 0);
717 if (GetPlayer()->hasUnitState(UNIT_STAT_DIED
))
718 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH
);
720 // Stop the npc if moving
721 if (!pCreature
->IsStopped())
722 pCreature
->StopMoving();
724 VendorItemData
const* vItems
= pCreature
->GetVendorItems();
728 _player
->SendSellError(SELL_ERR_CANT_FIND_VENDOR
, NULL
, 0, 0);
732 uint8 numitems
= vItems
->GetItemCount();
735 WorldPacket
data( SMSG_LIST_INVENTORY
, (8+1+numitems
*8*4) );
736 data
<< uint64(vendorguid
);
737 data
<< uint8(numitems
);
739 float discountMod
= _player
->GetReputationPriceDiscount(pCreature
);
741 for(int i
= 0; i
< numitems
; ++i
)
743 if(VendorItem
const* crItem
= vItems
->GetItem(i
))
745 if(ItemPrototype
const *pProto
= ObjectMgr::GetItemPrototype(crItem
->item
))
747 if((pProto
->AllowableClass
& _player
->getClassMask()) == 0 && pProto
->Bonding
== BIND_WHEN_PICKED_UP
&& !_player
->isGameMaster())
752 // reputation discount
753 uint32 price
= uint32(floor(pProto
->BuyPrice
* discountMod
));
755 data
<< uint32(count
);
756 data
<< uint32(crItem
->item
);
757 data
<< uint32(pProto
->DisplayInfoID
);
758 data
<< uint32(crItem
->maxcount
<= 0 ? 0xFFFFFFFF : pCreature
->GetVendorItemCurrentCount(crItem
));
759 data
<< uint32(price
);
760 data
<< uint32(pProto
->MaxDurability
);
761 data
<< uint32(pProto
->BuyCount
);
762 data
<< uint32(crItem
->ExtendedCost
);
767 if ( count
== 0 || data
.size() != 8 + 1 + size_t(count
) * 8 * 4 )
770 data
.put
<uint8
>(8, count
);
774 void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket
& recv_data
)
776 //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM");
777 uint8 srcbag
, srcslot
, dstbag
;
779 recv_data
>> srcbag
>> srcslot
>> dstbag
;
780 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag);
782 Item
*pItem
= _player
->GetItemByPos( srcbag
, srcslot
);
786 if(!_player
->IsValidPos(dstbag
, NULL_SLOT
, false)) // can be autostore pos
788 _player
->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT
, NULL
, NULL
);
792 uint16 src
= pItem
->GetPos();
794 // check unequip potability for equipped items and bank bags
795 if(_player
->IsEquipmentPos ( src
) || _player
->IsBagPos ( src
))
797 uint8 msg
= _player
->CanUnequipItem( src
, !_player
->IsBagPos ( src
));
798 if(msg
!= EQUIP_ERR_OK
)
800 _player
->SendEquipError( msg
, pItem
, NULL
);
805 ItemPosCountVec dest
;
806 uint8 msg
= _player
->CanStoreItem( dstbag
, NULL_SLOT
, dest
, pItem
, false );
807 if( msg
!= EQUIP_ERR_OK
)
809 _player
->SendEquipError( msg
, pItem
, NULL
);
813 // no-op: placed in same slot
814 if(dest
.size() == 1 && dest
[0].pos
== src
)
816 // just remove gray item state
817 _player
->SendEquipError( EQUIP_ERR_NONE
, pItem
, NULL
);
821 _player
->RemoveItem(srcbag
, srcslot
, true );
822 _player
->StoreItem( dest
, pItem
, true );
825 void WorldSession::HandleBuyBankSlotOpcode(WorldPacket
& recvPacket
)
827 sLog
.outDebug("WORLD: CMSG_BUY_BANK_SLOT");
832 // cheating protection
833 /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command.
834 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER);
837 sLog.outDebug( "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
842 uint32 slot
= _player
->GetBankBagSlotCount();
847 sLog
.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot
);
849 BankBagSlotPricesEntry
const* slotEntry
= sBankBagSlotPricesStore
.LookupEntry(slot
);
854 uint32 price
= slotEntry
->price
;
856 if (_player
->GetMoney() < price
)
859 _player
->SetBankBagSlotCount(slot
);
860 _player
->ModifyMoney(-int32(price
));
862 _player
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT
);
865 void WorldSession::HandleAutoBankItemOpcode(WorldPacket
& recvPacket
)
867 sLog
.outDebug("WORLD: CMSG_AUTOBANK_ITEM");
868 uint8 srcbag
, srcslot
;
870 recvPacket
>> srcbag
>> srcslot
;
871 sLog
.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag
, srcslot
);
873 Item
*pItem
= _player
->GetItemByPos( srcbag
, srcslot
);
877 ItemPosCountVec dest
;
878 uint8 msg
= _player
->CanBankItem( NULL_BAG
, NULL_SLOT
, dest
, pItem
, false );
879 if( msg
!= EQUIP_ERR_OK
)
881 _player
->SendEquipError( msg
, pItem
, NULL
);
885 _player
->RemoveItem(srcbag
, srcslot
, true);
886 _player
->BankItem( dest
, pItem
, true );
889 void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket
& recvPacket
)
891 sLog
.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM");
892 uint8 srcbag
, srcslot
;
894 recvPacket
>> srcbag
>> srcslot
;
895 sLog
.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag
, srcslot
);
897 Item
*pItem
= _player
->GetItemByPos( srcbag
, srcslot
);
901 if(_player
->IsBankPos(srcbag
, srcslot
)) // moving from bank to inventory
903 ItemPosCountVec dest
;
904 uint8 msg
= _player
->CanStoreItem( NULL_BAG
, NULL_SLOT
, dest
, pItem
, false );
905 if( msg
!= EQUIP_ERR_OK
)
907 _player
->SendEquipError( msg
, pItem
, NULL
);
911 _player
->RemoveItem(srcbag
, srcslot
, true);
912 _player
->StoreItem( dest
, pItem
, true );
914 else // moving from inventory to bank
916 ItemPosCountVec dest
;
917 uint8 msg
= _player
->CanBankItem( NULL_BAG
, NULL_SLOT
, dest
, pItem
, false );
918 if( msg
!= EQUIP_ERR_OK
)
920 _player
->SendEquipError( msg
, pItem
, NULL
);
924 _player
->RemoveItem(srcbag
, srcslot
, true);
925 _player
->BankItem( dest
, pItem
, true );
929 void WorldSession::HandleSetAmmoOpcode(WorldPacket
& recv_data
)
931 if(!GetPlayer()->isAlive())
933 GetPlayer()->SendEquipError( EQUIP_ERR_YOU_ARE_DEAD
, NULL
, NULL
);
937 sLog
.outDebug("WORLD: CMSG_SET_AMMO");
943 GetPlayer()->RemoveAmmo();
945 GetPlayer()->SetAmmo(item
);
948 void WorldSession::SendEnchantmentLog(uint64 Target
, uint64 Caster
,uint32 ItemID
,uint32 SpellID
)
950 WorldPacket
data(SMSG_ENCHANTMENTLOG
, (8+8+4+4+1)); // last check 2.0.10
951 data
<< uint64(Target
);
952 data
<< uint64(Caster
);
953 data
<< uint32(ItemID
);
954 data
<< uint32(SpellID
);
959 void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid
, uint64 Itemguid
,uint32 slot
,uint32 Duration
)
962 WorldPacket
data(SMSG_ITEM_ENCHANT_TIME_UPDATE
, (8+4+4+8));
963 data
<< uint64(Itemguid
);
964 data
<< uint32(slot
);
965 data
<< uint32(Duration
);
966 data
<< uint64(Playerguid
);
970 void WorldSession::HandleItemNameQueryOpcode(WorldPacket
& recv_data
)
974 recv_data
.read_skip
<uint64
>(); // guid
976 sLog
.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid
);
977 ItemPrototype
const *pProto
= ObjectMgr::GetItemPrototype( itemid
);
981 Name
= pProto
->Name1
;
983 int loc_idx
= GetSessionDbLocaleIndex();
986 ItemLocale
const *il
= sObjectMgr
.GetItemLocale(pProto
->ItemId
);
989 if (il
->Name
.size() > size_t(loc_idx
) && !il
->Name
[loc_idx
].empty())
990 Name
= il
->Name
[loc_idx
];
994 WorldPacket
data(SMSG_ITEM_NAME_QUERY_RESPONSE
, (4+10));
995 data
<< uint32(pProto
->ItemId
);
997 data
<< uint32(pProto
->InventoryType
);
1003 // listed in dbc or not expected to exist unknown item
1004 if(sItemStore
.LookupEntry(itemid
))
1005 sLog
.outErrorDb("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (item listed in Item.dbc but not exist in DB)", itemid
);
1007 sLog
.outError("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item, not listed in Item.dbc)", itemid
);
1011 void WorldSession::HandleWrapItemOpcode(WorldPacket
& recv_data
)
1013 sLog
.outDebug("Received opcode CMSG_WRAP_ITEM");
1015 uint8 gift_bag
, gift_slot
, item_bag
, item_slot
;
1016 //recv_data.hexlike();
1018 recv_data
>> gift_bag
>> gift_slot
; // paper
1019 recv_data
>> item_bag
>> item_slot
; // item
1021 sLog
.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag
, gift_slot
, item_bag
, item_slot
);
1023 Item
*gift
= _player
->GetItemByPos( gift_bag
, gift_slot
);
1026 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, gift
, NULL
);
1030 if(!gift
->HasFlag(ITEM_FIELD_FLAGS
, ITEM_FLAGS_WRAPPER
))// cheating: non-wrapper wrapper
1032 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, gift
, NULL
);
1036 Item
*item
= _player
->GetItemByPos( item_bag
, item_slot
);
1040 _player
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, item
, NULL
);
1044 if(item
== gift
) // not possible with packet from real client
1046 _player
->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED
, item
, NULL
);
1050 if(item
->IsEquipped())
1052 _player
->SendEquipError( EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED
, item
, NULL
);
1056 if(item
->GetUInt64Value(ITEM_FIELD_GIFTCREATOR
)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1058 _player
->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED
, item
, NULL
);
1064 _player
->SendEquipError( EQUIP_ERR_BAGS_CANT_BE_WRAPPED
, item
, NULL
);
1068 if(item
->IsSoulBound())
1070 _player
->SendEquipError( EQUIP_ERR_BOUND_CANT_BE_WRAPPED
, item
, NULL
);
1074 if(item
->GetMaxStackCount() != 1)
1076 _player
->SendEquipError( EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED
, item
, NULL
);
1080 // maybe not correct check (it is better than nothing)
1081 if(item
->GetProto()->MaxCount
> 0)
1083 _player
->SendEquipError( EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED
, item
, NULL
);
1087 CharacterDatabase
.BeginTransaction();
1088 CharacterDatabase
.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item
->GetOwnerGUID()), item
->GetGUIDLow(), item
->GetEntry(), item
->GetUInt32Value(ITEM_FIELD_FLAGS
));
1089 item
->SetEntry(gift
->GetEntry());
1091 switch (item
->GetEntry())
1093 case 5042: item
->SetEntry( 5043); break;
1094 case 5048: item
->SetEntry( 5044); break;
1095 case 17303: item
->SetEntry(17302); break;
1096 case 17304: item
->SetEntry(17305); break;
1097 case 17307: item
->SetEntry(17308); break;
1098 case 21830: item
->SetEntry(21831); break;
1100 item
->SetUInt64Value(ITEM_FIELD_GIFTCREATOR
, _player
->GetGUID());
1101 item
->SetUInt32Value(ITEM_FIELD_FLAGS
, ITEM_FLAGS_WRAPPED
);
1102 item
->SetState(ITEM_CHANGED
, _player
);
1104 if(item
->GetState() == ITEM_NEW
) // save new item, to have alway for `character_gifts` record in `item_instance`
1106 // after save it will be impossible to remove the item from the queue
1107 item
->RemoveFromUpdateQueueOf(_player
);
1108 item
->SaveToDB(); // item gave inventory record unchanged and can be save standalone
1110 CharacterDatabase
.CommitTransaction();
1113 _player
->DestroyItemCount(gift
, count
, true);
1116 void WorldSession::HandleSocketOpcode(WorldPacket
& recv_data
)
1118 sLog
.outDebug("WORLD: CMSG_SOCKET_GEMS");
1121 uint64 gem_guids
[MAX_GEM_SOCKETS
];
1123 recv_data
>> item_guid
;
1127 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
)
1128 recv_data
>> gem_guids
[i
];
1130 //cheat -> tried to socket same gem multiple times
1131 if ((gem_guids
[0] && (gem_guids
[0] == gem_guids
[1] || gem_guids
[0] == gem_guids
[2])) ||
1132 (gem_guids
[1] && (gem_guids
[1] == gem_guids
[2])))
1135 Item
*itemTarget
= _player
->GetItemByGuid(item_guid
);
1136 if(!itemTarget
) //missing item to socket
1139 ItemPrototype
const* itemProto
= itemTarget
->GetProto();
1143 //this slot is excepted when applying / removing meta gem bonus
1144 uint8 slot
= itemTarget
->IsEquipped() ? itemTarget
->GetSlot() : uint8(NULL_SLOT
);
1146 Item
*Gems
[MAX_GEM_SOCKETS
];
1147 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
)
1148 Gems
[i
] = gem_guids
[i
] ? _player
->GetItemByGuid(gem_guids
[i
]) : NULL
;
1150 GemPropertiesEntry
const *GemProps
[MAX_GEM_SOCKETS
];
1151 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
) //get geminfo from dbc storage
1152 GemProps
[i
] = (Gems
[i
]) ? sGemPropertiesStore
.LookupEntry(Gems
[i
]->GetProto()->GemProperties
) : NULL
;
1154 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
) //check for hack maybe
1159 // tried to put gem in socket where no socket exists (take care about prismatic sockets)
1160 if (!itemProto
->Socket
[i
].Color
)
1162 // no prismatic socket
1163 if(!itemTarget
->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT
))
1166 // not first not-colored (not normally used) socket
1167 if(i
!= 0 && !itemProto
->Socket
[i
- 1].Color
&& (i
+ 1 >= MAX_GEM_SOCKETS
|| itemProto
->Socket
[i
+ 1].Color
))
1170 // ok, this is first not colored socket for item with prismatic socket
1173 // tried to put normal gem in meta socket
1174 if (itemProto
->Socket
[i
].Color
== SOCKET_COLOR_META
&& GemProps
[i
]->color
!= SOCKET_COLOR_META
)
1177 // tried to put meta gem in normal socket
1178 if (itemProto
->Socket
[i
].Color
!= SOCKET_COLOR_META
&& GemProps
[i
]->color
== SOCKET_COLOR_META
)
1182 uint32 GemEnchants
[MAX_GEM_SOCKETS
];
1183 uint32 OldEnchants
[MAX_GEM_SOCKETS
];
1184 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
) //get new and old enchantments
1186 GemEnchants
[i
] = (GemProps
[i
]) ? GemProps
[i
]->spellitemenchantement
: 0;
1187 OldEnchants
[i
] = itemTarget
->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT
+ i
));
1190 // check unique-equipped conditions
1191 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
)
1196 // continue check for case when attempt add 2 similar unique equipped gems in one item.
1197 ItemPrototype
const* iGemProto
= Gems
[i
]->GetProto();
1199 // unique item (for new and already placed bit removed enchantments
1200 if (iGemProto
->Flags
& ITEM_FLAGS_UNIQUE_EQUIPPED
)
1202 for (int j
= 0; j
< MAX_GEM_SOCKETS
; ++j
)
1204 if(i
== j
) // skip self
1209 if (iGemProto
->ItemId
== Gems
[j
]->GetEntry())
1211 _player
->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED
, itemTarget
, NULL
);
1215 else if(OldEnchants
[j
])
1217 if(SpellItemEnchantmentEntry
const* enchantEntry
= sSpellItemEnchantmentStore
.LookupEntry(OldEnchants
[j
]))
1219 if (iGemProto
->ItemId
== enchantEntry
->GemID
)
1221 _player
->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED
, itemTarget
, NULL
);
1230 // unique limit type item
1231 int32 limit_newcount
= 0;
1232 if (iGemProto
->ItemLimitCategory
)
1234 if(ItemLimitCategoryEntry
const* limitEntry
= sItemLimitCategoryStore
.LookupEntry(iGemProto
->ItemLimitCategory
))
1236 for (int j
= 0; j
< MAX_GEM_SOCKETS
; ++j
)
1243 if(SpellItemEnchantmentEntry
const* enchantEntry
= sSpellItemEnchantmentStore
.LookupEntry(OldEnchants
[j
]))
1244 if(ItemPrototype
const* jProto
= ObjectMgr::GetItemPrototype(enchantEntry
->GemID
))
1245 if (iGemProto
->ItemLimitCategory
== jProto
->ItemLimitCategory
)
1250 if (iGemProto
->ItemLimitCategory
== Gems
[j
]->GetProto()->ItemLimitCategory
)
1254 else if(OldEnchants
[j
])
1256 if(SpellItemEnchantmentEntry
const* enchantEntry
= sSpellItemEnchantmentStore
.LookupEntry(OldEnchants
[j
]))
1257 if(ItemPrototype
const* jProto
= ObjectMgr::GetItemPrototype(enchantEntry
->GemID
))
1258 if (iGemProto
->ItemLimitCategory
== jProto
->ItemLimitCategory
)
1263 if(limit_newcount
> 0 && uint32(limit_newcount
) > limitEntry
->maxCount
)
1265 _player
->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED
, itemTarget
, NULL
);
1271 // for equipped item check all equipment for duplicate equipped gems
1272 if(itemTarget
->IsEquipped())
1274 if(uint8 res
= _player
->CanEquipUniqueItem(Gems
[i
], slot
, limit_newcount
>= 0 ? limit_newcount
: 0))
1276 _player
->SendEquipError( res
, itemTarget
, NULL
);
1282 bool SocketBonusActivated
= itemTarget
->GemsFitSockets(); //save state of socketbonus
1283 _player
->ToggleMetaGemsActive(slot
, false); //turn off all metagems (except for the target item)
1285 //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
1287 //remove ALL enchants
1288 for(uint32 enchant_slot
= SOCK_ENCHANTMENT_SLOT
; enchant_slot
< SOCK_ENCHANTMENT_SLOT
+ MAX_GEM_SOCKETS
; ++enchant_slot
)
1289 _player
->ApplyEnchantment(itemTarget
, EnchantmentSlot(enchant_slot
), false);
1291 for(int i
= 0; i
< MAX_GEM_SOCKETS
; ++i
)
1295 itemTarget
->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT
+ i
), GemEnchants
[i
], 0, 0);
1296 if(Item
* guidItem
= _player
->GetItemByGuid(gem_guids
[i
]))
1297 _player
->DestroyItem(guidItem
->GetBagSlot(), guidItem
->GetSlot(), true );
1301 for(uint32 enchant_slot
= SOCK_ENCHANTMENT_SLOT
; enchant_slot
< SOCK_ENCHANTMENT_SLOT
+ MAX_GEM_SOCKETS
; ++enchant_slot
)
1302 _player
->ApplyEnchantment(itemTarget
, EnchantmentSlot(enchant_slot
), true);
1304 bool SocketBonusToBeActivated
= itemTarget
->GemsFitSockets();// current socketbonus state
1305 if(SocketBonusActivated
!= SocketBonusToBeActivated
) // if there was a change...
1307 _player
->ApplyEnchantment(itemTarget
,BONUS_ENCHANTMENT_SLOT
, false);
1308 itemTarget
->SetEnchantment(BONUS_ENCHANTMENT_SLOT
, (SocketBonusToBeActivated
? itemTarget
->GetProto()->socketBonus
: 0), 0, 0);
1309 _player
->ApplyEnchantment(itemTarget
, BONUS_ENCHANTMENT_SLOT
, true);
1310 //it is not displayed, client has an inbuilt system to determine if the bonus is activated
1313 _player
->ToggleMetaGemsActive(slot
, true); // turn on all metagems (except for target item)
1316 void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket
& recv_data
)
1318 sLog
.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
1324 // apply only to equipped item
1325 if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0
, eslot
))
1328 Item
* item
= GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0
, eslot
);
1333 if(!item
->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT
))
1336 GetPlayer()->ApplyEnchantment(item
, TEMP_ENCHANTMENT_SLOT
, false);
1337 item
->ClearEnchantment(TEMP_ENCHANTMENT_SLOT
);
1340 void WorldSession::HandleItemRefundInfoRequest(WorldPacket
& recv_data
)
1342 sLog
.outDebug("WORLD: CMSG_ITEM_REFUND_INFO_REQUEST");
1345 recv_data
>> guid
; // item guid
1347 Item
*item
= _player
->GetItemByGuid(guid
);
1351 sLog
.outDebug("Item refund: item not found!");
1355 if(!item
->HasFlag(ITEM_FIELD_FLAGS
, ITEM_FLAGS_REFUNDABLE
))
1357 sLog
.outDebug("Item refund: item not refundable!");
1361 // item refund system not implemented yet