aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/Spell.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp72
1 files changed, 70 insertions, 2 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 95769040dde..4d6459bc66d 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3001,8 +3001,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggere
m_caster->SetCurrentCastedSpell(this);
SendSpellStart();
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->AddGlobalCooldown(m_spellInfo,this);
+ TriggerGlobalCooldown();
if (!m_casttime && !m_spellInfo->StartRecoveryTime
&& !m_castItemGUID //item: first cast may destroy item and second cast causes crash
@@ -3027,6 +3026,7 @@ void Spell::cancel()
switch (oldState)
{
case SPELL_STATE_PREPARING:
+ CancelGlobalCooldown();
case SPELL_STATE_DELAYED:
SendInterrupted(0);
SendCastResult(SPELL_FAILED_INTERRUPTED);
@@ -4680,6 +4680,10 @@ SpellCastResult Spell::CheckCast(bool strict)
}
}
+ // Check global cooldown
+ if (strict && !m_IsTriggeredSpell && HasGlobalCooldown())
+ return SPELL_FAILED_NOT_READY;
+
// only allow triggered spells if at an ended battleground
if (!m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER)
if (Battleground * bg = m_caster->ToPlayer()->GetBattleground())
@@ -7285,3 +7289,67 @@ void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTarget
(*scritr)->_FinishScriptCall();
}
}
+
+// Global cooldowns management
+enum GCDLimits
+{
+ MIN_GCD = 1000,
+ MAX_GCD = 1500
+};
+
+bool Spell::HasGlobalCooldown()
+{
+ // Only player or controlled units have global cooldown
+ if (m_caster->GetCharmInfo())
+ return m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
+ else if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ return m_caster->ToPlayer()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
+ else
+ return false;
+}
+
+void Spell::TriggerGlobalCooldown()
+{
+ int32 gcd = m_spellInfo->StartRecoveryTime;
+ if (!gcd)
+ return;
+
+ // Global cooldown can't leave range 1..1.5 secs
+ // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns
+ // but as tests show are not affected by any spell mods.
+ if (m_spellInfo->StartRecoveryTime >= MIN_GCD && m_spellInfo->StartRecoveryTime <= MAX_GCD)
+ {
+ // gcd modifier auras are applied only to own spells and only players have such mods
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_GLOBAL_COOLDOWN, gcd, this);
+
+ // Apply haste rating
+ gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
+ if (gcd < MIN_GCD)
+ gcd = MIN_GCD;
+ else if (gcd > MAX_GCD)
+ gcd = MAX_GCD;
+ }
+
+ // Only players or controlled units have global cooldown
+ if (m_caster->GetCharmInfo())
+ m_caster->GetCharmInfo()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
+ else if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
+}
+
+void Spell::CancelGlobalCooldown()
+{
+ if (!m_spellInfo->StartRecoveryTime)
+ return;
+
+ // Cancel global cooldown when interrupting current cast
+ if (m_caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) != this)
+ return;
+
+ // Only players or controlled units have global cooldown
+ if (m_caster->GetCharmInfo())
+ m_caster->GetCharmInfo()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
+ else if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
+}