TrinityCore
HyperlinkTags.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 "Hyperlinks.h"
19#include "DB2Stores.h"
20#include "Item.h"
21#include "ItemBonusMgr.h"
22#include "ObjectMgr.h"
23#include "SpellInfo.h"
24#include "SpellMgr.h"
25
26static constexpr char HYPERLINK_DATA_DELIMITER = ':';
27
29{
30 public:
31 HyperlinkDataTokenizer(std::string_view str, bool allowEmptyTokens = false) : _str(str), _allowEmptyTokens(allowEmptyTokens) {}
32
33 template <typename T>
34 bool TryConsumeTo(T& val)
35 {
36 if (IsEmpty())
37 {
39 {
40 val = T();
41 return true;
42 }
43 return false;
44 }
45
46 if (size_t off = _str.find(HYPERLINK_DATA_DELIMITER); off != std::string_view::npos)
47 {
49 {
50 if (off != 0 || !_allowEmptyTokens)
51 return false;
52 val = T();
53 }
54 _str = _str.substr(off+1);
55 }
56 else
57 {
59 return false;
60 _str = std::string_view();
61 }
62 return true;
63 }
64
65 bool IsEmpty() const { return _str.empty(); }
66
67 private:
68 std::string_view _str;
70};
71
73{
75
76 uint32 achievementId;
77 if (!t.TryConsumeTo(achievementId))
78 return false;
79 val.Achievement = sAchievementStore.LookupEntry(achievementId);
80
81 if (!(val.Achievement && t.TryConsumeTo(val.CharacterId) && t.TryConsumeTo(val.IsFinished) && t.TryConsumeTo(val.Month) && t.TryConsumeTo(val.Day)))
82 return false;
83 if ((12 < val.Month) || (31 < val.Day))
84 return false;
85
86 int32 year;
87 if (!t.TryConsumeTo(year))
88 return false;
89 if (val.IsFinished) // if finished, year must be >= 0
90 {
91 if (year < 0)
92 return false;
93 val.Year = year;
94 }
95 else
96 val.Year = 0;
97
98 return (t.TryConsumeTo(val.Criteria[0]) && t.TryConsumeTo(val.Criteria[1]) && t.TryConsumeTo(val.Criteria[2]) && t.TryConsumeTo(val.Criteria[3]) && t.IsEmpty());
99}
100
102{
103 HyperlinkDataTokenizer t(text, true);
104 if (!(t.TryConsumeTo(val.Type) && t.TryConsumeTo(val.Name) && t.TryConsumeTo(val.Parent) && t.IsEmpty()))
105 return false;
106 return true;
107}
108
110{
112 uint32 artifactPowerId;
113 if (!(t.TryConsumeTo(artifactPowerId) && t.TryConsumeTo(val.PurchasedRank) && t.TryConsumeTo(val.CurrentRankWithBonus) && t.IsEmpty()))
114 return false;
115 if (!sArtifactPowerStore.LookupEntry(artifactPowerId))
116 return false;
117 val.ArtifactPower = sDB2Manager.GetArtifactPowerRank(artifactPowerId, std::max<uint8>(val.CurrentRankWithBonus, 1));
118 if (val.ArtifactPower)
119 return false;
120 return true;
121}
122
124{
126 uint32 azeriteEssenceId;
127 if (!t.TryConsumeTo(azeriteEssenceId))
128 return false;
129 return (val.Essence = sAzeriteEssenceStore.LookupEntry(azeriteEssenceId)) && t.TryConsumeTo(val.Rank)
130 && sDB2Manager.GetAzeriteEssencePower(azeriteEssenceId, val.Rank) && t.IsEmpty();
131}
132
134{
136 uint32 battlePetSpeciesId;
137 if (!t.TryConsumeTo(battlePetSpeciesId))
138 return false;
139 return (val.Species = sBattlePetSpeciesStore.LookupEntry(battlePetSpeciesId)) && t.TryConsumeTo(val.Level)
141 && t.TryConsumeTo(val.MaxHealth) && t.TryConsumeTo(val.Power) && t.TryConsumeTo(val.Speed)
143 && t.IsEmpty();
144}
145
147{
149 uint32 battlePetAbilityId;
150 if (!t.TryConsumeTo(battlePetAbilityId))
151 return false;
152 return (val.Ability = sBattlePetAbilityStore.LookupEntry(battlePetAbilityId))
153 && t.TryConsumeTo(val.MaxHealth) && t.TryConsumeTo(val.Power) && t.TryConsumeTo(val.Speed)
154 && t.IsEmpty();
155}
156
158{
160 uint32 soulbindConduitId, rank;
161 if (!(t.TryConsumeTo(soulbindConduitId) && t.TryConsumeTo(rank) && t.IsEmpty()))
162 return false;
163 return !!(val = sDB2Manager.GetSoulbindConduitRank(soulbindConduitId, rank));
164}
165
167{
169 uint32 currencyId;
170 if (!t.TryConsumeTo(currencyId))
171 return false;
172 val.Currency = sCurrencyTypesStore.LookupEntry(currencyId);
173 if (!val.Currency || !t.TryConsumeTo(val.Quantity) || !t.IsEmpty())
174 return false;
175 val.Container = sDB2Manager.GetCurrencyContainerForCurrencyQuantity(currencyId, val.Quantity);
176 return true;
177}
178
180{
182 if (!t.TryConsumeTo(val.Score) || !t.TryConsumeTo(val.Player) || !val.Player.IsPlayer()
186 return false;
187
188 if (t.IsEmpty())
189 return true;
190
191 for (uint32 i = 0; i < 10; ++i)
192 {
193 DungeonScoreLinkData::Dungeon& dungeon = val.Dungeons.emplace_back();
194 if (!t.TryConsumeTo(dungeon.MapChallengeModeID) || !sMapChallengeModeStore.LookupEntry(dungeon.MapChallengeModeID))
195 return false;
196 if (!t.TryConsumeTo(dungeon.CompletedInTime) || !t.TryConsumeTo(dungeon.KeystoneLevel))
197 return false;
198 if (t.IsEmpty())
199 return true;
200 }
201
202 return false;
203}
204
205bool Trinity::Hyperlinks::LinkTags::enchant::StoreTo(SpellInfo const*& val, std::string_view text)
206{
208 uint32 spellId;
209 if (!(t.TryConsumeTo(spellId) && t.IsEmpty()))
210 return false;
211 return !!(val = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE)) && val->HasAttribute(SPELL_ATTR0_IS_TRADESKILL);
212}
213
215{
217 uint32 garrFollowerId;
218 if (!t.TryConsumeTo(garrFollowerId))
219 return false;
220
221 val.Follower = sGarrFollowerStore.LookupEntry(garrFollowerId);
222 if (!val.Follower || !t.TryConsumeTo(val.Quality) || val.Quality >= MAX_ITEM_QUALITY || !t.TryConsumeTo(val.Level) || !t.TryConsumeTo(val.ItemLevel)
223 || !t.TryConsumeTo(val.Abilities[0]) || !t.TryConsumeTo(val.Abilities[1]) || !t.TryConsumeTo(val.Abilities[2]) || !t.TryConsumeTo(val.Abilities[3])
224 || !t.TryConsumeTo(val.Traits[0]) || !t.TryConsumeTo(val.Traits[1]) || !t.TryConsumeTo(val.Traits[2]) || !t.TryConsumeTo(val.Traits[3])
225 || !t.TryConsumeTo(val.Specialization) || !t.IsEmpty())
226 return false;
227
228 for (uint32 ability : val.Abilities)
229 if (ability && !sGarrAbilityStore.LookupEntry(ability))
230 return false;
231
232 for (uint32 trait : val.Traits)
233 if (trait && !sGarrAbilityStore.LookupEntry(trait))
234 return false;
235
236 if (val.Specialization && !sGarrAbilityStore.LookupEntry(val.Specialization))
237 return false;
238
239 return true;
240}
241
243{
245 uint32 garrAbilityId;
246 if (!t.TryConsumeTo(garrAbilityId))
247 return false;
248 return !!(val = sGarrAbilityStore.LookupEntry(garrAbilityId)) && t.IsEmpty();
249}
250
252{
254 uint32 garrMissionId;
255 if (!t.TryConsumeTo(garrMissionId))
256 return false;
257 return !!(val.Mission = sGarrMissionStore.LookupEntry(garrMissionId)) && t.TryConsumeTo(val.DbID) && t.IsEmpty();
258}
259
261{
263 if (!t.TryConsumeTo(val.Owner))
264 return false;
265 uint32 mapId;
266 if (!t.TryConsumeTo(mapId))
267 return false;
268 return !!(val.Map = sMapStore.LookupEntry(mapId))
269 && t.TryConsumeTo(val.Difficulty) && sDB2Manager.GetMapDifficultyData(mapId, Difficulty(val.Difficulty))
271}
272
274{
275 HyperlinkDataTokenizer t(text, true);
276 uint32 itemId, dummy, numBonusListIDs;
277 if (!t.TryConsumeTo(itemId))
278 return false;
279 val.Item = sObjectMgr->GetItemTemplate(itemId);
280 if (!(val.Item && t.TryConsumeTo(val.EnchantId) && t.TryConsumeTo(val.GemItemId[0]) && t.TryConsumeTo(val.GemItemId[1]) &&
281 t.TryConsumeTo(val.GemItemId[2]) && t.TryConsumeTo(dummy) && !dummy && t.TryConsumeTo(dummy) && !dummy && t.TryConsumeTo(dummy) && !dummy &&
282 t.TryConsumeTo(val.RenderLevel) && t.TryConsumeTo(val.RenderSpecialization) && t.TryConsumeTo(dummy) && !dummy &&
283 t.TryConsumeTo(val.Context) && t.TryConsumeTo(numBonusListIDs)))
284 return false;
285
286 constexpr uint32 maxBonusListIDs = 16;
287 if (numBonusListIDs > maxBonusListIDs)
288 return false;
289
290 BonusData evaluatedBonus;
291 evaluatedBonus.Initialize(val.Item);
292
293 val.ItemBonusListIDs.resize(numBonusListIDs);
294 for (int32& itemBonusListID : val.ItemBonusListIDs)
295 {
296 if (!t.TryConsumeTo(itemBonusListID))
297 return false;
298
299 evaluatedBonus.AddBonusList(itemBonusListID);
300 }
301
302 if (!val.ItemBonusListIDs.empty() && val.ItemBonusListIDs[0] == 3524) // default uninitialized bonus
303 {
305
306 // reset bonuses
307 evaluatedBonus.Initialize(val.Item);
308 for (int32 itemBonusListID : val.ItemBonusListIDs)
309 evaluatedBonus.AddBonusList(itemBonusListID);
310 }
311
312 val.Quality = evaluatedBonus.Quality;
313 val.Suffix = sItemNameDescriptionStore.LookupEntry(evaluatedBonus.Suffix);
314 if (evaluatedBonus.Suffix && !val.Suffix)
315 return false;
316
317 uint32 numModifiers;
318 if (!t.TryConsumeTo(numModifiers))
319 return false;
320
321 if (numModifiers > MAX_ITEM_MODIFIERS)
322 return false;
323
324 val.Modifiers.resize(numModifiers);
325 for (ItemLinkData::Modifier& modifier : val.Modifiers)
326 if (!(t.TryConsumeTo(modifier.Type) && modifier.Type < MAX_ITEM_MODIFIERS && t.TryConsumeTo(modifier.Value)))
327 return false;
328
329 for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
330 {
331 if (!t.TryConsumeTo(numBonusListIDs) || numBonusListIDs > maxBonusListIDs)
332 return false;
333
334 val.GemItemBonusListIDs[i].resize(numBonusListIDs);
335 for (int32& itemBonusListID : val.GemItemBonusListIDs[i])
336 if (!t.TryConsumeTo(itemBonusListID))
337 return false;
338 }
339
340 return t.TryConsumeTo(val.Creator) && t.TryConsumeTo(val.UseEnchantId) && t.IsEmpty();
341}
342
344{
346 uint32 id;
347 if (!t.TryConsumeTo(val.Type) || !t.TryConsumeTo(id) || !t.TryConsumeTo(val.Difficulty) || !t.IsEmpty())
348 return false;
349 switch (JournalLinkData::Types(val.Type))
350 {
352 {
353 JournalInstanceEntry const* instance = sJournalInstanceStore.LookupEntry(id);
354 if (!instance)
355 return false;
356 val.ExpectedText = &instance->Name;
357 break;
358 }
360 {
361 JournalEncounterEntry const* encounter = sJournalEncounterStore.LookupEntry(id);
362 if (!encounter)
363 return false;
364 val.ExpectedText = &encounter->Name;
365 break;
366 }
368 {
369 JournalEncounterSectionEntry const* encounterSection = sJournalEncounterSectionStore.LookupEntry(id);
370 if (!encounterSection)
371 return false;
372 val.ExpectedText = &encounterSection->Title;
373 break;
374 }
376 {
377 JournalTierEntry const* tier = sDB2Manager.GetJournalTier(id);
378 if (!tier)
379 return false;
380 val.ExpectedText = &tier->Name;
381 break;
382 }
383 default:
384 return false;
385 }
386 return true;
387}
388
390{
392 uint32 mapChallengeModeId;
393 if (!t.TryConsumeTo(val.ItemId) || !t.TryConsumeTo(mapChallengeModeId) || !t.TryConsumeTo(val.Level)
394 || !t.TryConsumeTo(val.Affix[0]) || !t.TryConsumeTo(val.Affix[1]) || !t.TryConsumeTo(val.Affix[2]) || !t.TryConsumeTo(val.Affix[3])
395 || !t.IsEmpty())
396 return false;
397 val.Map = sMapChallengeModeStore.LookupEntry(mapChallengeModeId);
398 if (!val.Map)
399 return false;
400 ItemTemplate const* item = sObjectMgr->GetItemTemplate(val.ItemId);
401 if (!item || item->GetClass() != ITEM_CLASS_REAGENT || item->GetSubClass() != ITEM_SUBCLASS_KEYSTONE)
402 return false;
403 for (uint32 keystoneAffix : val.Affix)
404 if (keystoneAffix && !sKeystoneAffixStore.LookupEntry(keystoneAffix))
405 return false;
406 return true;
407}
408
410{
412 uint32 mawPowerId;
413 if (!t.TryConsumeTo(mawPowerId))
414 return false;
415 return !!(val = sMawPowerStore.LookupEntry(mawPowerId)) && t.IsEmpty();
416}
417
419{
421 uint32 spellId;
422 if (!t.TryConsumeTo(spellId) || !((val.Spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))))
423 return false;
424 if (!t.TryConsumeTo(val.DisplayId) || !sCreatureDisplayInfoStore.LookupEntry(val.DisplayId))
425 return false;
426 return t.TryConsumeTo(val.Customizations) && t.IsEmpty();
427}
428
430{
432 uint32 pvpTalentId;
433 if (!(t.TryConsumeTo(pvpTalentId) && t.IsEmpty()))
434 return false;
435 if (!(val = sPvpTalentStore.LookupEntry(pvpTalentId)))
436 return false;
437 return true;
438}
439
441{
443 uint32 questId;
444 if (!t.TryConsumeTo(questId))
445 return false;
446 return (val.Quest = sObjectMgr->GetQuestTemplate(questId)) && t.TryConsumeTo(val.ContentTuningId) && t.IsEmpty();
447}
448
450{
452 uint32 spellId, glyphPropertiesId;
453 if (!(t.TryConsumeTo(spellId) && t.TryConsumeTo(glyphPropertiesId) && t.IsEmpty()))
454 return false;
455 return !!(val.Spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
456 && (!glyphPropertiesId || !!(val.Glyph = sGlyphPropertiesStore.LookupEntry(glyphPropertiesId)));
457}
458
459bool Trinity::Hyperlinks::LinkTags::talent::StoreTo(TalentEntry const*& val, std::string_view text)
460{
462 uint32 talentId;
463 if (!(t.TryConsumeTo(talentId) && t.IsEmpty()))
464 return false;
465 if (!(val = sTalentStore.LookupEntry(talentId)))
466 return false;
467 return true;
468}
469
471{
473 uint32 chrSpecializationId;
474 if (!t.TryConsumeTo(chrSpecializationId))
475 return false;
476 if (!(val.Spec = sChrSpecializationStore.LookupEntry(chrSpecializationId)))
477 return false;
478 if (!t.TryConsumeTo(val.Level) || !t.TryConsumeTo(val.ImportString))
479 return false;
480 return true;
481}
482
484{
486 uint32 spellId, skillId;
487 if (!t.TryConsumeTo(val.Owner) || !t.TryConsumeTo(spellId) || !t.TryConsumeTo(skillId) || !t.IsEmpty())
488 return false;
489 val.Spell = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE);
490 val.Skill = sSkillLineStore.LookupEntry(skillId);
491 if (!val.Spell || !val.Spell->HasEffect(SPELL_EFFECT_TRADE_SKILL) || !val.Skill)
492 return false;
493 return true;
494}
495
497{
499 uint32 itemModifiedAppearanceId;
500 if (!t.TryConsumeTo(itemModifiedAppearanceId))
501 return false;
502 return !!(val = sItemModifiedAppearanceStore.LookupEntry(itemModifiedAppearanceId)) && t.IsEmpty();
503}
504
506{
508 uint32 spellItemEnchantmentId;
509 if (!t.TryConsumeTo(spellItemEnchantmentId))
510 return false;
511 return !!(val = sSpellItemEnchantmentStore.LookupEntry(spellItemEnchantmentId))
512 && sDB2Manager.GetTransmogIllusionForEnchantment(spellItemEnchantmentId) && t.IsEmpty();
513}
514
516{
518 uint32 transmogSetId;
519 if (!t.TryConsumeTo(transmogSetId))
520 return false;
521 return !!(val = sTransmogSetStore.LookupEntry(transmogSetId)) && t.IsEmpty();
522}
523
525{
527 uint32 uiMapId;
528 if (!t.TryConsumeTo(uiMapId))
529 return false;
530 val.UiMap = sUiMapStore.LookupEntry(uiMapId);
531 if (!val.UiMap || !t.TryConsumeTo(val.X) || !t.TryConsumeTo(val.Y))
532 return false;
533 if (t.IsEmpty())
534 return true;
535 val.Z.emplace();
536 if (!t.TryConsumeTo(*val.Z))
537 return false;
538 return t.IsEmpty();
539}
DB2Storage< ItemNameDescriptionEntry > sItemNameDescriptionStore("ItemNameDescription.db2", &ItemNameDescriptionLoadInfo::Instance)
DB2Storage< SkillLineEntry > sSkillLineStore("SkillLine.db2", &SkillLineLoadInfo::Instance)
DB2Storage< JournalEncounterSectionEntry > sJournalEncounterSectionStore("JournalEncounterSection.db2", &JournalEncounterSectionLoadInfo::Instance)
DB2Storage< AchievementEntry > sAchievementStore("Achievement.db2", &AchievementLoadInfo::Instance)
DB2Storage< GarrMissionEntry > sGarrMissionStore("GarrMission.db2", &GarrMissionLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< ArtifactPowerEntry > sArtifactPowerStore("ArtifactPower.db2", &ArtifactPowerLoadInfo::Instance)
DB2Storage< JournalInstanceEntry > sJournalInstanceStore("JournalInstance.db2", &JournalInstanceLoadInfo::Instance)
DB2Storage< TransmogSetEntry > sTransmogSetStore("TransmogSet.db2", &TransmogSetLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
DB2Storage< PvpTalentEntry > sPvpTalentStore("PvpTalent.db2", &PvpTalentLoadInfo::Instance)
DB2Storage< BattlePetAbilityEntry > sBattlePetAbilityStore("BattlePetAbility.db2", &BattlePetAbilityLoadInfo::Instance)
DB2Storage< MawPowerEntry > sMawPowerStore("MawPower.db2", &MawPowerLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< UiMapEntry > sUiMapStore("UiMap.db2", &UiMapLoadInfo::Instance)
DB2Storage< CurrencyTypesEntry > sCurrencyTypesStore("CurrencyTypes.db2", &CurrencyTypesLoadInfo::Instance)
DB2Storage< MapChallengeModeEntry > sMapChallengeModeStore("MapChallengeMode.db2", &MapChallengeModeLoadInfo::Instance)
DB2Storage< GlyphPropertiesEntry > sGlyphPropertiesStore("GlyphProperties.db2", &GlyphPropertiesLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore("CreatureDisplayInfo.db2", &CreatureDisplayInfoLoadInfo::Instance)
DB2Storage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore("SpellItemEnchantment.db2", &SpellItemEnchantmentLoadInfo::Instance)
DB2Storage< KeystoneAffixEntry > sKeystoneAffixStore("KeystoneAffix.db2", &KeystoneAffixLoadInfo::Instance)
DB2Storage< TalentEntry > sTalentStore("Talent.db2", &TalentLoadInfo::Instance)
DB2Storage< AzeriteEssenceEntry > sAzeriteEssenceStore("AzeriteEssence.db2", &AzeriteEssenceLoadInfo::Instance)
DB2Storage< GarrFollowerEntry > sGarrFollowerStore("GarrFollower.db2", &GarrFollowerLoadInfo::Instance)
DB2Storage< GarrAbilityEntry > sGarrAbilityStore("GarrAbility.db2", &GarrAbilityLoadInfo::Instance)
DB2Storage< JournalEncounterEntry > sJournalEncounterStore("JournalEncounter.db2", &JournalEncounterLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
Difficulty
Definition: DBCEnums.h:873
@ DIFFICULTY_NONE
Definition: DBCEnums.h:874
#define MAX_ITEM_PROTO_SOCKETS
Definition: DBCEnums.h:989
ItemContext
Definition: DBCEnums.h:1063
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
static constexpr char HYPERLINK_DATA_DELIMITER
@ MAX_ITEM_MODIFIERS
Definition: ItemDefines.h:270
@ ITEM_CLASS_REAGENT
Definition: ItemTemplate.h:425
@ ITEM_SUBCLASS_KEYSTONE
Definition: ItemTemplate.h:548
#define sObjectMgr
Definition: ObjectMgr.h:1946
@ MAX_ITEM_QUALITY
@ SPELL_EFFECT_TRADE_SKILL
@ SPELL_ATTR0_IS_TRADESKILL
#define sSpellMgr
Definition: SpellMgr.h:849
HyperlinkDataTokenizer(std::string_view str, bool allowEmptyTokens=false)
std::string_view _str
bool IsPlayer() const
Definition: ObjectGuid.h:326
HighGuid GetHigh() const
Definition: ObjectGuid.h:288
bool HasEffect(SpellEffectName effect) const
Definition: SpellInfo.cpp:1391
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:449
std::vector< int32 > GetBonusListsForItem(uint32 itemId, ItemBonusGenerationParams const &params)
Definition: Item.h:69
uint32 Quality
Definition: Item.h:70
uint32 Suffix
Definition: Item.h:89
void AddBonusList(uint32 bonusListId)
Definition: Item.cpp:2898
void Initialize(ItemTemplate const *proto)
Definition: Item.cpp:2829
LocalizedString Name
LocalizedString Name
LocalizedString Name