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
@@ -285,7 +285,7 @@ void TempSummon::UnSummon(uint32 msTime)
//ASSERT(!IsPet()); //ASSERT(!IsPet());
if (IsPet()) if (IsPet())
{ {
((Pet*)this)->Remove(PET_SAVE_NOT_IN_SLOT); ToPet()->Remove(PET_SAVE_NOT_IN_SLOT);
ASSERT(!IsInWorld()); ASSERT(!IsInWorld());
return; return;
} }
+2
View File
@@ -2252,6 +2252,8 @@ bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32
if (!InitEntry(Entry)) if (!InitEntry(Entry))
return false; 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); SetSheath(SHEATH_STATE_MELEE);
return true; return true;
+32 -3
View File
@@ -8656,7 +8656,7 @@ Pet* Player::GetPet() const
if (!pet) if (!pet)
return nullptr; return nullptr;
if (IsInWorld() && pet) if (IsInWorld())
return pet; return pet;
//there may be a guardian in slot //there may be a guardian in slot
@@ -8712,11 +8712,40 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
m_temporaryUnsummonedPetNumber = 0; 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; return;
}
pet->CombatStop(); 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 // only if current pet in slot
pet->SavePetToDB(mode); pet->SavePetToDB(mode);
@@ -13337,7 +13366,7 @@ void Player::AddKnownCurrency(uint32 itemId)
void Player::UnsummonPetTemporaryIfAny() void Player::UnsummonPetTemporaryIfAny()
{ {
Pet* pet = GetPet(); Pet* pet = GetPet();
if (!pet || !pet->IsInWorld()) if (!pet)
return; return;
if (!m_temporaryUnsummonedPetNumber && pet->isControlled() && !pet->isTemporarySummoned()) if (!m_temporaryUnsummonedPetNumber && pet->isControlled() && !pet->isTemporarySummoned())
+9 -2
View File
@@ -10168,10 +10168,15 @@ void Unit::SetMinion(Minion* minion, bool apply)
if (oldPet != minion && (oldPet->IsPet() || minion->IsPet() || oldPet->GetEntry() != minion->GetEntry())) if (oldPet != minion && (oldPet->IsPet() || minion->IsPet() || oldPet->GetEntry() != minion->GetEntry()))
{ {
// remove existing minion pet // remove existing minion pet
if (oldPet->IsPet()) if (Pet* oldPetAsPet = oldPet->ToPet())
((Pet*)oldPet)->Remove(PET_SAVE_AS_CURRENT); {
oldPetAsPet->Remove(PET_SAVE_NOT_IN_SLOT);
}
else else
{
oldPet->UnSummon(); oldPet->UnSummon();
}
SetPetGUID(minion->GetGUID()); SetPetGUID(minion->GetGUID());
SetMinionGUID(ObjectGuid::Empty); 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. // All summoned by totem minions must disappear when it is removed.
if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell())) if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell()))
{
for (int i = 0; i < MAX_SPELL_EFFECTS; ++i) for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
{ {
if (spInfo->Effects[i].Effect != SPELL_EFFECT_SUMMON) if (spInfo->Effects[i].Effect != SPELL_EFFECT_SUMMON)
@@ -10247,6 +10253,7 @@ void Unit::SetMinion(Minion* minion, bool apply)
RemoveAllMinionsByEntry(spInfo->Effects[i].MiscValue); RemoveAllMinionsByEntry(spInfo->Effects[i].MiscValue);
} }
} }
}
if (GetTypeId() == TYPEID_PLAYER) if (GetTypeId() == TYPEID_PLAYER)
{ {
+1 -1
View File
@@ -948,7 +948,7 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData)
pet->SetPower(POWER_HAPPINESS, feelty > 50000 ? (feelty - 50000) : 0); 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()) else if (pet->GetGUID() == _player->GetCharmGUID())
_player->StopCastingCharm(); _player->StopCastingCharm();
+1 -1
View File
@@ -607,7 +607,7 @@ void WorldSession::LogoutPlayer(bool save)
guild->HandleMemberLogout(this); guild->HandleMemberLogout(this);
///- Remove pet ///- 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) // 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 // 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
+1 -1
View File
@@ -4713,7 +4713,7 @@ void Spell::EffectDismissPet(SpellEffIndex effIndex)
Pet* pet = unitTarget->ToPet(); Pet* pet = unitTarget->ToPet();
ExecuteLogEffectUnsummonObject(effIndex, pet); ExecuteLogEffectUnsummonObject(effIndex, pet);
pet->GetOwner()->RemovePet(pet, PET_SAVE_NOT_IN_SLOT); pet->Remove(PET_SAVE_NOT_IN_SLOT);
} }
void Spell::EffectSummonObject(SpellEffIndex effIndex) void Spell::EffectSummonObject(SpellEffIndex effIndex)
+3 -1
View File
@@ -71,7 +71,9 @@ public:
return false; return false;
} }
if (player->GetPetGUID()) PetStable const* petStable = player->GetPetStable();
if (petStable && (petStable->CurrentPet || petStable->GetUnslottedHunterPet()))
{ {
handler->PSendSysMessage("You already have a pet"); handler->PSendSysMessage("You already have a pet");
handler->SetSentErrorMessage(true); handler->SetSentErrorMessage(true);