diff --git a/src/server/game/Entities/Pet/PetDefines.h b/src/server/game/Entities/Pet/PetDefines.h index ea7380ed2..5e4fcd48c 100644 --- a/src/server/game/Entities/Pet/PetDefines.h +++ b/src/server/game/Entities/Pet/PetDefines.h @@ -76,10 +76,10 @@ enum ActionFeedback FEEDBACK_CANT_ATT_TARGET = 3 }; -enum PetTalk +enum PetAction : int32 { - PET_TALK_SPECIAL_SPELL = 0, - PET_TALK_ATTACK = 1 + PET_ACTION_SPECIAL_SPELL = 0, + PET_ACTION_ATTACK = 1 }; enum PetLoadState diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 54b914833..4ec9c9567 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -50,6 +50,7 @@ #include "PassiveAI.h" #include "Pet.h" #include "PetAI.h" +#include "PetPackets.h" #include "Player.h" #include "ReputationMgr.h" #include "ScriptMgr.h" @@ -16672,7 +16673,7 @@ Player* Unit::GetSpellModOwner() const } ///----------Pet responses methods----------------- -void Unit::SendPetActionFeedback(uint8 msg) +void Unit::SendPetActionFeedback(uint8 msg) const { Unit* owner = GetOwner(); if (!owner || !owner->IsPlayer()) @@ -16683,19 +16684,18 @@ void Unit::SendPetActionFeedback(uint8 msg) owner->ToPlayer()->GetSession()->SendPacket(&data); } -void Unit::SendPetTalk(uint32 pettalk) +void Unit::SendPetActionSound(PetAction action) const { - Unit* owner = GetOwner(); - if (!owner || !owner->IsPlayer()) - return; - - WorldPacket data(SMSG_PET_ACTION_SOUND, 8 + 4); - data << GetGUID(); - data << uint32(pettalk); - owner->ToPlayer()->GetSession()->SendPacket(&data); + SendMessageToSet(WorldPackets::Pet::PetActionSound(GetGUID(), static_cast(action)).Write(), false); } -void Unit::SendPetAIReaction(ObjectGuid guid) +void Unit::SendPetDismissSound() const +{ + if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId())) + SendMessageToSet(WorldPackets::Pet::PetDismissSound(static_cast(displayInfo->ModelId), GetPosition()).Write(), false); +} + +void Unit::SendPetAIReaction(ObjectGuid guid) const { Unit* owner = GetOwner(); if (!owner || !owner->IsPlayer()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index f2fe6bb35..7b98132fe 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -26,6 +26,7 @@ #include "ItemTemplate.h" #include "MotionMaster.h" #include "Object.h" +#include "PetDefines.h" #include "SharedDefines.h" #include "SpellAuraDefines.h" #include "SpellDefines.h" @@ -1962,9 +1963,10 @@ public: void SendPlaySpellVisual(uint32 id); void SendPlaySpellImpact(ObjectGuid guid, uint32 id); - void SendPetActionFeedback (uint8 msg); - void SendPetTalk (uint32 pettalk); - void SendPetAIReaction(ObjectGuid guid); + void SendPetActionFeedback(uint8 msg) const; + void SendPetActionSound(PetAction action) const; + void SendPetDismissSound() const; + void SendPetAIReaction(ObjectGuid guid) const; void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo); diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 38b66926e..5234684c7 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -262,8 +262,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->ToCreature()->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_i(10)) + pet->SendPetActionSound(PET_ACTION_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature @@ -297,8 +297,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe if (pet->ToPet()->getPetType() == HUNTER_PET) GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED); else + { + pet->SendPetDismissSound(); //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) pet->setDeathState(DeathState::Corpse); + } } else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN)) { @@ -413,8 +416,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_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); @@ -509,8 +512,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->ToCreature()->AI()->AttackStart(TargetUnit); - if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else pet->SendPetAIReaction(guid1); } @@ -558,8 +561,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->GetMotionMaster()->MoveFollow(unit_target, PET_FOLLOW_DIST, rand_norm() * 2 * M_PI); - 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_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); @@ -1059,8 +1062,8 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { // 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->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk(PET_TALK_SPECIAL_SPELL); + if (pet->getPetType() == SUMMON_PET && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } diff --git a/src/server/game/Server/Packets/PetPackets.cpp b/src/server/game/Server/Packets/PetPackets.cpp index 8028bce25..860c4d4b7 100644 --- a/src/server/game/Server/Packets/PetPackets.cpp +++ b/src/server/game/Server/Packets/PetPackets.cpp @@ -50,3 +50,19 @@ WorldPacket const* WorldPackets::Pet::PetUnlearnedSpell::Write() _worldPacket << uint32(SpellID); return &_worldPacket; } + +WorldPacket const* WorldPackets::Pet::PetActionSound::Write() +{ + _worldPacket << UnitGUID; + _worldPacket << int32(Action); + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Pet::PetDismissSound::Write() +{ + _worldPacket << int32(ModelId); + _worldPacket << float(ModelPosition.x); + _worldPacket << float(ModelPosition.y); + _worldPacket << float(ModelPosition.z); + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/PetPackets.h b/src/server/game/Server/Packets/PetPackets.h index cbb96db70..f11f88e5b 100644 --- a/src/server/game/Server/Packets/PetPackets.h +++ b/src/server/game/Server/Packets/PetPackets.h @@ -20,6 +20,7 @@ #include "ObjectGuid.h" #include "Packet.h" +#include "G3D/Vector3.h" namespace WorldPackets { @@ -94,6 +95,30 @@ namespace WorldPackets void Read() override { } }; + + class PetActionSound final : public ServerPacket + { + public: + PetActionSound(ObjectGuid unitGUID, int32 action) + : ServerPacket(SMSG_PET_ACTION_SOUND, 8 + 4), UnitGUID(unitGUID), Action(action) { } + + WorldPacket const* Write() override; + + ObjectGuid UnitGUID; + int32 Action = 0; + }; + + class PetDismissSound final : public ServerPacket + { + public: + PetDismissSound(int32 modelId, G3D::Vector3 modelPosition) + : ServerPacket(SMSG_PET_DISMISS_SOUND, 4 + 12), ModelId(modelId), ModelPosition(modelPosition) { } + + WorldPacket const* Write() override; + + int32 ModelId = 0; + G3D::Vector3 ModelPosition; + }; } }