[7597] Fixed crash at stealing single target auras (54648 for example) Author: arrai

--HG--
branch : trunk
This commit is contained in:
megamage
2009-04-02 16:44:18 -06:00
parent 4a3066392f
commit 943d0c6e2d
4 changed files with 45 additions and 26 deletions
+6 -4
View File
@@ -14749,15 +14749,17 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
else else
remaincharges = 0; remaincharges = 0;
//do not load single target auras (unless they were cast by the player)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
continue;
for(uint32 i=0; i<stackcount; i++) for(uint32 i=0; i<stackcount; i++)
{ {
Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL); Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL);
if(!damage) if(!damage)
damage = aura->GetModifier()->m_amount; damage = aura->GetModifier()->m_amount;
// reset stolen single target auras
if (caster_guid != GetGUID() && aura->IsSingleTarget())
aura->SetIsSingleTarget(false);
aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges);
AddAura(aura); AddAura(aura);
sLog.outDetail("Added aura spellid %u, effect %u", spellproto->Id, effindex); sLog.outDetail("Added aura spellid %u, effect %u", spellproto->Id, effindex);
@@ -15874,7 +15876,7 @@ void Player::_SaveAuras()
if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost())) if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost()))
{ {
//do not save single target auras (unless they were cast by the player) //do not save single target auras (unless they were cast by the player)
if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo))) if (!(itr2->second->GetCasterGUID() != GetGUID() && itr2->second->IsSingleTarget()))
{ {
uint8 i; uint8 i;
// or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras
+20
View File
@@ -376,6 +376,8 @@ m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
m_positive = IsPositiveEffect(GetId(), m_effIndex); m_positive = IsPositiveEffect(GetId(), m_effIndex);
m_auraStateMask = 0; m_auraStateMask = 0;
m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto);
m_applyTime = time(NULL); m_applyTime = time(NULL);
if(!caster) if(!caster)
@@ -6726,3 +6728,21 @@ void Aura::HandlePhase(bool apply, bool Real)
m_target->SetVisibility(m_target->GetVisibility()); m_target->SetVisibility(m_target->GetVisibility());
} }
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;
}
}
+7
View File
@@ -279,6 +279,8 @@ class TRINITY_DLL_SPEC Aura
return m_procCharges == 0; return m_procCharges == 0;
} }
void UnregisterSingleCastAura();
int8 GetStackAmount() {return m_stackAmount;} int8 GetStackAmount() {return m_stackAmount;}
//int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;} //int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;}
void SetStackAmount(uint8 num); void SetStackAmount(uint8 num);
@@ -310,6 +312,10 @@ class TRINITY_DLL_SPEC Aura
bool IsUpdated() { return m_updated; } bool IsUpdated() { return m_updated; }
void SetUpdated(bool val) { m_updated = val; } void SetUpdated(bool val) { m_updated = val; }
bool IsSingleTarget() {return m_isSingleTargetAura;}
void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;}
void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; }
Unit* GetTriggerTarget() const; Unit* GetTriggerTarget() const;
@@ -367,6 +373,7 @@ class TRINITY_DLL_SPEC Aura
bool m_isRemovedOnShapeLost:1; bool m_isRemovedOnShapeLost:1;
bool m_updated:1; // Prevent remove aura by stack if set bool m_updated:1; // Prevent remove aura by stack if set
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
private: private:
}; };
+12 -22
View File
@@ -3864,7 +3864,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(;;)
@@ -4231,10 +4231,9 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit
if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
{ {
int32 basePoints = aur->GetBasePoints(); int32 basePoints = aur->GetBasePoints();
// construct the new aura for the attacker // construct the new aura for the attacker - will never return NULL, it's just a wrapper for
Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), NULL/*&basePoints*/, stealer); // some different constructors
if(!new_aur) Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), NULL, stealer, this);
continue;
// set its duration and maximum duration // set its duration and maximum duration
// max duration 2 minutes (in msecs) // max duration 2 minutes (in msecs)
@@ -4243,6 +4242,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);
@@ -4352,21 +4357,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
m_Auras.erase(i); m_Auras.erase(i);
++m_removedAuras; // internal count used by unit update ++m_removedAuras; // internal count used by unit update
Unit* caster = NULL; Aur->UnregisterSingleCastAura();
if (IsSingleTargetSpell(AurSpellInfo))
{
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)
@@ -4395,8 +4386,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
bool channeled = false; bool channeled = false;
if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(AurSpellInfo)) if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(AurSpellInfo))
{ {
if(!caster) // can be already located for IsSingleTargetSpell case Unit* caster = Aur->GetCaster();
caster = Aur->GetCaster();
if(caster && caster->isAlive()) if(caster && caster->isAlive())
{ {