mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[7597] Fixed crash at stealing single target auras (54648 for example)
This commit is contained in:
parent
4d42cd9e1a
commit
1ec8e1f24d
5 changed files with 46 additions and 27 deletions
|
|
@ -14391,15 +14391,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);
|
||||||
|
|
@ -15449,7 +15451,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
|
||||||
|
|
|
||||||
|
|
@ -360,6 +360,8 @@ m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false)
|
||||||
m_isPassive = IsPassiveSpell(GetId());
|
m_isPassive = IsPassiveSpell(GetId());
|
||||||
m_positive = IsPositiveEffect(GetId(), m_effIndex);
|
m_positive = IsPositiveEffect(GetId(), m_effIndex);
|
||||||
|
|
||||||
|
m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto);
|
||||||
|
|
||||||
m_applyTime = time(NULL);
|
m_applyTime = time(NULL);
|
||||||
|
|
||||||
int32 damage;
|
int32 damage;
|
||||||
|
|
@ -6742,3 +6744,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,8 @@ class MANGOS_DLL_SPEC Aura
|
||||||
return m_procCharges == 0;
|
return m_procCharges == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnregisterSingleCastAura();
|
||||||
|
|
||||||
void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
|
void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
|
||||||
void SendAuraUpdate(bool remove);
|
void SendAuraUpdate(bool remove);
|
||||||
|
|
||||||
|
|
@ -296,6 +298,10 @@ class MANGOS_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;}
|
||||||
|
bool SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;}
|
||||||
|
|
||||||
void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; }
|
void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; }
|
||||||
|
|
||||||
virtual Unit* GetTriggerTarget() const { return m_target; }
|
virtual Unit* GetTriggerTarget() const { return m_target; }
|
||||||
|
|
@ -352,6 +358,7 @@ class MANGOS_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:
|
||||||
void CleanupTriggeredSpells();
|
void CleanupTriggeredSpells();
|
||||||
|
|
|
||||||
|
|
@ -3423,7 +3423,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(;;)
|
||||||
|
|
@ -3704,10 +3704,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(), &basePoints, stealer);
|
// some different constructors
|
||||||
if(!new_aur)
|
Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, 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)
|
||||||
|
|
@ -3716,6 +3715,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);
|
||||||
|
|
||||||
|
|
@ -3842,21 +3847,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
||||||
Aura* Aur = i->second;
|
Aura* Aur = i->second;
|
||||||
SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
|
SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -3876,8 +3867,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
||||||
bool caster_channeled = false;
|
bool caster_channeled = false;
|
||||||
if(IsChanneledSpell(AurSpellInfo))
|
if(IsChanneledSpell(AurSpellInfo))
|
||||||
{
|
{
|
||||||
if(!caster) // can be already located for IsSingleTargetSpell case
|
Unit* caster = Aur->GetCaster();
|
||||||
caster = Aur->GetCaster();
|
|
||||||
|
|
||||||
if(caster)
|
if(caster)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "7596"
|
#define REVISION_NR "7597"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue