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 "ItemPackets.h"
27#include "Log.h"
28#include "LootItemStorage.h"
29#include "Map.h"
30#include "ObjectAccessor.h"
31#include "ObjectMgr.h"
32#include "ScriptMgr.h"
33#include "SpellInfo.h"
34#include "SpellMgr.h"
35#include "StringConvert.h"
36#include "Player.h"
37#include "TradeData.h"
38#include "UpdateData.h"
39#include "World.h"
40#include "WorldPacket.h"
41#include "WorldSession.h"
42
43void AddItemsSetItem(Player* player, Item* item)
44{
45 ItemTemplate const* proto = item->GetTemplate();
46 uint32 setid = proto->GetItemSet();
47
48 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
49
50 if (!set)
51 {
52 TC_LOG_ERROR("sql.sql", "Item set {} for item (id {}) not found, mods not applied.", setid, proto->GetId());
53 return;
54 }
55
56 if (set->RequiredSkill && player->GetSkillValue(set->RequiredSkill) < set->RequiredSkillRank)
57 return;
58
59 ItemSetEffect* eff = nullptr;
60
61 for (size_t x = 0; x < player->ItemSetEff.size(); ++x)
62 {
63 if (player->ItemSetEff[x] && player->ItemSetEff[x]->setid == setid)
64 {
65 eff = player->ItemSetEff[x];
66 break;
67 }
68 }
69
70 if (!eff)
71 {
72 eff = new ItemSetEffect();
73 eff->setid = setid;
74
75 size_t x = 0;
76 for (; x < player->ItemSetEff.size(); ++x)
77 if (!player->ItemSetEff[x])
78 break;
79
80 if (x < player->ItemSetEff.size())
81 player->ItemSetEff[x]=eff;
82 else
83 player->ItemSetEff.push_back(eff);
84 }
85
86 ++eff->item_count;
87
88 for (uint32 x = 0; x < MAX_ITEM_SET_SPELLS; ++x)
89 {
90 if (!set->SetSpellID[x])
91 continue;
92 //not enough for spell
93 if (set->SetThreshold[x] > eff->item_count)
94 continue;
95
96 uint32 z = 0;
97 for (; z < MAX_ITEM_SET_SPELLS; ++z)
98 if (eff->spells[z] && eff->spells[z]->Id == set->SetSpellID[x])
99 break;
100
101 if (z < MAX_ITEM_SET_SPELLS)
102 continue;
103
104 //new spell
105 for (uint32 y = 0; y < MAX_ITEM_SET_SPELLS; ++y)
106 {
107 if (!eff->spells[y]) // free slot
108 {
109 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(set->SetSpellID[x]);
110 if (!spellInfo)
111 {
112 TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id {} in items set {} effects", set->SetSpellID[x], setid);
113 break;
114 }
115
116 // spell cast only if fit form requirement, in other case will cast at form change
117 player->ApplyEquipSpell(spellInfo, nullptr, true);
118 eff->spells[y] = spellInfo;
119 break;
120 }
121 }
122 }
123}
124
125void RemoveItemsSetItem(Player*player, ItemTemplate const* proto)
126{
127 uint32 setid = proto->GetItemSet();
128
129 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
130
131 if (!set)
132 {
133 TC_LOG_ERROR("sql.sql", "Item set #{} for item #{} not found, mods not removed.", setid, proto->GetId());
134 return;
135 }
136
137 ItemSetEffect* eff = nullptr;
138 size_t setindex = 0;
139 for (; setindex < player->ItemSetEff.size(); setindex++)
140 {
141 if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->setid == setid)
142 {
143 eff = player->ItemSetEff[setindex];
144 break;
145 }
146 }
147
148 // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
149 if (!eff)
150 return;
151
152 --eff->item_count;
153
154 for (uint32 x = 0; x < MAX_ITEM_SET_SPELLS; x++)
155 {
156 if (!set->SetSpellID[x])
157 continue;
158
159 // enough for spell
160 if (set->SetThreshold[x] <= eff->item_count)
161 continue;
162
163 for (uint32 z = 0; z < MAX_ITEM_SET_SPELLS; z++)
164 {
165 if (eff->spells[z] && eff->spells[z]->Id == set->SetSpellID[x])
166 {
167 // spell can be not active if not fit form requirement
168 player->ApplyEquipSpell(eff->spells[z], nullptr, false);
169 eff->spells[z]=nullptr;
170 break;
171 }
172 }
173 }
174
175 if (!eff->item_count) //all items of a set were removed
176 {
177 ASSERT(eff == player->ItemSetEff[setindex]);
178 delete eff;
179 player->ItemSetEff[setindex] = nullptr;
180 }
181}
182
183bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
184{
185 if (!pProto || !pBagProto)
186 return false;
187
188 switch (pBagProto->GetClass())
189 {
191 switch (pBagProto->GetSubClass())
192 {
194 return true;
196 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_SOUL_SHARDS))
197 return false;
198 return true;
200 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_HERBS))
201 return false;
202 return true;
205 return false;
206 return true;
208 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_MINING_SUPP))
209 return false;
210 return true;
213 return false;
214 return true;
216 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_GEMS))
217 return false;
218 return true;
221 return false;
222 return true;
225 return false;
226 return true;
227 default:
228 return false;
229 }
231 switch (pBagProto->GetSubClass())
232 {
234 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_ARROWS))
235 return false;
236 return true;
238 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_BULLETS))
239 return false;
240 return true;
241 default:
242 return false;
243 }
244 }
245 return false;
246}
247
267
268bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, Player const* owner)
269{
270 Object::_Create(ObjectGuid::Create<HighGuid::Item>(guidlow));
271
272 SetEntry(itemId);
273 SetObjectScale(1.0f);
274
275 if (owner)
276 {
277 SetOwnerGUID(owner->GetGUID());
278 SetContainedIn(owner->GetGUID());
279 }
280
281 ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemId);
282 if (!itemProto)
283 return false;
284
285 SetCount(1);
287 SetDurability(itemProto->MaxDurability);
288
289 for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
290 SetSpellCharges(i, itemProto->Effects[i].Charges);
291
292 SetExpiration(itemProto->GetDuration());
294 return true;
295}
296
297std::string const& Item::GetNameForLocaleIdx(LocaleConstant locale) const
298{
299 return GetTemplate()->GetName(locale);
300}
301
302// Returns true if Item is a bag AND it is not empty.
303// Returns false if Item is not a bag OR it is an empty bag.
305{
306 if (Bag const* bag = ToBag())
307 return !bag->IsEmpty();
308 return false;
309}
310
312{
314 return;
315
316 TC_LOG_DEBUG("entities.player.items", "Item::UpdateDuration Item (Entry: {} Duration {} Diff {})", GetEntry(), GetUInt32Value(ITEM_FIELD_DURATION), diff);
317
319 {
320 sScriptMgr->OnItemExpire(owner, GetTemplate());
321 owner->DestroyItem(GetBagSlot(), GetSlot(), true);
322 return;
323 }
324
326 SetState(ITEM_CHANGED, owner); // save new time in database
327}
328
330{
331 bool isInTransaction = bool(trans);
332 if (!isInTransaction)
333 trans = CharacterDatabase.BeginTransaction();
334
335 switch (uState)
336 {
337 case ITEM_NEW:
338 case ITEM_CHANGED:
339 {
340 uint8 index = 0;
342 stmt->setUInt32( index, GetEntry());
343 stmt->setUInt32(++index, GetOwnerGUID().GetCounter());
346 stmt->setUInt32(++index, GetCount());
348
349 std::ostringstream ssSpells;
350 for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
351 ssSpells << GetSpellCharges(i) << ' ';
352 stmt->setString(++index, ssSpells.str());
353
355
356 std::ostringstream ssEnchants;
357 for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
358 {
359 ssEnchants << GetEnchantmentId(EnchantmentSlot(i)) << ' ';
360 ssEnchants << GetEnchantmentDuration(EnchantmentSlot(i)) << ' ';
361 ssEnchants << GetEnchantmentCharges(EnchantmentSlot(i)) << ' ';
362 }
363 stmt->setString(++index, ssEnchants.str());
364
365 stmt->setInt16 (++index, GetItemRandomPropertyId());
368 stmt->setString(++index, m_text);
369 stmt->setUInt32(++index, GetGUID().GetCounter());
370
371 trans->Append(stmt);
372
373 if ((uState == ITEM_CHANGED) && IsWrapped())
374 {
375 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GIFT_OWNER);
376 stmt->setUInt32(0, GetOwnerGUID().GetCounter());
377 stmt->setUInt32(1, GetGUID().GetCounter());
378 trans->Append(stmt);
379 }
380 break;
381 }
382 case ITEM_REMOVED:
383 {
385 stmt->setUInt32(0, GetGUID().GetCounter());
386 trans->Append(stmt);
387
388 if (IsWrapped())
389 {
390 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
391 stmt->setUInt32(0, GetGUID().GetCounter());
392 trans->Append(stmt);
393 }
394
395 if (!isInTransaction)
396 CharacterDatabase.CommitTransaction(trans);
397
398 // Delete the items if this is a container
399 if (!loot.isLooted())
400 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
401
402 delete this;
403 return;
404 }
405 case ITEM_UNCHANGED:
406 break;
407 }
408
410
411 if (!isInTransaction)
412 CharacterDatabase.CommitTransaction(trans);
413}
414
415bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fields, uint32 entry)
416{
417 // 0 1 2 3 4 5 6 7 8 9 10
418 //result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text FROM item_instance WHERE guid = '{}'", guid);
419
420 // create item before any checks for store correct guid
421 // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
422 Object::_Create(ObjectGuid::Create<HighGuid::Item>(guid));
423
424 // Set entry, MUST be before proto check
425 SetEntry(entry);
426 SetObjectScale(1.0f);
427
428 ItemTemplate const* proto = GetTemplate();
429 if (!proto)
430 {
431 TC_LOG_ERROR("entities.item", "Invalid entry {} for item {}. Refusing to load.", GetEntry(), GetGUID().ToString());
432 return false;
433 }
434
435 // set owner (not if item is only loaded for gbank/auction/mail
436 if (!owner_guid.IsEmpty())
437 SetOwnerGUID(owner_guid);
438
439 bool need_save = false; // need explicit save data at load fixes
440 if (uint32 creator = fields[0].GetUInt32())
441 SetCreator(ObjectGuid::Create<HighGuid::Player>(creator));
442 if (uint32 giftCreator = fields[1].GetUInt32())
443 SetGiftCreator(ObjectGuid::Create<HighGuid::Player>(giftCreator));
444 SetCount(fields[2].GetUInt32());
445
446 uint32 duration = fields[3].GetUInt32();
447 SetExpiration(duration);
448 // update duration if need, and remove if not need
449 if ((proto->GetDuration() == 0) != (duration == 0))
450 {
451 SetExpiration(proto->GetDuration());
452 need_save = true;
453 }
454
455 std::vector<std::string_view> tokens = Trinity::Tokenize(fields[4].GetStringView(), ' ', false);
456 if (tokens.size() == MAX_ITEM_PROTO_SPELLS)
457 {
458 for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
459 {
460 if (Optional<int32> charges = Trinity::StringTo<int32>(tokens[i]))
461 SetSpellCharges(i, *charges);
462 else
463 TC_LOG_ERROR("entities.item", "Invalid charge info '{}' for item {}, charge data not loaded.", tokens[i], GetGUID());
464 }
465 }
466
467 ReplaceAllItemFlags(ItemFieldFlags(fields[5].GetUInt32()));
468 // Remove bind flag for items vs NO_BIND set
469 if (IsSoulBound() && proto->GetBonding() == NO_BIND)
470 {
472 need_save = true;
473 }
474
476 TC_LOG_WARN("entities.item", "Invalid enchantment data '{}' for item {}. Forcing partial load.", fields[6].GetString(), GetGUID().ToString());
477
478 SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, fields[7].GetInt16());
479 // recalculate suffix factor
480 if (GetItemRandomPropertyId() < 0)
482
483 uint32 durability = fields[8].GetUInt16();
484 SetDurability(durability);
485 // update max durability (and durability) if need
487
488 // do not overwrite durability for wrapped items
489 if (durability > proto->MaxDurability && !IsWrapped())
490 {
492 need_save = true;
493 }
494
495 SetCreatePlayedTime(fields[9].GetUInt32());
496 SetText(fields[10].GetString());
497
498 if (need_save) // normal item changed state set not work at loading
499 {
504 stmt->setUInt32(3, guid);
505 CharacterDatabase.Execute(stmt);
506 }
507
508 return true;
509}
510
511/*static*/
513{
515 stmt->setUInt32(0, itemGuid);
516 trans->Append(stmt);
517}
518
520{
521 DeleteFromDB(trans, GetGUID().GetCounter());
522
523 // Delete the items if this is a container
524 if (!loot.isLooted())
525 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
526}
527
528/*static*/
530{
532 stmt->setUInt32(0, itemGuid);
533 trans->Append(stmt);
534}
535
540
542{
543 return sObjectMgr->GetItemTemplate(GetEntry());
544}
545
550
551// Just a "legacy shortcut" for proto->GetSkill()
553{
554 ItemTemplate const* proto = GetTemplate();
555 return proto->GetSkill();
556}
557
559{
560 ItemTemplate const* proto = GetTemplate();
561
562 switch (proto->GetClass())
563 {
565 switch (proto->GetSubClass())
566 {
567 case ITEM_SUBCLASS_WEAPON_AXE: return 196;
568 case ITEM_SUBCLASS_WEAPON_AXE2: return 197;
569 case ITEM_SUBCLASS_WEAPON_BOW: return 264;
570 case ITEM_SUBCLASS_WEAPON_GUN: return 266;
571 case ITEM_SUBCLASS_WEAPON_MACE: return 198;
572 case ITEM_SUBCLASS_WEAPON_MACE2: return 199;
573 case ITEM_SUBCLASS_WEAPON_POLEARM: return 200;
574 case ITEM_SUBCLASS_WEAPON_SWORD: return 201;
575 case ITEM_SUBCLASS_WEAPON_SWORD2: return 202;
576 case ITEM_SUBCLASS_WEAPON_STAFF: return 227;
577 case ITEM_SUBCLASS_WEAPON_DAGGER: return 1180;
578 case ITEM_SUBCLASS_WEAPON_THROWN: return 2567;
579 case ITEM_SUBCLASS_WEAPON_SPEAR: return 3386;
580 case ITEM_SUBCLASS_WEAPON_CROSSBOW:return 5011;
581 case ITEM_SUBCLASS_WEAPON_WAND: return 5009;
582 default: return 0;
583 }
584 case ITEM_CLASS_ARMOR:
585 switch (proto->GetSubClass())
586 {
587 case ITEM_SUBCLASS_ARMOR_CLOTH: return 9078;
588 case ITEM_SUBCLASS_ARMOR_LEATHER: return 9077;
589 case ITEM_SUBCLASS_ARMOR_MAIL: return 8737;
590 case ITEM_SUBCLASS_ARMOR_PLATE: return 750;
591 case ITEM_SUBCLASS_ARMOR_SHIELD: return 9116;
592 default: return 0;
593 }
594 }
595 return 0;
596}
597
599{
600 if (!randomPropId)
601 return;
602
603 if (randomPropId > 0)
604 {
605 ItemRandomPropertiesEntry const* item_rand = sItemRandomPropertiesStore.LookupEntry(randomPropId);
606 if (item_rand)
607 {
609 {
612 }
615 }
616 }
617 else
618 {
619 ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(-randomPropId);
620 if (item_rand)
621 {
624 {
628 }
629
632 }
633 }
634}
635
637{
638 uint32 suffixFactor = GenerateEnchSuffixFactor(GetEntry());
639 if (GetItemSuffixFactor() == suffixFactor)
640 return;
642}
643
644void Item::SetState(ItemUpdateState state, Player* forplayer)
645{
646 if (uState == ITEM_NEW && state == ITEM_REMOVED)
647 {
648 // pretend the item never existed
649 if (forplayer)
650 {
651 RemoveItemFromUpdateQueueOf(this, forplayer);
652 forplayer->DeleteRefundReference(GetGUID());
653 }
654 delete this;
655 return;
656 }
657 if (state != ITEM_UNCHANGED)
658 {
659 // new items must stay in new state until saved
660 if (uState != ITEM_NEW)
661 uState = state;
662
663 if (forplayer)
664 AddItemToUpdateQueueOf(this, forplayer);
665 }
666 else
667 {
668 // unset in queue
669 // the item must be removed from the queue manually
670 uQueuePos = -1;
672 }
673}
674
676{
677 if (item->IsInUpdateQueue())
678 return;
679
680 ASSERT(player != nullptr);
681
682 if (player->GetGUID() != item->GetOwnerGUID())
683 {
684 TC_LOG_DEBUG("entities.player.items", "AddItemToUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
685 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
686 return;
687 }
688
689 if (player->m_itemUpdateQueueBlocked)
690 return;
691
692 player->m_itemUpdateQueue.push_back(item);
693 item->uQueuePos = player->m_itemUpdateQueue.size() - 1;
694}
695
697{
698 if (!item->IsInUpdateQueue())
699 return;
700
701 ASSERT(player != nullptr);
702
703 if (player->GetGUID() != item->GetOwnerGUID())
704 {
705 TC_LOG_DEBUG("entities.player.items", "RemoveItemFromUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
706 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
707 return;
708 }
709
710 if (player->m_itemUpdateQueueBlocked)
711 return;
712
713 player->m_itemUpdateQueue[item->uQueuePos] = nullptr;
714 item->uQueuePos = -1;
715}
716
721
723{
724 return !IsInBag() && m_slot < EQUIPMENT_SLOT_END;
725}
726
727bool Item::CanBeTraded(bool mail, bool trade) const
728{
729 if (m_lootGenerated)
730 return false;
731
732 if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!IsBOPTradeable() || !trade)))
733 return false;
734
735 if (IsBag() && (Player::IsBagPos(GetPos()) || !ToBag()->IsEmpty()))
736 return false;
737
738 if (Player* owner = GetOwner())
739 {
740 if (owner->CanUnequipItem(GetPos(), false) != EQUIP_ERR_OK)
741 return false;
742 if (owner->GetLootGUID() == GetGUID())
743 return false;
744 }
745
746 if (IsBoundByEnchant())
747 return false;
748
749 return true;
750}
751
752uint32 Item::CalculateDurabilityRepairCost(float discount, bool useRateConfig /*= true*/) const
753{
755 if (!maxDurability)
756 return 0;
757
759 ASSERT(maxDurability >= curDurability);
760
761 uint32 lostDurability = maxDurability - curDurability;
762 if (!lostDurability)
763 return 0;
764
765 ItemTemplate const* itemTemplate = GetTemplate();
766
767 DurabilityCostsEntry const* durabilityCost = sDurabilityCostsStore.LookupEntry(itemTemplate->GetBaseItemLevel());
768 if (!durabilityCost)
769 return 0;
770
771 uint32 durabilityQualityEntryId = (itemTemplate->GetQuality() + 1) * 2;
772 DurabilityQualityEntry const* durabilityQualityEntry = sDurabilityQualityStore.LookupEntry(durabilityQualityEntryId);
773 if (!durabilityQualityEntry)
774 return 0;
775
776 uint32 dmultiplier;
777 switch (itemTemplate->GetClass())
778 {
780 dmultiplier = durabilityCost->WeaponSubClassCost[itemTemplate->GetSubClass()];
781 break;
782 case ITEM_CLASS_ARMOR:
783 dmultiplier = durabilityCost->ArmorSubClassCost[itemTemplate->GetSubClass()];
784 break;
785 default:
786 dmultiplier = 0;
787 break;
788 }
789
790 uint32 cost = static_cast<uint32>(std::round(lostDurability * dmultiplier * double(durabilityQualityEntry->Data)));
791 cost = uint32(cost * discount * (useRateConfig ? sWorld->getRate(RATE_REPAIRCOST) : 1));
792
793 if (cost == 0) // Fix for ITEM_QUALITY_ARTIFACT
794 cost = 1;
795
796 return cost;
797}
798
799bool Item::HasEnchantRequiredSkill(Player const* player) const
800{
801 // Check all enchants for required skill
802 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
803 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
804 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
805 if (enchantEntry->RequiredSkillID && player->GetSkillValue(enchantEntry->RequiredSkillID) < enchantEntry->RequiredSkillRank)
806 return false;
807
808 return true;
809}
810
812{
813 uint32 level = 0;
814
815 // Check all enchants for required level
816 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
817 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
818 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
819 if (enchantEntry->MinLevel > level)
820 level = enchantEntry->MinLevel;
821
822 return level;
823}
824
826{
827 // Check all enchants for soulbound
828 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
829 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
830 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
831 if (enchantEntry->Flags & ENCHANTMENT_CAN_SOULBOUND)
832 return true;
833 return false;
834}
835
837{
838 // not allow merge looting currently items
839 if (m_lootGenerated)
840 return EQUIP_ERR_LOOT_GONE;
841
842 // check item type
843 if (GetEntry() != proto->GetId())
845
846 // check free space (full stacks can't be target of merge
847 if (GetCount() >= proto->GetMaxStackSize())
849
850 return EQUIP_ERR_OK;
851}
852
853bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
854{
855 ItemTemplate const* proto = GetTemplate();
856
858 if (spellInfo->EquippedItemClass != -1) // -1 == any item class
859 {
860 // Special case - accept vellum for armor/weapon requirements
861 if (isEnchantSpell && ((spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && proto->IsArmorVellum())
862 || (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && proto->IsWeaponVellum())))
863 return true;
864
865 if (spellInfo->EquippedItemClass != int32(proto->GetClass()))
866 return false; // wrong item class
867
868 if (spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass
869 {
870 if ((spellInfo->EquippedItemSubClassMask & (1 << proto->GetSubClass())) == 0)
871 return false; // subclass not present in mask
872 }
873 }
874
875 if (isEnchantSpell && spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
876 {
877 // Special case - accept weapon type for main and offhand requirements
878 if (proto->GetInventoryType() == INVTYPE_WEAPON &&
881 return true;
882 else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->GetInventoryType())) == 0)
883 return false; // inventory type not present in mask
884 }
885
886 return true;
887}
888
889void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster /*= ObjectGuid::Empty*/)
890{
891 // Better lost small time at check in comparison lost time at item save to DB.
892 if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
893 return;
894
895 Player* owner = GetOwner();
897 {
898 if (uint32 oldEnchant = GetEnchantmentId(slot))
900
901 if (id)
902 owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetEntry(), id);
903 }
904
908 SetState(ITEM_CHANGED, owner);
909}
910
912{
913 if (GetEnchantmentDuration(slot) == duration)
914 return;
915
917 SetState(ITEM_CHANGED, owner);
918 // Cannot use GetOwner() here, has to be passed as an argument to avoid freeze due to hashtable locking
919}
920
929
939
941{
942 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
943 {
945
946 if (!SocketColor) // no socket slot
947 continue;
948
949 uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
950 if (!enchant_id) // no gems on this socket
951 return false;
952
953 SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
954 if (!enchantEntry) // invalid gem id on this socket
955 return false;
956
957 uint8 GemColor = 0;
958
959 uint32 gemid = enchantEntry->SrcItemID;
960 if (gemid)
961 {
962 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemid);
963 if (gemProto)
964 {
965 GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GetGemProperties());
966 if (gemProperty)
967 GemColor = gemProperty->Type;
968 }
969 }
970
971 if (!(GemColor & SocketColor)) // bad gem color on this socket
972 return false;
973 }
974 return true;
975}
976
978{
979 uint8 count = 0;
980 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
981 {
982 uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
983 if (!enchant_id)
984 continue;
985
986 SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
987 if (!enchantEntry)
988 continue;
989
990 if (GemID == enchantEntry->SrcItemID)
991 ++count;
992 }
993 return count;
994}
995
997{
998 uint8 count = 0;
999 for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot)
1000 {
1001 uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
1002 if (!enchant_id)
1003 continue;
1004
1005 SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1006 if (!enchantEntry)
1007 continue;
1008
1009 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(enchantEntry->SrcItemID);
1010 if (!gemProto)
1011 continue;
1012
1013 if (gemProto->GetItemLimitCategory() == limitCategory)
1014 ++count;
1015 }
1016 return count;
1017}
1018
1019bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
1020{
1021 ItemTemplate const* proto = GetTemplate();
1022 return proto && ((proto->GetMap() && proto->GetMap() != cur_mapId) || (proto->GetArea() && proto->GetArea() != cur_zoneId));
1023}
1024
1026{
1027 WorldPacket data(SMSG_SOCKET_GEMS_RESULT, 8+4+4+4+4);
1028 data << GetGUID();
1031
1032 GetOwner()->SendDirectMessage(&data);
1033}
1034
1035// Though the client has the information in the item's data field,
1036// we have to send SMSG_ITEM_TIME_UPDATE to display the remaining
1037// time.
1039{
1041 if (!duration)
1042 return;
1043
1045 itemTimeUpdate.ItemGuid = GetGUID();
1046 itemTimeUpdate.DurationLeft = duration;
1047 owner->SendDirectMessage(itemTimeUpdate.Write());
1048}
1049
1050Item* Item::CreateItem(uint32 itemEntry, uint32 count, Player const* player /*= nullptr*/)
1051{
1052 if (count < 1)
1053 return nullptr; //don't create item at zero count
1054
1055 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry);
1056 if (proto)
1057 {
1058 if (count > proto->GetMaxStackSize())
1059 count = proto->GetMaxStackSize();
1060
1061 ASSERT_NODEBUGINFO(count != 0 && "pProto->Stackable == 0 but checked at loading already");
1062
1063 Item* item = NewItemOrBag(proto);
1064 if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), itemEntry, player))
1065 {
1066 item->SetCount(count);
1067 return item;
1068 }
1069 else
1070 delete item;
1071 }
1072 else
1073 ABORT();
1074 return nullptr;
1075}
1076
1077Item* Item::CloneItem(uint32 count, Player const* player /*= nullptr*/) const
1078{
1079 Item* newItem = CreateItem(GetEntry(), count, player);
1080 if (!newItem)
1081 return nullptr;
1082
1083 newItem->SetCreator(GetCreator());
1084 newItem->SetGiftCreator(GetGiftCreator());
1087 // player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
1088 if (player)
1090 return newItem;
1091}
1092
1093bool Item::IsBindedNotWith(Player const* player) const
1094{
1095 // not binded item
1096 if (!IsSoulBound())
1097 return false;
1098
1099 // own item
1100 if (GetOwnerGUID() == player->GetGUID())
1101 return false;
1102
1103 if (IsBOPTradeable())
1104 if (allowedGUIDs.find(player->GetGUID()) != allowedGUIDs.end())
1105 return false;
1106
1107 // BOA item case
1108 if (IsBoundAccountWide())
1109 return false;
1110
1111 return true;
1112}
1113
1115{
1116 if (Player* owner = GetOwner())
1117 BuildFieldsUpdate(owner, data_map);
1118 ClearUpdateMask(false);
1119}
1120
1122{
1123 if (Player* owner = GetOwner())
1124 {
1125 owner->GetMap()->AddUpdateObject(this);
1126 return true;
1127 }
1128
1129 return false;
1130}
1131
1133{
1134 if (Player* owner = GetOwner())
1135 owner->GetMap()->RemoveUpdateObject(this);
1136}
1137
1139{
1141}
1142
1144{
1145 return proto->GetBuyPrice();
1146}
1147
1148uint32 Item::GetSellPrice(bool forVendor /*= false*/) const
1149{
1150 ItemTemplate const* itemTemplate = GetTemplate();
1151 int32 price = Item::GetSellPrice(itemTemplate);
1152 if (price && forVendor)
1153 {
1154 auto effectWithCharges = std::ranges::find_if(itemTemplate->Effects,
1155 [](ItemEffect const& itemEffect) { return itemEffect.SpellID && itemEffect.TriggerType == ITEM_SPELLTRIGGER_ON_USE && itemEffect.Charges < 0; });
1156
1157 if (effectWithCharges != itemTemplate->Effects.end())
1158 price = price * GetSpellCharges(std::ranges::distance(itemTemplate->Effects.begin(), effectWithCharges)) / effectWithCharges->Charges;
1159
1160 int32 repairCost = CalculateDurabilityRepairCost(1.0f, false);
1161 if (repairCost < price)
1162 price -= repairCost;
1163 else
1164 price = 1;
1165 }
1166
1167 return price;
1168}
1169
1171{
1172 return proto->GetSellPrice();
1173}
1174
1176{
1177 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1178
1180 stmt->setUInt32(0, GetGUID().GetCounter());
1181 trans->Append(stmt);
1182
1183 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_REFUND_INSTANCE);
1184 stmt->setUInt32(0, GetGUID().GetCounter());
1185 stmt->setUInt32(1, GetRefundRecipient().GetCounter());
1186 stmt->setUInt32(2, GetPaidMoney());
1188 trans->Append(stmt);
1189
1190 CharacterDatabase.CommitTransaction(trans);
1191}
1192
1194{
1195 if (trans)
1196 {
1198 stmt->setUInt32(0, GetGUID().GetCounter());
1199 (*trans)->Append(stmt);
1200
1201 }
1202}
1203
1204void Item::SetNotRefundable(Player* owner, bool changestate /*=true*/, CharacterDatabaseTransaction* trans /*=nullptr*/)
1205{
1206 if (!IsRefundable())
1207 return;
1208
1210 // Following is not applicable in the trading procedure
1211 if (changestate)
1212 SetState(ITEM_CHANGED, owner);
1213
1215 SetPaidMoney(0);
1218
1220}
1221
1223{
1224 /* Here we update our played time
1225 We simply add a number to the current played time,
1226 based on the time elapsed since the last update hereof.
1227 */
1228 // Get current played time
1230 // Calculate time elapsed since last played time update
1231 time_t curtime = GameTime::GetGameTime();
1232 uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
1233 uint32 new_playtime = current_playtime + elapsed;
1234 // Check if the refund timer has expired yet
1235 if (new_playtime <= 2*HOUR)
1236 {
1237 // No? Proceed.
1238 // Update the data field
1239 SetCreatePlayedTime(new_playtime);
1240 // Flag as changed to get saved to DB
1241 SetState(ITEM_CHANGED, owner);
1242 // Speaks for itself
1243 m_lastPlayedTimeUpdate = curtime;
1244 return;
1245 }
1246 // Yes
1247 SetNotRefundable(owner);
1248}
1249
1251{
1252 time_t curtime = GameTime::GetGameTime();
1253 uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
1255}
1256
1258{
1259 return (GetPlayedTime() > 2*HOUR);
1260}
1261
1262void Item::SetSoulboundTradeable(GuidSet const& allowedLooters)
1263{
1265 allowedGUIDs = allowedLooters;
1266}
1267
1269{
1271 if (allowedGUIDs.empty())
1272 return;
1273
1274 allowedGUIDs.clear();
1275 SetState(ITEM_CHANGED, currentOwner);
1277 stmt->setUInt32(0, GetGUID().GetCounter());
1278 CharacterDatabase.Execute(stmt);
1279}
1280
1282{
1283 // called from owner's update - GetOwner() MUST be valid
1284 if (GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME) + 2*HOUR < GetOwner()->GetTotalPlayedTime())
1285 {
1287 return true; // remove from tradeable list
1288 }
1289
1290 return false;
1291}
1292
1294{
1296
1297 if (Player* player = GetOwner())
1298 {
1299 if (TradeData* tradeData = player->GetTradeData())
1300 {
1301 TradeSlots slot = tradeData->GetTradeSlotForItem(GetGUID());
1302
1303 if (slot != TRADE_SLOT_INVALID)
1304 tradeData->SetItem(slot, this, true);
1305 }
1306 }
1307}
1308
1309std::string Item::GetDebugInfo() const
1310{
1311 std::stringstream sstr;
1312 sstr << Object::GetDebugInfo() << "\n"
1313 << std::boolalpha
1314 << "Owner: " << GetOwnerGUID().ToString() << " Count: " << GetCount()
1315 << " BagSlot: " << std::to_string(GetBagSlot()) << " Slot: " << std::to_string(GetSlot()) << " Equipped: " << IsEquipped();
1316 return sstr.str();
1317}
Item * NewItemOrBag(ItemTemplate const *proto)
Definition Bag.h:69
@ 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
LocaleConstant
Definition Common.h:48
@ HOUR
Definition Common.h:30
@ ENCHANTMENT_CAN_SOULBOUND
Definition DBCEnums.h:392
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
ItemFieldFlags
@ 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:43
bool ItemCanGoIntoBag(ItemTemplate const *pProto, ItemTemplate const *pBagProto)
Definition Item.cpp:183
void RemoveItemsSetItem(Player *player, ItemTemplate const *proto)
Definition Item.cpp:125
void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:696
void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:675
#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:579
#define INVENTORY_SLOT_BAG_0
Definition Player.h:555
#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
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:1309
std::string const & GetNameForLocaleIdx(LocaleConstant locale) const override
Definition Item.cpp:297
uint32 GetEnchantRequiredLevel() const
Definition Item.cpp:811
uint32 GetPlayedTime()
Definition Item.cpp:1250
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:529
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition Item.cpp:644
uint32 GetPaidExtendedCost() const
Definition Item.h:212
uint8 GetSlot() const
Definition Item.h:143
void SetItemFlag(ItemFieldFlags flags)
Definition Item.h:92
void UpdateItemSuffixFactor()
Definition Item.cpp:636
bool IsWrapped() const
Definition Item.h:115
uint32 CalculateDurabilityRepairCost(float discount, bool useRateConfig=true) const
Definition Item.cpp:752
void SetSpellCharges(uint8 index, int32 value)
Definition Item.h:180
bool AddToObjectUpdate() override
Definition Item.cpp:1121
void SetText(std::string const &text)
Definition Item.h:170
virtual bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field *fields, uint32 entry)
Definition Item.cpp:415
void UpdateDuration(Player *owner, uint32 diff)
Definition Item.cpp:311
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:329
void ReplaceAllItemFlags(ItemFieldFlags flags)
Definition Item.h:94
void BuildUpdate(UpdateDataMapType &) override
Definition Item.cpp:1114
bool IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
Definition Item.cpp:1019
void RemoveItemFlag(ItemFieldFlags flags)
Definition Item.h:93
Item()
Definition Item.cpp:248
void DeleteRefundDataFromDB(CharacterDatabaseTransaction *trans)
Definition Item.cpp:1193
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition Item.h:165
int32 GetSpellCharges(uint8 index=0) const
Definition Item.h:179
static Item * CreateItem(uint32 itemEntry, uint32 count, Player const *player=nullptr)
Definition Item.cpp:1050
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition Item.cpp:1077
Bag * m_container
Definition Item.h:242
void SetItemRandomProperties(int32 randomPropId)
Definition Item.cpp:598
void SetPaidMoney(uint32 money)
Definition Item.h:207
uint8 GetGemCountWithID(uint32 GemID) const
Definition Item.cpp:977
bool IsBoundAccountWide() const
Definition Item.h:97
bool mb_in_trade
Definition Item.h:245
Bag * ToBag()
Definition Item.h:110
std::string m_text
Definition Item.h:240
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition Item.cpp:727
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const
Definition Item.h:166
void SetCount(uint32 value)
Definition Item.cpp:1293
void SetDurability(uint32 durability)
Definition Item.h:121
int32 GetItemRandomPropertyId() const
Definition Item.h:157
ObjectGuid GetCreator() const
Definition Item.h:82
ItemTemplate const * GetTemplate() const
Definition Item.cpp:541
bool IsBOPTradeable() const
Definition Item.h:114
bool IsInBag() const
Definition Item.h:150
bool IsSoulBound() const
Definition Item.h:96
void SaveRefundDataToDB()
Definition Item.cpp:1175
void SetNotRefundable(Player *owner, bool changestate=true, CharacterDatabaseTransaction *trans=nullptr)
Definition Item.cpp:1204
uint32 GetItemSuffixFactor() const
Definition Item.h:158
friend void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:696
bool IsBindedNotWith(Player const *player) const
Definition Item.cpp:1093
uint32 m_paidMoney
Definition Item.h:248
bool IsEquipped() const
Definition Item.cpp:722
void SendTimeUpdate(Player *owner)
Definition Item.cpp:1038
uint32 GetSpell()
Definition Item.cpp:558
bool IsRefundExpired()
Definition Item.cpp:1257
void UpdatePlayedTime(Player *owner)
Definition Item.cpp:1222
uint32 GetBuyPrice() const
Definition Item.cpp:1138
Player * GetOwner() const
Definition Item.cpp:546
ObjectGuid GetOwnerGUID() const
Definition Item.h:78
bool HasEnchantRequiredSkill(Player const *player) const
Definition Item.cpp:799
time_t m_lastPlayedTimeUpdate
Definition Item.h:246
uint32 GetSkill()
Definition Item.cpp:552
bool IsRefundable() const
Definition Item.h:113
uint16 GetPos() const
Definition Item.h:147
bool GemsFitSockets() const
Definition Item.cpp:940
bool IsBoundByEnchant() const
Definition Item.cpp:825
void SetSoulboundTradeable(GuidSet const &allowedLooters)
Definition Item.cpp:1262
int16 uQueuePos
Definition Item.h:244
void SetContainedIn(ObjectGuid guid)
Definition Item.h:81
ObjectGuid GetGiftCreator() const
Definition Item.h:84
uint32 GetSellPrice(bool forVendor=false) const
Definition Item.cpp:1148
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
Definition Item.cpp:921
void SetMaxDurability(uint32 maxDurability)
Definition Item.h:122
uint32 m_paidExtendedCost
Definition Item.h:249
bool IsBag() const
Definition Item.h:117
void RemoveFromObjectUpdate() override
Definition Item.cpp:1132
void ClearEnchantment(EnchantmentSlot slot)
Definition Item.cpp:930
void SetCreator(ObjectGuid guid)
Definition Item.h:83
ObjectGuid const & GetRefundRecipient() const
Definition Item.h:210
void SetCreatePlayedTime(uint32 createPlayedTime)
Definition Item.h:176
void SendUpdateSockets()
Definition Item.cpp:1025
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player *owner)
Definition Item.cpp:911
InventoryResult CanBeMergedPartlyWith(ItemTemplate const *proto) const
Definition Item.cpp:836
void SetPaidExtendedCost(uint32 iece)
Definition Item.h:208
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const
Definition Item.h:167
void SetRefundRecipient(ObjectGuid const &guid)
Definition Item.h:206
virtual bool Create(ObjectGuid::LowType guidlow, uint32 itemId, Player const *owner)
Definition Item.cpp:268
uint32 GetPaidMoney() const
Definition Item.h:211
uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const
Definition Item.cpp:996
void ClearSoulboundTradeable(Player *currentOwner)
Definition Item.cpp:1268
bool IsNotEmptyBag() const
Definition Item.cpp:304
bool m_lootGenerated
Definition Item.h:183
uint32 GetCount() const
Definition Item.h:136
void SetExpiration(uint32 expiration)
Definition Item.h:88
bool CheckSoulboundTradeExpire()
Definition Item.cpp:1281
void SetOwnerGUID(ObjectGuid guid)
Definition Item.h:79
Loot loot
Definition Item.h:182
uint8 GetBagSlot() const
Definition Item.cpp:717
void SetGiftCreator(ObjectGuid guid)
Definition Item.h:85
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster=ObjectGuid::Empty)
Definition Item.cpp:889
static void DeleteFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:512
uint8 m_slot
Definition Item.h:241
friend void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:675
bool IsInUpdateQueue() const
Definition Item.h:188
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition Item.cpp:853
GuidSet allowedGUIDs
Definition Item.h:250
ItemUpdateState uState
Definition Item.h:243
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:484
uint16 m_objectType
Definition Object.h:234
int32 GetInt32Value(uint16 index) const
Definition Object.cpp:235
void SetInt32Value(uint16 index, int32 value)
Definition Object.cpp:564
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:241
uint16 m_valuesCount
Definition Object.h:248
void ClearUpdateMask(bool remove)
Definition Object.cpp:471
bool _LoadIntoDataField(std::string const &data, uint32 startOffset, uint32 count)
Definition Object.cpp:543
uint32 GetEntry() const
Definition Object.h:81
virtual std::string GetDebugInfo() const
Definition Object.cpp:900
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:577
uint16 m_updateFlag
Definition Object.h:237
ObjectGuid GetGUID() const
Definition Object.h:79
TypeID m_objectTypeId
Definition Object.h:236
ObjectGuid GetGuidValue(uint16 index) const
Definition Object.cpp:273
std::vector< Item * > m_itemUpdateQueue
Definition Player.h:2374
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6163
uint16 GetSkillValue(uint32 skill) const
Definition Player.cpp:5906
WorldSession * GetSession() const
Definition Player.h:1705
void DestroyItem(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:12111
std::vector< ItemSetEffect * > ItemSetEff
Definition Player.h:1957
static bool IsBagPos(uint16 pos)
Definition Player.cpp:9696
void ApplyEquipSpell(SpellInfo const *spellInfo, Item *item, bool apply, bool form_change=false)
Definition Player.cpp:7594
void DeleteRefundReference(ObjectGuid it)
Definition Player.cpp:25868
bool m_itemUpdateQueueBlocked
Definition Player.h:2375
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
WorldPacket const * Write() override
void SendEnchantmentLog(ObjectGuid target, ObjectGuid caster, uint32 itemId, uint32 enchantId)
@ SMSG_SOCKET_GEMS_RESULT
Definition Opcodes.h:1320
#define sWorld
Definition World.h:901
@ RATE_REPAIRCOST
Definition World.h:434
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 GetBaseItemLevel() const
uint32 GetQuality() const
uint32 GetDuration() const
uint32 GetGemProperties() const
uint32 GetId() const
uint32 GetMaxStackSize() const
SocketColor GetSocketColor(uint32 index) const
uint32 GetBuyPrice() const
ItemBondingType GetBonding() const
uint32 GetItemSet() const
bool IsArmorVellum() const
uint32 GetMap() const
std::string const & GetName(LocaleConstant locale) const
uint32 GetItemLimitCategory() const
uint32 GetSubClass() const
uint32 GetSellPrice() const
::InventoryType GetInventoryType() const
uint32 GetArea() const
uint32 MaxDurability
uint32 GetClass() const
bool IsWeaponVellum() const
uint32 GetSkill() const
uint32 GetBagFamily() const
bool isLooted() const
Definition Loot.h:256