From 3ce64b0f01d58a442ae63f3be5ccf84d488ea9f7 Mon Sep 17 00:00:00 2001 From: Andrius Peleckas <32540208+sanctum32@users.noreply.github.com> Date: Fri, 5 Nov 2021 16:56:45 +0200 Subject: [PATCH] feat(Core/Spells): implement two new custom attributes to handle aura saving rule (#8377) --- .../rev_1633787767742446400.sql | 6 +++ src/server/game/Spells/Auras/SpellAuras.cpp | 43 +++++++++++++---- src/server/game/Spells/SpellInfo.h | 20 ++++---- src/server/game/Spells/SpellMgr.cpp | 47 +++++++++++++------ 4 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1633787767742446400.sql diff --git a/data/sql/updates/pending_db_world/rev_1633787767742446400.sql b/data/sql/updates/pending_db_world/rev_1633787767742446400.sql new file mode 100644 index 000000000..61e986ee2 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1633787767742446400.sql @@ -0,0 +1,6 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1633787767742446400'); + +-- Raise Ally control aura should not be saved +DELETE FROM `spell_custom_attr` WHERE `spell_id` = '46619'; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES +('46619', '268435456'); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 20eb319d6..89f964e15 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1048,49 +1048,76 @@ bool Aura::IsRemovedOnShapeLost(Unit* target) const bool Aura::CanBeSaved() const { - if (IsPassive() || (GetSpellInfo()->HasAttribute(SPELL_ATTR0_DO_NOT_DISPLAY) && GetSpellInfo()->Stances)) + SpellInfo const* spellInfo = GetSpellInfo(); + + if (spellInfo->HasAttribute(SPELL_ATTR0_CU_FORCE_AURA_SAVING)) + { + return true; + } + + if (spellInfo->HasAttribute(SPELL_ATTR0_CU_REJECT_AURA_SAVING)) + { return false; + } + + if (IsPassive() || (spellInfo->HasAttribute(SPELL_ATTR0_DO_NOT_DISPLAY) && spellInfo->Stances)) + { + return false; + } // Xinef: do not save channel auras if (GetSpellInfo()->IsChanneled()) + { return false; + } // Xinef: Check if aura is single target, not only spell info - if (GetCasterGUID() != GetOwner()->GetGUID()) - if (GetSpellInfo()->IsSingleTarget() || IsSingleTarget()) - return false; + if (GetCasterGUID() != GetOwner()->GetGUID() && (GetSpellInfo()->IsSingleTarget() || IsSingleTarget())) + { + return false; + } // Xinef: Dont save control vehicle auras - caster may not exist if (HasEffectType(SPELL_AURA_CONTROL_VEHICLE)) + { return false; + } // Can't be saved - aura handler relies on calculated amount and changes it if (HasEffectType(SPELL_AURA_CONVERT_RUNE)) + { return false; + } // No point in saving this, since the stable dialog can't be open on aura load anyway. if (HasEffectType(SPELL_AURA_OPEN_STABLE)) + { return false; + } // xinef: do not save bind sight auras! if (HasEffectType(SPELL_AURA_BIND_SIGHT)) + { return false; + } // xinef: no charming auras (taking direct control) if (HasEffectType(SPELL_AURA_MOD_POSSESS) || HasEffectType(SPELL_AURA_MOD_POSSESS_PET)) + { return false; + } // xinef: no charming auras can be saved if (HasEffectType(SPELL_AURA_MOD_CHARM) || HasEffectType(SPELL_AURA_AOE_CHARM)) + { return false; - - // Xinef: Raise Ally control aura - if (GetId() == 46619) - return false; + } // don't save auras removed by proc system if (IsUsingCharges() && !GetCharges()) + { return false; + } return true; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index b0d984081..4d02717f5 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -201,6 +201,8 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_POSITIVE_EFF0 = 0x02000000, SPELL_ATTR0_CU_POSITIVE_EFF1 = 0x04000000, SPELL_ATTR0_CU_POSITIVE_EFF2 = 0x08000000, + SPELL_ATTR0_CU_REJECT_AURA_SAVING = 0x10000000, + SPELL_ATTR0_CU_FORCE_AURA_SAVING = 0x20000800, SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2, SPELL_ATTR0_CU_POSITIVE = SPELL_ATTR0_CU_POSITIVE_EFF0 | SPELL_ATTR0_CU_POSITIVE_EFF1 | SPELL_ATTR0_CU_POSITIVE_EFF2, @@ -403,15 +405,15 @@ public: bool HasAnyAura() const; bool HasAreaAuraEffect() const; - inline bool HasAttribute(SpellAttr0 attribute) const { return Attributes & attribute; } - inline bool HasAttribute(SpellAttr1 attribute) const { return AttributesEx & attribute; } - inline bool HasAttribute(SpellAttr2 attribute) const { return AttributesEx2 & attribute; } - inline bool HasAttribute(SpellAttr3 attribute) const { return AttributesEx3 & attribute; } - inline bool HasAttribute(SpellAttr4 attribute) const { return AttributesEx4 & attribute; } - inline bool HasAttribute(SpellAttr5 attribute) const { return AttributesEx5 & attribute; } - inline bool HasAttribute(SpellAttr6 attribute) const { return AttributesEx6 & attribute; } - inline bool HasAttribute(SpellAttr7 attribute) const { return AttributesEx7 & attribute; } - inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return AttributesCu & customAttribute; } + inline bool HasAttribute(SpellAttr0 attribute) const { return (Attributes & attribute) != 0; } + inline bool HasAttribute(SpellAttr1 attribute) const { return (AttributesEx & attribute) != 0; } + inline bool HasAttribute(SpellAttr2 attribute) const { return (AttributesEx2 & attribute) != 0; } + inline bool HasAttribute(SpellAttr3 attribute) const { return (AttributesEx3 & attribute) != 0; } + inline bool HasAttribute(SpellAttr4 attribute) const { return (AttributesEx4 & attribute) != 0; } + inline bool HasAttribute(SpellAttr5 attribute) const { return (AttributesEx5 & attribute) != 0; } + inline bool HasAttribute(SpellAttr6 attribute) const { return (AttributesEx6 & attribute) != 0; } + inline bool HasAttribute(SpellAttr7 attribute) const { return (AttributesEx7 & attribute) != 0; } + inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return (AttributesCu & customAttribute) != 0; } bool IsExplicitDiscovery() const; bool IsLootCrafting() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 4604f389a..0d7f1eff3 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2726,60 +2726,77 @@ void SpellMgr::LoadSpellSpecificAndAuraState() void SpellMgr::LoadSpellCustomAttr() { - uint32 oldMSTime = getMSTime(); - uint32 customAttrTime = getMSTime(); + uint32 const oldMSTime = getMSTime(); + uint32 const customAttrTime = getMSTime(); uint32 count; QueryResult result = WorldDatabase.Query("SELECT spell_id, attributes FROM spell_custom_attr"); if (!result) + { LOG_INFO("server.loading", ">> Loaded 0 spell custom attributes from DB. DB table `spell_custom_attr` is empty."); + } else { for (count = 0; result->NextRow(); ++count) { - Field* fields = result->Fetch(); + Field const* fields = result->Fetch(); - uint32 spellId = fields[0].GetUInt32(); + uint32 const spellId = fields[0].GetUInt32(); uint32 attributes = fields[1].GetUInt32(); SpellInfo* spellInfo = _GetSpellInfo(spellId); if (!spellInfo) { - LOG_INFO("spells", "Table `spell_custom_attr` has wrong spell (spell_id: %u), ignored.", spellId); + LOG_INFO("sql.sql", "Table `spell_custom_attr` has wrong spell (spell_id: %u), ignored.", spellId); continue; } - if ((attributes & SPELL_ATTR0_CU_NEGATIVE) != 0) + if (attributes & SPELL_ATTR0_CU_NEGATIVE) { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (spellInfo->Effects[i].IsEffect()) - continue; - - if ((attributes & (SPELL_ATTR0_CU_NEGATIVE_EFF0 << i)) != 0) { - LOG_ERROR("sql.sql", "Table `spell_custom_attr` has attribute SPELL_ATTR0_CU_NEGATIVE_EFF%u for spell %u with no EFFECT_%u", uint32(i), spellId, uint32(i)); + if ((attributes & (SPELL_ATTR0_CU_NEGATIVE_EFF0 << i)) && (attributes & (SPELL_ATTR0_CU_POSITIVE_EFF0 << i))) + { + LOG_ERROR("sql.sql", "Table `spell_custom_attr` has attribute SPELL_ATTR0_CU_NEGATIVE_EFF%u and SPELL_ATTR0_CU_POSITIVE_EFF%u attributes for spell %u which cannot stack together. Attributes will not get applied", static_cast(i), static_cast(i), spellId); + attributes &= ~(SPELL_ATTR0_CU_NEGATIVE_EFF0 << i)|(SPELL_ATTR0_CU_POSITIVE_EFF0 << i); + } continue; } + + if (attributes & (SPELL_ATTR0_CU_NEGATIVE_EFF0 << i)) + { + LOG_ERROR("sql.sql", "Table `spell_custom_attr` has attribute SPELL_ATTR0_CU_NEGATIVE_EFF%u for spell %u with no EFFECT_%u", static_cast(i), spellId, static_cast(i)); + attributes &= ~(SPELL_ATTR0_CU_NEGATIVE_EFF0 << i); + } } } - if ((attributes & SPELL_ATTR0_CU_POSITIVE) != 0) + if (attributes & SPELL_ATTR0_CU_POSITIVE) { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (spellInfo->Effects[i].IsEffect()) - continue; - - if ((attributes & (SPELL_ATTR0_CU_POSITIVE_EFF0 << i)) != 0) { - LOG_ERROR("sql.sql", "Table `spell_custom_attr` has attribute SPELL_ATTR0_CU_POSITIVE_EFF%u for spell %u with no EFFECT_%u", uint32(i), spellId, uint32(i)); continue; } + + if ((attributes & (SPELL_ATTR0_CU_POSITIVE_EFF0 << i))) + { + LOG_ERROR("sql.sql", "Table `spell_custom_attr` has attribute SPELL_ATTR0_CU_POSITIVE_EFF%u for spell %u with no EFFECT_%u", uint32(i), spellId, uint32(i)); + attributes &= ~(SPELL_ATTR0_CU_POSITIVE_EFF0 << i); + } } } + if ((attributes & SPELL_ATTR0_CU_FORCE_AURA_SAVING) && (attributes & SPELL_ATTR0_CU_REJECT_AURA_SAVING)) + { + LOG_ERROR("sql.sql", "Table `spell_custom_attr` attribute1 field has attributes SPELL_ATTR1_CU_FORCE_AURA_SAVING and SPELL_ATTR1_CU_REJECT_AURA_SAVING which cannot stack for spell %u. Both attributes will get applied", spellId); + attributes &= ~(SPELL_ATTR0_CU_FORCE_AURA_SAVING | SPELL_ATTR0_CU_REJECT_AURA_SAVING); + } + spellInfo->AttributesCu |= attributes; } LOG_INFO("server.loading", ">> Loaded %u spell custom attributes from DB in %u ms", count, GetMSTimeDiffToNow(customAttrTime));