mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge branch 'master' into master
This commit is contained in:
@@ -728,7 +728,7 @@ AiPlayerbot.FastReactInBG = 1
|
|||||||
#
|
#
|
||||||
|
|
||||||
# All In seconds
|
# All In seconds
|
||||||
AiPlayerbot.RandomBotUpdateInterval = 1
|
AiPlayerbot.RandomBotUpdateInterval = 20
|
||||||
AiPlayerbot.RandomBotCountChangeMinInterval = 1800
|
AiPlayerbot.RandomBotCountChangeMinInterval = 1800
|
||||||
AiPlayerbot.RandomBotCountChangeMaxInterval = 7200
|
AiPlayerbot.RandomBotCountChangeMaxInterval = 7200
|
||||||
AiPlayerbot.MinRandomBotInWorldTime = 3600
|
AiPlayerbot.MinRandomBotInWorldTime = 3600
|
||||||
@@ -1460,7 +1460,7 @@ AiPlayerbot.BotActiveAlone = 100
|
|||||||
# Specify smart scaling is enabled or not.
|
# Specify smart scaling is enabled or not.
|
||||||
# The default is 1. When enabled (smart) scales the 'BotActiveAlone' value.
|
# The default is 1. When enabled (smart) scales the 'BotActiveAlone' value.
|
||||||
# Only when botLevel is between WhenMinLevel and WhenMaxLevel.
|
# Only when botLevel is between WhenMinLevel and WhenMaxLevel.
|
||||||
AiPlayerbot.botActiveAloneSmartScale = 1
|
AiPlayerbot.botActiveAloneSmartScale = 0
|
||||||
AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel = 1
|
AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel = 1
|
||||||
AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel = 80
|
AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel = 80
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "AiFactory.h"
|
#include "AiFactory.h"
|
||||||
#include "BudgetValues.h"
|
#include "BudgetValues.h"
|
||||||
@@ -31,7 +32,6 @@
|
|||||||
#include "ObjectGuid.h"
|
#include "ObjectGuid.h"
|
||||||
#include "PerformanceMonitor.h"
|
#include "PerformanceMonitor.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "GameTime.h"
|
|
||||||
#include "PlayerbotAIConfig.h"
|
#include "PlayerbotAIConfig.h"
|
||||||
#include "PlayerbotDbStore.h"
|
#include "PlayerbotDbStore.h"
|
||||||
#include "PlayerbotMgr.h"
|
#include "PlayerbotMgr.h"
|
||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
#include "UpdateTime.h"
|
#include "UpdateTime.h"
|
||||||
#include "Vehicle.h"
|
#include "Vehicle.h"
|
||||||
|
#include "GameTime.h"
|
||||||
|
|
||||||
std::vector<std::string> PlayerbotAI::dispel_whitelist = {
|
std::vector<std::string> PlayerbotAI::dispel_whitelist = {
|
||||||
"mutating injection",
|
"mutating injection",
|
||||||
@@ -240,7 +241,6 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (!GetMaster() || !GetMaster()->IsInWorld() || !GetMaster()->GetSession() ||
|
// if (!GetMaster() || !GetMaster()->IsInWorld() || !GetMaster()->GetSession() ||
|
||||||
// GetMaster()->GetSession()->isLogingOut()) {
|
// GetMaster()->GetSession()->isLogingOut()) {
|
||||||
// return;
|
// return;
|
||||||
@@ -303,7 +303,6 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
|
|||||||
// bot->GetMotionMaster()->Clear();
|
// bot->GetMotionMaster()->Clear();
|
||||||
// bot->GetMotionMaster()->MoveIdle();
|
// bot->GetMotionMaster()->MoveIdle();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// cheat options
|
// cheat options
|
||||||
if (bot->IsAlive() && ((uint32)GetCheat() > 0 || (uint32)sPlayerbotAIConfig->botCheatMask > 0))
|
if (bot->IsAlive() && ((uint32)GetCheat() > 0 || (uint32)sPlayerbotAIConfig->botCheatMask > 0))
|
||||||
{
|
{
|
||||||
@@ -2452,8 +2451,12 @@ bool PlayerbotAI::SayToWorld(const std::string& msg)
|
|||||||
|
|
||||||
bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chanId)
|
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());
|
ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId());
|
||||||
if (!cMgr || msg.empty())
|
if (!cMgr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
AreaTableEntry const* current_zone = GetCurrentZone();
|
AreaTableEntry const* current_zone = GetCurrentZone();
|
||||||
@@ -2461,11 +2464,24 @@ bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chan
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto current_str_zone = GetLocalizedAreaName(current_zone);
|
const auto current_str_zone = GetLocalizedAreaName(current_zone);
|
||||||
|
|
||||||
|
std::mutex socialMutex;
|
||||||
|
std::lock_guard<std::mutex> lock(socialMutex); // Blocking for thread safety when accessing SocialMgr
|
||||||
|
|
||||||
for (auto const& [key, channel] : cMgr->GetChannels())
|
for (auto const& [key, channel] : cMgr->GetChannels())
|
||||||
{
|
{
|
||||||
// check for current zone
|
// Checks if the channel pointer is valid
|
||||||
if (channel && channel->GetChannelId() == chanId)
|
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;
|
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)
|
if (chanId != ChatChannelId::LOOKING_FOR_GROUP && chanId != ChatChannelId::WORLD_DEFENSE && !does_contains)
|
||||||
{
|
{
|
||||||
@@ -2473,13 +2489,17 @@ bool PlayerbotAI::SayToChannel(const std::string& msg, const ChatChannelId& chan
|
|||||||
}
|
}
|
||||||
else if (chanId == ChatChannelId::LOOKING_FOR_GROUP || chanId == ChatChannelId::WORLD_DEFENSE)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Final check to ensure the channel is correct before trying to say something
|
||||||
|
if (channel)
|
||||||
|
{
|
||||||
channel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
|
channel->Say(bot->GetGUID(), msg.c_str(), LANG_UNIVERSAL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3929,10 +3949,7 @@ Player* PlayerbotAI::GetGroupMaster()
|
|||||||
|
|
||||||
uint32 PlayerbotAI::GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum, float cyclePerMin)
|
uint32 PlayerbotAI::GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum, float cyclePerMin)
|
||||||
{
|
{
|
||||||
//deterministic seed
|
uint32 randseed = rand32(); // Seed random number
|
||||||
uint8 seedNumber = uint8(typeNumber);
|
|
||||||
std::mt19937 rng(seedNumber);
|
|
||||||
uint32 randseed = rng(); // Seed random number
|
|
||||||
uint32 randnum = bot->GetGUID().GetCounter() + randseed; // Semi-random but fixed number for each bot.
|
uint32 randnum = bot->GetGUID().GetCounter() + randseed; // Semi-random but fixed number for each bot.
|
||||||
|
|
||||||
if (cyclePerMin > 0)
|
if (cyclePerMin > 0)
|
||||||
@@ -3942,7 +3959,8 @@ uint32 PlayerbotAI::GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum, fl
|
|||||||
randnum += cycle; // Make the random number cylce.
|
randnum += cycle; // Make the random number cylce.
|
||||||
}
|
}
|
||||||
|
|
||||||
randnum = (randnum % (maxNum + 1)); // Loops the randomnumber at maxNum. Bassically removes all the numbers above 99.
|
randnum =
|
||||||
|
(randnum % (maxNum + 1)); // Loops the randomnumber at maxNum. Bassically removes all the numbers above 99.
|
||||||
return randnum; // Now we have a number unique for each bot between 0 and maxNum that increases by cyclePerMin.
|
return randnum; // Now we have a number unique for each bot between 0 and maxNum that increases by cyclePerMin.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4080,73 +4098,83 @@ inline bool HasRealPlayers(Map* map)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivePiorityType PlayerbotAI::GetPriorityType(ActivityType activityType)
|
bool PlayerbotAI::AllowActive(ActivityType activityType)
|
||||||
{
|
{
|
||||||
// First priority - priorities disabled or has player master. Always active.
|
// only keep updating till initializing time has completed,
|
||||||
if (HasRealPlayerMaster())
|
// which prevents unneeded expensive GameTime calls.
|
||||||
return ActivePiorityType::HAS_REAL_PLAYER_MASTER;
|
if (_isBotInitializing)
|
||||||
|
{
|
||||||
|
_isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * 0.12;
|
||||||
|
|
||||||
// Self bot in a group with a bot master.
|
// no activity allowed during bot initialization
|
||||||
if (IsRealPlayer())
|
if (_isBotInitializing)
|
||||||
return ActivePiorityType::IS_REAL_PLAYER;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// General exceptions
|
||||||
|
if (activityType == PACKET_ACTIVITY)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has player master. Always active.
|
||||||
|
if (GetMaster())
|
||||||
|
{
|
||||||
|
PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(GetMaster());
|
||||||
|
if (!masterBotAI || masterBotAI->IsRealPlayer())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If grouped up
|
||||||
Group* group = bot->GetGroup();
|
Group* group = bot->GetGroup();
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||||
{
|
{
|
||||||
Player* member = gref->GetSource();
|
Player* member = gref->GetSource();
|
||||||
if (!member || (!member->IsInWorld() && member->GetMapId() != bot->GetMapId()))
|
if (!member || !member->IsInWorld() && member->GetMapId() != bot->GetMapId())
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (member == bot)
|
if (member == bot)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//IN_GROUP_WITH_REAL_PLAYER
|
|
||||||
PlayerbotAI* memberBotAI = GET_PLAYERBOT_AI(member);
|
PlayerbotAI* memberBotAI = GET_PLAYERBOT_AI(member);
|
||||||
|
{
|
||||||
if (!memberBotAI || memberBotAI->HasRealPlayerMaster())
|
if (!memberBotAI || memberBotAI->HasRealPlayerMaster())
|
||||||
return ActivePiorityType::IN_GROUP_WITH_REAL_PLAYER;
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//ALLOWED_PARTY_ACTIVITY
|
|
||||||
if (group->IsLeader(member->GetGUID()))
|
if (group->IsLeader(member->GetGUID()))
|
||||||
{
|
{
|
||||||
if (!memberBotAI->AllowActivity(PARTY_ACTIVITY))
|
if (!memberBotAI->AllowActivity(PARTY_ACTIVITY))
|
||||||
return ActivePiorityType::ALLOWED_PARTY_ACTIVITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//IN_INSTANCE
|
|
||||||
if (bot->IsBeingTeleported()) // Allow activity while teleportation.
|
|
||||||
return ActivePiorityType::IN_INSTANCE;
|
|
||||||
|
|
||||||
//IN_INSTANCE
|
|
||||||
if (!WorldPosition(bot).isOverworld())
|
|
||||||
return ActivePiorityType::IN_INSTANCE;
|
|
||||||
|
|
||||||
//IN_COMBAT
|
|
||||||
if (activityType != OUT_OF_PARTY_ACTIVITY && activityType != PACKET_ACTIVITY)
|
|
||||||
{
|
{
|
||||||
// Is in combat, defend yourself.
|
return false;
|
||||||
if (bot->IsInCombat())
|
}
|
||||||
return ActivePiorityType::IN_COMBAT;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IN_REACT_DISTANCE
|
// bg, raid, dungeon
|
||||||
if (HasPlayerNearby(sPlayerbotAIConfig->reactDistance))
|
if (!WorldPosition(bot).isOverworld())
|
||||||
return ActivePiorityType::IN_REACT_DISTANCE;
|
{
|
||||||
|
return true;
|
||||||
// NEARBY_PLAYER acitivity based on yards.
|
}
|
||||||
if (HasPlayerNearby(300.f))
|
|
||||||
return ActivePiorityType::NEARBY_PLAYER_300;
|
|
||||||
if (HasPlayerNearby(600.f))
|
|
||||||
return ActivePiorityType::NEARBY_PLAYER_600;
|
|
||||||
|
|
||||||
//if (sPlayerbotAIConfig->IsFreeAltBot(bot) || HasStrategy("travel once", BotState::BOT_STATE_NON_COMBAT))
|
|
||||||
// return ActivePiorityType::IS_ALWAYS_ACTIVE;
|
|
||||||
|
|
||||||
|
// In bg queue. Speed up bg queue/join.
|
||||||
if (bot->InBattlegroundQueue())
|
if (bot->InBattlegroundQueue())
|
||||||
return ActivePiorityType::IN_BG_QUEUE;
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool isLFG = false;
|
bool isLFG = false;
|
||||||
if (group)
|
if (group)
|
||||||
@@ -4161,122 +4189,82 @@ ActivePiorityType PlayerbotAI::GetPriorityType(ActivityType activityType)
|
|||||||
isLFG = true;
|
isLFG = true;
|
||||||
}
|
}
|
||||||
if (isLFG)
|
if (isLFG)
|
||||||
return ActivePiorityType::IN_LFG;
|
|
||||||
|
|
||||||
//IN_EMPTY_SERVER
|
|
||||||
if (sRandomPlayerbotMgr->GetPlayers().empty())
|
|
||||||
return ActivePiorityType::IN_EMPTY_SERVER;
|
|
||||||
|
|
||||||
//PLAYER_FRIEND (on friendlist of real player) (needs to be tested for stability)
|
|
||||||
/*for (auto& player : sRandomPlayerbotMgr->GetPlayers())
|
|
||||||
{
|
{
|
||||||
if (!player || !player->IsInWorld())
|
return true;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
if (player->GetSocial() &&
|
// Is in combat. Defend yourself.
|
||||||
bot->GetGUID() &&
|
if (activityType != OUT_OF_PARTY_ACTIVITY && activityType != PACKET_ACTIVITY)
|
||||||
player->GetSocial()->HasFriend(bot->GetGUID()))
|
{
|
||||||
return ActivePiorityType::PLAYER_FRIEND;
|
if (bot->IsInCombat())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player is near. Always active.
|
||||||
|
if (HasPlayerNearby(300.f))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// friends always active
|
||||||
|
|
||||||
|
// HasFriend sometimes cause crash, disable
|
||||||
|
// for (auto& player : sRandomPlayerbotMgr->GetPlayers())
|
||||||
|
// {
|
||||||
|
// if (!player || !player->IsInWorld() || !player->GetSocial() || !bot->GetGUID())
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// if (player->GetSocial()->HasFriend(bot->GetGUID()))
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/* if (activityType == OUT_OF_PARTY_ACTIVITY || activityType == GRIND_ACTIVITY)
|
||||||
|
{
|
||||||
|
if (HasManyPlayersNearby())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
//PLAYER_GUILD (contains real player)
|
// Bots don't need to move using PathGenerator.
|
||||||
if (IsInRealGuild())
|
if (activityType == DETAILED_MOVE_ACTIVITY)
|
||||||
return ActivePiorityType::PLAYER_GUILD;
|
|
||||||
|
|
||||||
|
|
||||||
//IN_NOT_ACTIVE_MAP
|
|
||||||
if (Map* map = bot->GetMap())
|
|
||||||
{
|
{
|
||||||
if (map->GetEntry()->IsWorldMap())
|
|
||||||
{
|
|
||||||
if (!HasRealPlayers(map))
|
|
||||||
return ActivePiorityType::IN_NOT_ACTIVE_MAP;
|
|
||||||
|
|
||||||
if (!map->IsGridLoaded(bot->GetPositionX(), bot->GetPositionY()))
|
|
||||||
return ActivePiorityType::IN_NOT_ACTIVE_MAP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//IN_ACTIVE_MAP
|
|
||||||
if (Map* map = bot->GetMap())
|
|
||||||
{
|
|
||||||
if (map->GetEntry()->IsWorldMap())
|
|
||||||
{
|
|
||||||
if (HasRealPlayers(map))
|
|
||||||
return ActivePiorityType::IN_ACTIVE_MAP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IN_VERY_ACTIVE_AREA
|
|
||||||
if (activityType == OUT_OF_PARTY_ACTIVITY || activityType == GRIND_ACTIVITY)
|
|
||||||
{
|
|
||||||
if (HasManyPlayersNearby(20, sPlayerbotAIConfig->sightDistance))
|
|
||||||
return ActivePiorityType::IN_VERY_ACTIVE_AREA;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ActivePiorityType::DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PlayerbotAI::AllowActive(ActivityType activityType)
|
|
||||||
{
|
|
||||||
// no activity allowed during bot initialization during first
|
|
||||||
// few minutes after starting the server based on maxRandomBots.
|
|
||||||
if (sRandomPlayerbotMgr->isBotInitializing())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// General exceptions
|
|
||||||
if (activityType == PACKET_ACTIVITY)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
uint32 botActiveAlonePerc = sPlayerbotAIConfig->botActiveAlone > 100 ? 100 : sPlayerbotAIConfig->botActiveAlone;
|
|
||||||
uint32 mod = botActiveAlonePerc;
|
|
||||||
ActivePiorityType type = GetPriorityType(activityType);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ActivePiorityType::HAS_REAL_PLAYER_MASTER:
|
|
||||||
case ActivePiorityType::IS_REAL_PLAYER:
|
|
||||||
case ActivePiorityType::IN_GROUP_WITH_REAL_PLAYER:
|
|
||||||
case ActivePiorityType::IN_INSTANCE:
|
|
||||||
case ActivePiorityType::IN_COMBAT:
|
|
||||||
case ActivePiorityType::IN_REACT_DISTANCE:
|
|
||||||
case ActivePiorityType::NEARBY_PLAYER_300:
|
|
||||||
case ActivePiorityType::IS_ALWAYS_ACTIVE:
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case ActivePiorityType::ALLOWED_PARTY_ACTIVITY:
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case ActivePiorityType::IN_BG_QUEUE:
|
|
||||||
case ActivePiorityType::IN_LFG:
|
|
||||||
case ActivePiorityType::PLAYER_FRIEND:
|
|
||||||
case ActivePiorityType::PLAYER_GUILD:
|
|
||||||
case ActivePiorityType::IN_ACTIVE_MAP:
|
|
||||||
case ActivePiorityType::IN_NOT_ACTIVE_MAP:
|
|
||||||
case ActivePiorityType::IN_EMPTY_SERVER:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bots do not need to move using PathGenerator.
|
if (sPlayerbotAIConfig->botActiveAlone <= 0)
|
||||||
//if (activityType == DETAILED_MOVE_ACTIVITY) return false;
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (sPlayerbotAIConfig->botActiveAlone >= 100 && !sPlayerbotAIConfig->botActiveAloneSmartScale)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// All exceptions are now done, below is the code to have a specified % of bots
|
// #######################################################################################
|
||||||
// active at all times. The default is 10%. With 0.1% of all bots going active
|
// All mandatory conditations are checked to be active or not, from here the remaining
|
||||||
// or inactive each minute.
|
// situations are usable for scaling when enabled.
|
||||||
if (sPlayerbotAIConfig->botActiveAlone <= 0) return false;
|
// #######################################################################################
|
||||||
|
|
||||||
|
// Below is code to have a specified % of bots active at all times.
|
||||||
|
// The default is 10%. With 0.1% of all bots going active or inactive each minute.
|
||||||
|
uint32 mod = sPlayerbotAIConfig->botActiveAlone > 100 ? 100 : sPlayerbotAIConfig->botActiveAlone;
|
||||||
if (sPlayerbotAIConfig->botActiveAloneSmartScale &&
|
if (sPlayerbotAIConfig->botActiveAloneSmartScale &&
|
||||||
bot->GetLevel() >= sPlayerbotAIConfig->botActiveAloneSmartScaleWhenMinLevel &&
|
bot->GetLevel() >= sPlayerbotAIConfig->botActiveAloneSmartScaleWhenMinLevel &&
|
||||||
bot->GetLevel() <= sPlayerbotAIConfig->botActiveAloneSmartScaleWhenMaxLevel)
|
bot->GetLevel() <= sPlayerbotAIConfig->botActiveAloneSmartScaleWhenMaxLevel)
|
||||||
{
|
{
|
||||||
mod = SmartScaleActivity(type, botActiveAlonePerc);
|
mod = AutoScaleActivity(mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ActivityNumber = GetFixedBotNumer(BotTypeNumber::ACTIVITY_TYPE_NUMBER, 100,
|
uint32 ActivityNumber =
|
||||||
botActiveAlonePerc * static_cast<float>(mod) / 100 * 0.01f);
|
GetFixedBotNumer(BotTypeNumber::ACTIVITY_TYPE_NUMBER, 100,
|
||||||
|
sPlayerbotAIConfig->botActiveAlone * static_cast<float>(mod) / 100 * 0.01f);
|
||||||
|
|
||||||
// The given percentage of bots should be active and rotate 1% of those active bots each minute.
|
return ActivityNumber <=
|
||||||
return ActivityNumber <= (botActiveAlonePerc * mod) / 100;
|
(sPlayerbotAIConfig->botActiveAlone * mod) /
|
||||||
|
100; // The given percentage of bots should be active and rotate 1% of those active bots each minute.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlayerbotAI::AllowActivity(ActivityType activityType, bool checkNow)
|
bool PlayerbotAI::AllowActivity(ActivityType activityType, bool checkNow)
|
||||||
@@ -4293,42 +4281,37 @@ bool PlayerbotAI::AllowActivity(ActivityType activityType, bool checkNow)
|
|||||||
return allowed;
|
return allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 PlayerbotAI::SmartScaleActivity(ActivePiorityType type, uint32 botActiveAlonePerc)
|
uint32 PlayerbotAI::AutoScaleActivity(uint32 mod)
|
||||||
{
|
{
|
||||||
uint32 maxDiff = sWorldUpdateTime.GetMaxUpdateTime();
|
uint32 maxDiff = sWorldUpdateTime.GetAverageUpdateTime();
|
||||||
if (maxDiff > 1000) return false;
|
|
||||||
switch (type)
|
if (maxDiff > 500) return 0;
|
||||||
|
if (maxDiff > 250)
|
||||||
{
|
{
|
||||||
case ActivePiorityType::IN_BG_QUEUE:
|
if (Map* map = bot->GetMap())
|
||||||
case ActivePiorityType::IN_LFG:
|
{
|
||||||
if (maxDiff > 100) return 80;
|
if (map->GetEntry()->IsWorldMap())
|
||||||
if (maxDiff > 100) return 90;
|
{
|
||||||
break;
|
if (!HasRealPlayers(map))
|
||||||
case ActivePiorityType::NEARBY_PLAYER_600:
|
{
|
||||||
if (maxDiff > 100) return 50;
|
return 0;
|
||||||
if (maxDiff > 50) return 75;
|
|
||||||
break;
|
|
||||||
case ActivePiorityType::PLAYER_FRIEND:
|
|
||||||
case ActivePiorityType::PLAYER_GUILD:
|
|
||||||
case ActivePiorityType::IN_ACTIVE_MAP:
|
|
||||||
if (maxDiff > 200) return 30;
|
|
||||||
if (maxDiff > 100) return 50;
|
|
||||||
if (maxDiff > 50) return 75;
|
|
||||||
break;
|
|
||||||
case ActivePiorityType::IN_VERY_ACTIVE_AREA:
|
|
||||||
case ActivePiorityType::IN_NOT_ACTIVE_MAP:
|
|
||||||
if (maxDiff > 100) return 30;
|
|
||||||
if (maxDiff > 50) return 50;
|
|
||||||
break;
|
|
||||||
case ActivePiorityType::IN_EMPTY_SERVER:
|
|
||||||
return 30;
|
|
||||||
default:
|
|
||||||
if (maxDiff > 200) return 30;
|
|
||||||
if (maxDiff > 100) return 50;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return botActiveAlonePerc;
|
if (!map->IsGridLoaded(bot->GetPositionX(), bot->GetPositionY()))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (mod * 1) / 10;
|
||||||
|
}
|
||||||
|
if (maxDiff > 200) return (mod * 3) / 10;
|
||||||
|
if (maxDiff > 150) return (mod * 5) / 10;
|
||||||
|
if (maxDiff > 100) return (mod * 6) / 10;
|
||||||
|
if (maxDiff > 75) return (mod * 9) / 10;
|
||||||
|
|
||||||
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlayerbotAI::IsOpposing(Player* player) { return IsOpposing(player->getRace(), bot->getRace()); }
|
bool PlayerbotAI::IsOpposing(Player* player) { return IsOpposing(player->getRace(), bot->getRace()); }
|
||||||
@@ -5438,29 +5421,15 @@ bool PlayerbotAI::CanMove()
|
|||||||
if (IsInVehicle() && !IsInVehicle(true))
|
if (IsInVehicle() && !IsInVehicle(true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (bot->isFrozen() ||
|
if (bot->isFrozen() || bot->IsPolymorphed() || (bot->isDead() && !bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) ||
|
||||||
bot->IsPolymorphed() ||
|
bot->IsBeingTeleported() || bot->isInRoots() || bot->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION) ||
|
||||||
(bot->isDead() && !bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) ||
|
bot->HasAuraType(SPELL_AURA_MOD_CONFUSE) || bot->IsCharmed() || bot->HasAuraType(SPELL_AURA_MOD_STUN) ||
|
||||||
bot->IsBeingTeleported() ||
|
bot->HasUnitState(UNIT_STATE_IN_FLIGHT) || bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
||||||
bot->isInRoots() ||
|
|
||||||
bot->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION) ||
|
|
||||||
bot->HasAuraType(SPELL_AURA_MOD_CONFUSE) ||
|
|
||||||
bot->IsCharmed() ||
|
|
||||||
bot->HasAuraType(SPELL_AURA_MOD_STUN) ||
|
|
||||||
bot->HasUnitState(UNIT_STATE_IN_FLIGHT) ||
|
|
||||||
bot->HasUnitState(UNIT_STATE_LOST_CONTROL))
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return bot->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLIGHT_MOTION_TYPE;
|
return bot->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLIGHT_MOTION_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlayerbotAI::IsTaxiFlying()
|
|
||||||
{
|
|
||||||
return bot->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
|
|
||||||
bot->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PlayerbotAI::IsInRealGuild()
|
bool PlayerbotAI::IsInRealGuild()
|
||||||
{
|
{
|
||||||
if (!bot->GetGuildId())
|
if (!bot->GetGuildId())
|
||||||
|
|||||||
@@ -241,30 +241,6 @@ enum class GuilderType : uint8
|
|||||||
VERY_LARGE = 250
|
VERY_LARGE = 250
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ActivePiorityType : uint8
|
|
||||||
{
|
|
||||||
IS_REAL_PLAYER = 0,
|
|
||||||
HAS_REAL_PLAYER_MASTER = 1,
|
|
||||||
IN_GROUP_WITH_REAL_PLAYER = 2,
|
|
||||||
IN_INSTANCE = 3,
|
|
||||||
IS_ALWAYS_ACTIVE = 4,
|
|
||||||
IN_COMBAT = 5,
|
|
||||||
IN_BG_QUEUE = 6,
|
|
||||||
IN_LFG = 7,
|
|
||||||
IN_REACT_DISTANCE = 8,
|
|
||||||
NEARBY_PLAYER_300 = 9,
|
|
||||||
NEARBY_PLAYER_600 = 10,
|
|
||||||
NEARBY_PLAYER_900 = 11,
|
|
||||||
PLAYER_FRIEND = 12,
|
|
||||||
PLAYER_GUILD = 13,
|
|
||||||
IN_VERY_ACTIVE_AREA = 14,
|
|
||||||
IN_ACTIVE_MAP = 15,
|
|
||||||
IN_NOT_ACTIVE_MAP = 16,
|
|
||||||
IN_EMPTY_SERVER = 17,
|
|
||||||
ALLOWED_PARTY_ACTIVITY = 18,
|
|
||||||
DEFAULT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ActivityType
|
enum ActivityType
|
||||||
{
|
{
|
||||||
GRIND_ACTIVITY = 1,
|
GRIND_ACTIVITY = 1,
|
||||||
@@ -274,8 +250,8 @@ enum ActivityType
|
|||||||
PACKET_ACTIVITY = 5,
|
PACKET_ACTIVITY = 5,
|
||||||
DETAILED_MOVE_ACTIVITY = 6,
|
DETAILED_MOVE_ACTIVITY = 6,
|
||||||
PARTY_ACTIVITY = 7,
|
PARTY_ACTIVITY = 7,
|
||||||
REACT_ACTIVITY = 8,
|
ALL_ACTIVITY = 8,
|
||||||
ALL_ACTIVITY = 9,
|
|
||||||
MAX_ACTIVITY_TYPE
|
MAX_ACTIVITY_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -549,10 +525,9 @@ public:
|
|||||||
bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance);
|
bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance);
|
||||||
bool HasPlayerNearby(float range = sPlayerbotAIConfig->reactDistance);
|
bool HasPlayerNearby(float range = sPlayerbotAIConfig->reactDistance);
|
||||||
bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig->sightDistance);
|
bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig->sightDistance);
|
||||||
ActivePiorityType GetPriorityType(ActivityType activityType);
|
|
||||||
bool AllowActive(ActivityType activityType);
|
bool AllowActive(ActivityType activityType);
|
||||||
bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false);
|
bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false);
|
||||||
uint32 SmartScaleActivity(ActivePiorityType type, uint32 botActiveAlonePerc);
|
uint32 AutoScaleActivity(uint32 mod);
|
||||||
|
|
||||||
// Check if player is safe to use.
|
// Check if player is safe to use.
|
||||||
bool IsSafe(Player* player);
|
bool IsSafe(Player* player);
|
||||||
@@ -579,7 +554,6 @@ public:
|
|||||||
void ResetJumpDestination() { jumpDestination = Position(); }
|
void ResetJumpDestination() { jumpDestination = Position(); }
|
||||||
|
|
||||||
bool CanMove();
|
bool CanMove();
|
||||||
bool IsTaxiFlying();
|
|
||||||
bool IsInRealGuild();
|
bool IsInRealGuild();
|
||||||
static std::vector<std::string> dispel_whitelist;
|
static std::vector<std::string> dispel_whitelist;
|
||||||
bool EqualLowercaseName(std::string s1, std::string s2);
|
bool EqualLowercaseName(std::string s1, std::string s2);
|
||||||
@@ -606,6 +580,7 @@ private:
|
|||||||
|
|
||||||
void HandleCommands();
|
void HandleCommands();
|
||||||
void HandleCommand(uint32 type, const std::string& text, Player& fromPlayer, const uint32 lang = LANG_UNIVERSAL);
|
void HandleCommand(uint32 type, const std::string& text, Player& fromPlayer, const uint32 lang = LANG_UNIVERSAL);
|
||||||
|
bool _isBotInitializing = true;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Player* bot;
|
Player* bot;
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ bool PlayerbotAIConfig::Initialize()
|
|||||||
randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true);
|
randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true);
|
||||||
minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50);
|
minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50);
|
||||||
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 200);
|
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 200);
|
||||||
randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 1);
|
randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", 20);
|
||||||
randomBotCountChangeMinInterval =
|
randomBotCountChangeMinInterval =
|
||||||
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
|
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
|
||||||
randomBotCountChangeMaxInterval =
|
randomBotCountChangeMaxInterval =
|
||||||
@@ -465,7 +465,7 @@ bool PlayerbotAIConfig::Initialize()
|
|||||||
playerbotsXPrate = sConfigMgr->GetOption<int32>("AiPlayerbot.KillXPRate", 1);
|
playerbotsXPrate = sConfigMgr->GetOption<int32>("AiPlayerbot.KillXPRate", 1);
|
||||||
disableDeathKnightLogin = sConfigMgr->GetOption<bool>("AiPlayerbot.DisableDeathKnightLogin", 0);
|
disableDeathKnightLogin = sConfigMgr->GetOption<bool>("AiPlayerbot.DisableDeathKnightLogin", 0);
|
||||||
botActiveAlone = sConfigMgr->GetOption<int32>("AiPlayerbot.BotActiveAlone", 100);
|
botActiveAlone = sConfigMgr->GetOption<int32>("AiPlayerbot.BotActiveAlone", 100);
|
||||||
botActiveAloneSmartScale = sConfigMgr->GetOption<bool>("AiPlayerbot.botActiveAloneSmartScale", 1);
|
botActiveAloneSmartScale = sConfigMgr->GetOption<bool>("AiPlayerbot.botActiveAloneSmartScale", 0);
|
||||||
botActiveAloneSmartScaleWhenMinLevel =
|
botActiveAloneSmartScaleWhenMinLevel =
|
||||||
sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1);
|
sConfigMgr->GetOption<uint32>("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1);
|
||||||
botActiveAloneSmartScaleWhenMaxLevel =
|
botActiveAloneSmartScaleWhenMaxLevel =
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "RandomPlayerbotMgr.h"
|
#include "RandomPlayerbotMgr.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "cs_playerbots.h"
|
#include "cs_playerbots.h"
|
||||||
|
#include "cmath"
|
||||||
|
|
||||||
class PlayerbotsDatabaseScript : public DatabaseScript
|
class PlayerbotsDatabaseScript : public DatabaseScript
|
||||||
{
|
{
|
||||||
@@ -96,6 +97,16 @@ public:
|
|||||||
{
|
{
|
||||||
sPlayerbotsMgr->AddPlayerbotData(player, false);
|
sPlayerbotsMgr->AddPlayerbotData(player, false);
|
||||||
sRandomPlayerbotMgr->OnPlayerLogin(player);
|
sRandomPlayerbotMgr->OnPlayerLogin(player);
|
||||||
|
|
||||||
|
if (sPlayerbotAIConfig->enabled || sPlayerbotAIConfig->randomBotAutologin)
|
||||||
|
{
|
||||||
|
std::string roundedTime =
|
||||||
|
std::to_string(std::ceil((sPlayerbotAIConfig->maxRandomBots * 0.13 / 60) * 10) / 10.0);
|
||||||
|
roundedTime = roundedTime.substr(0, roundedTime.find('.') + 2);
|
||||||
|
|
||||||
|
ChatHandler(player->GetSession()).SendSysMessage(
|
||||||
|
"Playerbots: bot initialization at server startup will require '" + roundedTime + "' minutes.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
#include "Unit.h"
|
#include "Unit.h"
|
||||||
#include "UpdateTime.h"
|
#include "UpdateTime.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "GameTime.h"
|
|
||||||
|
|
||||||
void PrintStatsThread() { sRandomPlayerbotMgr->PrintStats(); }
|
void PrintStatsThread() { sRandomPlayerbotMgr->PrintStats(); }
|
||||||
|
|
||||||
@@ -166,7 +165,6 @@ RandomPlayerbotMgr::RandomPlayerbotMgr() : PlayerbotHolder(), processTicks(0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BattlegroundData.clear();
|
BattlegroundData.clear();
|
||||||
|
|
||||||
BgCheckTimer = 0;
|
BgCheckTimer = 0;
|
||||||
LfgCheckTimer = 0;
|
LfgCheckTimer = 0;
|
||||||
PlayersCheckTimer = 0;
|
PlayersCheckTimer = 0;
|
||||||
@@ -293,6 +291,15 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
|
|||||||
if (!sPlayerbotAIConfig->randomBotAutologin || !sPlayerbotAIConfig->enabled)
|
if (!sPlayerbotAIConfig->randomBotAutologin || !sPlayerbotAIConfig->enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*if (sPlayerbotAIConfig->enablePrototypePerformanceDiff)
|
||||||
|
{
|
||||||
|
LOG_INFO("playerbots", "---------------------------------------");
|
||||||
|
LOG_INFO("playerbots",
|
||||||
|
"PROTOTYPE: Playerbot performance enhancements are active. Issues and instability may occur.");
|
||||||
|
LOG_INFO("playerbots", "---------------------------------------");
|
||||||
|
ScaleBotActivity();
|
||||||
|
}*/
|
||||||
|
|
||||||
uint32 maxAllowedBotCount = GetEventValue(0, "bot_count");
|
uint32 maxAllowedBotCount = GetEventValue(0, "bot_count");
|
||||||
if (!maxAllowedBotCount || (maxAllowedBotCount < sPlayerbotAIConfig->minRandomBots ||
|
if (!maxAllowedBotCount || (maxAllowedBotCount < sPlayerbotAIConfig->minRandomBots ||
|
||||||
maxAllowedBotCount > sPlayerbotAIConfig->maxRandomBots))
|
maxAllowedBotCount > sPlayerbotAIConfig->maxRandomBots))
|
||||||
@@ -310,17 +317,16 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
|
|||||||
|
|
||||||
uint32 onlineBotFocus = 75;
|
uint32 onlineBotFocus = 75;
|
||||||
if (onlineBotCount < (uint32)(sPlayerbotAIConfig->minRandomBots * 90 / 100))
|
if (onlineBotCount < (uint32)(sPlayerbotAIConfig->minRandomBots * 90 / 100))
|
||||||
{
|
|
||||||
onlineBotFocus = 25;
|
onlineBotFocus = 25;
|
||||||
|
|
||||||
|
// only keep updating till initializing time has completed,
|
||||||
|
// which prevents unneeded expensive GameTime calls.
|
||||||
|
if (_isBotInitializing)
|
||||||
|
{
|
||||||
|
_isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * 0.13;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBotInitializing(
|
uint32 updateIntervalTurboBoost = _isBotInitializing ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval;
|
||||||
//onlineBotCount < maxAllowedBotCount && <-- these fields are incorrect when using bot amount min/max are not equal.
|
|
||||||
GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * 0.12);
|
|
||||||
|
|
||||||
// when server is balancing bots then boost (decrease value of) the nextCheckDelay till
|
|
||||||
// onlineBotCount reached the AllowedBotCount.
|
|
||||||
uint32 updateIntervalTurboBoost = isBotInitializing() ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval;
|
|
||||||
SetNextCheckDelay(updateIntervalTurboBoost * (onlineBotFocus + 25) * 10);
|
SetNextCheckDelay(updateIntervalTurboBoost * (onlineBotFocus + 25) * 10);
|
||||||
|
|
||||||
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(
|
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(
|
||||||
@@ -404,6 +410,26 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//void RandomPlayerbotMgr::ScaleBotActivity()
|
||||||
|
//{
|
||||||
|
// float activityPercentage = getActivityPercentage();
|
||||||
|
//
|
||||||
|
// // if (activityPercentage >= 100.0f || activityPercentage <= 0.0f) pid.reset(); //Stop integer buildup during
|
||||||
|
// // max/min activity
|
||||||
|
//
|
||||||
|
// // % increase/decrease wanted diff , avg diff
|
||||||
|
// float activityPercentageMod = pid.calculate(
|
||||||
|
// sRandomPlayerbotMgr->GetPlayers().empty() ? sPlayerbotAIConfig->diffEmpty : sPlayerbotAIConfig->diffWithPlayer,
|
||||||
|
// sWorldUpdateTime.GetAverageUpdateTime());
|
||||||
|
//
|
||||||
|
// activityPercentage = activityPercentageMod + 50;
|
||||||
|
//
|
||||||
|
// // Cap the percentage between 0 and 100.
|
||||||
|
// activityPercentage = std::max(0.0f, std::min(100.0f, activityPercentage));
|
||||||
|
//
|
||||||
|
// setActivityPercentage(activityPercentage);
|
||||||
|
//}
|
||||||
|
|
||||||
uint32 RandomPlayerbotMgr::AddRandomBots()
|
uint32 RandomPlayerbotMgr::AddRandomBots()
|
||||||
{
|
{
|
||||||
uint32 maxAllowedBotCount = GetEventValue(0, "bot_count");
|
uint32 maxAllowedBotCount = GetEventValue(0, "bot_count");
|
||||||
@@ -993,7 +1019,6 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot)
|
|||||||
if (isLogginIn)
|
if (isLogginIn)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
uint32 randomTime;
|
uint32 randomTime;
|
||||||
if (!player)
|
if (!player)
|
||||||
{
|
{
|
||||||
@@ -1001,21 +1026,21 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot)
|
|||||||
randomTime = urand(1, 2);
|
randomTime = urand(1, 2);
|
||||||
SetEventValue(bot, "login", 1, randomTime);
|
SetEventValue(bot, "login", 1, randomTime);
|
||||||
|
|
||||||
uint32 updateIntervalTurboBoost = isBotInitializing() ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval;
|
uint32 randomBotUpdateInterval = _isBotInitializing ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval;
|
||||||
randomTime = urand(std::max(5, static_cast<int>(updateIntervalTurboBoost * 0.5)),
|
randomTime = urand(std::max(5, static_cast<int>(randomBotUpdateInterval * 0.5)),
|
||||||
std::max(12, static_cast<int>(updateIntervalTurboBoost * 2)));
|
std::max(12, static_cast<int>(randomBotUpdateInterval * 2)));
|
||||||
SetEventValue(bot, "update", 1, randomTime);
|
SetEventValue(bot, "update", 1, randomTime);
|
||||||
|
|
||||||
// do not randomize or teleport immediately after server start (prevent lagging)
|
// do not randomize or teleport immediately after server start (prevent lagging)
|
||||||
if (!GetEventValue(bot, "randomize"))
|
if (!GetEventValue(bot, "randomize"))
|
||||||
{
|
{
|
||||||
randomTime = urand(3, std::max(4, static_cast<int>(updateIntervalTurboBoost * 0.4)));
|
randomTime = urand(3, std::max(4, static_cast<int>(randomBotUpdateInterval * 0.4)));
|
||||||
ScheduleRandomize(bot, randomTime);
|
ScheduleRandomize(bot, randomTime);
|
||||||
}
|
}
|
||||||
if (!GetEventValue(bot, "teleport"))
|
if (!GetEventValue(bot, "teleport"))
|
||||||
{
|
{
|
||||||
randomTime = urand(std::max(7, static_cast<int>(updateIntervalTurboBoost * 0.7)),
|
randomTime = urand(std::max(7, static_cast<int>(randomBotUpdateInterval * 0.7)),
|
||||||
std::max(14, static_cast<int>(updateIntervalTurboBoost * 1.4)));
|
std::max(14, static_cast<int>(randomBotUpdateInterval * 1.4)));
|
||||||
ScheduleTeleport(bot, randomTime);
|
ScheduleTeleport(bot, randomTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,9 +1110,6 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot)
|
|||||||
|
|
||||||
bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
||||||
{
|
{
|
||||||
if (!player || !player->IsInWorld() || player->IsBeingTeleported() || player->GetSession()->isLogingOut())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint32 bot = player->GetGUID().GetCounter();
|
uint32 bot = player->GetGUID().GetCounter();
|
||||||
|
|
||||||
if (player->InBattleground())
|
if (player->InBattleground())
|
||||||
@@ -1242,7 +1264,9 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
|||||||
if (botAI)
|
if (botAI)
|
||||||
{
|
{
|
||||||
// ignore when in when taxi with boat/zeppelin and has players nearby
|
// ignore when in when taxi with boat/zeppelin and has players nearby
|
||||||
if (botAI->IsTaxiFlying() && botAI->HasPlayerNearby())
|
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
|
||||||
|
bot->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) &&
|
||||||
|
botAI->HasPlayerNearby())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ public:
|
|||||||
void LogPlayerLocation();
|
void LogPlayerLocation();
|
||||||
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
|
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
|
||||||
|
|
||||||
//private:
|
private:
|
||||||
|
//void ScaleBotActivity();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32 activeBots = 0;
|
uint32 activeBots = 0;
|
||||||
@@ -163,11 +164,11 @@ public:
|
|||||||
return BattleMastersCache;
|
return BattleMastersCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float getActivityMod() { return activityMod; }
|
||||||
|
float getActivityPercentage() { return activityMod * 100.0f; }
|
||||||
|
void setActivityPercentage(float percentage) { activityMod = percentage / 100.0f; }
|
||||||
static uint8 GetTeamClassIdx(bool isAlliance, uint8 claz) { return isAlliance * 20 + claz; }
|
static uint8 GetTeamClassIdx(bool isAlliance, uint8 claz) { return isAlliance * 20 + claz; }
|
||||||
|
|
||||||
bool isBotInitializing() const { return _isBotInitializing; }
|
|
||||||
void setBotInitializing(bool completed) { _isBotInitializing = completed; }
|
|
||||||
|
|
||||||
void PrepareAddclassCache();
|
void PrepareAddclassCache();
|
||||||
std::map<uint8, std::vector<ObjectGuid>> addclassCache;
|
std::map<uint8, std::vector<ObjectGuid>> addclassCache;
|
||||||
protected:
|
protected:
|
||||||
@@ -176,6 +177,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
// pid values are set in constructor
|
// pid values are set in constructor
|
||||||
botPID pid = botPID(1, 50, -50, 0, 0, 0);
|
botPID pid = botPID(1, 50, -50, 0, 0, 0);
|
||||||
|
float activityMod = 0.25;
|
||||||
bool _isBotInitializing = true;
|
bool _isBotInitializing = true;
|
||||||
uint32 GetEventValue(uint32 bot, std::string const event);
|
uint32 GetEventValue(uint32 bot, std::string const event);
|
||||||
std::string const GetEventData(uint32 bot, std::string const event);
|
std::string const GetEventData(uint32 bot, std::string const event);
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ bool LfgAcceptAction::Execute(Event event)
|
|||||||
LOG_INFO("playerbots", "Bot {} {}:{} <{}> is in combat and refuses LFG proposal {}",
|
LOG_INFO("playerbots", "Bot {} {}:{} <{}> is in combat and refuses LFG proposal {}",
|
||||||
bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(),
|
bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(),
|
||||||
bot->GetName().c_str(), id);
|
bot->GetName().c_str(), id);
|
||||||
sLFGMgr->UpdateProposal(id, bot->GetGUID(), false);
|
sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,13 @@
|
|||||||
bool QuestAction::Execute(Event event)
|
bool QuestAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
ObjectGuid guid = event.getObject();
|
ObjectGuid guid = event.getObject();
|
||||||
|
|
||||||
Player* master = GetMaster();
|
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 (!guid)
|
||||||
{
|
{
|
||||||
if (!master)
|
if (!master)
|
||||||
@@ -36,20 +40,28 @@ bool QuestAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
// Check the nearest NPCs
|
||||||
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
|
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
|
||||||
for (const auto npc : npcs)
|
for (const auto& npc : npcs)
|
||||||
{
|
{
|
||||||
Unit* unit = botAI->GetUnit(npc);
|
Unit* unit = botAI->GetUnit(npc);
|
||||||
if (unit && bot->GetDistance(unit) <= INTERACTION_DISTANCE)
|
if (unit && bot->GetDistance(unit) <= INTERACTION_DISTANCE)
|
||||||
|
{
|
||||||
result |= ProcessQuests(unit);
|
result |= ProcessQuests(unit);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks the nearest game objects
|
||||||
std::list<ObjectGuid> gos = AI_VALUE(std::list<ObjectGuid>, "nearest game objects");
|
std::list<ObjectGuid> gos = AI_VALUE(std::list<ObjectGuid>, "nearest game objects");
|
||||||
for (const auto go : gos)
|
for (const auto& go : gos)
|
||||||
{
|
{
|
||||||
GameObject* gameobj = botAI->GetGameObject(go);
|
GameObject* gameobj = botAI->GetGameObject(go);
|
||||||
if (gameobj && bot->GetDistance(gameobj) <= INTERACTION_DISTANCE)
|
if (gameobj && bot->GetDistance(gameobj) <= INTERACTION_DISTANCE)
|
||||||
|
{
|
||||||
result |= ProcessQuests(gameobj);
|
result |= ProcessQuests(gameobj);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto)
|
|||||||
|
|
||||||
uint8 possibleSlots = 1;
|
uint8 possibleSlots = 1;
|
||||||
uint8 dstSlot = botAI->FindEquipSlot(itemProto, NULL_SLOT, true);
|
uint8 dstSlot = botAI->FindEquipSlot(itemProto, NULL_SLOT, true);
|
||||||
|
|
||||||
if (dstSlot == EQUIPMENT_SLOT_FINGER1 || dstSlot == EQUIPMENT_SLOT_TRINKET1)
|
if (dstSlot == EQUIPMENT_SLOT_FINGER1 || dstSlot == EQUIPMENT_SLOT_TRINKET1)
|
||||||
{
|
{
|
||||||
possibleSlots = 2;
|
possibleSlots = 2;
|
||||||
|
|||||||
Reference in New Issue
Block a user