TrinityCore
Loading...
Searching...
No Matches
Item.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Item.h"
19#include "ArtifactPackets.h"
21#include "AzeriteItem.h"
22#include "Bag.h"
23#include "ClientBuildInfo.h"
24#include "CollectionMgr.h"
25#include "Common.h"
26#include "ConditionMgr.h"
27#include "DB2Stores.h"
28#include "DatabaseEnv.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 "MapUtils.h"
40#include "ObjectAccessor.h"
41#include "ObjectMgr.h"
42#include "Player.h"
43#include "RealmList.h"
44#include "ScriptMgr.h"
45#include "SpellInfo.h"
46#include "SpellMgr.h"
47#include "StringConvert.h"
48#include "TradeData.h"
49#include "TransmogMgr.h"
50#include "UpdateData.h"
51#include "World.h"
52#include "WorldSession.h"
53#include <sstream>
54
56{
57 if (proto->GetInventoryType() == INVTYPE_BAG)
58 return new Bag();
59
60 if (sDB2Manager.IsAzeriteItem(proto->GetId()))
61 return new AzeriteItem();
62
63 if (sDB2Manager.GetAzeriteEmpoweredItem(proto->GetId()))
64 return new AzeriteEmpoweredItem();
65
66 return new Item();
67}
68
70{
72 std::unordered_set<Item const*> EquippedItems;
73 std::unordered_set<ItemSetSpellEntry const*> SetBonuses;
74};
75
76void AddItemsSetItem(Player* player, Item const* item)
77{
78 ItemTemplate const* proto = item->GetTemplate();
79 uint32 setid = proto->GetItemSet();
80
81 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
82
83 if (!set)
84 {
85 TC_LOG_ERROR("sql.sql", "Item set {} for item (id {}) not found, mods not applied.", setid, proto->GetId());
86 return;
87 }
88
89 if (set->RequiredSkill && player->GetSkillValue(set->RequiredSkill) < set->RequiredSkillRank)
90 return;
91
93 return;
94
95 // Check player level for heirlooms
96 if (sDB2Manager.GetHeirloomByItemId(item->GetEntry()))
97 {
99 {
100 uint32 maxLevel = sDB2Manager.GetCurveXAxisRange(item->GetBonus()->PlayerLevelToItemLevelCurveId).second;
101
102 if (Optional<ContentTuningLevels> contentTuning = sDB2Manager.GetContentTuningData(item->GetBonus()->ContentTuningId, player->m_playerData->CtrOptions->ConditionalFlags, true))
103 maxLevel = std::min<uint32>(maxLevel, contentTuning->MaxLevel);
104
105 if (player->GetLevel() > maxLevel)
106 return;
107 }
108 }
109
110 ItemSetEffect* eff = nullptr;
111
112 for (size_t x = 0; x < player->ItemSetEff.size(); ++x)
113 {
114 if (player->ItemSetEff[x] && player->ItemSetEff[x]->ItemSetID == setid)
115 {
116 eff = player->ItemSetEff[x];
117 break;
118 }
119 }
120
121 if (!eff)
122 {
123 eff = new ItemSetEffect();
124 eff->ItemSetID = setid;
125
126 size_t x = 0;
127 for (; x < player->ItemSetEff.size(); ++x)
128 if (!player->ItemSetEff[x])
129 break;
130
131 if (x < player->ItemSetEff.size())
132 player->ItemSetEff[x] = eff;
133 else
134 player->ItemSetEff.push_back(eff);
135 }
136
137 eff->EquippedItems.insert(item);
138
139 if (std::vector<ItemSetSpellEntry const*> const* itemSetSpells = sDB2Manager.GetItemSetSpells(setid))
140 {
141 for (ItemSetSpellEntry const* itemSetSpell : *itemSetSpells)
142 {
143 //not enough for spell
144 if (itemSetSpell->Threshold > eff->EquippedItems.size())
145 continue;
146
147 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
148 if (!spellInfo)
149 {
150 TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id {} in items set {} effects", itemSetSpell->SpellID, setid);
151 continue;
152 }
153
154 if (!eff->SetBonuses.insert(itemSetSpell).second)
155 continue;
156
157 // spell cast only if fit form requirement, in other case will cast at form change
158 if (itemSetSpell->ChrSpecID && ChrSpecialization(itemSetSpell->ChrSpecID) != player->GetPrimarySpecialization())
159 continue;
160
161 if (itemSetSpell->TraitSubTreeID && int32(itemSetSpell->TraitSubTreeID) != player->m_playerData->CurrentCombatTraitConfigSubTreeID)
162 continue;
163
164 player->ApplyEquipSpell(spellInfo, nullptr, true);
165 }
166 }
167}
168
169void RemoveItemsSetItem(Player* player, Item const* item)
170{
171 uint32 setid = item->GetTemplate()->GetItemSet();
172
173 ItemSetEntry const* set = sItemSetStore.LookupEntry(setid);
174
175 if (!set)
176 {
177 TC_LOG_ERROR("sql.sql", "Item set #{} for item #{} not found, mods not removed.", setid, item->GetEntry());
178 return;
179 }
180
181 ItemSetEffect* eff = nullptr;
182 size_t setindex = 0;
183 for (; setindex < player->ItemSetEff.size(); setindex++)
184 {
185 if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->ItemSetID == setid)
186 {
187 eff = player->ItemSetEff[setindex];
188 break;
189 }
190 }
191
192 // can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
193 if (!eff)
194 return;
195
196 eff->EquippedItems.erase(item);
197
198 if (std::vector<ItemSetSpellEntry const*> const* itemSetSpells = sDB2Manager.GetItemSetSpells(setid))
199 {
200 for (ItemSetSpellEntry const* itemSetSpell : *itemSetSpells)
201 {
202 // enough for spell
203 if (itemSetSpell->Threshold <= eff->EquippedItems.size())
204 continue;
205
206 if (!eff->SetBonuses.erase(itemSetSpell))
207 continue;
208
209 player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE), nullptr, false);
210 }
211 }
212
213 if (eff->EquippedItems.empty()) //all items of a set were removed
214 {
215 ASSERT(eff == player->ItemSetEff[setindex]);
216 delete eff;
217 player->ItemSetEff[setindex] = nullptr;
218 }
219}
220
221void UpdateItemSetAuras(Player* player, bool formChange)
222{
223 // item set bonuses not dependent from item broken state
224 for (ItemSetEffect* eff : player->ItemSetEff)
225 {
226 if (!eff)
227 continue;
228
229 for (ItemSetSpellEntry const* itemSetSpell : eff->SetBonuses)
230 {
231 SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
232
233 if ((itemSetSpell->ChrSpecID && ChrSpecialization(itemSetSpell->ChrSpecID) != player->GetPrimarySpecialization())
234 || (itemSetSpell->TraitSubTreeID && int32(itemSetSpell->TraitSubTreeID) != player->m_playerData->CurrentCombatTraitConfigSubTreeID))
235 player->ApplyEquipSpell(spellInfo, nullptr, false, false); // item set aura is not for current spec
236 else
237 {
238 player->ApplyEquipSpell(spellInfo, nullptr, false, formChange); // remove spells that not fit to form - removal is skipped if shapeshift condition is satisfied
239 player->ApplyEquipSpell(spellInfo, nullptr, true, formChange); // add spells that fit form but not active
240 }
241 }
242 }
243}
244
246{
247 delete itemSetEffect;
248}
249
250bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto)
251{
252 if (!pProto || !pBagProto)
253 return false;
254
255 switch (pBagProto->GetClass())
256 {
258 switch (pBagProto->GetSubClass())
259 {
261 return true;
263 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_SOUL_SHARDS))
264 return false;
265 return true;
267 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_HERBS))
268 return false;
269 return true;
272 return false;
273 return true;
275 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_MINING_SUPP))
276 return false;
277 return true;
280 return false;
281 return true;
283 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_GEMS))
284 return false;
285 return true;
288 return false;
289 return true;
292 return false;
293 return true;
296 return false;
297 return true;
300 return false;
301 return true;
303 return pProto->IsCraftingReagent();
304 default:
305 return false;
306 }
308 switch (pBagProto->GetSubClass())
309 {
311 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_ARROWS))
312 return false;
313 return true;
315 if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_BULLETS))
316 return false;
317 return true;
318 default:
319 return false;
320 }
321 }
322 return false;
323}
324
333
342
351
352void ItemAdditionalLoadInfo::Init(std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo>* loadInfo,
353 PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult,
354 PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult,
355 PreparedQueryResult azeriteEmpoweredItemResult)
356{
357 // 0 1 2 3 4 5
358 // 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 ...
359 if (artifactResult)
360 {
361 do
362 {
363 Field* fields = artifactResult->Fetch();
364 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
365 if (!info.Artifact)
366 info.Artifact.emplace();
367 info.Artifact->Xp = fields[1].GetUInt64();
368 info.Artifact->ArtifactAppearanceId = fields[2].GetUInt32();
369 info.Artifact->ArtifactTierId = fields[3].GetUInt32();
370 ArtifactPowerData artifactPowerData;
371 artifactPowerData.ArtifactPowerId = fields[4].GetUInt32();
372 artifactPowerData.PurchasedRank = fields[5].GetUInt8();
373 if (ArtifactPowerEntry const* artifactPower = sArtifactPowerStore.LookupEntry(artifactPowerData.ArtifactPowerId))
374 {
375 uint32 maxRank = artifactPower->MaxPurchasableRank;
376 // allow ARTIFACT_POWER_FLAG_FINAL to overflow maxrank here - needs to be handled in Item::CheckArtifactUnlock (will refund artifact power)
377 if (artifactPower->Flags & ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER && uint32(artifactPower->Tier) < info.Artifact->ArtifactTierId)
378 maxRank += info.Artifact->ArtifactTierId - artifactPower->Tier;
379
380 if (artifactPowerData.PurchasedRank > maxRank)
381 artifactPowerData.PurchasedRank = maxRank;
382
383 artifactPowerData.CurrentRankWithBonus = (artifactPower->Flags & ARTIFACT_POWER_FLAG_FIRST) == ARTIFACT_POWER_FLAG_FIRST ? 1 : 0;
384
385 info.Artifact->ArtifactPowers.push_back(artifactPowerData);
386 }
387
388 } while (artifactResult->NextRow());
389 }
390
391 // 0 1 2 3
392 // SELECT iz.itemGuid, iz.xp, iz.level, iz.knowledgeLevel,
393 // 4 5 6 7 8
394 // iz.selectedAzeriteEssences1specId, iz.selectedAzeriteEssences1azeriteEssenceId1, iz.selectedAzeriteEssences1azeriteEssenceId2, iz.selectedAzeriteEssences1azeriteEssenceId3, iz.selectedAzeriteEssences1azeriteEssenceId4,
395 // 9 10 11 12 13
396 // iz.selectedAzeriteEssences2specId, iz.selectedAzeriteEssences2azeriteEssenceId1, iz.selectedAzeriteEssences2azeriteEssenceId2, iz.selectedAzeriteEssences2azeriteEssenceId3, iz.selectedAzeriteEssences2azeriteEssenceId4,
397 // 14 15 16 17 18
398 // iz.selectedAzeriteEssences3specId, iz.selectedAzeriteEssences3azeriteEssenceId1, iz.selectedAzeriteEssences3azeriteEssenceId2, iz.selectedAzeriteEssences3azeriteEssenceId3, iz.selectedAzeriteEssences3azeriteEssenceId4,
399 // 19 20 21 22 23
400 // iz.selectedAzeriteEssences4specId, iz.selectedAzeriteEssences4azeriteEssenceId1, iz.selectedAzeriteEssences4azeriteEssenceId2, iz.selectedAzeriteEssences4azeriteEssenceId3, iz.selectedAzeriteEssences4azeriteEssenceId4
401 // FROM item_instance_azerite iz INNER JOIN ...
402 if (azeriteItemResult)
403 {
404 do
405 {
406 Field* fields = azeriteItemResult->Fetch();
407 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
408 if (!info.AzeriteItem)
409 info.AzeriteItem.emplace();
410 info.AzeriteItem->Xp = fields[1].GetUInt64();
411 info.AzeriteItem->Level = fields[2].GetUInt32();
412 info.AzeriteItem->KnowledgeLevel = fields[3].GetUInt32();
413 for (std::size_t i = 0; i < info.AzeriteItem->SelectedAzeriteEssences.size(); ++i)
414 {
415 uint32 specializationId = fields[4 + i * 4].GetUInt32();
416 if (!sChrSpecializationStore.LookupEntry(specializationId))
417 continue;
418
419 info.AzeriteItem->SelectedAzeriteEssences[i].SpecializationId = specializationId;
420 for (std::size_t j = 0; j < MAX_AZERITE_ESSENCE_SLOT; ++j)
421 {
422 AzeriteEssenceEntry const* azeriteEssence = sAzeriteEssenceStore.LookupEntry(fields[5 + i * 5 + j].GetUInt32());
423 if (!azeriteEssence || !sDB2Manager.IsSpecSetMember(azeriteEssence->SpecSetID, specializationId))
424 continue;
425
426 info.AzeriteItem->SelectedAzeriteEssences[i].AzeriteEssenceId[j] = azeriteEssence->ID;
427 }
428 }
429
430 } while (azeriteItemResult->NextRow());
431 }
432
433 // 0 1
434 // SELECT iamp.itemGuid, iamp.azeriteItemMilestonePowerId FROM item_instance_azerite_milestone_power iamp INNER JOIN ...
435 if (azeriteItemMilestonePowersResult)
436 {
437 do
438 {
439 Field* fields = azeriteItemMilestonePowersResult->Fetch();
440 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
441 if (!info.AzeriteItem)
442 info.AzeriteItem.emplace();
443 info.AzeriteItem->AzeriteItemMilestonePowers.push_back(fields[1].GetUInt32());
444 }
445 while (azeriteItemMilestonePowersResult->NextRow());
446 }
447
448 // 0 1 2
449 // SELECT iaue.itemGuid, iaue.azeriteEssenceId, iaue.`rank` FROM item_instance_azerite_unlocked_essence iaue INNER JOIN ...
450 if (azeriteItemUnlockedEssencesResult)
451 {
452 do
453 {
454 Field* fields = azeriteItemUnlockedEssencesResult->Fetch();
455 if (AzeriteEssencePowerEntry const* azeriteEssencePower = sDB2Manager.GetAzeriteEssencePower(fields[1].GetUInt32(), fields[2].GetUInt32()))
456 {
457 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
458 if (!info.AzeriteItem)
459 info.AzeriteItem.emplace();
460
461 info.AzeriteItem->UnlockedAzeriteEssences.push_back(azeriteEssencePower);
462 }
463 }
464 while (azeriteItemUnlockedEssencesResult->NextRow());
465 }
466
467 // 0 1 2 3 4 5
468 // SELECT iae.itemGuid, iae.azeritePowerId1, iae.azeritePowerId2, iae.azeritePowerId3, iae.azeritePowerId4, iae.azeritePowerId5 FROM item_instance_azerite_empowered iae INNER JOIN ...
469 if (azeriteEmpoweredItemResult)
470 {
471 do
472 {
473 Field* fields = azeriteEmpoweredItemResult->Fetch();
474 ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()];
475 if (!info.AzeriteEmpoweredItem)
476 info.AzeriteEmpoweredItem.emplace();
477
478 for (uint32 i = 0; i < MAX_AZERITE_EMPOWERED_TIER; ++i)
479 if (sAzeritePowerStore.LookupEntry(fields[1 + i].GetInt32()))
480 info.AzeriteEmpoweredItem->SelectedAzeritePowers[i] = fields[1 + i].GetInt32();
481
482 } while (azeriteEmpoweredItemResult->NextRow());
483 }
484}
485
487{
489
491
492 m_slot = 0;
494 uQueuePos = -1;
495 m_container = nullptr;
496 m_lootGenerated = false;
497 mb_in_trade = false;
498
499 m_paidMoney = 0;
501
503 m_gemScalingLevels = { };
504
505 memset(&_bonusData, 0, sizeof(_bonusData));
506}
507
508Item::~Item() = default;
509
510bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, ItemContext context, Player const* owner)
511{
512 _Create(ObjectGuid::Create<HighGuid::Item>(guidlow));
513
514 SetEntry(itemId);
515 SetObjectScale(1.0f);
516
517 if (owner)
518 {
519 SetOwnerGUID(owner->GetGUID());
520 SetContainedIn(owner->GetGUID());
521 }
522
523 ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemId);
524 if (!itemProto)
525 return false;
526
527 _bonusData.Initialize(itemProto);
528 SetCount(1);
530 SetDurability(itemProto->MaxDurability);
531
532 for (ItemEffectEntry const* effect : GetEffects())
533 SetSpellCharges(effect, effect->Charges);
534
535 SetExpiration(itemProto->GetDuration());
538 SetContext(context);
539
540 if (itemProto->GetArtifactID())
541 {
542 InitArtifactPowers(itemProto->GetArtifactID(), 0);
543 for (ArtifactAppearanceEntry const* artifactAppearance : sArtifactAppearanceStore)
544 {
545 if (ArtifactAppearanceSetEntry const* artifactAppearanceSet = sArtifactAppearanceSetStore.LookupEntry(artifactAppearance->ArtifactAppearanceSetID))
546 {
547 if (itemProto->GetArtifactID() != artifactAppearanceSet->ArtifactID)
548 continue;
549
550 if (!owner || !ConditionMgr::IsPlayerMeetingCondition(owner, artifactAppearance->UnlockPlayerConditionID))
551 continue;
552
553 SetModifier(ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID, artifactAppearance->ID);
554 SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID);
555 break;
556 }
557 }
558
559 CheckArtifactRelicSlotUnlock(owner ? owner : GetOwner());
560 }
561
562 return true;
563}
564
566{
567 ItemTemplate const* itemTemplate = GetTemplate();
569 return Trinity::StringFormat("{} {}", itemTemplate->GetName(locale), suffix->Description[locale]);
570
571 return itemTemplate->GetName(locale);
572}
573
574// Returns true if Item is a bag AND it is not empty.
575// Returns false if Item is not a bag OR it is an empty bag.
577{
578 if (Bag const* bag = ToBag())
579 return !bag->IsEmpty();
580 return false;
581}
582
584{
585 uint32 duration = m_itemData->Expiration;
586 if (!duration)
587 return;
588
589 TC_LOG_DEBUG("entities.player.items", "Item::UpdateDuration Item (Entry: {} Duration {} Diff {})", GetEntry(), duration, diff);
590
591 if (duration <= diff)
592 {
593 sScriptMgr->OnItemExpire(owner, GetTemplate());
594 owner->DestroyItem(GetBagSlot(), GetSlot(), true);
595 return;
596 }
597
598 SetExpiration(duration - diff);
599 SetState(ITEM_CHANGED, owner); // save new time in database
600}
601
602static uint32 FindSpellChargesSlot(BonusData const& bonusData, ItemEffectEntry const* effect)
603{
604 static constexpr uint32 MaxSpellChargesSlot = UF::size<decltype(UF::ItemData::SpellCharges)>();
605
606 if (!effect)
607 {
608 // return fist effect that has charges
609 for (uint32 i = 0; i < bonusData.EffectCount && i < MaxSpellChargesSlot; ++i)
610 if (bonusData.Effects[i] && bonusData.Effects[i]->Charges != 0)
611 return i;
612
613 return MaxSpellChargesSlot;
614 }
615
616 for (uint32 i = 0; i < bonusData.EffectCount && i < MaxSpellChargesSlot; ++i)
617 if (bonusData.Effects[i] == effect)
618 return i;
619
620 return MaxSpellChargesSlot;
621}
622
623int32 Item::GetSpellCharges(ItemEffectEntry const* effect /*= nullptr*/) const
624{
625 uint32 slot = FindSpellChargesSlot(_bonusData, effect);
626 if (slot < m_itemData->SpellCharges.size())
627 return m_itemData->SpellCharges[slot];
628
629 return 0;
630}
631
633{
634 uint32 slot = FindSpellChargesSlot(_bonusData, effect);
635 if (slot < m_itemData->SpellCharges.size())
637}
638
640{
641 bool isInTransaction = bool(trans);
642 if (!isInTransaction)
643 trans = CharacterDatabase.BeginTransaction();
644
645 switch (uState)
646 {
647 case ITEM_NEW:
648 case ITEM_CHANGED:
649 {
650 uint8 index = 0;
652 stmt->setUInt32( index, GetEntry());
653 stmt->setUInt64(++index, GetOwnerGUID().GetCounter());
654 stmt->setUInt64(++index, GetCreator().GetCounter());
655 stmt->setUInt64(++index, GetGiftCreator().GetCounter());
656 stmt->setUInt32(++index, GetCount());
657 stmt->setUInt32(++index, m_itemData->Expiration);
658
659 std::ostringstream ssSpells;
660 for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount; ++i)
661 ssSpells << m_itemData->SpellCharges[i] << ' ';
662 stmt->setString(++index, ssSpells.str());
663
664 stmt->setUInt32(++index, m_itemData->DynamicFlags);
665
666 std::ostringstream ssEnchants;
667 for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
668 {
670 enchantment && !enchantment->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotSaveToDB))
671 {
672 ssEnchants << GetEnchantmentId(EnchantmentSlot(i)) << ' ';
673 ssEnchants << GetEnchantmentDuration(EnchantmentSlot(i)) << ' ';
674 ssEnchants << GetEnchantmentCharges(EnchantmentSlot(i)) << ' ';
675 }
676 else
677 {
678 ssEnchants << "0 0 0 ";
679 }
680 }
681 stmt->setString(++index, ssEnchants.str());
682
683 stmt->setUInt32(++index, m_randomBonusListId);
684 stmt->setUInt16(++index, m_itemData->Durability);
685 stmt->setUInt32(++index, m_itemData->CreatePlayedTime);
686 stmt->setInt64(++index, m_itemData->CreateTime);
687 stmt->setString(++index, m_text);
692 stmt->setUInt8(++index, uint8(m_itemData->Context));
693
694 std::ostringstream bonusListIDs;
695 for (int32 bonusListID : GetBonusListIDs())
696 bonusListIDs << bonusListID << ' ';
697 stmt->setString(++index, bonusListIDs.str());
698
699 stmt->setUInt64(++index, GetGUID().GetCounter());
700
701 trans->Append(stmt);
702
703 if ((uState == ITEM_CHANGED) && IsWrapped())
704 {
705 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GIFT_OWNER);
706 stmt->setUInt64(0, GetOwnerGUID().GetCounter());
707 stmt->setUInt64(1, GetGUID().GetCounter());
708 trans->Append(stmt);
709 }
710
711 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
712 stmt->setUInt64(0, GetGUID().GetCounter());
713 trans->Append(stmt);
714
715 if (m_itemData->Gems.size())
716 {
717 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_GEMS);
718 stmt->setUInt64(0, GetGUID().GetCounter());
719 uint32 i = 0;
720 uint32 const gemFields = 4;
721 for (UF::SocketedGem const& gemData : m_itemData->Gems)
722 {
723 if (gemData.ItemID)
724 {
725 stmt->setUInt32(1 + i * gemFields, gemData.ItemID);
726 std::ostringstream gemBonusListIDs;
727 for (uint16 bonusListID : gemData.BonusListIDs)
728 if (bonusListID)
729 gemBonusListIDs << bonusListID << ' ';
730 stmt->setString(2 + i * gemFields, gemBonusListIDs.str());
731 stmt->setUInt8(3 + i * gemFields, gemData.Context);
732 stmt->setUInt32(4 + i * gemFields, m_gemScalingLevels[i]);
733 }
734 else
735 {
736 stmt->setUInt32(1 + i * gemFields, 0);
737 stmt->setString(2 + i * gemFields, ""sv);
738 stmt->setUInt8(3 + i * gemFields, 0);
739 stmt->setUInt32(4 + i * gemFields, 0);
740 }
741 ++i;
742 }
743 for (; i < MAX_GEM_SOCKETS; ++i)
744 {
745 stmt->setUInt32(1 + i * gemFields, 0);
746 stmt->setString(2 + i * gemFields, ""sv);
747 stmt->setUInt8(3 + i * gemFields, 0);
748 stmt->setUInt32(4 + i * gemFields, 0);
749 }
750 trans->Append(stmt);
751 }
752
753 static ItemModifier const transmogMods[18] =
754 {
761
768
775 };
776
777 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
778 stmt->setUInt64(0, GetGUID().GetCounter());
779 trans->Append(stmt);
780
781 if (std::find_if(std::begin(transmogMods), std::end(transmogMods), [this](ItemModifier modifier) { return GetModifier(modifier) != 0; }) != std::end(transmogMods))
782 {
783 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_TRANSMOG);
784 stmt->setUInt64(0, GetGUID().GetCounter());
803 trans->Append(stmt);
804 }
805
806 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
807 stmt->setUInt64(0, GetGUID().GetCounter());
808 trans->Append(stmt);
809
811 stmt->setUInt64(0, GetGUID().GetCounter());
812 trans->Append(stmt);
813
814 if (GetTemplate()->GetArtifactID())
815 {
816 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_ARTIFACT);
817 stmt->setUInt64(0, GetGUID().GetCounter());
818 stmt->setUInt64(1, m_itemData->ArtifactXP);
821 trans->Append(stmt);
822
823 for (UF::ArtifactPower const& artifactPower : m_itemData->ArtifactPowers)
824 {
826 stmt->setUInt64(0, GetGUID().GetCounter());
827 stmt->setUInt32(1, artifactPower.ArtifactPowerID);
828 stmt->setUInt8(2, artifactPower.PurchasedRank);
829 trans->Append(stmt);
830 }
831 }
832
833 static ItemModifier const modifiersTable[] =
834 {
837 };
838
839 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
840 stmt->setUInt64(0, GetGUID().GetCounter());
841 trans->Append(stmt);
842
843 if (std::find_if(std::begin(modifiersTable), std::end(modifiersTable), [this](ItemModifier modifier) { return GetModifier(modifier) != 0; }) != std::end(modifiersTable))
844 {
845 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_INSTANCE_MODIFIERS);
846 stmt->setUInt64(0, GetGUID().GetCounter());
849 trans->Append(stmt);
850 }
851
852 break;
853 }
854 case ITEM_REMOVED:
855 {
857 stmt->setUInt64(0, GetGUID().GetCounter());
858 trans->Append(stmt);
859
860 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
861 stmt->setUInt64(0, GetGUID().GetCounter());
862 trans->Append(stmt);
863
864 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
865 stmt->setUInt64(0, GetGUID().GetCounter());
866 trans->Append(stmt);
867
868 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
869 stmt->setUInt64(0, GetGUID().GetCounter());
870 trans->Append(stmt);
871
873 stmt->setUInt64(0, GetGUID().GetCounter());
874 trans->Append(stmt);
875
876 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
877 stmt->setUInt64(0, GetGUID().GetCounter());
878 trans->Append(stmt);
879
880 if (IsWrapped())
881 {
882 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
883 stmt->setUInt64(0, GetGUID().GetCounter());
884 trans->Append(stmt);
885 }
886
887 if (!isInTransaction)
888 CharacterDatabase.CommitTransaction(trans);
889
890 // Delete the items if this is a container
891 if (m_loot && !m_loot->isLooted())
892 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
893
894 delete this;
895 return;
896 }
897 case ITEM_UNCHANGED:
898 break;
899 }
900
902
903 if (!isInTransaction)
904 CharacterDatabase.CommitTransaction(trans);
905}
906
907bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry)
908{
909 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13
910 // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomBonusListId, durability, playedTime, createTime, text,
911 // 14 15 16 17 18 19
912 // battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, context, bonusListIDs,
913 // 20 21 22 23 24 25
914 // itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4, itemModifiedAppearanceSpec5,
915 // 26 27 28 29 30 31
916 // spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, spellItemEnchantmentSpec5,
917 // 32 33 34
918 // secondaryItemModifiedAppearanceAllSpecs, secondaryItemModifiedAppearanceSpec1, secondaryItemModifiedAppearanceSpec2,
919 // 35 36 37
920 // secondaryItemModifiedAppearanceSpec3, secondaryItemModifiedAppearanceSpec4, secondaryItemModifiedAppearanceSpec5,
921 // 38 39 40 41 42 43 44 45 46 47 48 49
922 // gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3
923 // 50 51
924 // fixedScalingLevel, artifactKnowledgeLevel FROM item_instance
925
926 // create item before any checks for store correct guid
927 // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB
928 _Create(ObjectGuid::Create<HighGuid::Item>(guid));
929
930 // Set entry, MUST be before proto check
931 SetEntry(entry);
932 SetObjectScale(1.0f);
933
934 ItemTemplate const* proto = GetTemplate();
935 if (!proto)
936 {
937 TC_LOG_ERROR("entities.item", "Invalid entry {} for item {}. Refusing to load.", GetEntry(), GetGUID().ToString());
938 return false;
939 }
940
941 _bonusData.Initialize(proto);
942
943 // set owner (not if item is only loaded for gbank/auction/mail
944 if (!ownerGuid.IsEmpty())
945 SetOwnerGUID(ownerGuid);
946
947 uint32 itemFlags = fields[7].GetUInt32();
948 bool need_save = false; // need explicit save data at load fixes
949 if (uint64 creator = fields[2].GetUInt64())
950 {
951 if (!(itemFlags & ITEM_FIELD_FLAG_CHILD))
952 SetCreator(ObjectGuid::Create<HighGuid::Player>(creator));
953 else
954 SetCreator(ObjectGuid::Create<HighGuid::Item>(creator));
955 }
956 if (uint64 giftCreator = fields[3].GetUInt64())
957 SetGiftCreator(ObjectGuid::Create<HighGuid::Player>(giftCreator));
958 SetCount(fields[4].GetUInt32());
959
960 uint32 duration = fields[5].GetUInt32();
961 SetExpiration(duration);
962 // update duration if need, and remove if not need
963 if ((proto->GetDuration() == 0) != (duration == 0))
964 {
965 SetExpiration(proto->GetDuration());
966 need_save = true;
967 }
968
970
971 uint32 durability = fields[10].GetUInt16();
972 SetDurability(durability);
973 // update max durability (and durability) if need
975
976 // do not overwrite durability for wrapped items
977 if (durability > proto->MaxDurability && !IsWrapped())
978 {
980 need_save = true;
981 }
982
983 SetCreatePlayedTime(fields[11].GetUInt32());
984 SetCreateTime(fields[12].GetInt64());
985 SetText(fields[13].GetString());
986
987 SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[14].GetUInt32());
988 SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[15].GetUInt32());
989 SetModifier(ITEM_MODIFIER_BATTLE_PET_LEVEL, fields[16].GetUInt16());
990 SetModifier(ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID, fields[17].GetUInt32());
991
992 SetContext(ItemContext(fields[18].GetUInt8()));
993
994 std::vector<std::string_view> bonusListString = Trinity::Tokenize(fields[19].GetStringView(), ' ', false);
995 std::vector<int32> bonusListIDs;
996 bonusListIDs.reserve(bonusListString.size());
997 for (std::string_view token : bonusListString)
998 if (Optional<int32> bonusListID = Trinity::StringTo<int32>(token))
999 bonusListIDs.push_back(*bonusListID);
1000 SetBonuses(std::move(bonusListIDs));
1001
1002 // load charges after bonuses, they can add more item effects
1003 std::vector<std::string_view> tokens = Trinity::Tokenize(fields[6].GetStringView(), ' ', false);
1004 for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount && i < tokens.size(); ++i)
1005 SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::SpellCharges, i), Trinity::StringTo<int32>(tokens[i]).value_or(0));
1006
1013
1015 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1, fields[27].GetUInt32());
1016 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2, fields[28].GetUInt32());
1017 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3, fields[29].GetUInt32());
1018 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4, fields[30].GetUInt32());
1019 SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5, fields[31].GetUInt32());
1020
1027
1028 uint32 const gemFields = 4;
1030 memset(gemData, 0, sizeof(gemData));
1031 for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i)
1032 {
1033 gemData[i].ItemId = fields[38 + i * gemFields].GetUInt32();
1034 std::vector<std::string_view> gemBonusListIDs = Trinity::Tokenize(fields[39 + i * gemFields].GetStringView(), ' ', false);
1035 uint32 b = 0;
1036 for (std::string_view token : gemBonusListIDs)
1037 if (Optional<uint16> bonusListID = Trinity::StringTo<uint16>(token))
1038 gemData[i].BonusListIDs[b++] = *bonusListID;
1039
1040 gemData[i].Context = fields[40 + i * gemFields].GetUInt8();
1041 if (gemData[i].ItemId)
1042 SetGem(i, &gemData[i], fields[41 + i * gemFields].GetUInt32());
1043 }
1044
1045 SetModifier(ITEM_MODIFIER_TIMEWALKER_LEVEL, fields[50].GetUInt32());
1046 SetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL, fields[51].GetUInt32());
1047
1048 // Enchants must be loaded after all other bonus/scaling data
1049 std::vector<std::string_view> enchantmentTokens = Trinity::Tokenize(fields[8].GetStringView(), ' ', false);
1050 if (enchantmentTokens.size() == MAX_ENCHANTMENT_SLOT * MAX_ENCHANTMENT_OFFSET)
1051 {
1052 for (uint32 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
1053 {
1054 auto enchantmentField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Enchantment, i);
1055 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::ID), Trinity::StringTo<int32>(enchantmentTokens[i * MAX_ENCHANTMENT_OFFSET + 0]).value_or(0));
1056 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Duration), Trinity::StringTo<uint32>(enchantmentTokens[i * MAX_ENCHANTMENT_OFFSET + 1]).value_or(0));
1057 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Charges), Trinity::StringTo<int16>(enchantmentTokens[i * MAX_ENCHANTMENT_OFFSET + 2]).value_or(0));
1058 }
1059 }
1060 m_randomBonusListId = fields[9].GetUInt32();
1061
1062 // Remove bind flag for items vs BIND_NONE set
1063 if (IsSoulBound() && GetBonding() == BIND_NONE)
1064 {
1066 need_save = true;
1067 }
1068
1069 if (need_save) // normal item changed state set not work at loading
1070 {
1071 uint8 index = 0;
1073 stmt->setUInt32(index++, m_itemData->Expiration);
1074 stmt->setUInt32(index++, m_itemData->DynamicFlags);
1075 stmt->setUInt32(index++, m_itemData->Durability);
1076 stmt->setUInt64(index++, guid);
1077 CharacterDatabase.Execute(stmt);
1078 }
1079
1080 return true;
1081}
1082
1084{
1085 if (GetTemplate()->GetArtifactID() && addionalData->Artifact)
1086 LoadArtifactData(owner, addionalData->Artifact->Xp, addionalData->Artifact->ArtifactAppearanceId,
1087 addionalData->Artifact->ArtifactTierId, addionalData->Artifact->ArtifactPowers);
1088
1089 if (addionalData->AzeriteItem)
1090 if (AzeriteItem* azeriteItem = ToAzeriteItem())
1091 azeriteItem->LoadAzeriteItemData(owner, *addionalData->AzeriteItem);
1092
1093 if (addionalData->AzeriteEmpoweredItem)
1094 if (AzeriteEmpoweredItem* azeriteEmpoweredItem = ToAzeriteEmpoweredItem())
1095 azeriteEmpoweredItem->LoadAzeriteEmpoweredItemData(owner, *addionalData->AzeriteEmpoweredItem);
1096}
1097
1098void Item::LoadArtifactData(Player const* owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector<ArtifactPowerData>& powers)
1099{
1100 for (uint8 i = 0; i <= artifactTier; ++i)
1101 InitArtifactPowers(GetTemplate()->GetArtifactID(), i);
1102
1106
1107 if (ArtifactAppearanceEntry const* artifactAppearance = sArtifactAppearanceStore.LookupEntry(artifactAppearanceId))
1108 SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID);
1109
1110 uint8 totalPurchasedRanks = 0;
1111 for (ArtifactPowerData& power : powers)
1112 {
1113 power.CurrentRankWithBonus += power.PurchasedRank;
1114 totalPurchasedRanks += power.PurchasedRank;
1115
1116 ArtifactPowerEntry const* artifactPower = sArtifactPowerStore.AssertEntry(power.ArtifactPowerId);
1118 {
1120 {
1121 for (uint32 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
1122 {
1123 switch (enchant->Effect[i])
1124 {
1126 if (uint32(artifactPower->Label) == enchant->EffectArg[i])
1127 power.CurrentRankWithBonus += enchant->EffectPointsMin[i];
1128 break;
1130 if (artifactPower->ID == enchant->EffectArg[i])
1131 power.CurrentRankWithBonus += enchant->EffectPointsMin[i];
1132 break;
1135 {
1136 ArtifactPowerPickerEntry const* artifactPowerPicker = sArtifactPowerPickerStore.LookupEntry(enchant->EffectArg[i]);
1137 if (artifactPowerPicker && owner && ConditionMgr::IsPlayerMeetingCondition(owner, artifactPowerPicker->PlayerConditionID))
1138 if (artifactPower->Label == _bonusData.GemRelicType[e - SOCK_ENCHANTMENT_SLOT])
1139 power.CurrentRankWithBonus += enchant->EffectPointsMin[i];
1140 }
1141 break;
1142 default:
1143 break;
1144 }
1145 }
1146 }
1147 }
1148
1149 SetArtifactPower(power.ArtifactPowerId, power.PurchasedRank, power.CurrentRankWithBonus);
1150 }
1151
1152 for (ArtifactPowerData& power : powers)
1153 {
1154 ArtifactPowerEntry const* scaledArtifactPowerEntry = sArtifactPowerStore.AssertEntry(power.ArtifactPowerId);
1155 if (!(scaledArtifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS))
1156 continue;
1157
1158 SetArtifactPower(power.ArtifactPowerId, power.PurchasedRank, totalPurchasedRanks + 1);
1159 }
1160
1162}
1163
1165{
1166 if (!owner)
1167 return;
1168
1169 uint8 artifactId = GetTemplate()->GetArtifactID();
1170 if (!artifactId)
1171 return;
1172
1173 for (ArtifactUnlockEntry const* artifactUnlock : sArtifactUnlockStore)
1174 if (artifactUnlock->ArtifactID == artifactId)
1175 if (owner->MeetPlayerCondition(artifactUnlock->PlayerConditionID))
1176 AddBonuses(artifactUnlock->ItemBonusListID);
1177}
1178
1179/*static*/
1181{
1183 stmt->setUInt64(0, itemGuid);
1184 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1185
1186 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
1187 stmt->setUInt64(0, itemGuid);
1188 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1189
1190 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
1191 stmt->setUInt64(0, itemGuid);
1192 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1193
1194 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
1195 stmt->setUInt64(0, itemGuid);
1196 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1197
1198 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS);
1199 stmt->setUInt64(0, itemGuid);
1200 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1201
1202 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
1203 stmt->setUInt64(0, itemGuid);
1204 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1205
1206 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
1207 stmt->setUInt64(0, itemGuid);
1208 CharacterDatabase.ExecuteOrAppend(trans, stmt);
1209}
1210
1212{
1213 DeleteFromDB(trans, GetGUID().GetCounter());
1214
1215 // Delete the items if this is a container
1216 if (m_loot && !m_loot->isLooted())
1217 sLootItemStorage->RemoveStoredLootForContainer(GetGUID().GetCounter());
1218}
1219
1220/*static*/
1222{
1224 stmt->setUInt64(0, itemGuid);
1225 trans->Append(stmt);
1226}
1227
1232
1234{
1235 return sObjectMgr->GetItemTemplate(GetEntry());
1236}
1237
1242
1243// Just a "legacy shortcut" for proto->GetSkill()
1245{
1246 ItemTemplate const* proto = GetTemplate();
1247 return proto->GetSkill();
1248}
1249
1251{
1252 if (!bonusListId)
1253 return;
1254
1255 AddBonuses(bonusListId);
1256}
1257
1259{
1260 if (uState == ITEM_NEW && state == ITEM_REMOVED)
1261 {
1262 // pretend the item never existed
1263 if (forplayer)
1264 {
1265 RemoveItemFromUpdateQueueOf(this, forplayer);
1266 forplayer->DeleteRefundReference(GetGUID());
1267 }
1268 delete this;
1269 return;
1270 }
1271 if (state != ITEM_UNCHANGED)
1272 {
1273 // new items must stay in new state until saved
1274 if (uState != ITEM_NEW)
1275 uState = state;
1276
1277 if (forplayer)
1278 AddItemToUpdateQueueOf(this, forplayer);
1279 }
1280 else
1281 {
1282 // unset in queue
1283 // the item must be removed from the queue manually
1284 uQueuePos = -1;
1286 }
1287}
1288
1290{
1291 if (item->IsInUpdateQueue())
1292 return;
1293
1294 ASSERT(player != nullptr);
1295
1296 if (player->GetGUID() != item->GetOwnerGUID())
1297 {
1298 TC_LOG_DEBUG("entities.player.items", "AddItemToUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
1299 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
1300 return;
1301 }
1302
1303 if (player->m_itemUpdateQueueBlocked)
1304 return;
1305
1306 player->m_itemUpdateQueue.push_back(item);
1307 item->uQueuePos = player->m_itemUpdateQueue.size() - 1;
1308}
1309
1311{
1312 if (!item->IsInUpdateQueue())
1313 return;
1314
1315 ASSERT(player != nullptr);
1316
1317 if (player->GetGUID() != item->GetOwnerGUID())
1318 {
1319 TC_LOG_DEBUG("entities.player.items", "RemoveItemFromUpdateQueueOf - Owner's guid ({}) and player's guid ({}) don't match!",
1320 item->GetOwnerGUID().ToString(), player->GetGUID().ToString());
1321 return;
1322 }
1323
1324 if (player->m_itemUpdateQueueBlocked)
1325 return;
1326
1327 player->m_itemUpdateQueue[item->uQueuePos] = nullptr;
1328 item->uQueuePos = -1;
1329}
1330
1335
1337{
1338 return !IsInBag() && (m_slot < EQUIPMENT_SLOT_END
1340}
1341
1342bool Item::CanBeTraded(bool mail, bool trade) const
1343{
1344 if (m_lootGenerated)
1345 return false;
1346
1347 if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!IsBOPTradeable() || !trade)))
1348 return false;
1349
1350 if (IsBag() && (Player::IsBagPos(GetPos()) || !ToBag()->IsEmpty()))
1351 return false;
1352
1353 if (Player* owner = GetOwner())
1354 {
1355 if (owner->CanUnequipItem(GetPos(), false) != EQUIP_ERR_OK)
1356 return false;
1357 if (owner->GetLootGUID() == GetGUID())
1358 return false;
1359 }
1360
1361 if (IsBoundByEnchant())
1362 return false;
1363
1364 return true;
1365}
1366
1368{
1370
1371 if (Player* player = GetOwner())
1372 {
1373 if (TradeData* tradeData = player->GetTradeData())
1374 {
1375 TradeSlots slot = tradeData->GetTradeSlotForItem(GetGUID());
1376
1377 if (slot != TRADE_SLOT_INVALID)
1378 tradeData->SetItem(slot, this, true);
1379 }
1380 }
1381}
1382
1383uint64 Item::CalculateDurabilityRepairCost(float discount, bool useRateConfig /*= true*/) const
1384{
1385 uint32 maxDurability = m_itemData->MaxDurability;
1386 if (!maxDurability)
1387 return 0;
1388
1389 uint32 curDurability = m_itemData->Durability;
1390 ASSERT(maxDurability >= curDurability);
1391
1392 uint32 lostDurability = maxDurability - curDurability;
1393 if (!lostDurability)
1394 return 0;
1395
1396 ItemTemplate const* itemTemplate = GetTemplate();
1397
1398 DurabilityCostsEntry const* durabilityCost = sDurabilityCostsStore.LookupEntry(GetItemLevel(GetOwner()));
1399 if (!durabilityCost)
1400 return 0;
1401
1402 uint32 durabilityQualityEntryId = (GetQuality() + 1) * 2;
1403 DurabilityQualityEntry const* durabilityQualityEntry = sDurabilityQualityStore.LookupEntry(durabilityQualityEntryId);
1404 if (!durabilityQualityEntry)
1405 return 0;
1406
1407 uint32 dmultiplier = 0;
1408 if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
1409 dmultiplier = durabilityCost->WeaponSubClassCost[itemTemplate->GetSubClass()];
1410 else if (itemTemplate->GetClass() == ITEM_CLASS_ARMOR)
1411 dmultiplier = durabilityCost->ArmorSubClassCost[itemTemplate->GetSubClass()];
1412
1413 uint64 cost = std::round(lostDurability * dmultiplier * durabilityQualityEntry->Data * GetRepairCostMultiplier());
1414 cost = uint64(cost * discount * (useRateConfig ? sWorld->getRate(RATE_REPAIRCOST) : 1));
1415
1416 if (cost == 0) // Fix for ITEM_QUALITY_ARTIFACT
1417 cost = 1;
1418
1419 return cost;
1420}
1421
1422bool Item::HasEnchantRequiredSkill(Player const* player) const
1423{
1424 // Check all enchants for required skill
1425 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
1426 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
1427 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1428 if (enchantEntry->RequiredSkillID && player->GetSkillValue(enchantEntry->RequiredSkillID) < enchantEntry->RequiredSkillRank)
1429 return false;
1430
1431 return true;
1432}
1433
1435{
1436 uint32 level = 0;
1437
1438 // Check all enchants for required level
1439 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
1440 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
1441 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1442 if (enchantEntry->MinLevel > level)
1443 level = enchantEntry->MinLevel;
1444
1445 return level;
1446}
1447
1449{
1450 // Check all enchants for soulbound
1451 for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
1452 if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
1453 if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
1454 if (enchantEntry->GetFlags().HasFlag(SpellItemEnchantmentFlags::Soulbound))
1455 return true;
1456
1457 return false;
1458}
1459
1461{
1462 // not allow merge looting currently items
1463 if (m_lootGenerated)
1464 return EQUIP_ERR_LOOT_GONE;
1465
1466 // check item type
1467 if (GetEntry() != proto->GetId())
1468 return EQUIP_ERR_CANT_STACK;
1469
1470 // check free space (full stacks can't be target of merge
1471 if (GetCount() >= proto->GetMaxStackSize())
1472 return EQUIP_ERR_CANT_STACK;
1473
1474 return EQUIP_ERR_OK;
1475}
1476
1477bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const
1478{
1479 ItemTemplate const* proto = GetTemplate();
1480
1482 if (spellInfo->EquippedItemClass != -1) // -1 == any item class
1483 {
1484 if (isEnchantSpell && proto->HasFlag(ITEM_FLAG3_CAN_STORE_ENCHANTS))
1485 return true;
1486
1487 if (spellInfo->EquippedItemClass != int32(proto->GetClass()))
1488 return false; // wrong item class
1489
1490 if (spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass
1491 {
1492 if ((spellInfo->EquippedItemSubClassMask & (1 << proto->GetSubClass())) == 0)
1493 return false; // subclass not present in mask
1494 }
1495 }
1496
1497 if (isEnchantSpell && spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type
1498 {
1499 // Special case - accept weapon type for main and offhand requirements
1500 if (proto->GetInventoryType() == INVTYPE_WEAPON &&
1503 return true;
1504 else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->GetInventoryType())) == 0)
1505 return false; // inventory type not present in mask
1506 }
1507
1508 return true;
1509}
1510
1511void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster /*= ObjectGuid::Empty*/)
1512{
1513 // Better lost small time at check in comparison lost time at item save to DB.
1514 if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
1515 return;
1516
1517 Player* owner = GetOwner();
1519 {
1520 if (SpellItemEnchantmentEntry const* oldEnchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(slot)))
1521 if (!oldEnchant->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotLog))
1522 owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), ObjectGuid::Empty, GetGUID(), GetEntry(), oldEnchant->ID, slot);
1523
1524 if (SpellItemEnchantmentEntry const* newEnchant = sSpellItemEnchantmentStore.LookupEntry(id))
1525 if (!newEnchant->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotLog))
1526 owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, slot);
1527 }
1528
1529 ApplyArtifactPowerEnchantmentBonuses(slot, GetEnchantmentId(slot), false, owner);
1530 ApplyArtifactPowerEnchantmentBonuses(slot, id, true, owner);
1531
1532 auto enchantmentField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Enchantment, slot);
1533 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::ID), id);
1534 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Duration), duration);
1535 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Charges), charges);
1536 SetState(ITEM_CHANGED, owner);
1537}
1538
1540{
1541 if (GetEnchantmentDuration(slot) == duration)
1542 return;
1543
1545 SetState(ITEM_CHANGED, owner);
1546 // Cannot use GetOwner() here, has to be passed as an argument to avoid freeze due to hashtable locking
1547}
1548
1550{
1551 if (GetEnchantmentCharges(slot) == charges)
1552 return;
1553
1556}
1557
1559{
1560 if (!GetEnchantmentId(slot))
1561 return;
1562
1563 auto enchantmentField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Enchantment, slot);
1564 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::ID), 0);
1565 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Duration), 0);
1566 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Charges), 0);
1567 SetUpdateFieldValue(enchantmentField.ModifyValue(&UF::ItemEnchantment::Inactive), 0);
1569}
1570
1572{
1573 ASSERT(slot < MAX_GEM_SOCKETS);
1574 return slot < m_itemData->Gems.size() ? &m_itemData->Gems[slot] : nullptr;
1575}
1576
1577void Item::SetGem(uint16 slot, ItemDynamicFieldGems const* gem, uint32 gemScalingLevel)
1578{
1579 ASSERT(slot < MAX_GEM_SOCKETS);
1580 m_gemScalingLevels[slot] = gemScalingLevel;
1581 _bonusData.GemItemLevelBonus[slot] = 0;
1582 if (ItemTemplate const* gemTemplate = sObjectMgr->GetItemTemplate(gem->ItemId))
1583 {
1584 if (GemPropertiesEntry const* gemProperties = sGemPropertiesStore.LookupEntry(gemTemplate->GetGemProperties()))
1585 {
1586 if (SpellItemEnchantmentEntry const* gemEnchant = sSpellItemEnchantmentStore.LookupEntry(gemProperties->EnchantId))
1587 {
1588 BonusData gemBonus;
1589 gemBonus.Initialize(gemTemplate);
1590 for (uint16 bonusListId : gem->BonusListIDs)
1591 gemBonus.AddBonusList(bonusListId);
1592
1593 uint32 gemBaseItemLevel = gemBonus.ItemLevel;
1594 if (gemBonus.PlayerLevelToItemLevelCurveId)
1595 if (uint32 scaledIlvl = uint32(sDB2Manager.GetCurveValueAt(gemBonus.PlayerLevelToItemLevelCurveId, gemScalingLevel)))
1596 gemBaseItemLevel = scaledIlvl;
1597
1598 _bonusData.GemRelicType[slot] = gemBonus.RelicType;
1599
1600 for (uint32 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
1601 {
1602 switch (gemEnchant->Effect[i])
1603 {
1605 {
1606 for (ItemBonusEntry const* itemBonus : ItemBonusMgr::GetItemBonuses(gemEnchant->EffectArg[i]))
1607 if (itemBonus->Type == ITEM_BONUS_ITEM_LEVEL)
1608 _bonusData.GemItemLevelBonus[slot] += itemBonus->Value[0];
1609 break;
1610 }
1612 {
1614 for (ItemBonusEntry const* itemBonus : ItemBonusMgr::GetItemBonuses(bonusListId))
1615 if (itemBonus->Type == ITEM_BONUS_ITEM_LEVEL)
1616 _bonusData.GemItemLevelBonus[slot] += itemBonus->Value[0];
1617 break;
1618 }
1619 default:
1620 break;
1621 }
1622 }
1623 }
1624 }
1625 }
1626
1627 auto gemField = m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::Gems, slot);
1628 SetUpdateFieldValue(gemField.ModifyValue(&UF::SocketedGem::ItemID), gem->ItemId);
1629 SetUpdateFieldValue(gemField.ModifyValue(&UF::SocketedGem::Context), gem->Context);
1630 for (uint32 i = 0; i < 16; ++i)
1631 SetUpdateFieldValue(gemField.ModifyValue(&UF::SocketedGem::BonusListIDs, i), gem->BonusListIDs[i]);
1632}
1633
1635{
1636 for (uint32 gemSlot = 0; gemSlot < MAX_ITEM_PROTO_SOCKETS; ++gemSlot)
1637 {
1639
1640 if (!SocketColor) // no socket slot
1641 continue;
1642
1643 if (gemSlot >= m_itemData->Gems.size()) // no gems on this socket
1644 return false;
1645
1646 uint8 GemColor = 0;
1647
1648 uint32 gemid = m_itemData->Gems[gemSlot].ItemID;
1649 if (gemid)
1650 {
1651 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemid);
1652 if (gemProto)
1653 {
1654 GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GetGemProperties());
1655 if (gemProperty)
1656 GemColor = gemProperty->Type;
1657 }
1658 }
1659
1660 if (!(GemColor & SocketColorToGemTypeMask[SocketColor])) // bad gem color on this socket
1661 return false;
1662 }
1663 return true;
1664}
1665
1667{
1668 return uint8(std::count_if(m_itemData->Gems.begin(), m_itemData->Gems.end(), [GemID](UF::SocketedGem const& gemData)
1669 {
1670 return gemData.ItemID == int32(GemID);
1671 }));
1672}
1673
1675{
1676 return uint8(std::count_if(m_itemData->Gems.begin(), m_itemData->Gems.end(), [limitCategory](UF::SocketedGem const& gemData)
1677 {
1678 ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemData.ItemID);
1679 if (!gemProto)
1680 return false;
1681
1682 BonusData gemBonus;
1683 gemBonus.Initialize(gemProto);
1684
1685 for (uint16 bonusListID : gemData.BonusListIDs)
1686 gemBonus.AddBonusList(bonusListID);
1687
1688 return gemBonus.LimitCategory == limitCategory;
1689 }));
1690}
1691
1692bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
1693{
1694 ItemTemplate const* proto = GetTemplate();
1695 return proto && ((proto->GetMap() && proto->GetMap() != cur_mapId) ||
1696 ((proto->GetArea(0) && proto->GetArea(0) != cur_zoneId) && (proto->GetArea(1) && proto->GetArea(1) != cur_zoneId)));
1697}
1698
1700{
1702 socketGems.Item = GetGUID();
1703 GetOwner()->SendDirectMessage(socketGems.Write());
1704}
1705
1706// Though the client has the information in the item's data field,
1707// we have to send SMSG_ITEM_TIME_UPDATE to display the remaining
1708// time.
1710{
1711 uint32 duration = m_itemData->Expiration;
1712 if (!duration)
1713 return;
1714
1716 itemTimeUpdate.ItemGuid = GetGUID();
1717 itemTimeUpdate.DurationLeft = duration;
1718 owner->SendDirectMessage(itemTimeUpdate.Write());
1719}
1720
1721Item* Item::CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const* player /*= nullptr*/, bool addDefaultBonuses /*= true*/)
1722{
1723 if (count < 1)
1724 return nullptr; //don't create item at zero count
1725
1726 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry);
1727 if (proto)
1728 {
1729 if (count > proto->GetMaxStackSize())
1730 count = proto->GetMaxStackSize();
1731
1732 ASSERT_NODEBUGINFO(count != 0, "proto->Stackable == 0 but checked at loading already");
1733
1734 Item* item = NewItemOrBag(proto);
1735 if (item->Create(sObjectMgr->GetGenerator<HighGuid::Item>().Generate(), itemEntry, context, player))
1736 {
1737 item->SetCount(count);
1738 if (addDefaultBonuses)
1739 item->SetBonuses(ItemBonusMgr::GetBonusListsForItem(itemEntry, context));
1740
1741 return item;
1742 }
1743 else
1744 delete item;
1745 }
1746 else
1747 ABORT();
1748 return nullptr;
1749}
1750
1751Item* Item::CloneItem(uint32 count, Player const* player /*= nullptr*/) const
1752{
1753 Item* newItem = CreateItem(GetEntry(), count, GetContext(), player, false);
1754 if (!newItem)
1755 return nullptr;
1756
1757 newItem->SetCreator(GetCreator());
1758 newItem->SetGiftCreator(GetGiftCreator());
1760 newItem->SetExpiration(m_itemData->Expiration);
1761 newItem->SetBonuses(m_itemData->ItemBonusKey->BonusListIDs);
1763 // player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
1764 if (player)
1766 return newItem;
1767}
1768
1769bool Item::IsBindedNotWith(Player const* player) const
1770{
1771 // not binded item
1772 if (!IsSoulBound())
1773 return false;
1774
1775 // own item
1776 if (GetOwnerGUID() == player->GetGUID())
1777 return false;
1778
1779 if (IsBOPTradeable())
1780 if (allowedGUIDs.find(player->GetGUID()) != allowedGUIDs.end())
1781 return false;
1782
1783 // BOA item case
1784 if (IsBoundAccountWide())
1785 return false;
1786
1787 return true;
1788}
1789
1791{
1793
1794 if (Player* owner = GetOwner())
1795 BuildFieldsUpdate(owner, data_map);
1796 ClearUpdateMask(false);
1797}
1798
1800{
1801 if (target->GetGUID() == GetOwnerGUID())
1803
1805}
1806
1808{
1809 m_objectData->WriteCreate(flags, data, target, this);
1810 m_itemData->WriteCreate(flags, data, target, this);
1811}
1812
1814{
1816
1818 m_objectData->WriteUpdate(flags, data, target, this);
1819
1821 m_itemData->WriteUpdate(flags, data, target, this);
1822}
1823
1825{
1827 valuesMask.Set(TYPEID_ITEM);
1828
1829 data << uint32(valuesMask.GetBlock(0));
1830
1831 UF::ItemData::Mask mask;
1833 m_itemData->WriteUpdate(mask, data, target, this, true);
1834}
1835
1837 UF::ItemData::Mask const& requestedItemMask, Player const* target, bool ignoreNestedChangesMask) const
1838{
1841 if (requestedObjectMask.IsAnySet())
1842 valuesMask.Set(TYPEID_OBJECT);
1843
1844 UF::ItemData::Mask itemMask = requestedItemMask;
1846 if (itemMask.IsAnySet())
1847 valuesMask.Set(TYPEID_ITEM);
1848
1849 ByteBuffer& buffer = PrepareValuesUpdateBuffer(data);
1850 std::size_t sizePos = buffer.wpos();
1851 buffer << uint32(0);
1853 buffer << uint32(valuesMask.GetBlock(0));
1854
1855 if (valuesMask[TYPEID_OBJECT])
1856 m_objectData->WriteUpdate(requestedObjectMask, buffer, target, this, ignoreNestedChangesMask);
1857
1858 if (valuesMask[TYPEID_ITEM])
1859 m_itemData->WriteUpdate(itemMask, buffer, target, this, ignoreNestedChangesMask);
1860
1861 buffer.put<uint32>(sizePos, buffer.wpos() - sizePos - 4);
1862
1863 data->AddUpdateBlock();
1864}
1865
1867{
1868 UpdateData udata(player->GetMapId());
1869 WorldPacket packet;
1870
1872
1873 udata.BuildPacket(&packet);
1874 player->SendDirectMessage(&packet);
1875}
1876
1882
1884{
1885 if (Player* owner = GetOwner())
1886 {
1887 owner->GetMap()->AddUpdateObject(this);
1888 return true;
1889 }
1890
1891 return false;
1892}
1893
1895{
1896 if (Player* owner = GetOwner())
1897 owner->GetMap()->RemoveUpdateObject(this);
1898}
1899
1901{
1902 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1903
1905 stmt->setUInt64(0, GetGUID().GetCounter());
1906 trans->Append(stmt);
1907
1908 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEM_REFUND_INSTANCE);
1909 stmt->setUInt64(0, GetGUID().GetCounter());
1910 stmt->setUInt64(1, GetRefundRecipient().GetCounter());
1911 stmt->setUInt64(2, GetPaidMoney());
1913 trans->Append(stmt);
1914
1915 CharacterDatabase.CommitTransaction(trans);
1916}
1917
1919{
1920 if (trans)
1921 {
1923 stmt->setUInt64(0, GetGUID().GetCounter());
1924 (*trans)->Append(stmt);
1925
1926 }
1927}
1928
1929void Item::SetNotRefundable(Player* owner, bool changestate /*= true*/, CharacterDatabaseTransaction* trans /*= nullptr*/, bool addToCollection /*= true*/)
1930{
1931 if (!IsRefundable())
1932 return;
1933
1934 WorldPackets::Item::ItemExpirePurchaseRefund itemExpirePurchaseRefund;
1935 itemExpirePurchaseRefund.ItemGUID = GetGUID();
1936 owner->SendDirectMessage(itemExpirePurchaseRefund.Write());
1937
1939 // Following is not applicable in the trading procedure
1940 if (changestate)
1941 SetState(ITEM_CHANGED, owner);
1942
1944 SetPaidMoney(0);
1947
1949 if (addToCollection)
1951}
1952
1954{
1955 return *m_itemData->CreatePlayedTime;
1956}
1957
1959{
1960 return *m_itemData->CreateTime + 2 * HOUR <= GameTime::GetGameTime();
1961}
1962
1963void Item::SetSoulboundTradeable(GuidSet const& allowedLooters)
1964{
1966 allowedGUIDs = allowedLooters;
1967}
1968
1970{
1972 if (allowedGUIDs.empty())
1973 return;
1974
1975 currentOwner->GetSession()->GetCollectionMgr()->AddItemAppearance(this);
1976 allowedGUIDs.clear();
1977 SetState(ITEM_CHANGED, currentOwner);
1979 stmt->setUInt64(0, GetGUID().GetCounter());
1980 CharacterDatabase.Execute(stmt);
1981}
1982
1984{
1985 // called from owner's update - GetOwner() MUST be valid
1986 if (m_itemData->CreatePlayedTime + 4 * HOUR < GetOwner()->GetTotalPlayedTime())
1987 {
1989 return true; // remove from tradeable list
1990 }
1991
1992 return false;
1993}
1994
1996{
1997 ItemTemplate const* proto = GetTemplate();
1998 if (!proto)
1999 return false;
2000
2001 if (proto->GetClass() != ITEM_CLASS_ARMOR &&
2002 proto->GetClass() != ITEM_CLASS_WEAPON)
2003 return false;
2004
2006 return false;
2007
2009 return false;
2010
2011 return true;
2012}
2013
2015{
2016 -1, // INVTYPE_NON_EQUIP
2017 EQUIPMENT_SLOT_HEAD, // INVTYPE_HEAD
2018 -1, // INVTYPE_NECK
2019 EQUIPMENT_SLOT_SHOULDERS, // INVTYPE_SHOULDERS
2020 EQUIPMENT_SLOT_BODY, // INVTYPE_BODY
2021 EQUIPMENT_SLOT_CHEST, // INVTYPE_CHEST
2022 EQUIPMENT_SLOT_WAIST, // INVTYPE_WAIST
2023 EQUIPMENT_SLOT_LEGS, // INVTYPE_LEGS
2024 EQUIPMENT_SLOT_FEET, // INVTYPE_FEET
2025 EQUIPMENT_SLOT_WRISTS, // INVTYPE_WRISTS
2026 EQUIPMENT_SLOT_HANDS, // INVTYPE_HANDS
2027 -1, // INVTYPE_FINGER
2028 -1, // INVTYPE_TRINKET
2029 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_WEAPON
2030 EQUIPMENT_SLOT_OFFHAND, // INVTYPE_SHIELD
2031 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_RANGED
2032 EQUIPMENT_SLOT_BACK, // INVTYPE_CLOAK
2033 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_2HWEAPON
2034 -1, // INVTYPE_BAG
2035 EQUIPMENT_SLOT_TABARD, // INVTYPE_TABARD
2036 EQUIPMENT_SLOT_CHEST, // INVTYPE_ROBE
2037 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_WEAPONMAINHAND
2038 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_WEAPONOFFHAND
2039 EQUIPMENT_SLOT_OFFHAND, // INVTYPE_HOLDABLE
2040 -1, // INVTYPE_AMMO
2041 -1, // INVTYPE_THROWN
2042 EQUIPMENT_SLOT_MAINHAND, // INVTYPE_RANGEDRIGHT
2043 -1, // INVTYPE_QUIVER
2044 -1, // INVTYPE_RELIC
2045 -1, // INVTYPE_PROFESSION_TOOL
2046 -1, // INVTYPE_PROFESSION_GEAR
2047 -1, // INVTYPE_EQUIPABLE_SPELL_OFFENSIVE
2048 -1, // INVTYPE_EQUIPABLE_SPELL_UTILITY
2049 -1, // INVTYPE_EQUIPABLE_SPELL_DEFENSIVE
2050 -1 // INVTYPE_EQUIPABLE_SPELL_MOBILITY
2051};
2052
2053bool Item::CanTransmogrifyItemWithItem(Item const* item, ItemModifiedAppearanceEntry const* itemModifiedAppearance)
2054{
2055 ItemTemplate const* source = sObjectMgr->GetItemTemplate(itemModifiedAppearance->ItemID); // source
2056 ItemTemplate const* target = item->GetTemplate(); // dest
2057
2058 if (!source || !target)
2059 return false;
2060
2061 if (itemModifiedAppearance == item->GetItemModifiedAppearance())
2062 return false;
2063
2065 return false;
2066
2067 if (source->GetClass() != target->GetClass())
2068 return false;
2069
2070 if (source->GetInventoryType() == INVTYPE_BAG ||
2071 source->GetInventoryType() == INVTYPE_RELIC ||
2072 source->GetInventoryType() == INVTYPE_FINGER ||
2073 source->GetInventoryType() == INVTYPE_TRINKET ||
2074 source->GetInventoryType() == INVTYPE_AMMO ||
2075 source->GetInventoryType() == INVTYPE_QUIVER)
2076 return false;
2077
2078 if (source->GetSubClass() != target->GetSubClass())
2079 {
2080 switch (source->GetClass())
2081 {
2082 case ITEM_CLASS_WEAPON:
2084 return false;
2085 break;
2086 case ITEM_CLASS_ARMOR:
2088 return false;
2089 if (source->GetInventoryType() != target->GetInventoryType())
2091 return false;
2092 break;
2093 default:
2094 return false;
2095 }
2096 }
2097
2098 return true;
2099}
2100
2101uint32 Item::GetBuyPrice(Player const* owner, bool& standardPrice) const
2102{
2103 return Item::GetBuyPrice(GetTemplate(), GetQuality(), GetItemLevel(owner), standardPrice);
2104}
2105
2106uint32 Item::GetBuyPrice(ItemTemplate const* proto, uint32 quality, uint32 itemLevel, bool& standardPrice)
2107{
2108 standardPrice = false;
2109
2111 return proto->GetBuyPrice();
2112
2113 ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(quality + 1);
2114 if (!qualityPrice)
2115 return 0;
2116
2117 ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(itemLevel);
2118 if (!basePrice)
2119 return 0;
2120
2121 float qualityFactor = qualityPrice->Data;
2122 float baseFactor = 0.0f;
2123
2124 uint32 inventoryType = proto->GetInventoryType();
2125
2126 if (inventoryType == INVTYPE_WEAPON ||
2127 inventoryType == INVTYPE_2HWEAPON ||
2128 inventoryType == INVTYPE_WEAPONMAINHAND ||
2129 inventoryType == INVTYPE_WEAPONOFFHAND ||
2130 inventoryType == INVTYPE_RANGED ||
2131 inventoryType == INVTYPE_THROWN ||
2132 inventoryType == INVTYPE_RANGEDRIGHT)
2133 baseFactor = basePrice->Weapon;
2134 else
2135 baseFactor = basePrice->Armor;
2136
2137 if (inventoryType == INVTYPE_ROBE)
2138 inventoryType = INVTYPE_CHEST;
2139
2141 {
2142 inventoryType = INVTYPE_WEAPON;
2143 baseFactor = basePrice->Weapon / 3.0f;
2144 }
2145
2146 float typeFactor = 0.0f;
2147 int8 weapType = -1;
2148
2149 switch (inventoryType)
2150 {
2151 case INVTYPE_HEAD:
2152 case INVTYPE_NECK:
2153 case INVTYPE_SHOULDERS:
2154 case INVTYPE_CHEST:
2155 case INVTYPE_WAIST:
2156 case INVTYPE_LEGS:
2157 case INVTYPE_FEET:
2158 case INVTYPE_WRISTS:
2159 case INVTYPE_HANDS:
2160 case INVTYPE_FINGER:
2161 case INVTYPE_TRINKET:
2162 case INVTYPE_CLOAK:
2163 case INVTYPE_HOLDABLE:
2164 {
2165 ImportPriceArmorEntry const* armorPrice = sImportPriceArmorStore.LookupEntry(inventoryType);
2166 if (!armorPrice)
2167 return 0;
2168
2169 switch (proto->GetSubClass())
2170 {
2173 typeFactor = armorPrice->ClothModifier;
2174 break;
2176 typeFactor = armorPrice->LeatherModifier;
2177 break;
2179 typeFactor = armorPrice->ChainModifier;
2180 break;
2182 typeFactor = armorPrice->PlateModifier;
2183 break;
2184 default:
2185 typeFactor = 1.0f;
2186 break;
2187 }
2188
2189 break;
2190 }
2191 case INVTYPE_SHIELD:
2192 {
2193 ImportPriceShieldEntry const* shieldPrice = sImportPriceShieldStore.LookupEntry(2);
2194 if (!shieldPrice)
2195 return 0;
2196
2197 typeFactor = shieldPrice->Data;
2198 break;
2199 }
2201 weapType = 0;
2202 break;
2204 weapType = 1;
2205 break;
2206 case INVTYPE_WEAPON:
2207 weapType = 2;
2208 break;
2209 case INVTYPE_2HWEAPON:
2210 weapType = 3;
2211 break;
2212 case INVTYPE_RANGED:
2214 case INVTYPE_RELIC:
2215 weapType = 4;
2216 break;
2217 default:
2218 return proto->GetBuyPrice();
2219 }
2220
2221 if (weapType != -1)
2222 {
2223 ImportPriceWeaponEntry const* weaponPrice = sImportPriceWeaponStore.LookupEntry(weapType + 1);
2224 if (!weaponPrice)
2225 return 0;
2226
2227 typeFactor = weaponPrice->Data;
2228 }
2229
2230 standardPrice = true;
2231 return uint32(proto->GetPriceVariance() * typeFactor * baseFactor * qualityFactor * proto->GetPriceRandomValue());
2232}
2233
2234uint32 Item::GetSellPrice(Player const* owner, bool forVendor /*= false*/) const
2235{
2236 ItemTemplate const* itemTemplate = GetTemplate();
2237 int64 price = Item::GetSellPrice(itemTemplate, GetQuality(), GetItemLevel(owner));
2238 if (price && forVendor)
2239 {
2240 std::span<ItemEffectEntry const* const> effects = GetEffects();
2241 auto effectWithCharges = std::ranges::find_if(effects,
2242 [](ItemEffectEntry const* itemEffect) { return itemEffect->SpellID && itemEffect->TriggerType == ITEM_SPELLTRIGGER_ON_USE && itemEffect->Charges < 0; });
2243
2244 if (effectWithCharges != effects.end())
2245 price = price * GetSpellCharges(*effectWithCharges) / (*effectWithCharges)->Charges;
2246
2247 int64 repairCost = CalculateDurabilityRepairCost(1.0f, false);
2248 if (repairCost < price)
2249 price -= repairCost;
2250 else
2251 price = 1;
2252 }
2253
2254 return price;
2255}
2256
2257uint32 Item::GetSellPrice(ItemTemplate const* proto, uint32 quality, uint32 itemLevel)
2258{
2260 return proto->GetSellPrice();
2261 else
2262 {
2263 bool standardPrice;
2264 uint32 cost = Item::GetBuyPrice(proto, quality, itemLevel, standardPrice);
2265
2266 if (standardPrice)
2267 {
2268 if (ItemClassEntry const* classEntry = sDB2Manager.GetItemClassByOldEnum(proto->GetClass()))
2269 {
2270 uint32 buyCount = std::max(proto->GetBuyCount(), 1u);
2271 return cost * classEntry->PriceModifier / buyCount;
2272 }
2273
2274 return 0;
2275 }
2276 else
2277 return proto->GetSellPrice();
2278 }
2279
2280 return 0;
2281}
2282
2284{
2285 ItemTemplate const* itemTemplate = GetTemplate();
2286 int32 minItemLevel = owner->m_unitData->MinItemLevel;
2287 int32 minItemLevelCutoff = owner->m_unitData->MinItemLevelCutoff;
2288 bool pvpBonus = owner->IsUsingPvpItemLevels();
2289 int32 maxItemLevel = pvpBonus && itemTemplate->HasFlag(ITEM_FLAG3_IGNORE_ITEM_LEVEL_CAP_IN_PVP) ? 0 : owner->m_unitData->MaxItemLevel;
2290 uint32 azeriteLevel = 0;
2291 if (AzeriteItem const* azeriteItem = ToAzeriteItem())
2292 azeriteLevel = azeriteItem->GetEffectiveLevel();
2294 minItemLevel, minItemLevelCutoff, maxItemLevel, pvpBonus, azeriteLevel, GetModifier(ITEM_MODIFIER_CONTENT_TUNING_ID));
2295}
2296
2297uint32 Item::GetItemLevel(ItemTemplate const* itemTemplate, BonusData const& bonusData, uint32 level, uint32 fixedLevel,
2298 int32 minItemLevel, int32 minItemLevelCutoff, int32 maxItemLevel, bool pvpBonus, uint32 azeriteLevel, uint32 overrideContentTuningId)
2299{
2300 if (!itemTemplate)
2301 return MIN_ITEM_LEVEL;
2302
2303 int32 itemLevel = bonusData.ItemLevel;
2304 if (AzeriteLevelInfoEntry const* azeriteLevelInfo = sAzeriteLevelInfoStore.LookupEntry(azeriteLevel))
2305 itemLevel = azeriteLevelInfo->ItemLevel;
2306
2307 if (!bonusData.ItemLevelOffsetCurveId)
2308 {
2309 if (bonusData.PlayerLevelToItemLevelCurveId)
2310 {
2311 if (fixedLevel)
2312 level = fixedLevel;
2313 else if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(overrideContentTuningId ? overrideContentTuningId : bonusData.ContentTuningId, {}, true))
2314 level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel);
2315
2316 itemLevel = int32(std::round(sDB2Manager.GetCurveValueAt(bonusData.PlayerLevelToItemLevelCurveId, level)));
2317 }
2318
2319 itemLevel += bonusData.ItemLevelBonus;
2320 }
2321 else
2322 {
2323 uint32 scalingLevel = bonusData.ItemLevelOffsetItemLevel;
2324 if (bonusData.ScalingConfigUsesPlayerLevel)
2325 scalingLevel = fixedLevel ? fixedLevel : level;
2326
2327 if (bonusData.RestrictScalingToContentTuning)
2328 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(overrideContentTuningId, {}, true))
2329 scalingLevel = std::min(std::max(int16(scalingLevel), levels->MinLevel), levels->MaxLevel);
2330
2331 itemLevel = bonusData.ItemLevelOffset + int32(std::round(sDB2Manager.GetCurveValueAt(bonusData.ItemLevelOffsetCurveId, scalingLevel)));
2332 itemLevel += bonusData.ScalingConfigItemLevelBonus;
2333 }
2334
2335 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
2336 itemLevel += bonusData.GemItemLevelBonus[i];
2337
2338 int32 itemLevelBeforeUpgrades = itemLevel;
2339
2340 if (pvpBonus)
2341 {
2342 if (bonusData.PvpItemLevel)
2343 itemLevel = bonusData.PvpItemLevel;
2344
2345 itemLevel += bonusData.PvpItemLevelBonus;
2346 }
2347
2348 if (!bonusData.IgnoreSquish)
2349 {
2350 if (std::shared_ptr<Realm const> currentRealm = sRealmList->GetCurrentRealm())
2351 {
2352 int32 currentBuild = ClientBuild::GetMinorMajorBugfixVersionForBuild(currentRealm->Build);
2353
2354 // apply all squishes between items_squish and server_squish
2355 for (uint32 squishId = bonusData.ItemSquishEraID + 1; squishId < sItemSquishEraStore.GetNumRows(); ++squishId)
2356 {
2357 ItemSquishEraEntry const* squish = sItemSquishEraStore.LookupEntry(squishId);
2358 if (!squish || squish->Flags & 0x1)
2359 continue;
2360
2361 if (squish->Patch > currentBuild)
2362 break;
2363
2364 if (squish->CurveID)
2365 itemLevel = int32(std::round(sDB2Manager.GetCurveValueAt(squish->CurveID, itemLevel)));
2366 }
2367 }
2368 }
2369
2370 if (bonusData.ItemLevelOffsetCurveId)
2371 itemLevel += bonusData.ScalingConfigCraftingQualityItemLevelBonus;
2372
2373 if (itemTemplate->GetInventoryType() != INVTYPE_NON_EQUIP)
2374 {
2375 if (minItemLevel && (!minItemLevelCutoff || itemLevelBeforeUpgrades >= minItemLevelCutoff) && itemLevel < minItemLevel)
2376 itemLevel = minItemLevel;
2377
2378 if (maxItemLevel && itemLevel > maxItemLevel)
2379 itemLevel = maxItemLevel;
2380 }
2381
2382 return std::min(std::max(itemLevel, int32(MIN_ITEM_LEVEL)), int32(MAX_ITEM_LEVEL));
2383}
2384
2385float Item::GetItemStatValue(uint32 index, Player const* owner) const
2386{
2388 switch (GetItemStatType(index))
2389 {
2392 return _bonusData.StatPercentEditor[index];
2393 default:
2394 break;
2395 }
2396
2397 uint32 itemLevel = GetItemLevel(owner);
2398 if (float randomPropPoints = GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate()->GetInventoryType(), GetTemplate()->GetSubClass()))
2399 {
2400 float statValue = float(_bonusData.StatPercentEditor[index] * randomPropPoints) * 0.0001f;
2401 if (GtItemSocketCostPerLevelEntry const* gtCost = sItemSocketCostPerLevelGameTable.GetRow(itemLevel))
2402 statValue -= float(_bonusData.ItemStatSocketCostMultiplier[index] * gtCost->SocketCost);
2403
2404 return statValue;
2405 }
2406
2407 return 0.0f;
2408}
2409
2411{
2413 return {};
2414
2417
2418 // ignore temporary item level scaling (pvp or timewalking)
2420
2421 ItemDisenchantLootEntry const* disenchantLoot = GetBaseDisenchantLoot(GetTemplate(), GetQuality(), itemLevel);
2422 if (!disenchantLoot)
2423 return {};
2424
2425 return disenchantLoot->ID;
2426}
2427
2429{
2431 return {};
2432
2433 // ignore temporary item level scaling (pvp or timewalking)
2435
2436 ItemDisenchantLootEntry const* disenchantLoot = GetBaseDisenchantLoot(GetTemplate(), GetQuality(), itemLevel);
2437 if (!disenchantLoot)
2438 return {};
2439
2440 return disenchantLoot->SkillRequired;
2441}
2442
2444{
2445 if (itemTemplate->HasFlag(ITEM_FLAG_CONJURED) || itemTemplate->HasFlag(ITEM_FLAG_NO_DISENCHANT) || itemTemplate->GetBonding() == BIND_QUEST)
2446 return nullptr;
2447
2448 if (itemTemplate->GetArea(0) || itemTemplate->GetArea(1) || itemTemplate->GetMap() || itemTemplate->GetMaxStackSize() > 1)
2449 return nullptr;
2450
2451 if (!Item::GetSellPrice(itemTemplate, quality, itemLevel) && !sDB2Manager.HasItemCurrencyCost(itemTemplate->GetId()))
2452 return nullptr;
2453
2454 uint32 itemClass = itemTemplate->GetClass();
2455 int8 itemSubClass = itemTemplate->GetSubClass();
2456 uint8 expansion = itemTemplate->GetRequiredExpansion();
2457 for (ItemDisenchantLootEntry const* disenchant : sItemDisenchantLootStore)
2458 {
2459 if (disenchant->Class != itemClass)
2460 continue;
2461
2462 if (disenchant->Subclass >= 0 && itemSubClass)
2463 continue;
2464
2465 if (disenchant->Quality != quality)
2466 continue;
2467
2468 if (disenchant->MinLevel > itemLevel || disenchant->MaxLevel < itemLevel)
2469 continue;
2470
2471 if (disenchant->ExpansionID != -2 && disenchant->ExpansionID != expansion)
2472 continue;
2473
2474 return disenchant;
2475 }
2476
2477 return nullptr;
2478}
2479
2481{
2482 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2483 if (!itemModifiedAppearanceId)
2484 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2485
2486 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId);
2487 if (!itemModifiedAppearance)
2488 itemModifiedAppearance = GetItemModifiedAppearance();
2489
2490 if (itemModifiedAppearance)
2491 if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(itemModifiedAppearance->ItemAppearanceID))
2492 return itemAppearance->ItemDisplayInfoID;
2493
2494 return 0;
2495}
2496
2501
2503{
2504 int32 modifierIndex = m_itemData->Modifiers->Values.FindIndexIf([modifier](UF::ItemMod mod)
2505 {
2506 return mod.Type == modifier;
2507 });
2508
2509 if (modifierIndex != -1)
2510 return m_itemData->Modifiers->Values[modifierIndex].Value;
2511
2512 return 0;
2513}
2514
2516{
2517 int32 modifierIndex = m_itemData->Modifiers->Values.FindIndexIf([modifier](UF::ItemMod mod)
2518 {
2519 return mod.Type == modifier;
2520 });
2521
2522 if (value)
2523 {
2524 if (modifierIndex == -1)
2525 {
2527 .ModifyValue(&UF::ItemData::Modifiers).ModifyValue(&UF::ItemModList::Values));
2528
2529 mod.Value = value;
2530 mod.Type = modifier;
2531 }
2532 else
2534 .ModifyValue(&UF::ItemData::Modifiers)
2535 .ModifyValue(&UF::ItemModList::Values, modifierIndex)
2536 .ModifyValue(&UF::ItemMod::Value), value);
2537 }
2538 else
2539 {
2540 if (modifierIndex == -1)
2541 return;
2542
2544 }
2545}
2546
2548{
2549 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2550 if (!itemModifiedAppearanceId)
2551 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2552
2553 if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
2554 return transmog->ItemID;
2555
2556 return GetEntry();
2557}
2558
2560{
2561 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2562 if (!itemModifiedAppearanceId)
2563 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2564
2565 if (ItemModifiedAppearanceEntry const* transmog = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId))
2566 return transmog->ItemAppearanceModifierID;
2567
2568 return uint16(GetAppearanceModId());
2569}
2570
2572{
2573 uint32 itemModifiedAppearanceId = GetModifier(AppearanceModifierSlotBySpec[owner->GetActiveTalentGroup()]);
2574 if (!itemModifiedAppearanceId)
2575 itemModifiedAppearanceId = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS);
2576
2577 if (!itemModifiedAppearanceId)
2578 if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = GetItemModifiedAppearance())
2579 itemModifiedAppearanceId = itemModifiedAppearance->ID;
2580
2581 return itemModifiedAppearanceId;
2582}
2583
2585{
2587 if (!itemModifiedAppearanceId)
2589
2590 return itemModifiedAppearanceId;
2591}
2592
2594{
2596 if (!enchantmentId)
2598
2599 if (!enchantmentId)
2600 enchantmentId = GetEnchantmentId(PERM_ENCHANTMENT_SLOT);
2601
2602 return enchantmentId;
2603}
2604
2606{
2607 if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(GetVisibleEnchantmentId(owner)))
2608 return enchant->ItemVisual;
2609
2610 return 0;
2611}
2612
2613void Item::AddBonuses(uint32 bonusListID)
2614{
2615 if (advstd::ranges::contains(GetBonusListIDs(), int32(bonusListID)))
2616 return;
2617
2619 itemBonusKey.ItemID = GetEntry();
2620 itemBonusKey.BonusListIDs = GetBonusListIDs();
2621 itemBonusKey.BonusListIDs.push_back(bonusListID);
2623 for (ItemBonusEntry const* bonus : ItemBonusMgr::GetItemBonuses(bonusListID))
2624 _bonusData.AddBonus(bonus->Type, bonus->Value);
2626}
2627
2628void Item::SetBonuses(std::vector<int32> bonusListIDs)
2629{
2631 itemBonusKey.ItemID = GetEntry();
2632 itemBonusKey.BonusListIDs = std::move(bonusListIDs);
2634
2635 for (int32 bonusListID : GetBonusListIDs())
2636 _bonusData.AddBonusList(bonusListID);
2637
2639}
2640
2649
2651{
2652 if (ArtifactEntry const* artifact = sArtifactStore.LookupEntry(GetTemplate()->GetArtifactID()))
2653 return artifact->ArtifactCategoryID != 2; // fishing artifact
2654
2655 return true;
2656}
2657
2659{
2660 return m_itemData->ArtifactPowers.FindIndexIf([artifactPowerId](UF::ArtifactPower const& artifactPower)
2661 {
2662 return uint32(artifactPower.ArtifactPowerID) == artifactPowerId;
2663 });
2664}
2665
2667{
2668 int32 index = GetArtifactPowerIndex(artifactPowerId);
2669 if (index >= 0)
2670 return &m_itemData->ArtifactPowers[index];
2671
2672 return nullptr;
2673}
2674
2676{
2678 powerField.ArtifactPowerID = artifactPower->ArtifactPowerId;
2679 powerField.PurchasedRank = artifactPower->PurchasedRank;
2680 powerField.CurrentRankWithBonus = artifactPower->CurrentRankWithBonus;
2681}
2682
2683void Item::SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus)
2684{
2685 int32 index = GetArtifactPowerIndex(artifactPowerId);
2686 if (index >= 0)
2687 {
2689 .ModifyValue(&UF::ItemData::ArtifactPowers, index)
2690 .ModifyValue(&UF::ArtifactPower::PurchasedRank), purchasedRank);
2691
2693 .ModifyValue(&UF::ItemData::ArtifactPowers, index)
2694 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), currentRankWithBonus);
2695 }
2696}
2697
2698void Item::InitArtifactPowers(uint8 artifactId, uint8 artifactTier)
2699{
2700 std::unordered_set<uint32> knownPowers;
2701 for (UF::ArtifactPower const& power : m_itemData->ArtifactPowers)
2702 knownPowers.insert(power.ArtifactPowerID);
2703
2704 for (ArtifactPowerEntry const* artifactPower : sDB2Manager.GetArtifactPowers(artifactId))
2705 {
2706 if (artifactPower->Tier != artifactTier)
2707 continue;
2708
2709 if (knownPowers.contains(artifactPower->ID))
2710 continue;
2711
2712 ArtifactPowerData powerData;
2713 powerData.ArtifactPowerId = artifactPower->ID;
2714 powerData.PurchasedRank = 0;
2715 powerData.CurrentRankWithBonus = (artifactPower->Flags & ARTIFACT_POWER_FLAG_FIRST) == ARTIFACT_POWER_FLAG_FIRST ? 1 : 0;
2716 AddArtifactPower(&powerData);
2717 }
2718}
2719
2721{
2723 uint64 artifactXp = m_itemData->ArtifactXP;
2724 uint32 currentArtifactTier = GetModifier(ITEM_MODIFIER_ARTIFACT_TIER);
2725 uint32 extraUnlocked = 0;
2726 do
2727 {
2728 uint64 xpCost = 0;
2729 if (GtArtifactLevelXPEntry const* cost = sArtifactLevelXPGameTable.GetRow(purchased + extraUnlocked + 1))
2730 xpCost = uint64(currentArtifactTier == MAX_ARTIFACT_TIER ? cost->XP2 : cost->XP);
2731
2732 if (artifactXp < xpCost)
2733 break;
2734
2735 artifactXp -= xpCost;
2736 ++extraUnlocked;
2737
2738 } while (true);
2739
2740 return purchased + extraUnlocked;
2741}
2742
2744{
2745 uint32 purchasedRanks = 0;
2746 for (UF::ArtifactPower const& power : m_itemData->ArtifactPowers)
2747 purchasedRanks += power.PurchasedRank;
2748
2749 return purchasedRanks;
2750}
2751
2753{
2754 if (SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId))
2755 {
2756 for (uint32 i = 0; i < MAX_ITEM_ENCHANTMENT_EFFECTS; ++i)
2757 {
2758 switch (enchant->Effect[i])
2759 {
2761 for (uint32 artifactPowerIndex = 0; artifactPowerIndex < m_itemData->ArtifactPowers.size(); ++artifactPowerIndex)
2762 {
2763 UF::ArtifactPower const& artifactPower = m_itemData->ArtifactPowers[artifactPowerIndex];
2764 if (uint32(sArtifactPowerStore.AssertEntry(artifactPower.ArtifactPowerID)->Label) == enchant->EffectArg[i])
2765 {
2766 uint8 newRank = artifactPower.CurrentRankWithBonus;
2767 if (apply)
2768 newRank += enchant->EffectPointsMin[i];
2769 else
2770 newRank -= enchant->EffectPointsMin[i];
2771
2773 .ModifyValue(&UF::ItemData::ArtifactPowers, artifactPowerIndex)
2774 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), newRank);
2775
2776 if (IsEquipped())
2777 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(artifactPower.ArtifactPowerID, newRank ? newRank - 1 : 0))
2778 owner->ApplyArtifactPowerRank(this, artifactPowerRank, newRank != 0);
2779 }
2780 }
2781 break;
2783 {
2784 if (int32 artifactPowerIndex = GetArtifactPowerIndex(enchant->EffectArg[i]); artifactPowerIndex >= 0)
2785 {
2786 uint8 newRank = m_itemData->ArtifactPowers[artifactPowerIndex].CurrentRankWithBonus;
2787 if (apply)
2788 newRank += enchant->EffectPointsMin[i];
2789 else
2790 newRank -= enchant->EffectPointsMin[i];
2791
2793 .ModifyValue(&UF::ItemData::ArtifactPowers, artifactPowerIndex)
2794 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), newRank);
2795
2796 if (IsEquipped())
2797 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(m_itemData->ArtifactPowers[artifactPowerIndex].ArtifactPowerID, newRank ? newRank - 1 : 0))
2798 owner->ApplyArtifactPowerRank(this, artifactPowerRank, newRank != 0);
2799 }
2800 break;
2801 }
2804 {
2805 if (ArtifactPowerPickerEntry const* artifactPowerPicker = sArtifactPowerPickerStore.LookupEntry(enchant->EffectArg[i]))
2806 {
2807 if (ConditionMgr::IsPlayerMeetingCondition(owner, artifactPowerPicker->PlayerConditionID))
2808 {
2809 for (uint32 artifactPowerIndex = 0; artifactPowerIndex < m_itemData->ArtifactPowers.size(); ++artifactPowerIndex)
2810 {
2811 UF::ArtifactPower const& artifactPower = m_itemData->ArtifactPowers[artifactPowerIndex];
2812 if (sArtifactPowerStore.AssertEntry(artifactPower.ArtifactPowerID)->Label == _bonusData.GemRelicType[slot - SOCK_ENCHANTMENT_SLOT])
2813 {
2814 uint8 newRank = artifactPower.CurrentRankWithBonus;
2815 if (apply)
2816 newRank += enchant->EffectPointsMin[i];
2817 else
2818 newRank -= enchant->EffectPointsMin[i];
2819
2821 .ModifyValue(&UF::ItemData::ArtifactPowers, artifactPowerIndex)
2822 .ModifyValue(&UF::ArtifactPower::CurrentRankWithBonus), newRank);
2823
2824 if (IsEquipped())
2825 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(artifactPower.ArtifactPowerID, newRank ? newRank - 1 : 0))
2826 owner->ApplyArtifactPowerRank(this, artifactPowerRank, newRank != 0);
2827 }
2828 }
2829 }
2830 }
2831 }
2832 break;
2833 default:
2834 break;
2835 }
2836 }
2837 }
2838}
2839
2846
2847void Item::GiveArtifactXp(uint64 amount, Item* sourceItem, uint32 artifactCategoryId)
2848{
2849 Player* owner = GetOwner();
2850 if (!owner)
2851 return;
2852
2853 if (artifactCategoryId)
2854 {
2855 uint32 artifactKnowledgeLevel = 1;
2856 if (sourceItem && sourceItem->GetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL))
2857 artifactKnowledgeLevel = sourceItem->GetModifier(ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL);
2858
2859 if (GtArtifactKnowledgeMultiplierEntry const* artifactKnowledge = sArtifactKnowledgeMultiplierGameTable.GetRow(artifactKnowledgeLevel))
2860 amount = uint64(amount * artifactKnowledge->Multiplier);
2861
2862 if (amount >= 5000)
2863 amount = 50 * (amount / 50);
2864 else if (amount >= 1000)
2865 amount = 25 * (amount / 25);
2866 else if (amount >= 50)
2867 amount = 5 * (amount / 5);
2868 }
2869
2870 SetArtifactXP(m_itemData->ArtifactXP + amount);
2871
2873 artifactXpGain.ArtifactGUID = GetGUID();
2874 artifactXpGain.Amount = amount;
2875 owner->SendDirectMessage(artifactXpGain.Write());
2876
2877 SetState(ITEM_CHANGED, owner);
2878
2880}
2881
2883{
2885 return;
2886
2888 {
2889 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(_bonusData.ContentTuningId, {}, true))
2890 level = std::min(std::max(int16(level), levels->MinLevel), levels->MaxLevel);
2891
2893 }
2894}
2895
2907
2908std::string Item::GetDebugInfo() const
2909{
2910 std::stringstream sstr;
2911 sstr << Object::GetDebugInfo() << "\n"
2912 << std::boolalpha
2913 << "Owner: " << GetOwnerGUID().ToString() << " Count: " << GetCount()
2914 << " BagSlot: " << std::to_string(GetBagSlot()) << " Slot: " << std::to_string(GetSlot()) << " Equipped: " << IsEquipped();
2915 return sstr.str();
2916}
2917
2919{
2920 Quality = proto->GetQuality();
2921 ItemLevel = proto->GetBaseItemLevel();
2922 ItemLevelBonus = 0;
2923 RequiredLevel = proto->GetBaseRequiredLevel();
2924 for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
2925 {
2926 ItemStatType[i] = proto->GetStatModifierBonusStat(i);
2927 StatPercentEditor[i] = proto->GetStatPercentEditor(i);
2928 ItemStatSocketCostMultiplier[i] = proto->GetStatPercentageOfSocket(i);
2929 }
2930
2931 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
2932 {
2933 SocketColor[i] = proto->GetSocketColor(i);
2934 GemItemLevelBonus[i] = 0;
2935 GemRelicType[i] = -1;
2936 GemRelicRankBonus[i] = 0;
2937 }
2938
2939 Bonding = proto->GetBonding();
2940
2941 AppearanceModID = 0;
2942 RepairCostMultiplier = 1.0f;
2943 ContentTuningId = proto->GetScalingStatContentTuning();
2944 PlayerLevelToItemLevelCurveId = proto->GetPlayerLevelToItemLevelCurveId();
2945 DisenchantLootId = 0;
2946 RelicType = -1;
2947 HasFixedLevel = false;
2948 RequiredLevelOverride = 0;
2949 AzeriteTierUnlockSetId = 0;
2950 if (AzeriteEmpoweredItemEntry const* azeriteEmpoweredItem = sDB2Manager.GetAzeriteEmpoweredItem(proto->GetId()))
2951 AzeriteTierUnlockSetId = azeriteEmpoweredItem->AzeriteTierUnlockSetID;
2952
2953 Suffix = 0;
2954 RequiredLevelCurve = 0;
2955
2956 PvpItemLevel = 0;
2957 PvpItemLevelBonus = 0;
2958
2959 ItemLevelOffsetCurveId = proto->GetItemLevelOffsetCurveId();
2960 ItemLevelOffsetItemLevel = proto->GetItemLevelOffsetItemLevel();
2961 ItemLevelOffset = 0;
2962 ItemSquishEraID = proto->GetItemSquishEraId();
2963 ScalingConfigItemLevelBonus = 0;
2964 ScalingConfigCraftingQualityItemLevelBonus = 0;
2965
2966 EffectCount = 0;
2967 for (ItemEffectEntry const* itemEffect : proto->Effects)
2968 Effects[EffectCount++] = itemEffect;
2969
2970 for (std::size_t i = EffectCount; i < Effects.size(); ++i)
2971 Effects[i] = nullptr;
2972
2973 LimitCategory = proto->GetItemLimitCategory();
2974
2975 CanDisenchant = !proto->HasFlag(ITEM_FLAG_NO_DISENCHANT);
2976 CanScrap = proto->HasFlag(ITEM_FLAG4_SCRAPABLE);
2977 CanSalvage = !proto->HasFlag(ITEM_FLAG4_NO_SALVAGE);
2978 CanRecraft = proto->HasFlag(ITEM_FLAG4_RECRAFTABLE);
2979 CannotTradeBindOnPickup = proto->HasFlag(ITEM_FLAG2_NO_TRADE_BIND_ON_ACQUIRE);
2980 IgnoreSquish = false;
2981 RestrictScalingToContentTuning = false;
2982 ScalingConfigUsesPlayerLevel = false;
2983
2984 _state.SuffixPriority = std::numeric_limits<int32>::max();
2985 _state.AppearanceModPriority = std::numeric_limits<int32>::max();
2986 _state.DisenchantLootPriority = std::numeric_limits<int32>::max();
2987 _state.ScalingStatDistributionPriority = std::numeric_limits<int32>::max();
2988 _state.AzeriteTierUnlockSetPriority = std::numeric_limits<int32>::max();
2989 _state.RequiredLevelCurvePriority = std::numeric_limits<int32>::max();
2990 _state.ItemLevelPriority = std::numeric_limits<int32>::max();
2991 _state.PvpItemLevelPriority = std::numeric_limits<int32>::max();
2992 _state.BondingPriority = std::numeric_limits<int32>::max();
2993 _state.ScalingConfigItemLevelBonusPriority = std::numeric_limits<int32>::max();
2994 _state.ScalingConfigCraftingQualityItemLevelBonusPriority = std::numeric_limits<int32>::max();
2995 _state.HasQualityBonus = false;
2996 _state.HasItemLimitCategory = false;
2997}
2998
3000{
3001 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemInstance.ItemID);
3002 if (!proto)
3003 return;
3004
3005 Initialize(proto);
3006
3007 if (itemInstance.ItemBonus)
3008 for (uint32 bonusListID : itemInstance.ItemBonus->BonusListIDs)
3009 AddBonusList(bonusListID);
3010}
3011
3013{
3014 for (ItemBonusEntry const* bonus : ItemBonusMgr::GetItemBonuses(bonusListId))
3015 AddBonus(bonus->Type, bonus->Value);
3016}
3017
3018void BonusData::AddBonus(uint32 type, std::array<int32, 4> const& values)
3019{
3020 switch (type)
3021 {
3023 ItemLevelBonus += values[0];
3024 break;
3025 case ITEM_BONUS_STAT:
3026 {
3027 uint32 statIndex = 0;
3028 for (statIndex = 0; statIndex < MAX_ITEM_PROTO_STATS; ++statIndex)
3029 if (ItemStatType[statIndex] == values[0] || ItemStatType[statIndex] == -1)
3030 break;
3031
3032 if (statIndex < MAX_ITEM_PROTO_STATS)
3033 {
3034 ItemStatType[statIndex] = values[0];
3035 StatPercentEditor[statIndex] += values[1];
3036 }
3037 break;
3038 }
3039 case ITEM_BONUS_QUALITY:
3040 if (!_state.HasQualityBonus)
3041 {
3042 Quality = static_cast<uint32>(values[0]);
3043 _state.HasQualityBonus = true;
3044 }
3045 else if (Quality < static_cast<uint32>(values[0]))
3046 Quality = static_cast<uint32>(values[0]);
3047 break;
3048 case ITEM_BONUS_SUFFIX:
3049 if (values[1] < _state.SuffixPriority)
3050 {
3051 Suffix = static_cast<uint32>(values[0]);
3052 _state.SuffixPriority = values[1];
3053 }
3054 break;
3055 case ITEM_BONUS_SOCKET:
3056 {
3057 uint32 socketCount = values[0];
3058 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS && socketCount; ++i)
3059 {
3060 if (!SocketColor[i])
3061 {
3062 SocketColor[i] = values[1];
3063 --socketCount;
3064 }
3065 }
3066 break;
3067 }
3069 if (values[1] < _state.AppearanceModPriority)
3070 {
3071 AppearanceModID = static_cast<uint32>(values[0]);
3072 _state.AppearanceModPriority = values[1];
3073 }
3074 break;
3076 RequiredLevel += values[0];
3077 break;
3079 RepairCostMultiplier *= static_cast<float>(values[0]) * 0.01f;
3080 break;
3083 if (values[1] < _state.ScalingStatDistributionPriority)
3084 {
3085 ContentTuningId = static_cast<uint32>(values[2]);
3086 PlayerLevelToItemLevelCurveId = static_cast<uint32>(values[3]);
3087 _state.ScalingStatDistributionPriority = values[1];
3088 HasFixedLevel = type == ITEM_BONUS_SCALING_STAT_DISTRIBUTION_FIXED;
3089 }
3090 break;
3092 if (values[1] < _state.DisenchantLootPriority)
3093 {
3094 DisenchantLootId = values[0];
3095 _state.DisenchantLootPriority = values[1];
3096 }
3097 break;
3098 case ITEM_BONUS_BONDING:
3099 Bonding = ItemBondingType(values[0]);
3100 break;
3102 RelicType = values[0];
3103 break;
3105 RequiredLevelOverride = values[0];
3106 break;
3108 if (values[1] < _state.AzeriteTierUnlockSetPriority)
3109 {
3110 AzeriteTierUnlockSetId = values[0];
3111 _state.AzeriteTierUnlockSetPriority = values[1];
3112 }
3113 break;
3115 CanDisenchant = values[0] != 0;
3116 break;
3118 CanScrap = values[0] != 0;
3119 break;
3121 if (ItemEffectEntry const* itemEffect = sItemEffectStore.LookupEntry(values[0]))
3122 Effects[EffectCount++] = itemEffect;
3123 break;
3125 if (values[2] < _state.RequiredLevelCurvePriority)
3126 {
3127 RequiredLevelCurve = values[0];
3128 _state.RequiredLevelCurvePriority = values[2];
3129 if (values[1])
3130 ContentTuningId = static_cast<uint32>(values[1]);
3131 }
3132 break;
3134 if (!_state.HasItemLimitCategory)
3135 {
3136 LimitCategory = values[0];
3137 _state.HasItemLimitCategory = true;
3138 }
3139 break;
3141 PvpItemLevelBonus += values[0];
3142 break;
3144 CanSalvage = values[0] != 0;
3145 break;
3147 CanRecraft = values[0] != 0;
3148 break;
3150 if (values[1] < _state.ItemLevelPriority)
3151 {
3152 ItemLevel = values[0];
3153 _state.ItemLevelPriority = values[1];
3154 }
3155 break;
3157 if (values[1] < _state.PvpItemLevelPriority)
3158 {
3159 PvpItemLevel = values[0];
3160 _state.PvpItemLevelPriority = values[1];
3161 }
3162 break;
3164 CannotTradeBindOnPickup = values[0] != 0;
3165 break;
3167 if (values[1] < _state.BondingPriority)
3168 {
3169 Bonding = static_cast<ItemBondingType>(values[0]);
3170 _state.BondingPriority = values[1];
3171 }
3172 break;
3174 if (values[3] < _state.ScalingStatDistributionPriority)
3175 {
3176 ItemLevelOffsetCurveId = values[0];
3177 ItemLevelOffsetItemLevel = values[1];
3178 _state.ScalingStatDistributionPriority = values[3];
3179 }
3180 break;
3182 if (values[1] < _state.ScalingStatDistributionPriority)
3183 {
3184 _state.ScalingStatDistributionPriority = values[1];
3185 if (ItemScalingConfigEntry const* scalingConfig = sItemScalingConfigStore.LookupEntry(values[0]))
3186 {
3187 if (ItemOffsetCurveEntry const* itemOffsetCurve = sItemOffsetCurveStore.LookupEntry(scalingConfig->ItemOffsetCurveID))
3188 {
3189 ItemLevelOffsetCurveId = itemOffsetCurve->CurveID;
3190 ItemLevelOffset = itemOffsetCurve->Offset;
3191 }
3192
3193 ScalingConfigUsesPlayerLevel = false;
3194 ItemSquishEraID = scalingConfig->ItemSquishEraID;
3195 if (scalingConfig->Flags & 0x1)
3196 IgnoreSquish = true;
3197 if (scalingConfig->Flags & 0x2)
3198 RestrictScalingToContentTuning = true;
3199
3200 if (values[1] < _state.RequiredLevelCurvePriority)
3201 {
3202 ItemLevelOffsetItemLevel = scalingConfig->ItemLevel;
3203 RequiredLevelOverride = scalingConfig->RequiredLevel;
3204 RequiredLevelCurve = 0;
3205 }
3206 }
3207 }
3208 break;
3210 AddBonusList(values[0]);
3211 break;
3213 if (values[1] < _state.ScalingStatDistributionPriority)
3214 {
3215 _state.ScalingStatDistributionPriority = values[1];
3216 if (ItemScalingConfigEntry const* scalingConfig = sItemScalingConfigStore.LookupEntry(values[0]))
3217 {
3218 if (ItemOffsetCurveEntry const* itemOffsetCurve = sItemOffsetCurveStore.LookupEntry(scalingConfig->ItemOffsetCurveID))
3219 {
3220 ItemLevelOffsetCurveId = itemOffsetCurve->CurveID;
3221 ItemLevelOffset = itemOffsetCurve->Offset;
3222 }
3223
3224 ScalingConfigUsesPlayerLevel = true;
3225 ItemLevelOffsetItemLevel = 0;
3226 ItemSquishEraID = scalingConfig->ItemSquishEraID;
3227 if (scalingConfig->Flags & 0x1)
3228 IgnoreSquish = true;
3229 if (scalingConfig->Flags & 0x2)
3230 RestrictScalingToContentTuning = true;
3231 }
3232 }
3233 break;
3235 if (values[3] < _state.ScalingConfigCraftingQualityItemLevelBonusPriority)
3236 {
3237 bool isSquished = false;
3238 if (std::shared_ptr<Realm const> currentRealm = sRealmList->GetCurrentRealm())
3239 {
3240 int32 currentBuild = ClientBuild::GetMinorMajorBugfixVersionForBuild(currentRealm->Build);
3241
3242 // apply all squishes between items_squish and server_squish
3243 for (uint32 squishId = values[1] + 1; squishId < sItemSquishEraStore.GetNumRows(); ++squishId)
3244 {
3245 ItemSquishEraEntry const* squish = sItemSquishEraStore.LookupEntry(squishId);
3246 if (!squish || squish->Flags & 0x1)
3247 continue;
3248
3249 isSquished = squish->Patch <= currentBuild;
3250 break;
3251 }
3252 }
3253
3254 ScalingConfigCraftingQualityItemLevelBonus = values[isSquished ? 2 : 0];
3255 _state.ScalingConfigCraftingQualityItemLevelBonusPriority = values[3];
3256 }
3257 break;
3259 if (values[1] < _state.ScalingConfigItemLevelBonusPriority)
3260 {
3261 ScalingConfigItemLevelBonus = values[0];
3262 _state.ScalingConfigItemLevelBonusPriority = values[1];
3263 }
3264 break;
3265 }
3266}
std::unordered_map< Player *, UpdateData > UpdateDataMapType
Definition BaseEntity.h:32
@ 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:51
@ HOUR
Definition Common.h:33
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< ItemScalingConfigEntry > sItemScalingConfigStore("ItemScalingConfig.db2", &ItemScalingConfigLoadInfo::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< ItemSquishEraEntry > sItemSquishEraStore("ItemSquishEra.db2", &ItemSquishEraLoadInfo::Instance)
DB2Storage< ImportPriceShieldEntry > sImportPriceShieldStore("ImportPriceShield.db2", &ImportPriceShieldLoadInfo::Instance)
DB2Storage< ItemOffsetCurveEntry > sItemOffsetCurveStore("ItemOffsetCurve.db2", &ItemOffsetCurveLoadInfo::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< 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:579
#define MAX_ITEM_ENCHANTMENT_EFFECTS
@ ITEM_BONUS_SCALING_CONFIG
Definition DBCEnums.h:1302
@ ITEM_BONUS_ITEM_OFFSET_CURVE
Definition DBCEnums.h:1299
@ ITEM_BONUS_APPEARANCE
Definition DBCEnums.h:1259
@ ITEM_BONUS_OVERRIDE_CAN_RECRAFT
Definition DBCEnums.h:1292
@ ITEM_BONUS_SCALING_ITEM_LEVEL_BONUS
Definition DBCEnums.h:1304
@ ITEM_BONUS_RELIC_TYPE
Definition DBCEnums.h:1269
@ ITEM_BONUS_BONDING
Definition DBCEnums.h:1268
@ ITEM_BONUS_SOCKET
Definition DBCEnums.h:1258
@ ITEM_BONUS_SUFFIX
Definition DBCEnums.h:1257
@ ITEM_BONUS_REQUIRED_LEVEL
Definition DBCEnums.h:1260
@ ITEM_BONUS_AZERITE_TIER_UNLOCK_SET
Definition DBCEnums.h:1271
@ ITEM_BONUS_SCALING_STAT_DISTRIBUTION
Definition DBCEnums.h:1263
@ ITEM_BONUS_BONDING_WITH_PRIORITY
Definition DBCEnums.h:1298
@ ITEM_BONUS_SCALING_STAT_DISTRIBUTION_FIXED
Definition DBCEnums.h:1265
@ ITEM_BONUS_CRAFTED_ITEM_LEVEL
Definition DBCEnums.h:1303
@ ITEM_BONUS_OVERRIDE_CAN_DISENCHANT
Definition DBCEnums.h:1273
@ ITEM_BONUS_PVP_ITEM_LEVEL_BASE
Definition DBCEnums.h:1294
@ ITEM_BONUS_ITEM_LEVEL
Definition DBCEnums.h:1253
@ ITEM_BONUS_REQUIRED_LEVEL_CURVE
Definition DBCEnums.h:1278
@ ITEM_BONUS_QUALITY
Definition DBCEnums.h:1255
@ ITEM_BONUS_OVERRIDE_CAN_SALVAGE
Definition DBCEnums.h:1290
@ ITEM_BONUS_ITEM_LEVEL_BASE
Definition DBCEnums.h:1293
@ ITEM_BONUS_REPAIR_COST_MULTIPLIER
Definition DBCEnums.h:1262
@ ITEM_BONUS_OVERRIDE_REQUIRED_LEVEL
Definition DBCEnums.h:1270
@ ITEM_BONUS_PVP_ITEM_LEVEL_INCREMENT
Definition DBCEnums.h:1287
@ ITEM_BONUS_SCALING_CONFIG_AND_REQ_LEVEL
Definition DBCEnums.h:1300
@ ITEM_BONUS_ITEM_LIMIT_CATEGORY
Definition DBCEnums.h:1286
@ ITEM_BONUS_OVERRIDE_CANNOT_TRADE_BOP
Definition DBCEnums.h:1297
@ ITEM_BONUS_OVERRIDE_CAN_SCRAP
Definition DBCEnums.h:1274
@ ITEM_BONUS_STAT
Definition DBCEnums.h:1254
@ ITEM_BONUS_ITEM_EFFECT_ID
Definition DBCEnums.h:1275
@ ITEM_BONUS_ITEM_BONUS_LIST
Definition DBCEnums.h:1301
@ ITEM_BONUS_DISENCHANT_LOOT_ID
Definition DBCEnums.h:1264
#define MAX_AZERITE_EMPOWERED_TIER
Definition DBCEnums.h:229
@ ITEM_ENCHANTMENT_TYPE_BONUS_LIST_CURVE
Definition DBCEnums.h:1237
@ ITEM_ENCHANTMENT_TYPE_ARTIFACT_POWER_BONUS_RANK_BY_TYPE
Definition DBCEnums.h:1234
@ ITEM_ENCHANTMENT_TYPE_ARTIFACT_POWER_BONUS_RANK_BY_ID
Definition DBCEnums.h:1235
@ ITEM_ENCHANTMENT_TYPE_BONUS_LIST_ID
Definition DBCEnums.h:1236
@ ITEM_ENCHANTMENT_TYPE_ARTIFACT_POWER_BONUS_RANK_PICKER
Definition DBCEnums.h:1238
#define MAX_ITEM_PROTO_SOCKETS
Definition DBCEnums.h:1213
ItemContext
Definition DBCEnums.h:1324
@ CURVE_ID_ARTIFACT_RELIC_ITEM_LEVEL_BONUS
Definition DBCEnums.h:918
ChrSpecialization
Definition DBCEnums.h:400
@ DIFFICULTY_NONE
Definition DBCEnums.h:936
@ ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS
Definition DBCEnums.h:220
@ ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER
Definition DBCEnums.h:222
@ ARTIFACT_POWER_FLAG_FIRST
Definition DBCEnums.h:224
@ ITEM_SET_FLAG_LEGACY_INACTIVE
Definition DBCEnums.h:1529
#define MAX_AZERITE_ESSENCE_SLOT
Definition DBCEnums.h:231
#define MAX_ITEM_PROTO_STATS
Definition DBCEnums.h:1214
#define MAX_ARTIFACT_TIER
Definition DBCEnums.h:227
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:156
int64_t int64
Definition Define.h:149
int16_t int16
Definition Define.h:151
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
uint16 flags
#define ABORT
Definition Errors.h:79
#define ASSERT_NODEBUGINFO
Definition Errors.h:73
#define ASSERT
Definition Errors.h:72
GameTable< GtItemSocketCostPerLevelEntry > sItemSocketCostPerLevelGameTable
GameTable< GtArtifactKnowledgeMultiplierEntry > sArtifactKnowledgeMultiplierGameTable
GameTable< GtArtifactLevelXPEntry > sArtifactLevelXPGameTable
EnchantmentSlot
@ PERM_ENCHANTMENT_SLOT
@ SOCK_ENCHANTMENT_SLOT_3
@ MAX_ENCHANTMENT_SLOT
@ SOCK_ENCHANTMENT_SLOT
@ MAX_INSPECTED_ENCHANTMENT_SLOT
InventoryResult
Definition ItemDefines.h:25
@ EQUIP_ERR_OK
Definition ItemDefines.h:26
@ EQUIP_ERR_LOOT_GONE
Definition ItemDefines.h:76
@ EQUIP_ERR_CANT_STACK
Definition ItemDefines.h:45
ItemModifier
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_5
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_2
@ ITEM_MODIFIER_ENCHANT_ILLUSION_ALL_SPECS
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_ALL_SPECS
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_4
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_1
@ ITEM_MODIFIER_TIMEWALKER_LEVEL
@ ITEM_MODIFIER_CONTENT_TUNING_ID
@ ITEM_MODIFIER_BATTLE_PET_DISPLAY_ID
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_5
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_4
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_5
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1
@ ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3
@ ITEM_MODIFIER_BATTLE_PET_BREED_DATA
@ ITEM_MODIFIER_ARTIFACT_KNOWLEDGE_LEVEL
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_2
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_3
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_2
@ ITEM_MODIFIER_ARTIFACT_TIER
@ ITEM_MODIFIER_BATTLE_PET_SPECIES_ID
@ ITEM_MODIFIER_BATTLE_PET_LEVEL
@ ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1
float GetRandomPropertyPoints(uint32 itemLevel, uint32 quality, uint32 inventoryType, uint32 subClass)
uint32 ItemRandomBonusListId
int32 const SocketColorToGemTypeMask[31]
@ ITEM_CLASS_QUIVER
@ ITEM_CLASS_CONTAINER
@ ITEM_CLASS_GEM
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
@ ITEM_FLAG2_NO_TRADE_BIND_ON_ACQUIRE
@ ITEM_FLAG2_NO_ALTER_ITEM_VISUAL
@ ITEM_FLAG2_OVERRIDE_GOLD_COST
@ ITEM_SUBCLASS_WEAPON_FISHING_POLE
ItemFieldFlags
@ ITEM_FIELD_FLAG_REFUNDABLE
@ ITEM_FIELD_FLAG_CHILD
@ ITEM_FIELD_FLAG_SOULBOUND
@ ITEM_FIELD_FLAG_BOP_TRADEABLE
@ ITEM_SPELLTRIGGER_ON_USE
@ BAG_FAMILY_MASK_MINING_SUPP
@ BAG_FAMILY_MASK_HERBS
@ BAG_FAMILY_MASK_ENCHANTING_SUPP
@ BAG_FAMILY_MASK_SOUL_SHARDS
@ BAG_FAMILY_MASK_INSCRIPTION_SUPP
@ BAG_FAMILY_MASK_GEMS
@ BAG_FAMILY_MASK_ARROWS
@ BAG_FAMILY_MASK_BULLETS
@ BAG_FAMILY_MASK_ENGINEERING_SUPP
@ BAG_FAMILY_MASK_COOKING_SUPP
@ BAG_FAMILY_MASK_FISHING_SUPP
@ BAG_FAMILY_MASK_LEATHERWORKING_SUPP
@ ITEM_SUBCLASS_CONTAINER
@ ITEM_SUBCLASS_REAGENT_CONTAINER
@ ITEM_SUBCLASS_COOKING_CONTAINER
@ ITEM_SUBCLASS_INSCRIPTION_CONTAINER
@ ITEM_SUBCLASS_LEATHERWORKING_CONTAINER
@ ITEM_SUBCLASS_TACKLE_CONTAINER
@ ITEM_SUBCLASS_GEM_CONTAINER
@ ITEM_SUBCLASS_SOUL_CONTAINER
@ ITEM_SUBCLASS_ENCHANTING_CONTAINER
@ ITEM_SUBCLASS_MINING_CONTAINER
@ ITEM_SUBCLASS_HERB_CONTAINER
@ ITEM_SUBCLASS_ENGINEERING_CONTAINER
@ ITEM_SUBCLASS_QUIVER
@ ITEM_SUBCLASS_AMMO_POUCH
@ ITEM_FLAG_NO_DISENCHANT
@ ITEM_FLAG_CONJURED
@ ITEM_FLAG3_CAN_STORE_ENCHANTS
@ ITEM_FLAG3_IGNORE_ITEM_LEVEL_CAP_IN_PVP
@ ITEM_MOD_CORRUPTION_RESISTANCE
@ ITEM_MOD_CORRUPTION
@ ITEM_SUBCLASS_ARMOR_MAIL
@ ITEM_SUBCLASS_ARMOR_CLOTH
@ ITEM_SUBCLASS_ARMOR_LEATHER
@ ITEM_SUBCLASS_ARMOR_PLATE
@ ITEM_SUBCLASS_ARMOR_MISCELLANEOUS
@ ITEM_SUBCLASS_ARMOR_COSMETIC
@ ITEM_FLAG4_RECRAFTABLE
@ ITEM_FLAG4_NO_SALVAGE
@ ITEM_FLAG4_SCRAPABLE
#define MAX_INVTYPE
@ MIN_ITEM_LEVEL
@ MAX_ITEM_LEVEL
SocketColor
@ ITEM_SUBCLASS_GEM_ARTIFACT_RELIC
ItemBondingType
@ BIND_QUEST
@ BIND_NONE
@ INVTYPE_FINGER
@ INVTYPE_HEAD
@ INVTYPE_CLOAK
@ INVTYPE_ROBE
@ INVTYPE_HOLDABLE
@ INVTYPE_TRINKET
@ INVTYPE_RELIC
@ INVTYPE_RANGED
@ INVTYPE_THROWN
@ INVTYPE_WAIST
@ INVTYPE_RANGEDRIGHT
@ INVTYPE_WRISTS
@ INVTYPE_WEAPON
@ INVTYPE_WEAPONMAINHAND
@ INVTYPE_WEAPONOFFHAND
@ INVTYPE_2HWEAPON
@ INVTYPE_BAG
@ INVTYPE_NECK
@ INVTYPE_SHOULDERS
@ INVTYPE_FEET
@ INVTYPE_NON_EQUIP
@ INVTYPE_AMMO
@ INVTYPE_QUIVER
@ INVTYPE_SHIELD
@ INVTYPE_LEGS
@ INVTYPE_CHEST
@ INVTYPE_HANDS
void RemoveItemsSetItem(Player *player, Item const *item)
Definition Item.cpp:169
bool ItemCanGoIntoBag(ItemTemplate const *pProto, ItemTemplate const *pBagProto)
Definition Item.cpp:250
ItemModifier const AppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition Item.cpp:325
void UpdateItemSetAuras(Player *player, bool formChange)
Definition Item.cpp:221
ItemModifier const SecondaryAppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition Item.cpp:343
void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:1310
Item * NewItemOrBag(ItemTemplate const *proto)
Definition Item.cpp:55
ItemModifier const IllusionModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition Item.cpp:334
static uint32 FindSpellChargesSlot(BonusData const &bonusData, ItemEffectEntry const *effect)
Definition Item.cpp:602
void AddItemsSetItem(Player *player, Item const *item)
Definition Item.cpp:76
void DeleteItemSetEffects(ItemSetEffect *itemSetEffect)
Definition Item.cpp:245
void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:1289
ItemModifier const AppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition Item.cpp:325
ItemModifier const SecondaryAppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition Item.cpp:343
#define MAX_GEM_SOCKETS
Definition Item.h:40
#define MAX_ENCHANTMENT_OFFSET
Definition Item.h:42
Item * NewItemOrBag(ItemTemplate const *proto)
Definition Item.cpp:55
ItemUpdateState
Definition Item.h:45
@ ITEM_CHANGED
Definition Item.h:47
@ ITEM_REMOVED
Definition Item.h:49
@ ITEM_NEW
Definition Item.h:48
@ ITEM_UNCHANGED
Definition Item.h:46
ItemModifier const IllusionModifierSlotBySpec[MAX_SPECIALIZATIONS]
Definition Item.cpp:334
int32 const ItemTransmogrificationSlots[MAX_INVTYPE]
Definition Item.cpp:2014
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
#define sLootItemStorage
@ TYPEID_OBJECT
Definition ObjectGuid.h:38
@ TYPEID_ITEM
Definition ObjectGuid.h:39
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:432
#define sObjectMgr
Definition ObjectMgr.h:1873
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ EQUIPMENT_SLOT_SHOULDERS
Definition Player.h:717
@ EQUIPMENT_SLOT_BODY
Definition Player.h:718
@ EQUIPMENT_SLOT_HANDS
Definition Player.h:724
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:730
@ EQUIPMENT_SLOT_TABARD
Definition Player.h:733
@ EQUIPMENT_SLOT_END
Definition Player.h:734
@ EQUIPMENT_SLOT_HEAD
Definition Player.h:715
@ EQUIPMENT_SLOT_LEGS
Definition Player.h:721
@ EQUIPMENT_SLOT_BACK
Definition Player.h:729
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:731
@ EQUIPMENT_SLOT_WAIST
Definition Player.h:720
@ EQUIPMENT_SLOT_FEET
Definition Player.h:722
@ EQUIPMENT_SLOT_CHEST
Definition Player.h:719
@ EQUIPMENT_SLOT_WRISTS
Definition Player.h:723
constexpr uint8 INVENTORY_SLOT_BAG_0
Definition Player.h:706
@ PROFESSION_SLOT_START
Definition Player.h:752
@ PROFESSION_SLOT_END
Definition Player.h:751
#define sRealmList
Definition RealmList.h:95
#define sScriptMgr
Definition ScriptMgr.h:1449
@ SPELL_EFFECT_ENCHANT_ITEM
@ SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
@ SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
#define MAX_SPECIALIZATIONS
#define sSpellMgr
Definition SpellMgr.h:812
TradeSlots
Definition TradeData.h:24
@ TRADE_SLOT_INVALID
Definition TradeData.h:28
Definition Bag.h:27
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void BuildUpdateChangesMask()
void SetUpdateFieldValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type value)
Definition BaseEntity.h:221
WowCS::EntityFragmentsHolder m_entityFragments
Definition BaseEntity.h:353
void RemoveDynamicUpdateFieldValue(UF::DynamicUpdateFieldSetter< T > setter, uint32 index)
Definition BaseEntity.h:256
UF::UpdateFieldHolder m_values
Definition BaseEntity.h:205
void _Create(ObjectGuid const &guid)
Definition BaseEntity.h:218
void ClearUpdateMask(bool remove)
UF::DynamicUpdateFieldSetter< T >::insert_result AddDynamicUpdateFieldValue(UF::DynamicUpdateFieldSetter< T > setter)
Definition BaseEntity.h:242
ByteBuffer & PrepareValuesUpdateBuffer(UpdateData *data) const
TypeID m_objectTypeId
Definition BaseEntity.h:351
void BuildFieldsUpdate(Player *player, UpdateDataMapType &data_map) const
size_t wpos() const
Definition ByteBuffer.h:462
void put(std::size_t pos, T value)
Definition ByteBuffer.h:261
void AddItemAppearance(Item *item)
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
Class used to access individual fields of database query result.
Definition Field.h:94
uint64 GetUInt64() const noexcept
Definition Field.cpp:71
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
uint16 GetUInt16() const noexcept
Definition Field.cpp:43
uint8 GetUInt8() const noexcept
Definition Field.cpp:29
int32 GetInt32() const noexcept
Definition Field.cpp:64
Definition Item.h:185
std::string GetDebugInfo() const override
Definition Item.cpp:2908
uint32 GetEnchantRequiredLevel() const
Definition Item.cpp:1434
static void DeleteFromInventoryDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:1221
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition Item.cpp:1258
uint32 GetPaidExtendedCost() const
Definition Item.h:381
uint8 GetSlot() const
Definition Item.h:296
void SetItemFlag(ItemFieldFlags flags)
Definition Item.h:224
std::span< ItemEffectEntry const *const > GetEffects() const
Definition Item.h:370
static bool CanTransmogrifyItemWithItem(Item const *item, ItemModifiedAppearanceEntry const *itemModifiedAppearance)
Definition Item.cpp:2053
void LoadAdditionalDataFromDB(Player const *owner, ItemAdditionalLoadInfo *addionalData)
Definition Item.cpp:1083
bool IsWrapped() const
Definition Item.h:266
bool AddToObjectUpdate() override
Definition Item.cpp:1883
void SetText(std::string const &text)
Definition Item.h:321
void SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus)
Definition Item.cpp:2683
void UpdateDuration(Player *owner, uint32 diff)
Definition Item.cpp:583
void BuildValuesUpdateForPlayerWithMask(UpdateData *data, UF::ObjectData::Mask const &requestedObjectMask, UF::ItemData::Mask const &requestedItemMask, Player const *target, bool ignoreNestedChangesMask) const
Definition Item.cpp:1836
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:639
void SetFixedLevel(uint8 level)
Definition Item.cpp:2882
uint32 GetBuyPrice(Player const *owner, bool &standardPrice) const
Definition Item.cpp:2101
void ReplaceAllItemFlags(ItemFieldFlags flags)
Definition Item.h:226
void BuildUpdate(UpdateDataMapType &) override
Definition Item.cpp:1790
bool IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const
Definition Item.cpp:1692
void RemoveItemFlag(ItemFieldFlags flags)
Definition Item.h:225
Item()
Definition Item.cpp:486
ItemBondingType GetBonding() const
Definition Item.h:215
int32 GetArtifactPowerIndex(uint32 artifactPowerId) const
Definition Item.cpp:2658
void DeleteRefundDataFromDB(CharacterDatabaseTransaction *trans)
Definition Item.cpp:1918
static ItemDisenchantLootEntry const * GetBaseDisenchantLoot(ItemTemplate const *itemTemplate, uint32 quality, uint32 itemLevel)
Definition Item.cpp:2443
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition Item.h:314
void SetPaidMoney(uint64 money)
Definition Item.h:376
Item * CloneItem(uint32 count, Player const *player=nullptr) const
Definition Item.cpp:1751
void AddBonuses(uint32 bonusListID)
Definition Item.cpp:2613
Bag * m_container
Definition Item.h:472
uint8 GetGemCountWithID(uint32 GemID) const
Definition Item.cpp:1666
bool IsBoundAccountWide() const
Definition Item.h:234
bool mb_in_trade
Definition Item.h:475
Bag * ToBag()
Definition Item.h:257
std::string m_text
Definition Item.h:470
void InitArtifactPowers(uint8 artifactId, uint8 artifactTier)
Definition Item.cpp:2698
AzeriteItem * ToAzeriteItem()
Definition Item.h:259
int32 GetItemStatType(uint32 index) const
Definition Item.h:357
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition Item.cpp:1342
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const
Definition Item.h:315
void ClearValuesChangesMask() override
Definition Item.cpp:1877
void ClearBonuses()
Definition Item.cpp:2641
void SetContext(ItemContext context)
Definition Item.h:457
uint32 GetQuality() const
Definition Item.h:352
uint64 m_paidMoney
Definition Item.h:477
std::array< uint32, MAX_ITEM_PROTO_SOCKETS > m_gemScalingLevels
Definition Item.h:482
void GiveArtifactXp(uint64 amount, Item *sourceItem, uint32 artifactCategoryId)
Definition Item.cpp:2847
UF::SocketedGem const * GetGem(uint16 slot) const
Definition Item.cpp:1571
void SetCount(uint32 value)
Definition Item.cpp:1367
void SetModifier(ItemModifier modifier, uint32 value)
Definition Item.cpp:2515
void SetDurability(uint32 durability)
Definition Item.h:274
void SetCreateTime(int64 createTime)
Definition Item.h:328
ObjectGuid GetCreator() const
Definition Item.h:207
ItemTemplate const * GetTemplate() const
Definition Item.cpp:1233
void ApplyArtifactPowerEnchantmentBonuses(EnchantmentSlot slot, uint32 enchantId, bool apply, Player *owner)
Definition Item.cpp:2752
UF::UpdateField< UF::ItemData, uint32(WowCS::EntityFragment::CGObject), TYPEID_ITEM > m_itemData
Definition Item.h:464
std::vector< int32 > const & GetBonusListIDs() const
Definition Item.h:245
bool IsBOPTradeable() const
Definition Item.h:265
bool IsInBag() const
Definition Item.h:303
void SetGem(uint16 slot, ItemDynamicFieldGems const *gem, uint32 gemScalingLevel)
Definition Item.cpp:1577
bool IsSoulBound() const
Definition Item.h:233
void SaveRefundDataToDB()
Definition Item.cpp:1900
ItemContext GetContext() const
Definition Item.h:456
void SetNotRefundable(Player *owner, bool changestate=true, CharacterDatabaseTransaction *trans=nullptr, bool addToCollection=true)
Definition Item.cpp:1929
ItemRandomBonusListId m_randomBonusListId
Definition Item.h:480
uint32 GetVisibleEnchantmentId(Player const *owner) const
Definition Item.cpp:2593
friend void RemoveItemFromUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:1310
bool IsBindedNotWith(Player const *player) const
Definition Item.cpp:1769
uint32 GetSellPrice(Player const *owner, bool forVendor=false) const
Definition Item.cpp:2234
bool IsEquipped() const
Definition Item.cpp:1336
void SendTimeUpdate(Player *owner)
Definition Item.cpp:1709
Optional< uint16 > GetDisenchantSkillRequired() const
Definition Item.cpp:2428
virtual bool Create(ObjectGuid::LowType guidlow, uint32 itemId, ItemContext context, Player const *owner)
Definition Item.cpp:510
void SetSpellCharges(ItemEffectEntry const *effect, int32 value)
Definition Item.cpp:632
BonusData const * GetBonus() const
Definition Item.h:201
void SetItemRandomBonusList(ItemRandomBonusListId bonusListId)
Definition Item.cpp:1250
Player * GetOwner() const
Definition Item.cpp:1238
bool IsValidTransmogrificationTarget() const
Definition Item.cpp:1995
ObjectGuid GetOwnerGUID() const
Definition Item.h:203
uint32 GetAppearanceModId() const
Definition Item.h:360
uint32 GetDisplayId(Player const *owner) const
Definition Item.cpp:2480
BonusData _bonusData
Definition Item.h:467
uint64 GetPaidMoney() const
Definition Item.h:380
bool HasEnchantRequiredSkill(Player const *player) const
Definition Item.cpp:1422
int32 GetVisibleSecondaryModifiedAppearanceId(Player const *owner) const
Definition Item.cpp:2584
uint32 GetSkill()
Definition Item.cpp:1244
bool IsRefundable() const
Definition Item.h:264
uint16 GetPos() const
Definition Item.h:300
Optional< uint32 > GetDisenchantLootId() const
Definition Item.cpp:2410
ItemModifiedAppearanceEntry const * GetItemModifiedAppearance() const
Definition Item.cpp:2497
float GetItemStatValue(uint32 index, Player const *owner) const
Definition Item.cpp:2385
bool GemsFitSockets() const
Definition Item.cpp:1634
bool IsBoundByEnchant() const
Definition Item.cpp:1448
void SetSoulboundTradeable(GuidSet const &allowedLooters)
Definition Item.cpp:1963
int16 uQueuePos
Definition Item.h:474
void SetContainedIn(ObjectGuid guid)
Definition Item.h:206
uint32 GetVisibleEntry(Player const *owner) const
Definition Item.cpp:2547
ObjectGuid GetGiftCreator() const
Definition Item.h:209
void CheckArtifactRelicSlotUnlock(Player const *owner)
Definition Item.cpp:1164
void BuildValuesUpdateWithFlag(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const override
Definition Item.cpp:1824
UF::ArtifactPower const * GetArtifactPower(uint32 artifactPowerId) const
Definition Item.cpp:2666
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
Definition Item.cpp:1549
void SetMaxDurability(uint32 maxDurability)
Definition Item.h:275
uint32 GetVisibleModifiedAppearanceId(Player const *owner) const
Definition Item.cpp:2571
bool IsArtifactDisabled() const
Definition Item.cpp:2650
UF::UpdateFieldFlag GetUpdateFieldFlagsFor(Player const *target) const final
Definition Item.cpp:1799
uint32 GetTotalUnlockedArtifactPowers() const
Definition Item.cpp:2720
uint32 m_paidExtendedCost
Definition Item.h:478
bool IsBag() const
Definition Item.h:268
void RemoveFromObjectUpdate() override
Definition Item.cpp:1894
void ClearEnchantment(EnchantmentSlot slot)
Definition Item.cpp:1558
uint32 GetPlayedTime() const
Definition Item.cpp:1953
bool IsRefundExpired() const
Definition Item.cpp:1958
void SetArtifactXP(uint64 xp)
Definition Item.h:453
std::unique_ptr< Loot > m_loot
Definition Item.h:334
void SetCreator(ObjectGuid guid)
Definition Item.h:208
uint32 GetItemLevel(Player const *owner) const
Definition Item.cpp:2283
ObjectGuid const & GetRefundRecipient() const
Definition Item.h:379
void SetCreatePlayedTime(uint32 createPlayedTime)
Definition Item.h:327
void SendUpdateSockets()
Definition Item.cpp:1699
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player *owner)
Definition Item.cpp:1539
InventoryResult CanBeMergedPartlyWith(ItemTemplate const *proto) const
Definition Item.cpp:1460
void SetPaidExtendedCost(uint32 iece)
Definition Item.h:377
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const
Definition Item.h:316
void SetBonuses(std::vector< int32 > bonusListIDs)
Definition Item.cpp:2628
void SetAppearanceModId(uint32 appearanceModId)
Definition Item.h:361
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
Definition Item.cpp:565
void SetRefundRecipient(ObjectGuid const &guid)
Definition Item.h:375
void BuildValuesUpdate(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const override
Definition Item.cpp:1813
uint8 GetGemCountWithLimitCategory(uint32 limitCategory) const
Definition Item.cpp:1674
void ClearSoulboundTradeable(Player *currentOwner)
Definition Item.cpp:1969
bool IsNotEmptyBag() const
Definition Item.cpp:576
virtual bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field *fields, uint32 entry)
Definition Item.cpp:907
bool m_lootGenerated
Definition Item.h:335
uint32 GetCount() const
Definition Item.h:289
void SetExpiration(uint32 expiration)
Definition Item.h:213
bool CheckSoulboundTradeExpire()
Definition Item.cpp:1983
void SetOwnerGUID(ObjectGuid guid)
Definition Item.h:204
AzeriteEmpoweredItem * ToAzeriteEmpoweredItem()
Definition Item.h:261
float GetRepairCostMultiplier() const
Definition Item.h:364
uint16 GetVisibleItemVisual(Player const *owner) const
Definition Item.cpp:2605
void BuildValuesCreate(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const override
Definition Item.cpp:1807
uint16 GetVisibleAppearanceModId(Player const *owner) const
Definition Item.cpp:2559
uint8 GetBagSlot() const
Definition Item.cpp:1331
void SetGiftCreator(ObjectGuid guid)
Definition Item.h:210
uint32 GetModifier(ItemModifier modifier) const
Definition Item.cpp:2502
void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid caster=ObjectGuid::Empty)
Definition Item.cpp:1511
static void DeleteFromDB(CharacterDatabaseTransaction trans, ObjectGuid::LowType itemGuid)
Definition Item.cpp:1180
void AddArtifactPower(ArtifactPowerData const *artifactPower)
Definition Item.cpp:2675
uint32 GetTotalPurchasedArtifactPowers() const
Definition Item.cpp:2743
uint8 m_slot
Definition Item.h:471
uint64 CalculateDurabilityRepairCost(float discount, bool useRateConfig=true) const
Definition Item.cpp:1383
void CopyArtifactDataFromParent(Item *parent)
Definition Item.cpp:2840
friend void AddItemToUpdateQueueOf(Item *item, Player *player)
Definition Item.cpp:1289
bool IsInUpdateQueue() const
Definition Item.h:341
int32 GetRequiredLevel() const
Definition Item.cpp:2896
static Item * CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const *player=nullptr, bool addDefaultBonuses=true)
Definition Item.cpp:1721
void LoadArtifactData(Player const *owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector< ArtifactPowerData > &powers)
Definition Item.cpp:1098
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition Item.cpp:1477
GuidSet allowedGUIDs
Definition Item.h:479
int32 GetSpellCharges(ItemEffectEntry const *effect=nullptr) const
Definition Item.cpp:623
ItemUpdateState uState
Definition Item.h:473
LowType GetCounter() const
Definition ObjectGuid.h:336
static ObjectGuid const Empty
Definition ObjectGuid.h:314
bool IsEmpty() const
Definition ObjectGuid.h:362
std::string ToString() const
uint64 LowType
Definition ObjectGuid.h:321
std::string GetDebugInfo() const override
Definition Object.cpp:160
uint32 GetEntry() const
Definition Object.h:89
void BuildEntityFragmentsForValuesUpdateForPlayerWithMask(ByteBuffer &data, EnumFlag< UF::UpdateFieldFlag > flags) const
Definition Object.cpp:113
void SetEntry(uint32 entry)
Definition Object.h:90
virtual void ClearValuesChangesMask()
Definition Object.cpp:130
virtual void SetObjectScale(float scale)
Definition Object.h:93
UF::UpdateField< UF::ObjectData, int32(WowCS::EntityFragment::CGObject), TYPEID_OBJECT > m_objectData
Definition Object.h:161
ChrSpecialization GetPrimarySpecialization() const
Definition Player.h:1993
UF::UpdateField< UF::PlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_PLAYER > m_playerData
Definition Player.h:3047
std::vector< Item * > m_itemUpdateQueue
Definition Player.h:3210
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6193
uint16 GetSkillValue(uint32 skill) const
Definition Player.cpp:5920
bool MeetPlayerCondition(uint32 conditionId) const
Definition Player.cpp:30226
WorldSession * GetSession() const
Definition Player.h:2256
void DestroyItem(uint8 bag, uint8 slot, bool update)
Definition Player.cpp:12039
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition Player.cpp:27532
bool IsUsingPvpItemLevels() const
Definition Player.h:2739
std::vector< ItemSetEffect * > ItemSetEff
Definition Player.h:2557
static bool IsBagPos(uint16 pos)
Definition Player.cpp:9691
uint8 GetActiveTalentGroup() const
Definition Player.h:1995
void ApplyEquipSpell(SpellInfo const *spellInfo, Item *item, bool apply, bool formChange=false)
Definition Player.cpp:8333
void DeleteRefundReference(ObjectGuid it)
Definition Player.cpp:29503
void ApplyArtifactPowerRank(Item *artifact, ArtifactPowerRankEntry const *artifactPowerRank, bool apply)
Definition Player.cpp:8432
bool m_itemUpdateQueueBlocked
Definition Player.h:3211
void setUInt16(uint8 index, uint16 value)
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setInt64(uint8 index, int64 value)
void setUInt64(uint8 index, uint64 value)
void setUInt8(uint8 index, uint8 value)
int32 EquippedItemClass
Definition SpellInfo.h:402
int32 EquippedItemSubClassMask
Definition SpellInfo.h:403
int32 EquippedItemInventoryTypeMask
Definition SpellInfo.h:404
bool HasEffect(SpellEffects effect) const
Mask const & GetChangesMask() const
MutableFieldReference< T, false > ModifyValue(UpdateField< T, BlockBit, Bit >(Derived::*field))
void ClearChangesMask(UpdateField< T, BlockBit, Bit >(Derived::*field))
bool HasChanged(uint32 index) const
Definition BaseEntity.h:83
uint32 GetChangedObjectTypeMask() const
Definition BaseEntity.h:81
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1897
uint8 GetLevel() const
Definition Unit.h:769
bool BuildPacket(WorldPacket *packet)
void AddUpdateBlock()
Definition UpdateData.h:46
constexpr uint32 GetBlock(uint32 index) const
Definition UpdateMask.h:59
constexpr void Set(uint32 index)
Definition UpdateMask.h:91
constexpr uint32 GetMapId() const
Definition Position.h:216
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
CollectionMgr * GetCollectionMgr() const
void SendEnchantmentLog(ObjectGuid owner, ObjectGuid caster, ObjectGuid itemGuid, uint32 itemId, uint32 enchantId, uint32 enchantSlot)
#define sWorld
Definition World.h:919
@ RATE_REPAIRCOST
Definition World.h:486
uint32 GetMinorMajorBugfixVersionForBuild(uint32 build)
time_t GetGameTime()
Definition GameTime.cpp:52
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 &)
ItemModifiedAppearanceEntry const * GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition Util.cpp:57
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
UpdateFieldFlag
Definition UpdateField.h:37
struct advstd::ranges::Contains contains
uint32 ArtifactPowerId
Definition Item.h:131
uint8 CurrentRankWithBonus
Definition Item.h:133
uint8 PurchasedRank
Definition Item.h:132
int32 RequiredLevel
Definition Item.h:65
int32 RequiredLevelOverride
Definition Item.h:80
std::array< ItemEffectEntry const *, 13 > Effects
Definition Item.h:92
int16 PvpItemLevelBonus
Definition Item.h:85
void AddBonus(uint32 type, std::array< int32, 4 > const &values)
Definition Item.cpp:3018
std::size_t EffectCount
Definition Item.h:93
uint32 DisenchantLootId
Definition Item.h:75
bool CanDisenchant
Definition Item.h:95
int32 RelicType
Definition Item.h:79
uint32 PlayerLevelToItemLevelCurveId
Definition Item.h:74
uint32 ItemSquishEraID
Definition Item.h:89
int32 GemRelicType[MAX_ITEM_PROTO_SOCKETS]
Definition Item.h:77
uint32 AppearanceModID
Definition Item.h:71
int32 ItemLevelOffset
Definition Item.h:88
bool RestrictScalingToContentTuning
Definition Item.h:102
bool IgnoreSquish
Definition Item.h:101
uint32 ItemLevelOffsetCurveId
Definition Item.h:86
int32 ItemLevelBonus
Definition Item.h:64
int32 StatPercentEditor[MAX_ITEM_PROTO_STATS]
Definition Item.h:67
uint32 Suffix
Definition Item.h:82
bool HasFixedLevel
Definition Item.h:99
bool ScalingConfigUsesPlayerLevel
Definition Item.h:103
uint16 PvpItemLevel
Definition Item.h:84
void AddBonusList(uint32 bonusListId)
Definition Item.cpp:3012
uint32 GemItemLevelBonus[MAX_ITEM_PROTO_SOCKETS]
Definition Item.h:76
int32 ScalingConfigItemLevelBonus
Definition Item.h:91
uint32 ItemLevelOffsetItemLevel
Definition Item.h:87
uint32 ItemLevel
Definition Item.h:63
float ItemStatSocketCostMultiplier[MAX_ITEM_PROTO_STATS]
Definition Item.h:68
uint32 ContentTuningId
Definition Item.h:73
int32 ScalingConfigCraftingQualityItemLevelBonus
Definition Item.h:90
void Initialize(ItemTemplate const *proto)
Definition Item.cpp:2918
int32 RequiredLevelCurve
Definition Item.h:83
std::array< uint16, 8 > ArmorSubClassCost
std::array< uint16, 21 > WeaponSubClassCost
Optional< ArtifactData > Artifact
Definition Item.h:170
Optional< AzeriteEmpoweredItemData > AzeriteEmpoweredItem
Definition Item.h:172
static void Init(std::unordered_map< ObjectGuid::LowType, ItemAdditionalLoadInfo > *loadInfo, PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult, PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult, PreparedQueryResult azeriteEmpoweredItemResult)
Definition Item.cpp:352
Optional< AzeriteItemData > AzeriteItem
Definition Item.h:171
uint16 BonusListIDs[16]
Definition Item.h:178
std::unordered_set< ItemSetSpellEntry const * > SetBonuses
Definition Item.cpp:73
std::unordered_set< Item const * > EquippedItems
Definition Item.cpp:72
uint32 ItemSetID
Definition Item.cpp:71
uint16 RequiredSkillRank
uint32 RequiredSkill
uint32 GetBaseItemLevel() const
uint32 GetArea(uint32 index) const
uint32 GetQuality() const
int32 GetStatModifierBonusStat(uint32 index) const
uint32 GetDuration() const
uint32 GetBuyCount() const
float GetPriceRandomValue() const
TransmogOutfitSlotOption GetWeaponTransmogOutfitSlotOption() const
uint32 GetGemProperties() const
uint32 GetId() const
uint32 GetMaxStackSize() const
InventoryType GetInventoryType() const
SocketColor GetSocketColor(uint32 index) const
uint32 GetBuyPrice() const
ItemBondingType GetBonding() const
uint32 GetItemSet() const
float GetStatPercentageOfSocket(uint32 index) const
uint32 GetScalingStatContentTuning() const
uint32 GetItemLevelOffsetItemLevel() const
uint8 GetArtifactID() const
uint32 GetMap() const
std::vector< ItemEffectEntry const * > Effects
bool IsCraftingReagent() const
uint32 GetItemSquishEraId() const
uint32 GetItemLimitCategory() const
int32 GetBaseRequiredLevel() const
uint32 GetItemLevelOffsetCurveId() const
bool HasFlag(ItemFlags flag) const
uint32 GetSubClass() const
uint32 GetSellPrice() const
uint32 MaxDurability
char const * GetName(LocaleConstant locale) const
uint8 GetRequiredExpansion() const
int32 GetStatPercentEditor(uint32 index) const
uint32 GetClass() const
float GetPriceVariance() const
uint32 GetPlayerLevelToItemLevelCurveId() const
uint32 GetSkill() const
uint32 GetBagFamily() const
void operator()(Player const *player) const
Definition Item.cpp:1866
UF::ObjectData::Base ObjectMask
Definition Item.h:409
EnumFlag< SpellItemEnchantmentFlags > GetFlags() const
static void AppendAllowedFieldsMaskForFlag(Mask &allowedMaskForTarget, EnumFlag< UpdateFieldFlag > fieldVisibilityFlags)
UpdateFieldArray< UF::ItemEnchantment, 13, 27, 28 > Enchantment
static void FilterDisallowedFieldsMaskForFlag(Mask &changesMask, EnumFlag< UpdateFieldFlag > fieldVisibilityFlags)
UpdateField< UF::ItemModList, 0, 17 > Modifiers
DynamicUpdateField< UF::SocketedGem, 0, 2 > Gems
UpdateField< WorldPackets::Item::ItemBonusKey, 0, 19 > ItemBonusKey
UpdateField< uint32, 0, 11 > MaxDurability
UpdateFieldArray< int32, 5, 21, 22 > SpellCharges
UpdateField< uint8, 0, 16 > ItemAppearanceModID
UpdateField< uint64, 0, 15 > ArtifactXP
UpdateField< uint32, 0, 7 > StackCount
DynamicUpdateField< UF::ArtifactPower, 0, 1 > ArtifactPowers
UpdateField< int16, 0, 3 > Charges
UpdateField< int32, 0, 1 > ID
UpdateField< uint16, 0, 4 > Inactive
UpdateField< uint32, 0, 2 > Duration
DynamicUpdateField< UF::ItemMod, -1, 0 > Values
UpdateFieldArray< uint16, 16, 3, 4 > BonusListIDs
UpdateField< uint8, 0, 2 > Context
UpdateField< int32, 0, 1 > ItemID
Optional< ItemBonuses > ItemBonus
void Add(EntityFragment fragment, bool update, void const *data=nullptr)