diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 8d7bf12e..884ab9f1 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -1460,7 +1460,7 @@ AiPlayerbot.BotActiveAlone = 100 # Specify smart scaling is enabled or not. # The default is 1. When enabled (smart) scales the 'BotActiveAlone' value. # Only when botLevel is between WhenMinLevel and WhenMaxLevel. -AiPlayerbot.botActiveAloneSmartScale = 1 +AiPlayerbot.botActiveAloneSmartScale = 0 AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel = 1 AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel = 80 diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 3c515ebb..b9c7ff60 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "AiFactory.h" #include "BudgetValues.h" @@ -2452,8 +2453,12 @@ bool PlayerbotAI::SayToWorld(const std::string& msg) bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chanId) { + // Checks whether the message or ChannelMgr is valid + if (msg.empty()) + return false; + ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId()); - if (!cMgr || msg.empty()) + if (!cMgr) return false; AreaTableEntry const* current_zone = GetCurrentZone(); @@ -2461,11 +2466,24 @@ bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chan return false; const auto current_str_zone = GetLocalizedAreaName(current_zone); + + std::mutex socialMutex; + std::lock_guard lock(socialMutex); // Blocking for thread safety when accessing SocialMgr + for (auto const& [key, channel] : cMgr->GetChannels()) { - // check for current zone - if (channel && channel->GetChannelId() == chanId) + // Checks if the channel pointer is valid + if (!channel) + continue; + + // Checks if the channel matches the specified ChatChannelId + if (channel->GetChannelId() == chanId) { + // If the channel name is empty, skip it to avoid access problems + if (channel->GetName().empty()) + continue; + + // Checks if the channel name contains the current zone const auto does_contains = channel->GetName().find(current_str_zone) != std::string::npos; if (chanId != ChatChannelId::LOOKING_FOR_GROUP && chanId != ChatChannelId::WORLD_DEFENSE && !does_contains) { @@ -2473,11 +2491,15 @@ bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chan } else if (chanId == ChatChannelId::LOOKING_FOR_GROUP || chanId == ChatChannelId::WORLD_DEFENSE) { - // check if capitals then return false if not + // Here you can add the capital check if necessary } - channel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); - return true; + // Final check to ensure the channel is correct before trying to say something + if (channel) + { + channel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL); + return true; + } } } diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 7bf16079..6c721024 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -465,7 +465,7 @@ bool PlayerbotAIConfig::Initialize() playerbotsXPrate = sConfigMgr->GetOption("AiPlayerbot.KillXPRate", 1); disableDeathKnightLogin = sConfigMgr->GetOption("AiPlayerbot.DisableDeathKnightLogin", 0); botActiveAlone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAlone", 100); - botActiveAloneSmartScale = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScale", 1); + botActiveAloneSmartScale = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScale", 0); botActiveAloneSmartScaleWhenMinLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1); botActiveAloneSmartScaleWhenMaxLevel = diff --git a/src/TravelMgr.cpp b/src/TravelMgr.cpp index af8bb12f..301802b6 100644 --- a/src/TravelMgr.cpp +++ b/src/TravelMgr.cpp @@ -18,6 +18,7 @@ #include "TransportMgr.h" #include "VMapFactory.h" #include "VMapMgr2.h" +#include "Corpse.h" WorldPosition::WorldPosition(std::string const str) { diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 791f0990..899b91b5 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -41,6 +41,7 @@ #include "Unit.h" #include "Vehicle.h" #include "WaypointMovementGenerator.h" +#include "Corpse.h" MovementAction::MovementAction(PlayerbotAI* botAI, std::string const name) : Action(botAI, name) { diff --git a/src/strategy/actions/QuestAction.cpp b/src/strategy/actions/QuestAction.cpp index 139033f1..13ed7bba 100644 --- a/src/strategy/actions/QuestAction.cpp +++ b/src/strategy/actions/QuestAction.cpp @@ -15,9 +15,13 @@ bool QuestAction::Execute(Event event) { ObjectGuid guid = event.getObject(); - Player* master = GetMaster(); + // Checks if the bot and botAI are valid + if (!bot || !botAI) + return false; + + // Sets guid based on bot or master target if (!guid) { if (!master) @@ -36,19 +40,27 @@ bool QuestAction::Execute(Event event) } bool result = false; + + // Check the nearest NPCs GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs"); - for (const auto npc : npcs) + for (const auto& npc : npcs) { Unit* unit = botAI->GetUnit(npc); if (unit && bot->GetDistance(unit) <= INTERACTION_DISTANCE) + { result |= ProcessQuests(unit); + } } + + // Checks the nearest game objects std::list gos = AI_VALUE(std::list, "nearest game objects"); - for (const auto go : gos) + for (const auto& go : gos) { GameObject* gameobj = botAI->GetGameObject(go); if (gameobj && bot->GetDistance(gameobj) <= INTERACTION_DISTANCE) + { result |= ProcessQuests(gameobj); + } } return result; diff --git a/src/strategy/actions/ReleaseSpiritAction.cpp b/src/strategy/actions/ReleaseSpiritAction.cpp index 382464e4..d15c7487 100644 --- a/src/strategy/actions/ReleaseSpiritAction.cpp +++ b/src/strategy/actions/ReleaseSpiritAction.cpp @@ -11,6 +11,7 @@ #include "ObjectGuid.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "Corpse.h" bool ReleaseSpiritAction::Execute(Event event) { diff --git a/src/strategy/actions/ReviveFromCorpseAction.cpp b/src/strategy/actions/ReviveFromCorpseAction.cpp index 4f522104..4f19a639 100644 --- a/src/strategy/actions/ReviveFromCorpseAction.cpp +++ b/src/strategy/actions/ReviveFromCorpseAction.cpp @@ -13,6 +13,7 @@ #include "Playerbots.h" #include "RandomPlayerbotMgr.h" #include "ServerFacade.h" +#include "Corpse.h" bool ReviveFromCorpseAction::Execute(Event event) { diff --git a/src/strategy/dungeons/wotlk/azjolnerub/AzjolNerubMultipliers.cpp b/src/strategy/dungeons/wotlk/azjolnerub/AzjolNerubMultipliers.cpp index 38cb9e9a..036d79c3 100644 --- a/src/strategy/dungeons/wotlk/azjolnerub/AzjolNerubMultipliers.cpp +++ b/src/strategy/dungeons/wotlk/azjolnerub/AzjolNerubMultipliers.cpp @@ -8,15 +8,17 @@ float KrikthirMultiplier::GetValue(Action* action) { + if (!botAI->IsDps(bot)) { return 1.0f; } + // Target is not findable from threat table using AI_VALUE2(), // therefore need to search manually for the unit name Unit* boss = nullptr; Unit* watcher = nullptr; - GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); - for (auto i = targets.begin(); i != targets.end(); ++i) + GuidVector targets = AI_VALUE(GuidVector, "possible targets no los"); + for (auto& target : targets) { - Unit* unit = botAI->GetUnit(*i); + Unit* unit = botAI->GetUnit(target); if (!unit) { continue; } switch (unit->GetEntry()) diff --git a/src/strategy/dungeons/wotlk/oculus/OculusMultipliers.cpp b/src/strategy/dungeons/wotlk/oculus/OculusMultipliers.cpp index 13490f93..023d5256 100644 --- a/src/strategy/dungeons/wotlk/oculus/OculusMultipliers.cpp +++ b/src/strategy/dungeons/wotlk/oculus/OculusMultipliers.cpp @@ -15,6 +15,8 @@ float MountingDrakeMultiplier::GetValue(Action* action) // It seems like this is due to moving/other actions being processed during the 0.5 secs. // If we suppress everything, they seem to mount properly. A bit of a ham-fisted solution but it works Player* master = botAI->GetMaster(); + if (!master) { return 1.0f; } + if (bot->GetMapId() != OCULUS_MAP_ID || !master->GetVehicleBase() || bot->GetVehicleBase()) { return 1.0f; } if (!dynamic_cast(action))