fix(Core/Pets): fixed crash happening when current pet is forcibly removed (#10025)

This commit is contained in:
Kargatum
2022-01-10 19:19:43 +07:00
committed by GitHub
parent b2df4aa970
commit c1ebda66ba
8 changed files with 50 additions and 10 deletions

View File

@@ -285,7 +285,7 @@ void TempSummon::UnSummon(uint32 msTime)
//ASSERT(!IsPet());
if (IsPet())
{
((Pet*)this)->Remove(PET_SAVE_NOT_IN_SLOT);
ToPet()->Remove(PET_SAVE_NOT_IN_SLOT);
ASSERT(!IsInWorld());
return;
}

View File

@@ -2252,6 +2252,8 @@ bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32
if (!InitEntry(Entry))
return false;
// Force regen flag for player pets, just like we do for players themselves
SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER);
SetSheath(SHEATH_STATE_MELEE);
return true;

View File

@@ -8656,7 +8656,7 @@ Pet* Player::GetPet() const
if (!pet)
return nullptr;
if (IsInWorld() && pet)
if (IsInWorld())
return pet;
//there may be a guardian in slot
@@ -8712,11 +8712,40 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
m_temporaryUnsummonedPetNumber = 0;
}
if (!pet || pet->GetOwnerGUID() != GetGUID())
if (!pet)
{
if (mode == PET_SAVE_NOT_IN_SLOT && m_petStable && m_petStable->CurrentPet)
{
// Handle removing pet while it is in "temporarily unsummoned" state, for example on mount
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
stmt->setUInt8(0, PET_SAVE_NOT_IN_SLOT);
stmt->setUInt32(1, GetGUID().GetCounter());
stmt->setUInt32(2, m_petStable->CurrentPet->PetNumber);
CharacterDatabase.Execute(stmt);
m_petStable->UnslottedPets.push_back(std::move(*m_petStable->CurrentPet));
m_petStable->CurrentPet.reset();
}
return;
}
pet->CombatStop();
if (returnreagent)
{
switch (pet->GetEntry())
{
//warlock pets except imp are removed(?) when logging out
case 1860:
case 1863:
case 417:
case 17252:
mode = PET_SAVE_NOT_IN_SLOT;
break;
}
}
// only if current pet in slot
pet->SavePetToDB(mode);
@@ -13337,7 +13366,7 @@ void Player::AddKnownCurrency(uint32 itemId)
void Player::UnsummonPetTemporaryIfAny()
{
Pet* pet = GetPet();
if (!pet || !pet->IsInWorld())
if (!pet)
return;
if (!m_temporaryUnsummonedPetNumber && pet->isControlled() && !pet->isTemporarySummoned())

View File

@@ -10168,10 +10168,15 @@ void Unit::SetMinion(Minion* minion, bool apply)
if (oldPet != minion && (oldPet->IsPet() || minion->IsPet() || oldPet->GetEntry() != minion->GetEntry()))
{
// remove existing minion pet
if (oldPet->IsPet())
((Pet*)oldPet)->Remove(PET_SAVE_AS_CURRENT);
if (Pet* oldPetAsPet = oldPet->ToPet())
{
oldPetAsPet->Remove(PET_SAVE_NOT_IN_SLOT);
}
else
{
oldPet->UnSummon();
}
SetPetGUID(minion->GetGUID());
SetMinionGUID(ObjectGuid::Empty);
}
@@ -10239,6 +10244,7 @@ void Unit::SetMinion(Minion* minion, bool apply)
{
// All summoned by totem minions must disappear when it is removed.
if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell()))
{
for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (spInfo->Effects[i].Effect != SPELL_EFFECT_SUMMON)
@@ -10246,6 +10252,7 @@ void Unit::SetMinion(Minion* minion, bool apply)
RemoveAllMinionsByEntry(spInfo->Effects[i].MiscValue);
}
}
}
if (GetTypeId() == TYPEID_PLAYER)

View File

@@ -948,7 +948,7 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData)
pet->SetPower(POWER_HAPPINESS, feelty > 50000 ? (feelty - 50000) : 0);
}
_player->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED);
_player->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED);
}
else if (pet->GetGUID() == _player->GetCharmGUID())
_player->StopCastingCharm();

View File

@@ -607,7 +607,7 @@ void WorldSession::LogoutPlayer(bool save)
guild->HandleMemberLogout(this);
///- Remove pet
_player->RemovePet(nullptr, PET_SAVE_AS_CURRENT);
_player->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true);
// pussywizard: on logout remove auras that are removed at map change (before saving to db)
// there are some positive auras from boss encounters that can be kept by logging out and logging in after boss is dead, and may be used on next bosses

View File

@@ -4713,7 +4713,7 @@ void Spell::EffectDismissPet(SpellEffIndex effIndex)
Pet* pet = unitTarget->ToPet();
ExecuteLogEffectUnsummonObject(effIndex, pet);
pet->GetOwner()->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
pet->Remove(PET_SAVE_NOT_IN_SLOT);
}
void Spell::EffectSummonObject(SpellEffIndex effIndex)

View File

@@ -71,7 +71,9 @@ public:
return false;
}
if (player->GetPetGUID())
PetStable const* petStable = player->GetPetStable();
if (petStable && (petStable->CurrentPet || petStable->GetUnslottedHunterPet()))
{
handler->PSendSysMessage("You already have a pet");
handler->SetSentErrorMessage(true);