diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 51510ee2..7f54bfc7 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -445,131 +445,191 @@ PlayerbotsDatabase.SynchThreads = 1 Playerbots.Updates.EnableDatabases = 1 - ############################################## -# TalentSpec # +# PremadeSpec # ############################################## +# AiPlayerbot.PremadeSpecName.. = #Name of the talent specialisation +# AiPlayerbot.PremadeSpecLink... = #Wowhead style link the bot should work towards at given level. +# 0 <= specno < 20, 1 <= level <= 80 # Warrior -AiPlayerbot.RandomClassSpecProbability.1.0 = 20 -AiPlayerbot.DefaultTalentsOrderLowLevel.1.0 = -AiPlayerbot.DefaultTalentsOrder.1.0 = 3022032123335100202012013031251-32505010002 -AiPlayerbot.RandomClassSpecProbability.1.1 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.1.1 = -AiPlayerbot.DefaultTalentsOrder.1.1 = 30202300233-305053000500310153120511351 -AiPlayerbot.RandomClassSpecProbability.1.2 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.1.2 = -AiPlayerbot.DefaultTalentsOrder.1.2 = 3500030023-301-053351225000210521030113321 +AiPlayerbot.PremadeSpecName.1.0 = arms pve +AiPlayerbot.PremadeSpecLink.1.0.60 = +AiPlayerbot.PremadeSpecLink.1.0.80 = 3022032123335100202012013031251-32505010002 +# AiPlayerbot.PremadeSpecGlyph.1.0 = 0,0,0,0,0,0 +AiPlayerbot.PremadeSpecName.1.1 = fury pve +AiPlayerbot.PremadeSpecLink.1.1.60 = +AiPlayerbot.PremadeSpecLink.1.1.80 = 30202300233-305053000500310153120511351 +AiPlayerbot.PremadeSpecName.1.2 = prot pve +AiPlayerbot.PremadeSpecLink.1.2.60 = +AiPlayerbot.PremadeSpecLink.1.2.80 = 3500030023-301-053351225000210521030113321 # Paladin -AiPlayerbot.RandomClassSpecProbability.2.0 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.2.0 = -AiPlayerbot.DefaultTalentsOrder.2.0 = 50350152220013053100515221-503201312 -AiPlayerbot.RandomClassSpecProbability.2.1 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.2.1 = -AiPlayerbot.DefaultTalentsOrder.2.1 = -05005135203132311333312321-5023005 -AiPlayerbot.RandomClassSpecProbability.2.2 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.2.2 = -AiPlayerbot.DefaultTalentsOrder.2.2 = 050501-05-05232051203331302133231331 -# Hunter -AiPlayerbot.RandomClassSpecProbability.3.0 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.3.0 = 51200201505112243100511351 -AiPlayerbot.DefaultTalentsOrder.3.0 = 51200201505112253100531351-015305021 -AiPlayerbot.RandomClassSpecProbability.3.1 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.3.1 = -AiPlayerbot.DefaultTalentsOrder.3.1 = 502-035305101230013233135031351-5000002 -AiPlayerbot.RandomClassSpecProbability.3.2 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.3.2 = -AiPlayerbot.DefaultTalentsOrder.3.2 = -0053041-5000032500033330523134321331 -# Rogue -AiPlayerbot.RandomClassSpecProbability.4.0 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.4.0 = -AiPlayerbot.DefaultTalentsOrder.4.0 = 005323005350100520103331051-005005003-502 # 0-0-2-5, 0-1-3-3, 0-1-0-3, 0-2-2-5, 0-3-2-5, 0-3-1-3, 0-4-1-1, 0-5-2-2, 0-5-1-5, 0-6-1-1, 0-2-1-2, 0-7-2-3, 0-7-0-3, 0-8-1-1, 0-8-0-3, 0-9-1-5, 0-10-1-1, 1-0-2-5, 1-1-3-5, 1-2-2-5, 1-3-2-3, 2-0-0-2 -AiPlayerbot.RandomClassSpecProbability.4.1 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.4.1 = -AiPlayerbot.DefaultTalentsOrder.4.1 = 30530000522-0252051000035015223100501251 -AiPlayerbot.RandomClassSpecProbability.4.2 = 20 -AiPlayerbot.DefaultTalentsOrderLowLevel.4.2 = -AiPlayerbot.DefaultTalentsOrder.4.2 = 0053231-2-5120222030321121050135231251 -# Priest -AiPlayerbot.RandomClassSpecProbability.5.0 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.5.0 = -AiPlayerbot.DefaultTalentsOrder.5.0 = 0503203130300512331323231251-03530003 -AiPlayerbot.RandomClassSpecProbability.5.1 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.5.1 = -AiPlayerbot.DefaultTalentsOrder.5.1 = 05032031-235050032302152530000331351 -AiPlayerbot.RandomClassSpecProbability.5.2 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.5.2 = -AiPlayerbot.DefaultTalentsOrder.5.2 = 0503203--325023051223010323152301351 -# DeathKnight -AiPlayerbot.RandomClassSpecProbability.6.0 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.6.0 = -AiPlayerbot.DefaultTalentsOrder.6.0 = 0355021533003313201020131351-005-005032 -AiPlayerbot.RandomClassSpecProbability.6.1 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.6.1 = -AiPlayerbot.DefaultTalentsOrder.6.1 = 03-32002350352203012300033101351-230200305 -AiPlayerbot.RandomClassSpecProbability.6.2 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.6.2 = -AiPlayerbot.DefaultTalentsOrder.6.2 = 23050202--2302003350032152003150003133151 -# Shaman -AiPlayerbot.RandomClassSpecProbability.7.0 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.7.0 = -AiPlayerbot.DefaultTalentsOrder.7.0 = 3530001523213351322301351-005050031 -AiPlayerbot.RandomClassSpecProbability.7.1 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.7.1 = -AiPlayerbot.DefaultTalentsOrder.7.1 = 053030052-30205033005021333031131131051 -AiPlayerbot.RandomClassSpecProbability.7.2 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.7.2 = -AiPlayerbot.DefaultTalentsOrder.7.2 = -00505031-50005331335310501022331251 -# Mage -AiPlayerbot.RandomClassSpecProbability.8.0 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.8.0 = -AiPlayerbot.DefaultTalentsOrder.8.0 = 235005030100230150323102505321-03-203023001 -AiPlayerbot.RandomClassSpecProbability.8.1 = 30 -AiPlayerbot.DefaultTalentsOrderLowLevel.8.1 = -AiPlayerbot.DefaultTalentsOrder.8.1 = 23000503310003-0055030012303330053120300351 -AiPlayerbot.RandomClassSpecProbability.8.2 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.8.2 = -AiPlayerbot.DefaultTalentsOrder.8.2 = 23002322010203--3533103310203100232102231151 -# Warlock -AiPlayerbot.RandomClassSpecProbability.9.0 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.9.0 = -AiPlayerbot.DefaultTalentsOrder.9.0 = 2350020021123510253500331151--55000005 -AiPlayerbot.RandomClassSpecProbability.9.1 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.9.1 = -AiPlayerbot.DefaultTalentsOrder.9.1 = -003203301135212530135211351-55000005 # 1-0-2-3, 1-0-3-2, 1-1-1-3, 1-1-2-3, 1-2-1-1, 1-2-2-1, 1-2-2-3, 1-3-1-5, 1-3-2-2, 1-4-0-1, 1-4-2-2 -AiPlayerbot.RandomClassSpecProbability.9.2 = 20 -AiPlayerbot.DefaultTalentsOrderLowLevel.9.2 = -AiPlayerbot.DefaultTalentsOrder.9.2 = -03310030003-05203205210331051335230351 -# Druid -AiPlayerbot.RandomClassSpecProbability.11.0 = 20 -AiPlayerbot.DefaultTalentsOrderLowLevel.11.0 = -AiPlayerbot.DefaultTalentsOrder.11.0 = 5012203125331103213305301231--205003212 -AiPlayerbot.RandomClassSpecProbability.11.1 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.11.1 = -AiPlayerbot.DefaultTalentsOrder.11.1 = -501232130322110353120303313511-20350001 -AiPlayerbot.RandomClassSpecProbability.11.2 = 40 -AiPlayerbot.DefaultTalentsOrderLowLevel.11.2 = -AiPlayerbot.DefaultTalentsOrder.11.2 = 05320001--230033312031512531153313051 +AiPlayerbot.PremadeSpecName.2.0 = holy pve +AiPlayerbot.PremadeSpecLink.2.0.60 = +AiPlayerbot.PremadeSpecLink.2.0.80 = 50350152220013053100515221-503201312 +AiPlayerbot.PremadeSpecName.2.1 = prot pve +AiPlayerbot.PremadeSpecLink.2.1.60 = +AiPlayerbot.PremadeSpecLink.2.1.80 = -05005135203132311333312321-5023005 +AiPlayerbot.PremadeSpecName.2.2 = ret pve +AiPlayerbot.PremadeSpecLink.2.2.60 = +AiPlayerbot.PremadeSpecLink.2.2.80 = 050501-05-05232051203331302133231331 -# no idea - TC was requesting these.. so.. -AiPlayerbot.RandomClassSpecProbability.0.0 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.0.0 = -AiPlayerbot.DefaultTalentsOrder.0.0 = -AiPlayerbot.RandomClassSpecProbability.0.1 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.0.1 = -AiPlayerbot.DefaultTalentsOrder.0.1 = -AiPlayerbot.RandomClassSpecProbability.0.2 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.0.2 = -AiPlayerbot.DefaultTalentsOrder.0.2 = -AiPlayerbot.RandomClassSpecProbability.10.0 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.10.0 = -AiPlayerbot.DefaultTalentsOrder.10.0 = -AiPlayerbot.RandomClassSpecProbability.10.1 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.10.1 = -AiPlayerbot.DefaultTalentsOrder.10.1 = -AiPlayerbot.RandomClassSpecProbability.10.2 = 33 -AiPlayerbot.DefaultTalentsOrderLowLevel.10.2 = -AiPlayerbot.DefaultTalentsOrder.10.2 = +# Hunter +AiPlayerbot.PremadeSpecName.3.0 = bm pve +AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243100511351 +AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112253100531351-015305021 +AiPlayerbot.PremadeSpecName.3.1 = mm pve +AiPlayerbot.PremadeSpecLink.3.1.60 = +AiPlayerbot.PremadeSpecLink.3.1.80 = 502-035305101230013233135031351-5000002 +AiPlayerbot.PremadeSpecName.3.2 = surv pve +AiPlayerbot.PremadeSpecLink.3.2.60 = +AiPlayerbot.PremadeSpecLink.3.2.80 = -0053041-5000032500033330523134321331 +# Rogue +AiPlayerbot.PremadeSpecName.4.0 = ass pve +AiPlayerbot.PremadeSpecLink.4.0.60 = +AiPlayerbot.PremadeSpecLink.4.0.80 = 005323005350100520103331051-005005003-502 +AiPlayerbot.PremadeSpecName.4.1 = combat pve +AiPlayerbot.PremadeSpecLink.4.1.60 = +AiPlayerbot.PremadeSpecLink.4.1.80 = 30530000522-0252051000035015223100501251 +AiPlayerbot.PremadeSpecName.4.2 = subtlety pve +AiPlayerbot.PremadeSpecLink.4.2.60 = +AiPlayerbot.PremadeSpecLink.4.2.80 = 0053231-2-5120222030321121050135231251 +# Priest +AiPlayerbot.PremadeSpecName.5.0 = disc pve +AiPlayerbot.PremadeSpecLink.5.0.60 = +AiPlayerbot.PremadeSpecLink.5.0.80 = 0503203130300512331323231251-03530003 +AiPlayerbot.PremadeSpecName.5.1 = holy pve +AiPlayerbot.PremadeSpecLink.5.1.60 = +AiPlayerbot.PremadeSpecLink.5.1.80 = 05032031-235050032302152530000331351 +AiPlayerbot.PremadeSpecName.5.2 = shadow pve +AiPlayerbot.PremadeSpecLink.5.2.60 = +AiPlayerbot.PremadeSpecLink.5.2.80 = 0053231-2-5120222030321121050135231251 +# DeathKnight +AiPlayerbot.PremadeSpecName.6.0 = blood pve +AiPlayerbot.PremadeSpecLink.6.0.60 = +AiPlayerbot.PremadeSpecLink.6.0.80 = 0355021533003313201020131351-005-005032 +AiPlayerbot.PremadeSpecName.6.1 = frost pve +AiPlayerbot.PremadeSpecLink.6.1.60 = +AiPlayerbot.PremadeSpecLink.6.1.80 = 03-32002350352203012300033101351-230200305 +AiPlayerbot.PremadeSpecName.6.2 = unholy pve +AiPlayerbot.PremadeSpecLink.6.2.60 = +AiPlayerbot.PremadeSpecLink.6.2.80 = 23050202--2302003350032152003150003133151 +# Shaman +AiPlayerbot.PremadeSpecName.7.0 = ele pve +AiPlayerbot.PremadeSpecLink.7.0.60 = +AiPlayerbot.PremadeSpecLink.7.0.80 = 3530001523213351322301351-005050031 +AiPlayerbot.PremadeSpecName.7.1 = enh pve +AiPlayerbot.PremadeSpecLink.7.1.60 = +AiPlayerbot.PremadeSpecLink.7.1.80 = 053030052-30205033005021333031131131051 +AiPlayerbot.PremadeSpecName.7.2 = resto pve +AiPlayerbot.PremadeSpecLink.7.2.60 = +AiPlayerbot.PremadeSpecLink.7.2.80 = -00505031-50005331335310501022331251 +# Mage +AiPlayerbot.PremadeSpecName.8.0 = arcane pve +AiPlayerbot.PremadeSpecLink.8.0.60 = +AiPlayerbot.PremadeSpecLink.8.0.80 = 235005030100230150323102505321-03-203023001 +AiPlayerbot.PremadeSpecName.8.1 = fire pve +AiPlayerbot.PremadeSpecLink.8.1.60 = +AiPlayerbot.PremadeSpecLink.8.1.80 = 23000503310003-0055030012303330053120300351 +AiPlayerbot.PremadeSpecName.8.2 = frost pve +AiPlayerbot.PremadeSpecLink.8.2.60 = +AiPlayerbot.PremadeSpecLink.8.2.80 = 23002322010203--3533103310203100232102231151 +# Warlock +AiPlayerbot.PremadeSpecName.9.0 = affli pve +AiPlayerbot.PremadeSpecLink.9.0.60 = +AiPlayerbot.PremadeSpecLink.9.0.80 = 2350020021123510253500331151--55000005 +AiPlayerbot.PremadeSpecName.9.1 = emo pve +AiPlayerbot.PremadeSpecLink.9.1.60 = +AiPlayerbot.PremadeSpecLink.9.1.80 = -003203301135212530135211351-55000005 +AiPlayerbot.PremadeSpecName.9.2 = destro pve +AiPlayerbot.PremadeSpecLink.9.2.60 = +AiPlayerbot.PremadeSpecLink.9.2.80 = -03310030003-05203205210331051335230351 +# Druid +AiPlayerbot.PremadeSpecName.11.0 = balance pve +AiPlayerbot.PremadeSpecLink.11.0.60 = +AiPlayerbot.PremadeSpecLink.11.0.80 = 5012203125331103213305301231--205003212 +AiPlayerbot.PremadeSpecName.11.1 = feral pve +AiPlayerbot.PremadeSpecLink.11.1.60 = +AiPlayerbot.PremadeSpecLink.11.1.80 = -501232130322110353120303313511-20350001 +AiPlayerbot.PremadeSpecName.11.2 = resto pve +AiPlayerbot.PremadeSpecLink.11.2.60 = +AiPlayerbot.PremadeSpecLink.11.2.80 = 05320001--230033312031512531153313051 + +############################################## +# Default TalentSpec for random bots # +############################################## +# AiPlayerbot.RandomClassSpecProb.. # The probability to choose the spec +# AiPlayerbot.RandomClassSpecIndex.. # The spec index in PremadeSpec +# Warrior +AiPlayerbot.RandomClassSpecProb.1.0 = 20 +AiPlayerbot.RandomClassSpecIndex.1.0 = 0 +AiPlayerbot.RandomClassSpecProb.1.1 = 40 +AiPlayerbot.RandomClassSpecIndex.1.1 = 1 +AiPlayerbot.RandomClassSpecProb.1.2 = 40 +AiPlayerbot.RandomClassSpecIndex.1.2 = 2 +# Paladin +AiPlayerbot.RandomClassSpecProb.2.0 = 30 +AiPlayerbot.RandomClassSpecIndex.2.0 = 0 +AiPlayerbot.RandomClassSpecProb.2.1 = 40 +AiPlayerbot.RandomClassSpecIndex.2.1 = 1 +AiPlayerbot.RandomClassSpecProb.2.2 = 30 +AiPlayerbot.RandomClassSpecIndex.2.2 = 2 +# Hunter +AiPlayerbot.RandomClassSpecProb.3.0 = 33 +AiPlayerbot.RandomClassSpecIndex.3.0 = 0 +AiPlayerbot.RandomClassSpecProb.3.1 = 33 +AiPlayerbot.RandomClassSpecIndex.3.1 = 1 +AiPlayerbot.RandomClassSpecProb.3.2 = 33 +AiPlayerbot.RandomClassSpecIndex.3.2 = 2 +# Rogue +AiPlayerbot.RandomClassSpecProb.4.0 = 45 +AiPlayerbot.RandomClassSpecIndex.4.0 = 0 +AiPlayerbot.RandomClassSpecProb.4.1 = 45 +AiPlayerbot.RandomClassSpecIndex.4.1 = 1 +AiPlayerbot.RandomClassSpecProb.4.2 = 10 +AiPlayerbot.RandomClassSpecIndex.4.2 = 2 +# Priest +AiPlayerbot.RandomClassSpecProb.5.0 = 40 +AiPlayerbot.RandomClassSpecIndex.5.0 = 0 +AiPlayerbot.RandomClassSpecProb.5.1 = 35 +AiPlayerbot.RandomClassSpecIndex.5.1 = 1 +AiPlayerbot.RandomClassSpecProb.5.2 = 25 +AiPlayerbot.RandomClassSpecIndex.5.2 = 2 +# DeathKnight +AiPlayerbot.RandomClassSpecProb.6.0 = 30 +AiPlayerbot.RandomClassSpecIndex.6.0 = 0 +AiPlayerbot.RandomClassSpecProb.6.1 = 40 +AiPlayerbot.RandomClassSpecIndex.6.1 = 1 +AiPlayerbot.RandomClassSpecProb.6.2 = 30 +AiPlayerbot.RandomClassSpecIndex.6.2 = 2 +# Shaman +AiPlayerbot.RandomClassSpecProb.7.0 = 33 +AiPlayerbot.RandomClassSpecIndex.7.0 = 0 +AiPlayerbot.RandomClassSpecProb.7.1 = 33 +AiPlayerbot.RandomClassSpecIndex.7.1 = 1 +AiPlayerbot.RandomClassSpecProb.7.2 = 33 +AiPlayerbot.RandomClassSpecIndex.7.2 = 2 +# Mage +AiPlayerbot.RandomClassSpecProb.8.0 = 30 +AiPlayerbot.RandomClassSpecIndex.8.0 = 0 +AiPlayerbot.RandomClassSpecProb.8.1 = 30 +AiPlayerbot.RandomClassSpecIndex.8.1 = 1 +AiPlayerbot.RandomClassSpecProb.8.2 = 40 +AiPlayerbot.RandomClassSpecIndex.8.2 = 2 +# Warlock +AiPlayerbot.RandomClassSpecProb.9.0 = 40 +AiPlayerbot.RandomClassSpecIndex.9.0 = 0 +AiPlayerbot.RandomClassSpecProb.9.1 = 40 +AiPlayerbot.RandomClassSpecIndex.9.1 = 1 +AiPlayerbot.RandomClassSpecProb.9.2 = 20 +AiPlayerbot.RandomClassSpecIndex.9.2 = 2 +# Druid +AiPlayerbot.RandomClassSpecProb.11.0 = 20 +AiPlayerbot.RandomClassSpecIndex.11.0 = 0 +AiPlayerbot.RandomClassSpecProb.11.1 = 40 +AiPlayerbot.RandomClassSpecIndex.11.1 = 1 +AiPlayerbot.RandomClassSpecProb.11.2 = 40 +AiPlayerbot.RandomClassSpecIndex.11.2 = 2 ################################################################################## # # diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index e7349fb3..d0502d13 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -593,8 +593,10 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies); } - else + else { + // nonCombatEngine->addStrategy("pvp"); nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies); + } } } } diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index d7033d41..1e928e5e 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -164,96 +164,33 @@ bool PlayerbotAIConfig::Initialize() for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) { - for (uint32 spec = 0; spec < 3; ++spec) + if (cls == 10) { + continue; + } + for (uint32 spec = 0; spec < MAX_SPECNO; ++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); + os << "AiPlayerbot.PremadeSpecName." << cls << "." << spec; + premadeSpecName[cls][spec] = sConfigMgr->GetOption(os.str().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(), ""); + parsedSpecLinkOrder[cls][spec][level] = ParseTempTalentsOrder(cls, premadeSpecLink[cls][spec][level]); } } 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 << "AiPlayerbot.RandomClassSpecProb." << cls << "." << spec; + randomClassSpecProb[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); - } + os << "AiPlayerbot.RandomClassSpecIndex." << cls << "." << spec; + randomClassSpecIndex[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), spec + 1); } } - // 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); @@ -561,7 +498,7 @@ static std::vector split(const std::string &str, const std::string 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); @@ -569,7 +506,7 @@ static std::vector split(const std::string &str, const std::string { 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); } @@ -584,7 +521,6 @@ std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 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); @@ -623,37 +559,5 @@ std::vector> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 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; } \ No newline at end of file diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 0d6367cb..06ed2213 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -6,6 +6,7 @@ #define _PLAYERBOT_PLAYERbotAICONFIG_H #include "Common.h" +#include "DBCEnums.h" #include "SharedDefines.h" #include "Talentspec.h" @@ -22,6 +23,8 @@ enum class BotCheatMask : uint32 maxMask = 32 }; +#define MAX_SPECNO 20 + class PlayerbotAIConfig { public: @@ -88,12 +91,17 @@ class PlayerbotAIConfig std::string randomBotCombatStrategies, randomBotNonCombatStrategies; uint32 randomBotMinLevel, randomBotMaxLevel; float randomChangeMultiplier; - uint32 specProbability[MAX_CLASSES][10]; - // [(tab, row, col, level)] - std::vector> defaultTalentsOrder[MAX_CLASSES][3]; - std::vector> defaultTalentsOrderLowLevel[MAX_CLASSES][3]; - std::string premadeLevelSpec[MAX_CLASSES][10][91]; //lvl 10 - 100 - ClassSpecs classSpecs[MAX_CLASSES]; + + + // std::string premadeLevelSpec[MAX_CLASSES][10][91]; //lvl 10 - 100 + // ClassSpecs classSpecs[MAX_CLASSES]; + + std::string premadeSpecName[MAX_CLASSES][MAX_SPECNO]; + std::string premadeSpecLink[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL]; + std::vector> parsedSpecLinkOrder[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL]; + uint32 randomClassSpecProb[MAX_CLASSES][MAX_SPECNO]; + uint32 randomClassSpecIndex[MAX_CLASSES][MAX_SPECNO]; + std::string commandPrefix, commandSeparator; std::string randomBotAccountPrefix; uint32 randomBotAccountCount; @@ -192,8 +200,7 @@ class PlayerbotAIConfig void log(std::string const fileName, const char* str, ...); void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel); - private: - std::vector> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order); + static std::vector> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order); }; #define sPlayerbotAIConfig PlayerbotAIConfig::instance() diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 3958deef..e34133a9 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -180,18 +180,14 @@ void PlayerbotFactory::Randomize(bool incremental) LOG_INFO("playerbots", "Initializing spells (step 1)..."); // bot->LearnDefaultSkills(); InitClassSpells(); - // bot->SaveToDB(false, false); InitAvailableSpells(); - // bot->SaveToDB(false, false); if (pmo) pmo->finish(); LOG_INFO("playerbots", "Initializing skills (step 1)..."); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1"); InitSkills(); - // bot->SaveToDB(false, false); InitSpecialSpells(); - // bot->SaveToDB(false, false); // InitTradeSkills(); if (pmo) @@ -200,7 +196,6 @@ void PlayerbotFactory::Randomize(bool incremental) pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents"); LOG_INFO("playerbots", "Initializing talents..."); InitTalentsTree(); - // bot->SaveToDB(false, false); sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", 0); if (botAI) { sPlayerbotDbStore->Reset(botAI); @@ -213,7 +208,6 @@ void PlayerbotFactory::Randomize(bool incremental) pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2"); LOG_INFO("playerbots", "Initializing spells (step 2)..."); InitAvailableSpells(); - // bot->SaveToDB(false, false); if (pmo) pmo->finish(); @@ -797,28 +791,141 @@ void PlayerbotFactory::InitSpells() void PlayerbotFactory::InitTalentsTree(bool increment/*false*/, bool use_template/*true*/, bool reset/*false*/) { - uint32 specNo; + uint32 specTab; uint8 cls = bot->getClass(); std::map tabs = AiFactory::GetPlayerSpecTabs(bot); uint32 total_tabs = tabs[0] + tabs[1] + tabs[2]; - if (increment && bot->GetFreeTalentPoints() <= 2 && total_tabs != 0) { - specNo = AiFactory::GetPlayerSpecTab(bot); + if (increment && total_tabs != 0) { + specTab = AiFactory::GetPlayerSpecTab(bot); } else { uint32 point = urand(0, 100); - uint32 p1 = sPlayerbotAIConfig->specProbability[cls][0]; - uint32 p2 = p1 + sPlayerbotAIConfig->specProbability[cls][1]; - specNo = (point < p1 ? 0 : (point < p2 ? 1 : 2)); + uint32 p1 = sPlayerbotAIConfig->randomClassSpecProb[cls][0]; + uint32 p2 = p1 + sPlayerbotAIConfig->randomClassSpecProb[cls][1]; + specTab = point < p1 ? 0 : (point < p2 ? 1 : 2); } if (reset) { bot->resetTalents(true); } // use template if can - if (use_template && sPlayerbotAIConfig->defaultTalentsOrder[cls][specNo].size() > 0) { - InitTalentsByTemplate(specNo); + if (use_template) { + InitTalentsByTemplate(specTab); } else { - InitTalents(specNo); + InitTalents(specTab); if (bot->GetFreeTalentPoints()) - InitTalents((specNo + 1) % 3); + InitTalents((specTab + 1) % 3); + } +} + +void PlayerbotFactory::InitTalentsBySpecNo(Player* bot, int specNo, bool reset) +{ + if (reset) { + bot->resetTalents(true); + } + uint32 cls = bot->getClass(); + int startLevel = bot->GetLevel(); + uint32 classMask = bot->getClassMask(); + std::map > spells_row; + 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_row[talentInfo->Row].push_back(talentInfo); + } + while (startLevel > 1 && startLevel < 80 && sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][startLevel].size() == 0) { + startLevel--; + } + for (int level = startLevel; level <= 80; level++) { + if (sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][level].size() == 0) { + continue; + } + for (std::vector &p : sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][level]) { + uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; + uint32 talentID = -1; + + std::vector &spells = spells_row[row]; + if (spells.size() <= 0) { + return; + } + for (TalentEntry const* talentInfo : spells) { + if (talentInfo->Col != col) { + continue; + } + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + if (talentTabInfo->tabpage != tab) { + continue; + } + if (talentInfo->DependsOn) { + bot->LearnTalent(talentInfo->DependsOn, std::min(talentInfo->DependsOnRank, bot->GetFreeTalentPoints() - 1)); + } + talentID = talentInfo->TalentID; + } + bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1); + if (bot->GetFreeTalentPoints() == 0) { + break; + } + } + if (bot->GetFreeTalentPoints() == 0) { + break; + } + } +} + +void PlayerbotFactory::InitTalentsByParsedSpecLink(Player* bot, std::vector> parsedSpecLink, bool reset) +{ + if (reset) { + bot->resetTalents(true); + } + uint32 classMask = bot->getClassMask(); + std::map > spells_row; + 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_row[talentInfo->Row].push_back(talentInfo); + } + for (std::vector &p : parsedSpecLink) { + uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; + uint32 talentID = -1; + + std::vector &spells = spells_row[row]; + if (spells.size() <= 0) { + return; + } + for (TalentEntry const* talentInfo : spells) { + if (talentInfo->Col != col) { + continue; + } + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + if (talentTabInfo->tabpage != tab) { + continue; + } + if (talentInfo->DependsOn) { + bot->LearnTalent(talentInfo->DependsOn, std::min(talentInfo->DependsOnRank, bot->GetFreeTalentPoints() - 1)); + } + talentID = talentInfo->TalentID; + } + bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1); + if (bot->GetFreeTalentPoints() == 0) { + break; + } } } @@ -2120,11 +2227,14 @@ void PlayerbotFactory::InitTalents(uint32 specNo) } } -void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo) +void PlayerbotFactory::InitTalentsByTemplate(uint32 specTab) { - if (sPlayerbotAIConfig->defaultTalentsOrder[bot->getClass()][specNo].size() == 0) { - return; - } + // if (sPlayerbotAIConfig->parsedSpecLinkOrder[bot->getClass()][specNo][80].size() == 0) { + // return; + // } + uint32 cls = bot->getClass(); + int startLevel = bot->GetLevel(); + uint32 specIndex = sPlayerbotAIConfig->randomClassSpecIndex[cls][specTab]; uint32 classMask = bot->getClassMask(); std::map > spells_row; for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) @@ -2142,10 +2252,14 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo) spells_row[talentInfo->Row].push_back(talentInfo); } - - // bot->SaveToDB(); - if (bot->GetLevel() < 80 && sPlayerbotAIConfig->defaultTalentsOrder[bot->getClass()][specNo].size() != 0) { - for (std::vector &p : sPlayerbotAIConfig->defaultTalentsOrderLowLevel[bot->getClass()][specNo]) { + while (startLevel > 1 && startLevel < 80 && sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][startLevel].size() == 0) { + startLevel--; + } + for (int level = startLevel; level <= 80; level++) { + if (sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][level].size() == 0) { + continue; + } + for (std::vector &p : sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][level]) { uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; uint32 talentID = -1; @@ -2153,7 +2267,6 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo) if (spells.size() <= 0) { return; } - // assert(spells.size() > 0); for (TalentEntry const* talentInfo : spells) { if (talentInfo->Col != col) { continue; @@ -2167,38 +2280,11 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo) } talentID = talentInfo->TalentID; } - assert(talentID != -1); bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1); if (bot->GetFreeTalentPoints() == 0) { break; } } - } - - 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]; - if (spells.size() <= 0) { - return; - } - // 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; - } - if (talentInfo->DependsOn) { - bot->LearnTalent(talentInfo->DependsOn, std::min(talentInfo->DependsOnRank, bot->GetFreeTalentPoints() - 1)); - } - talentID = talentInfo->TalentID; - } - assert(talentID != -1); - bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1); if (bot->GetFreeTalentPoints() == 0) { break; } diff --git a/src/PlayerbotFactory.h b/src/PlayerbotFactory.h index 4f585c31..b654dcd2 100644 --- a/src/PlayerbotFactory.h +++ b/src/PlayerbotFactory.h @@ -117,6 +117,8 @@ class PlayerbotFactory static uint32 tradeSkills[]; static float CalculateItemScore(uint32 item_id, Player* bot); void InitTalentsTree(bool incremental = false, bool use_template = true, bool reset = false); + static void InitTalentsBySpecNo(Player* bot, int specNo, bool reset); + static void InitTalentsByParsedSpecLink(Player* bot, std::vector> parsedSpecLink, bool reset); void InitAvailableSpells(); void InitClassSpells(); void InitEquipment(bool incremental); diff --git a/src/Talentspec.h b/src/Talentspec.h index 421a8e48..382fc6d8 100644 --- a/src/Talentspec.h +++ b/src/Talentspec.h @@ -18,6 +18,7 @@ struct TalentTabEntry; #define ADDED_POINTS 2 #define REMOVED_POINTS -2 +// unused currently class TalentSpec { public: diff --git a/src/strategy/actions/ChangeTalentsAction.cpp b/src/strategy/actions/ChangeTalentsAction.cpp index 4d3c5aba..d52e9e78 100644 --- a/src/strategy/actions/ChangeTalentsAction.cpp +++ b/src/strategy/actions/ChangeTalentsAction.cpp @@ -3,8 +3,10 @@ */ #include "ChangeTalentsAction.h" +#include "AiFactory.h" #include "ChatHelper.h" #include "Event.h" +#include "PlayerbotAIConfig.h" #include "PlayerbotFactory.h" #include "Playerbots.h" @@ -18,312 +20,303 @@ bool ChangeTalentsAction::Execute(Event event) if (!param.empty()) { - // if (param.find("auto") != std::string::npos) - // { - // AutoSelectTalents(&out); - // } - // else if (param.find("list ") != std::string::npos) - // { - // listPremadePaths(getPremadePaths(param.substr(5)), &out); - // } - // else if (param.find("list") != std::string::npos) - // { - // listPremadePaths(getPremadePaths(""), &out); - if (param == "1") { - bot->ActivateSpec(0); - } else if (param == "2") { - bot->ActivateSpec(1); + if (param.find("help") != std::string::npos) { + out << TalentsHelp(); + } else if (param.find("switch") != std::string::npos) { + if (param == "1") { + bot->ActivateSpec(0); + out << "Active first talent"; + } else if (param == "2") { + bot->ActivateSpec(1); + out << "Active second talent"; + } + } else if (param.find("autopick") != std::string::npos) { + PlayerbotFactory factory(bot, bot->GetLevel()); + factory.InitTalentsTree(true); + out << "Auto pick talents"; + } else if (param.find("spec list") != std::string::npos) { + out << SpecList(); + } else if (param.find("spec ") != std::string::npos) { + param = param.substr(5); + out << SpecPick(param); + } else if (param.find("apply ") != std::string::npos) { + param = param.substr(6); + out << SpecApply(param); + } else { + out << "Unknown command."; } - // else - // { - // bool crop = false; - // bool shift = false; - // if (param.find("do ") != std::string::npos) - // { - // crop = true; - // param = param.substr(3); - // } - // else if (param.find("shift ") != std::string::npos) - // { - // shift = true; - // param = param.substr(6); - // } - - // out << "Apply talents [" << param << "] "; - // if (botSpec.CheckTalentLink(param, &out)) - // { - // TalentSpec newSpec(bot, param); - // std::string const specLink = newSpec.GetTalentLink(); - - // if (crop) - // { - // newSpec.CropTalents(bot->getLevel()); - // out << "becomes: " << newSpec.GetTalentLink(); - // } - - // if (shift) - // { - // TalentSpec botSpec(bot); - // newSpec.ShiftTalents(&botSpec, bot->getLevel()); - // out << "becomes: " << newSpec.GetTalentLink(); - // } - - // if (newSpec.CheckTalents(bot->getLevel(), &out)) - // { - // newSpec.ApplyTalents(bot, &out); - // sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", 0); - // sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink); - // } - // } - // else - // { - // std::vector paths = getPremadePaths(param); - // if (paths.size() > 0) - // { - // out.str(""); - // out.clear(); - - // if (paths.size() > 1 && false/*!sPlayerbotAIConfig->autoPickTalents*/) - // { - // out << "Found multiple specs: "; - // listPremadePaths(paths, &out); - // } - // else - // { - // if (paths.size() > 1) - // out << "Found " << paths.size() << " possible specs to choose from. "; - - // TalentPath* path = PickPremadePath(paths, sRandomPlayerbotMgr->IsRandomBot(bot)); - // TalentSpec newSpec = *GetBestPremadeSpec(path->id); - // std::string const specLink = newSpec.GetTalentLink(); - // newSpec.CropTalents(bot->getLevel()); - // newSpec.ApplyTalents(bot, &out); - - // if (newSpec.GetTalentPoints() > 0) - // { - // out << "Apply spec " << "|h|cffffffff" << path->name << " " << newSpec.FormatSpec(bot); - // sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", path->id + 1); - // sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 0); - // } - // } - // } - // } - // } } - // else - // { - // uint32 specId = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo") - 1; - // std::string specName = ""; - // TalentPath* specPath; - // if (specId) - // { - // specPath = getPremadePath(specId); - // if (specPath->id == specId) - // specName = specPath->name; - // } - - // out << "My current talent spec is: " << "|h|cffffffff"; - // if (specName != "") - // out << specName << " (" << botSpec.FormatSpec(bot) << ")"; - // else - // out << chat->FormatClass(bot, botSpec.highestTree()); - // out << " Link: "; - // out << botSpec.GetTalentLink(); - // } + else + { + uint32 tab = AiFactory::GetPlayerSpecTab(bot); + out << "My current talent spec is: " << "|h|cffffffff"; + out << chat->FormatClass(bot, tab) << "\n"; + out << TalentsHelp(); + } botAI->TellMaster(out); return true; } -std::vector ChangeTalentsAction::getPremadePaths(std::string const findName) +std::string ChangeTalentsAction::TalentsHelp() { - std::vector ret; - for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) - { - if (findName.empty() || path.name.find(findName) != std::string::npos) - { - ret.push_back(&path); - } - } - - return std::move(ret); + std::ostringstream out; + out << "Talents usage: talents switch <1/2>, talents autopick, talents spec list, " + "talents spec , talents apply ."; + return out.str(); } -std::vector ChangeTalentsAction::getPremadePaths(TalentSpec* oldSpec) +std::string ChangeTalentsAction::SpecList() { - std::vector ret; - - for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) - { - TalentSpec newSpec = *GetBestPremadeSpec(path.id); - newSpec.CropTalents(bot->getLevel()); - if (oldSpec->isEarlierVersionOf(newSpec)) - { - ret.push_back(&path); + int cls = bot->getClass(); + int specFound = 0; + std::ostringstream out; + for (int specNo = 0; specNo < MAX_SPECNO; ++specNo) { + if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0) { + break; } + specFound++; + std::ostringstream out; + std::vector> parsed = sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][80]; + std::unordered_map tabCount; + tabCount[0] = tabCount[1] = tabCount[2] = 0; + for (auto item : parsed) { + tabCount[item[0]]++; + } + out << specFound << ". " << sPlayerbotAIConfig->premadeSpecName[cls][specNo] << " ("; + out << tabCount[0] << "-" << tabCount[1] << "-" << tabCount[2] << ")"; + botAI->TellMasterNoFacing(out.str()); } - - return std::move(ret); + out << "Total " << specFound << " specs found"; + return out.str(); } -TalentPath* ChangeTalentsAction::getPremadePath(uint32 id) +std::string ChangeTalentsAction::SpecPick(std::string param) { - for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) - { - if (id == path.id) - { - return &path; + int cls = bot->getClass(); + int specFound = 0; + for (int specNo = 0; specNo < MAX_SPECNO; ++specNo) { + if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0) { + break; + } + if (sPlayerbotAIConfig->premadeSpecName[cls][specNo] == param) { + PlayerbotFactory::InitTalentsBySpecNo(bot, specNo, true); + std::ostringstream out; + out << "Picking " << sPlayerbotAIConfig->premadeSpecName[cls][specNo]; + return out.str(); } } - - return &sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath[0]; + std::ostringstream out; + out << "Spec " << param << " not found"; + return out.str(); } -void ChangeTalentsAction::listPremadePaths(std::vector paths, std::ostringstream* out) + +std::string ChangeTalentsAction::SpecApply(std::string param) { - if (paths.size() == 0) - { - *out << "No predefined talents found.."; + int cls = bot->getClass(); + std::ostringstream out; + std::vector> parsedSpecLink = PlayerbotAIConfig::ParseTempTalentsOrder(cls, param); + if (parsedSpecLink.size() == 0) { + out << "Invalid link " << param; + return out.str(); } - - *out << "|h|cffffffff"; - - for (auto path : paths) - { - *out << path->name << " (" << path->talentSpec.back().FormatSpec(bot) << "), "; - } - - out->seekp(-2, out->cur); - *out << "."; + PlayerbotFactory::InitTalentsByParsedSpecLink(bot, parsedSpecLink, true); + out << "Applying " << param; + return out.str(); } -TalentPath* ChangeTalentsAction::PickPremadePath(std::vector paths, bool useProbability) -{ - uint32 totProbability = 0; - uint32 curProbability = 0; +// std::vector ChangeTalentsAction::getPremadePaths(std::string const findName) +// { +// std::vector ret; +// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) +// // { +// // if (findName.empty() || path.name.find(findName) != std::string::npos) +// // { +// // ret.push_back(&path); +// // } +// // } - if (paths.size() == 1) - return paths[0]; +// return std::move(ret); +// } - for (auto path : paths) - { - totProbability += useProbability ? path->probability : 1; - } +// std::vector ChangeTalentsAction::getPremadePaths(TalentSpec* oldSpec) +// { +// std::vector ret; - totProbability = urand(0, totProbability); +// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) +// // { +// // TalentSpec newSpec = *GetBestPremadeSpec(path.id); +// // newSpec.CropTalents(bot->getLevel()); +// // if (oldSpec->isEarlierVersionOf(newSpec)) +// // { +// // ret.push_back(&path); +// // } +// // } - for (auto path : paths) - { - curProbability += (useProbability ? path->probability : 1); - if (curProbability >= totProbability) - return path; - } +// return std::move(ret); +// } - return paths[0]; -} +// TalentPath* ChangeTalentsAction::getPremadePath(uint32 id) +// { +// // for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) +// // { +// // if (id == path.id) +// // { +// // return &path; +// // } +// // } -bool ChangeTalentsAction::AutoSelectTalents(std::ostringstream* out) -{ - // Does the bot have talentpoints? - if (bot->getLevel() < 10) - { - *out << "No free talent points."; - return false; - } +// // return &sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath[0]; +// return nullptr; +// } - uint32 specNo = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo"); - uint32 specId = specNo - 1; - std::string specLink = sRandomPlayerbotMgr->GetData(bot->GetGUID().GetCounter(), "specLink"); +// void ChangeTalentsAction::listPremadePaths(std::vector paths, std::ostringstream* out) +// { +// if (paths.size() == 0) +// { +// *out << "No predefined talents found.."; +// } - //Continue the current spec - if (specNo > 0) - { - TalentSpec newSpec = *GetBestPremadeSpec(specId); - newSpec.CropTalents(bot->getLevel()); - newSpec.ApplyTalents(bot, out); - if (newSpec.GetTalentPoints() > 0) - { - *out << "Upgrading spec " << "|h|cffffffff" << getPremadePath(specId)->name << "" << newSpec.FormatSpec(bot); - } - } - else if (!specLink.empty()) - { - TalentSpec newSpec(bot, specLink); - newSpec.CropTalents(bot->getLevel()); - newSpec.ApplyTalents(bot, out); - if (newSpec.GetTalentPoints() > 0) - { - *out << "Upgrading saved spec " - << "|h|cffffffff" << chat->FormatClass(bot, newSpec.highestTree()) << " (" << newSpec.FormatSpec(bot) << ")"; - } - } +// *out << "|h|cffffffff"; - //Spec was not found or not sufficient - if (bot->GetFreeTalentPoints() > 0 || (!specNo && specLink.empty())) - { - TalentSpec oldSpec(bot); - std::vector paths = getPremadePaths(&oldSpec); +// for (auto path : paths) +// { +// *out << path->name << " (" << path->talentSpec.back().FormatSpec(bot) << "), "; +// } - if (paths.size() == 0) //No spec like the old one found. Pick any. - { - if (bot->CalculateTalentsPoints() > 0) - *out << "No specs like the current spec found. "; +// out->seekp(-2, out->cur); +// *out << "."; +// } - paths = getPremadePaths(""); - } +// TalentPath* ChangeTalentsAction::PickPremadePath(std::vector paths, bool useProbability) +// { +// uint32 totProbability = 0; +// uint32 curProbability = 0; - if (paths.size() == 0) - { - *out << "No predefined talents found for this class."; - specId = -1; - // specLink = ""; - } - else if (paths.size() > 1 && false/*!sPlayerbotAIConfig->autoPickTalents*/ && !sRandomPlayerbotMgr->IsRandomBot(bot)) - { - *out << "Found multiple specs: "; - listPremadePaths(paths, out); - } - else - { - specId = PickPremadePath(paths, sRandomPlayerbotMgr->IsRandomBot(bot))->id; - TalentSpec newSpec = *GetBestPremadeSpec(specId); - specLink = newSpec.GetTalentLink(); - newSpec.CropTalents(bot->getLevel()); - newSpec.ApplyTalents(bot, out); +// if (paths.size() == 1) +// return paths[0]; - if (paths.size() > 1) - *out << "Found " << paths.size() << " possible specs to choose from. "; +// for (auto path : paths) +// { +// totProbability += useProbability ? path->probability : 1; +// } - *out << "Apply spec " << "|h|cffffffff" << getPremadePath(specId)->name << " " << newSpec.FormatSpec(bot); - } - } +// totProbability = urand(0, totProbability); - sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", specId + 1); +// for (auto path : paths) +// { +// curProbability += (useProbability ? path->probability : 1); +// if (curProbability >= totProbability) +// return path; +// } - if (!specLink.empty() && specId == -1) - sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink); - else - sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 0); +// return paths[0]; +// } - return (specNo == 0) ? false : true; -} +// bool ChangeTalentsAction::AutoSelectTalents(std::ostringstream* out) +// { +// // Does the bot have talentpoints? +// if (bot->getLevel() < 10) +// { +// *out << "No free talent points."; +// return false; +// } -//Returns a pre-made talentspec that best suits the bots current talents. -TalentSpec* ChangeTalentsAction::GetBestPremadeSpec(uint32 specId) -{ - TalentPath* path = getPremadePath(specId); - for (auto& spec : path->talentSpec) - { - if (spec.points >= bot->CalculateTalentsPoints()) - return &spec; - } +// uint32 specNo = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo"); +// uint32 specId = specNo - 1; +// std::string specLink = sRandomPlayerbotMgr->GetData(bot->GetGUID().GetCounter(), "specLink"); - if (path->talentSpec.size()) - return &path->talentSpec.back(); +// //Continue the current spec +// if (specNo > 0) +// { +// TalentSpec newSpec = *GetBestPremadeSpec(specId); +// newSpec.CropTalents(bot->getLevel()); +// newSpec.ApplyTalents(bot, out); +// if (newSpec.GetTalentPoints() > 0) +// { +// *out << "Upgrading spec " << "|h|cffffffff" << getPremadePath(specId)->name << "" << newSpec.FormatSpec(bot); +// } +// } +// else if (!specLink.empty()) +// { +// TalentSpec newSpec(bot, specLink); +// newSpec.CropTalents(bot->getLevel()); +// newSpec.ApplyTalents(bot, out); +// if (newSpec.GetTalentPoints() > 0) +// { +// *out << "Upgrading saved spec " +// << "|h|cffffffff" << chat->FormatClass(bot, newSpec.highestTree()) << " (" << newSpec.FormatSpec(bot) << ")"; +// } +// } - return &sPlayerbotAIConfig->classSpecs[bot->getClassMask()].baseSpec; -} +// //Spec was not found or not sufficient +// if (bot->GetFreeTalentPoints() > 0 || (!specNo && specLink.empty())) +// { +// TalentSpec oldSpec(bot); +// std::vector paths = getPremadePaths(&oldSpec); + +// if (paths.size() == 0) //No spec like the old one found. Pick any. +// { +// if (bot->CalculateTalentsPoints() > 0) +// *out << "No specs like the current spec found. "; + +// paths = getPremadePaths(""); +// } + +// if (paths.size() == 0) +// { +// *out << "No predefined talents found for this class."; +// specId = -1; +// // specLink = ""; +// } +// else if (paths.size() > 1 && false/*!sPlayerbotAIConfig->autoPickTalents*/ && !sRandomPlayerbotMgr->IsRandomBot(bot)) +// { +// *out << "Found multiple specs: "; +// listPremadePaths(paths, out); +// } +// else +// { +// specId = PickPremadePath(paths, sRandomPlayerbotMgr->IsRandomBot(bot))->id; +// TalentSpec newSpec = *GetBestPremadeSpec(specId); +// specLink = newSpec.GetTalentLink(); +// newSpec.CropTalents(bot->getLevel()); +// newSpec.ApplyTalents(bot, out); + +// if (paths.size() > 1) +// *out << "Found " << paths.size() << " possible specs to choose from. "; + +// *out << "Apply spec " << "|h|cffffffff" << getPremadePath(specId)->name << " " << newSpec.FormatSpec(bot); +// } +// } + +// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", specId + 1); + +// if (!specLink.empty() && specId == -1) +// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink); +// else +// sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 0); + +// return (specNo == 0) ? false : true; +// } + +// //Returns a pre-made talentspec that best suits the bots current talents. +// TalentSpec* ChangeTalentsAction::GetBestPremadeSpec(uint32 specId) +// { +// TalentPath* path = getPremadePath(specId); +// for (auto& spec : path->talentSpec) +// { +// if (spec.points >= bot->CalculateTalentsPoints()) +// return &spec; +// } + +// if (path->talentSpec.size()) +// return &path->talentSpec.back(); + +// // return &sPlayerbotAIConfig->classSpecs[bot->getClassMask()].baseSpec; +// return nullptr; +// } bool AutoSetTalentsAction::Execute(Event event) { diff --git a/src/strategy/actions/ChangeTalentsAction.h b/src/strategy/actions/ChangeTalentsAction.h index 6ef8460e..4ccb9e1b 100644 --- a/src/strategy/actions/ChangeTalentsAction.h +++ b/src/strategy/actions/ChangeTalentsAction.h @@ -16,15 +16,19 @@ class ChangeTalentsAction : public Action ChangeTalentsAction(PlayerbotAI* botAI, std::string const name = "talents") : Action(botAI, name) { } bool Execute(Event event); - bool AutoSelectTalents(std::ostringstream* out); + // bool AutoSelectTalents(std::ostringstream* out); private: - std::vector getPremadePaths(std::string const findName); - std::vector getPremadePaths(TalentSpec* oldSpec); - TalentPath* getPremadePath(uint32 id); - void listPremadePaths(std::vector paths, std::ostringstream* out); - TalentPath* PickPremadePath(std::vector paths, bool useProbability); - TalentSpec* GetBestPremadeSpec(uint32 spec); + // std::vector getPremadePaths(std::string const findName); + // std::vector getPremadePaths(TalentSpec* oldSpec); + // TalentPath* getPremadePath(uint32 id); + // void listPremadePaths(std::vector paths, std::ostringstream* out); + // TalentPath* PickPremadePath(std::vector paths, bool useProbability); + // TalentSpec* GetBestPremadeSpec(uint32 spec); + std::string TalentsHelp(); + std::string SpecList(); + std::string SpecPick(std::string param); + std::string SpecApply(std::string param); }; class AutoSetTalentsAction : public ChangeTalentsAction