[8023] Move guardian list at Unit level and unsummon guardians at owner-creature death/unload.

This expected to fix well known crash at intances unload with creature with summoned guardians.
Note: this "fix" special case but not original source of problem in general.
This commit is contained in:
VladimirMangos 2009-06-15 23:43:15 +04:00
parent 02a71edb86
commit 309ac7ead0
6 changed files with 56 additions and 46 deletions

View file

@ -1372,7 +1372,6 @@ void Player::setDeathState(DeathState s)
// remove uncontrolled pets
RemoveMiniPet();
RemoveGuardians();
// save value before aura remove in Unit::setDeathState
ressSpellId = GetUInt32Value(PLAYER_SELF_RES_SPELL);
@ -1764,7 +1763,6 @@ void Player::RemoveFromWorld()
Uncharm();
UnsummonAllTotems();
RemoveMiniPet();
RemoveGuardians();
}
for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
@ -16213,7 +16211,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
m_miniPet = 0;
break;
case GUARDIAN_PET:
m_guardianPets.erase(pet->GetGUID());
RemoveGuardian(pet);
break;
default:
if(GetPetGUID() == pet->GetGUID())
@ -16270,32 +16268,6 @@ Pet* Player::GetMiniPet()
return ObjectAccessor::GetPet(m_miniPet);
}
void Player::RemoveGuardians()
{
while(!m_guardianPets.empty())
{
uint64 guid = *m_guardianPets.begin();
if(Pet* pet = ObjectAccessor::GetPet(guid))
pet->Remove(PET_SAVE_AS_DELETED);
m_guardianPets.erase(guid);
}
}
bool Player::HasGuardianWithEntry(uint32 entry)
{
// pet guid middle part is entry (and creature also)
// and in guardian list must be guardians with same entry _always_
for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
{
if(Pet* pet = ObjectAccessor::GetPet(*itr))
if (pet->GetEntry() == entry)
return true;
}
return false;
}
void Player::Uncharm()
{
Unit* charm = GetCharm();

View file

@ -273,8 +273,6 @@ struct Runes
}
};
typedef std::set<uint64> GuardianPetList;
struct EnchantDuration
{
EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) {};
@ -991,10 +989,6 @@ class MANGOS_DLL_SPEC Player : public Unit
void RemoveMiniPet();
Pet* GetMiniPet();
void SetMiniPet(Pet* pet) { m_miniPet = pet->GetGUID(); }
void RemoveGuardians();
bool HasGuardianWithEntry(uint32 entry);
void AddGuardian(Pet* pet) { m_guardianPets.insert(pet->GetGUID()); }
GuardianPetList const& GetGuardians() const { return m_guardianPets; }
void Uncharm();
uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
@ -2311,7 +2305,6 @@ class MANGOS_DLL_SPEC Player : public Unit
uint64 m_auraUpdateMask;
uint64 m_miniPet;
GuardianPetList m_guardianPets;
// Player summoning
time_t m_summon_expire;

View file

@ -3711,8 +3711,7 @@ void Spell::EffectSummonGuardian(uint32 i)
spawnCreature->AIM_Initialize();
if(m_caster->GetTypeId()==TYPEID_PLAYER)
((Player*)m_caster)->AddGuardian(spawnCreature);
m_caster->AddGuardian(spawnCreature);
map->Add((Creature*)spawnCreature);
}

View file

@ -7383,13 +7383,10 @@ void Unit::CombatStopWithPets(bool includingCast)
pet->CombatStop(includingCast);
if(Unit* charm = GetCharm())
charm->CombatStop(includingCast);
if(GetTypeId()==TYPEID_PLAYER)
{
GuardianPetList const& guardians = ((Player*)this)->GetGuardians();
for(GuardianPetList::const_iterator itr = guardians.begin(); itr != guardians.end(); ++itr)
if(Unit* guardian = Unit::GetUnit(*this,*itr))
guardian->CombatStop(includingCast);
}
for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
if(Unit* guardian = Unit::GetUnit(*this,*itr))
guardian->CombatStop(includingCast);
}
bool Unit::isAttackingPlayer() const
@ -7563,6 +7560,44 @@ void Unit::SetCharm(Unit* pet)
((Player*)this)->m_mover = pet ? pet : this;
}
void Unit::AddGuardian( Pet* pet )
{
m_guardianPets.insert(pet->GetGUID());
}
void Unit::RemoveGuardian( Pet* pet )
{
m_guardianPets.erase(pet->GetGUID());
}
void Unit::RemoveGuardians()
{
while(!m_guardianPets.empty())
{
uint64 guid = *m_guardianPets.begin();
if(Pet* pet = ObjectAccessor::GetPet(guid))
pet->Remove(PET_SAVE_AS_DELETED);
m_guardianPets.erase(guid);
}
}
bool Unit::HasGuardianWithEntry(uint32 entry)
{
// pet guid middle part is entry (and creature also)
// and in guardian list must be guardians with same entry _always_
for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
{
if(Pet* pet = ObjectAccessor::GetPet(*itr))
if (pet->GetEntry() == entry)
return true;
}
return false;
}
void Unit::UnsummonAllTotems()
{
for (int8 i = 0; i < MAX_TOTEM; ++i)
@ -9461,6 +9496,7 @@ void Unit::setDeathState(DeathState s)
if (s == JUST_DIED)
{
RemoveAllAurasOnDeath();
RemoveGuardians();
UnsummonAllTotems();
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
@ -10322,6 +10358,7 @@ void Unit::RemoveFromWorld()
if(IsInWorld())
{
RemoveNotOwnSingleTargetAuras();
RemoveGuardians();
}
Object::RemoveFromWorld();

View file

@ -859,6 +859,8 @@ enum ReactiveType
#define MAX_REACTIVE 3
#define MAX_TOTEM 4
typedef std::set<uint64> GuardianPetList;
// delay time next attack to prevent client attack animation problems
#define ATTACK_DISPLAY_DELAY 200
@ -1191,6 +1193,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void SetPet(Pet* pet);
void SetCharm(Unit* pet);
void AddGuardian(Pet* pet);
void RemoveGuardian(Pet* pet);
void RemoveGuardians();
bool HasGuardianWithEntry(uint32 entry);
bool isCharmed() const { return GetCharmerGUID() != 0; }
CharmInfo* GetCharmInfo() { return m_charmInfo; }
@ -1581,5 +1588,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
FollowerRefManager m_FollowingRefManager;
ComboPointHolderSet m_ComboPointHolders;
GuardianPetList m_guardianPets;
};
#endif

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8022"
#define REVISION_NR "8023"
#endif // __REVISION_NR_H__