TrinityCore
Loading...
Searching...
No Matches
Item.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 "Item.h"
19#include "Bag.h"
20#include "Common.h"
21#include "ConditionMgr.h"
22#include "DatabaseEnv.h"
23#include "DBCStores.h"
24#include "GameTime.h"
25#include "ItemEnchantmentMgr.h"
26#include "Log.h"
27#include "LootItemStorage.h"
28#include "Map.h"
29#include "ObjectAccessor.h"
30#include "ObjectMgr.h"
31#include "ScriptMgr.h"
32#include "SpellInfo.h"
33#include "SpellMgr.h"
34#include "StringConvert.h"
35#include "Player.h"
36#include "TradeData.h"
37#include "UpdateData.h"
38#include "World.h"
39#include "WorldPacket.h"
40#include "WorldSession.h"
41
42void AddItemsSetItem(Player* player, Item* item)
43{
44 ItemTemplate const* proto = item->GetTemplate();
45 uint32 setid = proto->ItemSet;
46
47 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
48
49 if (!set)
50 {
51 TC_LOG_ERROR("sql.sql", "Item set {} for item (id {}) not found, mods not applied.", setid, proto->ItemId);
52 return;
53 }
54
55 if (set->RequiredSkill && player->GetSkillValue(set->RequiredSkill) < set->RequiredSkillRank)
56 return;
57
58 ItemSetEffect* eff = nullptr;
59
60 for (size_t x = 0; x < player->ItemSetEff.size(); ++x)
61 {
62 if (player->ItemSetEff[x] && player->ItemSetEff[x]->setid == setid)
63 {
64 eff = player->ItemSetEff[x];
65 break;
66 }
67 }
68
69 if (!eff)
70 {
71 eff = new ItemSetEffect();
72 eff->setid = setid;
73
74 size_t x = 0;
75 for (; x < player->ItemSetEff.size(); ++x)
76 if (!player->ItemSetEff[x])
77 break;
78
79 if (x < player->ItemSetEff.size())
80 player->ItemSetEff[x]=eff;
81 else
82 player->ItemSetEff.push_back(eff);
83 }
84
85 ++eff->item_count;
86
87 for (uint32 x = 0; x < MAX_ITEM_SET_SPELLS; ++x)
88 {
89 if (!set->SetSpellID[x])
90 continue;
91 //not enough for spell
92 if (set->SetThreshold[x] > eff->item_count)
93 continue;
94
95 uint32 z = 0;
96 for (; z < MAX_ITEM_SET_SPELLS; ++z)
97 if (eff->spells[z] && eff->spells[z]->Id == set->SetSpellID[x])
98 break;
99
100 if (z < MAX_ITEM_SET_SPELLS)
101 continue;
102
103 //new spell
104 for (uint32 y = 0; y < MAX_ITEM_SET_SPELLS; ++y)
105 {
106 if (!eff->spells[y]) // free slot
107 {
108 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(set->SetSpellID[x]);
109 if (!spellInfo)
110 {
111 TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id {} in items set {} effects", set->SetSpellID[x], setid);
112 break;
113 }
114
115 // spell cast only if fit form requirement, in other case will cast at form change
116 player->ApplyEquipSpell(spellInfo, nullptr, true);
117 eff->spells[y] = spellInfo;
118 break;
119 }
120 }
121 }
122}
123
124void RemoveItemsSetItem(Player*player, ItemTemplate const* proto)
125{
126 uint32 setid = proto->ItemSet;
127
128 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
129
130 if (!set)
131 {
132 TC_LOG_ERROR("sql.sql", "Item set #{} for item #{} not found, mods not removed.", setid, proto->ItemId);
133 return;
134 }
135
136 ItemSetEffect* eff = nullptr;
137 size_t setindex = 0;
138 for (; setindex < player->ItemSetEff.size(); setindex++)
139 {
140 if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->setid == setid)
141 {
142 eff = player->ItemSetEff[setindex];
143 break;
144 }
145 }
146
147 // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
148 if (!eff)
149 return;
150
151 --eff->item_count;
152
153 for (uint32 x = 0; x < MAX_ITEM_SET_SPELLS; x++)
154 {
155 if (!set->SetSpellID[x])
156 continue;
157
158 // enough for spell
159 if (set->SetThreshold[x] <= eff->item_count)
160 continue;
161
162 for (uint32 z = 0; z < MAX_ITEM_SET_SPELLS; z++)
163 {
164 if (eff->spells[z] && eff->spells[z]->Id == set->SetSpellID[x])
165 {
166 // spell can be not active if not fit form requirement
167 player->ApplyEquipSpell(eff->spells[z], nullptr, false);
168 eff->spells[z]=nullptr;
169 break;
170 }
171 }
172 }
173
174 if (!eff->item_count) //all items of a set were removed
175 {
176 ASSERT(eff == player->ItemSetEff[setindex]);
177 delete eff;
178 player->ItemSetEff[setindex] = nullptr;
179 }
180}
181
182bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
183{
184 if (!pProto || !pBagProto)
185 return false;
186
187 switch (pBagProto->Class)
188 {
190 switch (pBagProto->SubClass)
191 {
193 return true;
195 if (!(pProto->BagFamily & BAG_FAMILY_MASK_SOUL_SHARDS))
196 return false;
197 return true;
199 if (!(pProto->BagFamily & BAG_FAMILY_MASK_HERBS))
200 return false;
201 return true;
204 return false;
205 return true;
207 if (!(pProto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
208 return false;
209 return true;
212 return false;
213 return true;
215 if (!(pProto->BagFamily & BAG_FAMILY_MASK_GEMS))
216 return false;
217 return true;
220 return false;
221 return true;
224 return false;
225 return true;
226 default:
227 return false;
228 }
230 switch (pBagProto->SubClass)
231 {
233 if (!(pProto->BagFamily & BAG_FAMILY_MASK_ARROWS))
234 return false;
235 return true;
237 if (!(pProto->BagFamily & BAG_FAMILY_MASK_BULLETS))
238 return false;
239 return true;
240 default:
241 return false;
242 }
243 }
244 return false;
245}
246
266
267bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, Player const* owner)
268{
269 Object::_Create(ObjectGuid::Create<HighGuid::Item>(guidlow));
270
271 SetEntry(itemId);
272 SetObjectScale(1.0f);
273
274 if (owner)
275 {
276 SetOwnerGUID(owner->GetGUID());
278 }
279
280 ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemId);
281 if (!itemProto)
282 return false;
283
287
288 for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
289 SetSpellCharges(i, itemProto->Effects[i].Charges);
290
293 return true;
294}
295
296// Returns true if Item is a bag AND it is not empty.
297// Returns false if Item is not a bag OR it is an empty bag.
299{
300 if (Bag const* bag = ToBag())
301 return !bag->IsEmpty();
302 return false;
303}
304
306{
308 return;
309
310 TC_LOG_DEBUG("entities.player.items", "Item::UpdateDuration Item (Entry: {} Duration {} Diff {})", GetEntry(), GetUInt32Value(ITEM_FIELD_DURATION), diff);
311
313 {
314 sScriptMgr->OnItemExpire(owner, GetTemplate());
315 owner->DestroyItem(GetBagSlot(), GetSlot(), true);
316 return;
317 }
318
320 SetState(ITEM_CHANGED, owner); // save new time in database
321}
322
324{
325 bool isInTransaction = bool(trans);
326 if (!isInTransaction)
327 trans = CharacterDatabase.BeginTransaction();
328
329 switch (uState)
330 {
331 case ITEM_NEW:
332 case ITEM_CHANGED:
333 {
334 uint8 index = 0;
336 stmt->setUInt32( index, GetEntry());
337 stmt->setUInt32(++index, GetOwnerGUID().GetCounter());
340 stmt->setUInt32(++index, GetCount());
342
343 std::ostringstream ssSpells;
344 for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
345 ssSpells << GetSpellCharges(i) << ' ';
346 stmt->setString(++index, ssSpells.str());
347
349
350 std::ostringstream ssEnchants;
351 for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
352 {
353 ssEnchants << GetEnchantmentId(EnchantmentSlot(i)) << ' ';
354 ssEnchants << GetEnchantmentDuration(EnchantmentSlot(i)) << ' ';
355 ssEnchants << GetEnchantmentCharges(EnchantmentSlot(i)) << ' ';
356 }
357 stmt->setString(++index, ssEnchants.str());
358
359 stmt->setInt16 (++index, GetItemRandomPropertyId());
362 stmt->setString(++index, m_text);
363 stmt->setUInt32(++index, GetGUID().GetCounter());
364
365 trans->Append(stmt);
366
367 if ((uState == ITEM_CHANGED) && IsWrapped())
368 {
369 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GIFT_OWNER);
370 stmt->setUInt32(0, GetOwnerGUID().GetCounter());
371 stmt->setUInt32(1, GetGUID().GetCounter());
372 trans->Append(stmt);
373 }
374 break;
375 }
376 case ITEM_REMOVED:
377 {
379 stmt->setUInt32(0, GetGUID().GetCounter());
380 trans->Append(stmt);
381
382 if (IsWrapped())
383 {
384 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
385 stmt->setUInt32(0, GetGUID().GetCounter());
386 trans->Append(stmt);
387 }
388
389 if (!isInTransaction)
390 CharacterDatabase.CommitTransaction(trans);
391
392 // Delete the items if this is a container
393 if (!loot.isLooted())
394 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
395
396 delete this;
397 return;
398 }
399 case ITEM_UNCHANGED:
400 break;
401 }
402
404
405 if (!isInTransaction)
406 CharacterDatabase.CommitTransaction(trans);
407}
408
409bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fields, uint32 entry)
410{
411 // 0 1 2 3 4 5 6 7 8 9 10
412 //result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text FROM item_instance WHERE guid = '{}'", guid);
413
414 // create item before any checks for store correct guid
415 // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
416 Object::_Create(ObjectGuid::Create<HighGuid::Item>(guid));
417
418 // Set entry, MUST be before proto check
419 SetEntry(entry);
420 SetObjectScale(1.0f);
421
422 ItemTemplate const* proto = GetTemplate();
423 if (!proto)
424 {
425 TC_LOG_ERROR("entities.item", "Invalid entry {} for item {}. Refusing to load.", GetEntry(), GetGUID().ToString());
426 return false;
427 }
428
429 // set owner (not if item is only loaded for gbank/auction/mail
430 if (!owner_guid.IsEmpty())
431 SetOwnerGUID(owner_guid);
432
433 bool need_save = false; // need explicit save data at load fixes
434 if (uint32 creator = fields[0].GetUInt32())
435 SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid::Create<HighGuid::Player>(creator));
436 if (uint32 giftCreator = fields[1].GetUInt32())
437 SetGuidValue(ITEM_FIELD_GIFTCREATOR, ObjectGuid::Create<HighGuid::Player>(giftCreator));
438 SetCount(fields[2].GetUInt32());
439
440 uint32 duration = fields[3].GetUInt32();
442 // update duration if need, and remove if not need
443 if ((proto->Duration == 0) != (duration == 0))
444 {
446 need_save = true;
447 }
448
449 std::vector<std::string_view> tokens = Trinity::Tokenize(fields[4].GetStringView(), ' ', false);
450 if (tokens.size() == MAX_ITEM_PROTO_SPELLS)
451 {
452 for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
453 {
454 if (Optional<int32> charges = Trinity::StringTo<int32>(tokens[i]))
455 SetSpellCharges(i, *charges);
456 else
457 TC_LOG_ERROR("entities.item", "Invalid charge info '{}' for item {}, charge data not loaded.", tokens[i], GetGUID());
458 }
459 }
460
461 SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32());
462 // Remove bind flag for items vs NO_BIND set
463 if (IsSoulBound() && proto->Bonding == NO_BIND)
464 {
466 need_save = true;
467 }
468
470 TC_LOG_WARN("entities.item", "Invalid enchantment data '{}' for item {}. Forcing partial load.", fields[6].GetString(), GetGUID().ToString());
471
472 SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, fields[7].GetInt16());
473 // recalculate suffix factor
474 if (GetItemRandomPropertyId() < 0)
476
477 uint32 durability = fields[8].GetUInt16();
479 // update max durability (and durability) if need
481
482 // do not overwrite durability for wrapped items
483 if (durability > proto->MaxDurability && !IsWrapped())
484 {
486 need_save = true;
487 }
488
489 SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, fields[9].GetUInt32());
490 SetText(fields[10].GetString());
491
492 if (need_save) // normal item changed state set not work at loading
493 {
498 stmt->setUInt32(3, guid);
499 CharacterDatabase.Execute(stmt);
500 }
501
502 return true;
503}
504
505/*static*/
507{
509 stmt->setUInt32(0, itemGuid);
510 trans->Append(stmt);
511}
512
514{
515 DeleteFromDB(trans, GetGUID().GetCounter());
516
517 // Delete the items if this is a container
518 if (!loot.isLooted())
519 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
520}
521
522/*static*/
524{
526 stmt->setUInt32(0, itemGuid);
527 trans->Append(stmt);
528}
529
534
536{
537 return sObjectMgr->GetItemTemplate(GetEntry());
538}
539
544
545// Just a "legacy shortcut" for proto->GetSkill()
547{
548 ItemTemplate const* proto = GetTemplate();
549 return proto->GetSkill();
550}
551
553{
554 ItemTemplate const* proto = GetTemplate();
555
556 switch (proto->Class)
557 {
559 switch (proto->SubClass)
560 {
561 case ITEM_SUBCLASS_WEAPON_AXE: return 196;
562 case ITEM_SUBCLASS_WEAPON_AXE2: return 197;
563 case ITEM_SUBCLASS_WEAPON_BOW: return 264;
564 case ITEM_SUBCLASS_WEAPON_GUN: return 266;
565 case ITEM_SUBCLASS_WEAPON_MACE: return 198;
566 case ITEM_SUBCLASS_WEAPON_MACE2: return 199;
567 case ITEM_SUBCLASS_WEAPON_POLEARM: return 200;
568 case ITEM_SUBCLASS_WEAPON_SWORD: return 201;
569 case ITEM_SUBCLASS_WEAPON_SWORD2: return 202;
570 case ITEM_SUBCLASS_WEAPON_STAFF: return 227;
571 case ITEM_SUBCLASS_WEAPON_DAGGER: return 1180;
572 case ITEM_SUBCLASS_WEAPON_THROWN: return 2567;
573 case ITEM_SUBCLASS_WEAPON_SPEAR: return 3386;
574 case ITEM_SUBCLASS_WEAPON_CROSSBOW:return 5011;
575 case ITEM_SUBCLASS_WEAPON_WAND: return 5009;
576 default: return 0;
577 }
578 case ITEM_CLASS_ARMOR:
579 switch (proto->SubClass)
580 {
581 case ITEM_SUBCLASS_ARMOR_CLOTH: return 9078;
582 case ITEM_SUBCLASS_ARMOR_LEATHER: return 9077;
583 case ITEM_SUBCLASS_ARMOR_MAIL: return 8737;
584 case ITEM_SUBCLASS_ARMOR_PLATE: return 750;
585 case ITEM_SUBCLASS_ARMOR_SHIELD: return 9116;
586 default: return 0;
587 }
588 }
589 return 0;
590}
591
593{
594 if (!randomPropId)
595 return;
596
597 if (randomPropId > 0)
598 {
599 ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropId);
600 if (item_rand)
601 {
603 {
606 }
609 }
610 }
611 else
612 {
613 ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(-randomPropId);
614 if (item_rand)
615 {
618 {
622 }
623
626 }
627 }
628}
629
631{
632 uint32 suffixFactor = GenerateEnchSuffixFactor(GetEntry());
633 if (GetItemSuffixFactor() == suffixFactor)
634 return;
636}
637
638void Item::SetState(ItemUpdateState state, Player* forplayer)
639{
640 if (uState == ITEM_NEW && state == ITEM_REMOVED)
641 {
642 // pretend the item never existed
643 if (forplayer)
644 {
645 RemoveItemFromUpdateQueueOf(this, forplayer);
646 forplayer->DeleteRefundReference(GetGUID());
647 }
648 delete this;
649 return;
650 }
651 if (state != ITEM_UNCHANGED)
652 {
653 // new items must stay in new state until saved
654 if (uState != ITEM_NEW)
655 uState = state;
656
657 if (forplayer)
658 AddItemToUpdateQueueOf(this, forplayer);
659 }
660 else
661 {
662 // unset in queue
663 // the item must be removed from the queue manually
664 uQueuePos = -1;
666 }
667}
668
670{
671 if (item->IsInUpdateQueue())
672 return;
673
674 ASSERT(player != nullptr);
675
676 if (player->GetGUID() != item->GetOwnerGUID())
677 {
678 TC_LOG_DEBUG("entities.player.items", "AddItemToUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
679 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
680 return;
681 }
682
683 if (player->m_itemUpdateQueueBlocked)
684 return;
685
686 player->m_itemUpdateQueue.push_back(item);
687 item->uQueuePos = player->m_itemUpdateQueue.size() - 1;
688}
689
691{
692 if (!item->IsInUpdateQueue())
693 return;
694
695 ASSERT(player != nullptr);
696
697 if (player->GetGUID() != item->GetOwnerGUID())
698 {
699 TC_LOG_DEBUG("entities.player.items", "RemoveItemFromUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
700 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
701 return;
702 }
703
704 if (player->m_itemUpdateQueueBlocked)
705 return;
706
707 player->m_itemUpdateQueue[item->uQueuePos] = nullptr;
708 item->uQueuePos = -1;
709}
710
715
717{
718 return !IsInBag() && m_slot < EQUIPMENT_SLOT_END;
719}
720
721bool Item::CanBeTraded(bool mail, bool trade) const
722{
723 if (m_lootGenerated)
724 return false;
725
726 if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!IsBOPTradeable() || !trade)))
727 return false;
728
729 if (IsBag() && (Player::IsBagPos(GetPos()) || !ToBag()->IsEmpty()))
730 return false;
731
732 if (Player* owner = GetOwner())
733 {
734 if (owner->CanUnequipItem(GetPos(), false) != EQUIP_ERR_OK)
735 return false;
736 if (owner->GetLootGUID() == GetGUID())
737 return false;
738 }
739
740 if (IsBoundByEnchant())
741 return false;
742
743 return true;
744}
745
747{
749 if (!maxDurability)
750 return 0;
751
753 ASSERT(maxDurability >= curDurability);
754
755 uint32 lostDurability = maxDurability - curDurability;
756 if (!lostDurability)
757 return 0;
758
759 ItemTemplate const* itemTemplate = GetTemplate();
760
761 DurabilityCostsEntry const* durabilityCost = sDurabilityCostsStore.LookupEntry(itemTemplate->ItemLevel);
762 if (!durabilityCost)
763 return 0;
764
765 uint32 durabilityQualityEntryId = (itemTemplate->Quality + 1) * 2;
766 DurabilityQualityEntry const* durabilityQualityEntry = sDurabilityQualityStore.LookupEntry(durabilityQualityEntryId);
767 if (!durabilityQualityEntry)
768 return 0;
769
770 uint32 dmultiplier;
771 switch (itemTemplate->Class)
772 {
774 dmultiplier = durabilityCost->WeaponSubClassCost[itemTemplate->SubClass];
775 break;
776 case ITEM_CLASS_ARMOR:
777 dmultiplier = durabilityCost->ArmorSubClassCost[itemTemplate->SubClass];
778 break;
779 default:
780 dmultiplier = 0;
781 break;
782 }
783
784 uint32 cost = static_cast<uint32>(std::round(lostDurability * dmultiplier * double(durabilityQualityEntry->Data)));
785 cost = uint32(cost * discount * sWorld->getRate(RATE_REPAIRCOST));
786
787 if (cost == 0) // Fix for ITEM_QUALITY_ARTIFACT
788 cost = 1;
789
790 return cost;
791}
792
793bool Item::HasEnchantRequiredSkill(Player const* player) const
794{
795 // Check all enchants for required skill
796 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
797 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
798 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
799 if (enchantEntry->RequiredSkillID && player->GetSkillValue(enchantEntry->RequiredSkillID) < enchantEntry->RequiredSkillRank)
800 return false;
801
802 return true;
803}
804
806{
807 uint32 level = 0;
808
809 // Check all enchants for required level
810 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
811 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
812 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
813 if (enchantEntry->MinLevel > level)
814 level = enchantEntry->MinLevel;
815
816 return level;
817}
818
820{
821 // Check all enchants for soulbound
822 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
823 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
824 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
825 if (enchantEntry->Flags & ENCHANTMENT_CAN_SOULBOUND)
826 return true;
827 return false;
828}
829
831{
832 // not allow merge looting currently items
833 if (m_lootGenerated)
834 return EQUIP_ERR_LOOT_GONE;
835
836 // check item type
837 if (GetEntry() != proto->ItemId)
839
840 // check free space (full stacks can't be target of merge
841 if (GetCount() >= proto->GetMaxStackSize())
843
844 return EQUIP_ERR_OK;
845}
846
847bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
848{
849 ItemTemplate const* proto = GetTemplate();
850
852 if (spellInfo->EquippedItemClass != -1) // -1 == any item class
853 {
854 // Special case - accept vellum for armor/weapon requirements
855 if (isEnchantSpell && ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && proto->IsArmorVellum())
856 || (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && proto->IsWeaponVellum())))
857 return true;
858
859 if (spellInfo->EquippedItemClass != int32(proto->Class))
860 return false; // wrong item class
861
862 if (spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass
863 {
864 if ((spellInfo->EquippedItemSubClassMask & (1 << proto->SubClass)) == 0)
865 return false; // subclass not present in mask
866 }
867 }
868
869 if (isEnchantSpell && spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
870 {
871 // Special case - accept weapon type for main and offhand requirements
872 if (proto->InventoryType == INVTYPE_WEAPON &&
875 return true;
876 else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0)
877 return false; // inventory type not present in mask
878 }
879
880 return true;
881}
882
883void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster /*= ObjectGuid::Empty*/)
884{
885 // Better lost small time at check in comparison lost time at item save to DB.
886 if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
887 return;
888
889 Player* owner = GetOwner();
891 {
892 if (uint32 oldEnchant = GetEnchantmentId(slot))
894
895 if (id)
896 owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetEntry(), id);
897 }
898
902 SetState(ITEM_CHANGED, owner);
903}
904
906{
907 if (GetEnchantmentDuration(slot) == duration)
908 return;
909
911 SetState(ITEM_CHANGED, owner);
912 // Cannot use GetOwner() here, has to be passed as an argument to avoid freeze due to hashtable locking
913}
914
923
933
935{
936 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
937 {
939
940 if (!SocketColor) // no socket slot
941 continue;
942
943 uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
944 if (!enchant_id) // no gems on this socket
945 return false;
946
947 SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
948 if (!enchantEntry) // invalid gem id on this socket
949 return false;
950
951 uint8 GemColor = 0;
952
953 uint32 gemid = enchantEntry->SrcItemID;
954 if (gemid)
955 {
956 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemid);
957 if (gemProto)
958 {
959 GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties);
960 if (gemProperty)
961 GemColor = gemProperty->Type;
962 }
963 }
964
965 if (!(GemColor & SocketColor)) // bad gem color on this socket
966 return false;
967 }
968 return true;
969}
970
972{
973 uint8 count = 0;
974 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
975 {
976 uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
977 if (!enchant_id)
978 continue;
979
980 SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
981 if (!enchantEntry)
982 continue;
983
984 if (GemID == enchantEntry->SrcItemID)
985 ++count;
986 }
987 return count;
988}
989
991{
992 uint8 count = 0;
993 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
994 {
995 uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
996 if (!enchant_id)
997 continue;
998
999 SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1000 if (!enchantEntry)
1001 continue;
1002
1003 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(enchantEntry->SrcItemID);
1004 if (!gemProto)
1005 continue;
1006
1007 if (gemProto->ItemLimitCategory == limitCategory)
1008 ++count;
1009 }
1010 return count;
1011}
1012
1013bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
1014{
1015 ItemTemplate const* proto = GetTemplate();
1016 return proto && ((proto->Map && proto->Map != cur_mapId) || (proto->Area && proto->Area != cur_zoneId));
1017}
1018
1020{
1021 WorldPacket data(SMSG_SOCKET_GEMS_RESULT, 8+4+4+4+4);
1022 data << GetGUID();
1025
1026 GetOwner()->SendDirectMessage(&data);
1027}
1028
1029// Though the client has the information in the item's data field,
1030// we have to send SMSG_ITEM_TIME_UPDATE to display the remaining
1031// time.
1033{
1035 if (!duration)
1036 return;
1037
1039 data << GetGUID();
1040 data << uint32(duration);
1041 owner->SendDirectMessage(&data);
1042}
1043
1044Item* Item::CreateItem(uint32 itemEntry, uint32 count, Player const* player /*= nullptr*/)
1045{
1046 if (count < 1)
1047 return nullptr; //don't create item at zero count
1048
1049 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry);
1050 if (proto)
1051 {
1052 if (count > proto->GetMaxStackSize())
1053 count = proto->GetMaxStackSize();
1054
1055 ASSERT_NODEBUGINFO(count != 0 && "pProto->Stackable == 0 but checked at loading already");
1056
1057 Item* item = NewItemOrBag(proto);
1058 if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), itemEntry, player))
1059 {
1060 item->SetCount(count);
1061 return item;
1062 }
1063 else
1064 delete item;
1065 }
1066 else
1067 ABORT();
1068 return nullptr;
1069}
1070
1071Item* Item::CloneItem(uint32 count, Player const* player /*= nullptr*/) const
1072{
1073 Item* newItem = CreateItem(GetEntry(), count, player);
1074 if (!newItem)
1075 return nullptr;
1076
1081 // player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
1082 if (player)
1084 return newItem;
1085}
1086
1087bool Item::IsBindedNotWith(Player const* player) const
1088{
1089 // not binded item
1090 if (!IsSoulBound())
1091 return false;
1092
1093 // own item
1094 if (GetOwnerGUID() == player->GetGUID())
1095 return false;
1096
1097 if (IsBOPTradeable())
1098 if (allowedGUIDs.find(player->GetGUID()) != allowedGUIDs.end())
1099 return false;
1100
1101 // BOA item case
1102 if (IsBoundAccountWide())
1103 return false;
1104
1105 return true;
1106}
1107
1109{
1110 if (Player* owner = GetOwner())
1111 BuildFieldsUpdate(owner, data_map);
1112 ClearUpdateMask(false);
1113}
1114
1116{
1117 if (Player* owner = GetOwner())
1118 {
1119 owner->GetMap()->AddUpdateObject(this);
1120 return true;
1121 }
1122
1123 return false;
1124}
1125
1127{
1128 if (Player* owner = GetOwner())
1129 owner->GetMap()->RemoveUpdateObject(this);
1130}
1131
1133{
1134 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1135
1137 stmt->setUInt32(0, GetGUID().GetCounter());
1138 trans->Append(stmt);
1139
1140 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_REFUND_INSTANCE);
1141 stmt->setUInt32(0, GetGUID().GetCounter());
1142 stmt->setUInt32(1, GetRefundRecipient().GetCounter());
1143 stmt->setUInt32(2, GetPaidMoney());
1145 trans->Append(stmt);
1146
1147 CharacterDatabase.CommitTransaction(trans);
1148}
1149
1151{
1152 if (trans)
1153 {
1155 stmt->setUInt32(0, GetGUID().GetCounter());
1156 (*trans)->Append(stmt);
1157
1158 }
1159}
1160
1161void Item::SetNotRefundable(Player* owner, bool changestate /*=true*/, CharacterDatabaseTransaction* trans /*=nullptr*/)
1162{
1163 if (!IsRefundable())
1164 return;
1165
1167 // Following is not applicable in the trading procedure
1168 if (changestate)
1169 SetState(ITEM_CHANGED, owner);
1170
1172 SetPaidMoney(0);
1175
1177}
1178
1180{
1181 /* Here we update our played time
1182 We simply add a number to the current played time,
1183 based on the time elapsed since the last update hereof.
1184 */
1185 // Get current played time
1187 // Calculate time elapsed since last played time update
1188 time_t curtime = GameTime::GetGameTime();
1189 uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
1190 uint32 new_playtime = current_playtime + elapsed;
1191 // Check if the refund timer has expired yet
1192 if (new_playtime <= 2*HOUR)
1193 {
1194 // No? Proceed.
1195 // Update the data field
1197 // Flag as changed to get saved to DB
1198 SetState(ITEM_CHANGED, owner);
1199 // Speaks for itself
1200 m_lastPlayedTimeUpdate = curtime;
1201 return;
1202 }
1203 // Yes
1204 SetNotRefundable(owner);
1205}
1206
1208{
1209 time_t curtime = GameTime::GetGameTime();
1210 uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
1212}
1213
1215{
1216 return (GetPlayedTime() > 2*HOUR);
1217}
1218
1219void Item::SetSoulboundTradeable(GuidSet const& allowedLooters)
1220{
1222 allowedGUIDs = allowedLooters;
1223}
1224
1226{
1228 if (allowedGUIDs.empty())
1229 return;
1230
1231 allowedGUIDs.clear();
1232 SetState(ITEM_CHANGED, currentOwner);
1234 stmt->setUInt32(0, GetGUID().GetCounter());
1235 CharacterDatabase.Execute(stmt);
1236}
1237
1239{
1240 // called from owner's update - GetOwner() MUST be valid
1241 if (GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME) + 2*HOUR < GetOwner()->GetTotalPlayedTime())
1242 {
1244 return true; // remove from tradeable list
1245 }
1246
1247 return false;
1248}
1249
1251{
1253
1254 if (Player* player = GetOwner())
1255 {
1256 if (TradeData* tradeData = player->GetTradeData())
1257 {
1258 TradeSlots slot = tradeData->GetTradeSlotForItem(GetGUID());
1259
1260 if (slot != TRADE_SLOT_INVALID)
1261 tradeData->SetItem(slot, this, true);
1262 }
1263 }
1264}
1265
1266std::string Item::GetDebugInfo() const
1267{
1268 std::stringstream sstr;
1269 sstr << Object::GetDebugInfo() << "\n"
1270 << std::boolalpha
1271 << "Owner: " << GetOwnerGUID().ToString() << " Count: " << GetCount()
1272 << " BagSlot: " << std::to_string(GetBagSlot()) << " Slot: " << std::to_string(GetSlot()) << " Equipped: " << IsEquipped();
1273 return sstr.str();
1274}
Item * NewItemOrBag(ItemTemplate const *proto)
Definition Bag.h:67
@ CHAR_UPD_ITEM_INSTANCE
@ CHAR_UPD_ITEM_INSTANCE_ON_LOAD
@ CHAR_DEL_ITEM_INSTANCE
@ CHAR_DEL_CHAR_INVENTORY_BY_ITEM
@ CHAR_DEL_ITEM_BOP_TRADE
@ CHAR_DEL_ITEM_REFUND_INSTANCE
@ CHAR_UPD_GIFT_OWNER
@ CHAR_DEL_GIFT
@ CHAR_REP_ITEM_INSTANCE
@ CHAR_INS_ITEM_REFUND_INSTANCE
@ HOUR
Definition Common.h:30
@ ENCHANTMENT_CAN_SOULBOUND
Definition DBCEnums.h:394
DBCStorage< DurabilityQualityEntry > sDurabilityQualityStore(DurabilityQualityfmt)
DBCStorage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore(SpellItemEnchantmentfmt)
DBCStorage< ItemSetEntry > sItemSetStore(ItemSetEntryfmt)
DBCStorage< ItemRandomSuffixEntry > sItemRandomSuffixStore(ItemRandomSuffixfmt)
DBCStorage< DurabilityCostsEntry > sDurabilityCostsStore(DurabilityCostsfmt)
DBCStorage< GemPropertiesEntry > sGemPropertiesStore(GemPropertiesEntryfmt)
DBCStorage< ItemRandomPropertiesEntry > sItemRandomPropertiesStore(ItemRandomPropertiesfmt)
#define MAX_ITEM_SET_SPELLS
#define MAX_ITEM_ENCHANTMENT_EFFECTS
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define ABORT
Definition Errors.h:74
#define ASSERT_NODEBUGINFO
Definition Errors.h:69
#define ASSERT
Definition Errors.h:68
EnchantmentSlot
@ PERM_ENCHANTMENT_SLOT
@ PROP_ENCHANTMENT_SLOT_0
@ MAX_ENCHANTMENT_SLOT
@ PROP_ENCHANTMENT_SLOT_2
@ SOCK_ENCHANTMENT_SLOT
@ BONUS_ENCHANTMENT_SLOT
@ MAX_INSPECTED_ENCHANTMENT_SLOT
InventoryResult
Definition ItemDefines.h:25
@ EQUIP_ERR_OK
Definition ItemDefines.h:26
@ EQUIP_ERR_LOOT_GONE
Definition ItemDefines.h:75
@ EQUIP_ERR_CANT_STACK
Definition ItemDefines.h:45
uint32 GenerateEnchSuffixFactor(uint32 item_id)
@ ITEM_CLASS_QUIVER
@ ITEM_CLASS_CONTAINER
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
@ ITEM_SUBCLASS_WEAPON_CROSSBOW
@ ITEM_SUBCLASS_WEAPON_GUN
@ ITEM_SUBCLASS_WEAPON_AXE2
@ ITEM_SUBCLASS_WEAPON_SPEAR
@ ITEM_SUBCLASS_WEAPON_STAFF
@ ITEM_SUBCLASS_WEAPON_MACE
@ ITEM_SUBCLASS_WEAPON_MACE2
@ ITEM_SUBCLASS_WEAPON_DAGGER
@ ITEM_SUBCLASS_WEAPON_BOW
@ ITEM_SUBCLASS_WEAPON_SWORD
@ ITEM_SUBCLASS_WEAPON_AXE
@ ITEM_SUBCLASS_WEAPON_WAND
@ ITEM_SUBCLASS_WEAPON_THROWN
@ ITEM_SUBCLASS_WEAPON_SWORD2
@ ITEM_SUBCLASS_WEAPON_POLEARM
@ ITEM_FIELD_FLAG_REFUNDABLE
@ ITEM_FIELD_FLAG_SOULBOUND
@ ITEM_FIELD_FLAG_BOP_TRADEABLE
@ BAG_FAMILY_MASK_MINING_SUPP
@ BAG_FAMILY_MASK_HERBS
@ BAG_FAMILY_MASK_ENCHANTING_SUPP
@ BAG_FAMILY_MASK_SOUL_SHARDS
@ BAG_FAMILY_MASK_INSCRIPTION_SUPP
@ BAG_FAMILY_MASK_GEMS
@ BAG_FAMILY_MASK_ARROWS
@ BAG_FAMILY_MASK_BULLETS
@ BAG_FAMILY_MASK_ENGINEERING_SUPP
@ BAG_FAMILY_MASK_LEATHERWORKING_SUPP
@ ITEM_SUBCLASS_CONTAINER
@ ITEM_SUBCLASS_INSCRIPTION_CONTAINER
@ ITEM_SUBCLASS_LEATHERWORKING_CONTAINER
@ ITEM_SUBCLASS_GEM_CONTAINER
@ ITEM_SUBCLASS_SOUL_CONTAINER
@ ITEM_SUBCLASS_ENCHANTING_CONTAINER
@ ITEM_SUBCLASS_MINING_CONTAINER
@ ITEM_SUBCLASS_HERB_CONTAINER
@ ITEM_SUBCLASS_ENGINEERING_CONTAINER
@ ITEM_SUBCLASS_QUIVER
@ ITEM_SUBCLASS_AMMO_POUCH
@ ITEM_SUBCLASS_ARMOR_MAIL
@ ITEM_SUBCLASS_ARMOR_CLOTH
@ ITEM_SUBCLASS_ARMOR_LEATHER
@ ITEM_SUBCLASS_ARMOR_SHIELD
@ ITEM_SUBCLASS_ARMOR_PLATE
SocketColor
#define MAX_ITEM_PROTO_SPELLS
@ NO_BIND
@ INVTYPE_WEAPON
@ INVTYPE_WEAPONMAINHAND
@ INVTYPE_WEAPONOFFHAND
void AddItemsSetItem(Player *player, Item *item)
Definition Item.cpp:42
bool ItemCanGoIntoBag(ItemTemplate const *pProto, ItemTemplate const *pBagProto)
Definition Item.cpp:182
void RemoveItemsSetItem(Player *player, ItemTemplate const *proto)
Definition Item.cpp:124
void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:690
void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:669
#define MAX_GEM_SOCKETS
Definition Item.h:40
#define MAX_ENCHANTMENT_OFFSET
Definition Item.h:49
ItemUpdateState
Definition Item.h:52
@ ITEM_CHANGED
Definition Item.h:54
@ ITEM_REMOVED
Definition Item.h:56
@ ITEM_NEW
Definition Item.h:55
@ ITEM_UNCHANGED
Definition Item.h:53
@ ENCHANTMENT_ID_OFFSET
Definition Item.h:44
@ ENCHANTMENT_CHARGES_OFFSET
Definition Item.h:46
@ ENCHANTMENT_DURATION_OFFSET
Definition Item.h:45
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define sLootItemStorage
@ TYPEID_ITEM
Definition ObjectGuid.h:36
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:260
@ TYPEMASK_ITEM
Definition ObjectGuid.h:50
#define sObjectMgr
Definition ObjectMgr.h:1721
std::unordered_map< Player *, UpdateData > UpdateDataMapType
Definition Object.h:63
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ EQUIPMENT_SLOT_END
Definition Player.h:571
#define INVENTORY_SLOT_BAG_0
Definition Player.h:547
#define sScriptMgr
Definition ScriptMgr.h:1168
@ SPELL_EFFECT_ENCHANT_ITEM
@ SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
@ SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
#define sSpellMgr
Definition SpellMgr.h:738
TradeSlots
Definition TradeData.h:24
@ TRADE_SLOT_INVALID
Definition TradeData.h:28
@ UPDATEFLAG_LOWGUID
Definition UpdateData.h:45
@ ITEM_FIELD_DURABILITY
@ ITEM_FIELD_STACK_COUNT
@ ITEM_FIELD_DURATION
@ ITEM_END
@ ITEM_FIELD_FLAGS
@ ITEM_FIELD_MAXDURABILITY
@ ITEM_FIELD_RANDOM_PROPERTIES_ID
@ ITEM_FIELD_CREATOR
@ ITEM_FIELD_GIFTCREATOR
@ ITEM_FIELD_PROPERTY_SEED
@ ITEM_FIELD_ENCHANTMENT_1_1
@ ITEM_FIELD_CREATE_PLAYED_TIME
@ ITEM_FIELD_CONTAINED
Definition Bag.h:27
Class used to access individual fields of database query result.
Definition Field.h:92
uint16 GetUInt16() const
Definition Field.cpp:45
uint32 GetUInt32() const
Definition Field.cpp:61
Definition Item.h:62
std::string GetDebugInfo() const override
Definition Item.cpp:1266
uint32 GetEnchantRequiredLevel() const
Definition Item.cpp:805
uint32 GetPlayedTime()
Definition Item.cpp:1207
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:523
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition Item.cpp:638
uint32 GetPaidExtendedCost() const
Definition Item.h:192
uint8 GetSlot() const
Definition Item.h:126
void UpdateItemSuffixFactor()
Definition Item.cpp:630
bool IsWrapped() const
Definition Item.h:100
void SetSpellCharges(uint8 index, int32 value)
Definition Item.h:162
bool AddToObjectUpdate() override
Definition Item.cpp:1115
void SetText(std::string const &text)
Definition Item.h:153
virtual bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field *fields, uint32 entry)
Definition Item.cpp:409
void UpdateDuration(Player *owner, uint32 diff)
Definition Item.cpp:305
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:323
void BuildUpdate(UpdateDataMapType &) override
Definition Item.cpp:1108
bool IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
Definition Item.cpp:1013
Item()
Definition Item.cpp:247
void DeleteRefundDataFromDB(CharacterDatabaseTransaction *trans)
Definition Item.cpp:1150
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition Item.h:148
int32 GetSpellCharges(uint8 index=0) const
Definition Item.h:161
static Item * CreateItem(uint32 itemEntry, uint32 count, Player const *player=nullptr)
Definition Item.cpp:1044
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition Item.cpp:1071
Bag * m_container
Definition Item.h:214
void SetItemRandomProperties(int32 randomPropId)
Definition Item.cpp:592
void SetPaidMoney(uint32 money)
Definition Item.h:187
uint8 GetGemCountWithID(uint32 GemID) const
Definition Item.cpp:971
bool IsBoundAccountWide() const
Definition Item.h:82
bool mb_in_trade
Definition Item.h:217
Bag * ToBag()
Definition Item.h:95
std::string m_text
Definition Item.h:212
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition Item.cpp:721
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const
Definition Item.h:149
uint32 CalculateDurabilityRepairCost(float discount) const
Definition Item.cpp:746
void SetCount(uint32 value)
Definition Item.cpp:1250
int32 GetItemRandomPropertyId() const
Definition Item.h:140
ItemTemplate const * GetTemplate() const
Definition Item.cpp:535
bool IsBOPTradeable() const
Definition Item.h:99
bool IsInBag() const
Definition Item.h:133
bool IsSoulBound() const
Definition Item.h:81
void SaveRefundDataToDB()
Definition Item.cpp:1132
void SetNotRefundable(Player *owner, bool changestate=true, CharacterDatabaseTransaction *trans=nullptr)
Definition Item.cpp:1161
uint32 GetItemSuffixFactor() const
Definition Item.h:141
friend void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:690
bool IsBindedNotWith(Player const *player) const
Definition Item.cpp:1087
uint32 m_paidMoney
Definition Item.h:220
bool IsEquipped() const
Definition Item.cpp:716
void SendTimeUpdate(Player *owner)
Definition Item.cpp:1032
uint32 GetSpell()
Definition Item.cpp:552
bool IsRefundExpired()
Definition Item.cpp:1214
void UpdatePlayedTime(Player *owner)
Definition Item.cpp:1179
Player * GetOwner() const
Definition Item.cpp:540
ObjectGuid GetOwnerGUID() const
Definition Item.h:76
bool HasEnchantRequiredSkill(Player const *player) const
Definition Item.cpp:793
time_t m_lastPlayedTimeUpdate
Definition Item.h:218
uint32 GetSkill()
Definition Item.cpp:546
bool IsRefundable() const
Definition Item.h:98
uint16 GetPos() const
Definition Item.h:130
bool GemsFitSockets() const
Definition Item.cpp:934
bool IsBoundByEnchant() const
Definition Item.cpp:819
void SetSoulboundTradeable(GuidSet const &allowedLooters)
Definition Item.cpp:1219
int16 uQueuePos
Definition Item.h:216
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
Definition Item.cpp:915
uint32 m_paidExtendedCost
Definition Item.h:221
bool IsBag() const
Definition Item.h:102
void RemoveFromObjectUpdate() override
Definition Item.cpp:1126
void ClearEnchantment(EnchantmentSlot slot)
Definition Item.cpp:924
ObjectGuid const & GetRefundRecipient() const
Definition Item.h:190
void SendUpdateSockets()
Definition Item.cpp:1019
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player *owner)
Definition Item.cpp:905
InventoryResult CanBeMergedPartlyWith(ItemTemplate const *proto) const
Definition Item.cpp:830
void SetPaidExtendedCost(uint32 iece)
Definition Item.h:188
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const
Definition Item.h:150
void SetRefundRecipient(ObjectGuid const &guid)
Definition Item.h:186
virtual bool Create(ObjectGuid::LowType guidlow, uint32 itemId, Player const *owner)
Definition Item.cpp:267
uint32 GetPaidMoney() const
Definition Item.h:191
uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const
Definition Item.cpp:990
void ClearSoulboundTradeable(Player *currentOwner)
Definition Item.cpp:1225
bool IsNotEmptyBag() const
Definition Item.cpp:298
bool m_lootGenerated
Definition Item.h:165
uint32 GetCount() const
Definition Item.h:119
bool CheckSoulboundTradeExpire()
Definition Item.cpp:1238
void SetOwnerGUID(ObjectGuid guid)
Definition Item.h:77
Loot loot
Definition Item.h:164
uint8 GetBagSlot() const
Definition Item.cpp:711
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster=ObjectGuid::Empty)
Definition Item.cpp:883
static void DeleteFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:506
uint8 m_slot
Definition Item.h:213
friend void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:669
bool IsInUpdateQueue() const
Definition Item.h:170
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition Item.cpp:847
GuidSet allowedGUIDs
Definition Item.h:222
ItemUpdateState uState
Definition Item.h:215
LowType GetCounter() const
Definition ObjectGuid.h:156
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
std::string ToString() const
uint32 LowType
Definition ObjectGuid.h:142
void BuildFieldsUpdate(Player *, UpdateDataMapType &) const
Definition Object.cpp:492
uint16 m_objectType
Definition Object.h:232
int32 GetInt32Value(uint16 index) const
Definition Object.cpp:243
void SetInt32Value(uint16 index, int32 value)
Definition Object.cpp:572
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:249
uint16 m_valuesCount
Definition Object.h:246
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:760
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:775
void ApplyModFlag(uint16 index, uint32 flag, bool apply)
Definition Object.cpp:805
void ClearUpdateMask(bool remove)
Definition Object.cpp:479
void SetGuidValue(uint16 index, ObjectGuid value)
Definition Object.cpp:699
bool _LoadIntoDataField(std::string const &data, uint32 startOffset, uint32 count)
Definition Object.cpp:551
uint32 GetEntry() const
Definition Object.h:81
virtual std::string GetDebugInfo() const
Definition Object.cpp:899
void _Create(ObjectGuid const &guid)
Definition Object.cpp:109
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SetEntry(uint32 entry)
Definition Object.h:82
virtual void SetObjectScale(float scale)
Definition Object.h:85
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:585
uint16 m_updateFlag
Definition Object.h:235
ObjectGuid GetGUID() const
Definition Object.h:79
TypeID m_objectTypeId
Definition Object.h:234
ObjectGuid GetGuidValue(uint16 index) const
Definition Object.cpp:281
std::vector< Item * > m_itemUpdateQueue
Definition Player.h:2386
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
uint16 GetSkillValue(uint32 skill) const
Definition Player.cpp:5892
WorldSession * GetSession() const
Definition Player.h:1719
void DestroyItem(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:12113
std::vector< ItemSetEffect * > ItemSetEff
Definition Player.h:1970
static bool IsBagPos(uint16 pos)
Definition Player.cpp:9698
void ApplyEquipSpell(SpellInfo const *spellInfo, Item *item, bool apply, bool form_change=false)
Definition Player.cpp:7593
void DeleteRefundReference(ObjectGuid it)
Definition Player.cpp:25913
bool m_itemUpdateQueueBlocked
Definition Player.h:2387
void setInt16(uint8 index, int16 value)
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setString(uint8 index, std::string const &value)
uint32 Id
Definition SpellInfo.h:289
int32 EquippedItemClass
Definition SpellInfo.h:344
int32 EquippedItemSubClassMask
Definition SpellInfo.h:345
int32 EquippedItemInventoryTypeMask
Definition SpellInfo.h:346
bool HasEffect(SpellEffects effect) const
void SendEnchantmentLog(ObjectGuid target, ObjectGuid caster, uint32 itemId, uint32 enchantId)
@ SMSG_SOCKET_GEMS_RESULT
Definition Opcodes.h:1320
@ SMSG_ITEM_TIME_UPDATE
Definition Opcodes.h:519
#define sWorld
Definition World.h:900
@ RATE_REPAIRCOST
Definition World.h:433
time_t GetGameTime()
Definition GameTime.cpp:42
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition Util.cpp:56
uint32 ArmorSubClassCost[8]
uint32 WeaponSubClassCost[21]
std::array< uint32, MAX_ITEM_ENCHANTMENT_EFFECTS > Enchantment
std::array< uint32, MAX_ITEM_ENCHANTMENT_EFFECTS > Enchantment
uint32 item_count
Definition Item.h:36
uint32 setid
Definition Item.h:35
SpellInfo const * spells[8]
Definition Item.h:37
uint32 RequiredSkill
uint32 RequiredSkillRank
uint32 SetThreshold[MAX_ITEM_SET_SPELLS]
uint32 SetSpellID[MAX_ITEM_SET_SPELLS]
std::array< ItemEffect, MAX_ITEM_PROTO_SPELLS > Effects
uint32 GetMaxStackSize() const
std::array< _Socket, MAX_ITEM_PROTO_SOCKETS > Socket
bool IsArmorVellum() const
uint32 GemProperties
uint32 ItemLimitCategory
uint32 MaxDurability
uint32 InventoryType
bool IsWeaponVellum() const
uint32 GetSkill() const
bool isLooted() const
Definition Loot.h:239