From 1cbf52fb3dffce0aa7ae02af0d808ddcdc63ff15 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Mon, 24 Jan 2022 01:19:52 +0100 Subject: [PATCH] fix(Core/Spells): Fixed Revive Pet. (#10324) Fixed #10267 --- src/server/game/Entities/Pet/Pet.cpp | 14 +++++--- src/server/game/Entities/Pet/Pet.h | 2 +- src/server/game/Entities/Player/Player.cpp | 40 ++++++++++++---------- src/server/game/Entities/Player/Player.h | 2 +- src/server/game/Spells/SpellEffects.cpp | 32 ++++++++--------- 5 files changed, 48 insertions(+), 42 deletions(-) diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index fffcf8c7b..983f178b9 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -202,7 +202,7 @@ std::pair Pet::GetLoadPetInfo(PetStable return { nullptr, PET_SAVE_AS_DELETED }; } -bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool current) +bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool current, uint32 healthPct /*= 0*/) { m_loading = true; @@ -408,7 +408,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c owner->ToPlayer()->SetLastPetNumber(petInfo->PetNumber); owner->GetSession()->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(std::make_shared(ownerid, petInfo->PetNumber))) - .AfterComplete([this, owner, session = owner->GetSession(), isTemporarySummon, current, lastSaveTime = petInfo->LastSaveTime, savedhealth = petInfo->Health, savedmana = petInfo->Mana] + .AfterComplete([this, owner, session = owner->GetSession(), isTemporarySummon, current, lastSaveTime = petInfo->LastSaveTime, savedhealth = petInfo->Health, savedmana = petInfo->Mana, healthPct] (SQLQueryHolderBase const& holder) { if (session->GetPlayer() != owner || owner->GetPet() != this) @@ -458,6 +458,12 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c } } + uint32 curHealth = savedhealth; + if (healthPct) + { + curHealth = CountPctFromMaxHealth(healthPct); + } + if (getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current { SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); @@ -465,11 +471,11 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c } else { - if (!savedhealth && getPetType() == HUNTER_PET) + if (!curHealth && getPetType() == HUNTER_PET) setDeathState(JUST_DIED); else { - SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); + SetHealth(curHealth > GetMaxHealth() ? GetMaxHealth() : curHealth); SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana); } } diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 7c7181800..2f9b84167 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -59,7 +59,7 @@ public: bool CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner); bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask); static std::pair GetLoadPetInfo(PetStable const& stable, uint32 petEntry, uint32 petnumber, bool current); - bool LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool current); + bool LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool current, uint32 healthPct = 0); bool isBeingLoaded() const override { return m_loading; } void SavePetToDB(PetSaveMode mode); void FillPetInfo(PetStable::PetInfo* petInfo) const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fa9e850bb..12051a89a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8737,13 +8737,13 @@ Pet* Player::GetPet() const return nullptr; } -Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration /*= 0s*/) +Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration /*= 0s*/, uint32 healthPct /*= 0*/) { PetStable& petStable = GetOrInitPetStable(); Pet* pet = new Pet(this, petType); - if (petType == SUMMON_PET && pet->LoadPetFromDB(this, entry, 0, false)) + if (petType == SUMMON_PET && pet->LoadPetFromDB(this, entry, 0, false, healthPct)) { // Remove Demonic Sacrifice auras (known pet) Unit::AuraEffectList const& auraClassScripts = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); @@ -8810,23 +8810,27 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy switch (petType) { - case SUMMON_PET: - { - if (pet->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON || pet->GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD) - pet->GetCharmInfo()->SetPetNumber(pet_number, true); // Show pet details tab (Shift+P) only for demons & undead - else - pet->GetCharmInfo()->SetPetNumber(pet_number, false); + case SUMMON_PET: + { + if (pet->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON || pet->GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD) + { + pet->GetCharmInfo()->SetPetNumber(pet_number, true); // Show pet details tab (Shift+P) only for demons & undead + } + else + { + pet->GetCharmInfo()->SetPetNumber(pet_number, false); + } - pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); - pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000); - pet->SetFullHealth(); - pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA)); - pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(nullptr))); // cast can't be helped in this case - break; - } - default: - break; + pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); + pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); + pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000); + pet->SetFullHealth(); + pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA)); + pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(nullptr))); // cast can't be helped in this case + break; + } + default: + break; } map->AddToMap(pet->ToCreature(), true); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 07355bbe6..adb9fc9f4 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1171,7 +1171,7 @@ public: [[nodiscard]] PetStable const* GetPetStable() const { return m_petStable.get(); } [[nodiscard]] Pet* GetPet() const; - Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration = 0s); + Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, Milliseconds duration = 0s, uint32 healthPct = 0); void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false); bool CanPetResurrect(); bool IsExistPet(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index e28a628dd..f9f38c4bc 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5379,35 +5379,31 @@ void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/) Player* player = m_caster->ToPlayer(); if (!player) + { return; + } - // Maybe player dismissed dead pet or pet despawned? - bool hadPet = true; - - if (!player->GetPet()) + Pet* pet = player->GetPet(); + if (!pet) { // Position passed to SummonPet is irrelevant with current implementation, // pet will be relocated without using these coords in Pet::LoadPetFromDB - player->SummonPet(0, 0.0f, 0.0f, 0.0f, 0.0f, SUMMON_PET); - hadPet = false; + player->SummonPet(0, 0.0f, 0.0f, 0.0f, 0.0f, SUMMON_PET, 0s, damage); + return; } // TODO: Better to fail Hunter's "Revive Pet" at cast instead of here when casting ends - Pet* pet = player->GetPet(); // Attempt to get current pet - if (!pet || pet->IsAlive()) - return; - - // If player did have a pet before reviving, teleport it - if (hadPet) + if (pet->IsAlive()) { - // Reposition the pet's corpse before reviving so as not to grab aggro - // We can use a different, more accurate version of GetClosePoint() since we have a pet - float x, y, z; // Will be used later to reposition the pet if we have one - player->GetClosePoint(x, y, z, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle()); - pet->NearTeleportTo(x, y, z, player->GetOrientation()); - pet->Relocate(x, y, z, player->GetOrientation()); // This is needed so SaveStayPosition() will get the proper coords. + return; } + // Reposition the pet's corpse before reviving so as not to grab aggro + // We can use a different, more accurate version of GetClosePoint() since we have a pet + float x, y, z; // Will be used later to reposition the pet if we have one + player->GetClosePoint(x, y, z, pet->GetCombatReach(), PET_FOLLOW_DIST, pet->GetFollowAngle()); + pet->NearTeleportTo(x, y, z, player->GetOrientation()); + pet->Relocate(x, y, z, player->GetOrientation()); // This is needed so SaveStayPosition() will get the proper coords. pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE); pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); pet->setDeathState(ALIVE);