From e203ecda88a327c4e93588f39cc4ffdcf99b30f7 Mon Sep 17 00:00:00 2001 From: Giacomo Pozzoni Date: Mon, 10 May 2021 22:01:41 +0200 Subject: Core/Pet: Attempt to fix assertions triggered when summoning pets (#26501) * Core/Pet: Attempt to fix an assertion triggered when re-summoning the current pet * Core/Pet: Attempt to fix an assertion triggered when stabling a pet while in a vehicle * Core/Pet: Attempt to fix an assertion triggered when stabling a pet and casting spell 6962 * Core/Pet: Attempt to fix an assertion triggered when casting spell 6962 while being dead * Core/Pet: Attempt to fix an assertion triggered when summoning a pet while on vehicle 34775 * Handle cases in a generic way * Code cleanup * Core/Pet: Attempt to fix an assertion triggered when summoning a pet while on vehicle 34775 with a new character --- src/server/game/Entities/Pet/Pet.cpp | 23 ++++++++++++++++++++++- src/server/game/Entities/Player/Player.cpp | 3 +++ src/server/game/Handlers/NPCHandler.cpp | 2 -- 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index d887f260378..c1460157be3 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -197,6 +197,10 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c return false; } + // Don't try to reload the current pet + if (petStable->CurrentPet && owner->GetPet() && petStable->CurrentPet.value().PetNumber == petInfo->PetNumber) + return false; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petInfo->CreatedBySpellId); bool isTemporarySummon = spellInfo && spellInfo->GetDuration() > 0; @@ -320,9 +324,13 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (slot == PET_SAVE_NOT_IN_SLOT) { + uint32 petInfoNumber = petInfo->PetNumber; + if (petStable->CurrentPet) + owner->RemovePet(nullptr, PET_SAVE_NOT_IN_SLOT); + auto unslottedPetItr = std::find_if(petStable->UnslottedPets.begin(), petStable->UnslottedPets.end(), [&](PetStable::PetInfo const& unslottedPet) { - return unslottedPet.PetNumber == petInfo->PetNumber; + return unslottedPet.PetNumber == petInfoNumber; }); ASSERT(!petStable->CurrentPet); ASSERT(unslottedPetItr != petStable->UnslottedPets.end()); @@ -333,6 +341,19 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c // old petInfo pointer is no longer valid, refresh it petInfo = &petStable->CurrentPet.value(); } + else if (PET_SAVE_FIRST_STABLE_SLOT <= slot && slot <= PET_SAVE_LAST_STABLE_SLOT) + { + auto stabledPet = std::find_if(petStable->StabledPets.begin(), petStable->StabledPets.end(), [petnumber](Optional const& pet) + { + return pet && pet->PetNumber == petnumber; + }); + ASSERT(stabledPet != petStable->StabledPets.end()); + + std::swap(*stabledPet, petStable->CurrentPet); + + // old petInfo pointer is no longer valid, refresh it + petInfo = &petStable->CurrentPet.value(); + } // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 51f5586c78c..fbb7c73d8b6 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -26786,6 +26786,9 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy return nullptr; } + if (petType == SUMMON_PET && petStable.CurrentPet) + RemovePet(nullptr, PET_SAVE_NOT_IN_SLOT); + pet->SetCreatorGUID(GetGUID()); pet->SetFaction(GetFaction()); diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index c171df8b9ec..0e2339b5c60 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -542,8 +542,6 @@ void WorldSession::HandleUnstablePet(WorldPacket& recvData) } else { - std::swap(*stabledPet, petStable->CurrentPet); - // update current pet slot in db immediately to maintain slot consistency, dismissed pet was already saved CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID); stmt->setUInt8(0, PET_SAVE_AS_CURRENT); -- cgit v1.2.3