aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Item/Item.cpp118
-rw-r--r--src/server/game/Entities/Item/Item.h4
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp16
3 files changed, 114 insertions, 24 deletions
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index f87343b8670..d2b1a7e6c16 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -1329,9 +1329,9 @@ bool Item::CheckSoulboundTradeExpire()
return false;
}
-bool Item::CanBeTransmogrified(WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus)
+bool Item::IsValidTransmogrificationTarget() const
{
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(transmogrifier.ItemID);
+ ItemTemplate const* proto = GetTemplate();
if (!proto)
return false;
@@ -1348,15 +1348,15 @@ bool Item::CanBeTransmogrified(WorldPackets::Item::ItemInstance const& transmogr
if (proto->GetFlags2() & ITEM_FLAG2_CANNOT_BE_TRANSMOG)
return false;
- if (!HasStats(transmogrifier, bonus))
+ if (!HasStats())
return false;
return true;
}
-bool Item::CanTransmogrify() const
+bool Item::IsValidTransmogrificationSource(WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus)
{
- ItemTemplate const* proto = GetTemplate();
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(transmogrifier.ItemID);
if (!proto)
return false;
@@ -1376,7 +1376,7 @@ bool Item::CanTransmogrify() const
if (proto->GetFlags2() & ITEM_FLAG2_CAN_TRANSMOG)
return true;
- if (!HasStats())
+ if (!HasStats(transmogrifier, bonus))
return false;
return true;
@@ -1408,35 +1408,109 @@ bool Item::HasStats(WorldPackets::Item::ItemInstance const& itemInstance, BonusD
return false;
}
+enum class ItemTransmogrificationWeaponCategory : uint8
+{
+ // Two-handed
+ AXE_MACE_SWORD_2H,
+ STAFF_POLEARM,
+ RANGED,
+
+ // One-handed
+ AXE_MACE_SWORD_1H,
+ DAGGER,
+ FIST,
+
+ INVALID
+};
+
+static ItemTransmogrificationWeaponCategory GetTransmogrificationWeaponCategory(ItemTemplate const* proto)
+{
+ if (proto->GetClass() == ITEM_CLASS_WEAPON)
+ {
+ switch (proto->GetSubClass())
+ {
+ case ITEM_SUBCLASS_WEAPON_AXE2:
+ case ITEM_SUBCLASS_WEAPON_MACE2:
+ case ITEM_SUBCLASS_WEAPON_SWORD2:
+ return ItemTransmogrificationWeaponCategory::AXE_MACE_SWORD_2H;
+ case ITEM_SUBCLASS_WEAPON_STAFF:
+ case ITEM_SUBCLASS_WEAPON_POLEARM:
+ return ItemTransmogrificationWeaponCategory::STAFF_POLEARM;
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ return ItemTransmogrificationWeaponCategory::RANGED;
+ case ITEM_SUBCLASS_WEAPON_AXE:
+ case ITEM_SUBCLASS_WEAPON_MACE:
+ case ITEM_SUBCLASS_WEAPON_SWORD:
+ return ItemTransmogrificationWeaponCategory::AXE_MACE_SWORD_1H;
+ case ITEM_SUBCLASS_WEAPON_DAGGER:
+ return ItemTransmogrificationWeaponCategory::DAGGER;
+ case ITEM_SUBCLASS_WEAPON_FIST_WEAPON:
+ return ItemTransmogrificationWeaponCategory::FIST;
+ default:
+ break;
+ }
+ }
+
+ return ItemTransmogrificationWeaponCategory::INVALID;
+}
+
+InventoryType GetTransmogrificationInventoryType(ItemTemplate const* proto)
+{
+ InventoryType inventoryType = proto->GetInventoryType();
+ switch (proto->GetClass())
+ {
+ case ITEM_CLASS_WEAPON:
+ if (inventoryType == INVTYPE_WEAPONMAINHAND || inventoryType == INVTYPE_WEAPONOFFHAND)
+ inventoryType = INVTYPE_WEAPON;
+ break;
+ case ITEM_CLASS_ARMOR:
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
+ default:
+ break;
+ }
+ return inventoryType;
+}
+
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
+ ItemTemplate const* source = sObjectMgr->GetItemTemplate(transmogrifier.ItemID); // source
+ ItemTemplate const* target = transmogrified->GetTemplate(); // dest
- if (sDB2Manager.GetItemDisplayId(proto1->GetId(), bonus->AppearanceModID) == transmogrified->GetDisplayId())
+ if (!source || !target)
return false;
- if (!transmogrified->CanTransmogrify() || !CanBeTransmogrified(transmogrifier, bonus))
+ if (sDB2Manager.GetItemDisplayId(source->GetId(), bonus->AppearanceModID) == transmogrified->GetDisplayId())
return false;
- if (proto1->GetInventoryType() == INVTYPE_BAG ||
- proto1->GetInventoryType() == INVTYPE_RELIC ||
- proto1->GetInventoryType() == INVTYPE_BODY ||
- proto1->GetInventoryType() == INVTYPE_FINGER ||
- proto1->GetInventoryType() == INVTYPE_TRINKET ||
- proto1->GetInventoryType() == INVTYPE_AMMO ||
- proto1->GetInventoryType() == INVTYPE_QUIVER)
+ if (!IsValidTransmogrificationSource(transmogrifier, bonus) || !transmogrified->IsValidTransmogrificationTarget())
return false;
- if (proto1->GetSubClass() != proto2->GetSubClass() && (proto1->GetClass() != ITEM_CLASS_WEAPON || !proto2->IsRangedWeapon() || !proto1->IsRangedWeapon()))
+ if (source->GetClass() != target->GetClass())
return false;
- if (proto1->GetInventoryType() != proto2->GetInventoryType() &&
- (proto1->GetClass() != ITEM_CLASS_WEAPON || (proto2->GetInventoryType() != INVTYPE_WEAPONMAINHAND && proto2->GetInventoryType() != INVTYPE_WEAPONOFFHAND)) &&
- (proto1->GetClass() != ITEM_CLASS_ARMOR || (proto1->GetInventoryType() != INVTYPE_CHEST && proto2->GetInventoryType() != INVTYPE_ROBE && proto1->GetInventoryType() != INVTYPE_ROBE && proto2->GetInventoryType() != INVTYPE_CHEST)))
+ if (source->GetInventoryType() == INVTYPE_TABARD ||
+ source->GetInventoryType() == INVTYPE_BAG ||
+ source->GetInventoryType() == INVTYPE_RELIC ||
+ source->GetInventoryType() == INVTYPE_BODY ||
+ source->GetInventoryType() == INVTYPE_FINGER ||
+ source->GetInventoryType() == INVTYPE_TRINKET ||
+ source->GetInventoryType() == INVTYPE_AMMO ||
+ source->GetInventoryType() == INVTYPE_QUIVER)
return false;
- return true;
+ if (source->GetSubClass() != target->GetSubClass())
+ {
+ if (source->GetClass() != ITEM_CLASS_WEAPON)
+ return false;
+
+ if (GetTransmogrificationWeaponCategory(source) != GetTransmogrificationWeaponCategory(target))
+ return false;
+ }
+
+ return GetTransmogrificationInventoryType(source) == GetTransmogrificationInventoryType(target);
}
// used by mail items, transmog cost, stationeryinfo and others
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index e1cf177cc5b..7d1c3761430 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -424,8 +424,8 @@ class Item : public Object
uint32 GetScriptId() const { return GetTemplate()->ScriptId; }
- static bool CanBeTransmogrified(WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus);
- bool CanTransmogrify() const;
+ bool IsValidTransmogrificationTarget() const;
+ static bool IsValidTransmogrificationSource(WorldPackets::Item::ItemInstance const& transmogrifier, BonusData const* bonus);
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);
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index c2ae990e6c9..a85f6788e3a 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -1140,6 +1140,11 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems
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 (player->CanUseItem(itemTransmogrified->GetTemplate()) != EQUIP_ERR_OK)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify an unequippable item in a valid slot (slot: %u).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.Slot);
+ return;
+ }
WorldPackets::Item::ItemInstance itemInstance;
BonusData const* bonus = nullptr;
@@ -1152,6 +1157,11 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems
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;
}
+ if (player->CanUseItem(itemTransmogrifier->GetTemplate()) != EQUIP_ERR_OK)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an unequippable item (%s).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SrcItemGUID->ToString().c_str());
+ return;
+ }
itemInstance.Initialize(itemTransmogrifier);
bonus = itemTransmogrifier->GetBonus();
@@ -1167,6 +1177,12 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Item::TransmogrifyItems
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;
}
+ ItemTemplate const * transmogrifierTemplate = sObjectMgr->GetItemTemplate(itemTransmogrifier->ItemEntry);
+ if (player->CanUseItem(transmogrifierTemplate) != EQUIP_ERR_OK)
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (%s, name: %s) tried to transmogrify with an unequippable void storage item (%s).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SrcVoidItemGUID->ToString().c_str());
+ return;
+ }
itemInstance.Initialize(itemTransmogrifier);
std::pair<VoidStorageItem*, BonusData>& transmogData = transmogVoidItems[itemTransmogrified];