/* * Copyright (C) 2016+ AzerothCore , released under GNU AGPL v3 license, you may redistribute it * and/or modify it under version 3 of the License, or (at your option), any later version. */ #include "PlayerbotAIConfig.h" #include #include "Config.h" #include "NewRpgInfo.h" #include "PlayerbotDungeonSuggestionMgr.h" #include "PlayerbotFactory.h" #include "Playerbots.h" #include "RandomItemMgr.h" #include "RandomPlayerbotFactory.h" #include "RandomPlayerbotMgr.h" #include "Talentspec.h" template void LoadList(std::string const value, T& list) { std::vector ids = split(value, ','); for (std::vector::iterator i = ids.begin(); i != ids.end(); i++) { uint32 id = atoi((*i).c_str()); // if (!id) // continue; list.push_back(id); } } template void LoadSet(std::string const value, T& set) { std::vector ids = split(value, ','); for (std::vector::iterator i = ids.begin(); i != ids.end(); i++) { uint32 id = atoi((*i).c_str()); // if (!id) // continue; set.insert(id); } } template void LoadListString(std::string const value, T& list) { std::vector strings = split(value, ','); for (std::vector::iterator i = strings.begin(); i != strings.end(); i++) { std::string const string = *i; if (string.empty()) continue; list.push_back(string); } } bool PlayerbotAIConfig::Initialize() { LOG_INFO("server.loading", "Initializing mod-playerbots, based on AI Playerbots by ike and the original Playerbots by blueboy"); enabled = sConfigMgr->GetOption("AiPlayerbot.Enabled", true); if (!enabled) { LOG_INFO("server.loading", "Playerbots Module is disabled in playerbots.conf"); return false; } globalCoolDown = sConfigMgr->GetOption("AiPlayerbot.GlobalCooldown", 500); maxWaitForMove = sConfigMgr->GetOption("AiPlayerbot.MaxWaitForMove", 5000); disableMoveSplinePath = sConfigMgr->GetOption("AiPlayerbot.DisableMoveSplinePath", 0); maxMovementSearchTime = sConfigMgr->GetOption("AiPlayerbot.MaxMovementSearchTime", 3); expireActionTime = sConfigMgr->GetOption("AiPlayerbot.ExpireActionTime", 5000); dispelAuraDuration = sConfigMgr->GetOption("AiPlayerbot.DispelAuraDuration", 700); reactDelay = sConfigMgr->GetOption("AiPlayerbot.ReactDelay", 100); dynamicReactDelay = sConfigMgr->GetOption("AiPlayerbot.DynamicReactDelay", true); passiveDelay = sConfigMgr->GetOption("AiPlayerbot.PassiveDelay", 10000); repeatDelay = sConfigMgr->GetOption("AiPlayerbot.RepeatDelay", 2000); errorDelay = sConfigMgr->GetOption("AiPlayerbot.ErrorDelay", 100); rpgDelay = sConfigMgr->GetOption("AiPlayerbot.RpgDelay", 10000); sitDelay = sConfigMgr->GetOption("AiPlayerbot.SitDelay", 20000); returnDelay = sConfigMgr->GetOption("AiPlayerbot.ReturnDelay", 2000); lootDelay = sConfigMgr->GetOption("AiPlayerbot.LootDelay", 1000); minBotsForGreaterBuff = sConfigMgr->GetOption("AiPlayerbot.MinBotsForGreaterBuff", 3); rpWarningCooldown = sConfigMgr->GetOption("AiPlayerbot.RPWarningCooldown", 30); disabledWithoutRealPlayerLoginDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLoginDelay", 30); disabledWithoutRealPlayerLogoutDelay = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayerLogoutDelay", 300); farDistance = sConfigMgr->GetOption("AiPlayerbot.FarDistance", 20.0f); sightDistance = sConfigMgr->GetOption("AiPlayerbot.SightDistance", 100.0f); spellDistance = sConfigMgr->GetOption("AiPlayerbot.SpellDistance", 28.5f); shootDistance = sConfigMgr->GetOption("AiPlayerbot.ShootDistance", 5.0f); healDistance = sConfigMgr->GetOption("AiPlayerbot.HealDistance", 38.5f); lootDistance = sConfigMgr->GetOption("AiPlayerbot.LootDistance", 15.0f); fleeDistance = sConfigMgr->GetOption("AiPlayerbot.FleeDistance", 5.0f); aggroDistance = sConfigMgr->GetOption("AiPlayerbot.AggroDistance", 22.0f); tooCloseDistance = sConfigMgr->GetOption("AiPlayerbot.TooCloseDistance", 5.0f); meleeDistance = sConfigMgr->GetOption("AiPlayerbot.MeleeDistance", 0.75f); followDistance = sConfigMgr->GetOption("AiPlayerbot.FollowDistance", 1.5f); whisperDistance = sConfigMgr->GetOption("AiPlayerbot.WhisperDistance", 6000.0f); contactDistance = sConfigMgr->GetOption("AiPlayerbot.ContactDistance", 0.45f); aoeRadius = sConfigMgr->GetOption("AiPlayerbot.AoeRadius", 10.0f); rpgDistance = sConfigMgr->GetOption("AiPlayerbot.RpgDistance", 200.0f); grindDistance = sConfigMgr->GetOption("AiPlayerbot.GrindDistance", 75.0f); reactDistance = sConfigMgr->GetOption("AiPlayerbot.ReactDistance", 150.0f); criticalHealth = sConfigMgr->GetOption("AiPlayerbot.CriticalHealth", 25); lowHealth = sConfigMgr->GetOption("AiPlayerbot.LowHealth", 45); mediumHealth = sConfigMgr->GetOption("AiPlayerbot.MediumHealth", 65); almostFullHealth = sConfigMgr->GetOption("AiPlayerbot.AlmostFullHealth", 85); lowMana = sConfigMgr->GetOption("AiPlayerbot.LowMana", 15); mediumMana = sConfigMgr->GetOption("AiPlayerbot.MediumMana", 40); highMana = sConfigMgr->GetOption("AiPlayerbot.HighMana", 65); autoSaveMana = sConfigMgr->GetOption("AiPlayerbot.AutoSaveMana", true); saveManaThreshold = sConfigMgr->GetOption("AiPlayerbot.SaveManaThreshold", 60); autoAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.AutoAvoidAoe", true); maxAoeAvoidRadius = sConfigMgr->GetOption("AiPlayerbot.MaxAoeAvoidRadius", 15.0f); LoadSet>(sConfigMgr->GetOption("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810,29946"), aoeAvoidSpellWhitelist); tellWhenAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.TellWhenAvoidAoe", false); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.0f); incrementalGearInit = sConfigMgr->GetOption("AiPlayerbot.IncrementalGearInit", true); randomGearQualityLimit = sConfigMgr->GetOption("AiPlayerbot.RandomGearQualityLimit", 3); randomGearScoreLimit = sConfigMgr->GetOption("AiPlayerbot.RandomGearScoreLimit", 0); randomBotMinLevelChance = sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLevelChance", 0.1f); randomBotMaxLevelChance = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLevelChance", 0.1f); randomBotRpgChance = sConfigMgr->GetOption("AiPlayerbot.RandomBotRpgChance", 0.20f); iterationsPerTick = sConfigMgr->GetOption("AiPlayerbot.IterationsPerTick", 10); allowAccountBots = sConfigMgr->GetOption("AiPlayerbot.AllowAccountBots", true); allowGuildBots = sConfigMgr->GetOption("AiPlayerbot.AllowGuildBots", true); allowTrustedAccountBots = sConfigMgr->GetOption("AiPlayerbot.AllowTrustedAccountBots", true); disabledWithoutRealPlayer = sConfigMgr->GetOption("AiPlayerbot.DisabledWithoutRealPlayer", false); randomBotGuildNearby = sConfigMgr->GetOption("AiPlayerbot.RandomBotGuildNearby", false); randomBotInvitePlayer = sConfigMgr->GetOption("AiPlayerbot.RandomBotInvitePlayer", false); inviteChat = sConfigMgr->GetOption("AiPlayerbot.InviteChat", false); randomBotMapsAsString = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaps", "0,1,530,571"); LoadList>(randomBotMapsAsString, randomBotMaps); probTeleToBankers = sConfigMgr->GetOption("AiPlayerbot.ProbTeleToBankers", 0.25f); enableWeightTeleToCityBankers = sConfigMgr->GetOption("AiPlayerbot.EnableWeightTeleToCityBankers", false); weightTeleToStormwind = sConfigMgr->GetOption("AiPlayerbot.TeleToStormwindWeight", 2); weightTeleToIronforge = sConfigMgr->GetOption("AiPlayerbot.TeleToIronforgeWeight", 1); weightTeleToDarnassus = sConfigMgr->GetOption("AiPlayerbot.TeleToDarnassusWeight", 1); weightTeleToExodar = sConfigMgr->GetOption("AiPlayerbot.TeleToExodarWeight", 1); weightTeleToOrgrimmar = sConfigMgr->GetOption("AiPlayerbot.TeleToOrgrimmarWeight", 2); weightTeleToUndercity = sConfigMgr->GetOption("AiPlayerbot.TeleToUndercityWeight", 1); weightTeleToThunderBluff = sConfigMgr->GetOption("AiPlayerbot.TeleToThunderBluffWeight", 1); weightTeleToSilvermoonCity = sConfigMgr->GetOption("AiPlayerbot.TeleToSilvermoonCityWeight", 1); weightTeleToShattrathCity = sConfigMgr->GetOption("AiPlayerbot.TeleToShattrathCityWeight", 1); weightTeleToDalaran = sConfigMgr->GetOption("AiPlayerbot.TeleToDalaranWeight", 1); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestItems", "5175,5176,5177,5178,6948,11000,12382,13704,16309"), randomBotQuestItems); LoadList>(sConfigMgr->GetOption("AiPlayerbot.RandomBotSpellIds", "54197"), randomBotSpellIds); LoadList>( sConfigMgr->GetOption("AiPlayerbot.PvpProhibitedZoneIds", "2255,656,2361,2362,2363,976,35,2268,3425,392,541,1446,3828,3712,3738,3565," "3539,3623,4152,3988,4658,4284,4418,4436,4275,4323,4395,3703,4298,3951"), pvpProhibitedZoneIds); LoadList>( sConfigMgr->GetOption("AiPlayerbot.PvpProhibitedAreaIds", "976,35,392,2268,4161,4010,4317,4312,3649,3887,3958,3724,4080,3938,3754"), pvpProhibitedAreaIds); fastReactInBG = sConfigMgr->GetOption("AiPlayerbot.FastReactInBG", true); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestIds", "3802,5505,6502,7761,7848,10277,10285,11492,13188,13189,24499,24511,24710,24712"), randomBotQuestIds); LoadSet>( sConfigMgr->GetOption("AiPlayerbot.DisallowedGameObjects", "176213,17155,2656,74448,19020,3719,3658,3705,3706,105579,75293,2857," "179490,141596,160836,160845,179516,176224,181085,176112,128308,128403," "165739,165738,175245,175970,176325,176327,123329,2560"), disallowedGameObjects); botAutologin = sConfigMgr->GetOption("AiPlayerbot.BotAutologin", false); randomBotAutologin = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutologin", true); minRandomBots = sConfigMgr->GetOption("AiPlayerbot.MinRandomBots", 500); maxRandomBots = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBots", 500); randomBotUpdateInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotUpdateInterval", 20); randomBotCountChangeMinInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE); randomBotCountChangeMaxInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotCountChangeMaxInterval", 2 * HOUR); minRandomBotInWorldTime = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotInWorldTime", 2 * HOUR); maxRandomBotInWorldTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotInWorldTime", 14 * 24 * HOUR); minRandomBotRandomizeTime = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotRandomizeTime", 2 * HOUR); maxRandomBotRandomizeTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotRandomizeTime", 14 * 24 * HOUR); minRandomBotChangeStrategyTime = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotChangeStrategyTime", 30 * MINUTE); maxRandomBotChangeStrategyTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotChangeStrategyTime", 2 * HOUR); minRandomBotReviveTime = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotReviveTime", MINUTE); maxRandomBotReviveTime = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE); minRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR); maxRandomBotTeleportInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR); permanantlyInWorldTime = sConfigMgr->GetOption("AiPlayerbot.PermanantlyInWorldTime", 1 * YEAR); randomBotTeleportDistance = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotsPerInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotsPerInterval", 60); minRandomBotsPriceChangeInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR); maxRandomBotsPriceChangeInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotsPriceChangeInterval", 48 * HOUR); randomBotJoinLfg = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinLfg", true); restrictHealerDPS = sConfigMgr->GetOption("AiPlayerbot.HealerDPSMapRestriction", false); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RestrictedHealerDPSMaps", "33,34,36,43,47,48,70,90,109,129,209,229,230,329,349,389,429,1001,1004," "1007,269,540,542,543,545,546,547,552,553,554,555,556,557,558,560,585,574," "575,576,578,595,599,600,601,602,604,608,619,632,650,658,668,409,469,509," "531,532,534,544,548,550,564,565,580,249,533,603,615,616,624,631,649,724"), restrictedHealerDPSMaps); //////////////////////////// ICC EnableICCBuffs = sConfigMgr->GetOption("AiPlayerbot.EnableICCBuffs", true); //////////////////////////// CHAT enableBroadcasts = sConfigMgr->GetOption("AiPlayerbot.EnableBroadcasts", true); randomBotTalk = sConfigMgr->GetOption("AiPlayerbot.RandomBotTalk", false); randomBotEmote = sConfigMgr->GetOption("AiPlayerbot.RandomBotEmote", false); randomBotSuggestDungeons = sConfigMgr->GetOption("AiPlayerbot.RandomBotSuggestDungeons", true); randomBotSayWithoutMaster = sConfigMgr->GetOption("AiPlayerbot.RandomBotSayWithoutMaster", false); // broadcastChanceMaxValue is used in urand(1, broadcastChanceMaxValue) for broadcasts, // lowering it will increase the chance, setting it to 0 will disable broadcasts // for internal use, not intended to be change by the user broadcastChanceMaxValue = enableBroadcasts ? 30000 : 0; // all broadcast chances should be in range 1-broadcastChanceMaxValue, value of 0 will disable this particular // broadcast setting value to max does not guarantee the broadcast, as there are some internal randoms as well broadcastToGuildGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToGuildGlobalChance", 30000); broadcastToWorldGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToWorldGlobalChance", 30000); broadcastToGeneralGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToGeneralGlobalChance", 30000); broadcastToTradeGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToTradeGlobalChance", 30000); broadcastToLFGGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToLFGGlobalChance", 30000); broadcastToLocalDefenseGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToLocalDefenseGlobalChance", 30000); broadcastToWorldDefenseGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToWorldDefenseGlobalChance", 30000); broadcastToGuildRecruitmentGlobalChance = sConfigMgr->GetOption("AiPlayerbot.BroadcastToGuildRecruitmentGlobalChance", 30000); broadcastChanceLootingItemPoor = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemPoor", 30); broadcastChanceLootingItemNormal = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemNormal", 300); broadcastChanceLootingItemUncommon = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemUncommon", 10000); broadcastChanceLootingItemRare = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemRare", 20000); broadcastChanceLootingItemEpic = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemEpic", 30000); broadcastChanceLootingItemLegendary = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemLegendary", 30000); broadcastChanceLootingItemArtifact = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLootingItemArtifact", 30000); broadcastChanceQuestAccepted = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceQuestAccepted", 6000); broadcastChanceQuestUpdateObjectiveCompleted = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceQuestUpdateObjectiveCompleted", 300); broadcastChanceQuestUpdateObjectiveProgress = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceQuestUpdateObjectiveProgress", 300); broadcastChanceQuestUpdateFailedTimer = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceQuestUpdateFailedTimer", 300); broadcastChanceQuestUpdateComplete = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceQuestUpdateComplete", 1000); broadcastChanceQuestTurnedIn = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceQuestTurnedIn", 10000); broadcastChanceKillNormal = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillNormal", 30); broadcastChanceKillElite = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillElite", 300); broadcastChanceKillRareelite = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillRareelite", 3000); broadcastChanceKillWorldboss = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillWorldboss", 20000); broadcastChanceKillRare = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillRare", 10000); broadcastChanceKillUnknown = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillUnknown", 100); broadcastChanceKillPet = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillPet", 10); broadcastChanceKillPlayer = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceKillPlayer", 30); broadcastChanceLevelupGeneric = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLevelupGeneric", 20000); broadcastChanceLevelupTenX = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLevelupTenX", 30000); broadcastChanceLevelupMaxLevel = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceLevelupMaxLevel", 30000); broadcastChanceSuggestInstance = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestInstance", 5000); broadcastChanceSuggestQuest = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestQuest", 10000); broadcastChanceSuggestGrindMaterials = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestGrindMaterials", 5000); broadcastChanceSuggestGrindReputation = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestGrindReputation", 5000); broadcastChanceSuggestSell = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestSell", 300); broadcastChanceSuggestSomething = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestSomething", 30000); broadcastChanceSuggestSomethingToxic = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestSomethingToxic", 0); broadcastChanceSuggestToxicLinks = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestToxicLinks", 0); toxicLinksPrefix = sConfigMgr->GetOption("AiPlayerbot.ToxicLinksPrefix", "gnomes"); broadcastChanceSuggestThunderfury = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceSuggestThunderfury", 1); // does not depend on global chance broadcastChanceGuildManagement = sConfigMgr->GetOption("AiPlayerbot.BroadcastChanceGuildManagement", 30000); //////////////////////////// toxicLinksRepliesChance = sConfigMgr->GetOption("AiPlayerbot.ToxicLinksRepliesChance", 30); // 0-100 thunderfuryRepliesChance = sConfigMgr->GetOption("AiPlayerbot.ThunderfuryRepliesChance", 40); // 0-100 guildRepliesRate = sConfigMgr->GetOption("AiPlayerbot.GuildRepliesRate", 100); // 0-100 suggestDungeonsInLowerCaseRandomly = sConfigMgr->GetOption("AiPlayerbot.SuggestDungeonsInLowerCaseRandomly", false); ////////////////////////// !CHAT randomBotJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinBG", true); randomBotAutoJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBG", false); randomBotAutoJoinArenaBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7); randomBotAutoJoinICBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinICBrackets", "0,1"); randomBotAutoJoinEYBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2"); randomBotAutoJoinAVBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3"); randomBotAutoJoinABBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6"); randomBotAutoJoinWSBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7"); randomBotAutoJoinBGICCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGICCount", 0); randomBotAutoJoinBGEYCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGEYCount", 0); randomBotAutoJoinBGAVCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGAVCount", 0); randomBotAutoJoinBGABCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGABCount", 0); randomBotAutoJoinBGWSCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGWSCount", 0); randomBotAutoJoinBGRatedArena2v2Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count", 0); randomBotAutoJoinBGRatedArena3v3Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGRatedArena3v3Count", 0); randomBotAutoJoinBGRatedArena5v5Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGRatedArena5v5Count", 0); logInGroupOnly = sConfigMgr->GetOption("AiPlayerbot.LogInGroupOnly", true); logValuesPerTick = sConfigMgr->GetOption("AiPlayerbot.LogValuesPerTick", false); fleeingEnabled = sConfigMgr->GetOption("AiPlayerbot.FleeingEnabled", true); summonAtInnkeepersEnabled = sConfigMgr->GetOption("AiPlayerbot.SummonAtInnkeepersEnabled", true); randomBotMinLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLevel", 1); randomBotMaxLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLevel", 80); if (randomBotMaxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) randomBotMaxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); randomBotLoginAtStartup = sConfigMgr->GetOption("AiPlayerbot.RandomBotLoginAtStartup", true); randomBotTeleLowerLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleLowerLevel", 1); randomBotTeleHigherLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleHigherLevel", 3); openGoSpell = sConfigMgr->GetOption("AiPlayerbot.OpenGoSpell", 6477); // Zones for NewRpgStrategy teleportation brackets std::vector zoneIds = { // Classic WoW - Low-level zones 1, 12, 14, 85, 141, 215, 3430, 3524, // Classic WoW - Mid-level zones 17, 38, 40, 130, 148, 3433, 3525, // Classic WoW - High-level zones 10, 11, 44, 267, 331, 400, 406, // Classic WoW - Higher-level zones 3, 8, 15, 16, 33, 45, 47, 51, 357, 405, 440, // Classic WoW - Top-level zones 4, 28, 46, 139, 361, 490, 618, 1377, // The Burning Crusade - Zones 3483, 3518, 3519, 3520, 3521, 3522, 3523, 4080, // Wrath of the Lich King - Zones 65, 66, 67, 210, 394, 495, 2817, 3537, 3711, 4197 }; for (uint32 zoneId : zoneIds) { std::string setting = "AiPlayerbot.ZoneBracket." + std::to_string(zoneId); std::string value = sConfigMgr->GetOption(setting, ""); if (!value.empty()) { size_t commaPos = value.find(','); if (commaPos != std::string::npos) { uint32 minLevel = atoi(value.substr(0, commaPos).c_str()); uint32 maxLevel = atoi(value.substr(commaPos + 1).c_str()); zoneBrackets[zoneId] = std::make_pair(minLevel, maxLevel); } } } randomChangeMultiplier = sConfigMgr->GetOption("AiPlayerbot.RandomChangeMultiplier", 1.0); randomBotCombatStrategies = sConfigMgr->GetOption("AiPlayerbot.RandomBotCombatStrategies", ""); randomBotNonCombatStrategies = sConfigMgr->GetOption("AiPlayerbot.RandomBotNonCombatStrategies", ""); combatStrategies = sConfigMgr->GetOption("AiPlayerbot.CombatStrategies", ""); nonCombatStrategies = sConfigMgr->GetOption("AiPlayerbot.NonCombatStrategies", ""); applyInstanceStrategies = sConfigMgr->GetOption("AiPlayerbot.ApplyInstanceStrategies", true); commandPrefix = sConfigMgr->GetOption("AiPlayerbot.CommandPrefix", ""); commandSeparator = sConfigMgr->GetOption("AiPlayerbot.CommandSeparator", "\\\\"); commandServerPort = sConfigMgr->GetOption("AiPlayerbot.CommandServerPort", 8888); perfMonEnabled = sConfigMgr->GetOption("AiPlayerbot.PerfMonEnabled", false); useGroundMountAtMinLevel = sConfigMgr->GetOption("AiPlayerbot.UseGroundMountAtMinLevel", 20); useFastGroundMountAtMinLevel = sConfigMgr->GetOption("AiPlayerbot.UseFastGroundMountAtMinLevel", 40); useFlyMountAtMinLevel = sConfigMgr->GetOption("AiPlayerbot.UseFlyMountAtMinLevel", 60); useFastFlyMountAtMinLevel = sConfigMgr->GetOption("AiPlayerbot.UseFastFlyMountAtMinLevel", 70); // stagger bot flightpath takeoff delayMin = sConfigMgr->GetOption("AiPlayerbot.BotTaxiDelayMinMs", 350u); delayMax = sConfigMgr->GetOption("AiPlayerbot.BotTaxiDelayMaxMs", 5000u); gapMs = sConfigMgr->GetOption("AiPlayerbot.BotTaxiGapMs", 200u); gapJitterMs = sConfigMgr->GetOption("AiPlayerbot.BotTaxiGapJitterMs", 100u); LOG_INFO("server.loading", "Loading TalentSpecs..."); for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) { if (cls == 10) { continue; } for (uint32 spec = 0; spec < MAX_SPECNO; ++spec) { std::ostringstream os; os << "AiPlayerbot.PremadeSpecName." << cls << "." << spec; premadeSpecName[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), "", false); os.str(""); os.clear(); os << "AiPlayerbot.PremadeSpecGlyph." << cls << "." << spec; premadeSpecGlyph[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), "", false); std::vector splitSpecGlyph = split(premadeSpecGlyph[cls][spec], ','); for (std::string& split : splitSpecGlyph) { if (split.size() != 0) { parsedSpecGlyph[cls][spec].push_back(atoi(split.c_str())); } } for (uint32 level = 0; level < MAX_LEVEL; ++level) { std::ostringstream os; os << "AiPlayerbot.PremadeSpecLink." << cls << "." << spec << "." << level; premadeSpecLink[cls][spec][level] = sConfigMgr->GetOption(os.str().c_str(), "", false); parsedSpecLinkOrder[cls][spec][level] = ParseTempTalentsOrder(cls, premadeSpecLink[cls][spec][level]); } } for (uint32 spec = 0; spec < 3; ++spec) { for (uint32 points = 0; points < 21; ++points) { std::ostringstream os; os << "AiPlayerbot.PremadeHunterPetLink." << spec << "." << points; premadeHunterPetLink[spec][points] = sConfigMgr->GetOption(os.str().c_str(), "", false); parsedHunterPetLinkOrder[spec][points] = ParseTempPetTalentsOrder(spec, premadeHunterPetLink[spec][points]); } } for (uint32 spec = 0; spec < MAX_SPECNO; ++spec) { std::ostringstream os; os << "AiPlayerbot.RandomClassSpecProb." << cls << "." << spec; uint32 def; if (spec <= 1) def = 33; else if (spec == 2) def = 34; else def = 0; randomClassSpecProb[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), def, false); os.str(""); os.clear(); os << "AiPlayerbot.RandomClassSpecIndex." << cls << "." << spec; randomClassSpecIndex[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), spec, false); } } botCheats.clear(); LoadListString>(sConfigMgr->GetOption("AiPlayerbot.BotCheats", "food,taxi,raid"), botCheats); botCheatMask = 0; if (std::find(botCheats.begin(), botCheats.end(), "food") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::food; if (std::find(botCheats.begin(), botCheats.end(), "taxi") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::taxi; if (std::find(botCheats.begin(), botCheats.end(), "gold") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::gold; if (std::find(botCheats.begin(), botCheats.end(), "health") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::health; if (std::find(botCheats.begin(), botCheats.end(), "mana") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::mana; if (std::find(botCheats.begin(), botCheats.end(), "power") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::power; if (std::find(botCheats.begin(), botCheats.end(), "raid") != botCheats.end()) botCheatMask |= (uint32)BotCheatMask::raid; LoadListString>(sConfigMgr->GetOption("AiPlayerbot.AllowedLogFiles", ""), allowedLogFiles); LoadListString>(sConfigMgr->GetOption("AiPlayerbot.TradeActionExcludedPrefixes", ""), tradeActionExcludedPrefixes); worldBuffs.clear(); loadWorldBuff(); LOG_INFO("playerbots", "Loading World Buff Feature..."); randomBotAccountPrefix = sConfigMgr->GetOption("AiPlayerbot.RandomBotAccountPrefix", "rndbot"); randomBotAccountCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAccountCount", 0); deleteRandomBotAccounts = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotAccounts", false); randomBotGuildCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotGuildCount", 20); randomBotGuildSizeMax = sConfigMgr->GetOption("AiPlayerbot.RandomBotGuildSizeMax", 15); deleteRandomBotGuilds = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotGuilds", false); guildTaskEnabled = sConfigMgr->GetOption("AiPlayerbot.EnableGuildTasks", false); minGuildTaskChangeTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600); maxGuildTaskChangeTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600); minGuildTaskAdvertisementTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskAdvertisementTime", 300); maxGuildTaskAdvertisementTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600); minGuildTaskRewardTime = sConfigMgr->GetOption("AiPlayerbot.MinGuildTaskRewardTime", 300); maxGuildTaskRewardTime = sConfigMgr->GetOption("AiPlayerbot.MaxGuildTaskRewardTime", 3600); guildTaskAdvertCleanupTime = sConfigMgr->GetOption("AiPlayerbot.GuildTaskAdvertCleanupTime", 300); guildTaskKillTaskDistance = sConfigMgr->GetOption("AiPlayerbot.GuildTaskKillTaskDistance", 2000); targetPosRecalcDistance = sConfigMgr->GetOption("AiPlayerbot.TargetPosRecalcDistance", 0.1f); // cosmetics (by lidocain) randomBotShowCloak = sConfigMgr->GetOption("AiPlayerbot.RandomBotShowCloak", true); randomBotShowHelmet = sConfigMgr->GetOption("AiPlayerbot.RandomBotShowHelmet", true); // SPP switches enableGreet = sConfigMgr->GetOption("AiPlayerbot.EnableGreet", true); summonWhenGroup = sConfigMgr->GetOption("AiPlayerbot.SummonWhenGroup", true); randomBotFixedLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotFixedLevel", false); disableRandomLevels = sConfigMgr->GetOption("AiPlayerbot.DisableRandomLevels", false); randomBotRandomPassword = sConfigMgr->GetOption("AiPlayerbot.RandomBotRandomPassword", true); downgradeMaxLevelBot = sConfigMgr->GetOption("AiPlayerbot.DowngradeMaxLevelBot", true); equipmentPersistence = sConfigMgr->GetOption("AiPlayerbot.EquipmentPersistence", false); equipmentPersistenceLevel = sConfigMgr->GetOption("AiPlayerbot.EquipmentPersistenceLevel", 80); groupInvitationPermission = sConfigMgr->GetOption("AiPlayerbot.GroupInvitationPermission", 1); keepAltsInGroup = sConfigMgr->GetOption("AiPlayerbot.KeepAltsInGroup", false); allowSummonInCombat = sConfigMgr->GetOption("AiPlayerbot.AllowSummonInCombat", true); allowSummonWhenMasterIsDead = sConfigMgr->GetOption("AiPlayerbot.AllowSummonWhenMasterIsDead", true); allowSummonWhenBotIsDead = sConfigMgr->GetOption("AiPlayerbot.AllowSummonWhenBotIsDead", true); reviveBotWhenSummoned = sConfigMgr->GetOption("AiPlayerbot.ReviveBotWhenSummoned", 1); botRepairWhenSummon = sConfigMgr->GetOption("AiPlayerbot.BotRepairWhenSummon", true); autoInitOnly = sConfigMgr->GetOption("AiPlayerbot.AutoInitOnly", false); autoInitEquipLevelLimitRatio = sConfigMgr->GetOption("AiPlayerbot.AutoInitEquipLevelLimitRatio", 1.0); maxAddedBots = sConfigMgr->GetOption("AiPlayerbot.MaxAddedBots", 40); addClassCommand = sConfigMgr->GetOption("AiPlayerbot.AddClassCommand", 1); addClassAccountPoolSize = sConfigMgr->GetOption("AiPlayerbot.AddClassAccountPoolSize", 50); maintenanceCommand = sConfigMgr->GetOption("AiPlayerbot.MaintenanceCommand", 1); altMaintenanceAttunementQs = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceAttunementQuests", true); altMaintenanceBags = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceBags", true); altMaintenanceAmmo = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceAmmo", true); altMaintenanceFood = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceFood", true); altMaintenanceReagents = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceReagents", true); altMaintenanceConsumables = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceConsumables", true); altMaintenancePotions = sConfigMgr->GetOption("AiPlayerbot.AltMaintenancePotions", true); altMaintenanceTalentTree = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceTalentTree", true); altMaintenancePet = sConfigMgr->GetOption("AiPlayerbot.AltMaintenancePet", true); altMaintenancePetTalents = sConfigMgr->GetOption("AiPlayerbot.AltMaintenancePetTalents", true); altMaintenanceClassSpells = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceClassSpells", true); altMaintenanceAvailableSpells = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceAvailableSpells", true); altMaintenanceSkills = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceSkills", true); altMaintenanceReputation = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceReputation", true); altMaintenanceSpecialSpells = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceSpecialSpells", true); altMaintenanceMounts = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceMounts", true); altMaintenanceGlyphs = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceGlyphs", true); altMaintenanceKeyring = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceKeyring", true); altMaintenanceGemsEnchants = sConfigMgr->GetOption("AiPlayerbot.AltMaintenanceGemsEnchants", true); autoGearCommand = sConfigMgr->GetOption("AiPlayerbot.AutoGearCommand", 1); autoGearCommandAltBots = sConfigMgr->GetOption("AiPlayerbot.AutoGearCommandAltBots", 1); autoGearQualityLimit = sConfigMgr->GetOption("AiPlayerbot.AutoGearQualityLimit", 3); autoGearScoreLimit = sConfigMgr->GetOption("AiPlayerbot.AutoGearScoreLimit", 0); randomBotXPRate = sConfigMgr->GetOption("AiPlayerbot.RandomBotXPRate", 1.0); randomBotAllianceRatio = sConfigMgr->GetOption("AiPlayerbot.RandomBotAllianceRatio", 50); randomBotHordeRatio = sConfigMgr->GetOption("AiPlayerbot.RandomBotHordeRatio", 50); disableDeathKnightLogin = sConfigMgr->GetOption("AiPlayerbot.DisableDeathKnightLogin", 0); limitTalentsExpansion = sConfigMgr->GetOption("AiPlayerbot.LimitTalentsExpansion", 0); botActiveAlone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAlone", 100); BotActiveAloneForceWhenInRadius = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenInRadius", 150); BotActiveAloneForceWhenInZone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenInZone", 1); BotActiveAloneForceWhenInMap = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenInMap", 0); BotActiveAloneForceWhenIsFriend = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenIsFriend", 1); BotActiveAloneForceWhenInGuild = sConfigMgr->GetOption("AiPlayerbot.BotActiveAloneForceWhenInGuild", 1); botActiveAloneSmartScale = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScale", 1); botActiveAloneSmartScaleDiffLimitfloor = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitfloor", 50); botActiveAloneSmartScaleDiffLimitCeiling = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleDiffLimitCeiling", 200); botActiveAloneSmartScaleWhenMinLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMinLevel", 1); botActiveAloneSmartScaleWhenMaxLevel = sConfigMgr->GetOption("AiPlayerbot.botActiveAloneSmartScaleWhenMaxLevel", 80); randombotsWalkingRPG = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG", false); randombotsWalkingRPGInDoors = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG.InDoors", false); minEnchantingBotLevel = sConfigMgr->GetOption("AiPlayerbot.MinEnchantingBotLevel", 60); limitEnchantExpansion = sConfigMgr->GetOption("AiPlayerbot.LimitEnchantExpansion", 1); limitGearExpansion = sConfigMgr->GetOption("AiPlayerbot.LimitGearExpansion", 1); randombotStartingLevel = sConfigMgr->GetOption("AiPlayerbot.RandombotStartingLevel", 1); enablePeriodicOnlineOffline = sConfigMgr->GetOption("AiPlayerbot.EnablePeriodicOnlineOffline", false); enableRandomBotTrading = sConfigMgr->GetOption("AiPlayerbot.EnableRandomBotTrading", 1); periodicOnlineOfflineRatio = sConfigMgr->GetOption("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0); gearscorecheck = sConfigMgr->GetOption("AiPlayerbot.GearScoreCheck", false); randomBotPreQuests = sConfigMgr->GetOption("AiPlayerbot.PreQuests", false); // SPP automation freeMethodLoot = sConfigMgr->GetOption("AiPlayerbot.FreeMethodLoot", false); lootRollLevel = sConfigMgr->GetOption("AiPlayerbot.LootRollLevel", 1); autoPickReward = sConfigMgr->GetOption("AiPlayerbot.AutoPickReward", "yes"); autoEquipUpgradeLoot = sConfigMgr->GetOption("AiPlayerbot.AutoEquipUpgradeLoot", true); equipUpgradeThreshold = sConfigMgr->GetOption("AiPlayerbot.EquipUpgradeThreshold", 1.1f); twoRoundsGearInit = sConfigMgr->GetOption("AiPlayerbot.TwoRoundsGearInit", false); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", true); syncQuestForPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestForPlayer", false); dropObsoleteQuests = sConfigMgr->GetOption("AiPlayerbot.DropObsoleteQuests", true); autoTrainSpells = sConfigMgr->GetOption("AiPlayerbot.AutoTrainSpells", "yes"); autoPickTalents = sConfigMgr->GetOption("AiPlayerbot.AutoPickTalents", true); autoUpgradeEquip = sConfigMgr->GetOption("AiPlayerbot.AutoUpgradeEquip", false); hunterWolfPet = sConfigMgr->GetOption("AiPlayerbot.HunterWolfPet", 0); defaultPetStance = sConfigMgr->GetOption("AiPlayerbot.DefaultPetStance", 1); petChatCommandDebug = sConfigMgr->GetOption("AiPlayerbot.PetChatCommandDebug", 0); autoLearnTrainerSpells = sConfigMgr->GetOption("AiPlayerbot.AutoLearnTrainerSpells", true); autoLearnQuestSpells = sConfigMgr->GetOption("AiPlayerbot.AutoLearnQuestSpells", false); autoTeleportForLevel = sConfigMgr->GetOption("AiPlayerbot.AutoTeleportForLevel", false); autoDoQuests = sConfigMgr->GetOption("AiPlayerbot.AutoDoQuests", true); enableNewRpgStrategy = sConfigMgr->GetOption("AiPlayerbot.EnableNewRpgStrategy", true); RpgStatusProbWeight[RPG_WANDER_RANDOM] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderRandom", 15); RpgStatusProbWeight[RPG_WANDER_NPC] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.WanderNpc", 20); RpgStatusProbWeight[RPG_GO_GRIND] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.GoGrind", 15); RpgStatusProbWeight[RPG_GO_CAMP] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.GoCamp", 10); RpgStatusProbWeight[RPG_DO_QUEST] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.DoQuest", 60); RpgStatusProbWeight[RPG_TRAVEL_FLIGHT] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.TravelFlight", 15); RpgStatusProbWeight[RPG_REST] = sConfigMgr->GetOption("AiPlayerbot.RpgStatusProbWeight.Rest", 5); syncLevelWithPlayers = sConfigMgr->GetOption("AiPlayerbot.SyncLevelWithPlayers", false); randomBotGroupNearby = sConfigMgr->GetOption("AiPlayerbot.RandomBotGroupNearby", false); // arena randomBotArenaTeam2v2Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeam2v2Count", 10); randomBotArenaTeam3v3Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeam3v3Count", 10); randomBotArenaTeam5v5Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeam5v5Count", 5); deleteRandomBotArenaTeams = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotArenaTeams", false); randomBotArenaTeamMaxRating = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeamMaxRating", 2000); randomBotArenaTeamMinRating = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeamMinRating", 1000); selfBotLevel = sConfigMgr->GetOption("AiPlayerbot.SelfBotLevel", 1); RandomPlayerbotFactory::CreateRandomBots(); if (World::IsStopped()) { return true; } // Assign account types after accounts are created sRandomPlayerbotMgr->AssignAccountTypes(); if (sPlayerbotAIConfig->enabled) { sRandomPlayerbotMgr->Init(); } sRandomItemMgr->Init(); sRandomItemMgr->InitAfterAhBot(); sPlayerbotTextMgr->LoadBotTexts(); sPlayerbotTextMgr->LoadBotTextChance(); PlayerbotFactory::Init(); AiObjectContext::BuildAllSharedContexts(); if (sPlayerbotAIConfig->randomBotSuggestDungeons) { sPlayerbotDungeonSuggestionMgr->LoadDungeonSuggestions(); } excludedHunterPetFamilies.clear(); LoadList>(sConfigMgr->GetOption("AiPlayerbot.ExcludedHunterPetFamilies", ""), excludedHunterPetFamilies); LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", " mod-playerbots initialized "); LOG_INFO("server.loading", "---------------------------------------"); return true; } bool PlayerbotAIConfig::IsInRandomAccountList(uint32 id) { return find(randomBotAccounts.begin(), randomBotAccounts.end(), id) != randomBotAccounts.end(); } bool PlayerbotAIConfig::IsInRandomQuestItemList(uint32 id) { return find(randomBotQuestItems.begin(), randomBotQuestItems.end(), id) != randomBotQuestItems.end(); } bool PlayerbotAIConfig::IsPvpProhibited(uint32 zoneId, uint32 areaId) { return IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId) || IsInPvpProhibitedZone(areaId); } bool PlayerbotAIConfig::IsInPvpProhibitedZone(uint32 id) { return find(pvpProhibitedZoneIds.begin(), pvpProhibitedZoneIds.end(), id) != pvpProhibitedZoneIds.end(); } bool PlayerbotAIConfig::IsInPvpProhibitedArea(uint32 id) { return find(pvpProhibitedAreaIds.begin(), pvpProhibitedAreaIds.end(), id) != pvpProhibitedAreaIds.end(); } bool PlayerbotAIConfig::IsRestrictedHealerDPSMap(uint32 mapId) const { return restrictHealerDPS && std::find(restrictedHealerDPSMaps.begin(), restrictedHealerDPSMaps.end(), mapId) != restrictedHealerDPSMaps.end(); } std::string const PlayerbotAIConfig::GetTimestampStr() { time_t t = time(nullptr); tm* aTm = localtime(&t); // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) // HH hour (2 digits 00-23) // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) char buf[20]; snprintf(buf, 20, "%04d-%02d-%02d %02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); return std::string(buf); } bool PlayerbotAIConfig::openLog(std::string const fileName, char const* mode) { if (!hasLog(fileName)) return false; auto logFileIt = logFiles.find(fileName); if (logFileIt == logFiles.end()) { logFiles.insert(std::make_pair(fileName, std::make_pair(nullptr, false))); logFileIt = logFiles.find(fileName); } FILE* file = logFileIt->second.first; bool fileOpen = logFileIt->second.second; if (fileOpen) // close log file fclose(file); std::string m_logsDir = sConfigMgr->GetOption("LogsDir", "", false); if (!m_logsDir.empty()) { if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) m_logsDir.append("/"); } file = fopen((m_logsDir + fileName).c_str(), mode); fileOpen = true; logFileIt->second.first = file; logFileIt->second.second = fileOpen; return true; } void PlayerbotAIConfig::log(std::string const fileName, char const* str, ...) { if (!str) return; std::lock_guard guard(m_logMtx); if (!isLogOpen(fileName) && !openLog(fileName, "a")) return; FILE* file = logFiles.find(fileName)->second.first; va_list ap; va_start(ap, str); vfprintf(file, str, ap); fprintf(file, "\n"); va_end(ap); fflush(file); fflush(stdout); } void PlayerbotAIConfig::loadWorldBuff() { std::string matrix = sConfigMgr->GetOption("AiPlayerbot.WorldBuffMatrix", "", true); if (matrix.empty()) return; std::istringstream entryStream(matrix); std::string entry; while (std::getline(entryStream, entry, ';')) { entry.erase(0, entry.find_first_not_of(" \t\r\n")); entry.erase(entry.find_last_not_of(" \t\r\n") + 1); size_t firstColon = entry.find(':'); size_t secondColon = entry.find(':', firstColon + 1); if (firstColon == std::string::npos || secondColon == std::string::npos) { LOG_ERROR("playerbots", "Malformed entry: [{}]", entry); continue; } std::string metaPart = entry.substr(firstColon + 1, secondColon - firstColon - 1); std::string spellPart = entry.substr(secondColon + 1); std::vector ids; std::istringstream metaStream(metaPart); std::string token; while (std::getline(metaStream, token, ',')) { try { ids.push_back(static_cast(std::stoi(token))); } catch (...) { LOG_ERROR("playerbots", "Invalid meta token in [{}]", entry); break; } } if (ids.size() != 5) { LOG_ERROR("playerbots", "Entry [{}] has incomplete meta block", entry); continue; } std::istringstream spellStream(spellPart); while (std::getline(spellStream, token, ',')) { try { uint32 spellId = static_cast(std::stoi(token)); worldBuff wb = { spellId, ids[0], ids[1], ids[2], ids[3], ids[4] }; worldBuffs.push_back(wb); } catch (...) { LOG_ERROR("playerbots", "Invalid spell ID in [{}]", entry); } } } } static std::vector split(const std::string& str, const std::string& pattern) { std::vector res; if (str == "") return res; // Also add separators to string connections to facilitate intercepting the last paragraph. std::string strs = str + pattern; size_t pos = strs.find(pattern); while (pos != strs.npos) { std::string temp = strs.substr(0, pos); res.push_back(temp); // Remove the split string and split the remaining string strs = strs.substr(pos + 1, strs.size()); pos = strs.find(pattern); } return res; } std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 cls, std::string tab_link) { // check bad link uint32 classMask = 1 << (cls - 1); std::vector> res; std::vector tab_links = split(tab_link, "-"); std::map> spells; std::vector>> orders(3); for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); if (!talentTabInfo) continue; if ((classMask & talentTabInfo->ClassMask) == 0) continue; spells[talentTabInfo->tabpage].push_back(talentInfo); } for (int tab = 0; tab < 3; tab++) { if (tab_links.size() <= tab) { break; } std::sort(spells[tab].begin(), spells[tab].end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); for (int i = 0; i < tab_links[tab].size(); i++) { if (i >= spells[tab].size()) { break; } int lvl = tab_links[tab][i] - '0'; if (lvl == 0) continue; orders[tab].push_back({(uint32)tab, spells[tab][i]->Row, spells[tab][i]->Col, (uint32)lvl}); } } // sort by talent tab size std::sort(orders.begin(), orders.end(), [&](auto& lhs, auto& rhs) { return lhs.size() > rhs.size(); }); for (auto& order : orders) { res.insert(res.end(), order.begin(), order.end()); } return res; } std::vector> PlayerbotAIConfig::ParseTempPetTalentsOrder(uint32 spec, std::string tab_link) { // check bad link // uint32 classMask = 1 << (cls - 1); std::vector spells; std::vector> orders; for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); if (!talentTabInfo) continue; if (!((1 << spec) & talentTabInfo->petTalentMask)) continue; // skip some duplicate spells like dash/dive if (talentInfo->TalentID == 2201 || talentInfo->TalentID == 2208 || talentInfo->TalentID == 2219 || talentInfo->TalentID == 2203) continue; spells.push_back(talentInfo); } std::sort(spells.begin(), spells.end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; }); for (int i = 0; i < tab_link.size(); i++) { if (i >= spells.size()) { break; } int lvl = tab_link[i] - '0'; if (lvl == 0) continue; orders.push_back({spells[i]->Row, spells[i]->Col, (uint32)lvl}); } // sort by talent tab size std::sort(orders.begin(), orders.end(), [&](auto& lhs, auto& rhs) { return lhs.size() > rhs.size(); }); return orders; }