From c46cc865f565d515861af69db7c56431a6d84a37 Mon Sep 17 00:00:00 2001 From: Mykhailo Redko Date: Tue, 11 Feb 2025 15:47:51 +0200 Subject: [PATCH] Core/Pets: Implemented sound playback when dismissing warlock pets (#30683) (cherry picked from commit a827230910fd7e3e64bcb5526e2778b8b4752da4) --- src/server/game/Entities/Pet/PetDefines.h | 6 ++--- src/server/game/Entities/Unit/Unit.cpp | 23 +++++++++++-------- src/server/game/Entities/Unit/Unit.h | 8 ++++--- src/server/game/Handlers/PetHandler.cpp | 23 +++++++++++-------- src/server/game/Server/Packets/PetPackets.cpp | 9 ++++++++ src/server/game/Server/Packets/PetPackets.h | 12 ++++++++++ src/server/game/Server/Protocol/Opcodes.cpp | 2 +- 7 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/server/game/Entities/Pet/PetDefines.h b/src/server/game/Entities/Pet/PetDefines.h index 3be0ab20d4..820ae5d178 100644 --- a/src/server/game/Entities/Pet/PetDefines.h +++ b/src/server/game/Entities/Pet/PetDefines.h @@ -89,10 +89,10 @@ enum class PetActionFeedback : uint8 NoPath = 4 }; -enum PetTalk +enum PetAction : int32 { - PET_TALK_SPECIAL_SPELL = 0, - PET_TALK_ATTACK = 1 + PET_ACTION_SPECIAL_SPELL = 0, + PET_ACTION_ATTACK = 1 }; #define PET_FOLLOW_DIST 1.0f diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index eef0f570d4..85ae59e1ad 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -10634,7 +10634,7 @@ void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProc } ///----------Pet responses methods----------------- -void Unit::SendPetActionFeedback(PetActionFeedback msg, uint32 spellId) +void Unit::SendPetActionFeedback(PetActionFeedback msg, uint32 spellId) const { Unit* owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) @@ -10646,19 +10646,24 @@ void Unit::SendPetActionFeedback(PetActionFeedback msg, uint32 spellId) owner->ToPlayer()->SendDirectMessage(petActionFeedback.Write()); } -void Unit::SendPetTalk(uint32 pettalk) +void Unit::SendPetActionSound(PetAction action) const { - Unit* owner = GetOwner(); - if (!owner || owner->GetTypeId() != TYPEID_PLAYER) - return; - WorldPackets::Pet::PetActionSound petActionSound; petActionSound.UnitGUID = GetGUID(); - petActionSound.Action = pettalk; - owner->ToPlayer()->SendDirectMessage(petActionSound.Write()); + petActionSound.Action = action; + SendMessageToSet(petActionSound.Write(), false); } -void Unit::SendPetAIReaction(ObjectGuid guid) +void Unit::SendPetDismissSound() const +{ + WorldPackets::Pet::PetDismissSound petDismissSound; + petDismissSound.UnitGUID = GetGUID(); + petDismissSound.CreatureDisplayInfoID = GetNativeDisplayId(); + petDismissSound.ModelPosition = GetPosition(); + SendMessageToSet(petDismissSound.Write(), false); +} + +void Unit::SendPetAIReaction(ObjectGuid guid) const { Unit* owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9537667de5..a3378fe5b2 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -101,6 +101,7 @@ class VehicleJoinEvent; enum CharmType : uint8; enum class EncounterType : uint8; +enum PetAction : int32; enum class PetActionFeedback : uint8; enum MovementGeneratorType : uint8; enum ProcFlagsHit : uint32; @@ -1754,9 +1755,10 @@ class TC_GAME_API Unit : public WorldObject void ApplyControlStatesIfNeeded(); ///----------Pet responses methods----------------- - void SendPetActionFeedback(PetActionFeedback msg, uint32 spellId); - void SendPetTalk(uint32 pettalk); - void SendPetAIReaction(ObjectGuid guid); + void SendPetActionFeedback(PetActionFeedback msg, uint32 spellId) const; + void SendPetActionSound(PetAction action) const; + void SendPetDismissSound() const; + void SendPetAIReaction(ObjectGuid guid) const; ///----------End of Pet responses methods---------- void PropagateSpeedChange(); diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index ca7adbd4e0..06d86527ad 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -219,8 +219,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe AI->AttackStart(TargetUnit); // 10% chance to play special pet attack talk, else growl - if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance(10)) + pet->SendPetActionSound(PET_ACTION_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature @@ -249,10 +249,13 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe ASSERT(pet->GetTypeId() == TYPEID_UNIT); if (pet->IsPet()) { - if (((Pet*)pet)->getPetType() == HUNTER_PET) - GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); + if (pet->ToPet()->getPetType() == HUNTER_PET) + GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED); else - GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_NOT_IN_SLOT); + { + pet->SendPetDismissSound(); + GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_NOT_IN_SLOT); + } } else if (pet->HasUnitTypeMask(UNIT_MASK_MINION)) { @@ -361,8 +364,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != unit_target && roll_chance(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); @@ -743,10 +746,10 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell& { if (Pet* pet = creature->ToPet()) { - // 10% chance to play special pet attack talk, else growl + // 10% chance to play special pet attack sound, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk(PET_TALK_SPECIAL_SPELL); + if (pet->getPetType() == SUMMON_PET && roll_chance(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else pet->SendPetAIReaction(petCastSpell.PetGUID); } diff --git a/src/server/game/Server/Packets/PetPackets.cpp b/src/server/game/Server/Packets/PetPackets.cpp index 774c340d3d..c4368472e1 100644 --- a/src/server/game/Server/Packets/PetPackets.cpp +++ b/src/server/game/Server/Packets/PetPackets.cpp @@ -203,6 +203,15 @@ WorldPacket const* PetActionSound::Write() return &_worldPacket; } +WorldPacket const* PetDismissSound::Write() +{ + _worldPacket << UnitGUID; + _worldPacket << int32(CreatureDisplayInfoID); + _worldPacket << ModelPosition; + + return &_worldPacket; +} + WorldPacket const* PetTameFailure::Write() { _worldPacket << uint32(Result); diff --git a/src/server/game/Server/Packets/PetPackets.h b/src/server/game/Server/Packets/PetPackets.h index f59f111fb3..42e8045cdd 100644 --- a/src/server/game/Server/Packets/PetPackets.h +++ b/src/server/game/Server/Packets/PetPackets.h @@ -258,6 +258,18 @@ namespace WorldPackets int32 Action = 0; }; + class PetDismissSound final : public ServerPacket + { + public: + PetDismissSound() : ServerPacket(SMSG_PET_DISMISS_SOUND, 18 + 4 + 12) { } + + WorldPacket const* Write() override; + + ObjectGuid UnitGUID; + int32 CreatureDisplayInfoID = 0; + TaggedPosition ModelPosition; + }; + class PetTameFailure final : public ServerPacket { public: diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 5a804e77fd..bef91e7c57 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -2148,7 +2148,7 @@ void OpcodeTable::InitializeServerOpcodes() DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_SLOT_UPDATES, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CAST_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CLEAR_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_DISMISS_SOUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_DISMISS_SOUND, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_GOD_MODE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_GUIDS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_LEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);