aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-03-28 23:42:39 +0100
committerShauren <shauren.trinity@gmail.com>2025-03-28 23:42:39 +0100
commitdfcd41abefec371e6af9db7db92c1dd55aa701ff (patch)
tree732a3b27ad42c7c4ea68f742927ed1183eea6620 /src/server/game/Entities
parentba2847e7b82409bd721b872f7d6bb0b8653c28f2 (diff)
Core/Spells: Apply spell modifiers multiple times to each cast, based on number of matched SpellFamilyFlags bits
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Player/Player.cpp45
-rw-r--r--src/server/game/Entities/Player/Player.h2
2 files changed, 27 insertions, 20 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index cf8d7b08a6c..a8fe32ceb74 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -22403,45 +22403,45 @@ void Player::SendRemoveControlBar() const
SendDirectMessage(packet.Write());
}
-bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier const* mod, Spell* spell)
+uint32 Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier const* mod, Spell const* spell)
{
if (!mod || !spellInfo)
- return false;
+ return 0;
// First time this aura applies a mod to us and is out of charges
- if (spell && mod->ownerAura->IsUsingCharges() && !mod->ownerAura->GetCharges() && !spell->m_appliedMods.count(mod->ownerAura))
- return false;
+ if (spell && mod->ownerAura->IsUsingCharges() && !mod->ownerAura->GetCharges() && !spell->m_appliedMods.contains(mod->ownerAura))
+ return 0;
switch (mod->op)
{
case SpellModOp::Duration: // +duration to infinite duration spells making them limited
if (spellInfo->GetDuration() == -1)
- return false;
+ return 0;
break;
case SpellModOp::CritChance: // mod crit to spells that can't crit
if (!spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT))
- return false;
+ return 0;
break;
case SpellModOp::PointsIndex0: // check if spell has any effect at that index
case SpellModOp::Points:
if (spellInfo->GetEffects().size() <= EFFECT_0)
- return false;
+ return 0;
break;
case SpellModOp::PointsIndex1: // check if spell has any effect at that index
if (spellInfo->GetEffects().size() <= EFFECT_1)
- return false;
+ return 0;
break;
case SpellModOp::PointsIndex2: // check if spell has any effect at that index
if (spellInfo->GetEffects().size() <= EFFECT_2)
- return false;
+ return 0;
break;
case SpellModOp::PointsIndex3: // check if spell has any effect at that index
if (spellInfo->GetEffects().size() <= EFFECT_3)
- return false;
+ return 0;
break;
case SpellModOp::PointsIndex4: // check if spell has any effect at that index
if (spellInfo->GetEffects().size() <= EFFECT_4)
- return false;
+ return 0;
break;
default:
break;
@@ -22458,6 +22458,9 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell*
*flat = 0;
*pct = 1.0f;
+ if (!spellInfo->IsAffectedBySpellMods())
+ return;
+
auto spellModOpBegin = std::ranges::lower_bound(m_spellMods, op, std::ranges::less(), &SpellModifier::op);
if (spellModOpBegin == m_spellMods.end() || (*spellModOpBegin)->op != op)
return;
@@ -22587,33 +22590,36 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell*
for (SpellModifier* mod : spellModTypeRange(SPELLMOD_FLAT))
{
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ uint32 applyCount = IsAffectedBySpellmod(spellInfo, mod, spell);
+ if (!applyCount)
continue;
int32 value = static_cast<SpellModifierByClassMask*>(mod)->value;
if (value == 0)
continue;
- *flat += value;
+ *flat += value * applyCount;
Player::ApplyModToSpell(mod, spell);
}
for (SpellModifier* mod : spellModTypeRange(SPELLMOD_LABEL_FLAT))
{
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ uint32 applyCount = IsAffectedBySpellmod(spellInfo, mod, spell);
+ if (!applyCount)
continue;
int32 value = static_cast<SpellFlatModifierByLabel*>(mod)->value.ModifierValue;
if (value == 0)
continue;
- *flat += value;
+ *flat += value * applyCount;
Player::ApplyModToSpell(mod, spell);
}
for (SpellModifier* mod : spellModTypeRange(SPELLMOD_PCT))
{
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ uint32 applyCount = IsAffectedBySpellmod(spellInfo, mod, spell);
+ if (!applyCount)
continue;
// skip percent mods for null basevalue (most important for spell mods with charges)
@@ -22631,13 +22637,14 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell*
continue;
}
- *pct *= 1.0f + CalculatePct(1.0f, value);
+ *pct *= std::pow(1.0f + CalculatePct(1.0f, value), applyCount);
Player::ApplyModToSpell(mod, spell);
}
for (SpellModifier* mod : spellModTypeRange(SPELLMOD_LABEL_PCT))
{
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ uint32 applyCount = IsAffectedBySpellmod(spellInfo, mod, spell);
+ if (!applyCount)
continue;
// skip percent mods for null basevalue (most important for spell mods with charges)
@@ -22655,7 +22662,7 @@ void Player::GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell*
continue;
}
- *pct *= value;
+ *pct *= std::pow(value, applyCount);
Player::ApplyModToSpell(mod, spell);
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 36bf7c764eb..ae955a9b683 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1993,7 +1993,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
PlayerSpellMap & GetSpellMap() { return m_spells; }
void AddSpellMod(SpellModifier* mod, bool apply);
- static bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier const* mod, Spell* spell = nullptr);
+ static uint32 IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier const* mod, Spell const* spell = nullptr);
template <class T>
void GetSpellModValues(SpellInfo const* spellInfo, SpellModOp op, Spell* spell, T base, int32* flat, float* pct) const;
template <class T>