From abe7a321059118410f39469dd9e158df5192ae94 Mon Sep 17 00:00:00 2001 From: mostlikely4r Date: Fri, 29 Nov 2024 20:04:50 +0100 Subject: [PATCH] AI chat: Bots can now properly reply on global channels and will only do so if a real player is listening --- playerbot/PlayerbotAI.cpp | 23 +++++++++++++++---- playerbot/PlayerbotAI.h | 28 ++++++++++++++++++++++++ playerbot/strategy/actions/SayAction.cpp | 21 +++++++++++++----- playerbot/strategy/actions/SayAction.h | 2 +- 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/playerbot/PlayerbotAI.cpp b/playerbot/PlayerbotAI.cpp index e24fa3a0b..6d17ecac8 100644 --- a/playerbot/PlayerbotAI.cpp +++ b/playerbot/PlayerbotAI.cpp @@ -1587,7 +1587,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(const WorldPacket& packet) bool isAiChat = HasStrategy("ai chat", BotState::BOT_STATE_NON_COMBAT); - if (isAiChat && lang == LANG_ADDON) + if (isAiChat && (lang == LANG_ADDON || message.find("d:") == 0)) return; if (guid1 != bot->GetObjectGuid()) // do not reply to self @@ -1678,9 +1678,6 @@ void PlayerbotAI::HandleBotOutgoingPacket(const WorldPacket& packet) } else if (isAiChat) { - if (message.find("d:") != std::string::npos) - return; - ChatChannelSource chatChannelSource = bot->GetPlayerbotAI()->GetChatChannelSource(bot, msgtype, chanName); std::string llmChannel; @@ -5397,6 +5394,24 @@ bool PlayerbotAI::HasManyPlayersNearby(uint32 trigerrValue, float range) return false; } +bool PlayerbotAI::ChannelHasRealPlayer(std::string channelName) +{ + if (ChannelMgr* cMgr = channelMgr(bot->GetTeam())) + { + + if (Channel* chn = cMgr->GetChannel(channelName, bot)) + { + ChannelAcces* chna = reinterpret_cast(chn); + + for (auto& player : sRandomPlayerbotMgr.GetPlayers()) + if (chna->IsOn(player.second->GetObjectGuid())) + return true; + } + } + + return false; +} + /* enum ActivityType { diff --git a/playerbot/PlayerbotAI.h b/playerbot/PlayerbotAI.h index 236982580..8baff0c1d 100644 --- a/playerbot/PlayerbotAI.h +++ b/playerbot/PlayerbotAI.h @@ -34,6 +34,32 @@ class PlayerbotChatHandler: protected ChatHandler } }; +class ChannelAcces +{ +public: + struct PlayerInfo + { + ObjectGuid player; + uint8 flags; + }; + + typedef std::map PlayerList; + + bool IsOn(ObjectGuid who) const { return m_players.find(who) != m_players.end(); } + std::string m_name; + std::string m_password; + ObjectGuid m_ownerGuid; + PlayerList m_players; + GuidSet m_banned; + const ChatChannelsEntry* m_entry = nullptr; + bool m_announcements = false; + bool m_moderation = false; + uint8 m_flags = 0x00; + // Custom features: + bool m_static = false; + bool m_realmzone = false; +}; + namespace ai { class WorldPosition; @@ -563,6 +589,8 @@ class PlayerbotAI : public PlayerbotAIBase bool HasPlayerNearby(WorldPosition pos, float range); bool HasPlayerNearby(float range = sPlayerbotAIConfig.reactDistance); bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig.sightDistance); + bool ChannelHasRealPlayer(std::string channelName); + ActivePiorityType GetPriorityType(); std::pair GetPriorityBracket(ActivePiorityType type); diff --git a/playerbot/strategy/actions/SayAction.cpp b/playerbot/strategy/actions/SayAction.cpp index 4fe4d449d..715471280 100644 --- a/playerbot/strategy/actions/SayAction.cpp +++ b/playerbot/strategy/actions/SayAction.cpp @@ -276,7 +276,7 @@ void ChatReplyAction::GetAIChatPlaceholders(std::map& } } -WorldPacket ChatReplyAction::GetPacketTemplate(Opcodes op, uint32 type, Unit* sender, Unit* target) +WorldPacket ChatReplyAction::GetPacketTemplate(Opcodes op, uint32 type, Unit* sender, Unit* target, std::string channelName) { Player* senderPlayer = (sender->IsPlayer()) ? (Player*)sender : nullptr; ObjectGuid senderGuid = sender->GetObjectGuid(); @@ -298,8 +298,15 @@ WorldPacket ChatReplyAction::GetPacketTemplate(Opcodes op, uint32 type, Unit* se else packetTemplate << LANG_UNIVERSAL; - if (op == CMSG_MESSAGECHAT && type == CHAT_MSG_WHISPER) - packetTemplate << target->GetName(); + if (op == CMSG_MESSAGECHAT) + { + if (type == CHAT_MSG_WHISPER) + packetTemplate << target->GetName(); + + if (!channelName.empty()) + packetTemplate << channelName; + } + if (op != CMSG_MESSAGECHAT) { @@ -467,13 +474,17 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 return; } - if (bot->GetPlayerbotAI() && bot->GetPlayerbotAI()->HasStrategy("ai chat", BotState::BOT_STATE_NON_COMBAT) && chatChannelSource != ChatChannelSource::SRC_UNDEFINED && sPlayerbotAIConfig.llmBlockedReplyChannels.find(chatChannelSource) == sPlayerbotAIConfig.llmBlockedReplyChannels.end()) + if (bot->GetPlayerbotAI() && bot->GetPlayerbotAI()->HasStrategy("ai chat", BotState::BOT_STATE_NON_COMBAT) && chatChannelSource != ChatChannelSource::SRC_UNDEFINED && sPlayerbotAIConfig.llmBlockedReplyChannels.find(chatChannelSource) == sPlayerbotAIConfig.llmBlockedReplyChannels.end() + ) { Player* player = sObjectAccessor.FindPlayer(ObjectGuid(HIGHGUID_PLAYER, guid1)); PlayerbotAI* ai = bot->GetPlayerbotAI(); AiObjectContext* context = ai->GetAiObjectContext(); + if (!chanName.empty() && !ai->ChannelHasRealPlayer(chanName)) + player = nullptr; + std::string llmChannel; if (!sPlayerbotAIConfig.llmGlobalContext) @@ -597,7 +608,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 WorldSession* session = bot->GetSession(); - WorldPacket chatTemplate = GetPacketTemplate(CMSG_MESSAGECHAT, type, bot, player); + WorldPacket chatTemplate = GetPacketTemplate(CMSG_MESSAGECHAT, type, bot, player, channelName); WorldPacket emoteTemplate = (type == CHAT_MSG_SAY || type == CHAT_MSG_WHISPER) ? GetPacketTemplate(CMSG_MESSAGECHAT, CHAT_MSG_EMOTE, bot, player) : WorldPacket(); WorldPacket systemTemplate = GetPacketTemplate(CMSG_MESSAGECHAT, CHAT_MSG_WHISPER, bot, player); diff --git a/playerbot/strategy/actions/SayAction.h b/playerbot/strategy/actions/SayAction.h index 1b8738bbd..f00843a3b 100644 --- a/playerbot/strategy/actions/SayAction.h +++ b/playerbot/strategy/actions/SayAction.h @@ -29,7 +29,7 @@ namespace ai static void GetAIChatPlaceholders(std::map& placeholders, Unit* sender = nullptr, Unit* receiver = nullptr); static void GetAIChatPlaceholders(std::map& placeholders, Unit* unit, const std::string preFix = "bot", Player* observer = nullptr); - static WorldPacket GetPacketTemplate(Opcodes op, uint32 type, Unit* sender, Unit* target = nullptr); + static WorldPacket GetPacketTemplate(Opcodes op, uint32 type, Unit* sender, Unit* target = nullptr, std::string channelName = ""); static delayedPackets LinesToPackets(const std::vector& lines, WorldPacket packetTemplate, bool debug = false, uint32 MsPerChar = 0, WorldPacket emoteTemplate = WorldPacket()); static delayedPackets GenerateResponsePackets(const std::string json