diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index de27afaf860..d4c42db9563 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2763,6 +2763,14 @@ void Spell::DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& hitInfo) { bool refresh = false; + // delayed spells with multiple targets need to create a new aura object, otherwise we'll access a deleted aura + if (m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled()) + { + _spellAura = nullptr; + if (Aura* aura = unit->GetAura(m_spellInfo->Id, caster->GetGUID(), m_CastItem ? m_CastItem->GetGUID() : ObjectGuid::Empty, aura_effmask)) + _spellAura = aura->ToUnitAura(); + } + if (!_spellAura) { bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER); @@ -3546,21 +3554,19 @@ uint64 Spell::handle_delayed(uint64 t_offset) // now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases) { std::vector<TargetInfo> delayedTargets; - auto itr = std::remove_if(std::begin(m_UniqueTargetInfo), std::end(m_UniqueTargetInfo), [&](TargetInfo& target) -> bool + m_UniqueTargetInfo.erase(std::remove_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [&](TargetInfo& target) -> bool { if (single_missile || target.TimeDelay <= t_offset) { target.TimeDelay = t_offset; + delayedTargets.emplace_back(std::move(target)); return true; } else if (next_time == 0 || target.TimeDelay < next_time) next_time = target.TimeDelay; return false; - }); - - delayedTargets.insert(delayedTargets.end(), std::make_move_iterator(itr), std::make_move_iterator(m_UniqueTargetInfo.end())); - m_UniqueTargetInfo.erase(itr, m_UniqueTargetInfo.end()); + }), m_UniqueTargetInfo.end()); DoProcessTargetContainer(delayedTargets); } @@ -3568,21 +3574,19 @@ uint64 Spell::handle_delayed(uint64 t_offset) // now recheck gameobject targeting correctness { std::vector<GOTargetInfo> delayedGOTargets; - auto itr = std::remove_if(std::begin(m_UniqueGOTargetInfo), std::end(m_UniqueGOTargetInfo), [&](GOTargetInfo& goTarget) -> bool + m_UniqueGOTargetInfo.erase(std::remove_if(m_UniqueGOTargetInfo.begin(), m_UniqueGOTargetInfo.end(), [&](GOTargetInfo& goTarget) -> bool { if (single_missile || goTarget.TimeDelay <= t_offset) { goTarget.TimeDelay = t_offset; + delayedGOTargets.emplace_back(std::move(goTarget)); return true; } else if (next_time == 0 || goTarget.TimeDelay < next_time) next_time = goTarget.TimeDelay; return false; - }); - - delayedGOTargets.insert(delayedGOTargets.end(), std::make_move_iterator(itr), std::make_move_iterator(m_UniqueGOTargetInfo.end())); - m_UniqueGOTargetInfo.erase(itr, m_UniqueGOTargetInfo.end()); + }), m_UniqueGOTargetInfo.end()); DoProcessTargetContainer(delayedGOTargets); } |