diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rwxr-xr-x | src/server/game/Spells/Spell.cpp | 72 |
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); +} |
