mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Items: Implemented many new enchantment flags
This commit is contained in:
@@ -3347,6 +3347,8 @@ struct SpellItemEnchantmentEntry
|
||||
uint8 ConditionID;
|
||||
uint8 MinLevel;
|
||||
uint8 MaxLevel;
|
||||
|
||||
EnumFlag<SpellItemEnchantmentFlags> GetFlags() const { return static_cast<SpellItemEnchantmentFlags>(Flags); }
|
||||
};
|
||||
|
||||
struct SpellItemEnchantmentConditionEntry
|
||||
|
||||
@@ -1485,16 +1485,22 @@ DEFINE_ENUM_FLAG(SpellEffectAttributes);
|
||||
|
||||
#define MAX_SPELL_AURA_INTERRUPT_FLAGS 2
|
||||
|
||||
enum SpellItemEnchantmentFlags
|
||||
enum class SpellItemEnchantmentFlags : uint16
|
||||
{
|
||||
ENCHANTMENT_CAN_SOULBOUND = 0x01,
|
||||
ENCHANTMENT_UNK1 = 0x02,
|
||||
ENCHANTMENT_UNK2 = 0x04,
|
||||
ENCHANTMENT_UNK3 = 0x08,
|
||||
ENCHANTMENT_COLLECTABLE = 0x100,
|
||||
ENCHANTMENT_HIDE_IF_NOT_COLLECTED = 0x200,
|
||||
Soulbound = 0x001,
|
||||
DoNotLog = 0x002,
|
||||
MainhandOnly = 0x004,
|
||||
AllowEnteringArena = 0x008,
|
||||
DoNotSaveToDB = 0x010,
|
||||
ScaleAsAGem = 0x020,
|
||||
DisableInChallengeModes = 0x040,
|
||||
DisableInProvingGrounds = 0x080,
|
||||
AllowTransmog = 0x100,
|
||||
HideUntilCollected = 0x200,
|
||||
};
|
||||
|
||||
DEFINE_ENUM_FLAG(SpellItemEnchantmentFlags);
|
||||
|
||||
enum SpellProcsPerMinuteModType
|
||||
{
|
||||
SPELL_PPM_MOD_HASTE = 1,
|
||||
|
||||
@@ -580,9 +580,17 @@ void Item::SaveToDB(CharacterDatabaseTransaction& trans)
|
||||
std::ostringstream ssEnchants;
|
||||
for (uint8 i = 0; i < MAX_ENCHANTMENT_SLOT; ++i)
|
||||
{
|
||||
ssEnchants << GetEnchantmentId(EnchantmentSlot(i)) << ' ';
|
||||
ssEnchants << GetEnchantmentDuration(EnchantmentSlot(i)) << ' ';
|
||||
ssEnchants << GetEnchantmentCharges(EnchantmentSlot(i)) << ' ';
|
||||
if (SpellItemEnchantmentEntry const* enchantment = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(EnchantmentSlot(i)));
|
||||
enchantment && !enchantment->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotSaveToDB))
|
||||
{
|
||||
ssEnchants << GetEnchantmentId(EnchantmentSlot(i)) << ' ';
|
||||
ssEnchants << GetEnchantmentDuration(EnchantmentSlot(i)) << ' ';
|
||||
ssEnchants << GetEnchantmentCharges(EnchantmentSlot(i)) << ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
ssEnchants << "0 0 0 ";
|
||||
}
|
||||
}
|
||||
stmt->setString(++index, ssEnchants.str());
|
||||
|
||||
@@ -1303,7 +1311,7 @@ bool Item::IsBoundByEnchant() const
|
||||
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
|
||||
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
|
||||
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
|
||||
if (enchantEntry->Flags & ENCHANTMENT_CAN_SOULBOUND)
|
||||
if (enchantEntry->GetFlags().HasFlag(SpellItemEnchantmentFlags::Soulbound))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -1369,11 +1377,13 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint
|
||||
Player* owner = GetOwner();
|
||||
if (slot < MAX_INSPECTED_ENCHANTMENT_SLOT)
|
||||
{
|
||||
if (uint32 oldEnchant = GetEnchantmentId(slot))
|
||||
owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), ObjectGuid::Empty, GetGUID(), GetEntry(), oldEnchant, slot);
|
||||
if (SpellItemEnchantmentEntry const* oldEnchant = sSpellItemEnchantmentStore.LookupEntry(GetEnchantmentId(slot)))
|
||||
if (!oldEnchant->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotLog))
|
||||
owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), ObjectGuid::Empty, GetGUID(), GetEntry(), oldEnchant->ID, slot);
|
||||
|
||||
if (id)
|
||||
owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, slot);
|
||||
if (SpellItemEnchantmentEntry const* newEnchant = sSpellItemEnchantmentStore.LookupEntry(id))
|
||||
if (!newEnchant->GetFlags().HasFlag(SpellItemEnchantmentFlags::DoNotLog))
|
||||
owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, slot);
|
||||
}
|
||||
|
||||
ApplyArtifactPowerEnchantmentBonuses(slot, GetEnchantmentId(slot), false, owner);
|
||||
|
||||
@@ -12365,6 +12365,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
|
||||
case EQUIPMENT_SLOT_MAINHAND:
|
||||
case EQUIPMENT_SLOT_OFFHAND:
|
||||
RecalculateRating(CR_ARMOR_PENETRATION);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -12621,9 +12622,17 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
|
||||
// remove item dependent auras and casts (only weapon and armor slots)
|
||||
if (slot < EQUIPMENT_SLOT_END)
|
||||
{
|
||||
// remove held enchantments, update expertise
|
||||
// update expertise
|
||||
if (slot == EQUIPMENT_SLOT_MAINHAND)
|
||||
{
|
||||
// clear main hand only enchantments
|
||||
for (uint32 enchantSlot = 0; enchantSlot < MAX_ENCHANTMENT_SLOT; ++enchantSlot)
|
||||
if (SpellItemEnchantmentEntry const* enchantment = sSpellItemEnchantmentStore.LookupEntry(pItem->GetEnchantmentId(EnchantmentSlot(enchantSlot))))
|
||||
if (enchantment->GetFlags().HasFlag(SpellItemEnchantmentFlags::MainhandOnly))
|
||||
pItem->ClearEnchantment(EnchantmentSlot(enchantSlot));
|
||||
|
||||
UpdateExpertise(BASE_ATTACK);
|
||||
}
|
||||
else if (slot == EQUIPMENT_SLOT_OFFHAND)
|
||||
UpdateExpertise(OFF_ATTACK);
|
||||
// update armor penetration - passive auras may need it
|
||||
@@ -12632,6 +12641,7 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
|
||||
case EQUIPMENT_SLOT_MAINHAND:
|
||||
case EQUIPMENT_SLOT_OFFHAND:
|
||||
RecalculateRating(CR_ARMOR_PENETRATION);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -14056,7 +14066,7 @@ void Player::RemoveArenaEnchantments(EnchantmentSlot slot)
|
||||
uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
|
||||
for (uint8 i = INVENTORY_SLOT_ITEM_START; i < inventoryEnd; ++i)
|
||||
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
|
||||
if (pItem->GetEnchantmentId(slot))
|
||||
if (!sSpellMgr->IsArenaAllowedEnchancment(pItem->GetEnchantmentId(slot)))
|
||||
pItem->ClearEnchantment(slot);
|
||||
|
||||
// in inventory bags
|
||||
@@ -14064,7 +14074,7 @@ void Player::RemoveArenaEnchantments(EnchantmentSlot slot)
|
||||
if (Bag* pBag = GetBagByPos(i))
|
||||
for (uint32 j = 0; j < pBag->GetBagSize(); j++)
|
||||
if (Item* pItem = pBag->GetItemByPos(j))
|
||||
if (pItem->GetEnchantmentId(slot))
|
||||
if (!sSpellMgr->IsArenaAllowedEnchancment(pItem->GetEnchantmentId(slot)))
|
||||
pItem->ClearEnchantment(slot);
|
||||
}
|
||||
|
||||
|
||||
@@ -1926,7 +1926,7 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm
|
||||
if (!illusion)
|
||||
return false;
|
||||
|
||||
if (!illusion->ItemVisual || !(illusion->Flags & ENCHANTMENT_COLLECTABLE))
|
||||
if (!illusion->ItemVisual || !illusion->GetFlags().HasFlag(SpellItemEnchantmentFlags::AllowTransmog))
|
||||
return false;
|
||||
|
||||
if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogUseConditionID))
|
||||
|
||||
@@ -135,7 +135,7 @@ void WorldSession::HandleTransmogrifyItems(WorldPackets::Transmogrification::Tra
|
||||
return;
|
||||
}
|
||||
|
||||
if (!illusion->ItemVisual || !(illusion->Flags & ENCHANTMENT_COLLECTABLE))
|
||||
if (!illusion->ItemVisual || !illusion->GetFlags().HasFlag(SpellItemEnchantmentFlags::AllowTransmog))
|
||||
{
|
||||
TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - %s, Name: %s tried to transmogrify illusion using not allowed enchant (%d).", player->GetGUID().ToString().c_str(), player->GetName().c_str(), transmogItem.SpellItemEnchantmentID);
|
||||
return;
|
||||
|
||||
@@ -7087,7 +7087,7 @@ SpellCastResult Spell::CheckItems(int32* param1 /*= nullptr*/, int32* param2 /*=
|
||||
{
|
||||
if (!enchantEntry)
|
||||
return SPELL_FAILED_ERROR;
|
||||
if (enchantEntry->Flags & ENCHANTMENT_CAN_SOULBOUND)
|
||||
if (enchantEntry->GetFlags().HasFlag(SpellItemEnchantmentFlags::Soulbound))
|
||||
return SPELL_FAILED_NOT_TRADEABLE;
|
||||
}
|
||||
break;
|
||||
@@ -7101,10 +7101,10 @@ SpellCastResult Spell::CheckItems(int32* param1 /*= nullptr*/, int32* param2 /*=
|
||||
if (item->GetOwner() != player)
|
||||
{
|
||||
uint32 enchant_id = spellEffectInfo.MiscValue;
|
||||
SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
|
||||
if (!pEnchant)
|
||||
SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
|
||||
if (!enchantEntry)
|
||||
return SPELL_FAILED_ERROR;
|
||||
if (pEnchant->Flags & ENCHANTMENT_CAN_SOULBOUND)
|
||||
if (enchantEntry->GetFlags().HasFlag(SpellItemEnchantmentFlags::Soulbound))
|
||||
return SPELL_FAILED_NOT_TRADEABLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -634,7 +634,10 @@ SpellEnchantProcEntry const* SpellMgr::GetSpellEnchantProcEvent(uint32 enchId) c
|
||||
|
||||
bool SpellMgr::IsArenaAllowedEnchancment(uint32 ench_id) const
|
||||
{
|
||||
return mEnchantCustomAttr[ench_id];
|
||||
if (SpellItemEnchantmentEntry const* enchantment = sSpellItemEnchantmentStore.LookupEntry(ench_id))
|
||||
return enchantment->GetFlags().HasFlag(SpellItemEnchantmentFlags::AllowEnteringArena);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int32> const* SpellMgr::GetSpellLinked(int32 spell_id) const
|
||||
@@ -1988,42 +1991,6 @@ void SpellMgr::LoadSpellPetAuras()
|
||||
TC_LOG_INFO("server.loading", ">> Loaded %u spell pet auras in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
// Fill custom data about enchancments
|
||||
void SpellMgr::LoadEnchantCustomAttr()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
uint32 size = sSpellItemEnchantmentStore.GetNumRows();
|
||||
mEnchantCustomAttr.resize(size);
|
||||
|
||||
for (uint32 i = 0; i < size; ++i)
|
||||
mEnchantCustomAttr[i] = false;
|
||||
|
||||
uint32 count = 0;
|
||||
for (SpellInfo const& spellInfo : mSpellInfoMap)
|
||||
{
|
||||
/// @todo find a better check
|
||||
if (!spellInfo.HasAttribute(SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !spellInfo.HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT))
|
||||
continue;
|
||||
|
||||
for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects())
|
||||
{
|
||||
if (spellEffectInfo.Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY)
|
||||
{
|
||||
uint32 enchId = spellEffectInfo.MiscValue;
|
||||
SpellItemEnchantmentEntry const* ench = sSpellItemEnchantmentStore.LookupEntry(enchId);
|
||||
if (!ench)
|
||||
continue;
|
||||
mEnchantCustomAttr[enchId] = true;
|
||||
++count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded %u custom enchant attributes in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
void SpellMgr::LoadSpellEnchantProcData()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
@@ -578,8 +578,6 @@ struct PetDefaultSpellsEntry
|
||||
// < 0 for petspelldata id, > 0 for creature_id
|
||||
typedef std::map<int32, PetDefaultSpellsEntry> PetDefaultSpellsMap;
|
||||
|
||||
typedef std::vector<bool> EnchantCustomAttribute;
|
||||
|
||||
typedef std::unordered_map<int32, std::vector<int32>> SpellLinkedMap;
|
||||
|
||||
bool IsPrimaryProfessionSkill(uint32 skill);
|
||||
@@ -739,7 +737,6 @@ class TC_GAME_API SpellMgr
|
||||
void LoadSpellThreats();
|
||||
void LoadSkillLineAbilityMap();
|
||||
void LoadSpellPetAuras();
|
||||
void LoadEnchantCustomAttr();
|
||||
void LoadSpellEnchantProcData();
|
||||
void LoadSpellLinked();
|
||||
void LoadPetLevelupSpellMap();
|
||||
@@ -772,7 +769,6 @@ class TC_GAME_API SpellMgr
|
||||
SpellPetAuraMap mSpellPetAuraMap;
|
||||
SpellLinkedMap mSpellLinkedMap;
|
||||
SpellEnchantProcEventMap mSpellEnchantProcEventMap;
|
||||
EnchantCustomAttribute mEnchantCustomAttr;
|
||||
SpellAreaMap mSpellAreaMap;
|
||||
SpellAreaForQuestMap mSpellAreaForQuestMap;
|
||||
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
|
||||
|
||||
@@ -2080,9 +2080,6 @@ void World::SetInitialWorldSettings()
|
||||
TC_LOG_INFO("server.loading", "Loading Spell target coordinates...");
|
||||
sSpellMgr->LoadSpellTargetPositions();
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading enchant custom attributes...");
|
||||
sSpellMgr->LoadEnchantCustomAttr();
|
||||
|
||||
TC_LOG_INFO("server.loading", "Loading linked spells...");
|
||||
sSpellMgr->LoadSpellLinked();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user