diff --git a/src/ChatHelper.cpp b/src/ChatHelper.cpp index d2fcb213..144fbe0b 100644 --- a/src/ChatHelper.cpp +++ b/src/ChatHelper.cpp @@ -219,6 +219,26 @@ std::string const ChatHelper::formatMoney(uint32 copper) return out.str(); } +std::string ChatHelper::parseValue(const std::string& type, const std::string& text) +{ + std::string retString; + + std::string pattern = "Hvalue:" + type + ":"; + + int pos = text.find(pattern, 0); + if (pos == -1) + return retString; + + pos += pattern.size(); + + int endPos = text.find('|', pos); + if (endPos == -1) + return retString; + + retString = text.substr(pos, endPos - pos); + return retString; +} + uint32 ChatHelper::parseMoney(std::string const text) { // if user specified money in ##g##s##c format @@ -604,4 +624,4 @@ std::set ChatHelper::ExtractAllItemIds(const std::string& text) } return ids; -} \ No newline at end of file +} diff --git a/src/ChatHelper.h b/src/ChatHelper.h index 8806798a..aedcc703 100644 --- a/src/ChatHelper.h +++ b/src/ChatHelper.h @@ -33,6 +33,8 @@ class ChatHelper : public PlayerbotAIAware static uint32 parseMoney(std::string const text); static ItemIds parseItems(std::string const text); uint32 parseSpell(std::string const text); + static std::string parseValue(const std::string& type, const std::string& text); + static std::string const FormatQuest(Quest const* quest); static std::string const FormatItem(ItemTemplate const* proto, uint32 count = 0, uint32 total = 0); static std::string const FormatQItem(uint32 itemId); diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 686eea77..3c2d7e20 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -340,6 +340,29 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_TOTAL, "PlayerbotAI::UpdateAIInternal " + mapString); ExternalEventHelper helper(aiObjectContext); + // chat replies + std::list delayedResponses; + while (!chatReplies.empty()) + { + ChatQueuedReply holder = chatReplies.front(); + time_t checkTime = holder.m_time; + if (checkTime && time(0) < checkTime) + { + delayedResponses.push_back(holder); + chatReplies.pop(); + continue; + } + + ChatReplyAction::ChatReplyDo(bot, holder.m_type, holder.m_guid1, holder.m_guid2, holder.m_msg, holder.m_chanName, holder.m_name); + chatReplies.pop(); + } + + for (std::list::iterator i = delayedResponses.begin(); i != delayedResponses.end(); ++i) + { + chatReplies.push(*i); + } + + HandleCommands(); // logout if logout timer is ready or if instant logout is possible if (bot->GetSession()->isLogingOut()) @@ -391,6 +414,207 @@ void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal pmo->finish(); } +void PlayerbotAI::HandleCommands() +{ + ExternalEventHelper helper(aiObjectContext); + std::list delayed; + while (!chatCommands.empty()) + { + ChatCommandHolder holder = chatCommands.front(); + time_t checkTime = holder.GetTime(); + if (checkTime && time(0) < checkTime) + { + delayed.push_back(holder); + chatCommands.pop(); + continue; + } + + std::string command = holder.GetCommand(); + Player* owner = holder.GetOwner(); + if (!helper.ParseChatCommand(command, owner) && holder.GetType() == CHAT_MSG_WHISPER) + { + //ostringstream out; out << "Unknown command " << command; + //TellPlayer(out); + //helper.ParseChatCommand("help"); + } + + chatCommands.pop(); + } + + for (std::list::iterator i = delayed.begin(); i != delayed.end(); ++i) + { + chatCommands.push(*i); + } +} + +std::map chatMap; +void PlayerbotAI::HandleCommand(uint32 type, const std::string& text, Player& fromPlayer, const uint32 lang) +{ + std::string filtered = text; + + if (!IsAllowedCommand(filtered) && !GetSecurity()->CheckLevelFor(PlayerbotSecurityLevel::PLAYERBOT_SECURITY_INVITE, type != CHAT_MSG_WHISPER, &fromPlayer)) + return; + + if (type == CHAT_MSG_ADDON) + return; + + if (filtered.find("BOT\t") == 0) //Mangosbot has BOT prefix so we remove that. + filtered = filtered.substr(4); + else if (lang == LANG_ADDON) //Other addon messages should not command bots. + return; + + if (type == CHAT_MSG_SYSTEM) + return; + + if (filtered.find(sPlayerbotAIConfig->commandSeparator) != std::string::npos) + { + std::vector commands; + split(commands, filtered, sPlayerbotAIConfig->commandSeparator.c_str()); + for (std::vector::iterator i = commands.begin(); i != commands.end(); ++i) + { + HandleCommand(type, *i, fromPlayer); + } + return; + } + + if (!sPlayerbotAIConfig->commandPrefix.empty()) + { + if (filtered.find(sPlayerbotAIConfig->commandPrefix) != 0) + return; + + filtered = filtered.substr(sPlayerbotAIConfig->commandPrefix.size()); + } + + if (chatMap.empty()) + { + chatMap["#w "] = CHAT_MSG_WHISPER; + chatMap["#p "] = CHAT_MSG_PARTY; + chatMap["#r "] = CHAT_MSG_RAID; + chatMap["#a "] = CHAT_MSG_ADDON; + chatMap["#g "] = CHAT_MSG_GUILD; + } + currentChat = std::pair(CHAT_MSG_WHISPER, 0); + for (std::map::iterator i = chatMap.begin(); i != chatMap.end(); ++i) + { + if (filtered.find(i->first) == 0) + { + filtered = filtered.substr(3); + currentChat = std::pair(i->second, time(0) + 2); + break; + } + } + + filtered = chatFilter.Filter(trim((std::string&)filtered)); + if (filtered.empty()) + return; + + if (filtered.substr(0, 6) == "debug ") + { + std::string response = HandleRemoteCommand(filtered.substr(6)); + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_ADDON, response.c_str(), LANG_ADDON, + CHAT_TAG_NONE, bot->GetGUID(), bot->GetName()); + sServerFacade->SendPacket(&fromPlayer, &data); + return; + } + + if (!IsAllowedCommand(filtered) && !GetSecurity()->CheckLevelFor(PlayerbotSecurityLevel::PLAYERBOT_SECURITY_ALLOW_ALL, type != CHAT_MSG_WHISPER, &fromPlayer)) + return; + + if (type == CHAT_MSG_RAID_WARNING && filtered.find(bot->GetName()) != std::string::npos && filtered.find("award") == std::string::npos) + { + ChatCommandHolder cmd("warning", &fromPlayer, type); + chatCommands.push(cmd); + return; + } + + if ((filtered.size() > 2 && filtered.substr(0, 2) == "d ") || (filtered.size() > 3 && filtered.substr(0, 3) == "do ")) + { + Event event("do", "", &fromPlayer); + std::string action = filtered.substr(filtered.find(" ") + 1); + DoSpecificAction(action, event); + } + + if (ChatHelper::parseValue("command", filtered).substr(0, 3) == "do ") + { + Event event("do", "", &fromPlayer); + std::string action = ChatHelper::parseValue("command", filtered); + action = action.substr(3); + DoSpecificAction(action, event); + } + else if (type != CHAT_MSG_WHISPER && filtered.size() > 6 && filtered.substr(0, 6) == "queue ") + { + std::string remaining = filtered.substr(filtered.find(" ") + 1); + int index = 1; + Group* group = bot->GetGroup(); + if (group) + { + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + if (ref->GetSource() == master) + continue; + + if (ref->GetSource() == bot) + break; + + index++; + } + } + ChatCommandHolder cmd(remaining, &fromPlayer, type, time(0) + index); + chatCommands.push(cmd); + } + else if (filtered == "reset") + { + Reset(true); + } + + // TODO: missing implementation to port + /*else if (filtered == "logout") + { + if (!(bot->IsStunnedByLogout() || bot->GetSession()->isLogingOut())) + { + if (type == CHAT_MSG_WHISPER) + TellPlayer(&fromPlayer, BOT_TEXT("logout_start")); + + if (master && master->GetPlayerbotMgr()) + SetShouldLogOut(true); + } + } + else if (filtered == "logout cancel") + { + if (bot->IsStunnedByLogout() || bot->GetSession()->isLogingOut()) + { + if (type == CHAT_MSG_WHISPER) + TellPlayer(&fromPlayer, BOT_TEXT("logout_cancel")); + + WorldPacket p; + bot->GetSession()->HandleLogoutCancelOpcode(p); + SetShouldLogOut(false); + } + } + else if ((filtered.size() > 5) && (filtered.substr(0, 5) == "wait ") && (filtered.find("wait for attack") == std::string::npos)) + { + std::string remaining = filtered.substr(filtered.find(" ") + 1); + uint32 delay = atof(remaining.c_str()) * IN_MILLISECONDS; + if (delay > 20000) + { + bot->TellMaster(&fromPlayer, "Max wait time is 20 seconds!"); + return; + } + + IncreaseAIInternalUpdateDelay(delay); + isWaiting = true; + TellPlayer(&fromPlayer, "Waiting for " + remaining + " seconds!"); + return; + }*/ + + else + { + ChatCommandHolder cmd(filtered, &fromPlayer, type); + chatCommands.push(cmd); + } +} + void PlayerbotAI::HandleTeleportAck() { if (IsRealPlayer()) @@ -484,8 +708,6 @@ void PlayerbotAI::Reset(bool full) } } -std::map chatMap; - bool PlayerbotAI::IsAllowedCommand(std::string const text) { if (unsecuredCommands.empty()) @@ -718,6 +940,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) p >> guid1 >> unused; if (guid1.IsEmpty() || p.size() > p.DEFAULT_SIZE) return; + switch (msgtype) { case CHAT_MSG_CHANNEL: @@ -730,44 +953,67 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) case CHAT_MSG_GUILD: p >> guid2; p >> textLen >> message >> chatTag; - - if (guid1 != bot->GetGUID()) // do not reply to self - { - // try to always reply to real player - time_t lastChat = GetAiObjectContext()->GetValue("last said", "chat")->Get(); - bool isPaused = time(0) < lastChat; - bool shouldReply = false; - bool isRandomBot = false; - sCharacterCache->GetCharacterNameByGuid(guid1, name); - uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guid1); - isRandomBot = sPlayerbotAIConfig->IsInRandomAccountList(accountId); - bool isMentioned = message.find(bot->GetName()) != std::string::npos; - - // random bot speaks, chat CD - if (isRandomBot && isPaused) - return; - // BG: react only if mentioned or if not channel and real player spoke - if (bot->InBattleground() && bot->GetBattleground() && !(isMentioned || (msgtype != CHAT_MSG_CHANNEL && !isRandomBot))) - return; - - // Reduce chat spam - if (HasRealPlayerMaster()) - return; - - if (isRandomBot && urand(0, 20)) - return; - - if (!message.empty() && ((isRandomBot && !isPaused && (!urand(0, 20) || (!urand(0, 10) && message.find(bot->GetName()) != std::string::npos))) || (!isRandomBot && (isMentioned || !urand(0, 4))))) - { - QueueChatResponse(msgtype, guid1, ObjectGuid(), message, chanName, name); - GetAiObjectContext()->GetValue("last said", "chat")->Set(time(0) + urand(5, 25)); - return; - } - } break; default: break; } + + // do not reply to self but always try to reply to real player + if (guid1 != bot->GetGUID()) + { + time_t lastChat = GetAiObjectContext()->GetValue("last said", "chat")->Get(); + bool isPaused = time(0) < lastChat; + bool shouldReply = false; + bool isFromFreeBot = false; + uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(guid1); + isFromFreeBot = sPlayerbotAIConfig->IsInRandomAccountList(accountId); + bool isMentioned = message.find(bot->GetName()) != std::string::npos; + + ChatChannelSource chatChannelSource = GetChatChannelSource(bot, msgtype, chanName); + + // random bot speaks, chat CD + if (isFromFreeBot && isPaused) + return; + + // BG: react only if mentioned or if not channel and real player spoke + if (bot->InBattleground() && !(isMentioned || (msgtype != CHAT_MSG_CHANNEL && !isFromFreeBot))) + return; + + if (HasRealPlayerMaster() && guid1 != GetMaster()->GetGUID()) + return; + if (lang == LANG_ADDON) + return; + + // several talk config option later + /* + + TODO: + toxic link + legendary grind / thunderfury etc + + */ + if (isFromFreeBot && urand(0, 20)) + return; + + //if (msgtype == CHAT_MSG_GUILD && (!sPlayerbotAIConfig->guildRepliesRate || urand(1, 100) >= sPlayerbotAIConfig->guildRepliesRate)) + //return; + + if (!isFromFreeBot) + { + if (!isMentioned && urand(0, 4)) + return; + } + else + { + if (urand(0, 20 + 10 * isMentioned)) + return; + } + + QueueChatResponse(msgtype, guid1, ObjectGuid(), message, chanName, name); + GetAiObjectContext()->GetValue("last said", "chat")->Set(time(0) + urand(5, 25)); + + return; + } } return; @@ -1844,17 +2090,12 @@ WorldObject* PlayerbotAI::GetWorldObject(ObjectGuid guid) const AreaTableEntry* PlayerbotAI::GetCurrentArea() { - if (const auto map = bot->GetMap()) - return sAreaTableStore.LookupEntry(bot->GetMap()->GetAreaId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); - return nullptr; + return sAreaTableStore.LookupEntry(bot->GetMap()->GetAreaId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); } const AreaTableEntry* PlayerbotAI::GetCurrentZone() { - if (const auto map = bot->GetMap()) - return GetAreaEntryByAreaID(map->GetZoneId(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); - - return nullptr; + return sAreaTableStore.LookupEntry(bot->GetMap()->GetZoneId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); } std::string PlayerbotAI::GetLocalizedAreaName(const AreaTableEntry* entry) @@ -1909,6 +2150,7 @@ bool PlayerbotAI::SayToGuild(const std::string& msg) return false; } + bool PlayerbotAI::SayToWorld(const std::string& msg) { if (msg.empty()) @@ -1918,9 +2160,7 @@ bool PlayerbotAI::SayToWorld(const std::string& msg) ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()); if (!cMgr) - { return false; - } //no zone if (Channel* worldChannel = cMgr->GetChannel("World", bot)) @@ -1931,24 +2171,35 @@ bool PlayerbotAI::SayToWorld(const std::string& msg) return false; } + bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chanId) { ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()); if (!cMgr || msg.empty()) return false; - AreaTableEntry const* current_zone = sAreaTableStore.LookupEntry(bot->GetMap()->GetZoneId(bot->GetPhaseMask(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ())); - if (!current_zone) + AreaTableEntry const* current_zone = GetCurrentZone(); + AreaTableEntry const* current_area = GetCurrentArea(); + if (!current_zone || !current_area) return false; + const auto current_str_zone = GetLocalizedAreaName(current_zone); + const auto current_str_area = GetLocalizedAreaName(current_area); + for (auto const& [key, channel] : cMgr->GetChannels()) { //check for current zone if (channel && channel->GetChannelId() == chanId) { - const auto does_contains = channel->GetName().find(GetLocalizedAreaName(current_zone)) != std::string::npos; - if ((chanId != ChatChannelId::LOOKING_FOR_GROUP && chanId != ChatChannelId::WORLD_DEFENSE) && !does_contains) - return false; + const auto does_contains = channel->GetName().find(current_str_zone) != std::string::npos || channel->GetName().find(current_str_area) != std::string::npos; + if (chanId != ChatChannelId::LOOKING_FOR_GROUP && chanId != ChatChannelId::WORLD_DEFENSE && !does_contains) + { + continue; + } + else if (chanId == ChatChannelId::LOOKING_FOR_GROUP || chanId == ChatChannelId::WORLD_DEFENSE) + { + // check if capitals then return false if not + } channel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); return true; @@ -1957,6 +2208,7 @@ bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chan return false; } + bool PlayerbotAI::SayToParty(const std::string& msg) { if (!bot->GetGroup()) @@ -1972,6 +2224,7 @@ bool PlayerbotAI::SayToParty(const std::string& msg) return true; } + bool PlayerbotAI::SayToRaid(const std::string& msg) { if (!bot->GetGroup() || bot->GetGroup()->isRaidGroup()) @@ -1987,6 +2240,7 @@ bool PlayerbotAI::SayToRaid(const std::string& msg) return true; } + bool PlayerbotAI::Yell(const std::string& msg) { if (bot->GetTeamId() == TeamId::TEAM_ALLIANCE) @@ -2000,6 +2254,7 @@ bool PlayerbotAI::Yell(const std::string& msg) return true; } + bool PlayerbotAI::Say(const std::string& msg) { if (bot->GetTeamId() == TeamId::TEAM_ALLIANCE) @@ -2013,6 +2268,7 @@ bool PlayerbotAI::Say(const std::string& msg) return true; } + bool PlayerbotAI::Whisper(const std::string& msg, const std::string& receiverName) { const auto receiver = ObjectAccessor::FindPlayerByName(receiverName); @@ -4894,39 +5150,43 @@ ChatChannelSource PlayerbotAI::GetChatChannelSource(Player* bot, uint32 type, st { ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()); if (!cMgr) + { return ChatChannelSource::SRC_UNDEFINED; + } const Channel* channel = cMgr->GetChannel(channelName, bot); if (channel) { switch (channel->GetChannelId()) { - case ChatChannelId::GENERAL: - { - return ChatChannelSource::SRC_GENERAL; - } - case ChatChannelId::TRADE: - { - return ChatChannelSource::SRC_TRADE; - } - case ChatChannelId::LOCAL_DEFENSE: - { - return ChatChannelSource::SRC_LOCAL_DEFENSE; - } - case ChatChannelId::WORLD_DEFENSE: - { - return ChatChannelSource::SRC_WORLD_DEFENSE; - } - case ChatChannelId::LOOKING_FOR_GROUP: - { - return ChatChannelSource::SRC_LOOKING_FOR_GROUP; - } - case ChatChannelId::GUILD_RECRUITMENT: - { - return ChatChannelSource::SRC_GUILD_RECRUITMENT; - } - default: - return ChatChannelSource::SRC_UNDEFINED; + case ChatChannelId::GENERAL: + { + return ChatChannelSource::SRC_GENERAL; + } + case ChatChannelId::TRADE: + { + return ChatChannelSource::SRC_TRADE; + } + case ChatChannelId::LOCAL_DEFENSE: + { + return ChatChannelSource::SRC_LOCAL_DEFENSE; + } + case ChatChannelId::WORLD_DEFENSE: + { + return ChatChannelSource::SRC_WORLD_DEFENSE; + } + case ChatChannelId::LOOKING_FOR_GROUP: + { + return ChatChannelSource::SRC_LOOKING_FOR_GROUP; + } + case ChatChannelId::GUILD_RECRUITMENT: + { + return ChatChannelSource::SRC_GUILD_RECRUITMENT; + } + default: + { + return ChatChannelSource::SRC_UNDEFINED; + } } } } @@ -4968,11 +5228,14 @@ ChatChannelSource PlayerbotAI::GetChatChannelSource(Player* bot, uint32 type, st return ChatChannelSource::SRC_TEXT_EMOTE; } default: + { return ChatChannelSource::SRC_UNDEFINED; + } } } return ChatChannelSource::SRC_UNDEFINED; } + std::vector PlayerbotAI::GetAllCurrentQuests() { std::vector result; @@ -5051,4 +5314,4 @@ std::set PlayerbotAI::GetCurrentIncompleteQuestIds() } return result; -} \ No newline at end of file +} diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index ef54b552..00380f26 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -105,7 +105,6 @@ class MinValueCalculator void* param; float minValue; }; - enum ChatChannelSource { SRC_GUILD, @@ -128,6 +127,27 @@ enum ChatChannelSource SRC_UNDEFINED }; +static std::map ChatChannelSourceStr = { + { SRC_GUILD, "SRC_GUILD"}, + { SRC_WORLD, "SRC_WORLD"}, + { SRC_GENERAL, "SRC_GENERAL"}, + { SRC_TRADE, "SRC_TRADE"}, + { SRC_LOOKING_FOR_GROUP, "SRC_LOOKING_FOR_GROUP"}, + { SRC_LOCAL_DEFENSE, "SRC_LOCAL_DEFENSE"}, + { SRC_WORLD_DEFENSE, "SRC_WORLD_DEFENSE"}, + { SRC_GUILD_RECRUITMENT, "SRC_GUILD_RECRUITMENT"}, + + { SRC_SAY, "SRC_SAY"}, + { SRC_WHISPER, "SRC_WHISPER"}, + { SRC_EMOTE, "SRC_EMOTE"}, + { SRC_TEXT_EMOTE, "SRC_TEXT_EMOTE"}, + { SRC_YELL, "SRC_YELL"}, + + { SRC_PARTY, "SRC_PARTY"}, + { SRC_RAID, "SRC_RAID"}, + + { SRC_UNDEFINED, "SRC_UNDEFINED"} +}; enum ChatChannelId { GENERAL = 1, @@ -513,6 +533,10 @@ class PlayerbotAI : public PlayerbotAIBase private: static void _fillGearScoreData(Player* player, Item* item, std::vector* gearScore, uint32& twoHandScore, bool mixed = false); bool IsTellAllowed(PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); + + void HandleCommands(); + void HandleCommand(uint32 type, const std::string& text, Player& fromPlayer, const uint32 lang = LANG_UNIVERSAL); + protected: Player* bot; Player* master; diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 1774b93e..0bf0d7ff 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -526,10 +526,10 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) // join standard channels AreaTableEntry const* current_zone = sAreaTableStore.LookupEntry(bot->GetAreaId()); ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()); - std::string current_zone_name = current_zone ? current_zone->area_name[sWorld->GetDefaultDbcLocale()] : ""; if (current_zone && cMgr) { + const auto current_str_zone = botAI->GetLocalizedAreaName(current_zone); for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); @@ -551,11 +551,9 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) else { char new_channel_name_buf[100]; - snprintf(new_channel_name_buf, 100, channel->pattern[sWorld->GetDefaultDbcLocale()], current_zone_name.c_str()); + snprintf(new_channel_name_buf, 100, channel->pattern[sWorld->GetDefaultDbcLocale()], current_str_zone.c_str()); new_channel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID); } - if (new_channel && new_channel->GetName().length() > 0) - new_channel->JoinChannel(bot, ""); } } } diff --git a/src/strategy/actions/AutoLearnSpellAction.cpp b/src/strategy/actions/AutoLearnSpellAction.cpp index abc4c8bb..25d8db43 100644 --- a/src/strategy/actions/AutoLearnSpellAction.cpp +++ b/src/strategy/actions/AutoLearnSpellAction.cpp @@ -38,18 +38,9 @@ void AutoLearnSpellAction::LearnSpells(std::ostringstream* out) if (sPlayerbotAIConfig->randomBotGuildTalk) { - Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); - if (guild) - { - std::string toSay = ""; - - if (urand(0, 3)) - toSay = "Ding !"; - else - toSay = "Yay level " + std::to_string(bot->GetLevel()) + " !"; - - guild->BroadcastToGuild(bot->GetSession(), false, toSay, LANG_UNIVERSAL); - } + std::map args; + args["%my_level"] = std::to_string(bot->GetLevel()); + botAI->SayToGuild(BOT_TEXT2("broadcast_levelup_generic", args)); } } diff --git a/src/strategy/actions/LootAction.cpp b/src/strategy/actions/LootAction.cpp index 10ae1ccc..587528c8 100644 --- a/src/strategy/actions/LootAction.cpp +++ b/src/strategy/actions/LootAction.cpp @@ -417,21 +417,11 @@ bool StoreLootAction::Execute(Event event) if (proto->Quality >= ITEM_QUALITY_RARE && !urand(0, 1) && botAI->HasStrategy("emote", BOT_STATE_NON_COMBAT)) botAI->PlayEmote(TEXT_EMOTE_CHEER); - if (sPlayerbotAIConfig->randomBotGuildTalk && bot->GetGuildId() && urand(0, 10) && proto->Quality >= ITEM_QUALITY_RARE) + if (sPlayerbotAIConfig->randomBotGuildTalk && urand(0, 10) && proto->Quality >= ITEM_QUALITY_RARE) { - Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); - - if (guild) - { - std::string toSay = ""; - - if (urand(0, 3)) - toSay = "Yay I looted " + chat->FormatItem(proto) + " !"; - else - toSay = "Guess who got a " + chat->FormatItem(proto) + " ? Me !"; - - guild->BroadcastToGuild(bot->GetSession(), false, toSay, LANG_UNIVERSAL); - } + std::map args; + args["%item"] = chat->FormatItem(proto); + botAI->SayToGuild(BOT_TEXT2("loot_command", args)); } // std::ostringstream out; diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 935e1b34..58789c0f 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -153,11 +153,10 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 return; } - /*ChatChannelSource chatChannelSource = GET_PLAYERBOT_AI(bot)->GetChatChannelSource(bot, type, chanName); - + ChatChannelSource chatChannelSource = GET_PLAYERBOT_AI(bot)->GetChatChannelSource(bot, type, chanName); if ( (msg.starts_with("LFG") || msg.starts_with("LFM")) && HandleLFGQuestsReply(bot, chatChannelSource, msg, name)) { - + return; } if (msg.starts_with("WTB") && HandleWTBItemsReply(bot, chatChannelSource, msg, name)) @@ -180,8 +179,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 return; } - - SendGeneralResponse(bot, chatChannelSource, GenerateReplyMessage(bot, msg, guid1, name), name);*/ + SendGeneralResponse(bot, chatChannelSource, GenerateReplyMessage(bot, msg, guid1, name), name); } bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chatChannelSource, std::string msg, std::string name) @@ -196,12 +194,12 @@ bool ChatReplyAction::HandleThunderfuryReply(Player* bot, ChatChannelSource chat { case ChatChannelSource::SRC_WORLD: { - //GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); + GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); break; } case ChatChannelSource::SRC_GENERAL: { - //GET_PLAYERBOT_AI(bot)->SayToGeneral(responseMessage); + GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL); break; } } @@ -265,13 +263,13 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh //may reply to the same channel or whisper if (urand(0, 1)) { - //std::string responseMessage = BOT_TEXT2("response_lfg_quests_channel", placeholders); - //GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); + std::string responseMessage = BOT_TEXT2("response_lfg_quests_channel", placeholders); + GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); } else { - //std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); - //GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); + std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); + GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; } @@ -280,13 +278,13 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh //may reply to the same channel or whisper if (urand(0, 1)) { - //std::string responseMessage = BOT_TEXT2("response_lfg_quests_channel", placeholders); - //GET_PLAYERBOT_AI(bot)->SayToGeneral(responseMessage); + std::string responseMessage = BOT_TEXT2("response_lfg_quests_channel", placeholders); + GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL); } else { - //std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); - //GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); + std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); + GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); } break; } @@ -294,8 +292,8 @@ bool ChatReplyAction::HandleLFGQuestsReply(Player* bot, ChatChannelSource chatCh { //do not reply to the chat //may whisper - //std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); - //GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); + std::string responseMessage = BOT_TEXT2("response_lfg_quests_whisper", placeholders); + GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); break; } } @@ -310,70 +308,70 @@ bool ChatReplyAction::SendGeneralResponse(Player* bot, ChatChannelSource chatCha // send responds switch (chatChannelSource) { - case ChatChannelSource::SRC_WORLD: - { - //may reply to the same channel or whisper - //GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); - break; - } - case ChatChannelSource::SRC_GENERAL: - { - //may reply to the same channel or whisper - //GET_PLAYERBOT_AI(bot)->SayToGeneral(responseMessage); - //GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); - break; - } - case ChatChannelSource::SRC_TRADE: - { - //do not reply to the chat - //may whisper - break; - } - case ChatChannelSource::SRC_LOCAL_DEFENSE: - { - //may reply to the same channel or whisper - //GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::LOCAL_DEFENSE); - break; - } - case ChatChannelSource::SRC_WORLD_DEFENSE: - { - //may whisper - break; - } - case ChatChannelSource::SRC_LOOKING_FOR_GROUP: - { - //do not reply to the chat - //may whisper - break; - } - case ChatChannelSource::SRC_GUILD_RECRUITMENT: - { - //do not reply to the chat - //may whisper - break; - } - case ChatChannelSource::SRC_WHISPER: - { - //GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); - break; - } - case ChatChannelSource::SRC_SAY: - { - //GET_PLAYERBOT_AI(bot)->Say(responseMessage); - break; - } - case ChatChannelSource::SRC_YELL: - { - //GET_PLAYERBOT_AI(bot)->Yell(responseMessage); - break; - } - case ChatChannelSource::SRC_GUILD: - { - //GET_PLAYERBOT_AI(bot)->SayToGuild(responseMessage); - break; - } - default: - break; + case ChatChannelSource::SRC_WORLD: + { + //may reply to the same channel or whisper + GET_PLAYERBOT_AI(bot)->SayToWorld(responseMessage); + break; + } + case ChatChannelSource::SRC_GENERAL: + { + //may reply to the same channel or whisper + GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::GENERAL); + GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); + break; + } + case ChatChannelSource::SRC_TRADE: + { + //do not reply to the chat + //may whisper + break; + } + case ChatChannelSource::SRC_LOCAL_DEFENSE: + { + //may reply to the same channel or whisper + GET_PLAYERBOT_AI(bot)->SayToChannel(responseMessage, ChatChannelId::LOCAL_DEFENSE); + break; + } + case ChatChannelSource::SRC_WORLD_DEFENSE: + { + //may whisper + break; + } + case ChatChannelSource::SRC_LOOKING_FOR_GROUP: + { + //do not reply to the chat + //may whisper + break; + } + case ChatChannelSource::SRC_GUILD_RECRUITMENT: + { + //do not reply to the chat + //may whisper + break; + } + case ChatChannelSource::SRC_WHISPER: + { + GET_PLAYERBOT_AI(bot)->Whisper(responseMessage, name); + break; + } + case ChatChannelSource::SRC_SAY: + { + GET_PLAYERBOT_AI(bot)->Say(responseMessage); + break; + } + case ChatChannelSource::SRC_YELL: + { + GET_PLAYERBOT_AI(bot)->Yell(responseMessage); + break; + } + case ChatChannelSource::SRC_GUILD: + { + GET_PLAYERBOT_AI(bot)->SayToGuild(responseMessage); + break; + } + default: + break; } GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("last said", "chat")->Set(time(0) + urand(5, 25)); @@ -856,4 +854,4 @@ std::string ChatReplyAction::GenerateReplyMessage(Player* bot, std::string incom } return respondsText; -} \ No newline at end of file +} diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index b4e9600d..dcaef0a6 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -281,8 +281,6 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b } else { - if (!bot->IsInChannel(chn)) - chn->JoinChannel(bot, ""); chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); } @@ -291,9 +289,6 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b std::string randomName = channelNames[urand(0, channelNames.size() - 1)]; if (Channel* chn = cMgr->GetChannel(randomName, bot)) { - if (!bot->IsInChannel(chn)) - chn->JoinChannel(bot, ""); - chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); } } @@ -305,11 +300,9 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b } } - if (sPlayerbotAIConfig->randomBotGuildTalk && guild && bot->GetGuildId()) + if (sPlayerbotAIConfig->randomBotGuildTalk) { - Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); - if (guild) - guild->BroadcastToGuild(bot->GetSession(), false, msg.c_str(), LANG_UNIVERSAL); + botAI->SayToGuild(msg); } } diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index 8dc98ca6..471b0125 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -41,14 +41,9 @@ bool XpGainAction::Execute(Event event) Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); if (guild) { - std::string toSay = ""; - - if (urand(0, 3)) - toSay = "Wow I just killed " + creature->GetName() + " !"; - else - toSay = "Awesome that " + creature->GetName() + " went down quickly !"; - - guild->BroadcastToGuild(bot->GetSession(), false, toSay, LANG_UNIVERSAL); + std::map args; + args["%victim_name"] = creature->GetName(); + botAI->SayToGuild(BOT_TEXT2("broadcast_killed_rare", args)); } } }