aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2018-02-12 03:09:22 -0300
committerariel- <ariel-@users.noreply.github.com>2018-02-12 03:09:22 -0300
commite73bfe8df89e4fb6aecc7cb3a1e266e868510799 (patch)
tree34dba2a558f73b06202ed1a0b9aa90212c111958 /src/server/game/Entities
parent3edf90d16758632e1ab0dfd0a3adf2e5e0116a94 (diff)
Core/Spells: implemented SpellPriority field from SpellEntry to cleanup charged mod proc behaviour
- Only one charged mod will be consumed per SpellMod apply, and it'll be compared against other mod priority - This is proper way of handling Backdraft/Backlash and Deathchill/Killing Machine Thanks to killerwife for info
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Player/Player.cpp117
-rw-r--r--src/server/game/Entities/Player/Player.h1
2 files changed, 29 insertions, 89 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 266259b8257..6874c6a1f77 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -20869,6 +20869,10 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod
if (mod->op == SPELLMOD_DURATION && spellInfo->GetDuration() == -1)
return false;
+ // mod crit to spells that can't crit
+ if (mod->op == SPELLMOD_CRITICAL_CHANCE && !spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT))
+ return false;
+
return spellInfo->IsAffectedBySpellMod(mod);
}
@@ -20882,103 +20886,48 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
float totalmul = 1.0f;
int32 totalflat = 0;
- // Drop charges for triggering spells instead of triggered ones
- if (m_spellModTakingSpell)
- spell = m_spellModTakingSpell;
-
- switch (op)
+ auto calculateSpellMod = [&](SpellModifier* mod)
{
- // special case, if a mod makes spell instant, only consume that mod
- case SPELLMOD_CASTING_TIME:
- {
- SpellModifier* modInstantSpell = nullptr;
- for (SpellModifier* mod : m_spellMods[op])
- {
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
- continue;
-
- if (mod->type == SPELLMOD_PCT && basevalue < T(10000) && mod->value <= -100)
- {
- modInstantSpell = mod;
- break;
- }
- }
-
- if (modInstantSpell)
- {
- Player::ApplyModToSpell(modInstantSpell, spell);
- basevalue = T(0);
- return;
- }
- break;
- }
- // special case if two mods apply 100% critical chance, only consume one
- case SPELLMOD_CRITICAL_CHANCE:
- {
- SpellModifier* modCritical = nullptr;
- for (SpellModifier* mod : m_spellMods[op])
- {
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
- continue;
-
- if (mod->type == SPELLMOD_FLAT && mod->value >= 100)
- {
- modCritical = mod;
- break;
- }
- }
-
- if (modCritical)
- {
- Player::ApplyModToSpell(modCritical, spell);
- basevalue = T(100);
- return;
- }
- break;
- }
- default:
- break;
- }
-
- for (SpellModifier* mod : m_spellMods[op])
- {
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
- continue;
-
switch (mod->type)
{
case SPELLMOD_FLAT:
totalflat += mod->value;
break;
case SPELLMOD_PCT:
- {
- // skip percent mods with null basevalue (most important for spell mods with charges)
- if (basevalue == T(0))
- continue;
-
// special case (skip > 10sec spell casts for instant cast setting)
if (op == SPELLMOD_CASTING_TIME && mod->value <= -100 && basevalue >= T(10000))
- continue;
- else if (!Player::HasSpellModApplied(mod, spell))
- {
- // special case for Surge of Light, don't apply critical chance reduction if other mods not applied (ie procs while casting another spell)
- // (Surge of Light is the only PCT_MOD on critical chance)
- if (op == SPELLMOD_CRITICAL_CHANCE)
- continue;
- // special case for Backdraft, dont' apply GCD reduction if cast time reduction wasn't applied (ie when Backlash is consumed first)
- // (Backdraft is the only PCT_MOD on global cooldown)
- else if (op == SPELLMOD_GLOBAL_COOLDOWN)
- continue;
- }
+ return;
totalmul += CalculatePct(1.0f, mod->value);
break;
- }
}
Player::ApplyModToSpell(mod, spell);
+ };
+
+ // Drop charges for triggering spells instead of triggered ones
+ if (m_spellModTakingSpell)
+ spell = m_spellModTakingSpell;
+
+ SpellModifier* chargedMod = nullptr;
+ for (SpellModifier* mod : m_spellMods[op])
+ {
+ if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ continue;
+
+ if (mod->ownerAura->IsUsingCharges())
+ {
+ if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->Priority < mod->ownerAura->GetSpellInfo()->Priority))
+ chargedMod = mod;
+ continue;
+ }
+
+ calculateSpellMod(mod);
}
+ if (chargedMod)
+ calculateSpellMod(chargedMod);
+
basevalue = T(float(basevalue + totalflat) * totalmul);
}
@@ -21023,14 +20972,6 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
m_spellMods[mod->op].erase(mod);
}
-bool Player::HasSpellModApplied(SpellModifier* mod, Spell* spell)
-{
- if (!spell)
- return false;
-
- return spell->m_appliedMods.count(mod->ownerAura) != 0;
-}
-
void Player::ApplyModToSpell(SpellModifier* mod, Spell* spell)
{
if (!spell)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index fd9c4230ca9..e828bdb5488 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1454,7 +1454,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
template <class T>
void ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell = nullptr) const;
static void ApplyModToSpell(SpellModifier* mod, Spell* spell);
- static bool HasSpellModApplied(SpellModifier* mod, Spell* spell);
void SetSpellModTakingSpell(Spell* spell, bool apply);
void RemoveArenaSpellCooldowns(bool removeActivePetCooldowns = false);