From dfcd41abefec371e6af9db7db92c1dd55aa701ff Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 28 Mar 2025 23:42:39 +0100 Subject: Core/Spells: Apply spell modifiers multiple times to each cast, based on number of matched SpellFamilyFlags bits --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 +- src/server/game/Spells/SpellInfo.cpp | 22 ++++++++++++++-------- src/server/game/Spells/SpellInfo.h | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src/server/game/Spells') diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4d2749f28e3..36d3c91e33d 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1203,7 +1203,7 @@ void AuraEffect::ApplySpellMod(Unit* target, bool apply, AuraEffect const* trigg // only passive and permament auras-active auras should have amount set on spellcast and not be affected // if aura is cast by others, it will not be affected if ((!aura->IsPassive() && !aura->IsPermanent() && !GetSpellInfo()->IsUpdatingTemporaryAuraValuesBySpellMod()) - || aura->GetCasterGUID() != guid || !aura->GetSpellInfo()->IsAffectedBySpellMod(m_spellmod)) + || aura->GetCasterGUID() != guid || !aura->GetSpellInfo()->IsAffectedBySpellMods() || !aura->GetSpellInfo()->IsAffectedBySpellMod(m_spellmod)) continue; if (recalculateEffectIndex) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 5cadd602089..95432f8f02c 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -37,6 +37,7 @@ #include "SpellMgr.h" #include "Vehicle.h" #include +#include uint32 GetTargetFlagMask(SpellTargetObjectTypes objType) { @@ -1892,11 +1893,8 @@ bool SpellInfo::IsAffectedBySpellMods() const return !HasAttribute(SPELL_ATTR3_IGNORE_CASTER_MODIFIERS); } -bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const +uint32 SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const { - if (!IsAffectedBySpellMods()) - return false; - SpellInfo const* affectSpell = sSpellMgr->GetSpellInfo(mod->spellId, Difficulty); if (!affectSpell) return false; @@ -1905,13 +1903,21 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const { case SPELLMOD_FLAT: case SPELLMOD_PCT: + { // TEMP: dont use IsAffected - !familyName and !familyFlags are not valid options for spell mods // TODO: investigate if the !familyName and !familyFlags conditions are even valid for all other (nonmod) uses of SpellInfo::IsAffected - return affectSpell->SpellFamilyName == SpellFamilyName && static_cast(mod)->mask & SpellFamilyFlags; + if (affectSpell->SpellFamilyName != SpellFamilyName) + return false; + + // spell modifiers should apply as many times as number of matched SpellFamilyFlags bits (verified with spell 1218116 with modifier 384451 in patch 11.1.0 and client tooltip code since at least 3.3.5) + // unknown if this is a bug or strange design choice... + FlagsArray matched = static_cast(mod)->mask & SpellFamilyFlags; + return std::popcount(matched[0]) + std::popcount(matched[1]) + std::popcount(matched[2]) + std::popcount(matched[3]); + } case SPELLMOD_LABEL_FLAT: - return HasLabel(static_cast(mod)->value.LabelID); + return HasLabel(static_cast(mod)->value.LabelID) ? 1 : 0; case SPELLMOD_LABEL_PCT: - return HasLabel(static_cast(mod)->value.LabelID); + return HasLabel(static_cast(mod)->value.LabelID) ? 1 : 0; default: break; } @@ -5013,5 +5019,5 @@ bool SpellInfo::MeetsFutureSpellPlayerCondition(Player const* player) const bool SpellInfo::HasLabel(uint32 labelId) const { - return Labels.find(labelId) != Labels.end(); + return Labels.contains(labelId); } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 0b5b168a9d5..f1e01769316 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -516,7 +516,7 @@ class TC_GAME_API SpellInfo bool IsAffected(uint32 familyName, flag128 const& familyFlags) const; bool IsAffectedBySpellMods() const; - bool IsAffectedBySpellMod(SpellModifier const* mod) const; + uint32 IsAffectedBySpellMod(SpellModifier const* mod) const; bool IsUpdatingTemporaryAuraValuesBySpellMod() const; bool CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const; -- cgit v1.2.3