TrinityCore
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 "ArtifactPackets.h"
21#include "AzeriteItem.h"
22#include "Bag.h"
23#include "CollectionMgr.h"
24#include "Common.h"
25#include "ConditionMgr.h"
26#include "Containers.h"
27#include "DatabaseEnv.h"
28#include "DB2Stores.h"
29#include "GameTables.h"
30#include "GameTime.h"
31#include "ItemBonusMgr.h"
32#include "ItemEnchantmentMgr.h"
33#include "ItemPackets.h"
34#include "Log.h"
35#include "Loot.h"
36#include "LootItemStorage.h"
37#include "LootMgr.h"
38#include "Map.h"
39#include "ObjectAccessor.h"
40#include "ObjectMgr.h"
41#include "Player.h"
42#include "ScriptMgr.h"
43#include "SpellInfo.h"
44#include "SpellMgr.h"
45#include "StringConvert.h"
46#include "TradeData.h"
47#include "UpdateData.h"
48#include "World.h"
49#include "WorldSession.h"
50#include <sstream>
51
53{
54 if (proto->GetInventoryType() == INVTYPE_BAG)
55 return new Bag();
56
57 if (sDB2Manager.IsAzeriteItem(proto->GetId()))
58 return new AzeriteItem();
59
60 if (sDB2Manager.GetAzeriteEmpoweredItem(proto->GetId()))
61 return new AzeriteEmpoweredItem();
62
63 return new Item();
64}
65
66void AddItemsSetItem(Player* player, Item const* item)
67{
68 ItemTemplate const* proto = item->GetTemplate();
69 uint32 setid = proto->GetItemSet();
70
71 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
72
73 if (!set)
74 {
75 TC_LOG_ERROR("sql.sql", "Item set {} for item (id {}) not found, mods not applied.", setid, proto->GetId());
76 return;
77 }
78
79 if (set->RequiredSkill && player->GetSkillValue(set->RequiredSkill) < set->RequiredSkillRank)
80 return;
81
83 return;
84
85 // Check player level for heirlooms
86 if (sDB2Manager.GetHeirloomByItemId(item->GetEntry()))
87 {
89 {
90 uint32 maxLevel = sDB2Manager.GetCurveXAxisRange(item->GetBonus()->PlayerLevelToItemLevelCurveId).second;
91
92 if (Optional<ContentTuningLevels> contentTuning = sDB2Manager.GetContentTuningData(item->GetBonus()->ContentTuningId, player->m_playerData->CtrOptions->ContentTuningConditionMask, true))
93 maxLevel = std::min<uint32>(maxLevel, contentTuning->MaxLevel);
94
95 if (player->GetLevel() > maxLevel)
96 return;
97 }
98 }
99
100 ItemSetEffect* eff = nullptr;
101
102 for (size_t x = 0; x < player->ItemSetEff.size(); ++x)
103 {
104 if (player->ItemSetEff[x] && player->ItemSetEff[x]->ItemSetID == setid)
105 {
106 eff = player->ItemSetEff[x];
107 break;
108 }
109 }
110
111 if (!eff)
112 {
113 eff = new ItemSetEffect();
114 eff->ItemSetID = setid;
115
116 size_t x = 0;
117 for (; x < player->ItemSetEff.size(); ++x)
118 if (!player->ItemSetEff[x])
119 break;
120
121 if (x < player->ItemSetEff.size())
122 player->ItemSetEff[x] = eff;
123 else
124 player->ItemSetEff.push_back(eff);
125 }
126
127 eff->EquippedItems.insert(item);
128
129 if (std::vector<ItemSetSpellEntry const*> const* itemSetSpells = sDB2Manager.GetItemSetSpells(setid))
130 {
131 for (ItemSetSpellEntry const* itemSetSpell : *itemSetSpells)
132 {
133 //not enough for spell
134 if (itemSetSpell->Threshold > eff->EquippedItems.size())
135 continue;
136
137 if (eff->SetBonuses.count(itemSetSpell))
138 continue;
139
140 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
141 if (!spellInfo)
142 {
143 TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id {} in items set {} effects", itemSetSpell->SpellID, setid);
144 continue;
145 }
146
147 eff->SetBonuses.insert(itemSetSpell);
148 // spell cast only if fit form requirement, in other case will cast at form change
149 if (!itemSetSpell->ChrSpecID || ChrSpecialization(itemSetSpell->ChrSpecID) == player->GetPrimarySpecialization())
150 player->ApplyEquipSpell(spellInfo, nullptr, true);
151 }
152 }
153}
154
155void RemoveItemsSetItem(Player* player, Item const* item)
156{
157 uint32 setid = item->GetTemplate()->GetItemSet();
158
159 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
160
161 if (!set)
162 {
163 TC_LOG_ERROR("sql.sql", "Item set #{} for item #{} not found, mods not removed.", setid, item->GetEntry());
164 return;
165 }
166
167 ItemSetEffect* eff = nullptr;
168 size_t setindex = 0;
169 for (; setindex < player->ItemSetEff.size(); setindex++)
170 {
171 if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->ItemSetID == setid)
172 {
173 eff = player->ItemSetEff[setindex];
174 break;
175 }
176 }
177
178 // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
179 if (!eff)
180 return;
181
182 eff->EquippedItems.erase(item);
183
184 if (std::vector<ItemSetSpellEntry const*> const* itemSetSpells = sDB2Manager.GetItemSetSpells(setid))
185 {
186 for (ItemSetSpellEntry const* itemSetSpell : *itemSetSpells)
187 {
188 // enough for spell
189 if (itemSetSpell->Threshold <= eff->EquippedItems.size())
190 continue;
191
192 if (!eff->SetBonuses.count(itemSetSpell))
193 continue;
194
195 player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE), nullptr, false);
196 eff->SetBonuses.erase(itemSetSpell);
197 }
198 }
199
200 if (eff->EquippedItems.empty()) //all items of a set were removed
201 {
202 ASSERT(eff == player->ItemSetEff[setindex]);
203 delete eff;
204 player->ItemSetEff[setindex] = nullptr;
205 }
206}
207
208bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
209{
210 if (!pProto || !pBagProto)
211 return false;
212
213 switch (pBagProto->GetClass())
214 {
216 switch (pBagProto->GetSubClass())
217 {
219 return true;
221 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_SOUL_SHARDS))
222 return false;
223 return true;
225 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_HERBS))
226 return false;
227 return true;
230 return false;
231 return true;
233 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_MINING_SUPP))
234 return false;
235 return true;
238 return false;
239 return true;
241 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_GEMS))
242 return false;
243 return true;
246 return false;
247 return true;
250 return false;
251 return true;
254 return false;
255 return true;
258 return false;
259 return true;
261 return pProto->IsCraftingReagent();
262 default:
263 return false;
264 }
266 switch (pBagProto->GetSubClass())
267 {
269 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_ARROWS))
270 return false;
271 return true;
273 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_BULLETS))
274 return false;
275 return true;
276 default:
277 return false;
278 }
279 }
280 return false;
281}
282
284{
290};
291
293{
299};
300
302{
308};
309
310void ItemAdditionalLoadInfo::Init(std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo>* loadInfo,
311 PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult,
312 PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult,
313 PreparedQueryResult azeriteEmpoweredItemResult)
314{
315 // 0 1 2 3 4 5
316 // SELECT a.itemGuid, a.xp, a.artifactAppearanceId, a.artifactTierId, ap.artifactPowerId, ap.purchasedRank FROM item_instance_artifact_powers ap LEFT JOIN item_instance_artifact a ON ap.itemGuid = a.itemGuid ...
317 if (artifactResult)
318 {
319 do
320 {
321 Field* fields = artifactResult->Fetch();
322 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
323 if (!info.Artifact)
324 info.Artifact.emplace();
325 info.Artifact->Xp = fields[1].GetUInt64();
326 info.Artifact->ArtifactAppearanceId = fields[2].GetUInt32();
327 info.Artifact->ArtifactTierId = fields[3].GetUInt32();
328 ArtifactPowerData artifactPowerData;
329 artifactPowerData.ArtifactPowerId = fields[4].GetUInt32();
330 artifactPowerData.PurchasedRank = fields[5].GetUInt8();
331 if (ArtifactPowerEntry const* artifactPower = sArtifactPowerStore.LookupEntry(artifactPowerData.ArtifactPowerId))
332 {
333 uint32 maxRank = artifactPower->MaxPurchasableRank;
334 // allow ARTIFACT_POWER_FLAG_FINAL to overflow maxrank here - needs to be handled in Item::CheckArtifactUnlock (will refund artifact power)
335 if (artifactPower->Flags & ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER && artifactPower->Tier < info.Artifact->ArtifactTierId)
336 maxRank += info.Artifact->ArtifactTierId - artifactPower->Tier;
337
338 if (artifactPowerData.PurchasedRank > maxRank)
339 artifactPowerData.PurchasedRank = maxRank;
340
341 artifactPowerData.CurrentRankWithBonus = (artifactPower->Flags & ARTIFACT_POWER_FLAG_FIRST) == ARTIFACT_POWER_FLAG_FIRST ? 1 : 0;
342
343 info.Artifact->ArtifactPowers.push_back(artifactPowerData);
344 }
345
346 } while (artifactResult->NextRow());
347 }
348
349 // 0 1 2 3
350 // SELECT iz.itemGuid, iz.xp, iz.level, iz.knowledgeLevel,
351 // 4 5 6 7 8
352 // iz.selectedAzeriteEssences1specId, iz.selectedAzeriteEssences1azeriteEssenceId1, iz.selectedAzeriteEssences1azeriteEssenceId2, iz.selectedAzeriteEssences1azeriteEssenceId3, iz.selectedAzeriteEssences1azeriteEssenceId4,
353 // 9 10 11 12 13
354 // iz.selectedAzeriteEssences2specId, iz.selectedAzeriteEssences2azeriteEssenceId1, iz.selectedAzeriteEssences2azeriteEssenceId2, iz.selectedAzeriteEssences2azeriteEssenceId3, iz.selectedAzeriteEssences2azeriteEssenceId4,
355 // 14 15 16 17 18
356 // iz.selectedAzeriteEssences3specId, iz.selectedAzeriteEssences3azeriteEssenceId1, iz.selectedAzeriteEssences3azeriteEssenceId2, iz.selectedAzeriteEssences3azeriteEssenceId3, iz.selectedAzeriteEssences3azeriteEssenceId4,
357 // 19 20 21 22 23
358 // iz.selectedAzeriteEssences4specId, iz.selectedAzeriteEssences4azeriteEssenceId1, iz.selectedAzeriteEssences4azeriteEssenceId2, iz.selectedAzeriteEssences4azeriteEssenceId3, iz.selectedAzeriteEssences4azeriteEssenceId4
359 // FROM item_instance_azerite iz INNER JOIN ...
360 if (azeriteItemResult)
361 {
362 do
363 {
364 Field* fields = azeriteItemResult->Fetch();
365 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
366 if (!info.AzeriteItem)
367 info.AzeriteItem.emplace();
368 info.AzeriteItem->Xp = fields[1].GetUInt64();
369 info.AzeriteItem->Level = fields[2].GetUInt32();
370 info.AzeriteItem->KnowledgeLevel = fields[3].GetUInt32();
371 for (std::size_t i = 0; i < info.AzeriteItem->SelectedAzeriteEssences.size(); ++i)
372 {
373 uint32 specializationId = fields[4 + i * 4].GetUInt32();
374 if (!sChrSpecializationStore.LookupEntry(specializationId))
375 continue;
376
377 info.AzeriteItem->SelectedAzeriteEssences[i].SpecializationId = specializationId;
378 for (std::size_t j = 0; j < MAX_AZERITE_ESSENCE_SLOT; ++j)
379 {
380 AzeriteEssenceEntry const* azeriteEssence = sAzeriteEssenceStore.LookupEntry(fields[5 + i * 5 + j].GetUInt32());
381 if (!azeriteEssence || !sDB2Manager.IsSpecSetMember(azeriteEssence->SpecSetID, specializationId))
382 continue;
383
384 info.AzeriteItem->SelectedAzeriteEssences[i].AzeriteEssenceId[j] = azeriteEssence->ID;
385 }
386 }
387
388 } while (azeriteItemResult->NextRow());
389 }
390
391 // 0 1
392 // SELECT iamp.itemGuid, iamp.azeriteItemMilestonePowerId FROM item_instance_azerite_milestone_power iamp INNER JOIN ...
393 if (azeriteItemMilestonePowersResult)
394 {
395 do
396 {
397 Field* fields = azeriteItemMilestonePowersResult->Fetch();
398 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
399 if (!info.AzeriteItem)
400 info.AzeriteItem.emplace();
401 info.AzeriteItem->AzeriteItemMilestonePowers.push_back(fields[1].GetUInt32());
402 }
403 while (azeriteItemMilestonePowersResult->NextRow());
404 }
405
406 // 0 1 2
407 // SELECT iaue.itemGuid, iaue.azeriteEssenceId, iaue.`rank` FROM item_instance_azerite_unlocked_essence iaue INNER JOIN ...
408 if (azeriteItemUnlockedEssencesResult)
409 {
410 do
411 {
412 Field* fields = azeriteItemUnlockedEssencesResult->Fetch();
413 if (AzeriteEssencePowerEntry const* azeriteEssencePower = sDB2Manager.GetAzeriteEssencePower(fields[1].GetUInt32(), fields[2].GetUInt32()))
414 {
415 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
416 if (!info.AzeriteItem)
417 info.AzeriteItem.emplace();
418
419 info.AzeriteItem->UnlockedAzeriteEssences.push_back(azeriteEssencePower);
420 }
421 }
422 while (azeriteItemUnlockedEssencesResult->NextRow());
423 }
424
425 // 0 1 2 3 4 5
426 // SELECT iae.itemGuid, iae.azeritePowerId1, iae.azeritePowerId2, iae.azeritePowerId3, iae.azeritePowerId4, iae.azeritePowerId5 FROM item_instance_azerite_empowered iae INNER JOIN ...
427 if (azeriteEmpoweredItemResult)
428 {
429 do
430 {
431 Field* fields = azeriteEmpoweredItemResult->Fetch();
432 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
433 if (!info.AzeriteEmpoweredItem)
434 info.AzeriteEmpoweredItem.emplace();
435
436 for (uint32 i = 0; i < MAX_AZERITE_EMPOWERED_TIER; ++i)
437 if (sAzeritePowerStore.LookupEntry(fields[1 + i].GetInt32()))
438 info.AzeriteEmpoweredItem->SelectedAzeritePowers[i] = fields[1 + i].GetInt32();
439
440 } while (azeriteEmpoweredItemResult->NextRow());
441 }
442}
443
445{
448
449 m_slot = 0;
451 uQueuePos = -1;
452 m_container = nullptr;
453 m_lootGenerated = false;
454 mb_in_trade = false;
456
457 m_paidMoney = 0;
459
461 m_gemScalingLevels = { };
462
463 memset(&_bonusData, 0, sizeof(_bonusData));
464}
465
466Item::~Item() = default;
467
468bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, ItemContext context, Player const* owner)
469{
470 Object::_Create(ObjectGuid::Create<HighGuid::Item>(guidlow));
471
472 SetEntry(itemId);
473 SetObjectScale(1.0f);
474
475 if (owner)
476 {
477 SetOwnerGUID(owner->GetGUID());
478 SetContainedIn(owner->GetGUID());
479 }
480
481 ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemId);
482 if (!itemProto)
483 return false;
484
485 _bonusData.Initialize(itemProto);
486 SetCount(1);
488 SetDurability(itemProto->MaxDurability);
489
490 for (std::size_t i = 0; i < itemProto->Effects.size(); ++i)
491 if (itemProto->Effects[i]->LegacySlotIndex < 5)
492 SetSpellCharges(itemProto->Effects[i]->LegacySlotIndex, itemProto->Effects[i]->Charges);
493
494 SetExpiration(itemProto->GetDuration());
496 SetContext(context);
497
498 if (itemProto->GetArtifactID())
499 {
500 InitArtifactPowers(itemProto->GetArtifactID(), 0);
501 for (ArtifactAppearanceEntry const* artifactAppearance : sArtifactAppearanceStore)
502 {
503 if (ArtifactAppearanceSetEntry const* artifactAppearanceSet = sArtifactAppearanceSetStore.LookupEntry(artifactAppearance->ArtifactAppearanceSetID))
504 {
505 if (itemProto->GetArtifactID() != artifactAppearanceSet->ArtifactID)
506 continue;
507
508 if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(artifactAppearance->UnlockPlayerConditionID))
509 if (!owner || !sConditionMgr->IsPlayerMeetingCondition(owner, playerCondition))
510 continue;
511
512 SetModifier(ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID, artifactAppearance->ID);
513 SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID);
514 break;
515 }
516 }
517
518 CheckArtifactRelicSlotUnlock(owner ? owner : GetOwner());
519 }
520
521 return true;
522}
523
525{
526 ItemTemplate const* itemTemplate = GetTemplate();
528 return Trinity::StringFormat("{} {}", itemTemplate->GetName(locale), suffix->Description[locale]);
529
530 return itemTemplate->GetName(locale);
531}
532
533// Returns true if Item is a bag AND it is not empty.
534// Returns false if Item is not a bag OR it is an empty bag.
536{
537 if (Bag const* bag = ToBag())
538 return !bag->IsEmpty();
539 return false;
540}
541
543{
544 uint32 duration = m_itemData->Expiration;
545 if (!duration)
546 return;
547
548 TC_LOG_DEBUG("entities.player.items", "Item::UpdateDuration Item (Entry: {} Duration {} Diff {})", GetEntry(), duration, diff);
549
550 if (duration <= diff)
551 {
552 sScriptMgr->OnItemExpire(owner, GetTemplate());
553 owner->DestroyItem(GetBagSlot(), GetSlot(), true);
554 return;
555 }
556
557 SetExpiration(duration - diff);
558 SetState(ITEM_CHANGED, owner); // save new time in database
559}
560
562{
563 bool isInTransaction = bool(trans);
564 if (!isInTransaction)
565 trans = CharacterDatabase.BeginTransaction();
566
567 switch (uState)
568 {
569 case ITEM_NEW:
570 case ITEM_CHANGED:
571 {
572 uint8 index = 0;
574 stmt->setUInt32( index, GetEntry());
575 stmt->setUInt64(++index, GetOwnerGUID().GetCounter());
576 stmt->setUInt64(++index, GetCreator().GetCounter());
577 stmt->setUInt64(++index, GetGiftCreator().GetCounter());
578 stmt->setUInt32(++index, GetCount());
579 stmt->setUInt32(++index, m_itemData->Expiration);
580
581 std::ostringstream ssSpells;
582 for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount; ++i)
583 ssSpells << GetSpellCharges(i) << ' ';
584 stmt->setString(++index, ssSpells.str());
585
586 stmt->setUInt32(++index, m_itemData->DynamicFlags);
587
588 std::ostringstream ssEnchants;
589 for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
590 {
592 enchantment && !enchantment->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotSaveToDB))
593 {
594 ssEnchants << GetEnchantmentId(EnchantmentSlot(i)) << ' ';
595 ssEnchants << GetEnchantmentDuration(EnchantmentSlot(i)) << ' ';
596 ssEnchants << GetEnchantmentCharges(EnchantmentSlot(i)) << ' ';
597 }
598 else
599 {
600 ssEnchants << "0 0 0 ";
601 }
602 }
603 stmt->setString(++index, ssEnchants.str());
604
605 stmt->setUInt32(++index, m_randomBonusListId);
606 stmt->setUInt16(++index, m_itemData->Durability);
607 stmt->setUInt32(++index, m_itemData->CreatePlayedTime);
608 stmt->setString(++index, m_text);
613 stmt->setUInt8(++index, uint8(m_itemData->Context));
614
615 std::ostringstream bonusListIDs;
616 for (int32 bonusListID : GetBonusListIDs())
617 bonusListIDs << bonusListID << ' ';
618 stmt->setString(++index, bonusListIDs.str());
619
620 stmt->setUInt64(++index, GetGUID().GetCounter());
621
622 trans->Append(stmt);
623
624 if ((uState == ITEM_CHANGED) && IsWrapped())
625 {
626 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GIFT_OWNER);
627 stmt->setUInt64(0, GetOwnerGUID().GetCounter());
628 stmt->setUInt64(1, GetGUID().GetCounter());
629 trans->Append(stmt);
630 }
631
632 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
633 stmt->setUInt64(0, GetGUID().GetCounter());
634 trans->Append(stmt);
635
636 if (m_itemData->Gems.size())
637 {
638 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_GEMS);
639 stmt->setUInt64(0, GetGUID().GetCounter());
640 uint32 i = 0;
641 uint32 const gemFields = 4;
642 for (UF::SocketedGem const& gemData : m_itemData->Gems)
643 {
644 if (gemData.ItemID)
645 {
646 stmt->setUInt32(1 + i * gemFields, gemData.ItemID);
647 std::ostringstream gemBonusListIDs;
648 for (uint16 bonusListID : gemData.BonusListIDs)
649 if (bonusListID)
650 gemBonusListIDs << bonusListID << ' ';
651 stmt->setString(2 + i * gemFields, gemBonusListIDs.str());
652 stmt->setUInt8(3 + i * gemFields, gemData.Context);
653 stmt->setUInt32(4 + i * gemFields, m_gemScalingLevels[i]);
654 }
655 else
656 {
657 stmt->setUInt32(1 + i * gemFields, 0);
658 stmt->setString(2 + i * gemFields, "");
659 stmt->setUInt8(3 + i * gemFields, 0);
660 stmt->setUInt32(4 + i * gemFields, 0);
661 }
662 ++i;
663 }
664 for (; i < MAX_GEM_SOCKETS; ++i)
665 {
666 stmt->setUInt32(1 + i * gemFields, 0);
667 stmt->setString(2 + i * gemFields, "");
668 stmt->setUInt8(3 + i * gemFields, 0);
669 stmt->setUInt32(4 + i * gemFields, 0);
670 }
671 trans->Append(stmt);
672 }
673
674 static ItemModifier const transmogMods[18] =
675 {
682
689
696 };
697
698 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
699 stmt->setUInt64(0, GetGUID().GetCounter());
700 trans->Append(stmt);
701
702 if (std::find_if(std::begin(transmogMods), std::end(transmogMods), [this](ItemModifier modifier) { return GetModifier(modifier) != 0; }) != std::end(transmogMods))
703 {
704 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_TRANSMOG);
705 stmt->setUInt64(0, GetGUID().GetCounter());
724 trans->Append(stmt);
725 }
726
727 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
728 stmt->setUInt64(0, GetGUID().GetCounter());
729 trans->Append(stmt);
730
732 stmt->setUInt64(0, GetGUID().GetCounter());
733 trans->Append(stmt);
734
735 if (GetTemplate()->GetArtifactID())
736 {
737 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_ARTIFACT);
738 stmt->setUInt64(0, GetGUID().GetCounter());
739 stmt->setUInt64(1, m_itemData->ArtifactXP);
742 trans->Append(stmt);
743
744 for (UF::ArtifactPower const& artifactPower : m_itemData->ArtifactPowers)
745 {
747 stmt->setUInt64(0, GetGUID().GetCounter());
748 stmt->setUInt32(1, artifactPower.ArtifactPowerID);
749 stmt->setUInt8(2, artifactPower.PurchasedRank);
750 trans->Append(stmt);
751 }
752 }
753
754 static ItemModifier const modifiersTable[] =
755 {
758 };
759
760 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
761 stmt->setUInt64(0, GetGUID().GetCounter());
762 trans->Append(stmt);
763
764 if (std::find_if(std::begin(modifiersTable), std::end(modifiersTable), [this](ItemModifier modifier) { return GetModifier(modifier) != 0; }) != std::end(modifiersTable))
765 {
766 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_MODIFIERS);
767 stmt->setUInt64(0, GetGUID().GetCounter());
770 trans->Append(stmt);
771 }
772
773 break;
774 }
775 case ITEM_REMOVED:
776 {
778 stmt->setUInt64(0, GetGUID().GetCounter());
779 trans->Append(stmt);
780
781 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
782 stmt->setUInt64(0, GetGUID().GetCounter());
783 trans->Append(stmt);
784
785 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
786 stmt->setUInt64(0, GetGUID().GetCounter());
787 trans->Append(stmt);
788
789 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
790 stmt->setUInt64(0, GetGUID().GetCounter());
791 trans->Append(stmt);
792
794 stmt->setUInt64(0, GetGUID().GetCounter());
795 trans->Append(stmt);
796
797 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
798 stmt->setUInt64(0, GetGUID().GetCounter());
799 trans->Append(stmt);
800
801 if (IsWrapped())
802 {
803 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
804 stmt->setUInt64(0, GetGUID().GetCounter());
805 trans->Append(stmt);
806 }
807
808 if (!isInTransaction)
809 CharacterDatabase.CommitTransaction(trans);
810
811 // Delete the items if this is a container
812 if (m_loot && !m_loot->isLooted())
813 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
814
815 delete this;
816 return;
817 }
818 case ITEM_UNCHANGED:
819 break;
820 }
821
823
824 if (!isInTransaction)
825 CharacterDatabase.CommitTransaction(trans);
826}
827
828bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry)
829{
830 // 0 1 2 3 4 5 6 7 8 9 10 11 12
831 // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, text,
832 // 13 14 15 16 17 18
833 // battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs,
834 // 19 20 21 22 23 24
835 // itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4, itemModifiedAppearanceSpec5,
836 // 25 26 27 28 29 30
837 // spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, spellItemEnchantmentSpec5,
838 // 31 32 33
839 // secondaryItemModifiedAppearanceAllSpecs, secondaryItemModifiedAppearanceSpec1, secondaryItemModifiedAppearanceSpec2,
840 // 34 35 36
841 // secondaryItemModifiedAppearanceSpec3, secondaryItemModifiedAppearanceSpec4, secondaryItemModifiedAppearanceSpec5,
842 // 37 38 39 40 41 42 43 44 45 46 47 48
843 // gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
844 // 49 50
845 // fixedScalingLevel, artifactKnowledgeLevel FROM item_instance
846
847 // create item before any checks for store correct guid
848 // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
849 Object::_Create(ObjectGuid::Create<HighGuid::Item>(guid));
850
851 // Set entry, MUST be before proto check
852 SetEntry(entry);
853 SetObjectScale(1.0f);
854
855 ItemTemplate const* proto = GetTemplate();
856 if (!proto)
857 {
858 TC_LOG_ERROR("entities.item", "Invalid entry {} for item {}. Refusing to load.", GetEntry(), GetGUID().ToString());
859 return false;
860 }
861
862 _bonusData.Initialize(proto);
863
864 // set owner (not if item is only loaded for gbank/auction/mail
865 if (!ownerGuid.IsEmpty())
866 SetOwnerGUID(ownerGuid);
867
868 uint32 itemFlags = fields[7].GetUInt32();
869 bool need_save = false; // need explicit save data at load fixes
870 if (uint64 creator = fields[2].GetUInt64())
871 {
872 if (!(itemFlags & ITEM_FIELD_FLAG_CHILD))
873 SetCreator(ObjectGuid::Create<HighGuid::Player>(creator));
874 else
875 SetCreator(ObjectGuid::Create<HighGuid::Item>(creator));
876 }
877 if (uint64 giftCreator = fields[3].GetUInt64())
878 SetGiftCreator(ObjectGuid::Create<HighGuid::Player>(giftCreator));
879 SetCount(fields[4].GetUInt32());
880
881 uint32 duration = fields[5].GetUInt32();
882 SetExpiration(duration);
883 // update duration if need, and remove if not need
884 if ((proto->GetDuration() == 0) != (duration == 0))
885 {
886 SetExpiration(proto->GetDuration());
887 need_save = true;
888 }
889
891
892 uint32 durability = fields[10].GetUInt16();
893 SetDurability(durability);
894 // update max durability (and durability) if need
896
897 // do not overwrite durability for wrapped items
898 if (durability > proto->MaxDurability && !IsWrapped())
899 {
901 need_save = true;
902 }
903
904 SetCreatePlayedTime(fields[11].GetUInt32());
905 SetText(fields[12].GetString());
906
907 SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[13].GetUInt32());
908 SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[14].GetUInt32());
909 SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[15].GetUInt16());
910 SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[16].GetUInt32());
911
912 SetContext(ItemContext(fields[17].GetUInt8()));
913
914 std::vector<std::string_view> bonusListString = Trinity::Tokenize(fields[18].GetStringView(), ' ', false);
915 std::vector<int32> bonusListIDs;
916 bonusListIDs.reserve(bonusListString.size());
917 for (std::string_view token : bonusListString)
918 if (Optional<int32> bonusListID = Trinity::StringTo<int32>(token))
919 bonusListIDs.push_back(*bonusListID);
920 SetBonuses(std::move(bonusListIDs));
921
922 // load charges after bonuses, they can add more item effects
923 std::vector<std::string_view> tokens = Trinity::Tokenize(fields[6].GetStringView(), ' ', false);
924 for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount && i < tokens.size(); ++i)
925 SetSpellCharges(i, Trinity::StringTo<int32>(tokens[i]).value_or(0));
926
933
935 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, fields[26].GetUInt32());
936 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, fields[27].GetUInt32());
937 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, fields[28].GetUInt32());
938 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, fields[29].GetUInt32());
939 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5, fields[30].GetUInt32());
940
947
948 uint32 const gemFields = 4;
950 memset(gemData, 0, sizeof(gemData));
951 for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
952 {
953 gemData[i].ItemId = fields[37 + i * gemFields].GetUInt32();
954 std::vector<std::string_view> gemBonusListIDs = Trinity::Tokenize(fields[38 + i * gemFields].GetStringView(), ' ', false);
955 uint32 b = 0;
956 for (std::string_view token : gemBonusListIDs)
957 if (Optional<uint16> bonusListID = Trinity::StringTo<uint16>(token))
958 gemData[i].BonusListIDs[b++] = *bonusListID;
959
960 gemData[i].Context = fields[39 + i * gemFields].GetUInt8();
961 if (gemData[i].ItemId)
962 SetGem(i, &gemData[i], fields[40 + i * gemFields].GetUInt32());
963 }
964
965 SetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL, fields[49].GetUInt32());
967
968 // Enchants must be loaded after all other bonus/scaling data
969 std::vector<std::string_view> enchantmentTokens = Trinity::Tokenize(fields[8].GetStringView(), ' ', false);
970 if (enchantmentTokens.size() == MAX_ENCHANTMENT_SLOT * MAX_ENCHANTMENT_OFFSET)
971 {
972 for (uint32 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
973 {
974 auto enchantmentField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Enchantment, i);
975 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::ID), Trinity::StringTo<int32>(enchantmentTokens[i * MAX_ENCHANTMENT_OFFSET + 0]).value_or(0));
976 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Duration), Trinity::StringTo<uint32>(enchantmentTokens[i * MAX_ENCHANTMENT_OFFSET + 1]).value_or(0));
977 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Charges), Trinity::StringTo<int16>(enchantmentTokens[i * MAX_ENCHANTMENT_OFFSET + 2]).value_or(0));
978 }
979 }
980 m_randomBonusListId = fields[9].GetUInt32();
981
982 // Remove bind flag for items vs BIND_NONE set
983 if (IsSoulBound() && GetBonding() == BIND_NONE)
984 {
986 need_save = true;
987 }
988
989 if (need_save) // normal item changed state set not work at loading
990 {
991 uint8 index = 0;
993 stmt->setUInt32(index++, m_itemData->Expiration);
994 stmt->setUInt32(index++, m_itemData->DynamicFlags);
995 stmt->setUInt32(index++, m_itemData->Durability);
996 stmt->setUInt64(index++, guid);
997 CharacterDatabase.Execute(stmt);
998 }
999
1000 return true;
1001}
1002
1003void Item::LoadArtifactData(Player const* owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector<ArtifactPowerData>& powers)
1004{
1005 for (uint8 i = 0; i <= artifactTier; ++i)
1006 InitArtifactPowers(GetTemplate()->GetArtifactID(), i);
1007
1011
1012 if (ArtifactAppearanceEntry const* artifactAppearance = sArtifactAppearanceStore.LookupEntry(artifactAppearanceId))
1013 SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID);
1014
1015 uint8 totalPurchasedRanks = 0;
1016 for (ArtifactPowerData& power : powers)
1017 {
1018 power.CurrentRankWithBonus += power.PurchasedRank;
1019 totalPurchasedRanks += power.PurchasedRank;
1020
1021 ArtifactPowerEntry const* artifactPower = sArtifactPowerStore.AssertEntry(power.ArtifactPowerId);
1023 {
1025 {
1026 for (uint32 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
1027 {
1028 switch (enchant->Effect[i])
1029 {
1031 if (uint32(artifactPower->Label) == enchant->EffectArg[i])
1032 power.CurrentRankWithBonus += enchant->EffectPointsMin[i];
1033 break;
1035 if (artifactPower->ID == enchant->EffectArg[i])
1036 power.CurrentRankWithBonus += enchant->EffectPointsMin[i];
1037 break;
1040 {
1041 if (ArtifactPowerPickerEntry const* artifactPowerPicker = sArtifactPowerPickerStore.LookupEntry(enchant->EffectArg[i]))
1042 {
1043 PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(artifactPowerPicker->PlayerConditionID);
1044 if (!playerCondition || (owner && sConditionMgr->IsPlayerMeetingCondition(owner, playerCondition)))
1045 if (artifactPower->Label == _bonusData.GemRelicType[e - SOCK_ENCHANTMENT_SLOT])
1046 power.CurrentRankWithBonus += enchant->EffectPointsMin[i];
1047 }
1048 }
1049 break;
1050 default:
1051 break;
1052 }
1053 }
1054 }
1055 }
1056
1057 SetArtifactPower(power.ArtifactPowerId, power.PurchasedRank, power.CurrentRankWithBonus);
1058 }
1059
1060 for (ArtifactPowerData& power : powers)
1061 {
1062 ArtifactPowerEntry const* scaledArtifactPowerEntry = sArtifactPowerStore.AssertEntry(power.ArtifactPowerId);
1063 if (!(scaledArtifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS))
1064 continue;
1065
1066 SetArtifactPower(power.ArtifactPowerId, power.PurchasedRank, totalPurchasedRanks + 1);
1067 }
1068
1070}
1071
1073{
1074 if (!owner)
1075 return;
1076
1077 uint8 artifactId = GetTemplate()->GetArtifactID();
1078 if (!artifactId)
1079 return;
1080
1081 for (ArtifactUnlockEntry const* artifactUnlock : sArtifactUnlockStore)
1082 if (artifactUnlock->ArtifactID == artifactId)
1083 if (owner->MeetPlayerCondition(artifactUnlock->PlayerConditionID))
1084 AddBonuses(artifactUnlock->ItemBonusListID);
1085}
1086
1087/*static*/
1089{
1091 stmt->setUInt64(0, itemGuid);
1092 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1093
1094 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
1095 stmt->setUInt64(0, itemGuid);
1096 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1097
1098 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
1099 stmt->setUInt64(0, itemGuid);
1100 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1101
1102 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
1103 stmt->setUInt64(0, itemGuid);
1104 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1105
1106 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS);
1107 stmt->setUInt64(0, itemGuid);
1108 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1109
1110 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
1111 stmt->setUInt64(0, itemGuid);
1112 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1113
1114 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
1115 stmt->setUInt64(0, itemGuid);
1116 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1117}
1118
1120{
1121 DeleteFromDB(trans, GetGUID().GetCounter());
1122
1123 // Delete the items if this is a container
1124 if (m_loot && !m_loot->isLooted())
1125 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
1126}
1127
1128/*static*/
1130{
1132 stmt->setUInt64(0, itemGuid);
1133 trans->Append(stmt);
1134}
1135
1137{
1138 DeleteFromInventoryDB(trans, GetGUID().GetCounter());
1139}
1140
1142{
1143 return sObjectMgr->GetItemTemplate(GetEntry());
1144}
1145
1147{
1149}
1150
1151// Just a "legacy shortcut" for proto->GetSkill()
1153{
1154 ItemTemplate const* proto = GetTemplate();
1155 return proto->GetSkill();
1156}
1157
1159{
1160 if (!bonusListId)
1161 return;
1162
1163 AddBonuses(bonusListId);
1164}
1165
1167{
1168 if (uState == ITEM_NEW && state == ITEM_REMOVED)
1169 {
1170 // pretend the item never existed
1171 if (forplayer)
1172 {
1173 RemoveItemFromUpdateQueueOf(this, forplayer);
1174 forplayer->DeleteRefundReference(GetGUID());
1175 }
1176 delete this;
1177 return;
1178 }
1179 if (state != ITEM_UNCHANGED)
1180 {
1181 // new items must stay in new state until saved
1182 if (uState != ITEM_NEW)
1183 uState = state;
1184
1185 if (forplayer)
1186 AddItemToUpdateQueueOf(this, forplayer);
1187 }
1188 else
1189 {
1190 // unset in queue
1191 // the item must be removed from the queue manually
1192 uQueuePos = -1;
1194 }
1195}
1196
1198{
1199 if (item->IsInUpdateQueue())
1200 return;
1201
1202 ASSERT(player != nullptr);
1203
1204 if (player->GetGUID() != item->GetOwnerGUID())
1205 {
1206 TC_LOG_DEBUG("entities.player.items", "AddItemToUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
1207 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
1208 return;
1209 }
1210
1211 if (player->m_itemUpdateQueueBlocked)
1212 return;
1213
1214 player->m_itemUpdateQueue.push_back(item);
1215 item->uQueuePos = player->m_itemUpdateQueue.size() - 1;
1216}
1217
1219{
1220 if (!item->IsInUpdateQueue())
1221 return;
1222
1223 ASSERT(player != nullptr);
1224
1225 if (player->GetGUID() != item->GetOwnerGUID())
1226 {
1227 TC_LOG_DEBUG("entities.player.items", "RemoveItemFromUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
1228 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
1229 return;
1230 }
1231
1232 if (player->m_itemUpdateQueueBlocked)
1233 return;
1234
1235 player->m_itemUpdateQueue[item->uQueuePos] = nullptr;
1236 item->uQueuePos = -1;
1237}
1238
1240{
1242}
1243
1245{
1246 return !IsInBag() && (m_slot < EQUIPMENT_SLOT_END
1248}
1249
1250bool Item::CanBeTraded(bool mail, bool trade) const
1251{
1252 if (m_lootGenerated)
1253 return false;
1254
1255 if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!IsBOPTradeable() || !trade)))
1256 return false;
1257
1258 if (IsBag() && (Player::IsBagPos(GetPos()) || !ToBag()->IsEmpty()))
1259 return false;
1260
1261 if (Player* owner = GetOwner())
1262 {
1263 if (owner->CanUnequipItem(GetPos(), false) != EQUIP_ERR_OK)
1264 return false;
1265 if (owner->GetLootGUID() == GetGUID())
1266 return false;
1267 }
1268
1269 if (IsBoundByEnchant())
1270 return false;
1271
1272 return true;
1273}
1274
1276{
1278
1279 if (Player* player = GetOwner())
1280 {
1281 if (TradeData* tradeData = player->GetTradeData())
1282 {
1283 TradeSlots slot = tradeData->GetTradeSlotForItem(GetGUID());
1284
1285 if (slot != TRADE_SLOT_INVALID)
1286 tradeData->SetItem(slot, this, true);
1287 }
1288 }
1289}
1290
1292{
1293 uint32 maxDurability = m_itemData->MaxDurability;
1294 if (!maxDurability)
1295 return 0;
1296
1297 uint32 curDurability = m_itemData->Durability;
1298 ASSERT(maxDurability >= curDurability);
1299
1300 uint32 lostDurability = maxDurability - curDurability;
1301 if (!lostDurability)
1302 return 0;
1303
1304 ItemTemplate const* itemTemplate = GetTemplate();
1305
1306 DurabilityCostsEntry const* durabilityCost = sDurabilityCostsStore.LookupEntry(GetItemLevel(GetOwner()));
1307 if (!durabilityCost)
1308 return 0;
1309
1310 uint32 durabilityQualityEntryId = (GetQuality() + 1) * 2;
1311 DurabilityQualityEntry const* durabilityQualityEntry = sDurabilityQualityStore.LookupEntry(durabilityQualityEntryId);
1312 if (!durabilityQualityEntry)
1313 return 0;
1314
1315 uint32 dmultiplier = 0;
1316 if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
1317 dmultiplier = durabilityCost->WeaponSubClassCost[itemTemplate->GetSubClass()];
1318 else if (itemTemplate->GetClass() == ITEM_CLASS_ARMOR)
1319 dmultiplier = durabilityCost->ArmorSubClassCost[itemTemplate->GetSubClass()];
1320
1321 uint64 cost = std::round(lostDurability * dmultiplier * durabilityQualityEntry->Data * GetRepairCostMultiplier());
1322 cost = uint64(cost * discount * sWorld->getRate(RATE_REPAIRCOST));
1323
1324 if (cost == 0) // Fix for ITEM_QUALITY_ARTIFACT
1325 cost = 1;
1326
1327 return cost;
1328}
1329
1330bool Item::HasEnchantRequiredSkill(Player const* player) const
1331{
1332 // Check all enchants for required skill
1333 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
1334 {
1335 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
1336 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1337 if (enchantEntry->RequiredSkillID && player->GetSkillValue(enchantEntry->RequiredSkillID) < enchantEntry->RequiredSkillRank)
1338 return false;
1339 }
1340
1341 return true;
1342}
1343
1345{
1346 uint32 level = 0;
1347
1348 // Check all enchants for required level
1349 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
1350 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
1351 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1352 if (enchantEntry->MinLevel > level)
1353 level = enchantEntry->MinLevel;
1354
1355 return level;
1356}
1357
1359{
1360 // Check all enchants for soulbound
1361 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
1362 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
1363 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1364 if (enchantEntry->GetFlags().HasFlag(SpellItemEnchantmentFlags::Soulbound))
1365 return true;
1366
1367 return false;
1368}
1369
1371{
1372 // not allow merge looting currently items
1373 if (m_lootGenerated)
1374 return EQUIP_ERR_LOOT_GONE;
1375
1376 // check item type
1377 if (GetEntry() != proto->GetId())
1378 return EQUIP_ERR_CANT_STACK;
1379
1380 // check free space (full stacks can't be target of merge
1381 if (GetCount() >= proto->GetMaxStackSize())
1382 return EQUIP_ERR_CANT_STACK;
1383
1384 return EQUIP_ERR_OK;
1385}
1386
1387bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
1388{
1389 ItemTemplate const* proto = GetTemplate();
1390
1392 if (spellInfo->EquippedItemClass != -1) // -1 == any item class
1393 {
1394 if (isEnchantSpell && proto->HasFlag(ITEM_FLAG3_CAN_STORE_ENCHANTS))
1395 return true;
1396
1397 if (spellInfo->EquippedItemClass != int32(proto->GetClass()))
1398 return false; // wrong item class
1399
1400 if (spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass
1401 {
1402 if ((spellInfo->EquippedItemSubClassMask & (1 << proto->GetSubClass())) == 0)
1403 return false; // subclass not present in mask
1404 }
1405 }
1406
1407 if (isEnchantSpell && spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
1408 {
1409 // Special case - accept weapon type for main and offhand requirements
1410 if (proto->GetInventoryType() == INVTYPE_WEAPON &&
1413 return true;
1414 else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->GetInventoryType())) == 0)
1415 return false; // inventory type not present in mask
1416 }
1417
1418 return true;
1419}
1420
1421void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster /*= ObjectGuid::Empty*/)
1422{
1423 // Better lost small time at check in comparison lost time at item save to DB.
1424 if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
1425 return;
1426
1427 Player* owner = GetOwner();
1429 {
1430 if (SpellItemEnchantmentEntry const* oldEnchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(slot)))
1431 if (!oldEnchant->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotLog))
1432 owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), ObjectGuid::Empty, GetGUID(), GetEntry(), oldEnchant->ID, slot);
1433
1434 if (SpellItemEnchantmentEntry const* newEnchant = sSpellItemEnchantmentStore.LookupEntry(id))
1435 if (!newEnchant->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotLog))
1436 owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, slot);
1437 }
1438
1439 ApplyArtifactPowerEnchantmentBonuses(slot, GetEnchantmentId(slot), false, owner);
1440 ApplyArtifactPowerEnchantmentBonuses(slot, id, true, owner);
1441
1442 auto enchantmentField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Enchantment, slot);
1443 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::ID), id);
1444 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Duration), duration);
1445 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Charges), charges);
1446 SetState(ITEM_CHANGED, owner);
1447}
1448
1450{
1451 if (GetEnchantmentDuration(slot) == duration)
1452 return;
1453
1455 SetState(ITEM_CHANGED, owner);
1456 // Cannot use GetOwner() here, has to be passed as an argument to avoid freeze due to hashtable locking
1457}
1458
1460{
1461 if (GetEnchantmentCharges(slot) == charges)
1462 return;
1463
1466}
1467
1469{
1470 if (!GetEnchantmentId(slot))
1471 return;
1472
1473 auto enchantmentField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Enchantment, slot);
1474 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::ID), 0);
1475 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Duration), 0);
1476 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Charges), 0);
1477 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Inactive), 0);
1479}
1480
1482{
1483 ASSERT(slot < MAX_GEM_SOCKETS);
1484 return slot < m_itemData->Gems.size() ? &m_itemData->Gems[slot] : nullptr;
1485}
1486
1487void Item::SetGem(uint16 slot, ItemDynamicFieldGems const* gem, uint32 gemScalingLevel)
1488{
1489 ASSERT(slot < MAX_GEM_SOCKETS);
1490 m_gemScalingLevels[slot] = gemScalingLevel;
1491 _bonusData.GemItemLevelBonus[slot] = 0;
1492 if (ItemTemplate const* gemTemplate = sObjectMgr->GetItemTemplate(gem->ItemId))
1493 {
1494 if (GemPropertiesEntry const* gemProperties = sGemPropertiesStore.LookupEntry(gemTemplate->GetGemProperties()))
1495 {
1496 if (SpellItemEnchantmentEntry const* gemEnchant = sSpellItemEnchantmentStore.LookupEntry(gemProperties->EnchantId))
1497 {
1498 BonusData gemBonus;
1499 gemBonus.Initialize(gemTemplate);
1500 for (uint16 bonusListId : gem->BonusListIDs)
1501 gemBonus.AddBonusList(bonusListId);
1502
1503 uint32 gemBaseItemLevel = gemTemplate->GetBaseItemLevel();
1504 if (gemBonus.PlayerLevelToItemLevelCurveId)
1505 if (uint32 scaledIlvl = uint32(sDB2Manager.GetCurveValueAt(gemBonus.PlayerLevelToItemLevelCurveId, gemScalingLevel)))
1506 gemBaseItemLevel = scaledIlvl;
1507
1508 _bonusData.GemRelicType[slot] = gemBonus.RelicType;
1509
1510 for (uint32 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
1511 {
1512 switch (gemEnchant->Effect[i])
1513 {
1515 {
1516 for (ItemBonusEntry const* itemBonus : ItemBonusMgr::GetItemBonuses(gemEnchant->EffectArg[i]))
1517 if (itemBonus->Type == ITEM_BONUS_ITEM_LEVEL)
1518 _bonusData.GemItemLevelBonus[slot] += itemBonus->Value[0];
1519 break;
1520 }
1522 {
1524 for (ItemBonusEntry const* itemBonus : ItemBonusMgr::GetItemBonuses(bonusListId))
1525 if (itemBonus->Type == ITEM_BONUS_ITEM_LEVEL)
1526 _bonusData.GemItemLevelBonus[slot] += itemBonus->Value[0];
1527 break;
1528 }
1529 default:
1530 break;
1531 }
1532 }
1533 }
1534 }
1535 }
1536
1537 auto gemField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Gems, slot);
1538 SetUpdateFieldValue(gemField.ModifyValue(&UF::SocketedGem::ItemID), gem->ItemId);
1539 SetUpdateFieldValue(gemField.ModifyValue(&UF::SocketedGem::Context), gem->Context);
1540 for (uint32 i = 0; i < 16; ++i)
1541 SetUpdateFieldValue(gemField.ModifyValue(&UF::SocketedGem::BonusListIDs, i), gem->BonusListIDs[i]);
1542}
1543
1545{
1546 for (uint32 gemSlot = 0; gemSlot < MAX_ITEM_PROTO_SOCKETS; ++gemSlot)
1547 {
1549
1550 if (!SocketColor) // no socket slot
1551 continue;
1552
1553 if (gemSlot >= m_itemData->Gems.size()) // no gems on this socket
1554 return false;
1555
1556 uint8 GemColor = 0;
1557
1558 uint32 gemid = m_itemData->Gems[gemSlot].ItemID;
1559 if (gemid)
1560 {
1561 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemid);
1562 if (gemProto)
1563 {
1564 GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GetGemProperties());
1565 if (gemProperty)
1566 GemColor = gemProperty->Type;
1567 }
1568 }
1569
1570 if (!(GemColor & SocketColorToGemTypeMask[SocketColor])) // bad gem color on this socket
1571 return false;
1572 }
1573 return true;
1574}
1575
1577{
1578 return uint8(std::count_if(m_itemData->Gems.begin(), m_itemData->Gems.end(), [GemID](UF::SocketedGem const& gemData)
1579 {
1580 return gemData.ItemID == int32(GemID);
1581 }));
1582}
1583
1585{
1586 return uint8(std::count_if(m_itemData->Gems.begin(), m_itemData->Gems.end(), [limitCategory](UF::SocketedGem const& gemData)
1587 {
1588 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemData.ItemID);
1589 if (!gemProto)
1590 return false;
1591
1592 return gemProto->GetItemLimitCategory() == limitCategory;
1593 }));
1594}
1595
1596bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
1597{
1598 ItemTemplate const* proto = GetTemplate();
1599 return proto && ((proto->GetMap() && proto->GetMap() != cur_mapId) ||
1600 ((proto->GetArea(0) && proto->GetArea(0) != cur_zoneId) && (proto->GetArea(1) && proto->GetArea(1) != cur_zoneId)));
1601}
1602
1604{
1606 socketGems.Item = GetGUID();
1607 GetOwner()->GetSession()->SendPacket(socketGems.Write());
1608}
1609
1610// Though the client has the information in the item's data field,
1611// we have to send SMSG_ITEM_TIME_UPDATE to display the remaining
1612// time.
1614{
1615 uint32 duration = m_itemData->Expiration;
1616 if (!duration)
1617 return;
1618
1620 itemTimeUpdate.ItemGuid = GetGUID();
1621 itemTimeUpdate.DurationLeft = duration;
1622 owner->GetSession()->SendPacket(itemTimeUpdate.Write());
1623}
1624
1625Item* Item::CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const* player /*= nullptr*/, bool addDefaultBonuses /*= true*/)
1626{
1627 if (count < 1)
1628 return nullptr; //don't create item at zero count
1629
1630 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry);
1631 if (proto)
1632 {
1633 if (count > proto->GetMaxStackSize())
1634 count = proto->GetMaxStackSize();
1635
1636 ASSERT_NODEBUGINFO(count != 0, "proto->Stackable == 0 but checked at loading already");
1637
1638 Item* item = NewItemOrBag(proto);
1639 if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), itemEntry, context, player))
1640 {
1641 item->SetCount(count);
1642 if (addDefaultBonuses)
1643 item->SetBonuses(ItemBonusMgr::GetBonusListsForItem(itemEntry, context));
1644
1645 return item;
1646 }
1647 else
1648 delete item;
1649 }
1650 else
1651 ABORT();
1652 return nullptr;
1653}
1654
1655Item* Item::CloneItem(uint32 count, Player const* player /*= nullptr*/) const
1656{
1657 Item* newItem = CreateItem(GetEntry(), count, GetContext(), player, false);
1658 if (!newItem)
1659 return nullptr;
1660
1661 newItem->SetCreator(GetCreator());
1662 newItem->SetGiftCreator(GetGiftCreator());
1664 newItem->SetExpiration(m_itemData->Expiration);
1665 newItem->SetBonuses(m_itemData->ItemBonusKey->BonusListIDs);
1666 // player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
1667 if (player)
1669 return newItem;
1670}
1671
1672bool Item::IsBindedNotWith(Player const* player) const
1673{
1674 // not binded item
1675 if (!IsSoulBound())
1676 return false;
1677
1678 // own item
1679 if (GetOwnerGUID() == player->GetGUID())
1680 return false;
1681
1682 if (IsBOPTradeable())
1683 if (allowedGUIDs.find(player->GetGUID()) != allowedGUIDs.end())
1684 return false;
1685
1686 // BOA item case
1687 if (IsBoundAccountWide())
1688 return false;
1689
1690 return true;
1691}
1692
1694{
1695 if (Player* owner = GetOwner())
1696 BuildFieldsUpdate(owner, data_map);
1697 ClearUpdateMask(false);
1698}
1699
1701{
1702 if (target->GetGUID() == GetOwnerGUID())
1704
1706}
1707
1708void Item::BuildValuesCreate(ByteBuffer* data, Player const* target) const
1709{
1711 std::size_t sizePos = data->wpos();
1712 *data << uint32(0);
1713 *data << uint8(flags);
1714 m_objectData->WriteCreate(*data, flags, this, target);
1715 m_itemData->WriteCreate(*data, flags, this, target);
1716 data->put<uint32>(sizePos, data->wpos() - sizePos - 4);
1717}
1718
1719void Item::BuildValuesUpdate(ByteBuffer* data, Player const* target) const
1720{
1722 std::size_t sizePos = data->wpos();
1723 *data << uint32(0);
1725
1727 m_objectData->WriteUpdate(*data, flags, this, target);
1728
1730 m_itemData->WriteUpdate(*data, flags, this, target);
1731
1732 data->put<uint32>(sizePos, data->wpos() - sizePos - 4);
1733}
1734
1736{
1738 valuesMask.Set(TYPEID_ITEM);
1739
1740 std::size_t sizePos = data->wpos();
1741 *data << uint32(0);
1742 *data << uint32(valuesMask.GetBlock(0));
1743
1744 UF::ItemData::Mask mask;
1745 m_itemData->AppendAllowedFieldsMaskForFlag(mask, flags);
1746 m_itemData->WriteUpdate(*data, mask, true, this, target);
1747
1748 data->put<uint32>(sizePos, data->wpos() - sizePos - 4);
1749}
1750
1752 UF::ItemData::Mask const& requestedItemMask, Player const* target) const
1753{
1756 if (requestedObjectMask.IsAnySet())
1757 valuesMask.Set(TYPEID_OBJECT);
1758
1759 UF::ItemData::Mask itemMask = requestedItemMask;
1760 m_itemData->FilterDisallowedFieldsMaskForFlag(itemMask, flags);
1761 if (itemMask.IsAnySet())
1762 valuesMask.Set(TYPEID_ITEM);
1763
1764 ByteBuffer& buffer = PrepareValuesUpdateBuffer(data);
1765 std::size_t sizePos = buffer.wpos();
1766 buffer << uint32(0);
1767 buffer << uint32(valuesMask.GetBlock(0));
1768
1769 if (valuesMask[TYPEID_OBJECT])
1770 m_objectData->WriteUpdate(buffer, requestedObjectMask, true, this, target);
1771
1772 if (valuesMask[TYPEID_ITEM])
1773 m_itemData->WriteUpdate(buffer, itemMask, true, this, target);
1774
1775 buffer.put<uint32>(sizePos, buffer.wpos() - sizePos - 4);
1776
1777 data->AddUpdateBlock();
1778}
1779
1781{
1782 UpdateData udata(player->GetMapId());
1783 WorldPacket packet;
1784
1786
1787 udata.BuildPacket(&packet);
1788 player->SendDirectMessage(&packet);
1789}
1790
1791void Item::ClearUpdateMask(bool remove)
1792{
1795}
1796
1798{
1799 if (Player* owner = GetOwner())
1800 {
1801 owner->GetMap()->AddUpdateObject(this);
1802 return true;
1803 }
1804
1805 return false;
1806}
1807
1809{
1810 if (Player* owner = GetOwner())
1811 owner->GetMap()->RemoveUpdateObject(this);
1812}
1813
1815{
1816 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1817
1819 stmt->setUInt64(0, GetGUID().GetCounter());
1820 trans->Append(stmt);
1821
1822 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_REFUND_INSTANCE);
1823 stmt->setUInt64(0, GetGUID().GetCounter());
1824 stmt->setUInt64(1, GetRefundRecipient().GetCounter());
1825 stmt->setUInt64(2, GetPaidMoney());
1827 trans->Append(stmt);
1828
1829 CharacterDatabase.CommitTransaction(trans);
1830}
1831
1833{
1834 if (trans)
1835 {
1837 stmt->setUInt64(0, GetGUID().GetCounter());
1838 (*trans)->Append(stmt);
1839
1840 }
1841}
1842
1843void Item::SetNotRefundable(Player* owner, bool changestate /*= true*/, CharacterDatabaseTransaction* trans /*= nullptr*/, bool addToCollection /*= true*/)
1844{
1845 if (!IsRefundable())
1846 return;
1847
1848 WorldPackets::Item::ItemExpirePurchaseRefund itemExpirePurchaseRefund;
1849 itemExpirePurchaseRefund.ItemGUID = GetGUID();
1850 owner->SendDirectMessage(itemExpirePurchaseRefund.Write());
1851
1853 // Following is not applicable in the trading procedure
1854 if (changestate)
1855 SetState(ITEM_CHANGED, owner);
1856
1858 SetPaidMoney(0);
1861
1863 if (addToCollection)
1865}
1866
1868{
1869 /* Here we update our played time
1870 We simply add a number to the current played time,
1871 based on the time elapsed since the last update hereof.
1872 */
1873 // Get current played time
1874 uint32 current_playtime = m_itemData->CreatePlayedTime;
1875 // Calculate time elapsed since last played time update
1876 time_t curtime = GameTime::GetGameTime();
1877 uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
1878 uint32 new_playtime = current_playtime + elapsed;
1879 // Check if the refund timer has expired yet
1880 if (new_playtime <= 2*HOUR)
1881 {
1882 // No? Proceed.
1883 // Update the data field
1884 SetCreatePlayedTime(new_playtime);
1885 // Flag as changed to get saved to DB
1886 SetState(ITEM_CHANGED, owner);
1887 // Speaks for itself
1888 m_lastPlayedTimeUpdate = curtime;
1889 return;
1890 }
1891 // Yes
1892 SetNotRefundable(owner);
1893}
1894
1896{
1897 time_t curtime = GameTime::GetGameTime();
1898 uint32 elapsed = uint32(curtime - m_lastPlayedTimeUpdate);
1899 return *m_itemData->CreatePlayedTime + elapsed;
1900}
1901
1903{
1904 return (GetPlayedTime() > 2*HOUR);
1905}
1906
1907void Item::SetSoulboundTradeable(GuidSet const& allowedLooters)
1908{
1910 allowedGUIDs = allowedLooters;
1911}
1912
1914{
1916 if (allowedGUIDs.empty())
1917 return;
1918
1919 currentOwner->GetSession()->GetCollectionMgr()->AddItemAppearance(this);
1920 allowedGUIDs.clear();
1921 SetState(ITEM_CHANGED, currentOwner);
1923 stmt->setUInt64(0, GetGUID().GetCounter());
1924 CharacterDatabase.Execute(stmt);
1925}
1926
1928{
1929 // called from owner's update - GetOwner() MUST be valid
1930 if (m_itemData->CreatePlayedTime + 2*HOUR < GetOwner()->GetTotalPlayedTime())
1931 {
1933 return true; // remove from tradeable list
1934 }
1935
1936 return false;
1937}
1938
1940{
1941 ItemTemplate const* proto = GetTemplate();
1942 if (!proto)
1943 return false;
1944
1945 if (proto->GetClass() != ITEM_CLASS_ARMOR &&
1946 proto->GetClass() != ITEM_CLASS_WEAPON)
1947 return false;
1948
1950 return false;
1951
1953 return false;
1954
1955 if (!HasStats())
1956 return false;
1957
1958 return true;
1959}
1960
1961bool Item::HasStats() const
1962{
1963 ItemTemplate const* proto = GetTemplate();
1964 Player const* owner = GetOwner();
1965 for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
1966 if ((owner ? GetItemStatValue(i, owner) : proto->GetStatPercentEditor(i)) != 0)
1967 return true;
1968
1969 return false;
1970}
1971
1972bool Item::HasStats(WorldPackets::Item::ItemInstance const& /*itemInstance*/, BonusData const* bonus)
1973{
1974 for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
1975 if (bonus->StatPercentEditor[i] != 0)
1976 return true;
1977
1978 return false;
1979}
1980
1982{
1983 // Two-handed
1984 MELEE_2H,
1985 RANGED,
1986
1987 // One-handed
1989 DAGGER,
1990 FIST,
1991
1992 INVALID
1993};
1994
1996{
1997 if (proto->GetClass() == ITEM_CLASS_WEAPON)
1998 {
1999 switch (proto->GetSubClass())
2000 {
2020 default:
2021 break;
2022 }
2023 }
2024
2026}
2027
2029{
2030 -1, // INVTYPE_NON_EQUIP
2031 EQUIPMENT_SLOT_HEAD, // INVTYPE_HEAD
2032 -1, // INVTYPE_NECK
2033 EQUIPMENT_SLOT_SHOULDERS, // INVTYPE_SHOULDERS
2034 EQUIPMENT_SLOT_BODY, // INVTYPE_BODY
2035 EQUIPMENT_SLOT_CHEST, // INVTYPE_CHEST
2036 EQUIPMENT_SLOT_WAIST, // INVTYPE_WAIST
2037 EQUIPMENT_SLOT_LEGS, // INVTYPE_LEGS
2038 EQUIPMENT_SLOT_FEET, // INVTYPE_FEET
2039 EQUIPMENT_SLOT_WRISTS, // INVTYPE_WRISTS
2040 EQUIPMENT_SLOT_HANDS, // INVTYPE_HANDS
2041 -1, // INVTYPE_FINGER
2042 -1, // INVTYPE_TRINKET
2043 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_WEAPON
2044 EQUIPMENT_SLOT_OFFHAND, // INVTYPE_SHIELD
2045 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_RANGED
2046 EQUIPMENT_SLOT_BACK, // INVTYPE_CLOAK
2047 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_2HWEAPON
2048 -1, // INVTYPE_BAG
2049 EQUIPMENT_SLOT_TABARD, // INVTYPE_TABARD
2050 EQUIPMENT_SLOT_CHEST, // INVTYPE_ROBE
2051 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_WEAPONMAINHAND
2052 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_WEAPONOFFHAND
2053 EQUIPMENT_SLOT_OFFHAND, // INVTYPE_HOLDABLE
2054 -1, // INVTYPE_AMMO
2055 -1, // INVTYPE_THROWN
2056 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_RANGEDRIGHT
2057 -1, // INVTYPE_QUIVER
2058 -1 // INVTYPE_RELIC
2059 -1, // INVTYPE_PROFESSION_TOOL
2060 -1, // INVTYPE_PROFESSION_GEAR
2061 -1, // INVTYPE_EQUIPABLE_SPELL_OFFENSIVE
2062 -1, // INVTYPE_EQUIPABLE_SPELL_UTILITY
2063 -1, // INVTYPE_EQUIPABLE_SPELL_DEFENSIVE
2064 -1 // INVTYPE_EQUIPABLE_SPELL_MOBILITY
2065};
2066
2067bool Item::CanTransmogrifyItemWithItem(Item const* item, ItemModifiedAppearanceEntry const* itemModifiedAppearance)
2068{
2069 ItemTemplate const* source = sObjectMgr->GetItemTemplate(itemModifiedAppearance->ItemID); // source
2070 ItemTemplate const* target = item->GetTemplate(); // dest
2071
2072 if (!source || !target)
2073 return false;
2074
2075 if (itemModifiedAppearance == item->GetItemModifiedAppearance())
2076 return false;
2077
2079 return false;
2080
2081 if (source->GetClass() != target->GetClass())
2082 return false;
2083
2084 if (source->GetInventoryType() == INVTYPE_BAG ||
2085 source->GetInventoryType() == INVTYPE_RELIC ||
2086 source->GetInventoryType() == INVTYPE_FINGER ||
2087 source->GetInventoryType() == INVTYPE_TRINKET ||
2088 source->GetInventoryType() == INVTYPE_AMMO ||
2089 source->GetInventoryType() == INVTYPE_QUIVER)
2090 return false;
2091
2092 if (source->GetSubClass() != target->GetSubClass())
2093 {
2094 switch (source->GetClass())
2095 {
2096 case ITEM_CLASS_WEAPON:
2098 return false;
2099 break;
2100 case ITEM_CLASS_ARMOR:
2102 return false;
2103 if (source->GetInventoryType() != target->GetInventoryType())
2105 return false;
2106 break;
2107 default:
2108 return false;
2109 }
2110 }
2111
2112 return true;
2113}
2114
2115uint32 Item::GetBuyPrice(Player const* owner, bool& standardPrice) const
2116{
2117 return Item::GetBuyPrice(GetTemplate(), GetQuality(), GetItemLevel(owner), standardPrice);
2118}
2119
2120uint32 Item::GetBuyPrice(ItemTemplate const* proto, uint32 quality, uint32 itemLevel, bool& standardPrice)
2121{
2122 standardPrice = false;
2123
2125 return proto->GetBuyPrice();
2126
2127 ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(quality + 1);
2128 if (!qualityPrice)
2129 return 0;
2130
2131 ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(itemLevel);
2132 if (!basePrice)
2133 return 0;
2134
2135 float qualityFactor = qualityPrice->Data;
2136 float baseFactor = 0.0f;
2137
2138 uint32 inventoryType = proto->GetInventoryType();
2139
2140 if (inventoryType == INVTYPE_WEAPON ||
2141 inventoryType == INVTYPE_2HWEAPON ||
2142 inventoryType == INVTYPE_WEAPONMAINHAND ||
2143 inventoryType == INVTYPE_WEAPONOFFHAND ||
2144 inventoryType == INVTYPE_RANGED ||
2145 inventoryType == INVTYPE_THROWN ||
2146 inventoryType == INVTYPE_RANGEDRIGHT)
2147 baseFactor = basePrice->Weapon;
2148 else
2149 baseFactor = basePrice->Armor;
2150
2151 if (inventoryType == INVTYPE_ROBE)
2152 inventoryType = INVTYPE_CHEST;
2153
2155 {
2156 inventoryType = INVTYPE_WEAPON;
2157 baseFactor = basePrice->Weapon / 3.0f;
2158 }
2159
2160 float typeFactor = 0.0f;
2161 int8 weapType = -1;
2162
2163 switch (inventoryType)
2164 {
2165 case INVTYPE_HEAD:
2166 case INVTYPE_NECK:
2167 case INVTYPE_SHOULDERS:
2168 case INVTYPE_CHEST:
2169 case INVTYPE_WAIST:
2170 case INVTYPE_LEGS:
2171 case INVTYPE_FEET:
2172 case INVTYPE_WRISTS:
2173 case INVTYPE_HANDS:
2174 case INVTYPE_FINGER:
2175 case INVTYPE_TRINKET:
2176 case INVTYPE_CLOAK:
2177 case INVTYPE_HOLDABLE:
2178 {
2179 ImportPriceArmorEntry const* armorPrice = sImportPriceArmorStore.LookupEntry(inventoryType);
2180 if (!armorPrice)
2181 return 0;
2182
2183 switch (proto->GetSubClass())
2184 {
2187 typeFactor = armorPrice->ClothModifier;
2188 break;
2190 typeFactor = armorPrice->LeatherModifier;
2191 break;
2193 typeFactor = armorPrice->ChainModifier;
2194 break;
2196 typeFactor = armorPrice->PlateModifier;
2197 break;
2198 default:
2199 typeFactor = 1.0f;
2200 break;
2201 }
2202
2203 break;
2204 }
2205 case INVTYPE_SHIELD:
2206 {
2207 ImportPriceShieldEntry const* shieldPrice = sImportPriceShieldStore.LookupEntry(2);
2208 if (!shieldPrice)
2209 return 0;
2210
2211 typeFactor = shieldPrice->Data;
2212 break;
2213 }
2215 weapType = 0;
2216 break;
2218 weapType = 1;
2219 break;
2220 case INVTYPE_WEAPON:
2221 weapType = 2;
2222 break;
2223 case INVTYPE_2HWEAPON:
2224 weapType = 3;
2225 break;
2226 case INVTYPE_RANGED:
2228 case INVTYPE_RELIC:
2229 weapType = 4;
2230 break;
2231 default:
2232 return proto->GetBuyPrice();
2233 }
2234
2235 if (weapType != -1)
2236 {
2237 ImportPriceWeaponEntry const* weaponPrice = sImportPriceWeaponStore.LookupEntry(weapType + 1);
2238 if (!weaponPrice)
2239 return 0;
2240
2241 typeFactor = weaponPrice->Data;
2242 }
2243
2244 standardPrice = false;
2245 return uint32(proto->GetPriceVariance() * typeFactor * baseFactor * qualityFactor * proto->GetPriceRandomValue());
2246}
2247
2249{
2251}
2252
2253uint32 Item::GetSellPrice(ItemTemplate const* proto, uint32 quality, uint32 itemLevel)
2254{
2256 return proto->GetSellPrice();
2257 else
2258 {
2259 bool standardPrice;
2260 uint32 cost = Item::GetBuyPrice(proto, quality, itemLevel, standardPrice);
2261
2262 if (standardPrice)
2263 {
2264 if (ItemClassEntry const* classEntry = sDB2Manager.GetItemClassByOldEnum(proto->GetClass()))
2265 {
2266 uint32 buyCount = std::max(proto->GetBuyCount(), 1u);
2267 return cost * classEntry->PriceModifier / buyCount;
2268 }
2269
2270 return 0;
2271 }
2272 else
2273 return proto->GetSellPrice();
2274 }
2275
2276 return 0;
2277}
2278
2280{
2281 ItemTemplate const* itemTemplate = GetTemplate();
2282 uint32 minItemLevel = owner->m_unitData->MinItemLevel;
2283 uint32 minItemLevelCutoff = owner->m_unitData->MinItemLevelCutoff;
2284 uint32 maxItemLevel = itemTemplate->HasFlag(ITEM_FLAG3_IGNORE_ITEM_LEVEL_CAP_IN_PVP) ? 0 : owner->m_unitData->MaxItemLevel;
2285 bool pvpBonus = owner->IsUsingPvpItemLevels();
2286 uint32 azeriteLevel = 0;
2287 if (AzeriteItem const* azeriteItem = ToAzeriteItem())
2288 azeriteLevel = azeriteItem->GetEffectiveLevel();
2290 minItemLevel, minItemLevelCutoff, maxItemLevel, pvpBonus, azeriteLevel);
2291}
2292
2293uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bonusData, uint32 level, uint32 fixedLevel,
2294 uint32 minItemLevel, uint32 minItemLevelCutoff, uint32 maxItemLevel, bool pvpBonus, uint32 azeriteLevel)
2295{
2296 if (!itemTemplate)
2297 return MIN_ITEM_LEVEL;
2298
2299 uint32 itemLevel = itemTemplate->GetBaseItemLevel();
2300 if (AzeriteLevelInfoEntry const* azeriteLevelInfo = sAzeriteLevelInfoStore.LookupEntry(azeriteLevel))
2301 itemLevel = azeriteLevelInfo->ItemLevel;
2302
2303 if (bonusData.PlayerLevelToItemLevelCurveId)
2304 {
2305 if (fixedLevel)
2306 level = fixedLevel;
2307 else if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(bonusData.ContentTuningId, 0, true))
2308 level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel);
2309
2310 itemLevel = uint32(sDB2Manager.GetCurveValueAt(bonusData.PlayerLevelToItemLevelCurveId, level));
2311 }
2312
2313 itemLevel += bonusData.ItemLevelBonus;
2314
2315 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
2316 itemLevel += bonusData.GemItemLevelBonus[i];
2317
2318 uint32 itemLevelBeforeUpgrades = itemLevel;
2319
2320 if (pvpBonus)
2321 itemLevel += sDB2Manager.GetPvpItemLevelBonus(itemTemplate->GetId());
2322
2323 if (itemTemplate->GetInventoryType() != INVTYPE_NON_EQUIP)
2324 {
2325 if (minItemLevel && (!minItemLevelCutoff || itemLevelBeforeUpgrades >= minItemLevelCutoff) && itemLevel < minItemLevel)
2326 itemLevel = minItemLevel;
2327
2328 if (maxItemLevel && itemLevel > maxItemLevel)
2329 itemLevel = maxItemLevel;
2330 }
2331
2332 return std::min(std::max(itemLevel, uint32(MIN_ITEM_LEVEL)), uint32(MAX_ITEM_LEVEL));
2333}
2334
2335float Item::GetItemStatValue(uint32 index, Player const* owner) const
2336{
2338 switch (GetItemStatType(index))
2339 {
2342 return _bonusData.StatPercentEditor[index];
2343 default:
2344 break;
2345 }
2346
2347 uint32 itemLevel = GetItemLevel(owner);
2348 if (float randomPropPoints = GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate()->GetInventoryType(), GetTemplate()->GetSubClass()))
2349 {
2350 float statValue = float(_bonusData.StatPercentEditor[index] * randomPropPoints) * 0.0001f;
2351 if (GtItemSocketCostPerLevelEntry const* gtCost = sItemSocketCostPerLevelGameTable.GetRow(itemLevel))
2352 statValue -= float(int32(_bonusData.ItemStatSocketCostMultiplier[index] * gtCost->SocketCost));
2353
2354 return statValue;
2355 }
2356
2357 return 0.0f;
2358}
2359
2361{
2363 return nullptr;
2364
2366}
2367
2368ItemDisenchantLootEntry const* Item::GetDisenchantLoot(ItemTemplate const* itemTemplate, uint32 quality, uint32 itemLevel)
2369{
2370 if (itemTemplate->HasFlag(ITEM_FLAG_CONJURED) || itemTemplate->HasFlag(ITEM_FLAG_NO_DISENCHANT) || itemTemplate->GetBonding() == BIND_QUEST)
2371 return nullptr;
2372
2373 if (itemTemplate->GetArea(0) || itemTemplate->GetArea(1) || itemTemplate->GetMap() || itemTemplate->GetMaxStackSize() > 1)
2374 return nullptr;
2375
2376 if (!Item::GetSellPrice(itemTemplate, quality, itemLevel) && !sDB2Manager.HasItemCurrencyCost(itemTemplate->GetId()))
2377 return nullptr;
2378
2379 uint32 itemClass = itemTemplate->GetClass();
2380 int8 itemSubClass = itemTemplate->GetSubClass();
2381 uint8 expansion = itemTemplate->GetRequiredExpansion();
2382 for (ItemDisenchantLootEntry const* disenchant : sItemDisenchantLootStore)
2383 {
2384 if (disenchant->Class != itemClass)
2385 continue;
2386
2387 if (disenchant->Subclass >= 0 && itemSubClass)
2388 continue;
2389
2390 if (disenchant->Quality != quality)
2391 continue;
2392
2393 if (disenchant->MinLevel > itemLevel || disenchant->MaxLevel < itemLevel)
2394 continue;
2395
2396 if (disenchant->ExpansionID != -2 && disenchant->ExpansionID != expansion)
2397 continue;
2398
2399 return disenchant;
2400 }
2401
2402 return nullptr;
2403}
2404
2406{
2407 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2408 if (!itemModifiedAppearanceId)
2409 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2410
2411 if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
2412 if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(transmog->ItemAppearanceID))
2413 return itemAppearance->ItemDisplayInfoID;
2414
2415 return sDB2Manager.GetItemDisplayId(GetEntry(), GetAppearanceModId());
2416}
2417
2419{
2420 return sDB2Manager.GetItemModifiedAppearance(GetEntry(), _bonusData.AppearanceModID);
2421}
2422
2424{
2425 int32 modifierIndex = m_itemData->Modifiers->Values.FindIndexIf([modifier](UF::ItemMod mod)
2426 {
2427 return mod.Type == modifier;
2428 });
2429
2430 if (modifierIndex != -1)
2431 return m_itemData->Modifiers->Values[modifierIndex].Value;
2432
2433 return 0;
2434}
2435
2437{
2438 int32 modifierIndex = m_itemData->Modifiers->Values.FindIndexIf([modifier](UF::ItemMod mod)
2439 {
2440 return mod.Type == modifier;
2441 });
2442
2443 if (value)
2444 {
2445 if (modifierIndex == -1)
2446 {
2448 .ModifyValue(&UF::ItemData::Modifiers).ModifyValue(&UF::ItemModList::Values));
2449
2450 mod.Value = value;
2451 mod.Type = modifier;
2452 }
2453 else
2455 .ModifyValue(&UF::ItemData::Modifiers)
2456 .ModifyValue(&UF::ItemModList::Values, modifierIndex)
2457 .ModifyValue(&UF::ItemMod::Value), value);
2458 }
2459 else
2460 {
2461 if (modifierIndex == -1)
2462 return;
2463
2465 }
2466}
2467
2469{
2470 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2471 if (!itemModifiedAppearanceId)
2472 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2473
2474 if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
2475 return transmog->ItemID;
2476
2477 return GetEntry();
2478}
2479
2481{
2482 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2483 if (!itemModifiedAppearanceId)
2484 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2485
2486 if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
2487 return transmog->ItemAppearanceModifierID;
2488
2489 return uint16(GetAppearanceModId());
2490}
2491
2493{
2494 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2495 if (!itemModifiedAppearanceId)
2496 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2497
2498 if (!itemModifiedAppearanceId)
2499 if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = GetItemModifiedAppearance())
2500 itemModifiedAppearanceId = itemModifiedAppearance->ID;
2501
2502 return itemModifiedAppearanceId;
2503}
2504
2506{
2508 if (!itemModifiedAppearanceId)
2510
2511 return itemModifiedAppearanceId;
2512}
2513
2515{
2517 if (!enchantmentId)
2519
2520 if (!enchantmentId)
2521 enchantmentId = GetEnchantmentId(PERM_ENCHANTMENT_SLOT);
2522
2523 return enchantmentId;
2524}
2525
2527{
2528 if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetVisibleEnchantmentId(owner)))
2529 return enchant->ItemVisual;
2530
2531 return 0;
2532}
2533
2534void Item::AddBonuses(uint32 bonusListID)
2535{
2536 if (std::find(GetBonusListIDs().begin(), GetBonusListIDs().end(), int32(bonusListID)) != GetBonusListIDs().end())
2537 return;
2538
2540 itemBonusKey.ItemID = GetEntry();
2541 itemBonusKey.BonusListIDs = GetBonusListIDs();
2542 itemBonusKey.BonusListIDs.push_back(bonusListID);
2544 for (ItemBonusEntry const* bonus : ItemBonusMgr::GetItemBonuses(bonusListID))
2545 _bonusData.AddBonus(bonus->Type, bonus->Value);
2547}
2548
2549void Item::SetBonuses(std::vector<int32> bonusListIDs)
2550{
2552 itemBonusKey.ItemID = GetEntry();
2553 itemBonusKey.BonusListIDs = std::move(bonusListIDs);
2555
2556 for (int32 bonusListID : GetBonusListIDs())
2557 _bonusData.AddBonusList(bonusListID);
2558
2560}
2561
2563{
2565 itemBonusKey.ItemID = GetEntry();
2569}
2570
2572{
2573 if (ArtifactEntry const* artifact = sArtifactStore.LookupEntry(GetTemplate()->GetArtifactID()))
2574 return artifact->ArtifactCategoryID != 2; // fishing artifact
2575
2576 return true;
2577}
2578
2580{
2581 auto indexItr = m_artifactPowerIdToIndex.find(artifactPowerId);
2582 if (indexItr != m_artifactPowerIdToIndex.end())
2583 return &m_itemData->ArtifactPowers[indexItr->second];
2584
2585 return nullptr;
2586}
2587
2589{
2590 uint16 index = uint16(m_artifactPowerIdToIndex.size());
2591 m_artifactPowerIdToIndex[artifactPower->ArtifactPowerId] = index;
2592
2594 powerField.ArtifactPowerID = artifactPower->ArtifactPowerId;
2595 powerField.PurchasedRank = artifactPower->PurchasedRank;
2596 powerField.CurrentRankWithBonus = artifactPower->CurrentRankWithBonus;
2597}
2598
2599void Item::SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus)
2600{
2601 auto indexItr = m_artifactPowerIdToIndex.find(artifactPowerId);
2602 if (indexItr != m_artifactPowerIdToIndex.end())
2603 {
2605 .ModifyValue(&UF::ItemData::ArtifactPowers, indexItr->second)
2606 .ModifyValue(&UF::ArtifactPower::PurchasedRank), purchasedRank);
2607
2609 .ModifyValue(&UF::ItemData::ArtifactPowers, indexItr->second)
2610 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), currentRankWithBonus);
2611 }
2612}
2613
2614void Item::InitArtifactPowers(uint8 artifactId, uint8 artifactTier)
2615{
2616 for (ArtifactPowerEntry const* artifactPower : sDB2Manager.GetArtifactPowers(artifactId))
2617 {
2618 if (artifactPower->Tier != artifactTier)
2619 continue;
2620
2621 if (m_artifactPowerIdToIndex.find(artifactPower->ID) != m_artifactPowerIdToIndex.end())
2622 continue;
2623
2624 ArtifactPowerData powerData;
2625 powerData.ArtifactPowerId = artifactPower->ID;
2626 powerData.PurchasedRank = 0;
2627 powerData.CurrentRankWithBonus = (artifactPower->Flags & ARTIFACT_POWER_FLAG_FIRST) == ARTIFACT_POWER_FLAG_FIRST ? 1 : 0;
2628 AddArtifactPower(&powerData);
2629 }
2630}
2631
2633{
2635 uint64 artifactXp = m_itemData->ArtifactXP;
2636 uint32 currentArtifactTier = GetModifier(ITEM_MODIFIER_ARTIFACT_TIER);
2637 uint32 extraUnlocked = 0;
2638 do
2639 {
2640 uint64 xpCost = 0;
2641 if (GtArtifactLevelXPEntry const* cost = sArtifactLevelXPGameTable.GetRow(purchased + extraUnlocked + 1))
2642 xpCost = uint64(currentArtifactTier == MAX_ARTIFACT_TIER ? cost->XP2 : cost->XP);
2643
2644 if (artifactXp < xpCost)
2645 break;
2646
2647 artifactXp -= xpCost;
2648 ++extraUnlocked;
2649
2650 } while (true);
2651
2652 return purchased + extraUnlocked;
2653}
2654
2656{
2657 uint32 purchasedRanks = 0;
2658 for (UF::ArtifactPower const& power : m_itemData->ArtifactPowers)
2659 purchasedRanks += power.PurchasedRank;
2660
2661 return purchasedRanks;
2662}
2663
2665{
2666 if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId))
2667 {
2668 for (uint32 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
2669 {
2670 switch (enchant->Effect[i])
2671 {
2673 for (uint32 artifactPowerIndex = 0; artifactPowerIndex < m_itemData->ArtifactPowers.size(); ++artifactPowerIndex)
2674 {
2675 UF::ArtifactPower const& artifactPower = m_itemData->ArtifactPowers[artifactPowerIndex];
2676 if (uint32(sArtifactPowerStore.AssertEntry(artifactPower.ArtifactPowerID)->Label) == enchant->EffectArg[i])
2677 {
2678 uint8 newRank = artifactPower.CurrentRankWithBonus;
2679 if (apply)
2680 newRank += enchant->EffectPointsMin[i];
2681 else
2682 newRank -= enchant->EffectPointsMin[i];
2683
2685 .ModifyValue(&UF::ItemData::ArtifactPowers, artifactPowerIndex)
2686 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), newRank);
2687
2688 if (IsEquipped())
2689 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(artifactPower.ArtifactPowerID, newRank ? newRank - 1 : 0))
2690 owner->ApplyArtifactPowerRank(this, artifactPowerRank, newRank != 0);
2691 }
2692 }
2693 break;
2695 {
2696 if (uint16 const* artifactPowerIndex = Trinity::Containers::MapGetValuePtr(m_artifactPowerIdToIndex, enchant->EffectArg[i]))
2697 {
2698 uint8 newRank = m_itemData->ArtifactPowers[*artifactPowerIndex].CurrentRankWithBonus;
2699 if (apply)
2700 newRank += enchant->EffectPointsMin[i];
2701 else
2702 newRank -= enchant->EffectPointsMin[i];
2703
2705 .ModifyValue(&UF::ItemData::ArtifactPowers, *artifactPowerIndex)
2706 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), newRank);
2707
2708 if (IsEquipped())
2709 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(m_itemData->ArtifactPowers[*artifactPowerIndex].ArtifactPowerID, newRank ? newRank - 1 : 0))
2710 owner->ApplyArtifactPowerRank(this, artifactPowerRank, newRank != 0);
2711 }
2712 break;
2713 }
2716 {
2717 if (ArtifactPowerPickerEntry const* artifactPowerPicker = sArtifactPowerPickerStore.LookupEntry(enchant->EffectArg[i]))
2718 {
2719 PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(artifactPowerPicker->PlayerConditionID);
2720 if (!playerCondition || sConditionMgr->IsPlayerMeetingCondition(owner, playerCondition))
2721 {
2722 for (uint32 artifactPowerIndex = 0; artifactPowerIndex < m_itemData->ArtifactPowers.size(); ++artifactPowerIndex)
2723 {
2724 UF::ArtifactPower const& artifactPower = m_itemData->ArtifactPowers[artifactPowerIndex];
2725 if (sArtifactPowerStore.AssertEntry(artifactPower.ArtifactPowerID)->Label == _bonusData.GemRelicType[slot - SOCK_ENCHANTMENT_SLOT])
2726 {
2727 uint8 newRank = artifactPower.CurrentRankWithBonus;
2728 if (apply)
2729 newRank += enchant->EffectPointsMin[i];
2730 else
2731 newRank -= enchant->EffectPointsMin[i];
2732
2734 .ModifyValue(&UF::ItemData::ArtifactPowers, artifactPowerIndex)
2735 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), newRank);
2736
2737 if (IsEquipped())
2738 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(artifactPower.ArtifactPowerID, newRank ? newRank - 1 : 0))
2739 owner->ApplyArtifactPowerRank(this, artifactPowerRank, newRank != 0);
2740 }
2741 }
2742 }
2743 }
2744 }
2745 break;
2746 default:
2747 break;
2748 }
2749 }
2750 }
2751}
2752
2754{
2758}
2759
2760void Item::GiveArtifactXp(uint64 amount, Item* sourceItem, uint32 artifactCategoryId)
2761{
2762 Player* owner = GetOwner();
2763 if (!owner)
2764 return;
2765
2766 if (artifactCategoryId)
2767 {
2768 uint32 artifactKnowledgeLevel = 1;
2769 if (sourceItem && sourceItem->GetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL))
2770 artifactKnowledgeLevel = sourceItem->GetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL);
2771
2772 if (GtArtifactKnowledgeMultiplierEntry const* artifactKnowledge = sArtifactKnowledgeMultiplierGameTable.GetRow(artifactKnowledgeLevel))
2773 amount = uint64(amount * artifactKnowledge->Multiplier);
2774
2775 if (amount >= 5000)
2776 amount = 50 * (amount / 50);
2777 else if (amount >= 1000)
2778 amount = 25 * (amount / 25);
2779 else if (amount >= 50)
2780 amount = 5 * (amount / 5);
2781 }
2782
2783 SetArtifactXP(m_itemData->ArtifactXP + amount);
2784
2786 artifactXpGain.ArtifactGUID = GetGUID();
2787 artifactXpGain.Amount = amount;
2788 owner->SendDirectMessage(artifactXpGain.Write());
2789
2790 SetState(ITEM_CHANGED, owner);
2791}
2792
2794{
2796 return;
2797
2799 {
2800 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(_bonusData.ContentTuningId, 0, true))
2801 level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel);
2802
2804 }
2805}
2806
2808{
2811 return sDB2Manager.GetCurveValueAt(_bonusData.RequiredLevelCurve, fixedLevel);
2815 return fixedLevel;
2817}
2818
2819std::string Item::GetDebugInfo() const
2820{
2821 std::stringstream sstr;
2822 sstr << Object::GetDebugInfo() << "\n"
2823 << std::boolalpha
2824 << "Owner: " << GetOwnerGUID().ToString() << " Count: " << GetCount()
2825 << " BagSlot: " << std::to_string(GetBagSlot()) << " Slot: " << std::to_string(GetSlot()) << " Equipped: " << IsEquipped();
2826 return sstr.str();
2827}
2828
2830{
2831 Quality = proto->GetQuality();
2832 ItemLevelBonus = 0;
2833 RequiredLevel = proto->GetBaseRequiredLevel();
2834 for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
2835 ItemStatType[i] = proto->GetStatModifierBonusStat(i);
2836
2837 for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
2838 StatPercentEditor[i] = proto->GetStatPercentEditor(i);
2839
2840 for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
2841 ItemStatSocketCostMultiplier[i] = proto->GetStatPercentageOfSocket(i);
2842
2843 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
2844 {
2845 SocketColor[i] = proto->GetSocketColor(i);
2846 GemItemLevelBonus[i] = 0;
2847 GemRelicType[i] = -1;
2848 GemRelicRankBonus[i] = 0;
2849 }
2850
2851 Bonding = proto->GetBonding();
2852
2853 AppearanceModID = 0;
2854 RepairCostMultiplier = 1.0f;
2855 ContentTuningId = proto->GetScalingStatContentTuning();
2856 PlayerLevelToItemLevelCurveId = proto->GetPlayerLevelToItemLevelCurveId();
2857 RelicType = -1;
2858 HasFixedLevel = false;
2859 RequiredLevelOverride = 0;
2860 AzeriteTierUnlockSetId = 0;
2861 if (AzeriteEmpoweredItemEntry const* azeriteEmpoweredItem = sDB2Manager.GetAzeriteEmpoweredItem(proto->GetId()))
2862 AzeriteTierUnlockSetId = azeriteEmpoweredItem->AzeriteTierUnlockSetID;
2863
2864 Suffix = 0;
2865 RequiredLevelCurve = 0;
2866
2867 EffectCount = 0;
2868 for (ItemEffectEntry const* itemEffect : proto->Effects)
2869 Effects[EffectCount++] = itemEffect;
2870
2871 for (std::size_t i = EffectCount; i < Effects.size(); ++i)
2872 Effects[i] = nullptr;
2873
2874 CanDisenchant = !proto->HasFlag(ITEM_FLAG_NO_DISENCHANT);
2875 CanScrap = proto->HasFlag(ITEM_FLAG4_SCRAPABLE);
2876
2877 _state.SuffixPriority = std::numeric_limits<int32>::max();
2878 _state.AppearanceModPriority = std::numeric_limits<int32>::max();
2879 _state.ScalingStatDistributionPriority = std::numeric_limits<int32>::max();
2880 _state.AzeriteTierUnlockSetPriority = std::numeric_limits<int32>::max();
2881 _state.RequiredLevelCurvePriority = std::numeric_limits<int32>::max();
2882 _state.HasQualityBonus = false;
2883}
2884
2886{
2887 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemInstance.ItemID);
2888 if (!proto)
2889 return;
2890
2891 Initialize(proto);
2892
2893 if (itemInstance.ItemBonus)
2894 for (uint32 bonusListID : itemInstance.ItemBonus->BonusListIDs)
2895 AddBonusList(bonusListID);
2896}
2897
2899{
2900 for (ItemBonusEntry const* bonus : ItemBonusMgr::GetItemBonuses(bonusListId))
2901 AddBonus(bonus->Type, bonus->Value);
2902}
2903
2904void BonusData::AddBonus(uint32 type, std::array<int32, 4> const& values)
2905{
2906 switch (type)
2907 {
2909 ItemLevelBonus += values[0];
2910 break;
2911 case ITEM_BONUS_STAT:
2912 {
2913 uint32 statIndex = 0;
2914 for (statIndex = 0; statIndex < MAX_ITEM_PROTO_STATS; ++statIndex)
2915 if (ItemStatType[statIndex] == values[0] || ItemStatType[statIndex] == -1)
2916 break;
2917
2918 if (statIndex < MAX_ITEM_PROTO_STATS)
2919 {
2920 ItemStatType[statIndex] = values[0];
2921 StatPercentEditor[statIndex] += values[1];
2922 }
2923 break;
2924 }
2925 case ITEM_BONUS_QUALITY:
2926 if (!_state.HasQualityBonus)
2927 {
2928 Quality = static_cast<uint32>(values[0]);
2929 _state.HasQualityBonus = true;
2930 }
2931 else if (Quality < static_cast<uint32>(values[0]))
2932 Quality = static_cast<uint32>(values[0]);
2933 break;
2934 case ITEM_BONUS_SUFFIX:
2935 if (values[1] < _state.SuffixPriority)
2936 {
2937 Suffix = static_cast<uint32>(values[0]);
2938 _state.SuffixPriority = values[1];
2939 }
2940 break;
2941 case ITEM_BONUS_SOCKET:
2942 {
2943 uint32 socketCount = values[0];
2944 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS && socketCount; ++i)
2945 {
2946 if (!SocketColor[i])
2947 {
2948 SocketColor[i] = values[1];
2949 --socketCount;
2950 }
2951 }
2952 break;
2953 }
2955 if (values[1] < _state.AppearanceModPriority)
2956 {
2957 AppearanceModID = static_cast<uint32>(values[0]);
2958 _state.AppearanceModPriority = values[1];
2959 }
2960 break;
2962 RequiredLevel += values[0];
2963 break;
2965 RepairCostMultiplier *= static_cast<float>(values[0]) * 0.01f;
2966 break;
2969 if (values[1] < _state.ScalingStatDistributionPriority)
2970 {
2971 ContentTuningId = static_cast<uint32>(values[2]);
2972 PlayerLevelToItemLevelCurveId = static_cast<uint32>(values[3]);
2973 _state.ScalingStatDistributionPriority = values[1];
2974 HasFixedLevel = type == ITEM_BONUS_SCALING_STAT_DISTRIBUTION_FIXED;
2975 }
2976 break;
2977 case ITEM_BONUS_BONDING:
2978 Bonding = ItemBondingType(values[0]);
2979 break;
2981 RelicType = values[0];
2982 break;
2984 RequiredLevelOverride = values[0];
2985 break;
2987 if (values[1] < _state.AzeriteTierUnlockSetPriority)
2988 {
2989 AzeriteTierUnlockSetId = values[0];
2990 _state.AzeriteTierUnlockSetPriority = values[1];
2991 }
2992 break;
2994 CanDisenchant = values[0] != 0;
2995 break;
2997 CanScrap = values[0] != 0;
2998 break;
3000 if (ItemEffectEntry const* itemEffect = sItemEffectStore.LookupEntry(values[0]))
3001 Effects[EffectCount++] = itemEffect;
3002 break;
3004 if (values[2] < _state.RequiredLevelCurvePriority)
3005 {
3006 RequiredLevelCurve = values[0];
3007 _state.RequiredLevelCurvePriority = values[2];
3008 if (values[1])
3009 ContentTuningId = static_cast<uint32>(values[1]);
3010 }
3011 break;
3012 }
3013}
@ CHAR_UPD_ITEM_INSTANCE
@ CHAR_UPD_ITEM_INSTANCE_ON_LOAD
@ CHAR_DEL_ITEM_INSTANCE_GEMS
@ CHAR_DEL_ITEM_INSTANCE_ARTIFACT
@ CHAR_DEL_ITEM_INSTANCE_TRANSMOG
@ CHAR_DEL_ITEM_INSTANCE
@ CHAR_DEL_CHAR_INVENTORY_BY_ITEM
@ CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS
@ CHAR_INS_ITEM_INSTANCE_ARTIFACT_POWERS
@ CHAR_DEL_ITEM_BOP_TRADE
@ CHAR_DEL_ITEM_INSTANCE_MODIFIERS
@ CHAR_DEL_ITEM_REFUND_INSTANCE
@ CHAR_INS_ITEM_INSTANCE_MODIFIERS
@ CHAR_INS_ITEM_INSTANCE_TRANSMOG
@ CHAR_INS_ITEM_INSTANCE_ARTIFACT
@ CHAR_UPD_GIFT_OWNER
@ CHAR_INS_ITEM_INSTANCE_GEMS
@ CHAR_DEL_GIFT
@ CHAR_REP_ITEM_INSTANCE
@ CHAR_INS_ITEM_REFUND_INSTANCE
LocaleConstant
Definition: Common.h:48
@ HOUR
Definition: Common.h:30
#define sConditionMgr
Definition: ConditionMgr.h:365
DB2Storage< ArtifactAppearanceEntry > sArtifactAppearanceStore("ArtifactAppearance.db2", &ArtifactAppearanceLoadInfo::Instance)
DB2Storage< ItemNameDescriptionEntry > sItemNameDescriptionStore("ItemNameDescription.db2", &ItemNameDescriptionLoadInfo::Instance)
DB2Storage< ArtifactEntry > sArtifactStore("Artifact.db2", &ArtifactLoadInfo::Instance)
DB2Storage< ArtifactPowerPickerEntry > sArtifactPowerPickerStore("ArtifactPowerPicker.db2", &ArtifactPowerPickerLoadInfo::Instance)
DB2Storage< ImportPriceWeaponEntry > sImportPriceWeaponStore("ImportPriceWeapon.db2", &ImportPriceWeaponLoadInfo::Instance)
DB2Storage< DurabilityQualityEntry > sDurabilityQualityStore("DurabilityQuality.db2", &DurabilityQualityLoadInfo::Instance)
DB2Storage< ArtifactPowerEntry > sArtifactPowerStore("ArtifactPower.db2", &ArtifactPowerLoadInfo::Instance)
DB2Storage< ItemPriceBaseEntry > sItemPriceBaseStore("ItemPriceBase.db2", &ItemPriceBaseLoadInfo::Instance)
DB2Storage< ArtifactUnlockEntry > sArtifactUnlockStore("ArtifactUnlock.db2", &ArtifactUnlockLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
DB2Storage< ItemSetEntry > sItemSetStore("ItemSet.db2", &ItemSetLoadInfo::Instance)
DB2Storage< ItemEffectEntry > sItemEffectStore("ItemEffect.db2", &ItemEffectLoadInfo::Instance)
DB2Storage< ImportPriceShieldEntry > sImportPriceShieldStore("ImportPriceShield.db2", &ImportPriceShieldLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< ItemDisenchantLootEntry > sItemDisenchantLootStore("ItemDisenchantLoot.db2", &ItemDisenchantLootLoadInfo::Instance)
DB2Storage< AzeriteLevelInfoEntry > sAzeriteLevelInfoStore("AzeriteLevelInfo.db2", &AzeriteLevelInfoLoadInfo::Instance)
DB2Storage< ImportPriceQualityEntry > sImportPriceQualityStore("ImportPriceQuality.db2", &ImportPriceQualityLoadInfo::Instance)
DB2Storage< GemPropertiesEntry > sGemPropertiesStore("GemProperties.db2", &GemPropertiesLoadInfo::Instance)
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
DB2Storage< ImportPriceArmorEntry > sImportPriceArmorStore("ImportPriceArmor.db2", &ImportPriceArmorLoadInfo::Instance)
DB2Storage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore("SpellItemEnchantment.db2", &SpellItemEnchantmentLoadInfo::Instance)
DB2Storage< AzeritePowerEntry > sAzeritePowerStore("AzeritePower.db2", &AzeritePowerLoadInfo::Instance)
DB2Storage< ItemAppearanceEntry > sItemAppearanceStore("ItemAppearance.db2", &ItemAppearanceLoadInfo::Instance)
DB2Storage< AzeriteEssenceEntry > sAzeriteEssenceStore("AzeriteEssence.db2", &AzeriteEssenceLoadInfo::Instance)
DB2Storage< ArtifactAppearanceSetEntry > sArtifactAppearanceSetStore("ArtifactAppearanceSet.db2", &ArtifactAppearanceSetLoadInfo::Instance)
DB2Storage< DurabilityCostsEntry > sDurabilityCostsStore("DurabilityCosts.db2", &DurabilityCostsLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
#define MAX_ITEM_ENCHANTMENT_EFFECTS
@ ITEM_BONUS_APPEARANCE
Definition: DBCEnums.h:1035
@ ITEM_BONUS_RELIC_TYPE
Definition: DBCEnums.h:1045
@ ITEM_BONUS_BONDING
Definition: DBCEnums.h:1044
@ ITEM_BONUS_SOCKET
Definition: DBCEnums.h:1034
@ ITEM_BONUS_SUFFIX
Definition: DBCEnums.h:1033
@ ITEM_BONUS_REQUIRED_LEVEL
Definition: DBCEnums.h:1036
@ ITEM_BONUS_AZERITE_TIER_UNLOCK_SET
Definition: DBCEnums.h:1047
@ ITEM_BONUS_SCALING_STAT_DISTRIBUTION
Definition: DBCEnums.h:1039
@ ITEM_BONUS_SCALING_STAT_DISTRIBUTION_FIXED
Definition: DBCEnums.h:1041
@ ITEM_BONUS_OVERRIDE_CAN_DISENCHANT
Definition: DBCEnums.h:1049
@ ITEM_BONUS_ITEM_LEVEL
Definition: DBCEnums.h:1029
@ ITEM_BONUS_REQUIRED_LEVEL_CURVE
Definition: DBCEnums.h:1053
@ ITEM_BONUS_QUALITY
Definition: DBCEnums.h:1031
@ ITEM_BONUS_REPAIR_COST_MULTIPLIER
Definition: DBCEnums.h:1038
@ ITEM_BONUS_OVERRIDE_REQUIRED_LEVEL
Definition: DBCEnums.h:1046
@ ITEM_BONUS_OVERRIDE_CAN_SCRAP
Definition: DBCEnums.h:1050
@ ITEM_BONUS_STAT
Definition: DBCEnums.h:1030
@ ITEM_BONUS_ITEM_EFFECT_ID
Definition: DBCEnums.h:1051
#define MAX_AZERITE_EMPOWERED_TIER
Definition: DBCEnums.h:200
@ ITEM_ENCHANTMENT_TYPE_BONUS_LIST_CURVE
Definition: DBCEnums.h:1013
@ ITEM_ENCHANTMENT_TYPE_ARTIFACT_POWER_BONUS_RANK_BY_TYPE
Definition: DBCEnums.h:1010
@ ITEM_ENCHANTMENT_TYPE_ARTIFACT_POWER_BONUS_RANK_BY_ID
Definition: DBCEnums.h:1011
@ ITEM_ENCHANTMENT_TYPE_BONUS_LIST_ID
Definition: DBCEnums.h:1012
@ ITEM_ENCHANTMENT_TYPE_ARTIFACT_POWER_BONUS_RANK_PICKER
Definition: DBCEnums.h:1014
@ DIFFICULTY_NONE
Definition: DBCEnums.h:874
#define MAX_ITEM_PROTO_SOCKETS
Definition: DBCEnums.h:989
ItemContext
Definition: DBCEnums.h:1063
@ CURVE_ID_ARTIFACT_RELIC_ITEM_LEVEL_BONUS
Definition: DBCEnums.h:857
ChrSpecialization
Definition: DBCEnums.h:357
@ ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS
Definition: DBCEnums.h:191
@ ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER
Definition: DBCEnums.h:193
@ ARTIFACT_POWER_FLAG_FIRST
Definition: DBCEnums.h:195
@ ITEM_SET_FLAG_LEGACY_INACTIVE
Definition: DBCEnums.h:1177
#define MAX_AZERITE_ESSENCE_SLOT
Definition: DBCEnums.h:202
#define MAX_ITEM_PROTO_STATS
Definition: DBCEnums.h:990
#define MAX_ARTIFACT_TIER
Definition: DBCEnums.h:198
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int16_t int16
Definition: Define.h:139
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
uint16 flags
Definition: DisableMgr.cpp:49
#define ABORT
Definition: Errors.h:74
#define ASSERT_NODEBUGINFO
Definition: Errors.h:69
#define ASSERT
Definition: Errors.h:68
GameTable< GtItemSocketCostPerLevelEntry > sItemSocketCostPerLevelGameTable
Definition: GameTables.cpp:36
GameTable< GtArtifactKnowledgeMultiplierEntry > sArtifactKnowledgeMultiplierGameTable
Definition: GameTables.cpp:28
GameTable< GtArtifactLevelXPEntry > sArtifactLevelXPGameTable
Definition: GameTables.cpp:29
EnchantmentSlot
Definition: ItemDefines.h:178
@ PERM_ENCHANTMENT_SLOT
Definition: ItemDefines.h:179
@ SOCK_ENCHANTMENT_SLOT_3
Definition: ItemDefines.h:183
@ MAX_ENCHANTMENT_SLOT
Definition: ItemDefines.h:195
@ SOCK_ENCHANTMENT_SLOT
Definition: ItemDefines.h:181
@ MAX_INSPECTED_ENCHANTMENT_SLOT
Definition: ItemDefines.h:188
InventoryResult
Definition: ItemDefines.h:25
@ EQUIP_ERR_OK
Definition: ItemDefines.h:26
@ EQUIP_ERR_LOOT_GONE
Definition: ItemDefines.h:76
@ EQUIP_ERR_CANT_STACK
Definition: ItemDefines.h:45
ItemModifier
Definition: ItemDefines.h:210
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3
Definition: ItemDefines.h:245
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5
Definition: ItemDefines.h:238
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2
Definition: ItemDefines.h:223
@ ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS
Definition: ItemDefines.h:218
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_ALL_SPECS
Definition: ItemDefines.h:242
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4
Definition: ItemDefines.h:246
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1
Definition: ItemDefines.h:221
@ ITEM_MODIFIER_TIMEWALKER_LEVEL
Definition: ItemDefines.h:220
@ ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID
Definition: ItemDefines.h:217
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_5
Definition: ItemDefines.h:247
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4
Definition: ItemDefines.h:226
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_5
Definition: ItemDefines.h:236
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4
Definition: ItemDefines.h:227
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1
Definition: ItemDefines.h:243
@ ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID
Definition: ItemDefines.h:219
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3
Definition: ItemDefines.h:225
@ ITEM_MODIFIER_BATTLE_PET_BREED_DATA
Definition: ItemDefines.h:215
@ ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL
Definition: ItemDefines.h:234
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2
Definition: ItemDefines.h:222
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3
Definition: ItemDefines.h:224
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS
Definition: ItemDefines.h:211
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_2
Definition: ItemDefines.h:244
@ ITEM_MODIFIER_ARTIFACT_TIER
Definition: ItemDefines.h:235
@ ITEM_MODIFIER_BATTLE_PET_SPECIES_ID
Definition: ItemDefines.h:214
@ ITEM_MODIFIER_BATTLE_PET_LEVEL
Definition: ItemDefines.h:216
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1
Definition: ItemDefines.h:212
TC_GAME_API float GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subClass)
uint32 ItemRandomBonusListId
int32 const SocketColorToGemTypeMask[26]
@ ITEM_CLASS_QUIVER
Definition: ItemTemplate.h:431
@ ITEM_CLASS_CONTAINER
Definition: ItemTemplate.h:421
@ ITEM_CLASS_GEM
Definition: ItemTemplate.h:423
@ ITEM_CLASS_ARMOR
Definition: ItemTemplate.h:424
@ ITEM_CLASS_WEAPON
Definition: ItemTemplate.h:422
@ ITEM_FLAG2_NO_ALTER_ITEM_VISUAL
Definition: ItemTemplate.h:233
@ ITEM_FLAG2_OVERRIDE_GOLD_COST
Definition: ItemTemplate.h:226
@ ITEM_SUBCLASS_WEAPON_CROSSBOW
Definition: ItemTemplate.h:498
@ ITEM_SUBCLASS_WEAPON_GUN
Definition: ItemTemplate.h:483
@ ITEM_SUBCLASS_WEAPON_AXE2
Definition: ItemTemplate.h:481
@ ITEM_SUBCLASS_WEAPON_STAFF
Definition: ItemTemplate.h:490
@ ITEM_SUBCLASS_WEAPON_MACE
Definition: ItemTemplate.h:484
@ ITEM_SUBCLASS_WEAPON_WARGLAIVES
Definition: ItemTemplate.h:489
@ ITEM_SUBCLASS_WEAPON_FISHING_POLE
Definition: ItemTemplate.h:500
@ ITEM_SUBCLASS_WEAPON_MACE2
Definition: ItemTemplate.h:485
@ ITEM_SUBCLASS_WEAPON_DAGGER
Definition: ItemTemplate.h:495
@ ITEM_SUBCLASS_WEAPON_BOW
Definition: ItemTemplate.h:482
@ ITEM_SUBCLASS_WEAPON_SWORD
Definition: ItemTemplate.h:487
@ ITEM_SUBCLASS_WEAPON_AXE
Definition: ItemTemplate.h:480
@ ITEM_SUBCLASS_WEAPON_FIST_WEAPON
Definition: ItemTemplate.h:493
@ ITEM_SUBCLASS_WEAPON_SWORD2
Definition: ItemTemplate.h:488
@ ITEM_SUBCLASS_WEAPON_POLEARM
Definition: ItemTemplate.h:486
ItemFieldFlags
Definition: ItemTemplate.h:130
@ ITEM_FIELD_FLAG_REFUNDABLE
Definition: ItemTemplate.h:143
@ ITEM_FIELD_FLAG_CHILD
Definition: ItemTemplate.h:150
@ ITEM_FIELD_FLAG_SOULBOUND
Definition: ItemTemplate.h:131
@ ITEM_FIELD_FLAG_BOP_TRADEABLE
Definition: ItemTemplate.h:139
@ BAG_FAMILY_MASK_MINING_SUPP
Definition: ItemTemplate.h:335
@ BAG_FAMILY_MASK_HERBS
Definition: ItemTemplate.h:330
@ BAG_FAMILY_MASK_ENCHANTING_SUPP
Definition: ItemTemplate.h:331
@ BAG_FAMILY_MASK_SOUL_SHARDS
Definition: ItemTemplate.h:327
@ BAG_FAMILY_MASK_INSCRIPTION_SUPP
Definition: ItemTemplate.h:329
@ BAG_FAMILY_MASK_GEMS
Definition: ItemTemplate.h:334
@ BAG_FAMILY_MASK_ARROWS
Definition: ItemTemplate.h:325
@ BAG_FAMILY_MASK_BULLETS
Definition: ItemTemplate.h:326
@ BAG_FAMILY_MASK_ENGINEERING_SUPP
Definition: ItemTemplate.h:332
@ BAG_FAMILY_MASK_COOKING_SUPP
Definition: ItemTemplate.h:341
@ BAG_FAMILY_MASK_FISHING_SUPP
Definition: ItemTemplate.h:340
@ BAG_FAMILY_MASK_LEATHERWORKING_SUPP
Definition: ItemTemplate.h:328
@ ITEM_SUBCLASS_CONTAINER
Definition: ItemTemplate.h:462
@ ITEM_SUBCLASS_REAGENT_CONTAINER
Definition: ItemTemplate.h:473
@ ITEM_SUBCLASS_COOKING_CONTAINER
Definition: ItemTemplate.h:472
@ ITEM_SUBCLASS_INSCRIPTION_CONTAINER
Definition: ItemTemplate.h:470
@ ITEM_SUBCLASS_LEATHERWORKING_CONTAINER
Definition: ItemTemplate.h:469
@ ITEM_SUBCLASS_TACKLE_CONTAINER
Definition: ItemTemplate.h:471
@ ITEM_SUBCLASS_GEM_CONTAINER
Definition: ItemTemplate.h:467
@ ITEM_SUBCLASS_SOUL_CONTAINER
Definition: ItemTemplate.h:463
@ ITEM_SUBCLASS_ENCHANTING_CONTAINER
Definition: ItemTemplate.h:465
@ ITEM_SUBCLASS_MINING_CONTAINER
Definition: ItemTemplate.h:468
@ ITEM_SUBCLASS_HERB_CONTAINER
Definition: ItemTemplate.h:464
@ ITEM_SUBCLASS_ENGINEERING_CONTAINER
Definition: ItemTemplate.h:466
@ ITEM_SUBCLASS_QUIVER
Definition: ItemTemplate.h:641
@ ITEM_SUBCLASS_AMMO_POUCH
Definition: ItemTemplate.h:642
@ ITEM_FLAG_NO_DISENCHANT
Definition: ItemTemplate.h:191
@ ITEM_FLAG_CONJURED
Definition: ItemTemplate.h:177
@ ITEM_FLAG3_CAN_STORE_ENCHANTS
Definition: ItemTemplate.h:272
@ ITEM_FLAG3_IGNORE_ITEM_LEVEL_CAP_IN_PVP
Definition: ItemTemplate.h:256
@ ITEM_MOD_CORRUPTION_RESISTANCE
Definition: ItemTemplate.h:48
@ ITEM_MOD_CORRUPTION
Definition: ItemTemplate.h:47
@ ITEM_SUBCLASS_ARMOR_MAIL
Definition: ItemTemplate.h:532
@ ITEM_SUBCLASS_ARMOR_CLOTH
Definition: ItemTemplate.h:530
@ ITEM_SUBCLASS_ARMOR_LEATHER
Definition: ItemTemplate.h:531
@ ITEM_SUBCLASS_ARMOR_PLATE
Definition: ItemTemplate.h:533
@ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS
Definition: ItemTemplate.h:529
@ ITEM_SUBCLASS_ARMOR_COSMETIC
Definition: ItemTemplate.h:534
@ ITEM_FLAG4_SCRAPABLE
Definition: ItemTemplate.h:289
#define MAX_INVTYPE
Definition: ItemTemplate.h:416
@ MIN_ITEM_LEVEL
Definition: ItemTemplate.h:764
@ MAX_ITEM_LEVEL
Definition: ItemTemplate.h:765
SocketColor
Definition: ItemTemplate.h:345
@ ITEM_SUBCLASS_GEM_ARTIFACT_RELIC
Definition: ItemTemplate.h:522
ItemBondingType
Definition: ItemTemplate.h:115
@ BIND_QUEST
Definition: ItemTemplate.h:120
@ BIND_NONE
Definition: ItemTemplate.h:116
@ INVTYPE_FINGER
Definition: ItemTemplate.h:390
@ INVTYPE_HEAD
Definition: ItemTemplate.h:380
@ INVTYPE_CLOAK
Definition: ItemTemplate.h:395
@ INVTYPE_ROBE
Definition: ItemTemplate.h:399
@ INVTYPE_HOLDABLE
Definition: ItemTemplate.h:402
@ INVTYPE_TRINKET
Definition: ItemTemplate.h:391
@ INVTYPE_RELIC
Definition: ItemTemplate.h:407
@ INVTYPE_RANGED
Definition: ItemTemplate.h:394
@ INVTYPE_THROWN
Definition: ItemTemplate.h:404
@ INVTYPE_WAIST
Definition: ItemTemplate.h:385
@ INVTYPE_RANGEDRIGHT
Definition: ItemTemplate.h:405
@ INVTYPE_WRISTS
Definition: ItemTemplate.h:388
@ INVTYPE_WEAPON
Definition: ItemTemplate.h:392
@ INVTYPE_WEAPONMAINHAND
Definition: ItemTemplate.h:400
@ INVTYPE_WEAPONOFFHAND
Definition: ItemTemplate.h:401
@ INVTYPE_2HWEAPON
Definition: ItemTemplate.h:396
@ INVTYPE_BAG
Definition: ItemTemplate.h:397
@ INVTYPE_NECK
Definition: ItemTemplate.h:381
@ INVTYPE_SHOULDERS
Definition: ItemTemplate.h:382
@ INVTYPE_FEET
Definition: ItemTemplate.h:387
@ INVTYPE_NON_EQUIP
Definition: ItemTemplate.h:379
@ INVTYPE_AMMO
Definition: ItemTemplate.h:403
@ INVTYPE_QUIVER
Definition: ItemTemplate.h:406
@ INVTYPE_SHIELD
Definition: ItemTemplate.h:393
@ INVTYPE_LEGS
Definition: ItemTemplate.h:386
@ INVTYPE_CHEST
Definition: ItemTemplate.h:384
@ INVTYPE_HANDS
Definition: ItemTemplate.h:389
void RemoveItemsSetItem(Player *player, Item const *item)
Definition: Item.cpp:155
bool ItemCanGoIntoBag(ItemTemplate const *pProto, ItemTemplate const *pBagProto)
Definition: Item.cpp:208
ItemModifier const AppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition: Item.cpp:283
ItemTransmogrificationWeaponCategory
Definition: Item.cpp:1982
static ItemTransmogrificationWeaponCategory GetTransmogrificationWeaponCategory(ItemTemplate const *proto)
Definition: Item.cpp:1995
ItemModifier const SecondaryAppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition: Item.cpp:301
void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition: Item.cpp:1218
Item * NewItemOrBag(ItemTemplate const *proto)
Definition: Item.cpp:52
ItemModifier const IllusionModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition: Item.cpp:292
int32 const ItemTransmogrificationSlots[MAX_INVTYPE]
Definition: Item.cpp:2028
void AddItemsSetItem(Player *player, Item const *item)
Definition: Item.cpp:66
void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition: Item.cpp:1197
#define MAX_GEM_SOCKETS
Definition: Item.h:48
#define MAX_ENCHANTMENT_OFFSET
Definition: Item.h:50
ItemUpdateState
Definition: Item.h:53
@ ITEM_CHANGED
Definition: Item.h:55
@ ITEM_REMOVED
Definition: Item.h:57
@ ITEM_NEW
Definition: Item.h:56
@ ITEM_UNCHANGED
Definition: Item.h:54
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define sLootItemStorage
@ TYPEID_OBJECT
Definition: ObjectGuid.h:35
@ TYPEID_ITEM
Definition: ObjectGuid.h:36
std::set< ObjectGuid > GuidSet
Definition: ObjectGuid.h:393
@ TYPEMASK_ITEM
Definition: ObjectGuid.h:56
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::unordered_map< Player *, UpdateData > UpdateDataMapType
Definition: Object.h:79
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ EQUIPMENT_SLOT_SHOULDERS
Definition: Player.h:633
@ EQUIPMENT_SLOT_BODY
Definition: Player.h:634
@ EQUIPMENT_SLOT_HANDS
Definition: Player.h:640
@ EQUIPMENT_SLOT_MAINHAND
Definition: Player.h:646
@ EQUIPMENT_SLOT_TABARD
Definition: Player.h:649
@ EQUIPMENT_SLOT_END
Definition: Player.h:650
@ EQUIPMENT_SLOT_HEAD
Definition: Player.h:631
@ EQUIPMENT_SLOT_LEGS
Definition: Player.h:637
@ EQUIPMENT_SLOT_BACK
Definition: Player.h:645
@ EQUIPMENT_SLOT_OFFHAND
Definition: Player.h:647
@ EQUIPMENT_SLOT_WAIST
Definition: Player.h:636
@ EQUIPMENT_SLOT_FEET
Definition: Player.h:638
@ EQUIPMENT_SLOT_CHEST
Definition: Player.h:635
@ EQUIPMENT_SLOT_WRISTS
Definition: Player.h:639
@ PROFESSION_SLOT_START
Definition: Player.h:668
@ PROFESSION_SLOT_END
Definition: Player.h:667
#define INVENTORY_SLOT_BAG_0
Definition: Player.h:625
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
#define sScriptMgr
Definition: ScriptMgr.h:1418
#define MAX_SPECIALIZATIONS
@ SPELL_EFFECT_ENCHANT_ITEM
@ SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
@ SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
#define sSpellMgr
Definition: SpellMgr.h:849
TradeSlots
Definition: TradeData.h:24
@ TRADE_SLOT_INVALID
Definition: TradeData.h:28
Definition: Bag.h:27
size_t wpos() const
Definition: ByteBuffer.h:412
void put(std::size_t pos, T value)
Definition: ByteBuffer.h:220
void AddItemAppearance(Item *item)
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
uint64 GetUInt64() const
Definition: Field.cpp:78
uint16 GetUInt16() const
Definition: Field.cpp:46
uint32 GetUInt32() const
Definition: Field.cpp:62
int32 GetInt32() const
Definition: Field.cpp:70
Definition: Item.h:170
std::string GetDebugInfo() const override
Definition: Item.cpp:2819
uint32 GetEnchantRequiredLevel() const
Definition: Item.cpp:1344
uint32 GetPlayedTime()
Definition: Item.cpp:1895
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition: Item.cpp:1129
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition: Item.cpp:1166
uint32 GetPaidExtendedCost() const
Definition: Item.h:364
uint8 GetSlot() const
Definition: Item.h:280
void SetItemFlag(ItemFieldFlags flags)
Definition: Item.h:209
static bool CanTransmogrifyItemWithItem(Item const *item, ItemModifiedAppearanceEntry const *itemModifiedAppearance)
Definition: Item.cpp:2067
bool IsWrapped() const
Definition: Item.h:250
void SetSpellCharges(uint8 index, int32 value)
Definition: Item.h:315
bool AddToObjectUpdate() override
Definition: Item.cpp:1797
void SetText(std::string const &text)
Definition: Item.h:305
void SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus)
Definition: Item.cpp:2599
void UpdateDuration(Player *owner, uint32 diff)
Definition: Item.cpp:542
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition: Item.cpp:561
void SetFixedLevel(uint8 level)
Definition: Item.cpp:2793
uint32 GetBuyPrice(Player const *owner, bool &standardPrice) const
Definition: Item.cpp:2115
void ReplaceAllItemFlags(ItemFieldFlags flags)
Definition: Item.h:211
void BuildUpdate(UpdateDataMapType &) override
Definition: Item.cpp:1693
bool IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
Definition: Item.cpp:1596
void RemoveItemFlag(ItemFieldFlags flags)
Definition: Item.h:210
Item()
Definition: Item.cpp:444
void BuildValuesUpdateWithFlag(ByteBuffer *data, UF::UpdateFieldFlag flags, Player const *target) const override
Definition: Item.cpp:1735
ItemBondingType GetBonding() const
Definition: Item.h:200
void DeleteRefundDataFromDB(CharacterDatabaseTransaction *trans)
Definition: Item.cpp:1832
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition: Item.h:298
std::unordered_map< uint32, uint16 > m_artifactPowerIdToIndex
Definition: Item.h:468
void SetPaidMoney(uint64 money)
Definition: Item.h:359
int32 GetSpellCharges(uint8 index=0) const
Definition: Item.h:314
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition: Item.cpp:1655
void AddBonuses(uint32 bonusListID)
Definition: Item.cpp:2534
Bag * m_container
Definition: Item.h:457
uint8 GetGemCountWithID(uint32 GemID) const
Definition: Item.cpp:1576
bool IsBoundAccountWide() const
Definition: Item.h:219
bool mb_in_trade
Definition: Item.h:460
Bag * ToBag()
Definition: Item.h:241
std::string m_text
Definition: Item.h:455
void InitArtifactPowers(uint8 artifactId, uint8 artifactTier)
Definition: Item.cpp:2614
AzeriteItem * ToAzeriteItem()
Definition: Item.h:243
bool HasStats() const
Definition: Item.cpp:1961
void BuildValuesUpdateForPlayerWithMask(UpdateData *data, UF::ObjectData::Mask const &requestedObjectMask, UF::ItemData::Mask const &requestedItemMask, Player const *target) const
Definition: Item.cpp:1751
int32 GetItemStatType(uint32 index) const
Definition: Item.h:342
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition: Item.cpp:1250
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const
Definition: Item.h:299
void ClearBonuses()
Definition: Item.cpp:2562
void SetContext(ItemContext context)
Definition: Item.h:442
uint32 GetQuality() const
Definition: Item.h:337
uint64 m_paidMoney
Definition: Item.h:463
std::array< uint32, MAX_ITEM_PROTO_SOCKETS > m_gemScalingLevels
Definition: Item.h:469
void GiveArtifactXp(uint64 amount, Item *sourceItem, uint32 artifactCategoryId)
Definition: Item.cpp:2760
UF::SocketedGem const * GetGem(uint16 slot) const
Definition: Item.cpp:1481
void SetCount(uint32 value)
Definition: Item.cpp:1275
void SetModifier(ItemModifier modifier, uint32 value)
Definition: Item.cpp:2436
void SetDurability(uint32 durability)
Definition: Item.h:258
ObjectGuid GetCreator() const
Definition: Item.h:192
ItemTemplate const * GetTemplate() const
Definition: Item.cpp:1141
void ApplyArtifactPowerEnchantmentBonuses(EnchantmentSlot slot, uint32 enchantId, bool apply, Player *owner)
Definition: Item.cpp:2664
std::vector< int32 > const & GetBonusListIDs() const
Definition: Item.h:229
bool IsBOPTradeable() const
Definition: Item.h:249
bool IsInBag() const
Definition: Item.h:287
void SetGem(uint16 slot, ItemDynamicFieldGems const *gem, uint32 gemScalingLevel)
Definition: Item.cpp:1487
bool IsSoulBound() const
Definition: Item.h:218
void SaveRefundDataToDB()
Definition: Item.cpp:1814
ItemContext GetContext() const
Definition: Item.h:441
void SetNotRefundable(Player *owner, bool changestate=true, CharacterDatabaseTransaction *trans=nullptr, bool addToCollection=true)
Definition: Item.cpp:1843
ItemRandomBonusListId m_randomBonusListId
Definition: Item.h:466
uint32 GetVisibleEnchantmentId(Player const *owner) const
Definition: Item.cpp:2514
void ClearUpdateMask(bool remove) override
Definition: Item.cpp:1791
friend void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition: Item.cpp:1218
bool IsBindedNotWith(Player const *player) const
Definition: Item.cpp:1672
void BuildValuesCreate(ByteBuffer *data, Player const *target) const override
Definition: Item.cpp:1708
bool IsEquipped() const
Definition: Item.cpp:1244
void SendTimeUpdate(Player *owner)
Definition: Item.cpp:1613
virtual bool Create(ObjectGuid::LowType guidlow, uint32 itemId, ItemContext context, Player const *owner)
Definition: Item.cpp:468
BonusData const * GetBonus() const
Definition: Item.h:186
void SetItemRandomBonusList(ItemRandomBonusListId bonusListId)
Definition: Item.cpp:1158
bool IsRefundExpired()
Definition: Item.cpp:1902
void UpdatePlayedTime(Player *owner)
Definition: Item.cpp:1867
Player * GetOwner() const
Definition: Item.cpp:1146
bool IsValidTransmogrificationTarget() const
Definition: Item.cpp:1939
ObjectGuid GetOwnerGUID() const
Definition: Item.h:188
uint32 GetAppearanceModId() const
Definition: Item.h:345
uint32 GetDisplayId(Player const *owner) const
Definition: Item.cpp:2405
BonusData _bonusData
Definition: Item.h:452
uint64 GetPaidMoney() const
Definition: Item.h:363
bool HasEnchantRequiredSkill(Player const *player) const
Definition: Item.cpp:1330
int32 GetVisibleSecondaryModifiedAppearanceId(Player const *owner) const
Definition: Item.cpp:2505
time_t m_lastPlayedTimeUpdate
Definition: Item.h:461
uint32 GetSkill()
Definition: Item.cpp:1152
bool IsRefundable() const
Definition: Item.h:248
uint16 GetPos() const
Definition: Item.h:284
ItemModifiedAppearanceEntry const * GetItemModifiedAppearance() const
Definition: Item.cpp:2418
float GetItemStatValue(uint32 index, Player const *owner) const
Definition: Item.cpp:2335
bool GemsFitSockets() const
Definition: Item.cpp:1544
uint64 CalculateDurabilityRepairCost(float discount) const
Definition: Item.cpp:1291
bool IsBoundByEnchant() const
Definition: Item.cpp:1358
void SetSoulboundTradeable(GuidSet const &allowedLooters)
Definition: Item.cpp:1907
int16 uQueuePos
Definition: Item.h:459
void SetContainedIn(ObjectGuid guid)
Definition: Item.h:191
uint32 GetVisibleEntry(Player const *owner) const
Definition: Item.cpp:2468
void BuildValuesUpdate(ByteBuffer *data, Player const *target) const override
Definition: Item.cpp:1719
ObjectGuid GetGiftCreator() const
Definition: Item.h:194
void CheckArtifactRelicSlotUnlock(Player const *owner)
Definition: Item.cpp:1072
UF::ArtifactPower const * GetArtifactPower(uint32 artifactPowerId) const
Definition: Item.cpp:2579
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
Definition: Item.cpp:1459
uint32 GetVisibleModifiedAppearanceId(Player const *owner) const
Definition: Item.cpp:2492
bool IsArtifactDisabled() const
Definition: Item.cpp:2571
uint32 GetTotalUnlockedArtifactPowers() const
Definition: Item.cpp:2632
uint32 m_paidExtendedCost
Definition: Item.h:464
bool IsBag() const
Definition: Item.h:252
void RemoveFromObjectUpdate() override
Definition: Item.cpp:1808
void ClearEnchantment(EnchantmentSlot slot)
Definition: Item.cpp:1468
ItemDisenchantLootEntry const * GetDisenchantLoot(Player const *owner) const
Definition: Item.cpp:2360
void SetArtifactXP(uint64 xp)
Definition: Item.h:438
std::unique_ptr< Loot > m_loot
Definition: Item.h:317
void SetCreator(ObjectGuid guid)
Definition: Item.h:193
uint32 GetItemLevel(Player const *owner) const
Definition: Item.cpp:2279
ObjectGuid const & GetRefundRecipient() const
Definition: Item.h:362
void SetCreatePlayedTime(uint32 createPlayedTime)
Definition: Item.h:311
void SendUpdateSockets()
Definition: Item.cpp:1603
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player *owner)
Definition: Item.cpp:1449
InventoryResult CanBeMergedPartlyWith(ItemTemplate const *proto) const
Definition: Item.cpp:1370
void SetPaidExtendedCost(uint32 iece)
Definition: Item.h:360
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const
Definition: Item.h:300
void SetBonuses(std::vector< int32 > bonusListIDs)
Definition: Item.cpp:2549
void SetAppearanceModId(uint32 appearanceModId)
Definition: Item.h:346
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
Definition: Item.cpp:524
void SetRefundRecipient(ObjectGuid const &guid)
Definition: Item.h:358
uint32 GetSellPrice(Player const *owner) const
Definition: Item.cpp:2248
uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const
Definition: Item.cpp:1584
void ClearSoulboundTradeable(Player *currentOwner)
Definition: Item.cpp:1913
bool IsNotEmptyBag() const
Definition: Item.cpp:535
virtual bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field *fields, uint32 entry)
Definition: Item.cpp:828
bool m_lootGenerated
Definition: Item.h:318
uint32 GetCount() const
Definition: Item.h:273
void SetExpiration(uint32 expiration)
Definition: Item.h:198
bool CheckSoulboundTradeExpire()
Definition: Item.cpp:1927
void SetOwnerGUID(ObjectGuid guid)
Definition: Item.h:189
float GetRepairCostMultiplier() const
Definition: Item.h:349
uint16 GetVisibleItemVisual(Player const *owner) const
Definition: Item.cpp:2526
uint16 GetVisibleAppearanceModId(Player const *owner) const
Definition: Item.cpp:2480
uint8 GetBagSlot() const
Definition: Item.cpp:1239
UF::UpdateFieldFlag GetUpdateFieldFlagsFor(Player const *target) const override
Definition: Item.cpp:1700
void SetGiftCreator(ObjectGuid guid)
Definition: Item.h:195
uint32 GetModifier(ItemModifier modifier) const
Definition: Item.cpp:2423
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster=ObjectGuid::Empty)
Definition: Item.cpp:1421
static void DeleteFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition: Item.cpp:1088
void AddArtifactPower(ArtifactPowerData const *artifactPower)
Definition: Item.cpp:2588
uint32 GetTotalPurchasedArtifactPowers() const
Definition: Item.cpp:2655
uint8 m_slot
Definition: Item.h:456
void CopyArtifactDataFromParent(Item *parent)
Definition: Item.cpp:2753
UF::UpdateField< UF::ItemData, 0, TYPEID_ITEM > m_itemData
Definition: Item.h:449
friend void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition: Item.cpp:1197
bool IsInUpdateQueue() const
Definition: Item.h:324
int32 GetRequiredLevel() const
Definition: Item.cpp:2807
static Item * CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const *player=nullptr, bool addDefaultBonuses=true)
Definition: Item.cpp:1625
void LoadArtifactData(Player const *owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector< ArtifactPowerData > &powers)
Definition: Item.cpp:1003
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition: Item.cpp:1387
GuidSet allowedGUIDs
Definition: Item.h:465
ItemUpdateState uState
Definition: Item.h:458
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
std::string ToString() const
Definition: ObjectGuid.cpp:554
uint64 LowType
Definition: ObjectGuid.h:278
void BuildFieldsUpdate(Player *, UpdateDataMapType &) const
Definition: Object.cpp:802
uint16 m_objectType
Definition: Object.h:401
ObjectGuid const & GetGUID() const
Definition: Object.h:160
UF::UpdateField< UF::ObjectData, 0, TYPEID_OBJECT > m_objectData
Definition: Object.h:267
UF::DynamicUpdateFieldSetter< T >::insert_result AddDynamicUpdateFieldValue(UF::DynamicUpdateFieldSetter< T > setter)
Definition: Object.h:308
virtual void ClearUpdateMask(bool remove)
Definition: Object.cpp:790
void SetUpdateFieldValue(UF::UpdateFieldSetter< T > setter, typename UF::UpdateFieldSetter< T >::value_type value)
Definition: Object.h:287
uint32 GetEntry() const
Definition: Object.h:161
UF::UpdateFieldHolder m_values
Definition: Object.h:266
virtual std::string GetDebugInfo() const
Definition: Object.cpp:816
void _Create(ObjectGuid const &guid)
Definition: Object.cpp:101
ByteBuffer & PrepareValuesUpdateBuffer(UpdateData *data) const
Definition: Object.cpp:225
void RemoveDynamicUpdateFieldValue(UF::DynamicUpdateFieldSetter< T > setter, uint32 index)
Definition: Object.h:322
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void SetEntry(uint32 entry)
Definition: Object.h:162
virtual void SetObjectScale(float scale)
Definition: Object.h:165
TypeID m_objectTypeId
Definition: Object.h:403
ChrSpecialization GetPrimarySpecialization() const
Definition: Player.h:1841
std::vector< Item * > m_itemUpdateQueue
Definition: Player.h:3022
UF::UpdateField< UF::PlayerData, 0, TYPEID_PLAYER > m_playerData
Definition: Player.h:2863
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
uint16 GetSkillValue(uint32 skill) const
Definition: Player.cpp:6052
bool MeetPlayerCondition(uint32 conditionId) const
Definition: Player.cpp:29377
WorldSession * GetSession() const
Definition: Player.h:2101
void DestroyItem(uint8 bag, uint8 slot, bool update)
Definition: Player.cpp:12180
bool IsUsingPvpItemLevels() const
Definition: Player.h:2562
std::vector< ItemSetEffect * > ItemSetEff
Definition: Player.h:2381
static bool IsBagPos(uint16 pos)
Definition: Player.cpp:9766
uint8 GetActiveTalentGroup() const
Definition: Player.h:1843
void ApplyEquipSpell(SpellInfo const *spellInfo, Item *item, bool apply, bool formChange=false)
Definition: Player.cpp:8357
void DeleteRefundReference(ObjectGuid it)
Definition: Player.cpp:28576
void ApplyArtifactPowerRank(Item *artifact, ArtifactPowerRankEntry const *artifactPowerRank, bool apply)
Definition: Player.cpp:8458
bool m_itemUpdateQueueBlocked
Definition: Player.h:3023
void setUInt8(const uint8 index, const uint8 value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt16(const uint8 index, const uint16 value)
void setString(const uint8 index, const std::string &value)
void setUInt64(const uint8 index, const uint64 value)
bool HasEffect(SpellEffectName effect) const
Definition: SpellInfo.cpp:1391
int32 EquippedItemClass
Definition: SpellInfo.h:396
int32 EquippedItemSubClassMask
Definition: SpellInfo.h:397
int32 EquippedItemInventoryTypeMask
Definition: SpellInfo.h:398
Mask const & GetChangesMask() const
Definition: UpdateField.h:605
MutableFieldReference< T, false > ModifyValue(UpdateField< T, BlockBit, Bit >(Derived::*field))
Definition: UpdateField.h:683
void ClearChangesMask(UpdateField< T, BlockBit, Bit >(Derived::*field))
Definition: UpdateField.h:690
bool HasChanged(uint32 index) const
Definition: UpdateField.h:701
uint32 GetChangedObjectTypeMask() const
Definition: UpdateField.h:696
UF::UpdateField< UF::UnitData, 0, TYPEID_UNIT > m_unitData
Definition: Unit.h:1814
uint8 GetLevel() const
Definition: Unit.h:746
bool BuildPacket(WorldPacket *packet)
Definition: UpdateData.cpp:40
void AddUpdateBlock()
Definition: UpdateData.h:49
uint32 GetBlock(uint32 index) const
Definition: UpdateMask.h:53
void Set(uint32 index)
Definition: UpdateMask.h:84
constexpr uint32 GetMapId() const
Definition: Position.h:201
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
CollectionMgr * GetCollectionMgr() const
void SendEnchantmentLog(ObjectGuid owner, ObjectGuid caster, ObjectGuid itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantSlot)
#define sWorld
Definition: World.h:931
@ RATE_REPAIRCOST
Definition: World.h:488
void apply(T *val)
Definition: ByteConverter.h:41
time_t GetGameTime()
Definition: GameTime.cpp:44
std::vector< int32 > GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams const &params)
std::span< ItemBonusEntry const * > GetItemBonuses(uint32 bonusListId)
uint32 GetItemBonusListForItemLevelDelta(int16 delta)
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:29
std::string ToString(Type &&val, Params &&... params)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition: Util.cpp:56
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
UpdateFieldFlag
Definition: UpdateField.h:34
uint32 ArtifactPowerId
Definition: Item.h:116
uint8 CurrentRankWithBonus
Definition: Item.h:118
uint8 PurchasedRank
Definition: Item.h:117
Definition: Item.h:69
int32 RequiredLevel
Definition: Item.h:72
int32 RequiredLevelOverride
Definition: Item.h:87
void AddBonus(uint32 type, std::array< int32, 4 > const &values)
Definition: Item.cpp:2904
std::size_t EffectCount
Definition: Item.h:92
bool CanDisenchant
Definition: Item.h:93
int32 RelicType
Definition: Item.h:86
uint32 PlayerLevelToItemLevelCurveId
Definition: Item.h:81
int32 GemRelicType[MAX_ITEM_PROTO_SOCKETS]
Definition: Item.h:84
uint32 AppearanceModID
Definition: Item.h:78
int32 ItemLevelBonus
Definition: Item.h:71
int32 StatPercentEditor[MAX_ITEM_PROTO_STATS]
Definition: Item.h:74
uint32 Suffix
Definition: Item.h:89
bool HasFixedLevel
Definition: Item.h:95
void AddBonusList(uint32 bonusListId)
Definition: Item.cpp:2898
uint32 GemItemLevelBonus[MAX_ITEM_PROTO_SOCKETS]
Definition: Item.h:83
float ItemStatSocketCostMultiplier[MAX_ITEM_PROTO_STATS]
Definition: Item.h:75
uint32 ContentTuningId
Definition: Item.h:80
void Initialize(ItemTemplate const *proto)
Definition: Item.cpp:2829
int32 RequiredLevelCurve
Definition: Item.h:90
std::array< uint16, 8 > ArmorSubClassCost
std::array< uint16, 21 > WeaponSubClassCost
Optional< ArtifactData > Artifact
Definition: Item.h:155
Optional< AzeriteEmpoweredItemData > AzeriteEmpoweredItem
Definition: Item.h:157
static void Init(std::unordered_map< ObjectGuid::LowType, ItemAdditionalLoadInfo > *loadInfo, PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult, PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult, PreparedQueryResult azeriteEmpoweredItemResult)
Definition: Item.cpp:310
Optional< AzeriteItemData > AzeriteItem
Definition: Item.h:156
uint16 BonusListIDs[16]
Definition: Item.h:163
std::unordered_set< ItemSetSpellEntry const * > SetBonuses
Definition: Item.h:45
std::unordered_set< Item const * > EquippedItems
Definition: Item.h:44
uint32 ItemSetID
Definition: Item.h:43
uint16 RequiredSkillRank
uint32 RequiredSkill
uint32 GetBaseItemLevel() const
Definition: ItemTemplate.h:789
uint32 GetArea(uint32 index) const
Definition: ItemTemplate.h:812
uint32 GetQuality() const
Definition: ItemTemplate.h:779
int32 GetStatModifierBonusStat(uint32 index) const
Definition: ItemTemplate.h:798
uint32 GetDuration() const
Definition: ItemTemplate.h:820
uint32 GetBuyCount() const
Definition: ItemTemplate.h:783
float GetPriceRandomValue() const
Definition: ItemTemplate.h:781
uint32 GetGemProperties() const
Definition: ItemTemplate.h:818
uint32 GetId() const
Definition: ItemTemplate.h:776
uint32 GetMaxStackSize() const
Definition: ItemTemplate.h:847
InventoryType GetInventoryType() const
Definition: ItemTemplate.h:786
SocketColor GetSocketColor(uint32 index) const
Definition: ItemTemplate.h:816
uint32 GetBuyPrice() const
Definition: ItemTemplate.h:784
ItemBondingType GetBonding() const
Definition: ItemTemplate.h:806
uint32 GetItemSet() const
Definition: ItemTemplate.h:811
float GetStatPercentageOfSocket(uint32 index) const
Definition: ItemTemplate.h:800
uint32 GetScalingStatContentTuning() const
Definition: ItemTemplate.h:801
uint8 GetArtifactID() const
Definition: ItemTemplate.h:824
uint32 GetMap() const
Definition: ItemTemplate.h:813
std::vector< ItemEffectEntry const * > Effects
Definition: ItemTemplate.h:828
bool IsCraftingReagent() const
Definition: ItemTemplate.h:857
int32 GetBaseRequiredLevel() const
Definition: ItemTemplate.h:790
bool HasFlag(ItemFlags flag) const
Definition: ItemTemplate.h:871
uint32 GetSubClass() const
Definition: ItemTemplate.h:778
uint32 GetSellPrice() const
Definition: ItemTemplate.h:785
uint32 MaxDurability
Definition: ItemTemplate.h:827
char const * GetName(LocaleConstant locale) const
uint8 GetRequiredExpansion() const
Definition: ItemTemplate.h:825
int32 GetStatPercentEditor(uint32 index) const
Definition: ItemTemplate.h:799
uint32 GetClass() const
Definition: ItemTemplate.h:777
float GetPriceVariance() const
Definition: ItemTemplate.h:782
uint32 GetPlayerLevelToItemLevelCurveId() const
Definition: ItemTemplate.h:802
uint32 GetSkill() const
uint32 GetBagFamily() const
Definition: ItemTemplate.h:814
void operator()(Player const *player) const
Definition: Item.cpp:1780
UF::ObjectData::Base ObjectMask
Definition: Item.h:393
uint8 CurrentRankWithBonus
Definition: UpdateFields.h:99
UpdateFieldArray< UF::ItemEnchantment, 13, 27, 28 > Enchantment
Definition: UpdateFields.h:141
UpdateField< UF::ItemModList, 0, 17 > Modifiers
Definition: UpdateFields.h:136
DynamicUpdateField< UF::SocketedGem, 0, 2 > Gems
Definition: UpdateFields.h:121
UpdateField< WorldPackets::Item::ItemBonusKey, 0, 19 > ItemBonusKey
Definition: UpdateFields.h:138
UpdateField< uint32, 0, 11 > MaxDurability
Definition: UpdateFields.h:130
UpdateField< uint8, 0, 16 > ItemAppearanceModID
Definition: UpdateFields.h:135
UpdateField< uint64, 0, 15 > ArtifactXP
Definition: UpdateFields.h:134
UpdateField< uint32, 0, 7 > StackCount
Definition: UpdateFields.h:126
DynamicUpdateField< UF::ArtifactPower, 0, 1 > ArtifactPowers
Definition: UpdateFields.h:120
UpdateField< int16, 0, 3 > Charges
Definition: UpdateFields.h:67
UpdateField< int32, 0, 1 > ID
Definition: UpdateFields.h:65
UpdateField< uint16, 0, 4 > Inactive
Definition: UpdateFields.h:68
UpdateField< uint32, 0, 2 > Duration
Definition: UpdateFields.h:66
DynamicUpdateField< UF::ItemMod, -1, 0 > Values
Definition: UpdateFields.h:88
UpdateFieldArray< uint16, 16, 3, 4 > BonusListIDs
Definition: UpdateFields.h:111
UpdateField< uint8, 0, 2 > Context
Definition: UpdateFields.h:110
UpdateField< int32, 0, 1 > ItemID
Definition: UpdateFields.h:109
Optional< ItemBonuses > ItemBonus