Core/Spell Mechanics: introduce global cooldown manager for server-side checks for GCD (ported from mangos)
This commit is contained in:
@@ -3001,6 +3001,8 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggere
|
||||
m_caster->SetCurrentCastedSpell(this);
|
||||
SendSpellStart();
|
||||
|
||||
TriggerGlobalCooldown();
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
m_caster->ToPlayer()->AddGlobalCooldown(m_spellInfo,this);
|
||||
|
||||
@@ -3027,6 +3029,7 @@ void Spell::cancel()
|
||||
switch (oldState)
|
||||
{
|
||||
case SPELL_STATE_PREPARING:
|
||||
CancelGlobalCooldown();
|
||||
case SPELL_STATE_DELAYED:
|
||||
SendInterrupted(0);
|
||||
SendCastResult(SPELL_FAILED_INTERRUPTED);
|
||||
@@ -4680,6 +4683,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 +7292,65 @@ void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTarget
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
enum eGCD {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -543,6 +543,9 @@ class Spell
|
||||
|
||||
void SetSpellValue(SpellValueMod mod, int32 value);
|
||||
protected:
|
||||
bool HasGlobalCooldown();
|
||||
void TriggerGlobalCooldown();
|
||||
void CancelGlobalCooldown();
|
||||
|
||||
void SendLoot(uint64 guid, LootType loottype);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user