fix(Core/Pets): fixed crash happening when current pet is forcibly removed (#10025)
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user