mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 15:58:04 +00:00
fix(Core/Spells): Fire CAST proc before HIT/FINISH for instant spells (#25647)
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com> Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: sudlud <sudlud@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
-- Missile Barrage: consume on FINISH instead of CAST; its mods (DURATION,
|
||||||
|
-- ACTIVATION_TIME, COST) are applied inside handle_immediate, after CAST fires.
|
||||||
|
UPDATE `spell_proc` SET `SpellPhaseMask` = 4 WHERE `SpellId` = 44401;
|
||||||
@@ -3951,6 +3951,44 @@ void Spell::_cast(bool skipCheck)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CAST -> HIT -> FINISH ordering: fire CAST before handle_immediate so an aura
|
||||||
|
// applied during HIT (e.g. Arcane Potency from Clearcasting) isn't consumed by
|
||||||
|
// the same cast. Triggered spells skip this so periodic ticks (Blizzard etc.)
|
||||||
|
// don't burn cast-charge buffs.
|
||||||
|
if (m_originalCaster && !IsTriggered())
|
||||||
|
{
|
||||||
|
uint32 procAttacker = m_procAttacker;
|
||||||
|
if (!procAttacker)
|
||||||
|
{
|
||||||
|
bool IsPositive = m_spellInfo->IsPositive();
|
||||||
|
if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
|
||||||
|
{
|
||||||
|
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 hitMask = PROC_HIT_NORMAL;
|
||||||
|
|
||||||
|
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||||
|
{
|
||||||
|
if (ihit->missCondition != SPELL_MISS_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!ihit->crit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hitMask |= PROC_HIT_CRITICAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, hitMask, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
||||||
|
m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_CAST);
|
||||||
|
}
|
||||||
|
|
||||||
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
|
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
|
||||||
if ((m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled())/* xinef: we dont need this || m_spellInfo->Id == 14157*/)
|
if ((m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled())/* xinef: we dont need this || m_spellInfo->Id == 14157*/)
|
||||||
{
|
{
|
||||||
@@ -4008,46 +4046,6 @@ void Spell::_cast(bool skipCheck)
|
|||||||
if (modOwner)
|
if (modOwner)
|
||||||
modOwner->SetSpellModTakingSpell(this, false);
|
modOwner->SetSpellModTakingSpell(this, false);
|
||||||
|
|
||||||
// Handle procs on cast - only for non-triggered spells
|
|
||||||
// Triggered spells (from auras, items, etc.) should not fire CAST phase procs
|
|
||||||
// as they are not player-initiated casts. This prevents issues like Arcane Potency
|
|
||||||
// charges being consumed by periodic damage effects (e.g., Blizzard ticks).
|
|
||||||
// Must be called AFTER handle_immediate() so spell mods (like Missile Barrage's
|
|
||||||
// duration reduction) are applied before the aura is consumed by the proc.
|
|
||||||
if (m_originalCaster && !IsTriggered())
|
|
||||||
{
|
|
||||||
uint32 procAttacker = m_procAttacker;
|
|
||||||
if (!procAttacker)
|
|
||||||
{
|
|
||||||
bool IsPositive = m_spellInfo->IsPositive();
|
|
||||||
if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
|
|
||||||
{
|
|
||||||
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
procAttacker = IsPositive ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 hitMask = PROC_HIT_NORMAL;
|
|
||||||
|
|
||||||
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
|
||||||
{
|
|
||||||
if (ihit->missCondition != SPELL_MISS_NONE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!ihit->crit)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
hitMask |= PROC_HIT_CRITICAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, hitMask, 1, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell.spellInfo,
|
|
||||||
m_triggeredByAuraSpell.effectIndex, this, nullptr, nullptr, PROC_SPELL_PHASE_CAST);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::vector<int32> const* spell_triggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id))
|
if (std::vector<int32> const* spell_triggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id))
|
||||||
{
|
{
|
||||||
for (int32 id : *spell_triggered)
|
for (int32 id : *spell_triggered)
|
||||||
|
|||||||
Reference in New Issue
Block a user