From 21a6628161d5367c5d18f090d31cad54c8417fe1 Mon Sep 17 00:00:00 2001 From: antony Date: Thu, 25 Jul 2024 13:31:08 +0200 Subject: [PATCH 01/12] French + locale dbc use fix --- src/PlayerbotMgr.cpp | 6 +- src/PlayerbotTextMgr.cpp | 2 + src/strategy/actions/SayAction.cpp | 15 ++- .../actions/SuggestWhatToDoAction.cpp | 119 ++++++++++++++---- src/strategy/actions/SuggestWhatToDoAction.h | 2 + 5 files changed, 110 insertions(+), 34 deletions(-) diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index f236d769..c72e7a7b 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -544,13 +544,13 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) Channel* new_channel = nullptr; if (isLfg) { - std::string lfgChannelName = channel->pattern[0]; - new_channel = cMgr->GetJoinChannel("LookingForGroup", channel->ChannelID); + std::string lfgChannelName = channel->pattern[sWorld->GetDefaultDbcLocale()]; + new_channel = cMgr->GetJoinChannel(lfgChannelName, channel->ChannelID); } else { char new_channel_name_buf[100]; - snprintf(new_channel_name_buf, 100, channel->pattern[0], current_zone_name.c_str()); + snprintf(new_channel_name_buf, 100, channel->pattern[sWorld->GetDefaultDbcLocale()], current_zone_name.c_str()); new_channel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID); } if (new_channel && new_channel->GetName().length() > 0) diff --git a/src/PlayerbotTextMgr.cpp b/src/PlayerbotTextMgr.cpp index acfaada8..64261314 100644 --- a/src/PlayerbotTextMgr.cpp +++ b/src/PlayerbotTextMgr.cpp @@ -191,6 +191,8 @@ uint32 PlayerbotTextMgr::GetLocalePriority() if (botTextLocalePriority[i] > topLocale) topLocale = i; } + + LOG_INFO("playerbots", "GetLocalePriority: {}", topLocale); return topLocale; } diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 02f03499..4b68a323 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -105,6 +105,9 @@ bool SayAction::isUseful() if (!botAI->AllowActivity()) return false; + if (botAI->HasStrategy("silent", BotState::BOT_STATE_NON_COMBAT)) + return false; + time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier); return (time(nullptr) - lastSaid) > 30; } @@ -160,7 +163,8 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 // } // } // - if (word[i] == "hi" || word[i] == "hey" || word[i] == "hello" || word[i] == "wazzup") + if (word[i] == "hi" || word[i] == "hey" || word[i] == "hello" || word[i] == "wazzup" + || word[i] == "salut" || word[i] == "plop" || word[i] == "yo") { replyType = REPLY_HELLO; found = true; @@ -169,22 +173,23 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 if (verb_type < 4) { - if (word[i] == "am" || word[i] == "are" || word[i] == "is") + if (word[i] == "am" || word[i] == "are" || word[i] == "is" || word[i] == "suis" || word[i] == "a" || word[i] == "est" + || word[i] == "dois" || word[i] == "doit") { verb_pos = i; verb_type = 2; // present } - else if (word[i] == "will") + else if (word[i] == "will" || word[i] == "vais" || word[i] == "sera") { verb_pos = i; verb_type = 3; // future } - else if (word[i] == "was" || word[i] == "were") + else if (word[i] == "was" || word[i] == "were" || word[i] == "été" || word[i] == "ai" || word[i] == "eu" || word[i] == "étions" || word[i] == "etion" ) { verb_pos = i; verb_type = 1; // past } - else if (word[i] == "shut" || word[i] == "noob") + else if (word[i] == "shut" || word[i] == "noob" || word[i] == "tg") { if (msg.find(bot->GetName()) == std::string::npos) { diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 3c797193..fa8eada1 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -11,15 +11,39 @@ #include "Playerbots.h" #include "PlayerbotTextMgr.h" #include "GuildMgr.h" +#include "Config.h" + +enum eTalkType +{ + General = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, + Trade = ChannelFlags::CHANNEL_FLAG_CITY | ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG | ChannelFlags::CHANNEL_FLAG_TRADE, + LocalDefence = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, + GuildRecruitment = ChannelFlags::CHANNEL_FLAG_CITY | ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, + LookingForGroup = ChannelFlags::CHANNEL_FLAG_LFG | ChannelFlags::CHANNEL_FLAG_GENERAL +}; std::map SuggestWhatToDoAction::instances; std::map SuggestWhatToDoAction::factions; -SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string const name) : InventoryAction(botAI, name) +SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string const name) + : InventoryAction{ botAI, name } + , _dbc_locale{ sWorld->GetDefaultDbcLocale() } { suggestions.push_back(&SuggestWhatToDoAction::specificQuest); suggestions.push_back(&SuggestWhatToDoAction::grindReputation); suggestions.push_back(&SuggestWhatToDoAction::something); + suggestions.push_back(&SuggestWhatToDoAction::instance); + suggestions.push_back(&SuggestWhatToDoAction::grindMaterials); +} + +bool SuggestWhatToDoAction::isUseful() +{ + if (!sRandomPlayerbotMgr->IsRandomBot(bot) || bot->GetGroup() || bot->GetInstanceId()) + return false; + + std::string qualifier = "suggest what to do"; + time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier); + return (time(0) - lastSaid) > 30; } bool SuggestWhatToDoAction::Execute(Event event) @@ -85,12 +109,12 @@ void SuggestWhatToDoAction::instance() instances["Halls of Reflection"] = 80; } - std::vector allowedInstances; - for (auto & instance : instances) + std::vector allowedInstances; + for (const auto& instance : instances) { - if (bot->GetLevel() >= instance.second) allowedInstances.push_back(instance.first); + if (bot->GetLevel() >= instance.second) + allowedInstances.push_back(instance.first); } - if (allowedInstances.empty()) return; std::map placeholders; @@ -101,7 +125,7 @@ void SuggestWhatToDoAction::instance() itemout << allowedInstances[urand(0, allowedInstances.size() - 1)]; placeholders["%instance"] = itemout.str(); - spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? 0x50 : 0, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, urand(0, 2), urand(0, 2)); } std::vector SuggestWhatToDoAction::GetIncompletedQuests() @@ -136,7 +160,52 @@ void SuggestWhatToDoAction::specificQuest() placeholders["%role"] = chat->FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); placeholders["%quest"] = chat->FormatQuest(quest); - spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? 0x18 : 0, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_quest", placeholders), urand(0, 1) ? eTalkType::General : 0, urand(0, 2), urand(0, 2)); +} + +void SuggestWhatToDoAction::grindMaterials() +{ + /*if (bot->GetLevel() <= 5) + return; + + auto result = CharacterDatabase.Query("SELECT distinct category, multiplier FROM ahbot_category where category not in ('other', 'quest', 'trade', 'reagent') and multiplier > 3 order by multiplier desc limit 10"); + if (!result) + return; + + std::map categories; + do + { + Field* fields = result->Fetch(); + categories[fields[0].Get()] = fields[1].Get(); + } while (result->NextRow()); + + for (std::map::iterator i = categories.begin(); i != categories.end(); ++i) + { + if (urand(0, 10) < 3) { + std::string name = i->first; + double multiplier = i->second; + + for (int j = 0; j < ahbot::CategoryList::instance.size(); j++) + { + ahbot::Category* category = ahbot::CategoryList::instance[j]; + if (name == category->GetName()) + { + std::string item = category->GetLabel(); + transform(item.begin(), item.end(), item.begin(), ::tolower); + std::ostringstream itemout; + itemout << "|c0000b000" << item << "|r"; + item = itemout.str(); + + std::map placeholders; + placeholders["%role"] = chat->formatClass(bot, AiFactory::GetPlayerSpecTab(bot)); + placeholders["%category"] = item; + + spam(BOT_TEXT2("suggest_trade", placeholders), urand(0, 1) ? 0x3C : 0x18, !urand(0, 2), !urand(0, 3)); + return; + } + } + } + }*/ } void SuggestWhatToDoAction::grindReputation() @@ -179,18 +248,17 @@ void SuggestWhatToDoAction::grindReputation() factions["The Wyrmrest Accord"] = 77; } - std::vector levels; + std::vector levels; levels.push_back("honored"); levels.push_back("revered"); levels.push_back("exalted"); - std::vector allowedFactions; - for (std::map::iterator i = factions.begin(); i != factions.end(); ++i) + std::vector allowedFactions; + for (const auto& i : factions) { - if (bot->GetLevel() >= i->second) - allowedFactions.push_back(i->first); + if (bot->GetLevel() >= i.second) + allowedFactions.push_back(i.first); } - if (allowedFactions.empty()) return; @@ -207,7 +275,7 @@ void SuggestWhatToDoAction::grindReputation() itemout << allowedFactions[urand(0, allowedFactions.size() - 1)]; placeholders["%faction"] = itemout.str(); - spam(BOT_TEXT2("suggest_faction", placeholders), 0x18, true); + spam(BOT_TEXT2("suggest_faction", placeholders), eTalkType::General, true); } void SuggestWhatToDoAction::something() @@ -221,10 +289,10 @@ void SuggestWhatToDoAction::something() std::ostringstream out; // out << "|cffb04040" << entry->area_name[0] << "|r"; - out << entry->area_name[0]; + out << entry->area_name[_dbc_locale]; placeholders["%zone"] = out.str(); - spam(BOT_TEXT2("suggest_something", placeholders), urand(0, 1) ? 0x18 : 0, urand(0, 2), urand(0, 2)); + spam(BOT_TEXT2("suggest_something", placeholders), urand(0, 1) ? eTalkType::General : 0, urand(0, 2), urand(0, 2)); } void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, bool guild) @@ -237,12 +305,13 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if (!cMgr) return; - for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); if (!channel) continue; + LOG_INFO("playerbots", "Loop on channel: {}", channel->pattern[_dbc_locale]); + for (AreaTableEntry const* current_zone : sAreaTableStore) { if (!current_zone) @@ -254,13 +323,15 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b Channel* chn = nullptr; if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0) { - std::string chanName = channel->pattern[0]; + std::string chanName = channel->pattern[_dbc_locale]; + LOG_INFO("playerbots", "Trying to chat on channel: {}", chanName); chn = cMgr->GetChannel(chanName, bot); } else { - snprintf(channelName, 100, channel->pattern[0], current_zone->area_name[0]); + snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]); chn = cMgr->GetChannel(channelName, bot); + LOG_INFO("playerbots", "Trying to chat on channel: {}", channelName); } if (!chn) continue; @@ -287,8 +358,11 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if (!channelNames.empty()) { std::string randomName = channelNames[urand(0, channelNames.size() - 1)]; + LOG_INFO("playerbots", "Chatting on channel: {}", randomName); if (Channel* chn = cMgr->GetChannel(randomName, bot)) + { chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); + } } if (worldChat) @@ -403,10 +477,3 @@ bool SuggestTradeAction::Execute(Event event) spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? 0x3C : 0, urand(0, 1), urand(0, 5)); return true; } - -bool SuggestWhatToDoAction::isUseful() -{ - std::string const qualifier = "suggest what to do"; - time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier); - return (time(nullptr) - lastSaid) > 30; -} diff --git a/src/strategy/actions/SuggestWhatToDoAction.h b/src/strategy/actions/SuggestWhatToDoAction.h index 4bff50cf..58fafd59 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.h +++ b/src/strategy/actions/SuggestWhatToDoAction.h @@ -23,6 +23,7 @@ class SuggestWhatToDoAction : public InventoryAction void instance(); void specificQuest(); void grindReputation(); + void grindMaterials(); void something(); void spam(std::string msg, uint8 flags = 0, bool worldChat = false, bool guild = false); @@ -31,6 +32,7 @@ class SuggestWhatToDoAction : public InventoryAction private: static std::map instances; static std::map factions; + const int32_t& _dbc_locale; }; class SuggestTradeAction : public SuggestWhatToDoAction From 44b1b32e06ef2c0d8ad2db7aefd911e951981fb1 Mon Sep 17 00:00:00 2001 From: antony Date: Thu, 25 Jul 2024 15:06:25 +0200 Subject: [PATCH 02/12] Say debug + fixes --- src/strategy/actions/SayAction.cpp | 90 ++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 4b68a323..71b7664e 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -10,6 +10,16 @@ #include "GuildMgr.h" #include +static const std::unordered_set noReplyMsgs = { + "join", "leave", "follow", "attack", "pull", "flee", "reset", "reset ai", + "all ?", "talents", "talents list", "talents auto", "talk", "stay", "stats", + "who", "items", "leave", "join", "repair", "summon", "nc ?", "co ?", "de ?", + "dead ?", "follow", "los", "guard", "do accept invitation", "stats", "react ?", + "reset strats", "home", +}; +static const std::unordered_set noReplyMsgParts = { "+", "-","@" , "follow target", "focus heal", "cast ", "accept [", "e [", "destroy [", "go zone" }; +static const std::unordered_set noReplyMsgStarts = { "e ", "accept ", "cast ", "destroy " }; + SayAction::SayAction(PlayerbotAI* botAI) : Action(botAI, "say"), Qualified() { } @@ -114,9 +124,41 @@ bool SayAction::isUseful() void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 guid2, std::string msg, std::string chanName, std::string name) { + LOG_INFO("playerbots", "{} Handle chat reply", bot->GetName()); + ChatReplyType replyType = REPLY_NOT_UNDERSTAND; // default not understand std::string respondsText = ""; + // if we're just commanding bots around, don't respond... + // first one is for exact word matches + if (noReplyMsgs.find(msg) != noReplyMsgs.end()) { + std::ostringstream out; + out << "DEBUG ChatReplyDo decided to ignore exact blocklist match" << msg; + bot->Say(out.str(), LANG_UNIVERSAL); + return; + } + + // second one is for partial matches like + or - where we change strats + if (std::any_of(noReplyMsgParts.begin(), noReplyMsgParts.end(), [&msg](const std::string& part) { return msg.find(part) != std::string::npos; })) { + std::ostringstream out; + out << "DEBUG ChatReplyDo decided to ignore partial blocklist match" << msg; + bot->Say(out.str(), LANG_UNIVERSAL); + + return; + } + + if (std::any_of(noReplyMsgStarts.begin(), noReplyMsgStarts.end(), [&msg](const std::string& start) { + return msg.find(start) == 0; // Check if the start matches the beginning of msg + })) { + std::ostringstream out; + out << "DEBUG ChatReplyDo decided to ignore start blocklist match" << msg; + bot->Say(out.str(), LANG_UNIVERSAL); + return; + } + + ObjectGuid receiver = sCharacterCache->GetCharacterGuidByName(name); + Player* plr = ObjectAccessor::FindPlayer(receiver); + // Chat Logic int32 verb_pos = -1; int32 verb_type = -1; @@ -152,17 +194,14 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 // Responds for (uint32 i = 0; i < 8; i++) { -// // blame gm with chat tag -// if (Player* plr = sObjectMgr->GetPlayer(ObjectGuid(HIGHGUID_PLAYER, guid1))) -// { -// if (plr->isGMChat()) -// { -// replyType = REPLY_ADMIN_ABUSE; -// found = true; -// break; -// } -// } -// + // blame gm with chat tag + if (plr && plr->isGMChat()) + { + replyType = REPLY_ADMIN_ABUSE; + found = true; + break; + } + if (word[i] == "hi" || word[i] == "hey" || word[i] == "hello" || word[i] == "wazzup" || word[i] == "salut" || word[i] == "plop" || word[i] == "yo") { @@ -173,11 +212,13 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 if (verb_type < 4) { - if (word[i] == "am" || word[i] == "are" || word[i] == "is" || word[i] == "suis" || word[i] == "a" || word[i] == "est" + if (word[i] == "am" || word[i] == "are" || word[i] == "is" || word[i] == "suis" || word[i] == "as" || word[i] == "est" || word[i] == "dois" || word[i] == "doit") { verb_pos = i; verb_type = 2; // present + if (verb_pos == 0) + is_quest = 1; } else if (word[i] == "will" || word[i] == "vais" || word[i] == "sera") { @@ -605,19 +646,19 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 { if (type == CHAT_MSG_WHISPER) { - ObjectGuid receiver = sCharacterCache->GetCharacterGuidByName(name); - if (!receiver || !receiver.IsPlayer() || !ObjectAccessor::FindPlayer(receiver)) + if (plr) { - return; - } - if (bot->GetTeamId() == TEAM_ALLIANCE) - { - bot->Whisper(c, LANG_COMMON, ObjectAccessor::FindPlayer(receiver)); + if (bot->GetTeamId() == TEAM_ALLIANCE) + { + bot->Whisper(c, LANG_COMMON, plr); + } + else + { + bot->Whisper(c, LANG_ORCISH, plr); + } } else - { - bot->Whisper(c, LANG_ORCISH, ObjectAccessor::FindPlayer(receiver)); - } + LOG_ERROR("playerbots", "plr pointer is nullptr chat whisper"); } if (type == CHAT_MSG_SAY) @@ -647,6 +688,11 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 guild->BroadcastToGuild(bot->GetSession(), false, respondsText, LANG_UNIVERSAL); } + + else + { + LOG_ERROR("playerbots", "Unknown chat type {}", type); + } } GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("last said", "chat")->Set(time(nullptr) + urand(5, 25)); } From 916a0002e8984e17f62e536a84307139d0b61506 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Thu, 25 Jul 2024 17:56:53 +0200 Subject: [PATCH 03/12] Fix crash --- src/PlayerbotMgr.cpp | 2 +- src/PlayerbotTextMgr.cpp | 1 - src/strategy/actions/SayAction.cpp | 9 +++++---- src/strategy/actions/SuggestWhatToDoAction.cpp | 11 +++++++---- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index f8923316..2582fd5b 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -545,7 +545,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) if (isLfg) { std::string lfgChannelName = channel->pattern[sWorld->GetDefaultDbcLocale()]; - new_channel = cMgr->GetJoinChannel(lfgChannelName, channel->ChannelID); + new_channel = cMgr->GetJoinChannel("LookingForGroup", channel->ChannelID); } else { diff --git a/src/PlayerbotTextMgr.cpp b/src/PlayerbotTextMgr.cpp index 64261314..fd3a95a6 100644 --- a/src/PlayerbotTextMgr.cpp +++ b/src/PlayerbotTextMgr.cpp @@ -192,7 +192,6 @@ uint32 PlayerbotTextMgr::GetLocalePriority() topLocale = i; } - LOG_INFO("playerbots", "GetLocalePriority: {}", topLocale); return topLocale; } diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 71b7664e..46bcf089 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -661,15 +661,16 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 LOG_ERROR("playerbots", "plr pointer is nullptr chat whisper"); } - if (type == CHAT_MSG_SAY) + else if (type == CHAT_MSG_SAY) { + LOG_INFO("playerbots", "say respond: {}", respondsText); if (bot->GetTeamId() == TEAM_ALLIANCE) bot->Say(respondsText, LANG_COMMON); else bot->Say(respondsText, LANG_ORCISH); } - if (type == CHAT_MSG_YELL) + else if (type == CHAT_MSG_YELL) { if (bot->GetTeamId() == TEAM_ALLIANCE) bot->Yell(respondsText, LANG_COMMON); @@ -677,7 +678,7 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 bot->Yell(respondsText, LANG_ORCISH); } - if (type == CHAT_MSG_GUILD) + else if (type == CHAT_MSG_GUILD) { if (!bot->GetGuildId()) return; @@ -696,4 +697,4 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 } GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("last said", "chat")->Set(time(nullptr) + urand(5, 25)); } -} \ No newline at end of file +} diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index fa8eada1..0fd543c5 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -109,7 +109,7 @@ void SuggestWhatToDoAction::instance() instances["Halls of Reflection"] = 80; } - std::vector allowedInstances; + std::vector allowedInstances; for (const auto& instance : instances) { if (bot->GetLevel() >= instance.second) @@ -248,12 +248,12 @@ void SuggestWhatToDoAction::grindReputation() factions["The Wyrmrest Accord"] = 77; } - std::vector levels; + std::vector levels; levels.push_back("honored"); levels.push_back("revered"); levels.push_back("exalted"); - std::vector allowedFactions; + std::vector allowedFactions; for (const auto& i : factions) { if (bot->GetLevel() >= i.second) @@ -310,7 +310,10 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); if (!channel) continue; - LOG_INFO("playerbots", "Loop on channel: {}", channel->pattern[_dbc_locale]); + if (channel->pattern[_dbc_locale]) + LOG_INFO("playerbots", "Loop on channel: {}", channel->pattern[_dbc_locale]); + else + LOG_ERROR("playerbots", "channel->pattern[_dbc_locale] is null"); for (AreaTableEntry const* current_zone : sAreaTableStore) { From 50bd63575d5155701ce9a2751024ff53129b3d45 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Thu, 25 Jul 2024 23:18:04 +0200 Subject: [PATCH 04/12] Progress on channels and say yell etc --- src/AiFactory.cpp | 4 +-- src/PlayerbotTextMgr.cpp | 5 ++-- src/strategy/actions/EmoteAction.cpp | 8 ++--- src/strategy/actions/SayAction.cpp | 11 ------- .../actions/SuggestWhatToDoAction.cpp | 30 ++++++++----------- src/strategy/actions/SuggestWhatToDoAction.h | 4 +-- 6 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 2eb4453e..e932a111 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -264,7 +264,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (!player->InBattleground()) { - engine->addStrategies("racials", "chat", "default", "cast time", "duel", "boost", nullptr); + engine->addStrategies("racials", "chat", "default", "cast time", "duel", "boost", "emote", nullptr); } if (sPlayerbotAIConfig->autoSaveMana) { @@ -548,7 +548,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const if (!player->InBattleground()) { nonCombatEngine->addStrategies("nc", "food", "chat", "follow", - "default", "quest", "loot", "gather", "duel", "buff", "mount", nullptr); + "default", "quest", "loot", "gather", "duel", "buff", "mount", "emote", nullptr); } if (sPlayerbotAIConfig->autoSaveMana) { nonCombatEngine->addStrategy("auto save mana"); diff --git a/src/PlayerbotTextMgr.cpp b/src/PlayerbotTextMgr.cpp index fd3a95a6..7041185c 100644 --- a/src/PlayerbotTextMgr.cpp +++ b/src/PlayerbotTextMgr.cpp @@ -28,12 +28,13 @@ void PlayerbotTextMgr::LoadBotTexts() Field* fields = result->Fetch(); std::string name = fields[0].Get(); text[0] = fields[1].Get(); - uint32 sayType = fields[2].Get(); - uint32 replyType = fields[3].Get(); + uint8 sayType = fields[2].Get(); + uint8 replyType = fields[3].Get(); for (uint8 i = 1; i < MAX_LOCALES; ++i) { text[i] = fields[i + 3].Get(); } + botTexts[name].push_back(BotTextEntry(name, text, sayType, replyType)); ++count; } diff --git a/src/strategy/actions/EmoteAction.cpp b/src/strategy/actions/EmoteAction.cpp index 2ef6e90a..8fe57374 100644 --- a/src/strategy/actions/EmoteAction.cpp +++ b/src/strategy/actions/EmoteAction.cpp @@ -671,9 +671,9 @@ bool EmoteAction::Execute(Event event) if (pSource && (pSource->GetGUID() != bot->GetGUID()) && ((urand(0, 1) && bot->HasInArc(static_cast(M_PI), pSource, 10.0f)) || (namlen > 1 && strstri(bot->GetName().c_str(), nam.c_str())))) { - LOG_INFO("playerbots", "Bot {} {}:{} <{}> received SMSG_TEXT_EMOTE {} from player {} <{}>", + /*LOG_INFO("playerbots", "Bot {} {}:{} <{}> received SMSG_TEXT_EMOTE {} from player {} <{}>", bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), - bot->GetName(), text_emote, pSource->GetGUID().ToString().c_str(), pSource->GetName()); + bot->GetName(), text_emote, pSource->GetGUID().ToString().c_str(), pSource->GetName());*/ emote = text_emote; } @@ -693,9 +693,9 @@ bool EmoteAction::Execute(Event event) if ((pSource->GetGUID() != bot->GetGUID()) && (pSource->GetTarget() == bot->GetGUID() || (urand(0, 1) && bot->HasInArc(static_cast(M_PI), pSource, 10.0f)))) { - LOG_INFO("playerbots", "Bot {} {}:{} <{}> received SMSG_EMOTE {} from player {} <{}>", + /*LOG_INFO("playerbots", "Bot {} {}:{} <{}> received SMSG_EMOTE {} from player {} <{}>", bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName(), - emoteId, pSource->GetGUID().ToString().c_str(), pSource->GetName()); + emoteId, pSource->GetGUID().ToString().c_str(), pSource->GetName());*/ std::vector types; for (int32 i = sEmotesTextStore.GetNumRows(); i >= 0; --i) diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 46bcf089..67395b2e 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -124,8 +124,6 @@ bool SayAction::isUseful() void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 guid2, std::string msg, std::string chanName, std::string name) { - LOG_INFO("playerbots", "{} Handle chat reply", bot->GetName()); - ChatReplyType replyType = REPLY_NOT_UNDERSTAND; // default not understand std::string respondsText = ""; @@ -143,7 +141,6 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 std::ostringstream out; out << "DEBUG ChatReplyDo decided to ignore partial blocklist match" << msg; bot->Say(out.str(), LANG_UNIVERSAL); - return; } @@ -657,13 +654,10 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 bot->Whisper(c, LANG_ORCISH, plr); } } - else - LOG_ERROR("playerbots", "plr pointer is nullptr chat whisper"); } else if (type == CHAT_MSG_SAY) { - LOG_INFO("playerbots", "say respond: {}", respondsText); if (bot->GetTeamId() == TEAM_ALLIANCE) bot->Say(respondsText, LANG_COMMON); else @@ -689,11 +683,6 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 guild->BroadcastToGuild(bot->GetSession(), false, respondsText, LANG_UNIVERSAL); } - - else - { - LOG_ERROR("playerbots", "Unknown chat type {}", type); - } } GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("last said", "chat")->Set(time(nullptr) + urand(5, 25)); } diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 0fd543c5..81c5f540 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -13,6 +13,8 @@ #include "GuildMgr.h" #include "Config.h" +#include + enum eTalkType { General = ChannelFlags::CHANNEL_FLAG_GENERAL | ChannelFlags::CHANNEL_FLAG_NOT_LFG, @@ -29,11 +31,11 @@ SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string con : InventoryAction{ botAI, name } , _dbc_locale{ sWorld->GetDefaultDbcLocale() } { - suggestions.push_back(&SuggestWhatToDoAction::specificQuest); - suggestions.push_back(&SuggestWhatToDoAction::grindReputation); - suggestions.push_back(&SuggestWhatToDoAction::something); - suggestions.push_back(&SuggestWhatToDoAction::instance); - suggestions.push_back(&SuggestWhatToDoAction::grindMaterials); + suggestions.push_back(std::bind(&SuggestWhatToDoAction::specificQuest, this)); + suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindReputation, this)); + suggestions.push_back(std::bind(&SuggestWhatToDoAction::something, this)); + suggestions.push_back(std::bind(&SuggestWhatToDoAction::instance, this)); + suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindMaterials, this)); } bool SuggestWhatToDoAction::isUseful() @@ -48,11 +50,9 @@ bool SuggestWhatToDoAction::isUseful() bool SuggestWhatToDoAction::Execute(Event event) { - if (!sRandomPlayerbotMgr->IsRandomBot(bot) || bot->GetGroup() || bot->GetInstanceId()) - return false; - uint32 index = rand() % suggestions.size(); - (this->*suggestions[index])(); + auto fnct_ptr = suggestions[index]; + fnct_ptr(); std::string const qualifier = "suggest what to do"; time_t lastSaid = AI_VALUE2(time_t, "last said", qualifier); @@ -310,11 +310,6 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); if (!channel) continue; - if (channel->pattern[_dbc_locale]) - LOG_INFO("playerbots", "Loop on channel: {}", channel->pattern[_dbc_locale]); - else - LOG_ERROR("playerbots", "channel->pattern[_dbc_locale] is null"); - for (AreaTableEntry const* current_zone : sAreaTableStore) { if (!current_zone) @@ -327,14 +322,12 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0) { std::string chanName = channel->pattern[_dbc_locale]; - LOG_INFO("playerbots", "Trying to chat on channel: {}", chanName); chn = cMgr->GetChannel(chanName, bot); } else { snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]); chn = cMgr->GetChannel(channelName, bot); - LOG_INFO("playerbots", "Trying to chat on channel: {}", channelName); } if (!chn) continue; @@ -355,16 +348,19 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b channelNames.push_back(chn->GetName()); } else + { chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); + LOG_DEBUG("playerbots", "send grind {} - {}", bot->GetName().c_str(), msg.c_str()); + } } if (!channelNames.empty()) { std::string randomName = channelNames[urand(0, channelNames.size() - 1)]; - LOG_INFO("playerbots", "Chatting on channel: {}", randomName); if (Channel* chn = cMgr->GetChannel(randomName, bot)) { chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); + LOG_DEBUG("playerbots", "send grind {} - {}", bot->GetName().c_str(), msg.c_str()); } } diff --git a/src/strategy/actions/SuggestWhatToDoAction.h b/src/strategy/actions/SuggestWhatToDoAction.h index 58fafd59..2a942e34 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.h +++ b/src/strategy/actions/SuggestWhatToDoAction.h @@ -18,7 +18,7 @@ class SuggestWhatToDoAction : public InventoryAction bool isUseful() override; protected: - typedef void (SuggestWhatToDoAction::*Suggestion)(); + using Suggestion = std::function; std::vector suggestions; void instance(); void specificQuest(); @@ -32,7 +32,7 @@ class SuggestWhatToDoAction : public InventoryAction private: static std::map instances; static std::map factions; - const int32_t& _dbc_locale; + const int32_t _dbc_locale; }; class SuggestTradeAction : public SuggestWhatToDoAction From 8d43ab8cb47355b537570a797ee70d07ac3914d0 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Thu, 25 Jul 2024 23:22:10 +0200 Subject: [PATCH 05/12] fix log --- src/strategy/actions/SuggestWhatToDoAction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 81c5f540..95c933cd 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -350,7 +350,7 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b else { chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); - LOG_DEBUG("playerbots", "send grind {} - {}", bot->GetName().c_str(), msg.c_str()); + LOG_INFO("playerbots", "{} - {} channel {}", bot->GetName().c_str(), msg.c_str(), chn->GetName()); } } @@ -360,7 +360,7 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b if (Channel* chn = cMgr->GetChannel(randomName, bot)) { chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); - LOG_DEBUG("playerbots", "send grind {} - {}", bot->GetName().c_str(), msg.c_str()); + LOG_INFO("playerbots", "{} - {} channel {}", bot->GetName().c_str(), msg.c_str(), chn->GetName()); } } From d21d1e9b688c99c192ed8c78c5a3e594c0fb0687 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sat, 27 Jul 2024 10:13:33 +0200 Subject: [PATCH 06/12] Suggest dungeon implementation + log action unknown to help debug --- src/AiFactory.cpp | 2 +- src/PlayerbotMgr.cpp | 3 +- src/strategy/Engine.cpp | 1 + src/strategy/actions/ActionContext.h | 2 + .../actions/SuggestWhatToDoAction.cpp | 221 +++++++++--------- src/strategy/actions/SuggestWhatToDoAction.h | 12 +- 6 files changed, 130 insertions(+), 111 deletions(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index e932a111..db551d1a 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -636,7 +636,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const // Battleground switch if (player->InBattleground() && player->GetBattleground()) { - nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", "attack tagged", nullptr); + nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", "attack tagged", "emote", nullptr); nonCombatEngine->removeStrategy("custom::say"); nonCombatEngine->removeStrategy("travel"); nonCombatEngine->removeStrategy("rpg"); diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 2582fd5b..f2fab8c4 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -85,7 +85,8 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con uint32 botAccountId = holder.GetAccountId(); - WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), LOCALE_enUS, 0, false, false, 0, true); + // At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this allows channels to work as intended) + WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), sWorld->GetDefaultDbcLocale(), 0, false, false, 0, true); botSession->HandlePlayerLoginFromDB(holder); // will delete lqh diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index cef411c6..dbb35c74 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -172,6 +172,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) if (!action) { + LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(), botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel()); LogAction("A:%s - UNKNOWN", actionNode->getName().c_str()); } else if (action->isUseful()) diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index ea8b3362..e7caf4e2 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -123,6 +123,7 @@ class ActionContext : public NamedObjectContext creators["talk"] = &ActionContext::talk; creators["suggest what to do"] = &ActionContext::suggest_what_to_do; creators["suggest trade"] = &ActionContext::suggest_trade; + creators["suggest dungeon"] = &ActionContext::suggest_dungeon; creators["return"] = &ActionContext::_return; creators["move to loot"] = &ActionContext::move_to_loot; creators["open loot"] = &ActionContext::open_loot; @@ -280,6 +281,7 @@ class ActionContext : public NamedObjectContext static Action* talk(PlayerbotAI* botAI) { return new TalkAction(botAI); } static Action* suggest_what_to_do(PlayerbotAI* botAI) { return new SuggestWhatToDoAction(botAI); } static Action* suggest_trade(PlayerbotAI* botAI) { return new SuggestTradeAction(botAI); } + static Action* suggest_dungeon(PlayerbotAI* botAI) { return new SuggestDungeonAction(botAI); } static Action* attack_anything(PlayerbotAI* botAI) { return new AttackAnythingAction(botAI); } static Action* attack_least_hp_target(PlayerbotAI* botAI) { return new AttackLeastHpTargetAction(botAI); } static Action* attack_enemy_player(PlayerbotAI* botAI) { return new AttackEnemyPlayerAction(botAI); } diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 95c933cd..33b17e23 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -3,6 +3,7 @@ */ #include "SuggestWhatToDoAction.h" +#include "ServerFacade.h" #include "ChannelMgr.h" #include "Event.h" #include "ItemVisitors.h" @@ -24,7 +25,7 @@ enum eTalkType LookingForGroup = ChannelFlags::CHANNEL_FLAG_LFG | ChannelFlags::CHANNEL_FLAG_GENERAL }; -std::map SuggestWhatToDoAction::instances; +std::map SuggestDungeonAction::instances; std::map SuggestWhatToDoAction::factions; SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string const name) @@ -34,7 +35,6 @@ SuggestWhatToDoAction::SuggestWhatToDoAction(PlayerbotAI* botAI, std::string con suggestions.push_back(std::bind(&SuggestWhatToDoAction::specificQuest, this)); suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindReputation, this)); suggestions.push_back(std::bind(&SuggestWhatToDoAction::something, this)); - suggestions.push_back(std::bind(&SuggestWhatToDoAction::instance, this)); suggestions.push_back(std::bind(&SuggestWhatToDoAction::grindMaterials, this)); } @@ -61,73 +61,6 @@ bool SuggestWhatToDoAction::Execute(Event event) return true; } -void SuggestWhatToDoAction::instance() -{ - if (instances.empty()) - { - instances["Ragefire Chasm"] = 15; - instances["Deadmines"] = 18; - instances["Wailing Caverns"] = 18; - instances["Shadowfang Keep"] = 25; - instances["Blackfathom Deeps"] = 20; - instances["Stockade"] = 20; - instances["Gnomeregan"] = 35; - instances["Razorfen Kraul"] = 35; - instances["Maraudon"] = 50; - instances["Scarlet Monestery"] = 40; - instances["Uldaman"] = 45; - instances["Dire Maul"] = 58; - instances["Scholomance"] = 59; - instances["Razorfen Downs"] = 40; - instances["Strathholme"] = 59; - instances["Zul'Farrak"] = 45; - instances["Blackrock Depths"] = 55; - instances["Temple of Atal'Hakkar"] = 55; - instances["Lower Blackrock Spire"] = 57; - - instances["Hellfire Citidel"] = 65; - instances["Coilfang Reservoir"] = 65; - instances["Auchindoun"] = 65; - instances["Cavens of Time"] = 68; - instances["Tempest Keep"] = 69; - instances["Magister's Terrace"] = 70; - - instances["Utgarde Keep"] = 75; - instances["The Nexus"] = 75; - instances["Ahn'kahet: The Old Kingdom"] = 75; - instances["Azjol-Nerub"] = 75; - instances["Drak'Tharon Keep"] = 75; - instances["Violet Hold"] = 80; - instances["Gundrak"] = 77; - instances["Halls of Stone"] = 77; - instances["Halls of Lightning"] = 77; - instances["Oculus"] = 77; - instances["Utgarde Pinnacle"] = 77; - instances["Trial of the Champion"] = 80; - instances["Forge of Souls"] = 80; - instances["Pit of Saron"] = 80; - instances["Halls of Reflection"] = 80; - } - - std::vector allowedInstances; - for (const auto& instance : instances) - { - if (bot->GetLevel() >= instance.second) - allowedInstances.push_back(instance.first); - } - if (allowedInstances.empty()) return; - - std::map placeholders; - placeholders["%role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); - - std::ostringstream itemout; - //itemout << "|c00b000b0" << allowedInstances[urand(0, allowedInstances.size() - 1)] << "|r"; - itemout << allowedInstances[urand(0, allowedInstances.size() - 1)]; - placeholders["%instance"] = itemout.str(); - - spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, urand(0, 2), urand(0, 2)); -} - std::vector SuggestWhatToDoAction::GetIncompletedQuests() { std::vector result; @@ -310,48 +243,46 @@ void SuggestWhatToDoAction::spam(std::string msg, uint8 flags, bool worldChat, b ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); if (!channel) continue; - for (AreaTableEntry const* current_zone : sAreaTableStore) + AreaTableEntry const* current_zone = GetAreaEntryByAreaID(bot->GetAreaId()); + if (!current_zone) + continue; + + // combine full channel name + char channelName[100]; + Channel* chn = nullptr; + if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0) { - if (!current_zone) - continue; + std::string chanName = channel->pattern[_dbc_locale]; + chn = cMgr->GetChannel(chanName, bot); + } + else + { + snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]); + chn = cMgr->GetChannel(channelName, bot); + } + if (!chn) + continue; + // skip world chat here + if (chn->GetName() == "World") + continue; + if (flags != 0 && chn->GetFlags() != flags) + continue; - // combine full channel name - char channelName[100]; - Channel* chn = nullptr; - if ((channel->flags & CHANNEL_DBC_FLAG_LFG) != 0) - { - std::string chanName = channel->pattern[_dbc_locale]; - chn = cMgr->GetChannel(chanName, bot); - } - else - { - snprintf(channelName, 100, channel->pattern[_dbc_locale], current_zone->area_name[_dbc_locale]); - chn = cMgr->GetChannel(channelName, bot); - } - if (!chn) - continue; - // skip world chat here - if (chn->GetName() == "World") - continue; + // skip local defense + if (chn->GetChannelId() == 22) + continue; - if (flags != 0 && chn->GetFlags() != flags) - continue; - - // skip local defense - //if (chn->GetFlags() == 0x18) - // continue; - - // no filter, pick several options - if (flags == CHANNEL_FLAG_NONE) - { - channelNames.push_back(chn->GetName()); - } - else - { - chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); - LOG_INFO("playerbots", "{} - {} channel {}", bot->GetName().c_str(), msg.c_str(), chn->GetName()); - } + // no filter, pick several options + if (flags == CHANNEL_FLAG_NONE) + { + channelNames.push_back(chn->GetName()); + } + else + { + if (!bot->IsInChannel(chn)) + chn->JoinChannel(bot, ""); + chn->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); } if (!channelNames.empty()) @@ -359,8 +290,10 @@ 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); - LOG_INFO("playerbots", "{} - {} channel {}", bot->GetName().c_str(), msg.c_str(), chn->GetName()); } } @@ -410,6 +343,78 @@ class FindTradeItemsVisitor : public IterateItemsVisitor uint32 quality; }; +SuggestDungeonAction::SuggestDungeonAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest dungeon") +{ +} + +bool SuggestDungeonAction::Execute(Event event) +{ + if (instances.empty()) + { + instances["Ragefire Chasm"] = 15; + instances["Deadmines"] = 18; + instances["Wailing Caverns"] = 18; + instances["Shadowfang Keep"] = 25; + instances["Blackfathom Deeps"] = 20; + instances["Stockade"] = 20; + instances["Gnomeregan"] = 35; + instances["Razorfen Kraul"] = 35; + instances["Maraudon"] = 50; + instances["Scarlet Monestery"] = 40; + instances["Uldaman"] = 45; + instances["Dire Maul"] = 58; + instances["Scholomance"] = 59; + instances["Razorfen Downs"] = 40; + instances["Strathholme"] = 59; + instances["Zul'Farrak"] = 45; + instances["Blackrock Depths"] = 55; + instances["Temple of Atal'Hakkar"] = 55; + instances["Lower Blackrock Spire"] = 57; + + instances["Hellfire Citidel"] = 65; + instances["Coilfang Reservoir"] = 65; + instances["Auchindoun"] = 65; + instances["Cavens of Time"] = 68; + instances["Tempest Keep"] = 69; + instances["Magister's Terrace"] = 70; + + instances["Utgarde Keep"] = 75; + instances["The Nexus"] = 75; + instances["Ahn'kahet: The Old Kingdom"] = 75; + instances["Azjol-Nerub"] = 75; + instances["Drak'Tharon Keep"] = 75; + instances["Violet Hold"] = 80; + instances["Gundrak"] = 77; + instances["Halls of Stone"] = 77; + instances["Halls of Lightning"] = 77; + instances["Oculus"] = 77; + instances["Utgarde Pinnacle"] = 77; + instances["Trial of the Champion"] = 80; + instances["Forge of Souls"] = 80; + instances["Pit of Saron"] = 80; + instances["Halls of Reflection"] = 80; + } + + std::vector allowedInstances; + for (const auto& instance : instances) + { + if (bot->GetLevel() >= instance.second) + allowedInstances.push_back(instance.first); + } + if (allowedInstances.empty()) return false; + + std::map placeholders; + placeholders["%role"] = ChatHelper::FormatClass(bot, AiFactory::GetPlayerSpecTab(bot)); + + std::ostringstream itemout; + //itemout << "|c00b000b0" << allowedInstances[urand(0, allowedInstances.size() - 1)] << "|r"; + itemout << allowedInstances[urand(0, allowedInstances.size() - 1)]; + placeholders["%instance"] = itemout.str(); + + spam(BOT_TEXT2("suggest_instance", placeholders), urand(0, 1) ? eTalkType::LookingForGroup : 0, urand(0, 2), urand(0, 2)); + return true; +} + SuggestTradeAction::SuggestTradeAction(PlayerbotAI* botAI) : SuggestWhatToDoAction(botAI, "suggest trade") { } diff --git a/src/strategy/actions/SuggestWhatToDoAction.h b/src/strategy/actions/SuggestWhatToDoAction.h index 2a942e34..f3a57b89 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.h +++ b/src/strategy/actions/SuggestWhatToDoAction.h @@ -30,7 +30,6 @@ class SuggestWhatToDoAction : public InventoryAction std::vector GetIncompletedQuests(); private: - static std::map instances; static std::map factions; const int32_t _dbc_locale; }; @@ -44,4 +43,15 @@ class SuggestTradeAction : public SuggestWhatToDoAction bool isUseful() override { return true; } }; +class SuggestDungeonAction : public SuggestWhatToDoAction +{ + public: + SuggestDungeonAction(PlayerbotAI* botAI); + + bool Execute(Event event) override; + bool isUseful() override { return true; } + private: + static std::map instances; +}; + #endif From adf9924925b2187d4566def6660257421a11e744 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sat, 27 Jul 2024 10:15:12 +0200 Subject: [PATCH 07/12] using config to toggle chat functionnality and suggest dungeon --- conf/playerbots.conf.dist | 19 ++++++++++----- src/PlayerbotAIConfig.cpp | 2 ++ src/PlayerbotAIConfig.h | 2 ++ .../actions/SuggestWhatToDoAction.cpp | 2 ++ src/strategy/generic/EmoteStrategy.cpp | 23 +++++++++++-------- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 40a44683..496ea5d7 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -1238,6 +1238,19 @@ AiPlayerbot.CommandPrefix = "" # Separator for bot chat commands AiPlayerbot.CommandSeparator = "\\\\" +# Enable playerbot talk (say / yell / general chatting / lfg) +AiPlayerbot.RandomBotTalk = 0 + +# Enable playerbot emote +AiPlayerbot.RandomBotEmote = 0 + +# Enable dungeon suggestions for random bots +AiPlayerbot.RandomBotSuggestDungeons = 1 + +# Bots greet to the players +AiPlayerbot.EnableGreet = 0 + + # # # @@ -1276,9 +1289,6 @@ AiPlayerbot.RandomBotLoginAtStartup = 1 # Guild Task system AiPlayerbot.EnableGuildTasks = 0 -# Enable dungeon suggestions for random bots -AiPlayerbot.RandomBotSuggestDungeons = 1 - # Enable dungeon suggestions in lower case randomly AiPlayerbot.SuggestDungeonsInLowerCaseRandomly = 0 @@ -1297,9 +1307,6 @@ AiPlayerbot.RandombotsWalkingRPG = 0 # Set randombots movement speed to walking only inside buildings AiPlayerbot.RandombotsWalkingRPG.InDoors = 0 -# Bots greet to the players -AiPlayerbot.EnableGreet = 0 - # Specify percent of active bots # The default is 10. With 10% of all bots going active or inactive each minute. AiPlayerbot.BotActiveAlone = 100 diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 94e290fe..94765f34 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -140,6 +140,8 @@ bool PlayerbotAIConfig::Initialize() minRandomBotsPriceChangeInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR); maxRandomBotsPriceChangeInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotsPriceChangeInterval", 48 * HOUR); randomBotJoinLfg = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinLfg", true); + randomBotTalk = sConfigMgr->GetOption("AiPlayerbot.RandomBotTalk", false); + randomBotEmote = sConfigMgr->GetOption("AiPlayerbot.RandomBotEmote", false); randomBotSuggestDungeons = sConfigMgr->GetOption("AiPlayerbot.RandomBotSuggestDungeons", true); suggestDungeonsInLowerCaseRandomly = sConfigMgr->GetOption("AiPlayerbot.SuggestDungeonsInLowerCaseRandomly", false); randomBotJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinBG", true); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 5ce7d39e..c008c051 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -95,6 +95,8 @@ class PlayerbotAIConfig uint32 randomBotsPerInterval; uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval; bool randomBotJoinLfg; + bool randomBotTalk; + bool randomBotEmote; bool randomBotSuggestDungeons; bool suggestDungeonsInLowerCaseRandomly; bool randomBotJoinBG; diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 33b17e23..428edd33 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -349,6 +349,8 @@ SuggestDungeonAction::SuggestDungeonAction(PlayerbotAI* botAI) : SuggestWhatToDo bool SuggestDungeonAction::Execute(Event event) { + // TODO: use sPlayerbotDungeonSuggestionMgr + if (instances.empty()) { instances["Ragefire Chasm"] = 15; diff --git a/src/strategy/generic/EmoteStrategy.cpp b/src/strategy/generic/EmoteStrategy.cpp index a008f48e..57f400c9 100644 --- a/src/strategy/generic/EmoteStrategy.cpp +++ b/src/strategy/generic/EmoteStrategy.cpp @@ -7,22 +7,25 @@ void EmoteStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 1.0f), nullptr))); - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest what to do", 1.0f), nullptr))); - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest trade", 1.0f), nullptr))); + if (sPlayerbotAIConfig->randomBotEmote) + { + triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("emote", 1.0f), nullptr))); + triggers.push_back(new TriggerNode("receive text emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); + triggers.push_back(new TriggerNode("receive emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); + } + + if (sPlayerbotAIConfig->randomBotTalk) + { + triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest what to do", 1.0f), nullptr))); + triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest trade", 1.0f), nullptr))); + triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("talk", 1.0f), nullptr))); + } if (sPlayerbotAIConfig->randomBotSuggestDungeons) - { triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("suggest dungeon", 1.0f), nullptr))); - } if (sPlayerbotAIConfig->enableGreet) - { triggers.push_back(new TriggerNode("new player nearby", NextAction::array(0, new NextAction("greet", 1.0f), nullptr))); - } - triggers.push_back(new TriggerNode("seldom", NextAction::array(0, new NextAction("talk", 1.0f), nullptr))); - triggers.push_back(new TriggerNode("receive text emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); - triggers.push_back(new TriggerNode("receive emote", NextAction::array(0, new NextAction("emote", 10.0f), nullptr))); triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("rpg mount anim", 1.0f), nullptr))); } From 162229efe5c192bcb231a1a1a31a8f367db74e97 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sat, 27 Jul 2024 10:20:55 +0200 Subject: [PATCH 08/12] Fix spellid value to use forced enUS locale --- src/strategy/values/SpellIdValue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/values/SpellIdValue.cpp b/src/strategy/values/SpellIdValue.cpp index beb445f8..8cb8198f 100644 --- a/src/strategy/values/SpellIdValue.cpp +++ b/src/strategy/values/SpellIdValue.cpp @@ -190,7 +190,7 @@ uint32 VehicleSpellIdValue::Calculate() char firstSymbol = tolower(namepart[0]); int spellLength = wnamepart.length(); - int loc = bot->GetSession()->GetSessionDbcLocale(); + const int loc = LocaleConstant::LOCALE_enUS; Creature* creature = vehicleBase->ToCreature(); for (uint32 x = 0; x < MAX_CREATURE_SPELLS; ++x) From 00844985eb197933555c2447464772af9fa9d722 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sat, 27 Jul 2024 14:39:30 +0200 Subject: [PATCH 09/12] Fix chain link broken (random) unknown + dbc local enus force in some case (spell / chathelper etc) --- src/ChatHelper.cpp | 8 ++++---- src/RandomPlayerbotMgr.cpp | 4 ++-- src/strategy/actions/LfgActions.cpp | 2 +- src/strategy/actions/MovementActions.cpp | 6 +++--- src/strategy/actions/SuggestWhatToDoAction.h | 1 - src/strategy/actions/TellLosAction.cpp | 2 +- src/strategy/generic/EmoteStrategy.cpp | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/ChatHelper.cpp b/src/ChatHelper.cpp index 630bfca9..92daa117 100644 --- a/src/ChatHelper.cpp +++ b/src/ChatHelper.cpp @@ -288,7 +288,7 @@ std::string const ChatHelper::FormatQuest(Quest const* quest) std::string const ChatHelper::FormatGameobject(GameObject* go) { std::ostringstream out; - out << "|cFFFFFF00|Hfound:" << go->GetGUID().GetRawValue() << ":" << go->GetEntry() << ":" << "|h[" << go->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()) << "]|h|r"; + out << "|cFFFFFF00|Hfound:" << go->GetGUID().GetRawValue() << ":" << go->GetEntry() << ":" << "|h[" << go->GetNameForLocaleIdx(LOCALE_enUS) << "]|h|r"; return out.str(); } @@ -296,7 +296,7 @@ std::string const ChatHelper::FormatWorldobject(WorldObject* wo) { std::ostringstream out; out << "|cFFFFFF00|Hfound:" << wo->GetGUID().GetRawValue() << ":" << wo->GetEntry() << ":" << "|h["; - out << (wo->ToGameObject() ? ((GameObject*)wo)->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale()) : wo->GetNameForLocaleIdx(sWorld->GetDefaultDbcLocale())) << "]|h|r"; + out << (wo->ToGameObject() ? ((GameObject*)wo)->GetNameForLocaleIdx(LOCALE_enUS) : wo->GetNameForLocaleIdx(LOCALE_enUS)) << "]|h|r"; return out.str(); } @@ -327,7 +327,7 @@ std::string const ChatHelper::FormatWorldEntry(int32 entry) std::string const ChatHelper::FormatSpell(SpellInfo const* spellInfo) { std::ostringstream out; - out << "|cffffffff|Hspell:" << spellInfo->Id << "|h[" << spellInfo->SpellName[sWorld->GetDefaultDbcLocale()] << "]|h|r"; + out << "|cffffffff|Hspell:" << spellInfo->Id << "|h[" << spellInfo->SpellName[LOCALE_enUS] << "]|h|r"; return out.str(); } @@ -336,7 +336,7 @@ std::string const ChatHelper::FormatItem(ItemTemplate const* proto, uint32 count char color[32]; sprintf(color, "%x", ItemQualityColors[proto->Quality]); - // const std::string &name = sObjectMgr->GetItemLocale(proto->ItemId)->Name[sWorld->GetDefaultDbcLocale()]; + // const std::string &name = sObjectMgr->GetItemLocale(proto->ItemId)->Name[LOCALE_enUS]; std::ostringstream out; out << "|c" << color << "|Hitem:" << proto->ItemId diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 5e6891e5..639acd52 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1228,8 +1228,8 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& if (bot->GetLevel() <= 18 && (loc.GetMapId() != pInfo->mapId || dis > 10000.0f)) { continue; } - LocaleConstant locale = sWorld->GetDefaultDbcLocale(); - + + const LocaleConstant& locale = sWorld->GetDefaultDbcLocale(); LOG_INFO("playerbots", "Random teleporting bot {} (level {}) to Map: {} ({}) Zone: {} ({}) Area: {} ({}) {},{},{} ({}/{} locations)", bot->GetName().c_str(), bot->GetLevel(), map->GetId(), map->GetMapName(), diff --git a/src/strategy/actions/LfgActions.cpp b/src/strategy/actions/LfgActions.cpp index 4cb0bada..d7e7b865 100644 --- a/src/strategy/actions/LfgActions.cpp +++ b/src/strategy/actions/LfgActions.cpp @@ -105,7 +105,7 @@ bool LfgJoinAction::JoinLFG() const auto& botLevel = bot->GetLevel(); - /*LFG_TYPE_RANDOM on classic is 15-58 so bot over level 25 will never queue*/ + /*LFG_TYPE_RANDOM on classic is 15-58 so bot over level 25 will never queue*/ if (dungeon->MinLevel && (botLevel < dungeon->MinLevel || botLevel > dungeon->MaxLevel) || (botLevel > dungeon->MinLevel + 10 && dungeon->TypeID == LFG_TYPE_DUNGEON) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index ed002f53..9f7799b1 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1555,7 +1555,7 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj() return false; } std::ostringstream name; - name << spellInfo->SpellName[sWorld->GetDefaultDbcLocale()]; // << "] (aura)"; + name << spellInfo->SpellName[LOCALE_enUS]; // << "] (aura)"; if (FleePosition(dynOwner->GetPosition(), radius)) { if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); @@ -1613,7 +1613,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage() continue; } std::ostringstream name; - name << spellInfo->SpellName[sWorld->GetDefaultDbcLocale()]; // << "] (object)"; + name << spellInfo->SpellName[LOCALE_enUS]; // << "] (object)"; if (FleePosition(go->GetPosition(), radius)) { if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); @@ -1662,7 +1662,7 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() break; } std::ostringstream name; - name << triggerSpellInfo->SpellName[sWorld->GetDefaultDbcLocale()]; //<< "] (unit)"; + name << triggerSpellInfo->SpellName[LOCALE_enUS]; //<< "] (unit)"; if (FleePosition(unit->GetPosition(), radius)) { if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); diff --git a/src/strategy/actions/SuggestWhatToDoAction.h b/src/strategy/actions/SuggestWhatToDoAction.h index f3a57b89..46391ff2 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.h +++ b/src/strategy/actions/SuggestWhatToDoAction.h @@ -20,7 +20,6 @@ class SuggestWhatToDoAction : public InventoryAction protected: using Suggestion = std::function; std::vector suggestions; - void instance(); void specificQuest(); void grindReputation(); void grindMaterials(); diff --git a/src/strategy/actions/TellLosAction.cpp b/src/strategy/actions/TellLosAction.cpp index 688599ff..8917d2ed 100644 --- a/src/strategy/actions/TellLosAction.cpp +++ b/src/strategy/actions/TellLosAction.cpp @@ -138,4 +138,4 @@ bool TellExpectedDpsAction::Execute(Event event) float dps = AI_VALUE(float, "expected group dps"); botAI->TellMaster("Expected Group DPS: " + std::to_string(dps)); return true; -} \ No newline at end of file +} diff --git a/src/strategy/generic/EmoteStrategy.cpp b/src/strategy/generic/EmoteStrategy.cpp index 57f400c9..002fdc41 100644 --- a/src/strategy/generic/EmoteStrategy.cpp +++ b/src/strategy/generic/EmoteStrategy.cpp @@ -22,7 +22,7 @@ void EmoteStrategy::InitTriggers(std::vector& triggers) } if (sPlayerbotAIConfig->randomBotSuggestDungeons) - triggers.push_back(new TriggerNode("random", NextAction::array(0, new NextAction("suggest dungeon", 1.0f), nullptr))); + triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("suggest dungeon", 1.0f), nullptr))); if (sPlayerbotAIConfig->enableGreet) triggers.push_back(new TriggerNode("new player nearby", NextAction::array(0, new NextAction("greet", 1.0f), nullptr))); From 1fbd312d58f60e3d0c33824bf1a77b748276f1b2 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 01:02:54 +0200 Subject: [PATCH 10/12] Allow bot to talk in guild when they loot nice item, levelup, kill unique monsters --- src/strategy/actions/AutoLearnSpellAction.cpp | 17 +++++++++++++++- src/strategy/actions/LootAction.cpp | 17 ++++++++++++++++ src/strategy/actions/SayAction.cpp | 12 +++++------ src/strategy/actions/XpGainAction.cpp | 20 +++++++++++++++++++ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/strategy/actions/AutoLearnSpellAction.cpp b/src/strategy/actions/AutoLearnSpellAction.cpp index 3d5230ed..f2d7688f 100644 --- a/src/strategy/actions/AutoLearnSpellAction.cpp +++ b/src/strategy/actions/AutoLearnSpellAction.cpp @@ -6,6 +6,7 @@ #include "Event.h" #include "PlayerbotFactory.h" #include "Playerbots.h" +#include "GuildMgr.h" bool AutoLearnSpellAction::Execute(Event event) { @@ -27,7 +28,6 @@ bool AutoLearnSpellAction::Execute(Event event) return true; } - void AutoLearnSpellAction::LearnSpells(std::ostringstream* out) { if (sPlayerbotAIConfig->autoLearnTrainerSpells && sRandomPlayerbotMgr->IsRandomBot(bot))// || (!botAI->GetMaster() && sRandomPlayerbotMgr->IsRandomBot(bot))) @@ -35,6 +35,21 @@ void AutoLearnSpellAction::LearnSpells(std::ostringstream* out) if (sPlayerbotAIConfig->autoLearnQuestSpells && sRandomPlayerbotMgr->IsRandomBot(bot))// || (!botAI->GetMaster() && sRandomPlayerbotMgr->IsRandomBot(bot))) LearnQuestSpells(out); + + if (sPlayerbotAIConfig->randomBotTalk) + { + Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); + if (guild) + { + std::map placeholders; + placeholders["%level"] = std::to_string(bot->GetLevel()); + + if (urand(0, 3)) + guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Ding!", placeholders), LANG_UNIVERSAL); + else + guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Yay level %level!", placeholders), LANG_UNIVERSAL); + } + } } void AutoLearnSpellAction::LearnTrainerSpells(std::ostringstream* out) diff --git a/src/strategy/actions/LootAction.cpp b/src/strategy/actions/LootAction.cpp index f0526328..595ff16f 100644 --- a/src/strategy/actions/LootAction.cpp +++ b/src/strategy/actions/LootAction.cpp @@ -12,6 +12,7 @@ #include "PlayerbotAIConfig.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "GuildMgr.h" bool LootAction::Execute(Event event) { @@ -416,6 +417,22 @@ 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->randomBotTalk && bot->GetGuildId() && urand(0, 10) && proto->Quality >= ITEM_QUALITY_RARE) + { + Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); + + if (guild) + { + std::map placeholders; + placeholders["%name"] = chat->FormatItem(proto); + + if (urand(0, 3)) + guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Yay I looted %name!", placeholders), LANG_UNIVERSAL); + else + guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Guess who got a %name? Me!", placeholders), LANG_UNIVERSAL); + } + } + // std::ostringstream out; // out << "Looting " << chat->FormatItem(proto); // botAI->TellMasterNoFacing(out.str()); diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 67395b2e..e299736d 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -130,26 +130,26 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 // if we're just commanding bots around, don't respond... // first one is for exact word matches if (noReplyMsgs.find(msg) != noReplyMsgs.end()) { - std::ostringstream out; + /*std::ostringstream out; out << "DEBUG ChatReplyDo decided to ignore exact blocklist match" << msg; - bot->Say(out.str(), LANG_UNIVERSAL); + bot->Say(out.str(), LANG_UNIVERSAL);*/ return; } // second one is for partial matches like + or - where we change strats if (std::any_of(noReplyMsgParts.begin(), noReplyMsgParts.end(), [&msg](const std::string& part) { return msg.find(part) != std::string::npos; })) { - std::ostringstream out; + /*std::ostringstream out; out << "DEBUG ChatReplyDo decided to ignore partial blocklist match" << msg; - bot->Say(out.str(), LANG_UNIVERSAL); + bot->Say(out.str(), LANG_UNIVERSAL);*/ return; } if (std::any_of(noReplyMsgStarts.begin(), noReplyMsgStarts.end(), [&msg](const std::string& start) { return msg.find(start) == 0; // Check if the start matches the beginning of msg })) { - std::ostringstream out; + /*std::ostringstream out; out << "DEBUG ChatReplyDo decided to ignore start blocklist match" << msg; - bot->Say(out.str(), LANG_UNIVERSAL); + bot->Say(out.str(), LANG_UNIVERSAL);*/ return; } diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index 6dcca4a4..155cb752 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -6,6 +6,7 @@ #include "Event.h" #include "PlayerbotAIConfig.h" #include "Playerbots.h" +#include "GuildMgr.h" bool XpGainAction::Execute(Event event) { @@ -32,6 +33,25 @@ bool XpGainAction::Execute(Event event) p >> groupBonus; // 8 group bonus } + if (sPlayerbotAIConfig->randomBotTalk && bot->GetGuildId() && urand(0, 10)) + { + Creature* creature = botAI->GetCreature(guid); + if (creature && (creature->isElite() || creature->isWorldBoss() || creature->GetLevel() > 61 || creature->GetLevel() > bot->GetLevel() + 4)) + { + Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); + if (guild) + { + std::map placeholders; + placeholders["%name"] = creature->GetName(); + + if (urand(0, 3)) + guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Wow I just killed %name!", placeholders), LANG_UNIVERSAL); + else + guild->BroadcastToGuild(bot->GetSession(), false, BOT_TEXT2("Awesome that %name went down quickly!", placeholders), LANG_UNIVERSAL); + } + } + } + Unit* victim = nullptr; if (guid) victim = botAI->GetUnit(guid); From 5f60ded4198a7eba57ceb59f74e0619109166820 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 01:05:30 +0200 Subject: [PATCH 11/12] missing eTalkType enum on trade chat --- src/strategy/actions/SuggestWhatToDoAction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/actions/SuggestWhatToDoAction.cpp b/src/strategy/actions/SuggestWhatToDoAction.cpp index 428edd33..dc9241f8 100644 --- a/src/strategy/actions/SuggestWhatToDoAction.cpp +++ b/src/strategy/actions/SuggestWhatToDoAction.cpp @@ -480,6 +480,6 @@ bool SuggestTradeAction::Execute(Event event) placeholders["%item"] = chat->FormatItem(proto, count); placeholders["%gold"] = chat->formatMoney(price); - spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? 0x3C : 0, urand(0, 1), urand(0, 5)); + spam(BOT_TEXT2("suggest_sell", placeholders), urand(0, 1) ? eTalkType::Trade : 0, urand(0, 1), urand(0, 5)); return true; } From eec4776672c7b59a747f65a0b3ecc3a257111bf9 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sun, 28 Jul 2024 10:47:33 +0200 Subject: [PATCH 12/12] removed action error log --- src/strategy/Engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index dbb35c74..c4ca7394 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -172,7 +172,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) if (!action) { - LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(), botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel()); + //LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(), botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel()); LogAction("A:%s - UNKNOWN", actionNode->getName().c_str()); } else if (action->isUseful())