35 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {} not found or player can't interact with it.", transmogrifyItems.
Npc.
ToString());
40 std::unordered_map<Item*, std::pair<uint32, uint32>> transmogItems;
41 std::unordered_map<Item*, uint32> illusionItems;
43 std::vector<Item*> resetAppearanceItems;
44 std::vector<Item*> resetIllusionItems;
45 std::vector<uint32> bindAppearances;
47 auto validateAndStoreTransmogItem = [&](
Item* itemTransmogrified,
uint32 itemModifiedAppearanceId,
bool isSecondary)
50 if (!itemModifiedAppearance)
52 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify using invalid appearance ({}).", player->
GetGUID().
ToString(), player->
GetName(), itemModifiedAppearanceId);
58 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify secondary appearance to non-shoulder item.", player->
GetGUID().
ToString(), player->
GetName());
65 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify using appearance he has not collected ({}).", player->
GetGUID().
ToString(), player->
GetName(), itemModifiedAppearanceId);
71 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify using appearance he can never use ({}).", player->
GetGUID().
ToString(), player->
GetName(), itemModifiedAppearanceId);
78 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} failed CanTransmogrifyItemWithItem ({} with appearance {}).", player->
GetGUID().
ToString(), player->
GetName(), itemTransmogrified->
GetEntry(), itemModifiedAppearanceId);
83 transmogItems[itemTransmogrified].first = itemModifiedAppearanceId;
85 transmogItems[itemTransmogrified].second = itemModifiedAppearanceId;
88 bindAppearances.push_back(itemModifiedAppearanceId);
98 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - Player ({}, name: {}) tried to transmogrify wrong slot ({}) when transmogrifying items.", player->
GetGUID().
ToString(), player->
GetName(), transmogItem.Slot);
104 if (!itemTransmogrified)
106 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - Player ({}, name: {}) tried to transmogrify an invalid item in a valid slot (slot: {}).", player->
GetGUID().
ToString(), player->
GetName(), transmogItem.Slot);
110 if (transmogItem.ItemModifiedAppearanceID || transmogItem.SecondaryItemModifiedAppearanceID > 0)
112 if (transmogItem.ItemModifiedAppearanceID && !validateAndStoreTransmogItem(itemTransmogrified, transmogItem.ItemModifiedAppearanceID,
false))
115 if (transmogItem.SecondaryItemModifiedAppearanceID > 0 && !validateAndStoreTransmogItem(itemTransmogrified, transmogItem.SecondaryItemModifiedAppearanceID,
true))
122 resetAppearanceItems.push_back(itemTransmogrified);
124 if (transmogItem.SpellItemEnchantmentID)
128 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify illusion into non-weapon slot ({}).", player->
GetGUID().
ToString(), player->
GetName(), transmogItem.Slot);
135 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify illusion using invalid enchant ({}).", player->
GetGUID().
ToString(), player->
GetName(), transmogItem.SpellItemEnchantmentID);
141 TC_LOG_DEBUG(
"network",
"WORLD: HandleTransmogrifyItems - {}, Name: {} tried to transmogrify illusion using not allowed enchant ({}).", player->
GetGUID().
ToString(), player->
GetName(), transmogItem.SpellItemEnchantmentID);
145 illusionItems[itemTransmogrified] = transmogItem.SpellItemEnchantmentID;
149 resetIllusionItems.push_back(itemTransmogrified);
160 for (
auto& transmogPair : transmogItems)
162 Item* transmogrified = transmogPair.first;
209 for (
auto& illusionPair : illusionItems)
211 Item* transmogrified = illusionPair.first;
241 for (
Item* item : resetAppearanceItems)
286 for (
Item* item : resetIllusionItems)
315 for (
uint32 itemModifedAppearanceId : bindAppearances)
318 for (
ObjectGuid const& itemGuid : itemsProvidingAppearance)
322 item->SetNotRefundable(player);
323 item->ClearSoulboundTradeable(player);
334 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
343 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - source {} not allowed.",
350 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - set type {} not allowed.",
356 if (!transmogOutfitEntry)
358 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - no next unlockable outfit entry found for source {}.",
365 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - not enough money.",
383 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
392 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateInfo - player does not have outfit {}.",
404 transmogOutfitInfoUpdated.
OutfitInfo = &transmogOutfitUpdateInfo.
Info;
412 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
421 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSituations - player does not have outfit {}.",
428 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSituations - player sent invalid situations.",
452 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitNew - {} not found or player can't interact with it.",
462 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - player does not have outfit {}.",
469 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - player sent invalid slots.",
474 std::vector<uint32> bindAppearances;
478 if (slot.ItemModifiedAppearanceID)
483 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - player does not have appearance {} in collection.",
489 bindAppearances.push_back(slot.ItemModifiedAppearanceID);
494 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - player does not have enchant {} in illusion collection.",
502 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - player has already claimed free transmog before.",
512 float costMultiplier = 1.0f;
521 costMultiplier *= 0.5f;
527 auto oldSlotItr = transmogOutfit->
Slots.
begin();
528 auto oldSlotEnd = transmogOutfit->
Slots.
end();
531 oldSlotItr = std::ranges::find(oldSlotItr, oldSlotEnd,
543 cost =
static_cast<uint64>(std::floor(baseCost * slotEntry->ItemCostMultiplier)) + cost;
546 cost =
static_cast<uint64>(std::floor(baseCost * slotOptionEntry->ItemCostMultiplier)) + cost;
553 cost =
static_cast<uint64>(std::floor(baseCost * slotEntry->IllusionCostMultiplier)) + cost;
556 cost =
static_cast<uint64>(std::floor(baseCost * slotOptionEntry->IllusionCostMultiplier)) + cost;
562 cost =
static_cast<uint64>(std::clamp(costMultiplier, 0.0f, 1.0f) * cost);
564 if (cost != transmogOutfitUpdateSlots.
Cost)
566 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - player sent invalid cost {}.",
573 TC_LOG_ERROR(
"entities.player.cheat",
"{} WorldSession::HandleTransmogOutfitUpdateSlots - not enough money.",
593 transmogOutfitSlotsUpdated.
Slots = transmogOutfitUpdateSlots.
Slots;
596 for (
uint32 itemModifedAppearanceId : bindAppearances)
599 for (
ObjectGuid const& itemGuid : itemsProvidingAppearance)
603 item->SetNotRefundable(
_player);
604 item->ClearSoulboundTradeable(
_player);
614 npcInteraction.
Npc = guid;
DB2Storage< TransmogOutfitEntryEntry > sTransmogOutfitEntryStore("TransmogOutfitEntry.db2", &TransmogOutfitEntryLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< ChrRacesEntry > sChrRacesStore("ChrRaces.db2", &ChrRacesLoadInfo::Instance)
DB2Storage< TransmogHolidayEntry > sTransmogHolidayStore("TransmogHoliday.db2", &TransmogHolidayLoadInfo::Instance)
@ UseOverrideCostModifier
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_3
@ 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_TRANSMOG_APPEARANCE_SPEC_4
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4
@ ITEM_MODIFIER_TRANSMOG_SECONDARY_APPEARANCE_SPEC_1
@ ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3
@ 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_TRANSMOG_APPEARANCE_SPEC_1
ItemModifier const AppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
ItemModifier const SecondaryAppearanceModifierSlotBySpec[MAX_SPECIALIZATIONS]
ItemModifier const IllusionModifierSlotBySpec[MAX_SPECIALIZATIONS]
#define TC_LOG_DEBUG(filterType__, message__,...)
#define TC_LOG_ERROR(filterType__, message__,...)
@ EQUIPMENT_SLOT_MAINHAND
@ PLAYER_LOCAL_FLAG_FREE_TRANSMOG_CLAIMED
#define INVENTORY_SLOT_BAG_0
@ SPELL_AURA_MOD_TRANSMOG_OUTFIT_UPDATE_COST
@ SPELL_AURA_REMOVE_TRANSMOG_COST
@ UNIT_NPC_FLAG_TRANSMOGRIFIER
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
ObjectGuid const & GetGUID() const
void AddItemAppearance(Item *item)
void AddTransmogOutfit(int32 transmogOutfitId)
std::unordered_set< ObjectGuid > GetItemsProvidingTemporaryAppearance(uint32 itemModifiedAppearanceId) const
std::pair< bool, bool > HasItemAppearance(uint32 itemModifiedAppearanceId) const
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
static bool CanTransmogrifyItemWithItem(Item const *item, ItemModifiedAppearanceEntry const *itemModifiedAppearance)
void SetModifier(ItemModifier modifier, uint32 value)
ItemTemplate const * GetTemplate() const
void SetNotRefundable(Player *owner, bool changestate=true, CharacterDatabaseTransaction *trans=nullptr, bool addToCollection=true)
uint32 GetSellPrice(Player const *owner) const
void ClearSoulboundTradeable(Player *currentOwner)
uint32 GetModifier(ItemModifier modifier) const
std::string ToString() const
bool UpdateTransmogOutfit(uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const &outfitData)
bool ModifyMoney(int64 amount, bool sendError=true)
void SetPlayerLocalFlag(PlayerLocalFlags flags)
void SetVisibleItemSlot(uint8 slot, Item const *item)
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Item * GetItemByPos(uint16 pos) const
void EquipTransmogOutfit(uint32 id, TransmogSituationTrigger trigger, Optional< bool > locked)
bool HasPlayerLocalFlag(PlayerLocalFlags flags) const
void UpdateTransmogOutfitSlots(uint32 id, std::span< WorldPackets::Transmogrification::TransmogOutfitSlotData const > slots)
uint8 GetActiveTalentGroup() const
void UpdateTransmogOutfitSituations(uint32 id, bool situationsEnabled, std::span< WorldPackets::Transmogrification::TransmogOutfitSituationInfo const > situations)
Item * GetItemByGuid(ObjectGuid guid) const
void CreateTransmogOutfit(uint32 id, WorldPackets::Transmogrification::TransmogOutfitDataInfo const &outfitData)
bool HasEnoughMoney(uint64 amount) const
void SetHasClaimedFreeTransmog()
InventoryResult CanUseItem(Item *pItem, bool not_loading=true) const
std::vector< T >::const_iterator begin() const
std::vector< T >::const_iterator end() const
void MarkChanged(UpdateField< T, BlockBit, Bit >(Derived::*))
bool HasAuraType(AuraType auraType) const
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
std::string const & GetName() const
PlayerInteractionType InteractionType
WorldPacket const * Write() override
TransmogOutfitDataInfo const * OutfitInfo
WorldPacket const * Write() override
WorldPacket const * Write() override
TransmogOutfitEntrySource Source
TransmogOutfitDataInfo Info
std::span< TransmogOutfitSituationInfo const > Situations
WorldPacket const * Write() override
WorldPacket const * Write() override
std::span< TransmogOutfitSlotData const > Slots
TransmogOutfitDataInfo Info
Array< TransmogOutfitSituationInfo, 100 > Situations
bool UseAvailableDiscount
Array< TransmogOutfitSlotData, 30 > Slots
Array< TransmogrifyItem, MAX_TRANSMOGRIFY_ITEMS > Items
void HandleTransmogOutfitUpdateSituations(WorldPackets::Transmogrification::TransmogOutfitUpdateSituations const &transmogOutfitUpdateSituations)
void HandleTransmogrifyItems(WorldPackets::Transmogrification::TransmogrifyItems &transmogrifyItems)
void HandleTransmogOutfitNew(WorldPackets::Transmogrification::TransmogOutfitNew const &transmogOutfitNew)
void HandleTransmogOutfitUpdateSlots(WorldPackets::Transmogrification::TransmogOutfitUpdateSlots const &transmogOutfitUpdateSlots)
void HandleTransmogOutfitUpdateInfo(WorldPackets::Transmogrification::TransmogOutfitUpdateInfo const &transmogOutfitUpdateInfo)
std::string GetPlayerInfo() const
Player * GetPlayer() const
void SendOpenTransmogrifier(ObjectGuid const &guid)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
CollectionMgr * GetCollectionMgr() const
bool ValidateSituations(std::span< WorldPackets::Transmogrification::TransmogOutfitSituationInfo const > situations)
TransmogIllusionEntry const * GetTransmogIllusionForSpellItemEnchantment(uint32 spellItemEnchantmentId)
bool ValidateSlots(std::span< WorldPackets::Transmogrification::TransmogOutfitSlotData const > slots)
TransmogOutfitSlotAndOptionInfo const * GetSlotAndOption(TransmogOutfitSlot slot, TransmogOutfitSlotOption slotOption)
TransmogOutfitEntryEntry const * GetNextOutfitToUnlock(TransmogOutfitEntrySource source, Player const *player)
InventoryType GetInventoryType() const
UF::ActivePlayerData::Base ActivePlayerMask
float OverrideCostModifier
bool HasFlag(TransmogOutfitEntryFlags flag) const
MapUpdateField< uint32, UF::TransmogOutfitData, 134, 158 > TransmogOutfits
DynamicUpdateField< UF::TransmogOutfitSlotData, -1, 1 > Slots
TransmogOutfitSetType SetType