From d21d1e9b688c99c192ed8c78c5a3e594c0fb0687 Mon Sep 17 00:00:00 2001 From: Atidot3 Date: Sat, 27 Jul 2024 10:13:33 +0200 Subject: [PATCH] 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