fix(Core/Misc): bunch of crashfixes (#7307)

This commit is contained in:
Viste
2021-09-14 15:38:56 +03:00
committed by GitHub
parent bd956b5a57
commit a9796af174
56 changed files with 435 additions and 328 deletions

View File

@@ -506,6 +506,20 @@ void SpellCastTargets::Update(Unit* caster)
}
}
class SpellEvent : public BasicEvent
{
public:
SpellEvent(Spell* spell);
~SpellEvent();
bool Execute(uint64 e_time, uint32 p_time);
void Abort(uint64 e_time);
bool IsDeletable() const;
protected:
Spell* m_Spell;
};
void SpellCastTargets::OutDebug() const
{
if (!m_targetMask)
@@ -543,7 +557,7 @@ SpellValue::SpellValue(SpellInfo const* proto)
Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) :
m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)),
m_caster((info->HasAttribute(SPELL_ATTR6_ORIGINATE_FROM_CONTROLLER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster)
, m_spellValue(new SpellValue(m_spellInfo))
, m_spellValue(new SpellValue(m_spellInfo)), _spellEvent(nullptr)
{
m_customError = SPELL_CUSTOM_ERROR_NONE;
m_skipCheck = skipCheck;
@@ -825,8 +839,16 @@ void Spell::SelectSpellTargets()
if (m_spellInfo->IsChanneled())
{
// maybe do this for all spells?
if (!focusObject && m_UniqueTargetInfo.empty() && m_UniqueGOTargetInfo.empty() && m_UniqueItemInfo.empty() && !m_targets.HasDst())
{
SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS);
finish(false);
return;
}
uint8 mask = (1 << i);
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
if (ihit->effectMask & mask)
{
@@ -838,22 +860,18 @@ void Spell::SelectSpellTargets()
else if (m_auraScaleMask)
{
bool checkLvl = !m_UniqueTargetInfo.empty();
for (std::list<TargetInfo>::iterator itr = m_UniqueTargetInfo.begin(); itr != m_UniqueTargetInfo.end(); ++itr)
m_UniqueTargetInfo.erase(std::remove_if(std::begin(m_UniqueTargetInfo), std::end(m_UniqueTargetInfo), [&](TargetInfo const& targetInfo) -> bool
{
// remove targets which did not pass min level check
if (m_auraScaleMask && itr->effectMask == m_auraScaleMask)
if (m_auraScaleMask && targetInfo.effectMask == m_auraScaleMask)
{
bool needErase = false;
if (!itr->scaleAura && itr->targetGUID != m_caster->GetGUID())
needErase = true;
sScriptMgr->OnRemoveAuraScaleTargets(this, *itr, m_auraScaleMask, needErase);
if (needErase)
m_UniqueTargetInfo.erase(itr);
if (!targetInfo.scaleAura && targetInfo.targetGUID != m_caster->GetGUID())
return true;
}
}
return false;
}), std::end(m_UniqueTargetInfo));
if (checkLvl && m_UniqueTargetInfo.empty())
{
SendCastResult(SPELL_FAILED_LOWLEVEL);
@@ -862,20 +880,35 @@ void Spell::SelectSpellTargets()
}
}
if (uint64 dstDelay = CalculateDelayMomentForDst())
m_delayMoment = dstDelay;
}
uint64 Spell::CalculateDelayMomentForDst() const
{
if (m_targets.HasDst())
{
if (m_targets.HasTraj())
{
float speed = m_targets.GetSpeedXY();
if (speed > 0.0f)
m_delayTrajectory = (uint64)floor(m_targets.GetDist2d() / speed * 1000.0f);
return (uint64)floor(m_targets.GetDist2d() / speed * 1000.0f);
}
else if (m_spellInfo->Speed > 0.0f)
{
float dist = m_caster->GetExactDist(m_targets.GetDstPos());
m_delayTrajectory = (uint64) floor(dist / m_spellInfo->Speed * 1000.0f);
// We should not subtract caster size from dist calculation (fixes execution time desync with animation on client, eg. Malleable Goo cast by PP)
float dist = m_caster->GetExactDist(*m_targets.GetDstPos());
return (uint64)std::floor(dist / m_spellInfo->Speed * 1000.0f);
}
}
return 0;
}
void Spell::RecalculateDelayMomentForDst()
{
m_delayMoment = CalculateDelayMomentForDst();
m_caster->m_Events.ModifyEventTime(_spellEvent, Milliseconds(GetDelayStart() + m_delayMoment));
}
void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask)
@@ -898,11 +931,12 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar
for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
{
SpellEffectInfo const* effects = GetSpellInfo()->Effects;
if (effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() &&
effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() &&
effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions &&
effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) &&
CheckScriptEffectImplicitTargets(effIndex, j))
if (effects[j].IsEffect() &&
effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() &&
effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() &&
effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions &&
effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) &&
CheckScriptEffectImplicitTargets(effIndex, j))
{
effectMask |= 1 << j;
}
@@ -928,9 +962,8 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar
SelectImplicitAreaTargets(effIndex, targetType, effectMask);
break;
case TARGET_SELECT_CATEGORY_TRAJ:
// xinef: just in case there is no dest, explanation in SelectImplicitDestDestTargets
if (!m_targets.HasDst())
m_targets.SetDst(*m_caster);
// just in case there is no dest, explanation in SelectImplicitDestDestTargets
CheckDst();
SelectImplicitTrajTargets(effIndex, targetType);
break;
@@ -1513,7 +1546,7 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli
break;
case TARGET_UNIT_SUMMONER:
if (m_caster->IsSummon())
target = m_caster->ToTempSummon()->GetSummoner();
target = m_caster->ToTempSummon()->GetSummonerUnit();
break;
case TARGET_UNIT_VEHICLE:
target = m_caster->GetVehicleBase();
@@ -3208,8 +3241,8 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
}
// create and add update event for this spell
SpellEvent* Event = new SpellEvent(this);
m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
_spellEvent = new SpellEvent(this);
m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1));
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster))
{