fix(Core/Pet): Implement sound playback when dismissing warlock's pet. (#23240)

This commit is contained in:
天鹭
2025-10-18 01:22:18 +08:00
committed by GitHub
parent 5457678f48
commit 539aa67ef3
6 changed files with 73 additions and 27 deletions
+3 -3
View File
@@ -76,10 +76,10 @@ enum ActionFeedback
FEEDBACK_CANT_ATT_TARGET = 3 FEEDBACK_CANT_ATT_TARGET = 3
}; };
enum PetTalk enum PetAction : int32
{ {
PET_TALK_SPECIAL_SPELL = 0, PET_ACTION_SPECIAL_SPELL = 0,
PET_TALK_ATTACK = 1 PET_ACTION_ATTACK = 1
}; };
enum PetLoadState enum PetLoadState
+11 -11
View File
@@ -50,6 +50,7 @@
#include "PassiveAI.h" #include "PassiveAI.h"
#include "Pet.h" #include "Pet.h"
#include "PetAI.h" #include "PetAI.h"
#include "PetPackets.h"
#include "Player.h" #include "Player.h"
#include "ReputationMgr.h" #include "ReputationMgr.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
@@ -16672,7 +16673,7 @@ Player* Unit::GetSpellModOwner() const
} }
///----------Pet responses methods----------------- ///----------Pet responses methods-----------------
void Unit::SendPetActionFeedback(uint8 msg) void Unit::SendPetActionFeedback(uint8 msg) const
{ {
Unit* owner = GetOwner(); Unit* owner = GetOwner();
if (!owner || !owner->IsPlayer()) if (!owner || !owner->IsPlayer())
@@ -16683,19 +16684,18 @@ void Unit::SendPetActionFeedback(uint8 msg)
owner->ToPlayer()->GetSession()->SendPacket(&data); owner->ToPlayer()->GetSession()->SendPacket(&data);
} }
void Unit::SendPetTalk(uint32 pettalk) void Unit::SendPetActionSound(PetAction action) const
{ {
Unit* owner = GetOwner(); SendMessageToSet(WorldPackets::Pet::PetActionSound(GetGUID(), static_cast<int32>(action)).Write(), false);
if (!owner || !owner->IsPlayer())
return;
WorldPacket data(SMSG_PET_ACTION_SOUND, 8 + 4);
data << GetGUID();
data << uint32(pettalk);
owner->ToPlayer()->GetSession()->SendPacket(&data);
} }
void Unit::SendPetAIReaction(ObjectGuid guid) void Unit::SendPetDismissSound() const
{
if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId()))
SendMessageToSet(WorldPackets::Pet::PetDismissSound(static_cast<int32>(displayInfo->ModelId), GetPosition()).Write(), false);
}
void Unit::SendPetAIReaction(ObjectGuid guid) const
{ {
Unit* owner = GetOwner(); Unit* owner = GetOwner();
if (!owner || !owner->IsPlayer()) if (!owner || !owner->IsPlayer())
+5 -3
View File
@@ -26,6 +26,7 @@
#include "ItemTemplate.h" #include "ItemTemplate.h"
#include "MotionMaster.h" #include "MotionMaster.h"
#include "Object.h" #include "Object.h"
#include "PetDefines.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "SpellAuraDefines.h" #include "SpellAuraDefines.h"
#include "SpellDefines.h" #include "SpellDefines.h"
@@ -1962,9 +1963,10 @@ public:
void SendPlaySpellVisual(uint32 id); void SendPlaySpellVisual(uint32 id);
void SendPlaySpellImpact(ObjectGuid guid, uint32 id); void SendPlaySpellImpact(ObjectGuid guid, uint32 id);
void SendPetActionFeedback (uint8 msg); void SendPetActionFeedback(uint8 msg) const;
void SendPetTalk (uint32 pettalk); void SendPetActionSound(PetAction action) const;
void SendPetAIReaction(ObjectGuid guid); void SendPetDismissSound() const;
void SendPetAIReaction(ObjectGuid guid) const;
void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo); void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo);
+13 -10
View File
@@ -262,8 +262,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
pet->ToCreature()->AI()->AttackStart(TargetUnit); pet->ToCreature()->AI()->AttackStart(TargetUnit);
//10% chance to play special pet attack talk, else growl //10% chance to play special pet attack talk, else growl
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10))
pet->SendPetTalk((uint32)PET_TALK_ATTACK); pet->SendPetActionSound(PET_ACTION_ATTACK);
else else
{ {
// 90% chance for pet and 100% chance for charmed creature // 90% chance for pet and 100% chance for charmed creature
@@ -297,9 +297,12 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
if (pet->ToPet()->getPetType() == HUNTER_PET) if (pet->ToPet()->getPetType() == HUNTER_PET)
GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED); GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED);
else else
{
pet->SendPetDismissSound();
//dismissing a summoned pet is like killing them (this prevents returning a soulshard...) //dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
pet->setDeathState(DeathState::Corpse); pet->setDeathState(DeathState::Corpse);
} }
}
else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN)) else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN))
{ {
pet->ToTempSummon()->UnSummon(); pet->ToTempSummon()->UnSummon();
@@ -413,8 +416,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
//10% chance to play special pet attack talk, else growl //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 //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)) if (pet->IsPet() && (pet->ToPet()->getPetType() == SUMMON_PET) && (pet != unit_target) && roll_chance_i(10))
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
else else
{ {
pet->SendPetAIReaction(guid1); pet->SendPetAIReaction(guid1);
@@ -509,8 +512,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
pet->ToCreature()->AI()->AttackStart(TargetUnit); pet->ToCreature()->AI()->AttackStart(TargetUnit);
if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10))
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
else else
pet->SendPetAIReaction(guid1); 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); 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) if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10))
pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
else else
{ {
pet->SendPetAIReaction(guid1); pet->SendPetAIReaction(guid1);
@@ -1059,8 +1062,8 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{ {
// 10% chance to play special pet attack talk, else growl // 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 // 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)) if (pet->getPetType() == SUMMON_PET && roll_chance_i(10))
pet->SendPetTalk(PET_TALK_SPECIAL_SPELL); pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL);
else else
pet->SendPetAIReaction(guid); pet->SendPetAIReaction(guid);
} }
@@ -50,3 +50,19 @@ WorldPacket const* WorldPackets::Pet::PetUnlearnedSpell::Write()
_worldPacket << uint32(SpellID); _worldPacket << uint32(SpellID);
return &_worldPacket; 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;
}
@@ -20,6 +20,7 @@
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "Packet.h" #include "Packet.h"
#include "G3D/Vector3.h"
namespace WorldPackets namespace WorldPackets
{ {
@@ -94,6 +95,30 @@ namespace WorldPackets
void Read() override { } 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;
};
} }
} }