From 92fc09b1b5507c11c9e7ca63e6de0ec7574f0810 Mon Sep 17 00:00:00 2001 From: Giacomo Pozzoni Date: Fri, 2 Aug 2019 16:09:02 +0200 Subject: 3.3.5 Don't allow to summon dead hunter pets (#23271) * Core/Player: Add support to SMSG_PET_TAME_FAILURE * Core/Pet: Don't summon dead pets when using "Call pet" (cherry picked from commit a0f8ce14e9a7aeceea035a733625cc695909a5bd) --- src/server/game/Entities/Pet/PetDefines.h | 19 +++++++++++++++++++ src/server/game/Entities/Player/Player.cpp | 16 +++++++++++++++- src/server/game/Entities/Player/Player.h | 3 ++- src/server/game/Server/Packets/PetPackets.cpp | 7 +++++++ src/server/game/Server/Packets/PetPackets.h | 10 ++++++++++ src/server/game/Server/Protocol/Opcodes.cpp | 2 +- src/server/game/Spells/SpellEffects.cpp | 2 +- 7 files changed, 55 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Pet/PetDefines.h b/src/server/game/Entities/Pet/PetDefines.h index 266c6f1e15a..83607eb0bc1 100644 --- a/src/server/game/Entities/Pet/PetDefines.h +++ b/src/server/game/Entities/Pet/PetDefines.h @@ -79,4 +79,23 @@ enum PetTalk #define PET_FOLLOW_DIST 1.0f #define PET_FOLLOW_ANGLE float(M_PI) +enum class PetTameResult : uint8 +{ + Ok = 0, + InvalidCreature = 1, + TooMany = 2, + CreatureAlreadyOwned = 3, + NotTameable = 4, + AnotherSummonActive = 5, + UnitsCantTame = 6, + NoPetAvailable = 7, + InternalError = 8, + TooHighLevel = 9, + Dead = 10, + NotDead = 11, + CantControlExotic = 12, + InvalidSlot = 13, + EliteTooHighLevel = 14 +}; + #endif diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4edd20b9d62..22afdf05479 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -22016,6 +22016,13 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) } } +void Player::SendTameFailure(PetTameResult result) +{ + WorldPackets::Pet::PetTameFailure petTameFailure; + petTameFailure.Result = AsUnderlyingType(result); + SendDirectMessage(petTameFailure.Write()); +} + void Player::AddPetAura(PetAura const* petSpell) { m_petAuras.insert(petSpell); @@ -28505,12 +28512,19 @@ Guild const* Player::GetGuild() const return guildId ? sGuildMgr->GetGuildById(guildId) : nullptr; } -Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 duration) +Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 duration, bool aliveOnly) { Pet* pet = new Pet(this, petType); if (petType == SUMMON_PET && pet->LoadPetFromDB(this, entry)) { + if (aliveOnly && !pet->IsAlive()) + { + pet->DespawnOrUnsummon(); + SendTameFailure(PetTameResult::Dead); + return nullptr; + } + if (duration > 0) pet->SetDuration(duration); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ccc66ea506b..85578cd1ff6 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1207,8 +1207,9 @@ class TC_GAME_API Player : public Unit, public GridObject void setDeathState(DeathState s) override; // overwrite Unit::setDeathState Pet* GetPet() const; - Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime); + Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime, bool aliveOnly = false); void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false); + void SendTameFailure(PetTameResult result); // pet auras std::unordered_set m_petAuras; diff --git a/src/server/game/Server/Packets/PetPackets.cpp b/src/server/game/Server/Packets/PetPackets.cpp index 1389f36f530..52970173adc 100644 --- a/src/server/game/Server/Packets/PetPackets.cpp +++ b/src/server/game/Server/Packets/PetPackets.cpp @@ -208,3 +208,10 @@ WorldPacket const* WorldPackets::Pet::PetActionSound::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Pet::PetTameFailure::Write() +{ + _worldPacket << uint8(Result); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/PetPackets.h b/src/server/game/Server/Packets/PetPackets.h index 52bdb6850ae..125c79828ae 100644 --- a/src/server/game/Server/Packets/PetPackets.h +++ b/src/server/game/Server/Packets/PetPackets.h @@ -269,6 +269,16 @@ namespace WorldPackets ObjectGuid UnitGUID; int32 Action = 0; }; + + class PetTameFailure final : public ServerPacket + { + public: + PetTameFailure() : ServerPacket(SMSG_PET_TAME_FAILURE, 1) { } + + WorldPacket const* Write() override; + + uint8 Result = 0; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index f0a7262d2e2..57ab5a4cee1 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1699,7 +1699,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_SPELLS_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_STABLE_LIST, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_STABLE_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_TAME_FAILURE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_TAME_FAILURE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_UNLEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PHASE_SHIFT_CHANGE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYED_TIME, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index cf8fe0fa959..59974523b9c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2634,7 +2634,7 @@ void Spell::EffectSummonPet() float x, y, z; owner->GetClosePoint(x, y, z, owner->GetCombatReach()); - Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0); + Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0, true); if (!pet) return; -- cgit v1.2.3