mirror of
https://github.com/mangosfour/server.git
synced 2025-12-18 01:37:01 +00:00
[8742] Avoid aura remove triggered casts and packets send at logout/delete
This is must speedup logout and solve some crash cases or unexpected effects. Also fix some nonsense code with memory lost possibility.
This commit is contained in:
parent
7b6f4accd1
commit
15ab6794d3
6 changed files with 117 additions and 121 deletions
|
|
@ -354,38 +354,32 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
||||||
if (!pOwner)
|
if (!pOwner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// not save pet as current if another pet temporary unsummoned
|
|
||||||
if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
|
|
||||||
pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
|
|
||||||
{
|
|
||||||
// pet will lost anyway at restore temporary unsummoned
|
|
||||||
if(getPetType()==HUNTER_PET)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// for warlock case
|
|
||||||
mode = PET_SAVE_NOT_IN_SLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 curhealth = GetHealth();
|
|
||||||
uint32 curmana = GetPower(POWER_MANA);
|
|
||||||
|
|
||||||
// stable and not in slot saves
|
|
||||||
if(mode > PET_SAVE_AS_CURRENT)
|
|
||||||
{
|
|
||||||
RemoveAllAuras();
|
|
||||||
|
|
||||||
//only alive hunter pets get auras saved, the others don't
|
|
||||||
if(!(getPetType() == HUNTER_PET && isAlive()))
|
|
||||||
m_Auras.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
_SaveSpells();
|
|
||||||
_SaveSpellCooldowns();
|
|
||||||
_SaveAuras();
|
|
||||||
|
|
||||||
// current/stable/not_in_slot
|
// current/stable/not_in_slot
|
||||||
if(mode >= PET_SAVE_AS_CURRENT)
|
if (mode >= PET_SAVE_AS_CURRENT)
|
||||||
{
|
{
|
||||||
|
// not save pet as current if another pet temporary unsummoned
|
||||||
|
if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
|
||||||
|
pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
|
||||||
|
{
|
||||||
|
// pet will lost anyway at restore temporary unsummoned
|
||||||
|
if(getPetType()==HUNTER_PET)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// for warlock case
|
||||||
|
mode = PET_SAVE_NOT_IN_SLOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 curhealth = GetHealth();
|
||||||
|
uint32 curmana = GetPower(POWER_MANA);
|
||||||
|
|
||||||
|
// stable and not in slot saves
|
||||||
|
if (mode != PET_SAVE_AS_CURRENT)
|
||||||
|
RemoveAllAuras();
|
||||||
|
|
||||||
|
_SaveSpells();
|
||||||
|
_SaveSpellCooldowns();
|
||||||
|
_SaveAuras();
|
||||||
|
|
||||||
uint32 owner = GUID_LOPART(GetOwnerGUID());
|
uint32 owner = GUID_LOPART(GetOwnerGUID());
|
||||||
std::string name = m_name;
|
std::string name = m_name;
|
||||||
CharacterDatabase.escape_string(name);
|
CharacterDatabase.escape_string(name);
|
||||||
|
|
@ -440,7 +434,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
||||||
// delete
|
// delete
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RemoveAllAuras();
|
RemoveAllAuras(AURA_REMOVE_BY_DELETE);
|
||||||
DeleteFromDB(m_charmInfo->GetPetNumber());
|
DeleteFromDB(m_charmInfo->GetPetNumber());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1144,9 +1138,7 @@ void Pet::_SaveSpells()
|
||||||
|
|
||||||
void Pet::_LoadAuras(uint32 timediff)
|
void Pet::_LoadAuras(uint32 timediff)
|
||||||
{
|
{
|
||||||
m_Auras.clear();
|
RemoveAllAuras();
|
||||||
for (int i = 0; i < TOTAL_AURAS; ++i)
|
|
||||||
m_modAuras[i].clear();
|
|
||||||
|
|
||||||
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
|
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14783,9 +14783,7 @@ void Player::_LoadActions(QueryResult *result)
|
||||||
|
|
||||||
void Player::_LoadAuras(QueryResult *result, uint32 timediff)
|
void Player::_LoadAuras(QueryResult *result, uint32 timediff)
|
||||||
{
|
{
|
||||||
m_Auras.clear();
|
RemoveAllAuras();
|
||||||
for (int i = 0; i < TOTAL_AURAS; ++i)
|
|
||||||
m_modAuras[i].clear();
|
|
||||||
|
|
||||||
//QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow());
|
//QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1141,85 +1141,89 @@ bool Aura::_RemoveAura()
|
||||||
SetAura(true);
|
SetAura(true);
|
||||||
SetAuraFlags(AFLAG_NONE);
|
SetAuraFlags(AFLAG_NONE);
|
||||||
SetAuraLevel(0);
|
SetAuraLevel(0);
|
||||||
SendAuraUpdate(true);
|
|
||||||
|
|
||||||
// update for out of range group members
|
if (m_removeMode != AURA_REMOVE_BY_DELETE)
|
||||||
m_target->UpdateAuraForGroup(slot);
|
|
||||||
|
|
||||||
//*****************************************************
|
|
||||||
// Update target aura state flag (at last aura remove)
|
|
||||||
//*****************************************************
|
|
||||||
// Enrage aura state
|
|
||||||
if(m_spellProto->Dispel == DISPEL_ENRAGE)
|
|
||||||
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
|
|
||||||
|
|
||||||
uint32 removeState = 0;
|
|
||||||
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
|
|
||||||
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
|
|
||||||
switch(m_spellProto->SpellFamilyName)
|
|
||||||
{
|
{
|
||||||
case SPELLFAMILY_PALADIN:
|
SendAuraUpdate(true);
|
||||||
if (IsSealSpell(m_spellProto))
|
|
||||||
removeState = AURA_STATE_JUDGEMENT; // Update Seals information
|
|
||||||
break;
|
|
||||||
case SPELLFAMILY_WARLOCK:
|
|
||||||
// Conflagrate aura state on Immolate and Shadowflame,
|
|
||||||
if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
|
|
||||||
(m_spellProto->SpellFamilyFlags2 & 0x00000002))
|
|
||||||
{
|
|
||||||
removeFamilyFlag = UI64LIT(0x0000000000000004);
|
|
||||||
removeFamilyFlag2 = 0x00000002;
|
|
||||||
removeState = AURA_STATE_CONFLAGRATE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPELLFAMILY_DRUID:
|
|
||||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
|
|
||||||
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
|
|
||||||
else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50))
|
|
||||||
{
|
|
||||||
removeFamilyFlag = 0x50;
|
|
||||||
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPELLFAMILY_WARRIOR:
|
|
||||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000))
|
|
||||||
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
|
|
||||||
break;
|
|
||||||
case SPELLFAMILY_ROGUE:
|
|
||||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000))
|
|
||||||
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
|
|
||||||
break;
|
|
||||||
case SPELLFAMILY_HUNTER:
|
|
||||||
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000))
|
|
||||||
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
|
|
||||||
|
|
||||||
}
|
// update for out of range group members
|
||||||
// Remove state (but need check other auras for it)
|
m_target->UpdateAuraForGroup(slot);
|
||||||
if (removeState)
|
|
||||||
{
|
//*****************************************************
|
||||||
bool found = false;
|
// Update target aura state flag (at last aura remove)
|
||||||
Unit::AuraMap& Auras = m_target->GetAuras();
|
//*****************************************************
|
||||||
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
|
// Enrage aura state
|
||||||
|
if(m_spellProto->Dispel == DISPEL_ENRAGE)
|
||||||
|
m_target->ModifyAuraState(AURA_STATE_ENRAGE, false);
|
||||||
|
|
||||||
|
uint32 removeState = 0;
|
||||||
|
uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags;
|
||||||
|
uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2;
|
||||||
|
switch(m_spellProto->SpellFamilyName)
|
||||||
{
|
{
|
||||||
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
|
case SPELLFAMILY_PALADIN:
|
||||||
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
|
if (IsSealSpell(m_spellProto))
|
||||||
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
|
removeState = AURA_STATE_JUDGEMENT; // Update Seals information
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
case SPELLFAMILY_WARLOCK:
|
||||||
|
// Conflagrate aura state on Immolate and Shadowflame,
|
||||||
|
if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) ||
|
||||||
|
(m_spellProto->SpellFamilyFlags2 & 0x00000002))
|
||||||
|
{
|
||||||
|
removeFamilyFlag = UI64LIT(0x0000000000000004);
|
||||||
|
removeFamilyFlag2 = 0x00000002;
|
||||||
|
removeState = AURA_STATE_CONFLAGRATE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPELLFAMILY_DRUID:
|
||||||
|
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400))
|
||||||
|
removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions)
|
||||||
|
else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50))
|
||||||
|
{
|
||||||
|
removeFamilyFlag = 0x50;
|
||||||
|
removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPELLFAMILY_WARRIOR:
|
||||||
|
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000))
|
||||||
|
removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious
|
||||||
|
break;
|
||||||
|
case SPELLFAMILY_ROGUE:
|
||||||
|
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000))
|
||||||
|
removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state
|
||||||
|
break;
|
||||||
|
case SPELLFAMILY_HUNTER:
|
||||||
|
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000))
|
||||||
|
removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions)
|
||||||
}
|
}
|
||||||
// this has been last aura
|
|
||||||
if(!found)
|
|
||||||
m_target->ModifyAuraState(AuraState(removeState), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset cooldown state for spells
|
// Remove state (but need check other auras for it)
|
||||||
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
|
if (removeState)
|
||||||
{
|
{
|
||||||
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
|
bool found = false;
|
||||||
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
|
Unit::AuraMap& Auras = m_target->GetAuras();
|
||||||
((Player*)caster)->SendCooldownEvent(GetSpellProto());
|
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
|
||||||
|
{
|
||||||
|
SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto();
|
||||||
|
if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName &&
|
||||||
|
(auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// this has been last aura
|
||||||
|
if(!found)
|
||||||
|
m_target->ModifyAuraState(AuraState(removeState), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset cooldown state for spells
|
||||||
|
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
|
{
|
||||||
|
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
|
||||||
|
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
|
||||||
|
((Player*)caster)->SendCooldownEvent(GetSpellProto());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -4021,7 +4021,7 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::RemoveAura(Aura* aura)
|
void Unit::RemoveAura(Aura* aura, AuraRemoveMode mode /*= AURA_REMOVE_BY_DEFAULT*/)
|
||||||
{
|
{
|
||||||
AuraMap::iterator i = m_Auras.lower_bound(spellEffectPair(aura->GetId(), aura->GetEffIndex()));
|
AuraMap::iterator i = m_Auras.lower_bound(spellEffectPair(aura->GetId(), aura->GetEffIndex()));
|
||||||
AuraMap::iterator upperBound = m_Auras.upper_bound(spellEffectPair(aura->GetId(), aura->GetEffIndex()));
|
AuraMap::iterator upperBound = m_Auras.upper_bound(spellEffectPair(aura->GetId(), aura->GetEffIndex()));
|
||||||
|
|
@ -4029,7 +4029,7 @@ void Unit::RemoveAura(Aura* aura)
|
||||||
{
|
{
|
||||||
if (i->second == aura)
|
if (i->second == aura)
|
||||||
{
|
{
|
||||||
RemoveAura(i);
|
RemoveAura(i,mode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4079,12 +4079,13 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
|
sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
|
||||||
Aur->ApplyModifier(false,true);
|
if (mode != AURA_REMOVE_BY_DELETE) // not unapply if target will deleted
|
||||||
|
Aur->ApplyModifier(false,true);
|
||||||
|
|
||||||
if(Aur->_RemoveAura())
|
if (Aur->_RemoveAura())
|
||||||
{
|
{
|
||||||
// last aura in stack removed
|
// last aura in stack removed
|
||||||
if(IsSpellLastAuraEffect(Aur->GetSpellProto(),Aur->GetEffIndex()))
|
if (mode != AURA_REMOVE_BY_DELETE && IsSpellLastAuraEffect(Aur->GetSpellProto(),Aur->GetEffIndex()))
|
||||||
Aur->HandleSpellSpecificBoosts(false);
|
Aur->HandleSpellSpecificBoosts(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4108,12 +4109,12 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
|
||||||
i = m_Auras.begin();
|
i = m_Auras.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::RemoveAllAuras()
|
void Unit::RemoveAllAuras(AuraRemoveMode mode /*= AURA_REMOVE_BY_DEFAULT*/)
|
||||||
{
|
{
|
||||||
while (!m_Auras.empty())
|
while (!m_Auras.empty())
|
||||||
{
|
{
|
||||||
AuraMap::iterator iter = m_Auras.begin();
|
AuraMap::iterator iter = m_Auras.begin();
|
||||||
RemoveAura(iter);
|
RemoveAura(iter,mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11105,7 +11106,7 @@ void Unit::CleanupsBeforeDelete()
|
||||||
ClearComboPointHolders();
|
ClearComboPointHolders();
|
||||||
DeleteThreatList();
|
DeleteThreatList();
|
||||||
getHostileRefManager().setOnlineOfflineState(false);
|
getHostileRefManager().setOnlineOfflineState(false);
|
||||||
RemoveAllAuras();
|
RemoveAllAuras(AURA_REMOVE_BY_DELETE);
|
||||||
RemoveAllGameObjects();
|
RemoveAllGameObjects();
|
||||||
RemoveAllDynObjects();
|
RemoveAllDynObjects();
|
||||||
GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
|
GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,8 @@ enum AuraRemoveMode
|
||||||
AURA_REMOVE_BY_STACK, // at replace by similar aura
|
AURA_REMOVE_BY_STACK, // at replace by similar aura
|
||||||
AURA_REMOVE_BY_CANCEL,
|
AURA_REMOVE_BY_CANCEL,
|
||||||
AURA_REMOVE_BY_DISPEL,
|
AURA_REMOVE_BY_DISPEL,
|
||||||
AURA_REMOVE_BY_DEATH
|
AURA_REMOVE_BY_DEATH,
|
||||||
|
AURA_REMOVE_BY_DELETE, // use for speedup and prevent unexpected effects at player logout/pet unsummon (must be used _only_ after save), delete.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UnitMods
|
enum UnitMods
|
||||||
|
|
@ -1206,7 +1207,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
|
|
||||||
bool AddAura(Aura *aur);
|
bool AddAura(Aura *aur);
|
||||||
|
|
||||||
void RemoveAura(Aura* aura);
|
void RemoveAura(Aura* aura, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
||||||
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
||||||
void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL);
|
void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL);
|
||||||
void RemoveSingleSpellAurasFromStack(uint32 spellId);
|
void RemoveSingleSpellAurasFromStack(uint32 spellId);
|
||||||
|
|
@ -1228,7 +1229,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
void RemoveAurasWithInterruptFlags(uint32 flags);
|
void RemoveAurasWithInterruptFlags(uint32 flags);
|
||||||
void RemoveAurasWithDispelType( DispelType type );
|
void RemoveAurasWithDispelType( DispelType type );
|
||||||
|
|
||||||
void RemoveAllAuras();
|
void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
|
||||||
void RemoveArenaAuras(bool onleave = false);
|
void RemoveArenaAuras(bool onleave = false);
|
||||||
void RemoveAllAurasOnDeath();
|
void RemoveAllAurasOnDeath();
|
||||||
void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime);
|
void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "8741"
|
#define REVISION_NR "8742"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue