diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index bdf06435..3dac4031 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -63,8 +63,8 @@ AiPlayerbot.DeleteRandomBotArenaTeams = 0 # Change random bot has lower gear AiPlayerbot.RandomGearLoweringChance = 0 -# Chance random bot has max level on first randomize (default 0.15) -AiPlayerbot.RandomBotMaxLevelChance = 0 +# Chance random bot has max level on first randomize (default 0.0) +AiPlayerbot.RandomBotMaxLevelChance = 0.0 # Chance bot chooses RPG (Teleport to random camp for their level) instead of grinding AiPlayerbot.RandomBotRpgChance = 0.20 #unused now @@ -99,7 +99,7 @@ AiPlayerbot.BotActiveAlone = 100 # Set minimum level of randombots where gets enchants on items (Maxlevel + 1 to disable) # Default: 60 -AiPlayerbot.MinEnchantingBotLevel = 60 # unused now +AiPlayerbot.MinEnchantingBotLevel = 60 # Randombots checking players gear score level and deny the group invite if it's too low # Default: 1 (enabled) @@ -114,6 +114,37 @@ AiPlayerbot.RandomBotGroupNearby = 0 # Bots without a master will say their lines AiPlayerbot.RandomBotSayWithoutMaster = 0 +# Set RandomBotMaxLevel bots to RandomBotMinLevel or not +AiPlayerbot.DowngradeMaxLevelBot = 0 + +# Enable/Disable bot equipments persistence (stop random initialization) after certain level (EquipmentPersistenceLevel) +# default: 0 (disable) +AiPlayerbot.EquipmentPersistence = 0 + +# default: 80 +AiPlayerbot.EquipmentPersistenceLevel = 80 + +# Bot group invitation permission level (0 = GM only, 1 = accept based on level, 2 = always accept) +# default: 1 (accept based on level) +AiPlayerbot.GroupInvitationPermission = 1 + +# Enable/Disable bot revive and repair gear when summon +# default: 1 (enable) +AiPlayerbot.BotReviveWhenSummon = 1 + +# Non-GM player can only use init=auto to initialize bots based on their own level and gear score +# default: 0 (not allowed for non-gm player) +AiPlayerbot.AutoInitOnly = 0 + +# The upper limit ratio of bot equipment level for init=auto +# default: 1.0 (same with the player) +AiPlayerbot.AutoInitEquipLevelLimitRatio = 1.0 + +# Enable/Disable create bot by addclass command (0 = GM only, 1 = enable) +# default: 1 (enable) +AiPlayerbot.AddClassCommand = 1 + + # Automation # Bots keep looting when group loop method is free for all @@ -620,16 +651,6 @@ AiPlayerbot.BotCheats = "taxi" # Enables/Disables password to bot account AiPlayerbot.RandomBotRandomPassword = 0 -# Set RandomBotMaxLevel bots to RandomBotMinLevel or not -AiPlayerbot.DowngradeMaxLevelBot = 0 - -# Enable/Disable bot equipments persistence (stop random initialization) after certain level (EquipmentPersistenceLevel) -# default: 0 (disable) -AiPlayerbot.EquipmentPersistence = 0 - -# default: 80 -AiPlayerbot.EquipmentPersistenceLevel = 80 - ################################################################################## # # # Database Stuff # diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 930d0019..b4e67acf 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -312,6 +312,12 @@ bool PlayerbotAIConfig::Initialize() downgradeMaxLevelBot = sConfigMgr->GetOption("AiPlayerbot.DowngradeMaxLevelBot", true); equipmentPersistence = sConfigMgr->GetOption("AiPlayerbot.EquipmentPersistence", false); equipmentPersistenceLevel = sConfigMgr->GetOption("AiPlayerbot.EquipmentPersistenceLevel", 80); + groupInvitationPermission = sConfigMgr->GetOption("AiPlayerbot.GroupInvitationPermission", 1); + botReviveWhenSummon = sConfigMgr->GetOption("AiPlayerbot.BotReviveWhenSummon", true); + autoInitOnly = sConfigMgr->GetOption("AiPlayerbot.AutoInitOnly", false); + autoInitEquipLevelLimitRatio = sConfigMgr->GetOption("AiPlayerbot.AutoInitEquipLevelLimitRatio", 1.0); + addClassCommand = sConfigMgr->GetOption("AiPlayerbot.AddClassCommand", 1); + playerbotsXPrate = sConfigMgr->GetOption("AiPlayerbot.KillXPRate", 1); botActiveAlone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAlone", 10); randombotsWalkingRPG = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG", false); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 2f8bfdc9..0973f15a 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -170,6 +170,12 @@ class PlayerbotAIConfig bool downgradeMaxLevelBot; bool equipmentPersistence; int32 equipmentPersistenceLevel; + int32 groupInvitationPermission; + bool botReviveWhenSummon; + bool autoInitOnly; + float autoInitEquipLevelLimitRatio; + int32 addClassCommand; + std::string const GetTimestampStr(); bool hasLog(std::string const fileName) { return std::find(allowedLogFiles.begin(), allowedLogFiles.end(), fileName) != allowedLogFiles.end(); }; bool openLog(std::string const fileName, char const* mode = "a"); diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 838200bb..36973ed1 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -7,11 +7,13 @@ #include "Common.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" +#include "PlayerbotAIConfig.h" #include "PlayerbotMgr.h" #include "PlayerbotSecurity.h" #include "Playerbots.h" #include "PlayerbotDbStore.h" #include "PlayerbotFactory.h" +#include "SharedDefines.h" #include "WorldSession.h" #include "ChannelMgr.h" #include @@ -541,6 +543,9 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) { + if (master->GetSession()->GetSecurity() <= SEC_PLAYER && sPlayerbotAIConfig->autoInitOnly && cmd != "init=auto") { + return "The command is not allowed, use init=auto instead."; + } if (cmd == "init=white" || cmd == "init=common") { PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_NORMAL); @@ -573,10 +578,10 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje } else if (cmd == "init=auto") { - uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 10) * 1.1f; + uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore); factory.Randomize(false); - return "ok, gear score limit: " + std::to_string(mixedGearScore / 5) + "(for epic)"; + return "ok, gear score limit: " + std::to_string(mixedGearScore / (ITEM_QUALITY_EPIC + 1)) + "(for epic)"; } } @@ -724,6 +729,10 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg if (!strcmp(cmd, "addclass")) { + if (sPlayerbotAIConfig->addClassCommand == 0) { + messages.push_back("addclass command was disabled, please check your configuration"); + return messages; + } if (!charname) { messages.push_back("addclass: invalid CLASSNAME(warrior/paladin/hunter/rogue/priest/shaman/mage/warlock/druid/dk)"); return messages; diff --git a/src/PlayerbotSecurity.cpp b/src/PlayerbotSecurity.cpp index 8ba538e9..f99a6b52 100644 --- a/src/PlayerbotSecurity.cpp +++ b/src/PlayerbotSecurity.cpp @@ -4,6 +4,7 @@ #include "PlayerbotSecurity.h" #include "LFGMgr.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" PlayerbotSecurity::PlayerbotSecurity(Player* const bot) : bot(bot) @@ -58,7 +59,14 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea } } - if ((int32)bot->getLevel() - (int8)from->getLevel() > 5) + if (sPlayerbotAIConfig->groupInvitationPermission <= 0) { + if (reason) + *reason = PLAYERBOT_DENY_NONE; + + return PLAYERBOT_SECURITY_TALK; + } + + if (sPlayerbotAIConfig->groupInvitationPermission <= 1 && (int32)bot->getLevel() - (int8)from->getLevel() > 5) { if (!bot->GetGuildId() || bot->GetGuildId() != from->GetGuildId()) { diff --git a/src/strategy/actions/ReviveFromCorpseAction.cpp b/src/strategy/actions/ReviveFromCorpseAction.cpp index d55ecabc..d8ae366f 100644 --- a/src/strategy/actions/ReviveFromCorpseAction.cpp +++ b/src/strategy/actions/ReviveFromCorpseAction.cpp @@ -35,8 +35,8 @@ bool ReviveFromCorpseAction::Execute(Event event) if (!corpse) return false; - if (corpse->GetGhostTime() + bot->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP) > time(nullptr)) - return false; + // if (corpse->GetGhostTime() + bot->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP) > time(nullptr)) + // return false; if (master) { @@ -77,12 +77,12 @@ bool FindCorpseAction::Execute(Event event) if (!corpse) return false; - if (master) - { - if (!GET_PLAYERBOT_AI(master) && - sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "master target"), sPlayerbotAIConfig->farDistance)) - return false; - } + // if (master) + // { + // if (!GET_PLAYERBOT_AI(master) && + // sServerFacade->IsDistanceLessThan(AI_VALUE2(float, "distance", "master target"), sPlayerbotAIConfig->farDistance)) + // return false; + // } uint32 dCount = AI_VALUE(uint32, "death count"); diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index c00fd503..f0348ae4 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -7,6 +7,7 @@ #include "CellImpl.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" bool UseMeetingStoneAction::Execute(Event event) @@ -172,7 +173,7 @@ bool SummonAction::Teleport(Player* summoner, Player* player) if (summoner->IsWithinLOS(x, y, z)) { - if (bot->isDead() && botAI->GetMaster()->IsAlive()) + if (sPlayerbotAIConfig->botReviveWhenSummon && bot->isDead() && botAI->GetMaster()->IsAlive()) { bot->ResurrectPlayer(1.0f, false); bot->DurabilityRepairAll(false, 1.0f, false); diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index a6377e0b..911fa6da 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -726,7 +726,7 @@ class IsMountedTrigger : public Trigger class CorpseNearTrigger : public Trigger { public: - CorpseNearTrigger(PlayerbotAI* botAI) : Trigger(botAI, "corpse near", 10 * 1000) { } + CorpseNearTrigger(PlayerbotAI* botAI) : Trigger(botAI, "corpse near", 1 * 1000) { } bool IsActive() override; };