/* * 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 "Config.h" #include "Playerbots.h" #include "PlayerbotFactory.h" #include "RandomItemMgr.h" #include "RandomPlayerbotFactory.h" #include "Talentspec.h" #include "PlayerbotDungeonSuggestionMgr.h" #include 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); expireActionTime = sConfigMgr->GetOption("AiPlayerbot.ExpireActionTime", 5000); dispelAuraDuration = sConfigMgr->GetOption("AiPlayerbot.DispelAuraDuration", 7000); reactDelay = sConfigMgr->GetOption("AiPlayerbot.ReactDelay", 500); passiveDelay = sConfigMgr->GetOption("AiPlayerbot.PassiveDelay", 10000); repeatDelay = sConfigMgr->GetOption("AiPlayerbot.RepeatDelay", 5000); 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", 1.5f); 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); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.15f); 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); 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.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.MaxRandomRandomizeTime", 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); 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); randomBotSuggestDungeons = sConfigMgr->GetOption("AiPlayerbot.RandomBotSuggestDungeons", true); suggestDungeonsInLowerCaseRandomly = sConfigMgr->GetOption("AiPlayerbot.SuggestDungeonsInLowerCaseRandomly", false); randomBotJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinBG", true); randomBotAutoJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBG", false); 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"); 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) { for (uint32 spec = 0; spec < 3; ++spec) { std::ostringstream os; os << "AiPlayerbot.RandomClassSpecProbability." << cls << "." << spec; specProbability[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), 33); os.str(""); os.clear(); os << "AiPlayerbot.DefaultTalentsOrder." << cls << "." << spec; std::string temp_talents_order = sConfigMgr->GetOption(os.str().c_str(), ""); defaultTalentsOrder[cls][spec] = ParseTempTalentsOrder(cls, temp_talents_order); if (defaultTalentsOrder[cls][spec].size() > 0) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "default talents order for cls %d spec %d loaded.", cls, spec); } } for (uint32 spec = 0; spec < 3; ++spec) { std::ostringstream os; os << "AiPlayerbot.RandomClassSpecProbability." << cls << "." << spec; specProbability[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), 33); os.str(""); os.clear(); os << "AiPlayerbot.DefaultTalentsOrderLowLevel." << cls << "." << spec; std::string temp_talents_order = sConfigMgr->GetOption(os.str().c_str(), ""); defaultTalentsOrderLowLevel[cls][spec] = ParseTempTalentsOrder(cls, temp_talents_order); if (defaultTalentsOrderLowLevel[cls][spec].size() > 0) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "default low level talents order for cls %d spec %d loaded.", cls, spec); } } } // for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) // { // classSpecs[cls] = ClassSpecs(1 << (cls - 1)); // for (uint32 spec = 0; spec < MAX_LEVEL; ++spec) // { // std::ostringstream os; // os << "AiPlayerbot.PremadeSpecName." << cls << "." << spec; // std::string const specName = sConfigMgr->GetOption(os.str().c_str(), "", false); // if (!specName.empty()) // { // std::ostringstream os; // os << "AiPlayerbot.PremadeSpecProb." << cls << "." << spec; // uint32 probability = sConfigMgr->GetOption(os.str().c_str(), 100, false); // TalentPath talentPath(spec, specName, probability); // for (uint32 level = 10; level <= 80; level++) // { // std::ostringstream os; // os << "AiPlayerbot.PremadeSpecLink." << cls << "." << spec << "." << level; // std::string specLink = sConfigMgr->GetOption(os.str().c_str(), "", false); // specLink = specLink.substr(0, specLink.find("#", 0));; // specLink = specLink.substr(0, specLink.find(" ", 0));; // if (!specLink.empty()) // { // std::ostringstream out; // // Ignore bad specs. // if (!classSpecs[cls].baseSpec.CheckTalentLink(specLink, &out)) // { // LOG_ERROR("playerbots", "Error with premade spec link: {}", specLink.c_str()); // LOG_ERROR("playerbots", "{}", out.str().c_str()); // continue; // } // TalentSpec linkSpec(&classSpecs[cls].baseSpec, specLink); // if (!linkSpec.CheckTalents(level, &out)) // { // LOG_ERROR("playerbots", "Error with premade spec: {}", specLink.c_str()); // LOG_ERROR("playerbots", "{}", out.str().c_str()); // continue; // } // talentPath.talentSpec.push_back(linkSpec); // } // } // // Only add paths that have atleast 1 spec. // if (talentPath.talentSpec.size() > 0) // classSpecs[cls].talentPath.push_back(talentPath); // } // } // } 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); 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); botReviveWhenSummon = sConfigMgr->GetOption("AiPlayerbot.BotReviveWhenSummon", 1); 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); randombotsWalkingRPGInDoors = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG.InDoors", false); minEnchantingBotLevel = sConfigMgr->GetOption("AiPlayerbot.MinEnchantingBotLevel", 60); randombotStartingLevel = sConfigMgr->GetOption("AiPlayerbot.RandombotStartingLevel", 5); gearscorecheck = sConfigMgr->GetOption("AiPlayerbot.GearScoreCheck", false); randomBotPreQuests = sConfigMgr->GetOption("AiPlayerbot.PreQuests", true); // SPP automation freeMethodLoot = sConfigMgr->GetOption("AiPlayerbot.FreeMethodLoot", false); autoPickReward = sConfigMgr->GetOption("AiPlayerbot.AutoPickReward", "yes"); autoEquipUpgradeLoot = sConfigMgr->GetOption("AiPlayerbot.AutoEquipUpgradeLoot", true); syncQuestWithPlayer = sConfigMgr->GetOption("AiPlayerbot.SyncQuestWithPlayer", false); 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); randomBotSayWithoutMaster = sConfigMgr->GetOption("AiPlayerbot.RandomBotSayWithoutMaster", false); randomBotGroupNearby = sConfigMgr->GetOption("AiPlayerbot.RandomBotGroupNearby", true); // arena randomBotArenaTeamCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotArenaTeamCount", 20); deleteRandomBotArenaTeams = sConfigMgr->GetOption("AiPlayerbot.DeleteRandomBotArenaTeams", false); selfBotLevel = sConfigMgr->GetOption("AiPlayerbot.SelfBotLevel", 1); RandomPlayerbotFactory::CreateRandomBots(); PlayerbotFactory::Init(); sRandomItemMgr->Init(); sRandomItemMgr->InitAfterAhBot(); sPlayerbotTextMgr->LoadBotTexts(); sPlayerbotTextMgr->LoadBotTextChance(); 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::IsInPvpProhibitedZone(uint32 id) { return find(pvpProhibitedZoneIds.begin(), pvpProhibitedZoneIds.end(), id) != pvpProhibitedZoneIds.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; //在字符串末尾也加入分隔符,方便截取最后一段 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); //去掉已分割的字符串,在剩下的字符串中进行分割 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); // orders.assign(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()); } // for (std::vector &p : sPlayerbotAIConfig->defaultTalentsOrder[bot->getClass()][specNo]) { // uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; // uint32 talentID = -1; // std::vector &spells = spells_row[row]; // assert(spells.size() > 0); // for (TalentEntry const* talentInfo : spells) { // if (talentInfo->Col != col) { // continue; // } // TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); // if (talentTabInfo->tabpage != tab) { // continue; // } // talentID = talentInfo->TalentID; // } // assert(talentID != -1); // bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1); // if (bot->GetFreeTalentPoints() == 0) { // break; // } // } // // for (int tab = 0; tab < 3; tab++) { // // } // for (std::string piece : pieces) { // uint32 tab, row, col, lvl; // if (sscanf(piece.c_str(), "%u-%u-%u-%u", &tab, &row, &col, &lvl) == -1) { // break; // } // res.push_back({tab, row, col, lvl}); // } return res; }