diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 793cb8ed26..3e2cb36ddb 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2123,7 +2123,7 @@ void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, b void WorldObject::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { - Acore::MessageDistDeliverer notifier(this, data, 0.0f, false, skipped_rcvr); + Acore::MessageDistDeliverer notifier(this, data, 0.0f, Acore::TeamFilter::All, skipped_rcvr); notifier.Visit(GetObjectVisibilityContainer().GetVisiblePlayersMap()); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 756ed7826d..465dada401 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5694,7 +5694,7 @@ void Player::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcv if (skipped_rcvr != this) SendDirectMessage(data); - Acore::MessageDistDeliverer notifier(this, data, 0.0f, false, skipped_rcvr); + Acore::MessageDistDeliverer notifier(this, data, 0.0f, Acore::TeamFilter::All, skipped_rcvr); notifier.Visit(GetObjectVisibilityContainer().GetVisiblePlayersMap()); } @@ -9409,7 +9409,7 @@ void Player::Say(std::string_view text, Language language, WorldObject const* /* SendDirectMessage(&data); // Special handling for messages, do not use visibility map for stealthed units - Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), false, nullptr, true); + Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), Acore::TeamFilter::All, nullptr, true); Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY)); } @@ -9437,7 +9437,7 @@ void Player::Yell(std::string_view text, Language language, WorldObject const* / SendDirectMessage(&data); // Special handling for messages, do not use visibility map for stealthed units - Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), false, nullptr, true); + Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), Acore::TeamFilter::All, nullptr, true); Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL)); } @@ -9465,8 +9465,27 @@ void Player::TextEmote(std::string_view text, WorldObject const* /*= nullptr*/, SendDirectMessage(&data); // Special handling for messages, do not use visibility map for stealthed units - Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT), nullptr, true); - Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + if (GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT)) + { + Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), Acore::TeamFilter::All, nullptr, true); + Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + } + else + { + // Same faction + { + Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), Acore::TeamFilter::OwnTeam, nullptr, true); + Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + } + // Opposite faction + { + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, ""); + + Acore::MessageDistDeliverer notifier(this, &data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), Acore::TeamFilter::OtherTeam, nullptr, true); + Cell::VisitObjects(this, notifier, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + } + } } void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/) diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 838ed4048e..8484eb3b57 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -96,33 +96,63 @@ namespace Acore void Visit(CreatureMapType&); }; + enum class TeamFilter + { + All, + OwnTeam, + OtherTeam, + }; + struct MessageDistDeliverer { WorldObject const* i_source; WorldPacket const* i_message; uint32 i_phaseMask; float i_distSq; + TeamFilter teamFilter; TeamId teamId; Player const* skipped_receiver; bool required3dDist; - MessageDistDeliverer(WorldObject const* src, WorldPacket const* msg, float dist, bool own_team_only = false, Player const* skipped = nullptr, bool req3dDist = false) - : i_source(src), i_message(msg), i_phaseMask(src->GetPhaseMask()), i_distSq(dist * dist) - , teamId((own_team_only && src->IsPlayer()) ? src->ToPlayer()->GetTeamId() : TEAM_NEUTRAL) - , skipped_receiver(skipped), required3dDist(req3dDist) - { - } + + MessageDistDeliverer(WorldObject const* src, WorldPacket const* msg, float dist, TeamFilter teamFilter = TeamFilter::All, Player const* skipped = nullptr, bool req3dDist = false) : + i_source(src), + i_message(msg), + i_phaseMask(src->GetPhaseMask()), + i_distSq(dist * dist), + teamFilter(src->IsPlayer() ? teamFilter : TeamFilter::All), + teamId(src->IsPlayer() ? src->ToPlayer()->GetTeamId() : TEAM_NEUTRAL), + skipped_receiver(skipped), + required3dDist(req3dDist) + { } + void Visit(VisiblePlayersMap const& m); void Visit(PlayerMapType& m); void Visit(CreatureMapType& m); void Visit(DynamicObjectMapType& m); - template void Visit(GridRefMgr&) {} - void SendPacket(Player* player) + template void Visit(GridRefMgr&) { } + + void SendPacket(Player* player) const { // never send packet to self - if (player == i_source || (teamId != TEAM_NEUTRAL && player->GetTeamId() != teamId) || skipped_receiver == player) + if (player == i_source || skipped_receiver == player) return; + switch (teamFilter) + { + default: + case TeamFilter::All: + break; + case TeamFilter::OwnTeam: + if (player->GetTeamId() != teamId) + return; + break; + case TeamFilter::OtherTeam: + if (player->GetTeamId() == teamId) + return; + break; + } + if (!player->HaveAtClient(i_source)) return;