aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Item/Item.cpp75
-rw-r--r--src/server/game/Entities/Item/Item.h16
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp207
-rw-r--r--src/server/game/Handlers/VoidStorageHandler.cpp2
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp56
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h30
-rw-r--r--src/server/game/Server/Packets/PacketUtilities.h10
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/WorldSession.h3
9 files changed, 246 insertions, 155 deletions
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 70d63a853e7..4d65598c298 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -1298,10 +1298,9 @@ bool Item::CheckSoulboundTradeExpire()
return false;
}
-bool Item::CanBeTransmogrified() const
+bool Item::CanBeTransmogrified(WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus)
{
- ItemTemplate const* proto = GetTemplate();
-
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(transmogrifier.ItemID);
if (!proto)
return false;
@@ -1318,7 +1317,7 @@ bool Item::CanBeTransmogrified() const
if (proto->GetFlags2() & ITEM_FLAG2_CANNOT_BE_TRANSMOG)
return false;
- if (!HasStats())
+ if (!HasStats(transmogrifier, bonus))
return false;
return true;
@@ -1327,7 +1326,6 @@ bool Item::CanBeTransmogrified() const
bool Item::CanTransmogrify() const
{
ItemTemplate const* proto = GetTemplate();
-
if (!proto)
return false;
@@ -1353,18 +1351,41 @@ bool Item::CanTransmogrify() const
return true;
}
-bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier)
+bool Item::HasStats() const
{
- if (!transmogrifier || !transmogrified)
- return false;
+ if (GetItemRandomPropertyId() != 0)
+ return true;
+
+ ItemTemplate const* proto = GetTemplate();
+ Player const* owner = GetOwner();
+ for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ if ((owner ? GetItemStatValue(i, owner) : proto->GetItemStatValue(i)) != 0)
+ return true;
+
+ return false;
+}
+
+bool Item::HasStats(WorldPackets::Item::ItemInstance const& itemInstance, BonusData const* bonus)
+{
+ if (itemInstance.RandomPropertiesID != 0)
+ return true;
+
+ for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ if (bonus->ItemStatValue[i] != 0)
+ return true;
+
+ return false;
+}
- ItemTemplate const* proto1 = transmogrifier->GetTemplate(); // source
+bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus)
+{
+ ItemTemplate const* proto1 = sObjectMgr->GetItemTemplate(transmogrifier.ItemID); // source
ItemTemplate const* proto2 = transmogrified->GetTemplate(); // dest
- if (proto1->GetId() == proto2->GetId())
+ if (sDB2Manager.GetItemDisplayId(proto1->GetId(), bonus->AppearanceModID) == transmogrified->GetDisplayId())
return false;
- if (!transmogrified->CanTransmogrify() || !transmogrifier->CanBeTransmogrified())
+ if (!transmogrified->CanTransmogrify() || !CanBeTransmogrified(transmogrifier, bonus))
return false;
if (proto1->GetInventoryType() == INVTYPE_BAG ||
@@ -1387,19 +1408,6 @@ bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* t
return true;
}
-bool Item::HasStats() const
-{
- if (GetItemRandomPropertyId() != 0)
- return true;
-
- ItemTemplate const* proto = GetTemplate();
- for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- if (proto->GetItemStatValue(i) != 0)
- return true;
-
- return false;
-}
-
// used by mail items, transmog cost, stationeryinfo and others
uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice)
{
@@ -1784,8 +1792,8 @@ uint32 Item::GetVisibleEntry() const
uint32 Item::GetVisibleAppearanceModId() const
{
- if (uint32 transmogMod = GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD))
- return transmogMod;
+ if (GetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID))
+ return GetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD);
return GetAppearanceModId();
}
@@ -1823,6 +1831,21 @@ void BonusData::Initialize(ItemTemplate const* proto)
AppearanceModID = 0;
}
+void BonusData::Initialize(WorldPackets::Item::ItemInstance const& itemInstance)
+{
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemInstance.ItemID);
+ if (!proto)
+ return;
+
+ Initialize(proto);
+
+ if (itemInstance.ItemBonus)
+ for (uint32 bonusListID : itemInstance.ItemBonus->BonusListIDs)
+ if (DB2Manager::ItemBonusList const* bonuses = sDB2Manager.GetItemBonusList(bonusListID))
+ for (ItemBonusEntry const* bonus : *bonuses)
+ AddBonus(bonus->Type, bonus->Value);
+}
+
void BonusData::AddBonus(uint32 type, int32 const (&values)[2])
{
switch (type)
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 7d03a0a68eb..f81c72c0f98 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -28,6 +28,13 @@
class SpellInfo;
class Bag;
class Unit;
+namespace WorldPackets
+{
+ namespace Item
+ {
+ struct ItemInstance;
+ }
+}
struct ItemSetEffect
{
@@ -242,6 +249,7 @@ struct BonusData
uint32 AppearanceModID;
void Initialize(ItemTemplate const* proto);
+ void Initialize(WorldPackets::Item::ItemInstance const& itemInstance);
void AddBonus(uint32 type, int32 const (&values)[2]);
};
@@ -256,6 +264,7 @@ class Item : public Object
virtual bool Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner);
ItemTemplate const* GetTemplate() const;
+ BonusData const* GetBonus() const { return &_bonusData; }
ObjectGuid GetOwnerGUID() const { return GetGuidValue(ITEM_FIELD_OWNER); }
void SetOwnerGUID(ObjectGuid guid) { SetGuidValue(ITEM_FIELD_OWNER, guid); }
@@ -369,7 +378,6 @@ class Item : public Object
bool hasQuest(uint32 quest_id) const override { return GetTemplate()->GetStartQuest() == quest_id; }
bool hasInvolvedQuest(uint32 /*quest_id*/) const override { return false; }
- bool HasStats() const;
bool IsPotion() const { return GetTemplate()->IsPotion(); }
bool IsVellum() const { return GetTemplate()->IsVellum(); }
bool IsConjuredConsumable() const { return GetTemplate()->IsConjuredConsumable(); }
@@ -411,9 +419,11 @@ class Item : public Object
uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
- bool CanBeTransmogrified() const;
+ static bool CanBeTransmogrified(WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus);
bool CanTransmogrify() const;
- static bool CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier);
+ bool HasStats() const;
+ static bool HasStats(WorldPackets::Item::ItemInstance const& itemInstance, BonusData const* bonus);
+ static bool CanTransmogrifyItemWithItem(Item const* transmogrified, WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus);
static uint32 GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice = 10000);
uint32 GetSpecialPrice(uint32 minimumPrice = 10000) const { return Item::GetSpecialPrice(GetTemplate(), minimumPrice); }
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 9c1afcc3785..b241dac38d0 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -1109,142 +1109,93 @@ void WorldSession::HandleItemRefund(WorldPacket &recvData)
GetPlayer()->RefundItem(item);
}
-void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
+void WorldSession::HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems& transmogrifyItems)
{
Player* player = GetPlayer();
-
- // Read data
- uint32 count = recvData.ReadBits(22);
-
- if (count >= EQUIPMENT_SLOT_END)
- {
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) sent a wrong count (%u) when transmogrifying items.", player->GetGUID().ToString().c_str(), player->GetName().c_str(), count);
- recvData.rfinish();
- return;
- }
-
- std::vector<ObjectGuid> itemGuids(count, ObjectGuid());
- std::vector<uint32> newEntries(count, 0);
- std::vector<uint32> slots(count, 0);
-
- for (uint8 i = 0; i < count; ++i)
- {
- itemGuids[i][0] = recvData.ReadBit();
- itemGuids[i][5] = recvData.ReadBit();
- itemGuids[i][6] = recvData.ReadBit();
- itemGuids[i][2] = recvData.ReadBit();
- itemGuids[i][3] = recvData.ReadBit();
- itemGuids[i][7] = recvData.ReadBit();
- itemGuids[i][4] = recvData.ReadBit();
- itemGuids[i][1] = recvData.ReadBit();
- }
-
- ObjectGuid npcGuid;
- npcGuid[7] = recvData.ReadBit();
- npcGuid[3] = recvData.ReadBit();
- npcGuid[5] = recvData.ReadBit();
- npcGuid[6] = recvData.ReadBit();
- npcGuid[1] = recvData.ReadBit();
- npcGuid[4] = recvData.ReadBit();
- npcGuid[0] = recvData.ReadBit();
- npcGuid[2] = recvData.ReadBit();
-
- recvData.FlushBits();
-
- for (uint32 i = 0; i < count; ++i)
- {
- recvData >> newEntries[i];
-
- recvData.ReadByteSeq(itemGuids[i][1]);
- recvData.ReadByteSeq(itemGuids[i][5]);
- recvData.ReadByteSeq(itemGuids[i][0]);
- recvData.ReadByteSeq(itemGuids[i][4]);
- recvData.ReadByteSeq(itemGuids[i][6]);
- recvData.ReadByteSeq(itemGuids[i][7]);
- recvData.ReadByteSeq(itemGuids[i][3]);
- recvData.ReadByteSeq(itemGuids[i][2]);
-
- recvData >> slots[i];
- }
-
- recvData.ReadByteSeq(npcGuid[7]);
- recvData.ReadByteSeq(npcGuid[2]);
- recvData.ReadByteSeq(npcGuid[5]);
- recvData.ReadByteSeq(npcGuid[4]);
- recvData.ReadByteSeq(npcGuid[3]);
- recvData.ReadByteSeq(npcGuid[1]);
- recvData.ReadByteSeq(npcGuid[6]);
- recvData.ReadByteSeq(npcGuid[0]);
-
// Validate
-
- if (!player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_TRANSMOGRIFIER))
+ if (!player->GetNPCIfCanInteractWith(transmogrifyItems.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER))
{
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s not found or player can't interact with it.", npcGuid.ToString().c_str());
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s not found or player can't interact with it.", transmogrifyItems.Npc.ToString().c_str());
return;
}
int64 cost = 0;
- std::vector<Item*> transmogrifier(count, NULL);
- std::vector<Item*> transmogrified(count, NULL);
+ std::unordered_map<Item*, Item*> transmogItems;
+ std::unordered_map<Item*, std::pair<VoidStorageItem*, BonusData>> transmogVoidItems;
+ std::vector<Item*> resetAppearanceItems;
- for (uint8 i = 0; i < count; ++i)
+ for (WorldPackets::Item::TransmogrifyItem const& transmogItem : transmogrifyItems.Items)
{
// slot of the transmogrified item
- if (slots[i] >= EQUIPMENT_SLOT_END)
+ if (transmogItem.Slot >= EQUIPMENT_SLOT_END)
{
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify %s with a wrong slot (%u) when transmogrifying items.", player->GetGUID().ToString().c_str(), player->GetName().c_str(), itemGuids[i].ToString().c_str(), slots[i]);
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify wrong slot (%u) when transmogrifying items.", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.Slot);
return;
}
// transmogrified item
- Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[i]);
+ Item* itemTransmogrified = player->GetItemByPos(INVENTORY_SLOT_BAG_0, transmogItem.Slot);
if (!itemTransmogrified)
{
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), slots[i]);
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify an invalid item in a valid slot (slot: %u).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.Slot);
return;
}
- // if not resetting look
- Item* itemTransmogrifier = NULL;
- if (newEntries[i])
+ WorldPackets::Item::ItemInstance itemInstance;
+ BonusData const* bonus = nullptr;
+ if (transmogItem.SrcItemGUID)
{
- // entry of the transmogrifier item
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(newEntries[i]);
- if (!proto)
+ // guid of the transmogrifier item
+ Item* itemTransmogrifier = player->GetItemByGuid(*transmogItem.SrcItemGUID);
+ if (!itemTransmogrifier)
{
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify to an invalid item (entry: %u).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), newEntries[i]);
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid item (%s).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SrcItemGUID->ToString().c_str());
return;
}
+ itemInstance.Initialize(itemTransmogrifier);
+ bonus = itemTransmogrifier->GetBonus();
+ transmogItems[itemTransmogrified] = itemTransmogrifier;
+ }
+ else if (transmogItem.SrcVoidItemGUID)
+ {
// guid of the transmogrifier item
- itemTransmogrifier = player->GetItemByGuid(itemGuids[i]);
+ uint8 slot;
+ VoidStorageItem* itemTransmogrifier = player->GetVoidStorageItem(transmogItem.SrcVoidItemGUID->GetCounter(), slot);
if (!itemTransmogrifier)
{
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid item (%s).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), itemGuids[i].ToString().c_str());
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid void storage item (%s).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SrcVoidItemGUID->ToString().c_str());
return;
}
- // entry of transmogrifier and from packet
- if (itemTransmogrifier->GetEntry() != newEntries[i])
- {
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid entry (entry: %u) for %s.", player->GetGUID().ToString().c_str(), player->GetName().c_str(), newEntries[i], itemGuids[i].ToString().c_str());
- return;
- }
+ itemInstance.Initialize(itemTransmogrifier);
+ std::pair<VoidStorageItem*, BonusData>& transmogData = transmogVoidItems[itemTransmogrified];
+ transmogData.first = itemTransmogrifier;
+ transmogData.second.Initialize(itemInstance);
+ bonus = &transmogData.second;
+ }
+ else
+ {
+ resetAppearanceItems.push_back(itemTransmogrified);
+ continue;
+ }
- // validity of the transmogrification items
- if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier))
- {
- TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), itemTransmogrified->GetEntry(), itemTransmogrifier->GetEntry());
- return;
- }
+ // entry of transmogrifier and from packet
+ if (itemInstance != transmogItem.Item)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an invalid item instance data for %s.", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.Item.ItemID, transmogItem.SrcItemGUID->ToString().c_str());
+ return;
+ }
- // add cost
- cost += itemTransmogrified->GetSpecialPrice();
+ // validity of the transmogrification items
+ if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, transmogItem.Item, bonus))
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), itemTransmogrified->GetEntry(), transmogItem.Item.ItemID);
+ return;
}
- transmogrifier[i] = itemTransmogrifier;
- transmogrified[i] = itemTransmogrified;
+ // add cost
+ cost += itemTransmogrified->GetSpecialPrice();
}
if (cost) // 0 cost if reverting look
@@ -1255,34 +1206,44 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
}
// Everything is fine, proceed
-
- for (uint8 i = 0; i < count; ++i)
+ for (auto& transmogPair : transmogItems)
{
- if (transmogrifier[i])
- {
- // Transmogrify
- transmogrified[i]->SetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID, newEntries[i]);
- player->SetVisibleItemSlot(slots[i], transmogrified[i]);
+ Item* transmogrified = transmogPair.first;
+ Item* transmogrifier = transmogPair.second;
- transmogrified[i]->UpdatePlayedTime(player);
+ transmogrified->SetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID, transmogrifier->GetEntry());
+ transmogrified->SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD, transmogrifier->GetAppearanceModId());
+ player->SetVisibleItemSlot(transmogrified->GetSlot(), transmogrified);
- transmogrified[i]->SetOwnerGUID(player->GetGUID());
- transmogrified[i]->SetNotRefundable(player);
- transmogrified[i]->ClearSoulboundTradeable(player);
+ transmogrified->SetNotRefundable(player);
+ transmogrified->ClearSoulboundTradeable(player);
- if (transmogrifier[i]->GetTemplate()->GetBonding() == BIND_WHEN_EQUIPED || transmogrifier[i]->GetTemplate()->GetBonding() == BIND_WHEN_USE)
- transmogrifier[i]->SetBinding(true);
+ transmogrifier->SetNotRefundable(player);
+ transmogrifier->ClearSoulboundTradeable(player);
- transmogrifier[i]->SetOwnerGUID(player->GetGUID());
- transmogrifier[i]->SetNotRefundable(player);
- transmogrifier[i]->ClearSoulboundTradeable(player);
- }
- else
- {
- // Reset
- transmogrified[i]->SetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID, 0);
- player->SetVisibleItemSlot(slots[i], transmogrified[i]);
- }
+ if (transmogrifier->GetTemplate()->GetBonding() == BIND_WHEN_EQUIPED || transmogrifier->GetTemplate()->GetBonding() == BIND_WHEN_USE)
+ transmogrifier->SetBinding(true);
+ }
+
+ for (auto& transmogVoirPair : transmogVoidItems)
+ {
+ Item* transmogrified = transmogVoirPair.first;
+ VoidStorageItem* transmogrifier = transmogVoirPair.second.first;
+ BonusData& bonus = transmogVoirPair.second.second;
+
+ transmogrified->SetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID, transmogrifier->ItemEntry);
+ transmogrified->SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD, bonus.AppearanceModID);
+ player->SetVisibleItemSlot(transmogrified->GetSlot(), transmogrified);
+
+ transmogrified->SetNotRefundable(player);
+ transmogrified->ClearSoulboundTradeable(player);
+ }
+
+ for (Item* item : resetAppearanceItems)
+ {
+ item->SetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID, 0);
+ item->SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD, 0);
+ player->SetVisibleItemSlot(item->GetSlot(), item);
}
}
diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp
index 95d117227ad..ba8ad1dc056 100644
--- a/src/server/game/Handlers/VoidStorageHandler.cpp
+++ b/src/server/game/Handlers/VoidStorageHandler.cpp
@@ -52,7 +52,7 @@ void WorldSession::HandleVoidStorageUnlock(WorldPackets::VoidStorage::UnlockVoid
void WorldSession::HandleVoidStorageQuery(WorldPackets::VoidStorage::QueryVoidStorage& queryVoidStorage)
{
- Creature* unit = _player->GetNPCIfCanInteractWith(queryVoidStorage.Npc, UNIT_NPC_FLAG_VAULTKEEPER);
+ Creature* unit = _player->GetNPCIfCanInteractWith(queryVoidStorage.Npc, UNIT_NPC_FLAG_TRANSMOGRIFIER | UNIT_NPC_FLAG_VAULTKEEPER);
if (!unit)
{
TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageQuery - %s not found or player can't interact with it.", queryVoidStorage.Npc.ToString().c_str());
diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp
index 7d54ebe3ec6..80bafbba104 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -18,6 +18,17 @@
#include "ItemPackets.h"
#include "Player.h"
+bool WorldPackets::Item::ItemBonusInstanceData::operator==(ItemBonusInstanceData const& r) const
+{
+ if (Context != r.Context)
+ return false;
+
+ if (BonusListIDs.size() != r.BonusListIDs.size())
+ return false;
+
+ return std::is_permutation(BonusListIDs.begin(), BonusListIDs.end(), r.BonusListIDs.begin());
+}
+
void WorldPackets::Item::BuyBackItem::Read()
{
_worldPacket >> VendorGUID
@@ -228,6 +239,23 @@ void WorldPackets::Item::ItemInstance::Initialize(::VoidStorageItem const* voidI
}
}
+bool WorldPackets::Item::ItemInstance::operator==(ItemInstance const& r) const
+{
+ if (ItemID != r.ItemID || RandomPropertiesID != r.RandomPropertiesID || RandomPropertiesSeed != r.RandomPropertiesSeed)
+ return false;
+
+ if (ItemBonus.is_initialized() != r.ItemBonus.is_initialized() || Modifications.is_initialized() != r.Modifications.is_initialized())
+ return false;
+
+ if (Modifications.is_initialized() && *Modifications != *r.Modifications)
+ return false;
+
+ if (ItemBonus.is_initialized() && *ItemBonus != *r.ItemBonus)
+ return false;
+
+ return true;
+}
+
WorldPacket const* WorldPackets::Item::InventoryChangeFailure::Write()
{
_worldPacket << int8(BagResult);
@@ -405,3 +433,31 @@ WorldPacket const* WorldPackets::Item::ItemEnchantTimeUpdate::Write()
return &_worldPacket;
}
+
+ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Item::TransmogrifyItem& transmogItem)
+{
+ if (data.ReadBit())
+ transmogItem.SrcItemGUID = boost::in_place();
+
+ if (data.ReadBit())
+ transmogItem.SrcVoidItemGUID = boost::in_place();
+
+ data >> transmogItem.Item;
+ data >> transmogItem.Slot;
+
+ if (transmogItem.SrcItemGUID.is_initialized())
+ data >> *transmogItem.SrcItemGUID;
+
+ if (transmogItem.SrcVoidItemGUID.is_initialized())
+ data >> *transmogItem.SrcVoidItemGUID;
+
+ return data;
+}
+
+void WorldPackets::Item::TransmogrifyItems::Read()
+{
+ Items.resize(_worldPacket.read<uint32>());
+ _worldPacket >> Npc;
+ for (TransmogrifyItem& item : Items)
+ _worldPacket >> item;
+}
diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h
index d179f03b041..943a681edbe 100644
--- a/src/server/game/Server/Packets/ItemPackets.h
+++ b/src/server/game/Server/Packets/ItemPackets.h
@@ -32,6 +32,9 @@ namespace WorldPackets
{
uint8 Context = 0;
std::vector<int32> BonusListIDs;
+
+ bool operator==(ItemBonusInstanceData const& r) const;
+ bool operator!=(ItemBonusInstanceData const& r) const { return !(*this == r); }
};
struct ItemInstance
@@ -45,6 +48,9 @@ namespace WorldPackets
uint32 RandomPropertiesID = 0;
Optional<ItemBonusInstanceData> ItemBonus;
Optional<CompactArray<int32>> Modifications;
+
+ bool operator==(ItemInstance const& r) const;
+ bool operator!=(ItemInstance const& r) const { return !(*this == r); }
};
class BuyBackItem final : public ClientPacket
@@ -398,6 +404,30 @@ namespace WorldPackets
uint32 Slot = 0;
};
+ struct TransmogrifyItem
+ {
+ Optional<ObjectGuid> SrcItemGUID;
+ Optional<ObjectGuid> SrcVoidItemGUID;
+ ItemInstance Item;
+ uint32 Slot = 0;
+ };
+
+ class TransmogrifyItems final : public ClientPacket
+ {
+ public:
+ enum
+ {
+ MAX_TRANSMOGRIFY_ITEMS = 11
+ };
+
+ TransmogrifyItems(WorldPacket&& packet) : ClientPacket(CMSG_TRANSMOGRIFY_ITEMS, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Npc;
+ Array<TransmogrifyItem, MAX_TRANSMOGRIFY_ITEMS> Items;
+ };
+
ByteBuffer& operator>>(ByteBuffer& data, InvUpdate& invUpdate);
}
}
diff --git a/src/server/game/Server/Packets/PacketUtilities.h b/src/server/game/Server/Packets/PacketUtilities.h
index 4837ee9e69c..4f39e264efb 100644
--- a/src/server/game/Server/Packets/PacketUtilities.h
+++ b/src/server/game/Server/Packets/PacketUtilities.h
@@ -178,6 +178,16 @@ namespace WorldPackets
_contents.clear();
}
+ bool operator==(CompactArray const& r) const
+ {
+ if (_mask != r._mask)
+ return false;
+
+ return _contents == r._contents;
+ }
+
+ bool operator!=(CompactArray const& r) const { return !(*this == r); }
+
private:
uint32 _mask;
std::vector<T> _contents;
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 4dcf5fe9bc4..88fdbdc3305 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -789,7 +789,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_TOY_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_TRAINER_BUY_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::TrainerBuySpell, &WorldSession::HandleTrainerBuySpellOpcode);
DEFINE_HANDLER(CMSG_TRAINER_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleTrainerListOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_TRANSMOGRIFY_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems );
+ DEFINE_HANDLER(CMSG_TRANSMOGRIFY_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::TransmogrifyItems, &WorldSession::HandleTransmogrifyItems);
DEFINE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::TurnInPetition, &WorldSession::HandleTurnInPetition);
DEFINE_HANDLER(CMSG_TUTORIAL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::TutorialSetFlag, &WorldSession::HandleTutorialFlag);
DEFINE_HANDLER(CMSG_TWITTER_CHECK_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 8d31aefe48a..107a4350af6 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -319,6 +319,7 @@ namespace WorldPackets
class SwapItem;
class WrapItem;
class CancelTempEnchantment;
+ class TransmogrifyItems;
}
namespace Loot
@@ -1519,7 +1520,7 @@ class WorldSession
void SendVoidStorageTransferResult(VoidTransferError result);
// Transmogrification
- void HandleTransmogrifyItems(WorldPacket& recvData);
+ void HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems& transmogrifyItems);
// Miscellaneous
void HandleSpellClick(WorldPackets::Spells::SpellClick& spellClick);