From de592386dcd6ac85feb11d2af85538d62c192696 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 8 May 2022 15:54:15 +0200 Subject: Core/Spells: Autorepeat casting fixes * Fixed cast bars of ranged spells not disappearing when canceled while autoshooting * Replaced hacky 500ms delay on non auto shot autorepeat spells with native spell cast time (wands have 500ms cast time) * Update cooldowns before attempting to cast autorepeat spells (for cases when cooldown ends on the same server tick as cast attempt) --- src/server/game/Spells/Spell.cpp | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'src/server/game/Spells/Spell.cpp') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e207befbf55..1283068269b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3338,7 +3338,7 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const // handle just the general SPELL_FAILED_BAD_TARGETS result which is the default result for most DBC target checks if (_triggeredCastFlags & TRIGGERED_IGNORE_TARGET_CHECK && result == SPELL_FAILED_BAD_TARGETS) result = SPELL_CAST_OK; - if (result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering + if (result != SPELL_CAST_OK) { // Periodic auras should be interrupted when aura triggers a spell which can't be cast // for example bladestorm aura should be removed on disarm as of patch 3.3.5 @@ -3355,6 +3355,10 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const else SendCastResult(result); + // queue autorepeat spells for future repeating + if (GetCurrentContainer() == CURRENT_AUTOREPEAT_SPELL && m_caster->IsUnit()) + m_caster->ToUnit()->SetCurrentCastSpell(this); + finish(false); return result; } @@ -4084,6 +4088,9 @@ void Spell::SendSpellCooldown() m_caster->ToUnit()->GetSpellHistory()->HandleCooldowns(m_spellInfo, m_CastItem, this); else m_caster->ToUnit()->GetSpellHistory()->HandleCooldowns(m_spellInfo, m_castItemEntry, this); + + if (IsAutoRepeat()) + m_caster->ToUnit()->resetAttackTimer(RANGED_ATTACK); } void Spell::update(uint32 difftime) @@ -4126,7 +4133,7 @@ void Spell::update(uint32 difftime) m_timer -= difftime; } - if (m_timer == 0 && !m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat()) + if (m_timer == 0 && !m_spellInfo->IsNextMeleeSwingSpell()) // don't CheckCast for instant spells - done in spell::prepare, skip duplicate checks, needed for range checks for example cast(!m_casttime); break; @@ -4186,6 +4193,10 @@ void Spell::finish(bool ok) if (!unitCaster) return; + // successful cast of the initial autorepeat spell is moved to idle state so that it is not deleted as long as autorepeat is active + if (IsAutoRepeat() && unitCaster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) == this) + m_spellState = SPELL_STATE_IDLE; + if (m_spellInfo->IsChanneled()) unitCaster->UpdateInterruptMask(); @@ -5464,12 +5475,18 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 return SPELL_FAILED_NOT_READY; } - if (!IsIgnoringCooldowns() && m_caster->ToUnit() && !m_caster->ToUnit()->GetSpellHistory()->IsReady(m_spellInfo, m_castItemEntry)) + if (!IsIgnoringCooldowns() && m_caster->ToUnit()) { - if (m_triggeredByAuraSpell) + if (!m_caster->ToUnit()->GetSpellHistory()->IsReady(m_spellInfo, m_castItemEntry)) + { + if (m_triggeredByAuraSpell) + return SPELL_FAILED_DONT_REPORT; + else + return SPELL_FAILED_NOT_READY; + } + + if ((IsAutoRepeat() || m_spellInfo->CategoryId == 76) && !m_caster->ToUnit()->isAttackReady(RANGED_ATTACK)) return SPELL_FAILED_DONT_REPORT; - else - return SPELL_FAILED_NOT_READY; } } -- cgit v1.2.3