mirror of
https://github.com/azerothcore/mod-transmog
synced 2025-11-29 22:48:30 +08:00
Code Cleanup, More Options and a Bugfix. (#158)
This commit is contained in:
@@ -153,6 +153,14 @@ Transmogrification.TokenAmount = 1
|
||||
# Description: Allow cloth items to be transmogrified with plate for example
|
||||
# Default: 0
|
||||
#
|
||||
# Transmogrification.AllowLowerTiers
|
||||
# Description: Allows using any armor tier the player can equip (i.e. Warrior plate->cloth | Mage cloth)
|
||||
# Default: 0
|
||||
#
|
||||
# Transmogrification.AllowMixedOffhandArmorTypes
|
||||
# Description: Allow shields, offhands (i.e. lamps), and bucklers to be used interchangeably
|
||||
# Default: 0
|
||||
#
|
||||
# Transmogrification.AllowMixedWeaponTypes
|
||||
# Description: Allow axe to be transmogrified with dagger for example
|
||||
# Possible options:
|
||||
@@ -208,6 +216,8 @@ Transmogrification.AllowHeirloom = 1
|
||||
Transmogrification.AllowTradeable = 0
|
||||
|
||||
Transmogrification.AllowMixedArmorTypes = 0
|
||||
Transmogrification.AllowLowerTiers = 0
|
||||
Transmogrification.AllowMixedOffhandArmorTypes = 0
|
||||
Transmogrification.AllowMixedWeaponTypes = 0
|
||||
Transmogrification.AllowMixedWeaponHandedness = 0
|
||||
Transmogrification.AllowFishingPoles = 0
|
||||
|
||||
@@ -625,87 +625,119 @@ bool Transmogrification::CanTransmogrifyItemWithItem(Player* player, ItemTemplat
|
||||
if (IsRangedWeapon(source->Class, source->SubClass) != IsRangedWeapon(target->Class, target->SubClass))
|
||||
return false;
|
||||
|
||||
if (source->SubClass != target->SubClass && !IsRangedWeapon(target->Class, target->SubClass))
|
||||
{
|
||||
if (!IsAllowed(source->ItemId))
|
||||
{
|
||||
if (source->Class == ITEM_CLASS_ARMOR && !AllowMixedArmorTypes)
|
||||
if (source->SubClass != target->SubClass && !IsSubclassMismatchAllowed(player, source, target))
|
||||
return false;
|
||||
if (source->Class == ITEM_CLASS_WEAPON)
|
||||
{
|
||||
if (AllowMixedWeaponTypes == MIXED_WEAPONS_STRICT)
|
||||
{
|
||||
|
||||
if (source->InventoryType != target->InventoryType && !IsInvTypeMismatchAllowed(source, target))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Transmogrification::IsSubclassMismatchAllowed(Player *player, const ItemTemplate *source, const ItemTemplate *target) const
|
||||
{
|
||||
if (IsAllowed(source->ItemId)) return true;
|
||||
|
||||
uint32 sourceType = source->InventoryType;
|
||||
uint32 targetType = target->InventoryType;
|
||||
uint32 sourceClass = source->Class;
|
||||
uint32 targetClass = target->Class;
|
||||
uint32 sourceSub = source->SubClass;
|
||||
uint32 targetSub = target->SubClass;
|
||||
|
||||
if (targetClass == ITEM_CLASS_WEAPON)
|
||||
{
|
||||
if (IsRangedWeapon(sourceClass, sourceSub))
|
||||
return true;
|
||||
|
||||
if (AllowMixedWeaponTypes == MIXED_WEAPONS_MODERN)
|
||||
{
|
||||
switch (source->SubClass)
|
||||
switch (targetSub)
|
||||
{
|
||||
case ITEM_SUBCLASS_WEAPON_WAND:
|
||||
case ITEM_SUBCLASS_WEAPON_DAGGER:
|
||||
case ITEM_SUBCLASS_WEAPON_FIST:
|
||||
return false;
|
||||
case ITEM_SUBCLASS_WEAPON_AXE:
|
||||
case ITEM_SUBCLASS_WEAPON_SWORD:
|
||||
case ITEM_SUBCLASS_WEAPON_MACE:
|
||||
if (target->SubClass != ITEM_SUBCLASS_WEAPON_MACE &&
|
||||
target->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
|
||||
target->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (sourceSub == ITEM_SUBCLASS_WEAPON_AXE ||
|
||||
sourceSub == ITEM_SUBCLASS_WEAPON_SWORD ||
|
||||
sourceSub == ITEM_SUBCLASS_WEAPON_MACE )
|
||||
return true;
|
||||
break;
|
||||
case ITEM_SUBCLASS_WEAPON_AXE2:
|
||||
case ITEM_SUBCLASS_WEAPON_SWORD2:
|
||||
case ITEM_SUBCLASS_WEAPON_MACE2:
|
||||
case ITEM_SUBCLASS_WEAPON_STAFF:
|
||||
case ITEM_SUBCLASS_WEAPON_POLEARM:
|
||||
if (target->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 &&
|
||||
target->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 &&
|
||||
target->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
|
||||
target->SubClass != ITEM_SUBCLASS_WEAPON_STAFF &&
|
||||
target->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM)
|
||||
if (sourceSub == ITEM_SUBCLASS_WEAPON_AXE2 ||
|
||||
sourceSub == ITEM_SUBCLASS_WEAPON_SWORD2 ||
|
||||
sourceSub == ITEM_SUBCLASS_WEAPON_MACE2 ||
|
||||
sourceSub == ITEM_SUBCLASS_WEAPON_STAFF ||
|
||||
sourceSub == ITEM_SUBCLASS_WEAPON_POLEARM )
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (AllowMixedWeaponTypes == MIXED_WEAPONS_LOOSE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (targetClass == ITEM_CLASS_ARMOR)
|
||||
{
|
||||
if (AllowMixedArmorTypes)
|
||||
return true;
|
||||
if (AllowLowerTiers && IsTieredArmorSubclass(targetSub) && TierAvailable(player, 0, sourceSub))
|
||||
return true;
|
||||
if (AllowMixedOffhandArmorTypes && IsValidOffhandArmor(targetSub, targetType) && IsValidOffhandArmor(sourceSub, sourceType))
|
||||
return true;
|
||||
if (sourceSub == ITEM_SUBCLASS_ARMOR_MISC)
|
||||
return sourceType == targetType;
|
||||
}
|
||||
|
||||
if (source->InventoryType != target->InventoryType)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Transmogrification::IsInvTypeMismatchAllowed(const ItemTemplate *source, const ItemTemplate *target) const
|
||||
{
|
||||
uint32 sourceType = source->InventoryType;
|
||||
uint32 targetType = target->InventoryType;
|
||||
uint32 sourceClass = source->Class;
|
||||
uint32 targetClass = target->Class;
|
||||
uint32 sourceSub = source->SubClass;
|
||||
uint32 targetSub = target->SubClass;
|
||||
|
||||
if (targetClass == ITEM_CLASS_WEAPON)
|
||||
{
|
||||
if (IsRangedWeapon(sourceClass, sourceSub))
|
||||
return true;
|
||||
|
||||
// Main-hand to offhand restrictions - see https://wowpedia.fandom.com/wiki/Transmogrification
|
||||
if (!AllowMixedWeaponHandedness && AllowMixedWeaponTypes != MIXED_WEAPONS_LOOSE)
|
||||
if (targetType == INVTYPE_WEAPONMAINHAND || targetType == INVTYPE_WEAPONOFFHAND)
|
||||
{
|
||||
if ((source->InventoryType == INVTYPE_WEAPONMAINHAND && target->InventoryType != INVTYPE_WEAPONMAINHAND) ||
|
||||
(source->InventoryType == INVTYPE_WEAPONOFFHAND && target->InventoryType != INVTYPE_WEAPONOFFHAND))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (source->Class == ITEM_CLASS_WEAPON && !(IsRangedWeapon(target->Class, target->SubClass) ||
|
||||
(
|
||||
// [AZTH] Yehonal: fixed weapon check
|
||||
(target->InventoryType == INVTYPE_WEAPON || target->InventoryType == INVTYPE_2HWEAPON || target->InventoryType == INVTYPE_WEAPONMAINHAND || target->InventoryType == INVTYPE_WEAPONOFFHAND)
|
||||
&& (source->InventoryType == INVTYPE_WEAPON || source->InventoryType == INVTYPE_2HWEAPON || source->InventoryType == INVTYPE_WEAPONMAINHAND || source->InventoryType == INVTYPE_WEAPONOFFHAND)
|
||||
)
|
||||
))
|
||||
return false;
|
||||
if (source->Class == ITEM_CLASS_ARMOR &&
|
||||
!((source->InventoryType == INVTYPE_CHEST || source->InventoryType == INVTYPE_ROBE) &&
|
||||
(target->InventoryType == INVTYPE_CHEST || target->InventoryType == INVTYPE_ROBE)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AllowMixedWeaponTypes == MIXED_WEAPONS_LOOSE)
|
||||
return true;
|
||||
if (sourceType == INVTYPE_WEAPONMAINHAND || sourceType == INVTYPE_WEAPONOFFHAND)
|
||||
return (AllowMixedWeaponHandedness || AllowMixedWeaponTypes == MIXED_WEAPONS_LOOSE);
|
||||
}
|
||||
}
|
||||
else if (targetClass == ITEM_CLASS_ARMOR)
|
||||
{
|
||||
if (AllowMixedOffhandArmorTypes && IsValidOffhandArmor(targetSub, targetType) && IsValidOffhandArmor(sourceSub, sourceType))
|
||||
return true;
|
||||
if (targetType == INVTYPE_CHEST || targetType == INVTYPE_ROBE)
|
||||
return sourceType == INVTYPE_CHEST || sourceType == INVTYPE_ROBE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Transmogrification::IsValidOffhandArmor(uint32 subclass, uint32 invType) const
|
||||
{
|
||||
return subclass == ITEM_SUBCLASS_ARMOR_BUCKLER || (subclass == ITEM_SUBCLASS_ARMOR_MISC && invType == INVTYPE_HOLDABLE) || subclass == ITEM_SUBCLASS_ARMOR_SHIELD;
|
||||
}
|
||||
|
||||
bool Transmogrification::IsTieredArmorSubclass(uint32 subclass) const
|
||||
{
|
||||
return subclass == ITEM_SUBCLASS_ARMOR_PLATE || subclass == ITEM_SUBCLASS_ARMOR_MAIL || subclass == ITEM_SUBCLASS_ARMOR_LEATHER || subclass == ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
}
|
||||
|
||||
bool Transmogrification::SuitableForTransmogrification(Player* player, ItemTemplate const* proto) const
|
||||
@@ -763,6 +795,9 @@ bool Transmogrification::SuitableForTransmogrification(Player* player, ItemTempl
|
||||
if (!IgnoreReqLevel && player->GetLevel() < proto->RequiredLevel)
|
||||
return false;
|
||||
|
||||
if (AllowLowerTiers && TierAvailable(player, 0, proto->SubClass))
|
||||
return true;
|
||||
|
||||
if (!IgnoreReqSpell && proto->RequiredSpell != 0 && !player->HasSpell(proto->RequiredSpell))
|
||||
return false;
|
||||
|
||||
@@ -849,12 +884,65 @@ bool Transmogrification::SuitableForTransmogrification(ObjectGuid guid, ItemTemp
|
||||
if (!IgnoreReqLevel && playerLevel < proto->RequiredLevel)
|
||||
return false;
|
||||
|
||||
if (AllowLowerTiers && TierAvailable(NULL, playerGuid, proto->SubClass))
|
||||
return true;
|
||||
|
||||
if (!IgnoreReqSpell && proto->RequiredSpell != 0 && !(CharacterDatabase.Query("SELECT `spell` FROM `character_spell` WHERE `guid` = {} and `spell` = {}", playerGuid, proto->RequiredSpell)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Transmogrification::TierAvailable(Player *player, int playerGuid, uint32 tier) const
|
||||
{
|
||||
if (!player && !playerGuid) return false;
|
||||
if (!IsTieredArmorSubclass(tier)) return false;
|
||||
|
||||
uint32 playerHighest = ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
if (player)
|
||||
playerHighest = GetHighestAvailableForPlayer(player);
|
||||
else if (playerGuid)
|
||||
playerHighest = GetHighestAvailableForPlayer(playerGuid);
|
||||
|
||||
switch (playerHighest)
|
||||
{
|
||||
case ITEM_SUBCLASS_ARMOR_PLATE:
|
||||
return true;
|
||||
case ITEM_SUBCLASS_ARMOR_MAIL:
|
||||
return tier != ITEM_SUBCLASS_ARMOR_PLATE;
|
||||
case ITEM_SUBCLASS_ARMOR_LEATHER:
|
||||
return tier == ITEM_SUBCLASS_ARMOR_LEATHER || tier == ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
case ITEM_SUBCLASS_ARMOR_CLOTH:
|
||||
return tier == ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 Transmogrification::GetHighestAvailableForPlayer(int playerGuid) const
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (CharacterDatabase.Query("SELECT `spell` FROM `character_spell` WHERE `guid` = {} and `spell` = {}", playerGuid, AllArmorSpellIds[i]))
|
||||
return AllArmorTiers[i];
|
||||
}
|
||||
|
||||
return ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
}
|
||||
|
||||
uint32 Transmogrification::GetHighestAvailableForPlayer(Player *player) const
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (player->HasSpell(AllArmorSpellIds[i]))
|
||||
return AllArmorTiers[i];
|
||||
}
|
||||
|
||||
return ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
}
|
||||
|
||||
bool Transmogrification::IsItemTransmogrifiable(ItemTemplate const* proto, ObjectGuid const &playerGuid) const
|
||||
{
|
||||
if (!proto)
|
||||
@@ -1015,6 +1103,8 @@ void Transmogrification::LoadConfig(bool reload)
|
||||
AllowTradeable = sConfigMgr->GetOption<bool>("Transmogrification.AllowTradeable", false);
|
||||
|
||||
AllowMixedArmorTypes = sConfigMgr->GetOption<bool>("Transmogrification.AllowMixedArmorTypes", false);
|
||||
AllowLowerTiers = sConfigMgr->GetOption<bool>("Transmogrification.AllowLowerTiers", false);
|
||||
AllowMixedOffhandArmorTypes = sConfigMgr->GetOption<bool>("Transmogrification.AllowMixedOffhandArmorTypes", false);
|
||||
AllowMixedWeaponHandedness = sConfigMgr->GetOption<bool>("Transmogrification.AllowMixedWeaponHandedness", false);
|
||||
AllowFishingPoles = sConfigMgr->GetOption<bool>("Transmogrification.AllowFishingPoles", false);
|
||||
|
||||
@@ -1191,6 +1281,14 @@ bool Transmogrification::GetAllowMixedArmorTypes() const
|
||||
{
|
||||
return AllowMixedArmorTypes;
|
||||
};
|
||||
bool Transmogrification::GetAllowLowerTiers() const
|
||||
{
|
||||
return AllowLowerTiers;
|
||||
};
|
||||
bool Transmogrification::GetAllowMixedOffhandArmorTypes() const
|
||||
{
|
||||
return AllowMixedOffhandArmorTypes;
|
||||
};
|
||||
uint8 Transmogrification::GetAllowMixedWeaponTypes() const
|
||||
{
|
||||
return AllowMixedWeaponTypes;
|
||||
|
||||
@@ -63,6 +63,30 @@ enum TransmogAcoreStrings // Language.h might have same entries, appears when ex
|
||||
LANG_CMD_TRANSMOG_COMPLETE_SYNC = 11116,
|
||||
};
|
||||
|
||||
enum ArmorClassSpellIDs
|
||||
{
|
||||
SPELL_PLATE = 750,
|
||||
SPELL_MAIL = 8737,
|
||||
SPELL_LEATHER = 9077,
|
||||
SPELL_CLOTH = 9078
|
||||
};
|
||||
|
||||
const uint32 AllArmorSpellIds[4] =
|
||||
{
|
||||
SPELL_PLATE,
|
||||
SPELL_MAIL,
|
||||
SPELL_LEATHER,
|
||||
SPELL_CLOTH
|
||||
};
|
||||
|
||||
const uint32 AllArmorTiers[4] =
|
||||
{
|
||||
ITEM_SUBCLASS_ARMOR_PLATE,
|
||||
ITEM_SUBCLASS_ARMOR_MAIL,
|
||||
ITEM_SUBCLASS_ARMOR_LEATHER,
|
||||
ITEM_SUBCLASS_ARMOR_CLOTH
|
||||
};
|
||||
|
||||
class Transmogrification
|
||||
{
|
||||
public:
|
||||
@@ -134,6 +158,8 @@ public:
|
||||
bool AllowTradeable;
|
||||
|
||||
bool AllowMixedArmorTypes;
|
||||
bool AllowLowerTiers;
|
||||
bool AllowMixedOffhandArmorTypes;
|
||||
bool AllowMixedWeaponHandedness;
|
||||
bool AllowFishingPoles;
|
||||
|
||||
@@ -193,6 +219,8 @@ public:
|
||||
uint32 GetTokenAmount() const;
|
||||
|
||||
bool GetAllowMixedArmorTypes() const;
|
||||
bool GetAllowLowerTiers() const;
|
||||
bool GetAllowMixedOffhandArmorTypes() const;
|
||||
uint8 GetAllowMixedWeaponTypes() const;
|
||||
|
||||
// Config
|
||||
@@ -209,6 +237,17 @@ public:
|
||||
bool EnableResetRetroActiveAppearances() const;
|
||||
[[nodiscard]] bool IsEnabled() const;
|
||||
|
||||
bool IsValidOffhandArmor(uint32 subclass, uint32 invType) const;
|
||||
bool IsTieredArmorSubclass(uint32 subclass) const;
|
||||
|
||||
uint32 GetHighestAvailableForPlayer(Player* player) const;
|
||||
uint32 GetHighestAvailableForPlayer(int playerGuid) const;
|
||||
|
||||
bool TierAvailable(Player* player, int playerGuid, uint32 tierSpell) const;
|
||||
|
||||
bool IsInvTypeMismatchAllowed (const ItemTemplate *source, const ItemTemplate *target) const;
|
||||
bool IsSubclassMismatchAllowed (Player *player, const ItemTemplate *source, const ItemTemplate *target) const;
|
||||
|
||||
// Transmog Plus
|
||||
bool IsTransmogPlusEnabled;
|
||||
std::vector<uint32> MembershipIds;
|
||||
|
||||
Reference in New Issue
Block a user