*Backport a crash fix from TC2. Fix a crash caused by stealing single target aura. Source: Mangos.
--HG-- branch : trunk
This commit is contained in:
@@ -352,6 +352,8 @@ m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
|
|||||||
|
|
||||||
m_applyTime = time(NULL);
|
m_applyTime = time(NULL);
|
||||||
|
|
||||||
|
m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto);
|
||||||
|
|
||||||
if(!caster)
|
if(!caster)
|
||||||
{
|
{
|
||||||
m_caster_guid = target->GetGUID();
|
m_caster_guid = target->GetGUID();
|
||||||
@@ -6176,3 +6178,21 @@ void Aura::HandleArenaPreparation(bool apply, bool Real)
|
|||||||
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
|
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Aura::UnregisterSingleCastAura()
|
||||||
|
{
|
||||||
|
if (IsSingleTarget())
|
||||||
|
{
|
||||||
|
Unit* caster = NULL;
|
||||||
|
caster = GetCaster();
|
||||||
|
if(caster)
|
||||||
|
{
|
||||||
|
caster->GetSingleCastAuras().remove(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sLog.outError("Couldn't find the caster of the single target aura, may crash later!");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
m_isSingleTargetAura = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -310,6 +310,11 @@ class TRINITY_DLL_SPEC Aura
|
|||||||
|
|
||||||
int32 GetStackAmount() {return m_stackAmount;}
|
int32 GetStackAmount() {return m_stackAmount;}
|
||||||
void SetStackAmount(int32 amount) {m_stackAmount=amount;}
|
void SetStackAmount(int32 amount) {m_stackAmount=amount;}
|
||||||
|
|
||||||
|
// Single cast aura helpers
|
||||||
|
void UnregisterSingleCastAura();
|
||||||
|
bool IsSingleTarget() const {return m_isSingleTargetAura;}
|
||||||
|
void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;}
|
||||||
protected:
|
protected:
|
||||||
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
|
||||||
|
|
||||||
@@ -342,6 +347,7 @@ class TRINITY_DLL_SPEC Aura
|
|||||||
bool m_isRemovedOnShapeLost:1;
|
bool m_isRemovedOnShapeLost:1;
|
||||||
bool m_updated:1;
|
bool m_updated:1;
|
||||||
bool m_in_use:1; // true while in Aura::ApplyModifier call
|
bool m_in_use:1; // true while in Aura::ApplyModifier call
|
||||||
|
bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
|
||||||
|
|
||||||
int32 m_periodicTimer;
|
int32 m_periodicTimer;
|
||||||
uint32 m_PeriodicEventId;
|
uint32 m_PeriodicEventId;
|
||||||
|
|||||||
+6
-17
@@ -3822,7 +3822,7 @@ bool Unit::AddAura(Aura *Aur)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura)
|
// update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura)
|
||||||
if (IsSingleTargetSpell(aurSpellInfo) && Aur->GetTarget())
|
if (Aur->IsSingleTarget() && Aur->GetTarget())
|
||||||
{
|
{
|
||||||
// caster pointer can be deleted in time aura remove, find it by guid at each iteration
|
// caster pointer can be deleted in time aura remove, find it by guid at each iteration
|
||||||
for(;;)
|
for(;;)
|
||||||
@@ -4160,9 +4160,12 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit
|
|||||||
new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur );
|
new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur );
|
||||||
new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur );
|
new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur );
|
||||||
|
|
||||||
|
// Unregister _before_ adding to stealer
|
||||||
|
aur->UnregisterSingleCastAura();
|
||||||
|
// strange but intended behaviour: Stolen single target auras won't be treated as single targeted
|
||||||
|
new_aur->SetIsSingleTarget(false);
|
||||||
// add the new aura to stealer
|
// add the new aura to stealer
|
||||||
stealer->AddAura(new_aur);
|
stealer->AddAura(new_aur);
|
||||||
|
|
||||||
// Remove aura as dispel
|
// Remove aura as dispel
|
||||||
RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
|
RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
|
||||||
}
|
}
|
||||||
@@ -4309,20 +4312,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
|||||||
++m_removedAuras; // internal count used by unit update
|
++m_removedAuras; // internal count used by unit update
|
||||||
|
|
||||||
Unit* caster = NULL;
|
Unit* caster = NULL;
|
||||||
if (IsSingleTargetSpell(AurSpellInfo))
|
Aur->UnregisterSingleCastAura();
|
||||||
{
|
|
||||||
caster = Aur->GetCaster();
|
|
||||||
if(caster)
|
|
||||||
{
|
|
||||||
AuraList& scAuras = caster->GetSingleCastAuras();
|
|
||||||
scAuras.remove(Aur);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sLog.outError("Couldn't find the caster of the single target aura, may crash later!");
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
|
// remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
|
||||||
if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
|
if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
|
||||||
@@ -13087,4 +13077,3 @@ void Unit::AddAura(uint32 spellId, Unit* target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user