/* * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it * and/or modify it under version 2 of the License, or (at your option), any later version. */ #include "PlayerbotAIConfig.h" #include #include "Config.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 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 AI Playerbots by ike3, based on the original Playerbots by blueboy"); enabled = sConfigMgr->GetOption("AiPlayerbot.Enabled", true); if (!enabled) { LOG_INFO("server.loading", "AI Playerbots is Disabled in aiplayerbot.conf"); return false; } globalCoolDown = sConfigMgr->GetOption("AiPlayerbot.GlobalCooldown", 1500); 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", 7000); 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", 5000); rpgDelay = sConfigMgr->GetOption("AiPlayerbot.RpgDelay", 10000); sitDelay = sConfigMgr->GetOption("AiPlayerbot.SitDelay", 30000); returnDelay = sConfigMgr->GetOption("AiPlayerbot.ReturnDelay", 7000); lootDelay = sConfigMgr->GetOption("AiPlayerbot.LootDelay", 1000); farDistance = sConfigMgr->GetOption("AiPlayerbot.FarDistance", 20.0f); sightDistance = sConfigMgr->GetOption("AiPlayerbot.SightDistance", 75.0f); spellDistance = sConfigMgr->GetOption("AiPlayerbot.SpellDistance", 25.0f); shootDistance = sConfigMgr->GetOption("AiPlayerbot.ShootDistance", 25.0f); healDistance = sConfigMgr->GetOption("AiPlayerbot.HealDistance", 25.0f); lootDistance = sConfigMgr->GetOption("AiPlayerbot.LootDistance", 15.0f); fleeDistance = sConfigMgr->GetOption("AiPlayerbot.FleeDistance", 7.5f); 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.5f); aoeRadius = sConfigMgr->GetOption("AiPlayerbot.AoeRadius", 5.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", 20); 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); tellWhenAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.TellWhenAvoidAoe", true); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.0f); randomGearQualityLimit = sConfigMgr->GetOption("AiPlayerbot.RandomGearQualityLimit", 3); randomGearScoreLimit = sConfigMgr->GetOption("AiPlayerbot.RandomGearScoreLimit", 0); randomBotMaxLevelChance = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLevelChance", 0.15f); randomBotRpgChance = sConfigMgr->GetOption("AiPlayerbot.RandomBotRpgChance", 0.20f); iterationsPerTick = sConfigMgr->GetOption("AiPlayerbot.IterationsPerTick", 100); allowGuildBots = sConfigMgr->GetOption("AiPlayerbot.AllowGuildBots", true); randomBotGuildNearby = sConfigMgr->GetOption("AiPlayerbot.RandomBotGuildNearby", false); randomBotInvitePlayer = sConfigMgr->GetOption("AiPlayerbot.RandomBotInvitePlayer", false); inviteChat = sConfigMgr->GetOption("AiPlayerbot.InviteChat", false); allowPlayerBots = sConfigMgr->GetOption("AiPlayerbot.AllowPlayerBots", false); randomBotMapsAsString = sConfigMgr->GetOption("AiPlayerbot.RandomBotMaps", "0,1,530,571"); LoadList>(randomBotMapsAsString, randomBotMaps); probTeleToBankers = sConfigMgr->GetOption("AiPlayerbot.ProbTeleToBankers", 0.25f); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestItems", "6948,5175,5176,5177,5178,16309,12382,13704,11000"), 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"), pvpProhibitedZoneIds); LoadList>(sConfigMgr->GetOption("AiPlayerbot.PvpProhibitedAreaIds", "976,35"), pvpProhibitedAreaIds); fastReactInBG = sConfigMgr->GetOption("AiPlayerbot.FastReactInBG", true); LoadList>( sConfigMgr->GetOption("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761"), randomBotQuestIds); botAutologin = sConfigMgr->GetOption("AiPlayerbot.BotAutologin", false); randomBotAutologin = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutologin", true); minRandomBots = sConfigMgr->GetOption("AiPlayerbot.MinRandomBots", 50); maxRandomBots = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBots", 200); randomBotUpdateInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotUpdateInterval", MINUTE); 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", 12 * 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); randomBotInWorldWithRotationDisabled = sConfigMgr->GetOption("AiPlayerbot.RandomBotInWorldWithRotationDisabled", 1 * YEAR); randomBotTeleportDistance = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotsPerInterval = sConfigMgr->GetOption("AiPlayerbot.RandomBotsPerInterval", MINUTE); minRandomBotsPriceChangeInterval = sConfigMgr->GetOption("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR); maxRandomBotsPriceChangeInterval = sConfigMgr->GetOption("AiPlayerbot.MaxRandomBotsPriceChangeInterval", 48 * HOUR); randomBotJoinLfg = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinLfg", 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); randomBotAutoJoinWarsongBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWarsongBracket", 14); randomBotAutoJoinArenaBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7); randomBotAutoJoinBGWarsongCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGWarsongCount", 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); randomBotLoginAtStartup = sConfigMgr->GetOption("AiPlayerbot.RandomBotLoginAtStartup", true); randomBotTeleLowerLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleLowerLevel", 3); randomBotTeleHigherLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotTeleHigherLevel", 1); openGoSpell = sConfigMgr->GetOption("AiPlayerbot.OpenGoSpell", 6477); randomChangeMultiplier = sConfigMgr->GetOption("AiPlayerbot.RandomChangeMultiplier", 1.0); randomBotCombatStrategies = sConfigMgr->GetOption("AiPlayerbot.RandomBotCombatStrategies", "-threat"); randomBotNonCombatStrategies = sConfigMgr->GetOption("AiPlayerbot.RandomBotNonCombatStrategies", ""); combatStrategies = sConfigMgr->GetOption("AiPlayerbot.CombatStrategies", "+custom::say"); nonCombatStrategies = sConfigMgr->GetOption("AiPlayerbot.NonCombatStrategies", "+custom::say,+return"); 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); LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", " Loading TalentSpecs "); LOG_INFO("server.loading", "---------------------------------------"); 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", "taxi"), botCheats); botCheatMask = 0; 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; LoadListString>(sConfigMgr->GetOption("AiPlayerbot.AllowedLogFiles", ""), allowedLogFiles); worldBuffs.clear(); for (uint32 factionId = 0; factionId < 3; factionId++) { for (uint32 classId = 0; classId < MAX_CLASSES; classId++) { for (uint32 minLevel = 0; minLevel < MAX_LEVEL; minLevel++) { for (uint32 maxLevel = 0; maxLevel < MAX_LEVEL; maxLevel++) { loadWorldBuf(factionId, classId, minLevel, maxLevel); } } } } randomBotAccountPrefix = sConfigMgr->GetOption("AiPlayerbot.RandomBotAccountPrefix", "rndbot"); randomBotAccountCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAccountCount", 200); deleteRandomBotAccounts = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotAccounts", false); randomBotGuildCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotGuildCount", 20); deleteRandomBotGuilds = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotGuilds", false); guildTaskEnabled = sConfigMgr->GetOption("AiPlayerbot.EnableGuildTasks", true); 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); 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); maxAddedBotsPerClass = sConfigMgr->GetOption("AiPlayerbot.MaxAddedBotsPerClass", 10); addClassCommand = sConfigMgr->GetOption("AiPlayerbot.AddClassCommand", 1); addClassAccountPoolSize = sConfigMgr->GetOption("AiPlayerbot.AddClassAccountPoolSize", 50); maintenanceCommand = sConfigMgr->GetOption("AiPlayerbot.MaintenanceCommand", 1); autoGearCommand = sConfigMgr->GetOption("AiPlayerbot.AutoGearCommand", 1); autoGearQualityLimit = sConfigMgr->GetOption("AiPlayerbot.AutoGearQualityLimit", 3); autoGearScoreLimit = sConfigMgr->GetOption("AiPlayerbot.AutoGearScoreLimit", 0); playerbotsXPrate = sConfigMgr->GetOption("AiPlayerbot.KillXPRate", 1); disableDeathKnightLogin = sConfigMgr->GetOption("AiPlayerbot.DisableDeathKnightLogin", 0); botActiveAlone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAlone", 10); enablePrototypePerformanceDiff = sConfigMgr->GetOption("AiPlayerbot.EnablePrototypePerformanceDiff", false); diffWithPlayer = sConfigMgr->GetOption("AiPlayerbot.DiffWithPlayer", 100); diffEmpty = sConfigMgr->GetOption("AiPlayerbot.DiffEmpty", 200); 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", 5); enableRotation = sConfigMgr->GetOption("AiPlayerbot.EnableRotation", false); rotationPoolSize = sConfigMgr->GetOption("AiPlayerbot.RotationPoolSize", 500); gearscorecheck = sConfigMgr->GetOption("AiPlayerbot.GearScoreCheck", false); randomBotPreQuests = sConfigMgr->GetOption("AiPlayerbot.PreQuests", true); // 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); autoTrainSpells = sConfigMgr->GetOption("AiPlayerbot.AutoTrainSpells", "yes"); autoPickTalents = sConfigMgr->GetOption("AiPlayerbot.AutoPickTalents", true); autoUpgradeEquip = sConfigMgr->GetOption("AiPlayerbot.AutoUpgradeEquip", false); autoLearnTrainerSpells = sConfigMgr->GetOption("AiPlayerbot.AutoLearnTrainerSpells", true); autoLearnQuestSpells = sConfigMgr->GetOption("AiPlayerbot.AutoLearnQuestSpells", false); autoTeleportForLevel = sConfigMgr->GetOption("AiPlayerbot.AutoTeleportForLevel", false); autoDoQuests = sConfigMgr->GetOption("AiPlayerbot.AutoDoQuests", false); syncLevelWithPlayers = sConfigMgr->GetOption("AiPlayerbot.SyncLevelWithPlayers", false); freeFood = sConfigMgr->GetOption("AiPlayerbot.FreeFood", true); randomBotGroupNearby = sConfigMgr->GetOption("AiPlayerbot.RandomBotGroupNearby", true); // 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 (sPlayerbotAIConfig->addClassCommand) sRandomPlayerbotMgr->PrepareAddclassCache(); if (World::IsStopped()) { return true; } sRandomItemMgr->Init(); sRandomItemMgr->InitAfterAhBot(); sPlayerbotTextMgr->LoadBotTexts(); sPlayerbotTextMgr->LoadBotTextChance(); PlayerbotFactory::Init(); if (!sPlayerbotAIConfig->autoDoQuests) { LOG_INFO("server.loading", "Loading Quest Detail Data..."); sTravelMgr->LoadQuestTravelTable(); } if (sPlayerbotAIConfig->randomBotJoinBG) sRandomPlayerbotMgr->LoadBattleMastersCache(); if (sPlayerbotAIConfig->randomBotSuggestDungeons) { sPlayerbotDungeonSuggestionMgr->LoadDungeonSuggestions(); } LOG_INFO("server.loading", "---------------------------------------"); LOG_INFO("server.loading", " AI 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); } 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(); } 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::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32 minLevel1, uint32 maxLevel1) { std::vector buffs; std::ostringstream os; os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << minLevel1 << "." << maxLevel1; LoadList>(sConfigMgr->GetOption(os.str().c_str(), "", false), buffs); for (auto buff : buffs) { worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1}; worldBuffs.push_back(wb); } if (maxLevel1 == 0) { std::ostringstream os; os << "AiPlayerbot.WorldBuff." << factionId1 << "." << classId1 << "." << minLevel1; LoadList>(sConfigMgr->GetOption(os.str().c_str(), "", false), buffs); for (auto buff : buffs) { worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1}; worldBuffs.push_back(wb); } } if (maxLevel1 == 0 && minLevel1 == 0) { std::ostringstream os; os << "AiPlayerbot.WorldBuff." << factionId1 << "." << factionId1 << "." << classId1; LoadList>(sConfigMgr->GetOption(os.str().c_str(), "", false), buffs); for (auto buff : buffs) { worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1}; worldBuffs.push_back(wb); } } if (classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0) { std::ostringstream os; os << "AiPlayerbot.WorldBuff." << factionId1; LoadList>(sConfigMgr->GetOption(os.str().c_str(), "", false), buffs); for (auto buff : buffs) { worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1}; worldBuffs.push_back(wb); } } if (factionId1 == 0 && classId1 == 0 && maxLevel1 == 0 && minLevel1 == 0) { std::ostringstream os; os << "AiPlayerbot.WorldBuff"; LoadList>(sConfigMgr->GetOption(os.str().c_str(), "", false), buffs); for (auto buff : buffs) { worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1}; worldBuffs.push_back(wb); } } } 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; }