TrinityCore
Loading...
Searching...
No Matches
TransmogMgr.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 "TransmogMgr.h"
19#include "DB2Stores.h"
20#include "FlatSet.h"
21#include "MapUtils.h"
22#include "ObjectMgr.h"
23#include "Player.h"
25#include "Util.h"
26
27namespace
28{
29struct TransmogOutfitSlotOptionInfo
30{
31 TransmogOutfitSlotOptionEntry const* Data = nullptr;
32 int32 SlotIndex = -1;
33};
34
35struct TransmogOutfitSlotInfo
36{
37 TransmogOutfitSlotInfoEntry const* Data = nullptr;
38 std::variant<int32, std::unique_ptr<TransmogOutfitSlotOptionInfo[]>> SlotIndexOrOptions;
39
40 int32 GetSlotIndex(TransmogOutfitSlotOption slotOption) const
41 {
42 switch (SlotIndexOrOptions.index())
43 {
44 case 0:
45 return std::get<0>(SlotIndexOrOptions);
46 case 1:
47 return std::get<1>(SlotIndexOrOptions)[AsUnderlyingType(slotOption)].SlotIndex;
48 default:
49 return -1;
50 }
51 }
52};
53
54std::unordered_map<std::pair<uint32 /*itemId*/, uint32 /*appearanceMod*/>, ItemModifiedAppearanceEntry const*> ItemModifiedAppearancesByItem;
55std::unordered_map<uint32, TransmogIllusionEntry const*> TransmogIllusionBySpellItemEnchantment;
56std::unordered_map<uint32, Trinity::Containers::FlatSet<TransmogSetEntry const*>> TransmogSetsByItemModifiedAppearance;
57std::vector<TransmogSetItemEntry const*> TransmogSetItemsByTransmogSet;
58std::array<std::vector<TransmogOutfitEntryEntry const*>, AsUnderlyingType(TransmogOutfitEntrySource::Max)> TransmogOutfitsBySource;
59std::vector<TransmogOutfitEntryEntry const*> TransmogOutfitsAutomaticallyCreated;
60std::vector<TransmogMgr::TransmogOutfitSlotAndOptionInfo> AllSlots;
61std::array<TransmogOutfitSlotInfo, AsUnderlyingType(TransmogOutfitSlot::Max)> SlotInfoByOutfitSlot;
62std::array<TransmogOutfitSlotInfo const*, EQUIPMENT_SLOT_END> SlotInfoByInvSlot;
63std::vector<TransmogSituationEntry const*> DefaultSituations;
64
66{
80};
81
82constexpr bool IsArtifactTransmogOutfitSlotOption(TransmogOutfitSlotOption option)
83{
88}
89
90bool IsValidTransmogOutfitSlotForItem(ItemTemplate const* item, TransmogOutfitSlot slot, TransmogOutfitSlotOption option)
91{
92 if (IsArtifactTransmogOutfitSlotOption(option))
93 if (ArtifactEntry const* artifact = sArtifactStore.LookupEntry(item->GetArtifactID()))
94 if (ChrSpecializationEntry const* specialization = sChrSpecializationStore.LookupEntry(artifact->ChrSpecializationID))
95 if ((int8(option) - int8(TransmogOutfitSlotOption::ArtifactSpecOne)) != specialization->OrderIndex)
96 return false;
97
98 switch (item->GetInventoryType())
99 {
100 case INVTYPE_HEAD:
101 return slot == TransmogOutfitSlot::Head;
104 case INVTYPE_BODY:
105 return slot == TransmogOutfitSlot::Body;
106 case INVTYPE_CHEST:
107 case INVTYPE_ROBE:
108 return slot == TransmogOutfitSlot::Chest;
109 case INVTYPE_WAIST:
110 return slot == TransmogOutfitSlot::Waist;
111 case INVTYPE_LEGS:
112 return slot == TransmogOutfitSlot::Legs;
113 case INVTYPE_FEET:
114 return slot == TransmogOutfitSlot::Feet;
115 case INVTYPE_WRISTS:
116 return slot == TransmogOutfitSlot::Wrist;
117 case INVTYPE_HANDS:
118 return slot == TransmogOutfitSlot::Hand;
119 case INVTYPE_WEAPON:
122 return slot == TransmogOutfitSlot::WeaponMainHand || slot == TransmogOutfitSlot::WeaponOffHand || IsArtifactTransmogOutfitSlotOption(option);
123 case INVTYPE_SHIELD:
124 case INVTYPE_HOLDABLE:
125 return slot == TransmogOutfitSlot::WeaponOffHand || IsArtifactTransmogOutfitSlotOption(option);
126 case INVTYPE_RANGED:
127 return (slot == TransmogOutfitSlot::WeaponMainHand && option == TransmogOutfitSlotOption::RangedWeapon) || IsArtifactTransmogOutfitSlotOption(option);
128 case INVTYPE_CLOAK:
129 return slot == TransmogOutfitSlot::Back;
130 case INVTYPE_2HWEAPON:
131 return slot == TransmogOutfitSlot::WeaponMainHand || (slot == TransmogOutfitSlot::WeaponOffHand && option == TransmogOutfitSlotOption::FuryTwoHandedWeapon) || IsArtifactTransmogOutfitSlotOption(option);
132 case INVTYPE_TABARD:
133 return slot == TransmogOutfitSlot::Tabard;
135 return slot == (item->GetSubClass() == ITEM_SUBCLASS_WEAPON_WAND ? TransmogOutfitSlot::WeaponMainHand : TransmogOutfitSlot::WeaponRanged) || IsArtifactTransmogOutfitSlotOption(option);
136 default:
137 break;
138 }
139 return false;
140}
141}
142
144{
146 ItemModifiedAppearancesByItem[{ appearanceMod->ItemID, appearanceMod->ItemAppearanceModifierID }] = appearanceMod;
147
148 for (TransmogIllusionEntry const* transmogIllusion : sTransmogIllusionStore)
149 TransmogIllusionBySpellItemEnchantment[transmogIllusion->SpellItemEnchantmentID] = transmogIllusion;
150
151 for (TransmogSetItemEntry const* transmogSetItem : sTransmogSetItemStore)
152 {
153 TransmogSetEntry const* set = sTransmogSetStore.LookupEntry(transmogSetItem->TransmogSetID);
154 if (!set)
155 continue;
156
157 TransmogSetsByItemModifiedAppearance[transmogSetItem->ItemModifiedAppearanceID].insert(set);
158 TransmogSetItemsByTransmogSet.push_back(transmogSetItem);
159 }
160
161 std::ranges::sort(TransmogSetItemsByTransmogSet, {}, &TransmogSetItemEntry::TransmogSetID);
162
163 for (TransmogOutfitEntryEntry const* transmogOutfitEntry : sTransmogOutfitEntryStore)
164 {
165 if (transmogOutfitEntry->HasFlag(TransmogOutfitEntryFlags::AutomaticallyAwardedOnLogin))
166 TransmogOutfitsAutomaticallyCreated.push_back(transmogOutfitEntry);
167
168 if (transmogOutfitEntry->GetSetType() == TransmogOutfitSetType::Outfit)
169 TransmogOutfitsBySource[AsUnderlyingType(transmogOutfitEntry->GetSource())].push_back(transmogOutfitEntry);
170 }
171
172 for (std::vector<TransmogOutfitEntryEntry const*>& transmogOutfitEntries : TransmogOutfitsBySource)
173 std::ranges::sort(transmogOutfitEntries, {}, &TransmogOutfitEntryEntry::OrderIndex);
174
175 for (TransmogOutfitSlotInfoEntry const* transmogOutfitSlot : sTransmogOutfitSlotInfoStore)
176 {
177 ASSERT(transmogOutfitSlot->GetSlot() < TransmogOutfitSlot::Max);
178
179 TransmogOutfitSlotInfo* slot = &SlotInfoByOutfitSlot[AsUnderlyingType(transmogOutfitSlot->GetSlot())];
180 slot->Data = transmogOutfitSlot;
181
182 if (!transmogOutfitSlot->HasFlag(TransmogOutfitSlotFlags::IsSecondarySlot))
183 {
184 ASSERT(transmogOutfitSlot->InventorySlotEnum < EQUIPMENT_SLOT_END);
185 SlotInfoByInvSlot[transmogOutfitSlot->InventorySlotEnum] = slot;
186 }
187 }
188
189 for (TransmogOutfitSlotOptionEntry const* transmogOutfitSlotOption : sTransmogOutfitSlotOptionInfoStore)
190 {
191 ASSERT(transmogOutfitSlotOption->GetOption() < TransmogOutfitSlotOption::Max);
192
193 TransmogOutfitSlotInfoEntry const* transmogOutfitSlot = sTransmogOutfitSlotInfoStore.AssertEntry(transmogOutfitSlotOption->TransmogOutfitSlotInfoID);
194
195 TransmogOutfitSlotInfo& slotInfo = SlotInfoByOutfitSlot[AsUnderlyingType(transmogOutfitSlot->GetSlot())];
196 if (!std::holds_alternative<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions))
197 slotInfo.SlotIndexOrOptions.emplace<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(new TransmogOutfitSlotOptionInfo[AsUnderlyingType(TransmogOutfitSlotOption::Max)]);
198
199 std::get<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions)[AsUnderlyingType(transmogOutfitSlotOption->GetOption())].Data = transmogOutfitSlotOption;
200 }
201
202 for (TransmogOutfitSlotInfo& slotInfo : SlotInfoByOutfitSlot)
203 {
204 if (!slotInfo.Data)
205 continue;
206
207 TransmogOutfitSlotAndOptionInfo& slot = AllSlots.emplace_back();
208 slot.Slot = slotInfo.Data;
209 slot.SlotIndex = AllSlots.size() - 1;
210
211 if (std::holds_alternative<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions))
212 {
213 // if slot has options, keep adding transmog slots for every option
214 auto options = std::span<TransmogOutfitSlotOptionInfo, AsUnderlyingType(TransmogOutfitSlotOption::Max)>(
215 &std::get<std::unique_ptr<TransmogOutfitSlotOptionInfo[]>>(slotInfo.SlotIndexOrOptions)[0],
217
218 auto optionItr = std::ranges::find_if(options,
219 [](TransmogOutfitSlotOptionEntry const* option) { return option != nullptr; },
220 &TransmogOutfitSlotOptionInfo::Data);
221
222 slot.SlotOption = optionItr->Data;
223 optionItr->SlotIndex = AllSlots.size() - 1;
224
225 while (++optionItr != options.end())
226 {
227 if (!optionItr->Data)
228 continue;
229
230 TransmogOutfitSlotAndOptionInfo& newSlot = AllSlots.emplace_back();
231 newSlot.Slot = slotInfo.Data;
232 newSlot.SlotOption = optionItr->Data;
233 newSlot.SlotIndex = AllSlots.size() - 1;
234 optionItr->SlotIndex = AllSlots.size() - 1;
235 }
236 }
237 if (std::holds_alternative<int32>(slotInfo.SlotIndexOrOptions))
238 std::get<int32>(slotInfo.SlotIndexOrOptions) = AllSlots.size() - 1;
239 }
240
241 for (TransmogSituationEntry const* transmogSituation : sTransmogSituationStore)
242 if (transmogSituation->HasFlag(TransmogSituationFlags::DefaultsToOn))
243 DefaultSituations.push_back(transmogSituation);
244}
245
247{
248 auto itr = ItemModifiedAppearancesByItem.find({ itemId, appearanceModId });
249 if (itr != ItemModifiedAppearancesByItem.end())
250 return itr->second;
251
252 // Fall back to unmodified appearance
253 if (appearanceModId)
255
256 return nullptr;
257}
258
260{
261 return Trinity::Containers::MapGetValuePtr(ItemModifiedAppearancesByItem, { itemId, 0 });
262}
263
265{
266 return Trinity::Containers::MapGetValuePtr(TransmogIllusionBySpellItemEnchantment, spellItemEnchantmentId);
267}
268
269std::span<TransmogSetEntry const* const> TransmogMgr::GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId)
270{
271 std::span<TransmogSetEntry const* const> result;
272 auto itr = TransmogSetsByItemModifiedAppearance.find(itemModifiedAppearanceId);
273 if (itr != TransmogSetsByItemModifiedAppearance.end())
274 result = itr->second;
275
276 return result;
277}
278
279std::span<TransmogSetItemEntry const* const> TransmogMgr::GetTransmogSetItems(uint32 transmogSetId)
280{
281 return std::ranges::equal_range(TransmogSetItemsByTransmogSet, transmogSetId, {}, &TransmogSetItemEntry::TransmogSetID);
282}
283
284std::span<TransmogOutfitEntryEntry const* const> TransmogMgr::GetAutomaticallyUnlockedOutfits()
285{
286 return TransmogOutfitsAutomaticallyCreated;
287}
288
289std::span<TransmogMgr::TransmogOutfitSlotAndOptionInfo const> TransmogMgr::GetAllSlots()
290{
291 return AllSlots;
292}
293
295{
296 int32 slotIndex = SlotInfoByOutfitSlot[AsUnderlyingType(slot)].GetSlotIndex(slotOption);
297 if (slotIndex >= 0)
298 return &AllSlots[slotIndex];
299
300 return nullptr;
301}
302
304{
305 if (TransmogOutfitSlotInfo const* slotInfo = SlotInfoByInvSlot[inventorySlot])
306 if (int32 slotIndex = slotInfo->GetSlotIndex(slotOption); slotIndex >= 0)
307 return &AllSlots[slotIndex];
308
309 return nullptr;
310}
311
312std::span<TransmogSituationEntry const* const> TransmogMgr::GetDefaultSituations()
313{
314 return DefaultSituations;
315}
316
318{
319 if (source >= TransmogOutfitEntrySource::Max)
320 return nullptr;
321
322 TransmogOutfitEntryEntry const* lastOwnedOutfit = nullptr;
323 for (auto const& [id, transmogOutfit] : player->m_activePlayerData->TransmogOutfits)
324 {
325 TransmogOutfitEntryEntry const* transmogOutfitEntry = sTransmogOutfitEntryStore.LookupEntry(transmogOutfit.value.Id);
326 if (!transmogOutfitEntry || transmogOutfitEntry->GetSource() != source)
327 continue;
328
329 if (!lastOwnedOutfit || transmogOutfitEntry->OrderIndex > lastOwnedOutfit->OrderIndex)
330 lastOwnedOutfit = transmogOutfitEntry;
331 }
332
333 if (!lastOwnedOutfit)
334 return TransmogOutfitsBySource[AsUnderlyingType(source)].front();
335
336 auto itr = std::ranges::find(TransmogOutfitsBySource[AsUnderlyingType(source)], lastOwnedOutfit) + 1;
337 if (itr != TransmogOutfitsBySource[AsUnderlyingType(source)].end())
338 return *itr;
339
340 return nullptr;
341}
342
343bool TransmogMgr::ValidateSituations(std::span<WorldPackets::Transmogrification::TransmogOutfitSituationInfo const> situations)
344{
345 struct SituationTriggerStatus
346 {
347 uint8 AllSituationCount = 0;
348 uint8 NoneSituationCount = 0;
349 uint8 RegularSituationCount = 0;
350 };
351
352 std::array<SituationTriggerStatus, AsUnderlyingType(TransmogSituationTrigger::Max)> statusByTrigger;
353
354 for (WorldPackets::Transmogrification::TransmogOutfitSituationInfo const& situation : situations)
355 {
356 TransmogSituationEntry const* transmogSituation = sTransmogSituationStore.LookupEntry(situation.SituationID);
357 if (!transmogSituation)
358 return false;
359
360 TransmogSituationGroupEntry const* transmogSituationGroup = sTransmogSituationGroupStore.LookupEntry(transmogSituation->TransmogSituationGroupID);
361 if (!transmogSituationGroup)
362 return false;
363
364 TransmogSituationTriggerEntry const* transmogSituationTrigger = sTransmogSituationTriggerStore.LookupEntry(transmogSituationGroup->TransmogSituationTriggerID);
365 if (!transmogSituationTrigger)
366 return false;
367
368 SituationTriggerStatus& triggers = statusByTrigger[AsUnderlyingType(transmogSituationTrigger->GetTrigger())];
369 uint8* count = nullptr;
370 if (transmogSituation->HasFlag(TransmogSituationFlags::AllSituation))
371 count = &triggers.AllSituationCount;
372 else if (transmogSituation->HasFlag(TransmogSituationFlags::NoneSituation))
373 count = &triggers.NoneSituationCount;
374 else
375 count = &triggers.RegularSituationCount;
376
377 *count += 1;
378 if (transmogSituationTrigger->HasFlag(TransmogSituationTriggerFlags::SituationsAreExclusive) && *count > 1)
379 return false;
380 }
381
382 for (SituationTriggerStatus const& triggers : statusByTrigger)
383 if ((triggers.AllSituationCount > 0) + (triggers.NoneSituationCount > 0) + (triggers.RegularSituationCount > 0) > 1) // only 1 group can be active
384 return false;
385
386 return true;
387}
388
389bool TransmogMgr::ValidateSlots(std::span<WorldPackets::Transmogrification::TransmogOutfitSlotData const> slots)
390{
392 {
393 if (slot.Slot >= TransmogOutfitSlot::Max)
394 return false;
395
396 if (slot.SlotOption >= TransmogOutfitSlotOption::Max)
397 return false;
398
399 if (slot.SheatheCategory >= TransmogOutfitSlotOptionSheatheCategory::Max)
400 return false;
401
402 if (slot.AppearanceDisplayType >= TransmogOutfitDisplayType::Max)
403 return false;
404
405 if (slot.IllusionDisplayType >= TransmogOutfitDisplayType::Max)
406 return false;
407
408 if (!GetSlotAndOption(slot.Slot, slot.SlotOption))
409 return false;
410
411 if (slot.ItemModifiedAppearanceID)
412 {
413 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(slot.ItemModifiedAppearanceID);
414 if (!itemModifiedAppearance)
415 return false;
416
417 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemModifiedAppearance->ItemID);
418 if (!itemTemplate)
419 return false;
420
421 if (!IsValidTransmogOutfitSlotForItem(itemTemplate, slot.Slot, slot.SlotOption))
422 return false;
423
424 TransmogOutfitSlotOption appearanceSlotOption = itemTemplate->GetWeaponTransmogOutfitSlotOption();
425 if (appearanceSlotOption != slot.SlotOption
427 || appearanceSlotOption != TransmogOutfitSlotOption::TwoHandedWeapon))
428 return false;
429
430 if (slot.SheatheCategory != TransmogOutfitSlotOptionSheatheCategory::Default &&
431 (itemTemplate->GetSheatheType() >= ItemSheatheType::Max ||
432 TransmogSheatheMappingByCategoryAndSheatheType[AsUnderlyingType(itemTemplate->GetSheatheType())][AsUnderlyingType(slot.SheatheCategory)] == ItemSheatheType::None))
433 return false;
434 }
435
436 if (slot.SpellItemEnchantmentID && !TransmogIllusionBySpellItemEnchantment.contains(slot.SpellItemEnchantmentID))
437 return false;
438 }
439
440 return true;
441}
DB2Storage< TransmogOutfitSlotInfoEntry > sTransmogOutfitSlotInfoStore("TransmogOutfitSlotInfo.db2", &TransmogOutfitSlotInfoLoadInfo::Instance)
DB2Storage< ArtifactEntry > sArtifactStore("Artifact.db2", &ArtifactLoadInfo::Instance)
DB2Storage< TransmogOutfitSlotOptionEntry > sTransmogOutfitSlotOptionInfoStore("TransmogOutfitSlotOption.db2", &TransmogOutfitSlotOptionLoadInfo::Instance)
DB2Storage< TransmogSituationEntry > sTransmogSituationStore("TransmogSituation.db2", &TransmogSituationLoadInfo::Instance)
DB2Storage< TransmogOutfitEntryEntry > sTransmogOutfitEntryStore("TransmogOutfitEntry.db2", &TransmogOutfitEntryLoadInfo::Instance)
DB2Storage< TransmogIllusionEntry > sTransmogIllusionStore("TransmogIllusion.db2", &TransmogIllusionLoadInfo::Instance)
DB2Storage< TransmogSetEntry > sTransmogSetStore("TransmogSet.db2", &TransmogSetLoadInfo::Instance)
DB2Storage< TransmogSituationGroupEntry > sTransmogSituationGroupStore("TransmogSituationGroup.db2", &TransmogSituationGroupLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< TransmogSituationTriggerEntry > sTransmogSituationTriggerStore("TransmogSituationTrigger.db2", &TransmogSituationTriggerLoadInfo::Instance)
DB2Storage< TransmogSetItemEntry > sTransmogSetItemStore("TransmogSetItem.db2", &TransmogSetItemLoadInfo::Instance)
TransmogOutfitSlotOption
Definition DBCEnums.h:2622
TransmogOutfitEntrySource
Definition DBCEnums.h:2576
TransmogOutfitSlot
Definition DBCEnums.h:2592
ItemSheatheType
Definition DBCEnums.h:1518
uint8_t uint8
Definition Define.h:156
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
#define ASSERT
Definition Errors.h:80
@ ITEM_SUBCLASS_WEAPON_WAND
@ INVTYPE_BODY
@ INVTYPE_HEAD
@ INVTYPE_CLOAK
@ INVTYPE_ROBE
@ INVTYPE_HOLDABLE
@ INVTYPE_RANGED
@ INVTYPE_WAIST
@ INVTYPE_RANGEDRIGHT
@ INVTYPE_WRISTS
@ INVTYPE_WEAPON
@ INVTYPE_WEAPONMAINHAND
@ INVTYPE_WEAPONOFFHAND
@ INVTYPE_2HWEAPON
@ INVTYPE_SHOULDERS
@ INVTYPE_FEET
@ INVTYPE_SHIELD
@ INVTYPE_TABARD
@ INVTYPE_LEGS
@ INVTYPE_CHEST
@ INVTYPE_HANDS
#define sObjectMgr
Definition ObjectMgr.h:1885
EquipmentSlots
Definition Player.h:727
@ EQUIPMENT_SLOT_END
Definition Player.h:748
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition Player.h:3062
std::span< TransmogSetItemEntry const *const > GetTransmogSetItems(uint32 transmogSetId)
bool ValidateSituations(std::span< WorldPackets::Transmogrification::TransmogOutfitSituationInfo const > situations)
TransmogIllusionEntry const * GetTransmogIllusionForSpellItemEnchantment(uint32 spellItemEnchantmentId)
ItemModifiedAppearanceEntry const * GetDefaultItemModifiedAppearance(uint32 itemId)
std::span< TransmogSetEntry const *const > GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId)
ItemModifiedAppearanceEntry const * GetItemModifiedAppearance(uint32 itemId, uint32 appearanceModId)
std::span< TransmogSituationEntry const *const > GetDefaultSituations()
std::span< TransmogOutfitSlotAndOptionInfo const > GetAllSlots()
bool ValidateSlots(std::span< WorldPackets::Transmogrification::TransmogOutfitSlotData const > slots)
TransmogOutfitSlotAndOptionInfo const * GetSlotAndOption(TransmogOutfitSlot slot, TransmogOutfitSlotOption slotOption)
std::span< TransmogOutfitEntryEntry const *const > GetAutomaticallyUnlockedOutfits()
TransmogOutfitEntryEntry const * GetNextOutfitToUnlock(TransmogOutfitEntrySource source, Player const *player)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
TransmogOutfitSlotOption GetWeaponTransmogOutfitSlotOption() const
InventoryType GetInventoryType() const
ItemSheatheType GetSheatheType() const
uint8 GetArtifactID() const
uint32 GetSubClass() const
TransmogOutfitSlotInfoEntry const * Slot
Definition TransmogMgr.h:48
TransmogOutfitSlotOptionEntry const * SlotOption
Definition TransmogMgr.h:49
TransmogOutfitEntrySource GetSource() const
TransmogOutfitSlot GetSlot() const
bool HasFlag(TransmogSituationFlags flag) const
TransmogSituationTrigger GetTrigger() const
bool HasFlag(TransmogSituationTriggerFlags flag) const