diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index 9c423760e..2742398a6 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -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; } diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 053f8d077..a0f0c9e39 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -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; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 94a91eb06..3240562f7 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -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()) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e5dcdb6d6..e23be051a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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) diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 6add902a4..797631540 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -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(); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 4b2967462..c46c7357c 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -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 diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index d5083d85c..e28a628dd 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -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) diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index 6dd3f2812..c4995bd47 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -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);