[10739] Cleanup pet remove code and some fixes.

* Merge Player::RemovePet and Pet::Remove function code to Pet::Unsummon
  This let be sure that in all cases all required steps doen. For example this fix
  creature's guardians propertly remove from guardians list.
* Add new pet save mode PET_SAVE_REAGENTS as replacement PET_SAVE_NOT_IN_SLOT+true-arg stable pair in old function args
  This will avoid use reagent save arg with wrong different save modes.
* Fixed recently added code with absent check for re-summon protector pet call.
This commit is contained in:
VladimirMangos 2010-11-19 02:07:14 +03:00
parent de66f32882
commit f9bcfa3a89
13 changed files with 138 additions and 125 deletions

View file

@ -356,8 +356,11 @@ void Pet::SavePetToDB(PetSaveMode mode)
// current/stable/not_in_slot
if (mode >= PET_SAVE_AS_CURRENT)
{
// reagents must be returned before save call
if (mode == PET_SAVE_REAGENTS)
mode = PET_SAVE_NOT_IN_SLOT;
// not save pet as current if another pet temporary unsummoned
if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
else if (mode == PET_SAVE_AS_CURRENT && pOwner->GetTemporaryUnsummonedPetNumber() &&
pOwner->GetTemporaryUnsummonedPetNumber() != m_charmInfo->GetPetNumber())
{
// pet will lost anyway at restore temporary unsummoned
@ -453,7 +456,7 @@ void Pet::SetDeathState(DeathState s) // overwrite virtual
{
//remove summoned pet (no corpse)
if(getPetType()==SUMMON_PET)
Remove(PET_SAVE_NOT_IN_SLOT);
Unsummon(PET_SAVE_NOT_IN_SLOT);
// other will despawn at corpse desppawning (Pet::Update code)
else
{
@ -488,7 +491,7 @@ void Pet::Update(uint32 diff)
if (m_corpseDecayTimer <= diff)
{
MANGOS_ASSERT(getPetType()!=SUMMON_PET && "Must be already removed.");
Remove(PET_SAVE_NOT_IN_SLOT); //hunters' pets never get removed because of death, NEVER!
Unsummon(PET_SAVE_NOT_IN_SLOT); //hunters' pets never get removed because of death, NEVER!
return;
}
break;
@ -499,7 +502,7 @@ void Pet::Update(uint32 diff)
Unit* owner = GetOwner();
if (!owner || (!IsWithinDistInMap(owner, GetMap()->GetVisibilityDistance()) && (!owner->GetCharmGuid().IsEmpty() && (owner->GetCharmGuid() != GetObjectGuid()))) || (isControlled() && owner->GetPetGuid().IsEmpty()))
{
Remove(PET_SAVE_NOT_IN_SLOT, true);
Unsummon(PET_SAVE_REAGENTS);
return;
}
@ -507,7 +510,7 @@ void Pet::Update(uint32 diff)
{
if (owner->GetPetGuid() != GetObjectGuid())
{
Remove(getPetType()==HUNTER_PET?PET_SAVE_AS_DELETED:PET_SAVE_NOT_IN_SLOT);
Unsummon(getPetType() == HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT, owner);
return;
}
}
@ -518,7 +521,7 @@ void Pet::Update(uint32 diff)
m_duration -= (int32)diff;
else
{
Remove(getPetType() != SUMMON_PET ? PET_SAVE_AS_DELETED:PET_SAVE_NOT_IN_SLOT);
Unsummon(getPetType() != SUMMON_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT, owner);
return;
}
}
@ -656,23 +659,81 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
return true;
}
void Pet::Remove(PetSaveMode mode, bool returnreagent)
void Pet::Unsummon(PetSaveMode mode, Unit* owner /*= NULL*/)
{
Unit* owner = GetOwner();
if (!owner)
owner = GetOwner();
CombatStop();
if(owner)
{
if(owner->GetTypeId()==TYPEID_PLAYER)
{
((Player*)owner)->RemovePet(this,mode,returnreagent);
if (GetOwnerGuid() != owner->GetObjectGuid())
return;
Player* p_owner = owner->GetTypeId()==TYPEID_PLAYER ? (Player*)owner : NULL;
if (p_owner)
{
// not save secondary permanent pet as current
if (mode == PET_SAVE_AS_CURRENT && p_owner->GetTemporaryUnsummonedPetNumber() &&
p_owner->GetTemporaryUnsummonedPetNumber() != GetCharmInfo()->GetPetNumber())
mode = PET_SAVE_NOT_IN_SLOT;
if (mode == PET_SAVE_REAGENTS)
{
//returning of reagents only for players, so best done here
uint32 spellId = GetUInt32Value(UNIT_CREATED_BY_SPELL);
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (spellInfo)
{
for(uint32 i = 0; i < MAX_SPELL_REAGENTS; ++i)
{
if (spellInfo->Reagent[i] > 0)
{
ItemPosCountVec dest; //for succubus, voidwalker, felhunter and felguard credit soulshard when despawn reason other than death (out of range, logout)
uint8 msg = p_owner->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, spellInfo->Reagent[i], spellInfo->ReagentCount[i]);
if (msg == EQUIP_ERR_OK)
{
Item* item = p_owner->StoreNewItem(dest, spellInfo->Reagent[i], true);
if (p_owner->IsInWorld())
p_owner->SendNewItem(item, spellInfo->ReagentCount[i], true, false);
}
}
}
}
}
if (isControlled())
{
p_owner->RemovePetActionBar();
if (p_owner->GetGroup())
p_owner->SetGroupUpdateFlag(GROUP_UPDATE_PET);
}
}
// only if current pet in slot
if (owner->GetPetGuid() == GetObjectGuid())
owner->SetPet(0);
switch(getPetType())
{
case MINI_PET:
if (p_owner)
p_owner->_SetMiniPet(NULL);
break;
case PROTECTOR_PET:
case GUARDIAN_PET:
owner->RemoveGuardian(this);
break;
default:
if (owner->GetPetGuid() == GetObjectGuid())
owner->SetPet(NULL);
break;
}
}
SavePetToDB(mode);
AddObjectToRemoveList();
m_removed = true;
}