diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 1396975b..88cffdce 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -49,7 +49,7 @@ AiPlayerbot.RandomBotMinLevel = 1 AiPlayerbot.RandomBotMaxLevel = 80 # Enable/Disable rotation of bots (randomly select a bot from the bots pool to go online and rotate them periodically) -# Need reset rndbot after changing the setting +# Need to reset rndbot after changing the setting (.playerbot rndbot reset) # default: 0 (disable, the online bots are fixed) AiPlayerbot.EnableRotation = 0 @@ -108,6 +108,10 @@ AiPlayerbot.RandombotStartingLevel = 5 # Server XP Rate * AiPlayerbot.KillXPRate AiPlayerbot.KillXPRate = 1 +# Disable death knight for bots login +# Need to reset rndbot after changing the setting (.playerbot rndbot reset) +AiPlayerbot.DisableDeathKnightLogin = 0 + # Specify percent of active bots # The default is 10. With 10% of all bots going active or inactive each minute. AiPlayerbot.BotActiveAlone = 100 @@ -213,8 +217,8 @@ AiPlayerbot.SyncQuestForPlayer = 0 AiPlayerbot.SyncLevelWithPlayers = 0 # Give free food to random bots -# Default: 1 (enabled) -AiPlayerbot.FreeFood = 1 +# Default: 0 (disabled) +AiPlayerbot.FreeFood = 0 # Bot automatically trains spells when talking to trainer (yes = train all available spells as long as the bot has the money, free = auto trains with no money cost, no = only list spells) # Only for random bots diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index d3ab8a0b..87b85830 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -281,11 +281,12 @@ bool PlayerbotAIConfig::Initialize() autoGearScoreLimit = sConfigMgr->GetOption("AiPlayerbot.AutoGearScoreLimit", 0); playerbotsXPrate = sConfigMgr->GetOption("AiPlayerbot.KillXPRate", 1); + disableDeathKnightLogin = sConfigMgr->GetOption("AiPlayerbot.DisableDeathKnightLogin", 0); botActiveAlone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAlone", 10); enablePrototypePerformanceDiff = sConfigMgr->GetOption("AiPlayerbot.EnablePrototypePerformanceDiff", false); - diffWithPlayer = sConfigMgr->GetOption("AiPlayerbot.DiffWithPlayer", 100); - diffEmpty = sConfigMgr->GetIntDefault("AiPlayerbot.DiffEmpty", 200); + diffWithPlayer = sConfigMgr->GetOption("AiPlayerbot.DiffWithPlayer", 100); + diffEmpty = sConfigMgr->GetOption("AiPlayerbot.DiffEmpty", 200); randombotsWalkingRPG = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG", false); randombotsWalkingRPGInDoors = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG.InDoors", false); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 4447fc17..5356bc49 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -176,6 +176,7 @@ class PlayerbotAIConfig bool randomBotShowCloak; bool disableRandomLevels; uint32 playerbotsXPrate; + bool disableDeathKnightLogin; uint32 botActiveAlone; uint32 enablePrototypePerformanceDiff; diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 80c4a1bc..14a11e32 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -9,6 +9,7 @@ #include "Battleground.h" #include "BattlegroundMgr.h" #include "CellImpl.h" +#include "DatabaseEnv.h" #include "Define.h" #include "FleeManager.h" #include "GameTime.h" @@ -26,6 +27,7 @@ #include "Random.h" #include "ServerFacade.h" #include "ChannelMgr.h" +#include "SharedDefines.h" #include "Unit.h" #include "World.h" #include "UpdateTime.h" @@ -480,7 +482,6 @@ uint32 RandomPlayerbotMgr::AddRandomBots() { Field* fields = result->Fetch(); ObjectGuid::LowType guid = fields[0].Get(); - if (GetEventValue(guid, "add")) continue; @@ -492,6 +493,18 @@ uint32 RandomPlayerbotMgr::AddRandomBots() if (std::find(currentBots.begin(), currentBots.end(), guid) != currentBots.end()) continue; + + if (sPlayerbotAIConfig->disableDeathKnightLogin) { + QueryResult result = CharacterDatabase.Query("Select class from characters where guid = {}", guid); + if (!result) { + continue; + } + Field* fields = result->Fetch(); + uint32 rClass = fields[0].Get(); + if (rClass == CLASS_DEATH_KNIGHT) { + continue; + } + } guids.push_back(guid); } while (result->NextRow()); @@ -1161,67 +1174,76 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "RandomTeleportByLocations"); - uint32 index = 0; + std::shuffle(std::begin(tlocs), std::end(tlocs), RandomEngine::Instance()); for (uint32 i = 0; i < tlocs.size(); i++) { - for (uint8 attemtps = 0; attemtps < 3; ++attemtps) - { - WorldLocation loc = tlocs[urand(0, tlocs.size() - 1)]; + WorldLocation loc = tlocs[i]; - float x = loc.GetPositionX(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0); - float y = loc.GetPositionY(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0); - float z = loc.GetPositionZ(); + float x = loc.GetPositionX(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0); + float y = loc.GetPositionY(); // + (attemtps > 0 ? urand(0, sPlayerbotAIConfig->grindDistance) - sPlayerbotAIConfig->grindDistance / 2 : 0); + float z = loc.GetPositionZ(); - Map* map = sMapMgr->FindMap(loc.GetMapId(), 0); - if (!map) - continue; - - AreaTableEntry const* zone = sAreaTableStore.LookupEntry(map->GetZoneId(bot->GetPhaseMask(), x, y, z)); - if (!zone) - continue; + Map* map = sMapMgr->FindMap(loc.GetMapId(), 0); + if (!map) + continue; + + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(map->GetZoneId(bot->GetPhaseMask(), x, y, z)); + if (!zone) + continue; - // Do not teleport to enemy zones if level is low - if (zone->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE) - continue; + // Do not teleport to enemy zones if level is low + if (zone->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE) + continue; - if (zone->team == 2 && bot->GetTeamId() == TEAM_HORDE) - continue; + if (zone->team == 2 && bot->GetTeamId() == TEAM_HORDE) + continue; - if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight())) - continue; + if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight())) + continue; - float ground = map->GetHeight(x, y, z + 0.5f); - if (ground <= INVALID_HEIGHT) - continue; + float ground = map->GetHeight(bot->GetPhaseMask(), x, y, z + 0.5f); + if (ground <= INVALID_HEIGHT) + continue; - z = 0.05f + ground; - - LOG_INFO("playerbots", "Random teleporting bot {} (level {}) to {} {},{},{} ({}/{} locations)", - bot->GetName().c_str(), bot->GetLevel(), zone->area_name[0], x, y, z, attemtps, tlocs.size()); - - if (hearth) - { - bot->SetHomebind(loc, zone->ID); - } - - bot->GetMotionMaster()->Clear(); - PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); - if (botAI) - botAI->Reset(true); - bot->TeleportTo(loc.GetMapId(), x, y, z, 0); - bot->SendMovementFlagUpdate(); - - if (pmo) - pmo->finish(); - - return; + z = 0.05f + ground; + PlayerInfo const* pInfo = sObjectMgr->GetPlayerInfo(bot->getRace(true), bot->getClass()); + float dis = loc.GetExactDist(pInfo->positionX, pInfo->positionY, pInfo->positionZ); + // yunfan: distance check for low level + if (bot->GetLevel() <= 4 && (loc.GetMapId() != pInfo->mapId || dis > 500.0f)) { + continue; } + if (bot->GetLevel() <= 10 && (loc.GetMapId() != pInfo->mapId || dis > 2500.0f)) { + continue; + } + if (bot->GetLevel() <= 18 && (loc.GetMapId() != pInfo->mapId || dis > 10000.0f)) { + continue; + } + + LOG_INFO("playerbots", "Random teleporting bot {} (level {}) to {} {},{},{} ({}/{} locations)", + bot->GetName().c_str(), bot->GetLevel(), zone->area_name[0], x, y, z, i + 1, tlocs.size()); + + if (hearth) + { + bot->SetHomebind(loc, zone->ID); + } + + bot->GetMotionMaster()->Clear(); + PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); + if (botAI) + botAI->Reset(true); + bot->TeleportTo(loc.GetMapId(), x, y, z, 0); + bot->SendMovementFlagUpdate(); + + if (pmo) + pmo->finish(); + + return; } if (pmo) pmo->finish(); - LOG_ERROR("playerbots", "Cannot teleport bot {} - no locations available", bot->GetName().c_str()); + LOG_ERROR("playerbots", "Cannot teleport bot {} - no locations available ({} locations)", bot->GetName().c_str(), tlocs.size()); } void RandomPlayerbotMgr::PrepareTeleportCache() @@ -1388,7 +1410,7 @@ void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot) uint32 level = bot->getLevel(); uint8 race = bot->getRace(); LOG_DEBUG("playerbots", "Random teleporting bot {} for level {} ({} locations available)", bot->GetName().c_str(), bot->GetLevel(), locsPerLevelCache[level].size()); - if (urand(0, 100) < sPlayerbotAIConfig->probTeleToBankers * 100) { + if (level > 10 && urand(0, 100) < sPlayerbotAIConfig->probTeleToBankers * 100) { RandomTeleport(bot, bankerLocsPerLevelCache[level], true); } else { RandomTeleport(bot, locsPerLevelCache[level]); diff --git a/src/strategy/priest/HealPriestStrategy.cpp b/src/strategy/priest/HealPriestStrategy.cpp index b4da45ea..53998500 100644 --- a/src/strategy/priest/HealPriestStrategy.cpp +++ b/src/strategy/priest/HealPriestStrategy.cpp @@ -36,12 +36,14 @@ void HealPriestStrategy::InitTriggers(std::vector& triggers) NextAction::array(0, new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 8), new NextAction("power word: shield on almost full health below", ACTION_MEDIUM_HEAL + 7), - new NextAction("prayer of healing on party", ACTION_MEDIUM_HEAL + 6), NULL))); triggers.push_back(new TriggerNode( "medium group heal occasion", - NextAction::array(0, new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 5), NULL))); + NextAction::array(0, + new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 6), + new NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 5), + nullptr))); triggers.push_back(new TriggerNode( "party member critical health", diff --git a/src/strategy/priest/HolyPriestStrategy.cpp b/src/strategy/priest/HolyPriestStrategy.cpp index a9e64204..27d3d1d7 100644 --- a/src/strategy/priest/HolyPriestStrategy.cpp +++ b/src/strategy/priest/HolyPriestStrategy.cpp @@ -60,13 +60,15 @@ void HolyHealPriestStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode( "group heal occasion", NextAction::array(0, - new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 8), - new NextAction("prayer of healing on party", ACTION_MEDIUM_HEAL + 6), + new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 8), NULL))); triggers.push_back(new TriggerNode( "medium group heal occasion", - NextAction::array(0, new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 5), NULL))); + NextAction::array(0, + new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 6), + new NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 5), + nullptr))); triggers.push_back(new TriggerNode( "party member critical health",