*Add m_duringRemoveFromWorld lock to prevent adding single target auras during or after remove from world process.

--HG--
branch : trunk
This commit is contained in:
QAston
2010-08-03 06:11:03 +02:00
parent 14827321bf
commit c5a9d3b463
5 changed files with 73 additions and 42 deletions
+38 -5
View File
@@ -280,6 +280,21 @@ Aura * Aura::Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * o
else
caster = ObjectAccessor::GetUnit(*owner, casterGUID);
}
else
{
casterGUID = caster->GetGUID();
}
// check if aura can be owned by owner
if (owner->isType(TYPEMASK_UNIT))
{
if (!owner->IsInWorld() || ((Unit*)owner)->IsDuringRemoveFromWorld())
{
// owner not in world so
// don't allow to own not self casted single target auras
if (casterGUID != owner->GetGUID() && IsSingleTargetSpell(spellproto))
return NULL;
}
}
Aura * aura = NULL;
switch(owner->GetTypeId())
{
@@ -455,7 +470,7 @@ void Aura::UpdateTargetMap(Unit * caster, bool apply)
{
// needs readding - remove now, will be applied in next update cycle
// (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
if (appIter->second->GetEffectMask() != existing->second)
if (appIter->second->GetEffectMask() != existing->second || !CanBeAppliedOn(existing->first))
targetsToRemove.push_back(appIter->second->GetTarget());
// nothing todo - aura already applied
// remove from auras to register list
@@ -469,8 +484,7 @@ void Aura::UpdateTargetMap(Unit * caster, bool apply)
bool addUnit = true;
// check target immunities
if (itr->first->IsImmunedToSpell(GetSpellProto())
// check area target requirements
|| (itr->first != GetOwner() && !CheckAreaTarget(itr->first)))
|| !CanBeAppliedOn(itr->first))
addUnit = false;
if (addUnit)
@@ -764,8 +778,10 @@ bool Aura::IsVisible() const
void Aura::UnregisterSingleTarget()
{
ASSERT(m_isSingleTarget);
Unit * caster = ObjectAccessor::GetObjectInOrOutOfWorld(GetCasterGUID(), (Unit*)NULL);//GetCaster();
assert(caster);
Unit * caster = GetCaster();
//if (!caster)
//caster = ObjectAccessor::GetObjectInOrOutOfWorld(GetCasterGUID(), (Unit*)NULL);
ASSERT(caster);
caster->GetSingleCastAuras().remove(this);
SetIsSingleTarget(false);
}
@@ -1494,6 +1510,23 @@ void Aura::HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster,
}
}
bool Aura::CanBeAppliedOn(Unit *target)
{
// unit not in world or during remove from world
if (!target->IsInWorld() || target->IsDuringRemoveFromWorld())
{
// area auras mustn't be applied
if (GetOwner() != target)
return false;
// not selfcasted single target auras mustn't be applied
if (GetCasterGUID() != GetOwner()->GetGUID() && IsSingleTargetSpell(GetSpellProto()))
return false;
}
else if (GetOwner() != target)
return CheckAreaTarget(target);
return true;
}
bool Aura::CheckAreaTarget(Unit *target)
{
// for owner check use Spell::CheckTarget
@@ -163,6 +163,7 @@ class Aura
void SetNeedClientUpdateForTargets() const;
void HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster, bool apply);
bool CanBeAppliedOn(Unit *target);
bool CheckAreaTarget(Unit *target);
private:
void _DeleteRemovedApplications();