TrinityCore
ItemHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "BattlePetMgr.h"
20#include "Common.h"
21#include "Creature.h"
22#include "DatabaseEnv.h"
23#include "DB2Stores.h"
24#include "GossipDef.h"
25#include "Item.h"
26#include "ItemPackets.h"
27#include "Log.h"
28#include "NPCPackets.h"
29#include "ObjectMgr.h"
30#include "Player.h"
31#include "World.h"
32
34{
35 if (!splitItem.Inv.Items.empty())
36 {
37 TC_LOG_ERROR("network", "HandleSplitItemOpcode - Invalid ItemCount ({})", splitItem.Inv.Items.size());
38 return;
39 }
40
41 TC_LOG_DEBUG("network", "HandleSplitItemOpcode: receive FromPackSlot: {}, FromSlot: {}, ToPackSlot: {}, ToSlot: {}, Quantity: {}",
42 splitItem.FromPackSlot, splitItem.FromSlot, splitItem.ToPackSlot, splitItem.ToSlot, splitItem.Quantity);
43
44 uint16 src = ((splitItem.FromPackSlot << 8) | splitItem.FromSlot);
45 uint16 dst = ((splitItem.ToPackSlot << 8) | splitItem.ToSlot);
46
47 if (src == dst)
48 return;
49
50 // check count - if zero it's fake packet
51 if (!splitItem.Quantity)
52 return;
53
54 if (!_player->IsValidPos(splitItem.FromPackSlot, splitItem.FromSlot, true))
55 {
57 return;
58 }
59
60 if (!_player->IsValidPos(splitItem.ToPackSlot, splitItem.ToSlot, false)) // can be autostore pos
61 {
63 return;
64 }
65
66 _player->SplitItem(src, dst, splitItem.Quantity);
67}
68
70{
71 if (swapInvItem.Inv.Items.size() != 2)
72 {
73 TC_LOG_ERROR("network", "HandleSwapInvItemOpcode - Invalid itemCount ({})", swapInvItem.Inv.Items.size());
74 return;
75 }
76
77 TC_LOG_DEBUG("network", "HandleSwapInvItemOpcode: receive Slot1: {}, Slot2: {}",
78 swapInvItem.Slot1, swapInvItem.Slot2);
79
80 // prevent attempt swap same item to current position generated by client at special checting sequence
81 if (swapInvItem.Slot1 == swapInvItem.Slot2)
82 return;
83
84 if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, swapInvItem.Slot1, true))
85 {
87 return;
88 }
89
90 if (!_player->IsValidPos(INVENTORY_SLOT_BAG_0, swapInvItem.Slot2, true))
91 {
93 return;
94 }
95
96 if (_player->IsBankPos(INVENTORY_SLOT_BAG_0, swapInvItem.Slot1) && !CanUseBank())
97 {
98 TC_LOG_DEBUG("network", "HandleSwapInvItemOpcode - Unit ({}) not found or you can't interact with him.", _player->PlayerTalkClass->GetInteractionData().SourceGuid.ToString());
99 return;
100 }
101
102 if (_player->IsBankPos(INVENTORY_SLOT_BAG_0, swapInvItem.Slot2) && !CanUseBank())
103 {
104 TC_LOG_DEBUG("network", "HandleSwapInvItemOpcode - Unit ({}) not found or you can't interact with him.", _player->PlayerTalkClass->GetInteractionData().SourceGuid.ToString());
105 return;
106 }
107
108 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | swapInvItem.Slot1);
109 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | swapInvItem.Slot2);
110
111 _player->SwapItem(src, dst);
112}
113
115{
116 // cheating attempt, client should never send opcode in that case
117 if (autoEquipItemSlot.Inv.Items.size() != 1 || !Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, autoEquipItemSlot.ItemDstSlot))
118 return;
119
120 Item* item = _player->GetItemByGuid(autoEquipItemSlot.Item);
121 uint16 dstPos = autoEquipItemSlot.ItemDstSlot | (INVENTORY_SLOT_BAG_0 << 8);
122 uint16 srcPos = autoEquipItemSlot.Inv.Items[0].Slot | (uint32(autoEquipItemSlot.Inv.Items[0].ContainerSlot) << 8);
123
124 if (!item || item->GetPos() != srcPos || srcPos == dstPos)
125 return;
126
127 _player->SwapItem(srcPos, dstPos);
128}
129
131{
132 if (swapItem.Inv.Items.size() != 2)
133 {
134 TC_LOG_ERROR("network", "HandleSwapItem - Invalid itemCount ({})", swapItem.Inv.Items.size());
135 return;
136 }
137
138 TC_LOG_DEBUG("network", "HandleSwapItem: receive ContainerSlotA: {}, SlotA: {}, ContainerSlotB: {}, SlotB: {}",
139 swapItem.ContainerSlotA, swapItem.SlotA, swapItem.ContainerSlotB, swapItem.SlotB);
140
141 uint16 src = ((swapItem.ContainerSlotA << 8) | swapItem.SlotA);
142 uint16 dst = ((swapItem.ContainerSlotB << 8) | swapItem.SlotB);
143
144 // prevent attempt swap same item to current position generated by client at special checting sequence
145 if (src == dst)
146 return;
147
148 if (!_player->IsValidPos(swapItem.ContainerSlotA, swapItem.SlotA, true))
149 {
151 return;
152 }
153
154 if (!_player->IsValidPos(swapItem.ContainerSlotB, swapItem.SlotB, true))
155 {
157 return;
158 }
159
160 if (_player->IsBankPos(swapItem.ContainerSlotA, swapItem.SlotA) && !CanUseBank())
161 {
162 TC_LOG_DEBUG("network", "HandleSwapItem - Unit ({}) not found or you can't interact with him.", _player->PlayerTalkClass->GetInteractionData().SourceGuid.ToString());
163 return;
164 }
165
166 if (_player->IsBankPos(swapItem.ContainerSlotB, swapItem.SlotB) && !CanUseBank())
167 {
168 TC_LOG_DEBUG("network", "HandleSwapItem - Unit ({}) not found or you can't interact with him.", _player->PlayerTalkClass->GetInteractionData().SourceGuid.ToString());
169 return;
170 }
171
172 _player->SwapItem(src, dst);
173}
174
176{
177 if (autoEquipItem.Inv.Items.size() != 1)
178 {
179 TC_LOG_ERROR("network", "HandleAutoEquipItemOpcode - Invalid itemCount ({})", autoEquipItem.Inv.Items.size());
180 return;
181 }
182
183 TC_LOG_DEBUG("network", "HandleAutoEquipItemOpcode: receive PackSlot: {}, Slot: {}",
184 autoEquipItem.PackSlot, autoEquipItem.Slot);
185
186 Item* srcItem = _player->GetItemByPos(autoEquipItem.PackSlot, autoEquipItem.Slot);
187 if (!srcItem)
188 return; // only at cheat
189
190 uint16 dest;
191 InventoryResult msg = _player->CanEquipItem(NULL_SLOT, dest, srcItem, !srcItem->IsBag());
192 if (msg != EQUIP_ERR_OK)
193 {
194 _player->SendEquipError(msg, srcItem);
195 return;
196 }
197
198 uint16 src = srcItem->GetPos();
199 if (dest == src) // prevent equip in same slot, only at cheat
200 return;
201
202 Item* dstItem = _player->GetItemByPos(dest);
203 if (!dstItem) // empty slot, simple case
204 {
205 if (!srcItem->GetChildItem().IsEmpty())
206 {
207 InventoryResult childEquipResult = _player->CanEquipChildItem(srcItem);
208 if (childEquipResult != EQUIP_ERR_OK)
209 {
210 _player->SendEquipError(msg, srcItem);
211 return;
212 }
213 }
214
215 _player->RemoveItem(autoEquipItem.PackSlot, autoEquipItem.Slot, true);
216 _player->EquipItem(dest, srcItem, true);
217 if (!srcItem->GetChildItem().IsEmpty())
218 _player->EquipChildItem(autoEquipItem.PackSlot, autoEquipItem.Slot, srcItem);
219
221 }
222 else // have currently equipped item, not simple case
223 {
224 uint8 dstbag = dstItem->GetBagSlot();
225 uint8 dstslot = dstItem->GetSlot();
226
227 msg = _player->CanUnequipItem(dest, !srcItem->IsBag());
228 if (msg != EQUIP_ERR_OK)
229 {
230 _player->SendEquipError(msg, dstItem);
231 return;
232 }
233
234 if (!dstItem->HasItemFlag(ITEM_FIELD_FLAG_CHILD))
235 {
236 // check dest->src move possibility
237 ItemPosCountVec sSrc;
238 uint16 eSrc = 0;
239 if (_player->IsInventoryPos(src))
240 {
241 msg = _player->CanStoreItem(autoEquipItem.PackSlot, autoEquipItem.Slot, sSrc, dstItem, true);
242 if (msg != EQUIP_ERR_OK)
243 msg = _player->CanStoreItem(autoEquipItem.PackSlot, NULL_SLOT, sSrc, dstItem, true);
244 if (msg != EQUIP_ERR_OK)
245 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, dstItem, true);
246 }
247 else if (_player->IsBankPos(src))
248 {
249 msg = _player->CanBankItem(autoEquipItem.PackSlot, autoEquipItem.Slot, sSrc, dstItem, true);
250 if (msg != EQUIP_ERR_OK)
251 msg = _player->CanBankItem(autoEquipItem.PackSlot, NULL_SLOT, sSrc, dstItem, true);
252 if (msg != EQUIP_ERR_OK)
253 msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, dstItem, true);
254 }
255 else if (_player->IsEquipmentPos(src))
256 {
257 msg = _player->CanEquipItem(autoEquipItem.Slot, eSrc, dstItem, true);
258 if (msg == EQUIP_ERR_OK)
259 msg = _player->CanUnequipItem(eSrc, true);
260 }
261
262 if (msg == EQUIP_ERR_OK && Player::IsEquipmentPos(dest) && !srcItem->GetChildItem().IsEmpty())
263 msg = _player->CanEquipChildItem(srcItem);
264
265 if (msg != EQUIP_ERR_OK)
266 {
267 _player->SendEquipError(msg, dstItem, srcItem);
268 return;
269 }
270
271 // now do moves, remove...
272 _player->RemoveItem(dstbag, dstslot, false);
273 _player->RemoveItem(autoEquipItem.PackSlot, autoEquipItem.Slot, false);
274
275 // add to dest
276 _player->EquipItem(dest, srcItem, true);
277
278 // add to src
279 if (_player->IsInventoryPos(src))
280 _player->StoreItem(sSrc, dstItem, true);
281 else if (_player->IsBankPos(src))
282 _player->BankItem(sSrc, dstItem, true);
283 else if (_player->IsEquipmentPos(src))
284 _player->EquipItem(eSrc, dstItem, true);
285
286 if (Player::IsEquipmentPos(dest) && !srcItem->GetChildItem().IsEmpty())
287 _player->EquipChildItem(autoEquipItem.PackSlot, autoEquipItem.Slot, srcItem);
288 }
289 else
290 {
291 if (Item* parentItem = _player->GetItemByGuid(dstItem->GetCreator()))
292 {
293 if (Player::IsEquipmentPos(dest))
294 {
295 _player->AutoUnequipChildItem(parentItem);
296 // dest is now empty
297 _player->SwapItem(src, dest);
298 // src is now empty
299 _player->SwapItem(parentItem->GetPos(), src);
300 }
301 }
302 }
303
305
306 // if inventory item was moved, check if we can remove dependent auras, because they were not removed in Player::RemoveItem (update was set to false)
307 // do this after swaps are done, we pass nullptr because both weapons could be swapped and none of them should be ignored
308 if ((autoEquipItem.PackSlot == INVENTORY_SLOT_BAG_0 && autoEquipItem.Slot < INVENTORY_SLOT_BAG_END) || (dstbag == INVENTORY_SLOT_BAG_0 && dstslot < INVENTORY_SLOT_BAG_END))
309 _player->ApplyItemDependentAuras((Item*)nullptr, false);
310 }
311}
312
314{
315 TC_LOG_DEBUG("network", "HandleDestroyItemOpcode: receive ContainerId: {}, SlotNum: {}, Count: {}",
316 destroyItem.ContainerId, destroyItem.SlotNum, destroyItem.Count);
317
318 uint16 pos = (destroyItem.ContainerId << 8) | destroyItem.SlotNum;
319
320 // prevent drop unequipable items (in combat, for example) and non-empty bags
321 if (_player->IsEquipmentPos(pos) || _player->IsBagPos(pos))
322 {
323 InventoryResult msg = _player->CanUnequipItem(pos, false);
324 if (msg != EQUIP_ERR_OK)
325 {
327 return;
328 }
329 }
330
331 Item* item = _player->GetItemByPos(destroyItem.ContainerId, destroyItem.SlotNum);
332 if (!item)
333 {
335 return;
336 }
337
339 {
341 return;
342 }
343
344 if (destroyItem.Count)
345 {
346 uint32 i_count = destroyItem.Count;
347 _player->DestroyItemCount(item, i_count, true);
348 }
349 else
350 _player->DestroyItem(destroyItem.ContainerId, destroyItem.SlotNum, true);
351}
352
354{
355 Item* item = _player->GetItemByPos(readItem.PackSlot, readItem.Slot);
356 if (item && item->GetTemplate()->GetPageText())
357 {
359 if (msg == EQUIP_ERR_OK)
360 {
362 packet.Item = item->GetGUID();
363 SendPacket(packet.Write());
364
365 TC_LOG_INFO("network", "STORAGE: Item page sent");
366 }
367 else
368 {
370 /*WorldPackets::Item::ReadItemResultFailed packet;
371 packet.Item = item->GetGUID();
372 packet.Subcode = ??;
373 packet.Delay = ??;
374 SendPacket(packet.Write());*/
375
376 TC_LOG_INFO("network", "STORAGE: Unable to read item");
377 _player->SendEquipError(msg, item, nullptr);
378 }
379 }
380 else
382}
383
385{
386 TC_LOG_DEBUG("network", "WORLD: Received CMSG_SELL_ITEM: Vendor {}, Item {}, Amount: {}",
387 packet.VendorGUID.ToString(), packet.ItemGUID.ToString(), packet.Amount);
388
389 if (packet.ItemGUID.IsEmpty())
390 return;
391
393 if (!creature)
394 {
395 TC_LOG_DEBUG("network", "WORLD: HandleSellItemOpcode - {} not found or you can not interact with him.", packet.VendorGUID.ToString());
397 return;
398 }
399
401 {
403 return;
404 }
405
406 // remove fake death
407 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
409
410 Item* pItem = _player->GetItemByGuid(packet.ItemGUID);
411 if (pItem)
412 {
413 // prevent sell not owner item
414 if (_player->GetGUID() != pItem->GetOwnerGUID())
415 {
417 return;
418 }
419
420 // prevent sell non empty bag by drag-and-drop at vendor's item list
421 if (pItem->IsNotEmptyBag())
422 {
424 return;
425 }
426
427 // prevent sell currently looted item
428 if (_player->GetLootGUID() == pItem->GetGUID())
429 {
431 return;
432 }
433
434 // prevent selling item for sellprice when the item is still refundable
435 // this probably happens when right clicking a refundable item, the client sends both
436 // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified)
437 if (pItem->IsRefundable())
438 return; // Therefore, no feedback to client
439
440 // special case at auto sell (sell all)
441 if (packet.Amount == 0)
442 packet.Amount = pItem->GetCount();
443 else
444 {
445 // prevent sell more items that exist in stack (possible only not from client)
446 if (packet.Amount > pItem->GetCount())
447 {
449 return;
450 }
451 }
452
453 ItemTemplate const* pProto = pItem->GetTemplate();
454 if (pProto)
455 {
456 if (pProto->GetSellPrice() > 0)
457 {
458 uint64 money = uint64(pProto->GetSellPrice()) * packet.Amount;
459
460 if (!_player->ModifyMoney(money)) // ensure player doesn't exceed gold limit
461 {
463 return;
464 }
465
468
469 if (packet.Amount < pItem->GetCount()) // need split items
470 {
471 Item* pNewItem = pItem->CloneItem(packet.Amount, _player);
472 if (!pNewItem)
473 {
474 TC_LOG_ERROR("network", "WORLD: HandleSellItemOpcode - could not create clone of item {}; count = {}", pItem->GetEntry(), packet.Amount);
476 return;
477 }
478
479 pItem->SetCount(pItem->GetCount() - packet.Amount);
480 _player->ItemRemovedQuestCheck(pItem->GetEntry(), packet.Amount);
481 if (_player->IsInWorld())
484
485 _player->AddItemToBuyBackSlot(pNewItem);
486 if (_player->IsInWorld())
487 pNewItem->SendUpdateToPlayer(_player);
488 }
489 else
490 {
491 _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
492 _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount());
495 }
496 }
497 else
499 return;
500 }
501 }
503 return;
504}
505
507{
508 TC_LOG_DEBUG("network", "WORLD: Received CMSG_BUYBACK_ITEM: Vendor {}, Slot: {}", packet.VendorGUID.ToString(), packet.Slot);
509
511 if (!creature)
512 {
513 TC_LOG_DEBUG("network", "WORLD: HandleBuybackItem - Unit ({}) not found or you can not interact with him.", packet.VendorGUID.ToString());
515 return;
516 }
517
518 // remove fake death
519 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
521
522 Item* pItem = _player->GetItemFromBuyBackSlot(packet.Slot);
523 if (pItem)
524 {
525 uint32 price = _player->m_activePlayerData->BuybackPrice[packet.Slot - BUYBACK_SLOT_START];
526 if (!_player->HasEnoughMoney(uint64(price)))
527 {
529 return;
530 }
531
532 ItemPosCountVec dest;
533 InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, pItem, false);
534 if (msg == EQUIP_ERR_OK)
535 {
536 _player->ModifyMoney(-(int32)price);
537 _player->RemoveItemFromBuyBackSlot(packet.Slot, false);
538 _player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount());
539 _player->StoreItem(dest, pItem, true);
540 }
541 else
542 _player->SendEquipError(msg, pItem, nullptr);
543 return;
544 }
545 else
547}
548
550{
551 // client expects count starting at 1, and we send vendorslot+1 to client already
552 if (packet.Muid > 0)
553 --packet.Muid;
554 else
555 return; // cheating
556
557 switch (packet.ItemType)
558 {
560 {
561 Item* bagItem = _player->GetItemByGuid(packet.ContainerGUID);
562
563 uint8 bag = NULL_BAG;
564 if (bagItem && bagItem->IsBag())
565 bag = bagItem->GetSlot();
566 else if (packet.ContainerGUID == GetPlayer()->GetGUID()) // The client sends the player guid when trying to store an item in the default backpack
568
569 GetPlayer()->BuyItemFromVendorSlot(packet.VendorGUID, packet.Muid, packet.Item.ItemID,
570 packet.Quantity, bag, packet.Slot);
571 break;
572 }
574 {
575 GetPlayer()->BuyCurrencyFromVendorSlot(packet.VendorGUID, packet.Muid, packet.Item.ItemID, packet.Quantity);
576 break;
577 }
578 default:
579 {
580 TC_LOG_DEBUG("network", "WORLD: received wrong itemType ({}) in HandleBuyItemOpcode", packet.ItemType);
581 break;
582 }
583 }
584}
585
587{
588 if (!GetPlayer()->IsAlive())
589 return;
590
591 SendListInventory(packet.Unit);
592}
593
595{
597 if (!vendor)
598 {
599 TC_LOG_DEBUG("network", "WORLD: SendListInventory - {} not found or you can not interact with him.", vendorGuid.ToString());
601 return;
602 }
603
604 // remove fake death
605 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
607
608 // Stop the npc if moving
610 vendor->PauseMovement(pause);
611 vendor->SetHomePosition(vendor->GetPosition());
612
613 VendorItemData const* vendorItems = vendor->GetVendorItems();
614 uint32 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0;
615
617 packet.Vendor = vendor->GetGUID();
618
619 packet.Items.resize(rawItemCount);
620
621 const float discountMod = _player->GetReputationPriceDiscount(vendor);
622 uint8 count = 0;
623 for (uint32 slot = 0; slot < rawItemCount; ++slot)
624 {
625 VendorItem const* vendorItem = vendorItems->GetItem(slot);
626 if (!vendorItem)
627 continue;
628
629 WorldPackets::NPC::VendorItem& item = packet.Items[count];
630
631 if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(vendorItem->PlayerConditionId))
632 if (!ConditionMgr::IsPlayerMeetingCondition(_player, playerCondition))
633 item.PlayerConditionFailed = playerCondition->ID;
634
635 if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM)
636 {
637 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item);
638 if (!itemTemplate)
639 continue;
640
641 int32 leftInStock = !vendorItem->maxcount ? -1 : vendor->GetVendorItemCurrentCount(vendorItem);
642 if (!_player->IsGameMaster()) // ignore conditions if GM on
643 {
644 // Respect allowed class
645 if (!(itemTemplate->GetAllowableClass() & _player->GetClassMask()) && itemTemplate->GetBonding() == BIND_ON_ACQUIRE)
646 continue;
647
648 // Only display items in vendor lists for the team the player is on
649 if ((itemTemplate->HasFlag(ITEM_FLAG2_FACTION_HORDE) && _player->GetTeam() == ALLIANCE) ||
650 (itemTemplate->HasFlag(ITEM_FLAG2_FACTION_ALLIANCE) && _player->GetTeam() == HORDE))
651 continue;
652
653 // Items sold out are not displayed in list
654 if (leftInStock == 0)
655 continue;
656 }
657
658 if (!sConditionMgr->IsObjectMeetingVendorItemConditions(vendor->GetEntry(), vendorItem->item, _player, vendor))
659 {
660 TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry {} item {}", vendor->GetEntry(), vendorItem->item);
661 continue;
662 }
663
664 uint64 price = uint64(floor(itemTemplate->GetBuyPrice() * discountMod));
665 price = itemTemplate->GetBuyPrice() > 0 ? std::max(uint64(1), price) : price;
666
668 price -= CalculatePct(price, priceMod);
669
670 item.MuID = slot + 1; // client expects counting to start at 1
671 item.Durability = itemTemplate->MaxDurability;
672 item.ExtendedCostID = vendorItem->ExtendedCost;
673 item.Type = vendorItem->Type;
674 item.Quantity = leftInStock;
675 item.StackCount = itemTemplate->GetBuyCount();
676 item.Price = price;
677 item.DoNotFilterOnVendor = vendorItem->IgnoreFiltering;
678 item.Refundable = itemTemplate->HasFlag(ITEM_FLAG_ITEM_PURCHASE_RECORD) && vendorItem->ExtendedCost && itemTemplate->GetMaxStackSize() == 1;
679
680 item.Item.ItemID = vendorItem->item;
681 if (!vendorItem->BonusListIDs.empty())
682 {
683 item.Item.ItemBonus.emplace();
684 item.Item.ItemBonus->BonusListIDs = vendorItem->BonusListIDs;
685 }
686 }
687 else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY)
688 {
689 CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item);
690 if (!currencyTemplate)
691 continue;
692
693 if (!vendorItem->ExtendedCost)
694 continue; // there's no price defined for currencies, only extendedcost is used
695
696 item.MuID = slot + 1; // client expects counting to start at 1
697 item.ExtendedCostID = vendorItem->ExtendedCost;
698 item.Item.ItemID = vendorItem->item;
699 item.Type = vendorItem->Type;
700 item.StackCount = vendorItem->maxcount;
701 item.DoNotFilterOnVendor = vendorItem->IgnoreFiltering;
702 }
703 else
704 continue;
705
706 if (++count >= MAX_VENDOR_ITEMS)
707 break;
708 }
709
710 // Resize vector to real size (some items can be skipped due to checks)
711 packet.Items.resize(count);
712
714
715 SendPacket(packet.Write());
716}
717
719{
720 if (!packet.Inv.Items.empty())
721 {
722 TC_LOG_ERROR("network", "HandleAutoStoreBagItemOpcode - Invalid itemCount ({})", packet.Inv.Items.size());
723 return;
724 }
725
726 TC_LOG_DEBUG("network", "HandleAutoStoreBagItemOpcode: receive ContainerSlotA: {}, SlotA: {}, ContainerSlotB: {}",
727 packet.ContainerSlotA, packet.SlotA, packet.ContainerSlotB);
728
729 Item* item = _player->GetItemByPos(packet.ContainerSlotA, packet.SlotA);
730 if (!item)
731 return;
732
733 if (!_player->IsValidPos(packet.ContainerSlotB, NULL_SLOT, false)) // can be autostore pos
734 {
736 return;
737 }
738
739 uint16 src = item->GetPos();
740
741 // check unequip potability for equipped items and bank bags
742 if (_player->IsEquipmentPos(src) || _player->IsBagPos(src))
743 {
745 if (msg != EQUIP_ERR_OK)
746 {
747 _player->SendEquipError(msg, item);
748 return;
749 }
750 }
751
752 ItemPosCountVec dest;
753 InventoryResult msg = _player->CanStoreItem(packet.ContainerSlotB, NULL_SLOT, dest, item, false);
754 if (msg != EQUIP_ERR_OK)
755 {
756 _player->SendEquipError(msg, item);
757 return;
758 }
759
760 // no-op: placed in same slot
761 if (dest.size() == 1 && dest[0].pos == src)
762 {
763 // just remove grey item state
765 return;
766 }
767
768 _player->RemoveItem(packet.ContainerSlotA, packet.SlotA, true);
769 _player->StoreItem(dest, item, true);
770}
771
772void WorldSession::SendEnchantmentLog(ObjectGuid owner, ObjectGuid caster, ObjectGuid itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantSlot)
773{
775 enchantmentLog.Owner = owner;
776 enchantmentLog.Caster = caster;
777 enchantmentLog.ItemGUID = itemGuid;
778 enchantmentLog.ItemID = itemId;
779 enchantmentLog.Enchantment = enchantId;
780 enchantmentLog.EnchantSlot = enchantSlot;
781 GetPlayer()->SendMessageToSet(enchantmentLog.Write(), true);
782}
783
785{
787 data.ItemGuid = Itemguid;
788 data.DurationLeft = Duration;
789 data.Slot = slot;
790 data.OwnerGuid = Playerguid;
791 SendPacket(data.Write());
792}
793
795{
796 if (packet.Inv.Items.size() != 2)
797 {
798 TC_LOG_ERROR("network", "HandleWrapItem - Invalid itemCount ({})", packet.Inv.Items.size());
799 return;
800 }
801
803 // Gift
804 uint8 giftContainerSlot = packet.Inv.Items[0].ContainerSlot;
805 uint8 giftSlot = packet.Inv.Items[0].Slot;
806 // Item
807 uint8 itemContainerSlot = packet.Inv.Items[1].ContainerSlot;
808 uint8 itemSlot = packet.Inv.Items[1].Slot;
809
810 TC_LOG_DEBUG("network", "HandleWrapItem - Receive giftContainerSlot = {}, giftSlot = {}, itemContainerSlot = {}, itemSlot = {}", giftContainerSlot, giftSlot, itemContainerSlot, itemSlot);
811
812 Item* gift = _player->GetItemByPos(giftContainerSlot, giftSlot);
813 if (!gift)
814 {
816 return;
817 }
818
819 if (!gift->GetTemplate()->HasFlag(ITEM_FLAG_IS_WRAPPER)) // cheating: non-wrapper wrapper
820 {
822 return;
823 }
824
825 Item* item = _player->GetItemByPos(itemContainerSlot, itemSlot);
826 if (!item)
827 {
829 return;
830 }
831
832 if (item == gift) // not possable with pacjket from real client
833 {
835 return;
836 }
837
838 if (item->IsEquipped())
839 {
841 return;
842 }
843
844 if (!item->GetGiftCreator().IsEmpty()) // HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED);
845 {
847 return;
848 }
849
850 if (item->IsBag())
851 {
853 return;
854 }
855
856 if (item->IsSoulBound())
857 {
859 return;
860 }
861
862 if (item->GetMaxStackCount() != 1)
863 {
865 return;
866 }
867
868 // maybe not correct check (it is better than nothing)
869 if (item->GetTemplate()->GetMaxCount() > 0)
870 {
872 return;
873 }
874
875 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
876
878 stmt->setUInt64(0, item->GetOwnerGUID().GetCounter());
879 stmt->setUInt64(1, item->GetGUID().GetCounter());
880 stmt->setUInt32(2, item->GetEntry());
881 stmt->setUInt32(3, item->m_itemData->DynamicFlags);
882 trans->Append(stmt);
883
884 item->SetEntry(gift->GetEntry());
885
886 switch (item->GetEntry())
887 {
888 case 5042:
889 item->SetEntry(5043);
890 break;
891 case 5048:
892 item->SetEntry(5044);
893 break;
894 case 17303:
895 item->SetEntry(17302);
896 break;
897 case 17304:
898 item->SetEntry(17305);
899 break;
900 case 17307:
901 item->SetEntry(17308);
902 break;
903 case 21830:
904 item->SetEntry(21831);
905 break;
906 }
907
911
912 if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance`
913 {
914 // after save it will be impossible to remove the item from the queue
916 item->SaveToDB(trans); // item gave inventory record unchanged and can be save standalone
917 }
918 CharacterDatabase.CommitTransaction(trans);
919
920 uint32 count = 1;
921 _player->DestroyItemCount(gift, count, true);
922}
923
925{
926 if (!socketGems.ItemGuid)
927 return;
928
929 //cheat -> tried to socket same gem multiple times
930 if ((!socketGems.GemItem[0].IsEmpty() && (socketGems.GemItem[0] == socketGems.GemItem[1] || socketGems.GemItem[0] == socketGems.GemItem[2])) ||
931 (!socketGems.GemItem[1].IsEmpty() && (socketGems.GemItem[1] == socketGems.GemItem[2])))
932 return;
933
934 Item* itemTarget = _player->GetItemByGuid(socketGems.ItemGuid);
935 if (!itemTarget) //missing item to socket
936 return;
937
938 ItemTemplate const* itemProto = itemTarget->GetTemplate();
939 if (!itemProto)
940 return;
941
942 //this slot is excepted when applying / removing meta gem bonus
943 uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : uint8(NULL_SLOT);
944
945 Item* gems[MAX_GEM_SOCKETS];
946 memset(gems, 0, sizeof(gems));
948 memset(gemData, 0, sizeof(gemData));
949 GemPropertiesEntry const* gemProperties[MAX_GEM_SOCKETS];
950 memset(gemProperties, 0, sizeof(gemProperties));
951 UF::SocketedGem const* oldGemData[MAX_GEM_SOCKETS];
952 memset(oldGemData, 0, sizeof(oldGemData));
953 for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
954 {
955 if (Item* gem = _player->GetItemByGuid(socketGems.GemItem[i]))
956 {
957 gems[i] = gem;
958 gemData[i].ItemId = gem->GetEntry();
959 gemData[i].Context = gem->m_itemData->Context;
960 for (std::size_t b = 0; b < gem->GetBonusListIDs().size() && b < 16; ++b)
961 gemData[i].BonusListIDs[b] = gem->GetBonusListIDs()[b];
962
963 gemProperties[i] = sGemPropertiesStore.LookupEntry(gem->GetTemplate()->GetGemProperties());
964 }
965
966 oldGemData[i] = itemTarget->GetGem(i);
967 }
968
969 // Find first prismatic socket
970 uint32 firstPrismatic = 0;
971 while (firstPrismatic < MAX_GEM_SOCKETS && itemTarget->GetSocketColor(firstPrismatic))
972 ++firstPrismatic;
973
974 for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe
975 {
976 if (!gemProperties[i])
977 continue;
978
979 // tried to put gem in socket where no socket exists (take care about prismatic sockets)
980 if (!itemTarget->GetSocketColor(i))
981 {
982 // no prismatic socket
984 return;
985
986 if (i != firstPrismatic)
987 return;
988 }
989
990 // Gem must match socket color
991 if (SocketColorToGemTypeMask[itemTarget->GetSocketColor(i)] != gemProperties[i]->Type)
992 {
993 // unless its red, blue, yellow or prismatic
994 if (!(SocketColorToGemTypeMask[itemTarget->GetSocketColor(i)] & SOCKET_COLOR_PRISMATIC) || !(gemProperties[i]->Type & SOCKET_COLOR_PRISMATIC))
995 return;
996 }
997 }
998
999 // check unique-equipped conditions
1000 for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
1001 {
1002 if (!gems[i])
1003 continue;
1004
1005 // continue check for case when attempt add 2 similar unique equipped gems in one item.
1006 ItemTemplate const* iGemProto = gems[i]->GetTemplate();
1007
1008 // unique item (for new and already placed bit removed enchantments
1009 if (iGemProto->HasFlag(ITEM_FLAG_UNIQUE_EQUIPPABLE))
1010 {
1011 for (uint32 j = 0; j < MAX_GEM_SOCKETS; ++j)
1012 {
1013 if (i == j) // skip self
1014 continue;
1015
1016 if (gems[j])
1017 {
1018 if (iGemProto->GetId() == gems[j]->GetEntry())
1019 {
1021 return;
1022 }
1023 }
1024 else if (oldGemData[j])
1025 {
1026 if (int32(iGemProto->GetId()) == oldGemData[j]->ItemID)
1027 {
1029 return;
1030 }
1031 }
1032 }
1033 }
1034
1035 // unique limit type item
1036 int32 limit_newcount = 0;
1037 if (iGemProto->GetItemLimitCategory())
1038 {
1039 if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->GetItemLimitCategory()))
1040 {
1041 // NOTE: limitEntry->Flags is not checked because if item has limit then it is applied in equip case
1042 for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
1043 {
1044 if (gems[j])
1045 {
1046 // new gem
1047 if (iGemProto->GetItemLimitCategory() == gems[j]->GetTemplate()->GetItemLimitCategory())
1048 ++limit_newcount;
1049 }
1050 else if (oldGemData[j])
1051 {
1052 // existing gem
1053 if (ItemTemplate const* jProto = sObjectMgr->GetItemTemplate(oldGemData[j]->ItemID))
1054 if (iGemProto->GetItemLimitCategory() == jProto->GetItemLimitCategory())
1055 ++limit_newcount;
1056 }
1057 }
1058
1059 if (limit_newcount > 0 && uint32(limit_newcount) > _player->GetItemLimitCategoryQuantity(limitEntry))
1060 {
1062 return;
1063 }
1064 }
1065 }
1066
1067 // for equipped item check all equipment for duplicate equipped gems
1068 if (itemTarget->IsEquipped())
1069 {
1070 if (InventoryResult res = _player->CanEquipUniqueItem(gems[i], slot, std::max(limit_newcount, 0)))
1071 {
1072 _player->SendEquipError(res, itemTarget, nullptr);
1073 return;
1074 }
1075 }
1076 }
1077
1078 bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus
1079 _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item)
1080
1081 //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
1082
1083 //remove ALL mods - gem can change item level
1084 if (itemTarget->IsEquipped())
1085 _player->_ApplyItemMods(itemTarget, itemTarget->GetSlot(), false);
1086
1087 for (uint16 i = 0; i < MAX_GEM_SOCKETS; ++i)
1088 {
1089 if (gems[i])
1090 {
1091 uint32 gemScalingLevel = _player->GetLevel();
1092 if (uint32 fixedLevel = gems[i]->GetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL))
1093 gemScalingLevel = fixedLevel;
1094
1095 itemTarget->SetGem(i, &gemData[i], gemScalingLevel);
1096
1097 if (gemProperties[i] && gemProperties[i]->EnchantId)
1098 itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT + i), gemProperties[i]->EnchantId, 0, 0, _player->GetGUID());
1099
1100 uint32 gemCount = 1;
1101 _player->DestroyItemCount(gems[i], gemCount, true);
1102 }
1103 }
1104
1105 if (itemTarget->IsEquipped())
1106 _player->_ApplyItemMods(itemTarget, itemTarget->GetSlot(), true);
1107
1108 if (Item* childItem = _player->GetChildItemByGuid(itemTarget->GetChildItem()))
1109 {
1110 if (childItem->IsEquipped())
1111 _player->_ApplyItemMods(childItem, childItem->GetSlot(), false);
1112 childItem->CopyArtifactDataFromParent(itemTarget);
1113 if (childItem->IsEquipped())
1114 _player->_ApplyItemMods(childItem, childItem->GetSlot(), true);
1115 }
1116
1117 bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state
1118 if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change...
1119 {
1120 _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false);
1121 itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->GetSocketBonus() : 0), 0, 0, _player->GetGUID());
1123 //it is not displayed, client has an inbuilt system to determine if the bonus is activated
1124 }
1125
1126 _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item)
1127
1128 _player->RemoveTradeableItem(itemTarget);
1129 itemTarget->ClearSoulboundTradeable(_player); // clear tradeable flag
1130
1131 itemTarget->SendUpdateSockets();
1132}
1133
1135{
1136 // apply only to equipped item
1137 if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, cancelTempEnchantment.Slot))
1138 return;
1139
1140 Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, cancelTempEnchantment.Slot);
1141
1142 if (!item)
1143 return;
1144
1146 return;
1147
1150}
1151
1153{
1154 Item* item = _player->GetItemByGuid(packet.ItemGUID);
1155 if (!item)
1156 {
1157 TC_LOG_DEBUG("network", "HandleGetItemPurchaseData: Item {} not found!", packet.ItemGUID.ToString());
1158 return;
1159 }
1160
1161 TC_LOG_DEBUG("network", "HandleGetItemPurchaseData: Item {}", packet.ItemGUID.ToString());
1162
1163 GetPlayer()->SendRefundInfo(item);
1164}
1165
1167{
1168 Item* item = _player->GetItemByGuid(packet.ItemGUID);
1169 if (!item)
1170 {
1171 TC_LOG_DEBUG("network", "WorldSession::HandleItemRefund: Item ({}) not found!", packet.ItemGUID.ToString());
1172 return;
1173 }
1174
1175 // Don't try to refund item currently being disenchanted
1176 if (_player->GetLootGUID() == packet.ItemGUID)
1177 return;
1178
1179 GetPlayer()->RefundItem(item);
1180}
1181
1183{
1184 // bankerGUID parameter is optional, set to 0 by default.
1185 if (!bankerGUID)
1186 bankerGUID = _player->PlayerTalkClass->GetInteractionData().SourceGuid;
1187
1188 bool isUsingBankCommand = (bankerGUID == GetPlayer()->GetGUID() && bankerGUID == _player->PlayerTalkClass->GetInteractionData().SourceGuid);
1189
1190 if (!isUsingBankCommand)
1191 {
1193 if (!creature)
1194 return false;
1195 }
1196
1197 return true;
1198}
1199
1201{
1202 Item* item = _player->GetItemByGuid(useCritterItem.ItemGuid);
1203 if (!item)
1204 return;
1205
1206 for (ItemEffectEntry const* itemEffect : item->GetEffects())
1207 {
1208 if (itemEffect->TriggerType != ITEM_SPELLTRIGGER_ON_LEARN)
1209 continue;
1210
1211 if (BattlePetSpeciesEntry const* speciesEntry = BattlePets::BattlePetMgr::GetBattlePetSpeciesBySpell(uint32(itemEffect->SpellID)))
1212 GetBattlePetMgr()->AddPet(speciesEntry->ID, BattlePets::BattlePetMgr::SelectPetDisplay(speciesEntry),
1214 }
1215
1216 _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
1217}
1218
1220{
1221 // TODO: Implement sorting
1222 // Placeholder to prevent completely locking out bags clientside
1224}
1225
1227{
1228 // TODO: Implement sorting
1229 // Placeholder to prevent completely locking out bags clientside
1231}
1232
1234{
1235 // TODO: Implement sorting
1236 // Placeholder to prevent completely locking out bags clientside
1238}
1239
1241{
1242 Item* item = _player->GetItemByGuid(removeNewItem.ItemGuid);
1243 if (!item)
1244 {
1245 TC_LOG_DEBUG("network", "WorldSession::HandleRemoveNewItem: Item ({}) not found for {}!", removeNewItem.ItemGuid.ToString(), GetPlayerInfo());
1246 return;
1247 }
1248
1250 {
1253 }
1254}
@ CHAR_INS_CHAR_GIFT
#define sConditionMgr
Definition: ConditionMgr.h:365
@ CREATURE_FLAG_EXTRA_NO_SELL_VENDOR
Definition: CreatureData.h:346
#define MAX_VENDOR_ITEMS
Definition: Creature.h:54
DB2Storage< ItemLimitCategoryEntry > sItemLimitCategoryStore("ItemLimitCategory.db2", &ItemLimitCategoryLoadInfo::Instance)
DB2Storage< CurrencyTypesEntry > sCurrencyTypesStore("CurrencyTypes.db2", &CurrencyTypesLoadInfo::Instance)
DB2Storage< GemPropertiesEntry > sGemPropertiesStore("GemProperties.db2", &GemPropertiesLoadInfo::Instance)
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
EnchantmentSlot
Definition: ItemDefines.h:178
@ TEMP_ENCHANTMENT_SLOT
Definition: ItemDefines.h:180
@ PRISMATIC_ENCHANTMENT_SLOT
Definition: ItemDefines.h:185
@ SOCK_ENCHANTMENT_SLOT
Definition: ItemDefines.h:181
@ BONUS_ENCHANTMENT_SLOT
Definition: ItemDefines.h:184
InventoryResult
Definition: ItemDefines.h:25
@ EQUIP_ERR_CANT_WRAP_BAGS
Definition: ItemDefines.h:75
@ EQUIP_ERR_WRONG_SLOT
Definition: ItemDefines.h:29
@ EQUIP_ERR_DROP_BOUND_ITEM
Definition: ItemDefines.h:50
@ EQUIP_ERR_ITEM_NOT_FOUND
Definition: ItemDefines.h:49
@ EQUIP_ERR_CANT_WRAP_BOUND
Definition: ItemDefines.h:73
@ EQUIP_ERR_OK
Definition: ItemDefines.h:26
@ EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED
Definition: ItemDefines.h:103
@ EQUIP_ERR_INTERNAL_BAG_ERROR
Definition: ItemDefines.h:67
@ EQUIP_ERR_CANT_WRAP_EQUIPPED
Definition: ItemDefines.h:71
@ EQUIP_ERR_CANT_WRAP_STACKABLE
Definition: ItemDefines.h:70
@ EQUIP_ERR_CANT_WRAP_WRAPPED
Definition: ItemDefines.h:72
@ EQUIP_ERR_CANT_WRAP_UNIQUE
Definition: ItemDefines.h:74
@ BUY_ERR_CANT_FIND_ITEM
Definition: ItemDefines.h:150
@ BUY_ERR_NOT_ENOUGHT_MONEY
Definition: ItemDefines.h:152
@ ITEM_MODIFIER_TIMEWALKER_LEVEL
Definition: ItemDefines.h:220
@ SELL_ERR_CANT_FIND_VENDOR
Definition: ItemDefines.h:166
@ SELL_ERR_CANT_SELL_TO_THIS_MERCHANT
Definition: ItemDefines.h:170
@ SELL_ERR_CANT_FIND_ITEM
Definition: ItemDefines.h:164
@ SELL_ERR_CANT_SELL_ITEM
Definition: ItemDefines.h:165
@ ITEM_VENDOR_TYPE_ITEM
Definition: ItemDefines.h:203
@ ITEM_VENDOR_TYPE_CURRENCY
Definition: ItemDefines.h:204
int32 const SocketColorToGemTypeMask[26]
@ ITEM_FLAG2_FACTION_HORDE
Definition: ItemTemplate.h:212
@ ITEM_FLAG2_FACTION_ALLIANCE
Definition: ItemTemplate.h:213
@ ITEM_FIELD_FLAG_NEW_ITEM
Definition: ItemTemplate.h:152
@ ITEM_FIELD_FLAG_CHILD
Definition: ItemTemplate.h:150
@ ITEM_FIELD_FLAG_WRAPPED
Definition: ItemTemplate.h:134
@ ITEM_SPELLTRIGGER_ON_LEARN
Definition: ItemTemplate.h:110
@ ITEM_FLAG_IS_WRAPPER
Definition: ItemTemplate.h:185
@ ITEM_FLAG_NO_USER_DESTROY
Definition: ItemTemplate.h:181
@ ITEM_FLAG_UNIQUE_EQUIPPABLE
Definition: ItemTemplate.h:195
@ ITEM_FLAG_ITEM_PURCHASE_RECORD
Definition: ItemTemplate.h:188
@ SOCKET_COLOR_PRISMATIC
Definition: ItemTemplate.h:352
@ BIND_ON_ACQUIRE
Definition: ItemTemplate.h:117
void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition: Item.cpp:1218
#define MAX_GEM_SOCKETS
Definition: Item.h:48
@ ITEM_CHANGED
Definition: Item.h:55
@ ITEM_NEW
Definition: Item.h:56
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::vector< ItemPosCount > ItemPosCountVec
Definition: Player.h:750
@ INVENTORY_SLOT_BAG_END
Definition: Player.h:676
@ BUYBACK_SLOT_START
Definition: Player.h:706
#define INVENTORY_SLOT_BAG_0
Definition: Player.h:625
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
@ ALLIANCE
@ HORDE
@ SPELL_AURA_MOD_VENDOR_ITEMS_PRICES
@ SPELL_AURA_FEIGN_DEATH
@ UNIT_NPC_FLAG_BANKER
Definition: UnitDefines.h:314
@ UNIT_NPC_FLAG_VENDOR
Definition: UnitDefines.h:304
@ UNIT_NPC_FLAG_2_NONE
Definition: UnitDefines.h:336
@ UNIT_STATE_DIED
Definition: Unit.h:255
@ NULL_BAG
Definition: Unit.h:62
@ NULL_SLOT
Definition: Unit.h:63
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
T CalculatePct(T base, U pct)
Definition: Util.h:72
static uint16 RollPetBreed(uint32 species)
static uint32 SelectPetDisplay(BattlePetSpeciesEntry const *speciesEntry)
static BattlePetSpeciesEntry const * GetBattlePetSpeciesBySpell(uint32 spellId)
void AddPet(uint32 species, uint32 display, uint16 breed, BattlePetBreedQuality quality, uint16 level=1)
static BattlePetBreedQuality GetDefaultPetQuality(uint32 species)
static bool IsPlayerMeetingCondition(Player const *player, PlayerConditionEntry const *condition)
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:371
VendorItemData const * GetVendorItems() const
Definition: Creature.cpp:3184
CreatureTemplate const * GetCreatureTemplate() const
Definition: Creature.h:250
uint32 GetVendorItemCurrentCount(VendorItem const *vItem)
Definition: Creature.cpp:3189
CreatureMovementData const & GetMovementTemplate() const
Definition: Creature.cpp:2939
Definition: Item.h:170
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition: Item.cpp:1166
uint8 GetSlot() const
Definition: Item.h:280
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition: Item.cpp:561
void ReplaceAllItemFlags(ItemFieldFlags flags)
Definition: Item.h:211
void RemoveItemFlag(ItemFieldFlags flags)
Definition: Item.h:210
Trinity::IteratorPair< ItemEffectEntry const *const * > GetEffects() const
Definition: Item.h:354
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition: Item.h:298
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition: Item.cpp:1655
UF::SocketedGem const * GetGem(uint16 slot) const
Definition: Item.cpp:1481
void SetCount(uint32 value)
Definition: Item.cpp:1275
ObjectGuid GetCreator() const
Definition: Item.h:192
ItemTemplate const * GetTemplate() const
Definition: Item.cpp:1141
void SetGem(uint16 slot, ItemDynamicFieldGems const *gem, uint32 gemScalingLevel)
Definition: Item.cpp:1487
bool IsSoulBound() const
Definition: Item.h:218
ItemUpdateState GetState() const
Definition: Item.h:322
bool HasItemFlag(ItemFieldFlags flag) const
Definition: Item.h:208
bool IsEquipped() const
Definition: Item.cpp:1244
SocketColor GetSocketColor(uint32 index) const
Definition: Item.h:344
ObjectGuid GetOwnerGUID() const
Definition: Item.h:188
bool IsRefundable() const
Definition: Item.h:248
uint16 GetPos() const
Definition: Item.h:284
bool GemsFitSockets() const
Definition: Item.cpp:1544
ObjectGuid GetGiftCreator() const
Definition: Item.h:194
bool IsBag() const
Definition: Item.h:252
void ClearEnchantment(EnchantmentSlot slot)
Definition: Item.cpp:1468
void SendUpdateSockets()
Definition: Item.cpp:1603
void ClearSoulboundTradeable(Player *currentOwner)
Definition: Item.cpp:1913
bool IsNotEmptyBag() const
Definition: Item.cpp:535
uint32 GetCount() const
Definition: Item.h:273
uint8 GetBagSlot() const
Definition: Item.cpp:1239
ObjectGuid GetChildItem() const
Definition: Item.h:423
uint32 GetMaxStackCount() const
Definition: Item.h:275
void SetGiftCreator(ObjectGuid guid)
Definition: Item.h:195
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster=ObjectGuid::Empty)
Definition: Item.cpp:1421
UF::UpdateField< UF::ItemData, 0, TYPEID_ITEM > m_itemData
Definition: Item.h:449
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
bool IsInWorld() const
Definition: Object.h:154
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void SetEntry(uint32 entry)
Definition: Object.h:162
void SendUpdateToPlayer(Player *player)
Definition: Object.cpp:183
bool IsValidPos(uint16 pos, bool explicit_pos) const
Definition: Player.h:1374
void SendEquipError(InventoryResult msg, Item const *item1=nullptr, Item const *item2=nullptr, uint32 itemId=0) const
Definition: Player.cpp:13254
void ItemRemovedQuestCheck(uint32 entry, uint32 count)
Definition: Player.cpp:16645
static bool IsEquipmentPos(uint16 pos)
Definition: Player.h:1365
InventoryResult CanUnequipItem(uint16 src, bool swap) const
Definition: Player.cpp:11127
void ToggleMetaGemsActive(uint8 exceptslot, bool apply)
Definition: Player.cpp:23527
bool ModifyMoney(int64 amount, bool sendError=true)
Definition: Player.cpp:24098
void AutoUnequipChildItem(Item *parentItem)
Definition: Player.cpp:11948
InventoryResult CanEquipItem(uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading=true) const
Definition: Player.cpp:10896
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Definition: Player.cpp:1947
Item * BankItem(ItemPosCountVec const &dest, Item *pItem, bool update)
Definition: Player.cpp:12043
void SplitItem(uint16 src, uint16 dst, uint32 count)
Definition: Player.cpp:12647
InventoryResult CanEquipUniqueItem(Item *pItem, uint8 except_slot=NULL_SLOT, uint32 limit_count=1) const
Definition: Player.cpp:26613
InventoryResult CanEquipChildItem(Item *parentItem) const
Definition: Player.cpp:11087
Item * GetChildItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9695
InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap=false) const
Definition: Player.cpp:10037
void _ApplyItemMods(Item *item, uint8 slot, bool apply, bool updateItemAuras=true)
Definition: Player.cpp:7865
uint8 GetItemLimitCategoryQuantity(ItemLimitCategoryEntry const *limitEntry) const
Definition: Player.cpp:29878
void RemoveItemFromBuyBackSlot(uint32 slot, bool del)
Definition: Player.cpp:13221
float GetReputationPriceDiscount(Creature const *creature) const
Definition: Player.cpp:25133
ObjectGuid const & GetLootGUID() const
Definition: Player.h:2091
void ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool apply_dur=true, bool ignore_condition=false)
Definition: Player.cpp:13577
InventoryResult CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap, bool not_loading=true, bool reagentBankOnly=false) const
Definition: Player.cpp:11172
void AddItemToBuyBackSlot(Item *pItem)
Definition: Player.cpp:13156
void SendSellError(SellResult msg, Creature *creature, ObjectGuid guid) const
Definition: Player.cpp:13309
void SwapItem(uint16 src, uint16 dst)
Definition: Player.cpp:12763
bool BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot)
Definition: Player.cpp:23034
void ApplyItemDependentAuras(Item *item, bool apply)
Definition: Player.cpp:8299
void RemoveTradeableItem(Item *item)
Definition: Player.cpp:13414
Item * StoreItem(ItemPosCountVec const &pos, Item *pItem, bool update)
Definition: Player.cpp:11612
void EquipChildItem(uint8 parentBag, uint8 parentSlot, Item *parentItem)
Definition: Player.cpp:11870
Item * GetItemByPos(uint16 pos) const
Definition: Player.cpp:9582
void DestroyItem(uint8 bag, uint8 slot, bool update)
Definition: Player.cpp:12180
static bool IsInventoryPos(uint16 pos)
Definition: Player.h:1363
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition: Player.cpp:26767
uint32 DestroyItemCount(uint32 item, uint32 count, bool update, bool unequip_check=false)
Definition: Player.cpp:12281
void SendBuyError(BuyResult msg, Creature *creature, uint32 item, uint32 param) const
Definition: Player.cpp:13300
void SendRefundInfo(Item *item)
Definition: Player.cpp:28583
void AutoUnequipOffhandIfNeed(bool force=false)
Definition: Player.cpp:25403
void ItemAddedQuestCheck(uint32 entry, uint32 count, Optional< bool > boundItemFlagRequirement={}, bool *hadBoundItemObjective=nullptr)
Definition: Player.cpp:16624
bool IsGameMaster() const
Definition: Player.h:1178
Item * EquipItem(uint16 pos, Item *pItem, bool update)
Definition: Player.cpp:11754
static bool IsBagPos(uint16 pos)
Definition: Player.cpp:9766
Item * GetItemFromBuyBackSlot(uint32 slot)
Definition: Player.cpp:13212
UF::UpdateField< UF::ActivePlayerData, 0, TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition: Player.h:2864
bool BuyCurrencyFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorSlot, uint32 currency, uint32 count)
Definition: Player.cpp:22879
static bool IsBankPos(uint16 pos)
Definition: Player.h:1368
void RemoveItem(uint8 bag, uint8 slot, bool update)
Definition: Player.cpp:12048
void RefundItem(Item *item)
Definition: Player.cpp:28880
void SendMessageToSet(WorldPacket const *data, bool self) const override
Definition: Player.h:2151
Item * GetItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9566
std::unique_ptr< PlayerMenu > PlayerTalkClass
Definition: Player.h:2380
Team GetTeam() const
Definition: Player.h:2235
bool HasEnoughMoney(uint64 amount) const
Definition: Player.h:1740
InventoryResult CanUseItem(Item *pItem, bool not_loading=true) const
Definition: Player.cpp:11381
void setUInt32(const uint8 index, const uint32 value)
void setUInt64(const uint8 index, const uint64 value)
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3812
uint32 GetClassMask() const
Definition: Unit.h:754
void PauseMovement(uint32 timer=0, uint8 slot=0, bool forced=true)
Definition: Unit.cpp:10064
int32 GetTotalAuraModifier(AuraType auraType) const
Definition: Unit.cpp:4929
uint8 GetLevel() const
Definition: Unit.h:746
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::array< ObjectGuid, MAX_ITEM_PROTO_SOCKETS > GemItem
Definition: ItemPackets.h:477
WorldPacket const * Write() override
Definition: NPCPackets.cpp:150
std::vector< VendorItem > Items
Definition: NPCPackets.h:183
void HandleReadItem(WorldPackets::Item::ReadItem &readItem)
void HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem &autoEquipItem)
void HandleSplitItemOpcode(WorldPackets::Item::SplitItem &splitItem)
Definition: ItemHandler.cpp:33
void HandleCancelTempEnchantmentOpcode(WorldPackets::Item::CancelTempEnchantment &cancelTempEnchantment)
void HandleBuybackItem(WorldPackets::Item::BuyBackItem &packet)
void HandleGetItemPurchaseData(WorldPackets::Item::GetItemPurchaseData &packet)
void HandleSortBags(WorldPackets::Item::SortBags &sortBags)
std::string GetPlayerInfo() const
void HandleAutoStoreBagItemOpcode(WorldPackets::Item::AutoStoreBagItem &packet)
Player * GetPlayer() const
void HandleSortBankBags(WorldPackets::Item::SortBankBags &sortBankBags)
void HandleUseCritterItem(WorldPackets::Item::UseCritterItem &packet)
void SendItemEnchantTimeUpdate(ObjectGuid Playerguid, ObjectGuid Itemguid, uint32 slot, uint32 Duration)
void HandleSwapInvItemOpcode(WorldPackets::Item::SwapInvItem &swapInvItem)
Definition: ItemHandler.cpp:69
void HandleRemoveNewItem(WorldPackets::Item::RemoveNewItem &removeNewItem)
void HandleSocketGems(WorldPackets::Item::SocketGems &socketGems)
void HandleDestroyItemOpcode(WorldPackets::Item::DestroyItem &destroyItem)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
Player * _player
void HandleSellItemOpcode(WorldPackets::Item::SellItem &packet)
void SendListInventory(ObjectGuid guid)
void HandleSwapItem(WorldPackets::Item::SwapItem &swapItem)
void HandleWrapItem(WorldPackets::Item::WrapItem &packet)
void HandleSortReagentBankBags(WorldPackets::Item::SortReagentBankBags &sortReagentBankBags)
bool CanUseBank(ObjectGuid bankerGUID=ObjectGuid::Empty) const
void HandleAutoEquipItemSlotOpcode(WorldPackets::Item::AutoEquipItemSlot &autoEquipItemSlot)
void HandleListInventoryOpcode(WorldPackets::NPC::Hello &packet)
void HandleBuyItemOpcode(WorldPackets::Item::BuyItem &packet)
void HandleItemRefund(WorldPackets::Item::ItemPurchaseRefund &packet)
BattlePets::BattlePetMgr * GetBattlePetMgr() const
void SendEnchantmentLog(ObjectGuid owner, ObjectGuid caster, ObjectGuid itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantSlot)
constexpr std::size_t size()
Definition: UpdateField.h:796
uint32 GetInteractionPauseTimer() const
Definition: CreatureData.h:407
uint32 GetBuyCount() const
Definition: ItemTemplate.h:783
int32 GetAllowableClass() const
Definition: ItemTemplate.h:787
uint32 GetPageText() const
Definition: ItemTemplate.h:808
uint32 GetId() const
Definition: ItemTemplate.h:776
uint32 GetMaxStackSize() const
Definition: ItemTemplate.h:847
uint32 GetBuyPrice() const
Definition: ItemTemplate.h:784
ItemBondingType GetBonding() const
Definition: ItemTemplate.h:806
uint32 GetItemLimitCategory() const
Definition: ItemTemplate.h:821
bool HasFlag(ItemFlags flag) const
Definition: ItemTemplate.h:871
uint32 GetSellPrice() const
Definition: ItemTemplate.h:785
uint32 MaxDurability
Definition: ItemTemplate.h:827
uint32 GetSocketBonus() const
Definition: ItemTemplate.h:817
uint32 GetMaxCount() const
Definition: ItemTemplate.h:796
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
UpdateField< int32, 0, 1 > ItemID
Definition: UpdateFields.h:109
uint32 GetItemCount() const
Definition: CreatureData.h:677
VendorItem const * GetItem(uint32 slot) const
Definition: CreatureData.h:669
uint32 ExtendedCost
Definition: CreatureData.h:658
bool IgnoreFiltering
Definition: CreatureData.h:662
uint32 PlayerConditionId
Definition: CreatureData.h:661
uint32 item
Definition: CreatureData.h:655
uint32 maxcount
Definition: CreatureData.h:656
std::vector< int32 > BonusListIDs
Definition: CreatureData.h:660
std::vector< InvItem > Items
Optional< ItemBonuses > ItemBonus
WorldPackets::Item::ItemInstance Item
Definition: NPCPackets.h:163