Skip to content

Commit

Permalink
AI chat: Bots can now properly reply on global channels and will only…
Browse files Browse the repository at this point in the history
… do so if a real player is listening
  • Loading branch information
mostlikely4r committed Nov 29, 2024
1 parent a9d0a8b commit abe7a32
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 10 deletions.
23 changes: 19 additions & 4 deletions playerbot/PlayerbotAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<ChannelAcces*>(chn);

for (auto& player : sRandomPlayerbotMgr.GetPlayers())
if (chna->IsOn(player.second->GetObjectGuid()))
return true;
}
}

return false;
}

/*
enum ActivityType
{
Expand Down
28 changes: 28 additions & 0 deletions playerbot/PlayerbotAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ class PlayerbotChatHandler: protected ChatHandler
}
};

class ChannelAcces
{
public:
struct PlayerInfo
{
ObjectGuid player;
uint8 flags;
};

typedef std::map<ObjectGuid, PlayerInfo> 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;
Expand Down Expand Up @@ -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<uint32,uint32> GetPriorityBracket(ActivePiorityType type);
Expand Down
21 changes: 16 additions & 5 deletions playerbot/strategy/actions/SayAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ void ChatReplyAction::GetAIChatPlaceholders(std::map<std::string, std::string>&
}
}

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();
Expand All @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion playerbot/strategy/actions/SayAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace ai

static void GetAIChatPlaceholders(std::map<std::string, std::string>& placeholders, Unit* sender = nullptr, Unit* receiver = nullptr);
static void GetAIChatPlaceholders(std::map<std::string, std::string>& 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<std::string>& lines, WorldPacket packetTemplate, bool debug = false, uint32 MsPerChar = 0, WorldPacket emoteTemplate = WorldPacket());

static delayedPackets GenerateResponsePackets(const std::string json
Expand Down

0 comments on commit abe7a32

Please sign in to comment.