[8449] Deprecate healing/damage item mods and merge internal data in to spell power.
[getmangos.git] / src / game / ItemHandler.cpp
blobeccab500def22042c671bafac44bf595160b7c4c
1 /*
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
19 #include "Common.h"
20 #include "WorldPacket.h"
21 #include "WorldSession.h"
22 #include "Opcodes.h"
23 #include "Log.h"
24 #include "ObjectMgr.h"
25 #include "Player.h"
26 #include "Item.h"
27 #include "UpdateData.h"
28 #include "ObjectAccessor.h"
30 void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data )
32 //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM");
33 uint8 srcbag, srcslot, dstbag, dstslot;
34 uint32 count;
36 recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count;
37 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count);
39 uint16 src = ( (srcbag << 8) | srcslot );
40 uint16 dst = ( (dstbag << 8) | dstslot );
42 if(src==dst)
43 return;
45 if (count==0)
46 return; //check count - if zero it's fake packet
48 if(!_player->IsValidPos(srcbag,srcslot))
50 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
51 return;
54 if(!_player->IsValidPos(dstbag,dstslot))
56 _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
57 return;
60 _player->SplitItem( src, dst, count );
63 void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data )
65 //sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM");
66 uint8 srcslot, dstslot;
68 recv_data >> srcslot >> dstslot;
69 //sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
71 // prevent attempt swap same item to current position generated by client at special checting sequence
72 if(srcslot==dstslot)
73 return;
75 if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
77 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
78 return;
81 if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
83 _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
84 return;
87 uint16 src = ( (INVENTORY_SLOT_BAG_0 << 8) | srcslot );
88 uint16 dst = ( (INVENTORY_SLOT_BAG_0 << 8) | dstslot );
90 _player->SwapItem( src, dst );
93 void WorldSession::HandleAutoEquipItemSlotOpcode( WorldPacket & recv_data )
95 uint64 itemguid;
96 uint8 dstslot;
97 recv_data >> itemguid >> dstslot;
99 // cheating attempt, client should never send opcode in that case
100 if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, dstslot))
101 return;
103 Item* item = _player->GetItemByGuid(itemguid);
104 uint16 dstpos = dstslot | (INVENTORY_SLOT_BAG_0 << 8);
106 if(!item || item->GetPos() == dstpos)
107 return;
109 _player->SwapItem(item->GetPos(), dstpos);
112 void WorldSession::HandleSwapItem( WorldPacket & recv_data )
114 //sLog.outDebug("WORLD: CMSG_SWAP_ITEM");
115 uint8 dstbag, dstslot, srcbag, srcslot;
117 recv_data >> dstbag >> dstslot >> srcbag >> srcslot ;
118 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u", srcbag, srcslot, dstbag, dstslot);
120 uint16 src = ( (srcbag << 8) | srcslot );
121 uint16 dst = ( (dstbag << 8) | dstslot );
123 // prevent attempt swap same item to current position generated by client at special checting sequence
124 if(src==dst)
125 return;
127 if(!_player->IsValidPos(srcbag,srcslot))
129 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
130 return;
133 if(!_player->IsValidPos(dstbag,dstslot))
135 _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
136 return;
139 _player->SwapItem( src, dst );
142 void WorldSession::HandleAutoEquipItemOpcode( WorldPacket & recv_data )
144 //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM");
145 uint8 srcbag, srcslot;
147 recv_data >> srcbag >> srcslot;
148 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
150 Item *pSrcItem = _player->GetItemByPos( srcbag, srcslot );
151 if( !pSrcItem )
152 return; // only at cheat
154 if(pSrcItem->m_lootGenerated) // prevent swap looting item
156 //best error message found for attempting to swap while looting
157 _player->SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pSrcItem, NULL );
158 return;
161 uint16 dest;
162 uint8 msg = _player->CanEquipItem( NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag() );
163 if( msg != EQUIP_ERR_OK )
165 _player->SendEquipError( msg, pSrcItem, NULL );
166 return;
169 uint16 src = pSrcItem->GetPos();
170 if(dest==src) // prevent equip in same slot, only at cheat
171 return;
173 Item *pDstItem = _player->GetItemByPos( dest );
174 if( !pDstItem ) // empty slot, simple case
176 _player->RemoveItem( srcbag, srcslot, true );
177 _player->EquipItem( dest, pSrcItem, true );
178 _player->AutoUnequipOffhandIfNeed();
180 else // have currently equipped item, not simple case
182 uint8 dstbag = pDstItem->GetBagSlot();
183 uint8 dstslot = pDstItem->GetSlot();
185 msg = _player->CanUnequipItem( dest, !pSrcItem->IsBag() );
186 if( msg != EQUIP_ERR_OK )
188 _player->SendEquipError( msg, pDstItem, NULL );
189 return;
192 // check dest->src move possibility
193 ItemPosCountVec sSrc;
194 uint16 eSrc = 0;
195 if( _player->IsInventoryPos( src ) )
197 msg = _player->CanStoreItem( srcbag, srcslot, sSrc, pDstItem, true );
198 if( msg != EQUIP_ERR_OK )
199 msg = _player->CanStoreItem( srcbag, NULL_SLOT, sSrc, pDstItem, true );
200 if( msg != EQUIP_ERR_OK )
201 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, sSrc, pDstItem, true );
203 else if( _player->IsBankPos( src ) )
205 msg = _player->CanBankItem( srcbag, srcslot, sSrc, pDstItem, true );
206 if( msg != EQUIP_ERR_OK )
207 msg = _player->CanBankItem( srcbag, NULL_SLOT, sSrc, pDstItem, true );
208 if( msg != EQUIP_ERR_OK )
209 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, sSrc, pDstItem, true );
211 else if( _player->IsEquipmentPos( src ) )
213 msg = _player->CanEquipItem( srcslot, eSrc, pDstItem, true);
214 if( msg == EQUIP_ERR_OK )
215 msg = _player->CanUnequipItem( eSrc, true);
218 if( msg != EQUIP_ERR_OK )
220 _player->SendEquipError( msg, pDstItem, pSrcItem );
221 return;
224 // now do moves, remove...
225 _player->RemoveItem(dstbag, dstslot, false);
226 _player->RemoveItem(srcbag, srcslot, false);
228 // add to dest
229 _player->EquipItem(dest, pSrcItem, true);
231 // add to src
232 if( _player->IsInventoryPos( src ) )
233 _player->StoreItem(sSrc, pDstItem, true);
234 else if( _player->IsBankPos( src ) )
235 _player->BankItem(sSrc, pDstItem, true);
236 else if( _player->IsEquipmentPos( src ) )
237 _player->EquipItem(eSrc, pDstItem, true);
239 _player->AutoUnequipOffhandIfNeed();
243 void WorldSession::HandleDestroyItemOpcode( WorldPacket & recv_data )
245 //sLog.outDebug("WORLD: CMSG_DESTROYITEM");
246 uint8 bag, slot, count, data1, data2, data3;
248 recv_data >> bag >> slot >> count >> data1 >> data2 >> data3;
249 //sLog.outDebug("STORAGE: receive bag = %u, slot = %u, count = %u", bag, slot, count);
251 uint16 pos = (bag << 8) | slot;
253 // prevent drop unequipable items (in combat, for example) and non-empty bags
254 if(_player->IsEquipmentPos(pos) || _player->IsBagPos(pos))
256 uint8 msg = _player->CanUnequipItem( pos, false );
257 if( msg != EQUIP_ERR_OK )
259 _player->SendEquipError( msg, _player->GetItemByPos(pos), NULL );
260 return;
264 Item *pItem = _player->GetItemByPos( bag, slot );
265 if(!pItem)
267 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
268 return;
271 if(count)
273 uint32 i_count = count;
274 _player->DestroyItemCount( pItem, i_count, true );
276 else
277 _player->DestroyItem( bag, slot, true );
280 // Only _static_ data send in this packet !!!
281 void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
283 //sLog.outDebug("WORLD: CMSG_ITEM_QUERY_SINGLE");
284 uint32 item;
285 recv_data >> item;
287 sLog.outDetail("STORAGE: Item Query = %u", item);
289 ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
290 if( pProto )
292 std::string Name = pProto->Name1;
293 std::string Description = pProto->Description;
295 int loc_idx = GetSessionDbLocaleIndex();
296 if ( loc_idx >= 0 )
298 ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
299 if (il)
301 if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
302 Name = il->Name[loc_idx];
303 if (il->Description.size() > size_t(loc_idx) && !il->Description[loc_idx].empty())
304 Description = il->Description[loc_idx];
307 // guess size
308 WorldPacket data( SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
309 data << pProto->ItemId;
310 data << pProto->Class;
311 data << pProto->SubClass;
312 data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache?
313 data << Name;
314 data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
315 data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
316 data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
317 data << pProto->DisplayInfoID;
318 data << pProto->Quality;
319 data << pProto->Flags;
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;
352 // resistances (7)
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);
370 if(spell)
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));
378 if(db_data)
380 data << uint32(pProto->Spells[s].SpellCooldown);
381 data << uint32(pProto->Spells[s].SpellCategory);
382 data << uint32(pProto->Spells[s].SpellCategoryCooldown);
384 else
386 data << uint32(spell->RecoveryTime);
387 data << uint32(spell->Category);
388 data << uint32(spell->CategoryRecoveryTime);
391 else
393 data << uint32(0);
394 data << uint32(0);
395 data << uint32(0);
396 data << uint32(-1);
397 data << uint32(0);
398 data << uint32(-1);
401 data << pProto->Bonding;
402 data << Description;
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 << pProto->Duration; // added in 2.4.2.8209, duration (seconds)
429 data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
430 data << pProto->HolidayId; // Holiday.dbc?
431 SendPacket( &data );
433 else
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);
438 SendPacket( &data );
442 void WorldSession::HandleReadItem( WorldPacket & recv_data )
444 //sLog.outDebug( "WORLD: CMSG_READ_ITEM");
446 uint8 bag, slot;
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 )
454 WorldPacket data;
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");
462 else
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();
469 SendPacket(&data);
471 else
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" );
479 uint32 itemid;
480 uint64 guid;
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;
492 uint32 count;
494 recv_data >> vendorguid >> itemguid >> count;
496 if(!itemguid)
497 return;
499 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR);
500 if (!pCreature)
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);
504 return;
507 // remove fake death
508 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
509 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
511 Item *pItem = _player->GetItemByGuid( itemguid );
512 if( pItem )
514 // prevent sell not owner item
515 if(_player->GetGUID()!=pItem->GetOwnerGUID())
517 _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
518 return;
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);
525 return;
528 // prevent sell currently looted item
529 if(_player->GetLootGUID()==pItem->GetGUID())
531 _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
532 return;
535 // special case at auto sell (sell all)
536 if(count==0)
538 count = pItem->GetCount();
540 else
542 // prevent sell more items that exist in stack (possable only not from client)
543 if(count > pItem->GetCount())
545 _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
546 return;
550 ItemPrototype const *pProto = pItem->GetProto();
551 if( pProto )
553 if( pProto->SellPrice > 0 )
555 if(count < pItem->GetCount()) // need split items
557 Item *pNewItem = pItem->CloneItem( count, _player );
558 if (!pNewItem)
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);
562 return;
565 pItem->SetCount( pItem->GetCount() - count );
566 _player->ItemRemovedQuestCheck( pItem->GetEntry(), count );
567 if( _player->IsInWorld() )
568 pItem->SendUpdateToPlayer( _player );
569 pItem->SetState(ITEM_CHANGED, _player);
571 _player->AddItemToBuyBackSlot( pNewItem );
572 if( _player->IsInWorld() )
573 pNewItem->SendUpdateToPlayer( _player );
575 else
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 );
585 else
586 _player->SendSellError( SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0);
587 return;
590 _player->SendSellError( SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0);
591 return;
594 void WorldSession::HandleBuybackItem(WorldPacket & recv_data)
596 sLog.outDebug( "WORLD: Received CMSG_BUYBACK_ITEM" );
597 uint64 vendorguid;
598 uint32 slot;
600 recv_data >> vendorguid >> slot;
602 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR);
603 if (!pCreature)
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);
607 return;
610 // remove fake death
611 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
612 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
614 Item *pItem = _player->GetItemFromBuyBackSlot( slot );
615 if( pItem )
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);
621 return;
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 );
633 else
634 _player->SendEquipError( msg, pItem, NULL );
635 return;
637 else
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;
646 uint8 bagslot;
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;
655 else
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())
663 bag = i;
664 break;
670 // bag not found, cheating?
671 if (bag == NULL_BAG)
672 return;
674 GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bag,bagslot);
677 void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data )
679 sLog.outDebug( "WORLD: Received CMSG_BUY_ITEM" );
680 uint64 vendorguid;
681 uint32 item, slot, count;
682 uint8 unk1;
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 )
691 uint64 guid;
693 recv_data >> guid;
695 if(!GetPlayer()->isAlive())
696 return;
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);
708 if (!pCreature)
710 sLog.outDebug( "WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) );
711 _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
712 return;
715 // remove fake death
716 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
717 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
719 // Stop the npc if moving
720 pCreature->StopMoving();
722 VendorItemData const* vItems = pCreature->GetVendorItems();
723 if(!vItems)
725 _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0);
726 return;
729 uint8 numitems = vItems->GetItemCount();
730 uint8 count = 0;
732 WorldPacket data( SMSG_LIST_INVENTORY, (8+1+numitems*8*4) );
733 data << uint64(vendorguid);
734 data << uint8(numitems);
736 float discountMod = _player->GetReputationPriceDiscount(pCreature);
738 for(int i = 0; i < numitems; ++i )
740 if(VendorItem const* crItem = vItems->GetItem(i))
742 if(ItemPrototype const *pProto = objmgr.GetItemPrototype(crItem->item))
744 if((pProto->AllowableClass & _player->getClassMask()) == 0 && pProto->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster())
745 continue;
747 ++count;
749 // reputation discount
750 uint32 price = uint32(floor(pProto->BuyPrice * discountMod));
752 data << uint32(count);
753 data << uint32(crItem->item);
754 data << uint32(pProto->DisplayInfoID);
755 data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
756 data << uint32(price);
757 data << uint32(pProto->MaxDurability);
758 data << uint32(pProto->BuyCount);
759 data << uint32(crItem->ExtendedCost);
764 if ( count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4 )
765 return;
767 data.put<uint8>(8, count);
768 SendPacket( &data );
771 void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data )
773 //sLog.outDebug("WORLD: CMSG_AUTOSTORE_BAG_ITEM");
774 uint8 srcbag, srcslot, dstbag;
776 recv_data >> srcbag >> srcslot >> dstbag;
777 //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u", srcbag, srcslot, dstbag);
779 Item *pItem = _player->GetItemByPos( srcbag, srcslot );
780 if( !pItem )
781 return;
783 if(!_player->IsValidPos(dstbag,NULL_SLOT))
785 _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL );
786 return;
789 uint16 src = pItem->GetPos();
791 // check unequip potability for equipped items and bank bags
792 if(_player->IsEquipmentPos ( src ) || _player->IsBagPos ( src ))
794 uint8 msg = _player->CanUnequipItem( src, !_player->IsBagPos ( src ));
795 if(msg != EQUIP_ERR_OK)
797 _player->SendEquipError( msg, pItem, NULL );
798 return;
802 ItemPosCountVec dest;
803 uint8 msg = _player->CanStoreItem( dstbag, NULL_SLOT, dest, pItem, false );
804 if( msg != EQUIP_ERR_OK )
806 _player->SendEquipError( msg, pItem, NULL );
807 return;
810 // no-op: placed in same slot
811 if(dest.size()==1 && dest[0].pos==src)
813 // just remove grey item state
814 _player->SendEquipError( EQUIP_ERR_NONE, pItem, NULL );
815 return;
818 _player->RemoveItem(srcbag, srcslot, true );
819 _player->StoreItem( dest, pItem, true );
822 void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
824 sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT");
826 uint64 guid;
827 recvPacket >> guid;
829 // cheating protection
830 /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command.
831 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER);
832 if(!pCreature)
834 sLog.outDebug( "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
835 return;
839 uint32 slot = _player->GetBankBagSlotCount();
841 // next slot
842 ++slot;
844 sLog.outDetail("PLAYER: Buy bank bag slot, slot number = %u", slot);
846 BankBagSlotPricesEntry const* slotEntry = sBankBagSlotPricesStore.LookupEntry(slot);
848 if(!slotEntry)
849 return;
851 uint32 price = slotEntry->price;
853 if (_player->GetMoney() < price)
854 return;
856 _player->SetBankBagSlotCount(slot);
857 _player->ModifyMoney(-int32(price));
859 _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT);
862 void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
864 sLog.outDebug("WORLD: CMSG_AUTOBANK_ITEM");
865 uint8 srcbag, srcslot;
867 recvPacket >> srcbag >> srcslot;
868 sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
870 Item *pItem = _player->GetItemByPos( srcbag, srcslot );
871 if( !pItem )
872 return;
874 ItemPosCountVec dest;
875 uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
876 if( msg != EQUIP_ERR_OK )
878 _player->SendEquipError( msg, pItem, NULL );
879 return;
882 _player->RemoveItem(srcbag, srcslot, true);
883 _player->BankItem( dest, pItem, true );
886 void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
888 sLog.outDebug("WORLD: CMSG_AUTOSTORE_BANK_ITEM");
889 uint8 srcbag, srcslot;
891 recvPacket >> srcbag >> srcslot;
892 sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
894 Item *pItem = _player->GetItemByPos( srcbag, srcslot );
895 if( !pItem )
896 return;
898 if(_player->IsBankPos(srcbag, srcslot)) // moving from bank to inventory
900 ItemPosCountVec dest;
901 uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
902 if( msg != EQUIP_ERR_OK )
904 _player->SendEquipError( msg, pItem, NULL );
905 return;
908 _player->RemoveItem(srcbag, srcslot, true);
909 _player->StoreItem( dest, pItem, true );
911 else // moving from inventory to bank
913 ItemPosCountVec dest;
914 uint8 msg = _player->CanBankItem( NULL_BAG, NULL_SLOT, dest, pItem, false );
915 if( msg != EQUIP_ERR_OK )
917 _player->SendEquipError( msg, pItem, NULL );
918 return;
921 _player->RemoveItem(srcbag, srcslot, true);
922 _player->BankItem( dest, pItem, true );
926 void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data)
928 if(!GetPlayer()->isAlive())
930 GetPlayer()->SendEquipError( EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL );
931 return;
934 sLog.outDebug("WORLD: CMSG_SET_AMMO");
935 uint32 item;
937 recv_data >> item;
939 if(!item)
940 GetPlayer()->RemoveAmmo();
941 else
942 GetPlayer()->SetAmmo(item);
945 void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID)
947 WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10
948 data << Target;
949 data << Caster;
950 data << ItemID;
951 data << SpellID;
952 data << uint8(0);
953 SendPacket(&data);
956 void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid,uint32 slot,uint32 Duration)
958 // last check 2.0.10
959 WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8));
960 data << uint64(Itemguid);
961 data << uint32(slot);
962 data << uint32(Duration);
963 data << uint64(Playerguid);
964 SendPacket(&data);
967 void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data)
969 uint32 itemid;
970 recv_data >> itemid;
971 recv_data.read_skip<uint64>(); // guid
973 sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid);
974 ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid );
975 if( pProto )
977 std::string Name;
978 Name = pProto->Name1;
980 int loc_idx = GetSessionDbLocaleIndex();
981 if (loc_idx >= 0)
983 ItemLocale const *il = objmgr.GetItemLocale(pProto->ItemId);
984 if (il)
986 if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
987 Name = il->Name[loc_idx];
990 // guess size
991 WorldPacket data(SMSG_ITEM_NAME_QUERY_RESPONSE, (4+10));
992 data << uint32(pProto->ItemId);
993 data << Name;
994 data << uint32(pProto->InventoryType);
995 SendPacket(&data);
996 return;
998 else
1000 // listed in dbc or not expected to exist unknown item
1001 if(sItemStore.LookupEntry(itemid))
1002 sLog.outErrorDb("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (item listed in Item.dbc but not exist in DB)", itemid);
1003 else
1004 sLog.outError("WORLD: CMSG_ITEM_NAME_QUERY for item %u failed (unknown item, not listed in Item.dbc)", itemid);
1008 void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data)
1010 sLog.outDebug("Received opcode CMSG_WRAP_ITEM");
1012 uint8 gift_bag, gift_slot, item_bag, item_slot;
1013 //recv_data.hexlike();
1015 recv_data >> gift_bag >> gift_slot; // paper
1016 recv_data >> item_bag >> item_slot; // item
1018 sLog.outDebug("WRAP: receive gift_bag = %u, gift_slot = %u, item_bag = %u, item_slot = %u", gift_bag, gift_slot, item_bag, item_slot);
1020 Item *gift = _player->GetItemByPos( gift_bag, gift_slot );
1021 if(!gift)
1023 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL );
1024 return;
1027 if(!gift->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPER))// cheating: non-wrapper wrapper
1029 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL );
1030 return;
1033 Item *item = _player->GetItemByPos( item_bag, item_slot );
1035 if( !item )
1037 _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, item, NULL );
1038 return;
1041 if(item==gift) // not possable with pacjket from real client
1043 _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
1044 return;
1047 if(item->IsEquipped())
1049 _player->SendEquipError( EQUIP_ERR_EQUIPPED_CANT_BE_WRAPPED, item, NULL );
1050 return;
1053 if(item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR)) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1055 _player->SendEquipError( EQUIP_ERR_WRAPPED_CANT_BE_WRAPPED, item, NULL );
1056 return;
1059 if(item->IsBag())
1061 _player->SendEquipError( EQUIP_ERR_BAGS_CANT_BE_WRAPPED, item, NULL );
1062 return;
1065 if(item->IsSoulBound())
1067 _player->SendEquipError( EQUIP_ERR_BOUND_CANT_BE_WRAPPED, item, NULL );
1068 return;
1071 if(item->GetMaxStackCount() != 1)
1073 _player->SendEquipError( EQUIP_ERR_STACKABLE_CANT_BE_WRAPPED, item, NULL );
1074 return;
1077 // maybe not correct check (it is better than nothing)
1078 if(item->GetProto()->MaxCount>0)
1080 _player->SendEquipError( EQUIP_ERR_UNIQUE_CANT_BE_WRAPPED, item, NULL );
1081 return;
1084 CharacterDatabase.BeginTransaction();
1085 CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS));
1086 item->SetEntry(gift->GetEntry());
1088 switch (item->GetEntry())
1090 case 5042: item->SetEntry( 5043); break;
1091 case 5048: item->SetEntry( 5044); break;
1092 case 17303: item->SetEntry(17302); break;
1093 case 17304: item->SetEntry(17305); break;
1094 case 17307: item->SetEntry(17308); break;
1095 case 21830: item->SetEntry(21831); break;
1097 item->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
1098 item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
1099 item->SetState(ITEM_CHANGED, _player);
1101 if(item->GetState()==ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance`
1103 // after save it will be impossible to remove the item from the queue
1104 item->RemoveFromUpdateQueueOf(_player);
1105 item->SaveToDB(); // item gave inventory record unchanged and can be save standalone
1107 CharacterDatabase.CommitTransaction();
1109 uint32 count = 1;
1110 _player->DestroyItemCount(gift, count, true);
1113 void WorldSession::HandleSocketOpcode(WorldPacket& recv_data)
1115 sLog.outDebug("WORLD: CMSG_SOCKET_GEMS");
1117 uint64 item_guid;
1118 uint64 gem_guids[MAX_GEM_SOCKETS];
1120 recv_data >> item_guid;
1121 if(!item_guid)
1122 return;
1124 for(int i = 0; i < MAX_GEM_SOCKETS; ++i)
1125 recv_data >> gem_guids[i];
1127 //cheat -> tried to socket same gem multiple times
1128 if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) ||
1129 (gem_guids[1] && (gem_guids[1] == gem_guids[2])))
1130 return;
1132 Item *itemTarget = _player->GetItemByGuid(item_guid);
1133 if(!itemTarget) //missing item to socket
1134 return;
1136 ItemPrototype const* itemProto = itemTarget->GetProto();
1137 if(!itemProto)
1138 return;
1140 //this slot is excepted when applying / removing meta gem bonus
1141 uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT);
1143 Item *Gems[MAX_GEM_SOCKETS];
1144 for(int i = 0; i < MAX_GEM_SOCKETS; ++i)
1145 Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL;
1147 GemPropertiesEntry const *GemProps[MAX_GEM_SOCKETS];
1148 for(int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage
1149 GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL;
1151 for(int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe
1153 if (!GemProps[i])
1154 continue;
1156 // tried to put gem in socket where no socket exists (take care about prismatic sockets)
1157 if (!itemProto->Socket[i].Color)
1159 // no prismatic socket
1160 if(!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT))
1161 return;
1163 // not first not-colored (not normaly used) socket
1164 if(i!=0 && !itemProto->Socket[i-1].Color && (i+1 >= MAX_GEM_SOCKETS || itemProto->Socket[i+1].Color))
1165 return;
1167 // ok, this is first not colored socket for item with prismatic socket
1170 // tried to put normal gem in meta socket
1171 if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META)
1172 return;
1174 // tried to put meta gem in normal socket
1175 if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META)
1176 return;
1179 uint32 GemEnchants[MAX_GEM_SOCKETS];
1180 uint32 OldEnchants[MAX_GEM_SOCKETS];
1181 for(int i = 0; i < MAX_GEM_SOCKETS; ++i) //get new and old enchantments
1183 GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0;
1184 OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i));
1187 // check unique-equipped conditions
1188 for(int i = 0; i < MAX_GEM_SOCKETS; ++i)
1190 if(!Gems[i])
1191 continue;
1193 // continue check for case when attempt add 2 similar unique equipped gems in one item.
1194 ItemPrototype const* iGemProto = Gems[i]->GetProto();
1196 // unique item (for new and already placed bit removed enchantments
1197 if (iGemProto->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED)
1199 for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
1201 if(i==j) // skip self
1202 continue;
1204 if (Gems[j])
1206 if (iGemProto->ItemId == Gems[j]->GetEntry())
1208 _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1209 return;
1212 else if(OldEnchants[j])
1214 if(SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
1216 if (iGemProto->ItemId == enchantEntry->GemID)
1218 _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1219 return;
1227 // unique limit type item
1228 int32 limit_newcount = 0;
1229 if (iGemProto->ItemLimitCategory)
1231 if(ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory))
1233 for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
1235 if (Gems[j])
1237 // destroyed gem
1238 if (OldEnchants[j])
1240 if(SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
1241 if(ItemPrototype const* jProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID))
1242 if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory)
1243 --limit_newcount;
1246 // new gem
1247 if (iGemProto->ItemLimitCategory == Gems[j]->GetProto()->ItemLimitCategory)
1248 ++limit_newcount;
1250 // existed gem
1251 else if(OldEnchants[j])
1253 if(SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j]))
1254 if(ItemPrototype const* jProto = ObjectMgr::GetItemPrototype(enchantEntry->GemID))
1255 if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory)
1256 ++limit_newcount;
1260 if(limit_newcount > 0 && uint32(limit_newcount) > limitEntry->maxCount)
1262 _player->SendEquipError( EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, NULL );
1263 return;
1268 // for equipped item check all equipment for duplicate equipped gems
1269 if(itemTarget->IsEquipped())
1271 if(uint8 res = _player->CanEquipUniqueItem(Gems[i],slot,limit_newcount >= 0 ? limit_newcount : 0))
1273 _player->SendEquipError( res, itemTarget, NULL );
1274 return;
1279 bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus
1280 _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item)
1282 //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
1284 //remove ALL enchants
1285 for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
1286 _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false);
1288 for(int i = 0; i < MAX_GEM_SOCKETS; ++i)
1290 if(GemEnchants[i])
1292 itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0);
1293 if(Item* guidItem = _player->GetItemByGuid(gem_guids[i]))
1294 _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true );
1298 for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
1299 _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true);
1301 bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
1302 if(SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change...
1304 _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false);
1305 itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetProto()->socketBonus : 0), 0, 0);
1306 _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,true);
1307 //it is not displayed, client has an inbuilt system to determine if the bonus is activated
1310 _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item)
1313 void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data)
1315 sLog.outDebug("WORLD: CMSG_CANCEL_TEMP_ENCHANTMENT");
1317 uint32 eslot;
1319 recv_data >> eslot;
1321 // apply only to equipped item
1322 if(!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0,eslot))
1323 return;
1325 Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, eslot);
1327 if(!item)
1328 return;
1330 if(!item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT))
1331 return;
1333 GetPlayer()->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
1334 item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);