Rebuild talents command

This commit is contained in:
Yunfan Li
2024-01-14 14:54:48 +08:00
parent 8af79825e4
commit 1d21feb1ea
9 changed files with 620 additions and 561 deletions

View File

@@ -445,131 +445,191 @@ PlayerbotsDatabase.SynchThreads = 1
Playerbots.Updates.EnableDatabases = 1 Playerbots.Updates.EnableDatabases = 1
############################################## ##############################################
# TalentSpec # # PremadeSpec #
############################################## ##############################################
# AiPlayerbot.PremadeSpecName.<class>.<specno> = <name> #Name of the talent specialisation
# AiPlayerbot.PremadeSpecLink.<class>.<specno>.<level> = <link> #Wowhead style link the bot should work towards at given level.
# 0 <= specno < 20, 1 <= level <= 80
# Warrior # Warrior
AiPlayerbot.RandomClassSpecProbability.1.0 = 20 AiPlayerbot.PremadeSpecName.1.0 = arms pve
AiPlayerbot.DefaultTalentsOrderLowLevel.1.0 = AiPlayerbot.PremadeSpecLink.1.0.60 =
AiPlayerbot.DefaultTalentsOrder.1.0 = 3022032123335100202012013031251-32505010002 AiPlayerbot.PremadeSpecLink.1.0.80 = 3022032123335100202012013031251-32505010002
AiPlayerbot.RandomClassSpecProbability.1.1 = 40 # AiPlayerbot.PremadeSpecGlyph.1.0 = 0,0,0,0,0,0
AiPlayerbot.DefaultTalentsOrderLowLevel.1.1 = AiPlayerbot.PremadeSpecName.1.1 = fury pve
AiPlayerbot.DefaultTalentsOrder.1.1 = 30202300233-305053000500310153120511351 AiPlayerbot.PremadeSpecLink.1.1.60 =
AiPlayerbot.RandomClassSpecProbability.1.2 = 40 AiPlayerbot.PremadeSpecLink.1.1.80 = 30202300233-305053000500310153120511351
AiPlayerbot.DefaultTalentsOrderLowLevel.1.2 = AiPlayerbot.PremadeSpecName.1.2 = prot pve
AiPlayerbot.DefaultTalentsOrder.1.2 = 3500030023-301-053351225000210521030113321 AiPlayerbot.PremadeSpecLink.1.2.60 =
AiPlayerbot.PremadeSpecLink.1.2.80 = 3500030023-301-053351225000210521030113321
# Paladin # Paladin
AiPlayerbot.RandomClassSpecProbability.2.0 = 30 AiPlayerbot.PremadeSpecName.2.0 = holy pve
AiPlayerbot.DefaultTalentsOrderLowLevel.2.0 = AiPlayerbot.PremadeSpecLink.2.0.60 =
AiPlayerbot.DefaultTalentsOrder.2.0 = 50350152220013053100515221-503201312 AiPlayerbot.PremadeSpecLink.2.0.80 = 50350152220013053100515221-503201312
AiPlayerbot.RandomClassSpecProbability.2.1 = 40 AiPlayerbot.PremadeSpecName.2.1 = prot pve
AiPlayerbot.DefaultTalentsOrderLowLevel.2.1 = AiPlayerbot.PremadeSpecLink.2.1.60 =
AiPlayerbot.DefaultTalentsOrder.2.1 = -05005135203132311333312321-5023005 AiPlayerbot.PremadeSpecLink.2.1.80 = -05005135203132311333312321-5023005
AiPlayerbot.RandomClassSpecProbability.2.2 = 30 AiPlayerbot.PremadeSpecName.2.2 = ret pve
AiPlayerbot.DefaultTalentsOrderLowLevel.2.2 = AiPlayerbot.PremadeSpecLink.2.2.60 =
AiPlayerbot.DefaultTalentsOrder.2.2 = 050501-05-05232051203331302133231331 AiPlayerbot.PremadeSpecLink.2.2.80 = 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
# no idea - TC was requesting these.. so.. # Hunter
AiPlayerbot.RandomClassSpecProbability.0.0 = 33 AiPlayerbot.PremadeSpecName.3.0 = bm pve
AiPlayerbot.DefaultTalentsOrderLowLevel.0.0 = AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112243100511351
AiPlayerbot.DefaultTalentsOrder.0.0 = AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112253100531351-015305021
AiPlayerbot.RandomClassSpecProbability.0.1 = 33 AiPlayerbot.PremadeSpecName.3.1 = mm pve
AiPlayerbot.DefaultTalentsOrderLowLevel.0.1 = AiPlayerbot.PremadeSpecLink.3.1.60 =
AiPlayerbot.DefaultTalentsOrder.0.1 = AiPlayerbot.PremadeSpecLink.3.1.80 = 502-035305101230013233135031351-5000002
AiPlayerbot.RandomClassSpecProbability.0.2 = 33 AiPlayerbot.PremadeSpecName.3.2 = surv pve
AiPlayerbot.DefaultTalentsOrderLowLevel.0.2 = AiPlayerbot.PremadeSpecLink.3.2.60 =
AiPlayerbot.DefaultTalentsOrder.0.2 = AiPlayerbot.PremadeSpecLink.3.2.80 = -0053041-5000032500033330523134321331
AiPlayerbot.RandomClassSpecProbability.10.0 = 33 # Rogue
AiPlayerbot.DefaultTalentsOrderLowLevel.10.0 = AiPlayerbot.PremadeSpecName.4.0 = ass pve
AiPlayerbot.DefaultTalentsOrder.10.0 = AiPlayerbot.PremadeSpecLink.4.0.60 =
AiPlayerbot.RandomClassSpecProbability.10.1 = 33 AiPlayerbot.PremadeSpecLink.4.0.80 = 005323005350100520103331051-005005003-502
AiPlayerbot.DefaultTalentsOrderLowLevel.10.1 = AiPlayerbot.PremadeSpecName.4.1 = combat pve
AiPlayerbot.DefaultTalentsOrder.10.1 = AiPlayerbot.PremadeSpecLink.4.1.60 =
AiPlayerbot.RandomClassSpecProbability.10.2 = 33 AiPlayerbot.PremadeSpecLink.4.1.80 = 30530000522-0252051000035015223100501251
AiPlayerbot.DefaultTalentsOrderLowLevel.10.2 = AiPlayerbot.PremadeSpecName.4.2 = subtlety pve
AiPlayerbot.DefaultTalentsOrder.10.2 = 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.<class>.<specno> # The probability to choose the spec
# AiPlayerbot.RandomClassSpecIndex.<class>.<specno> # 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
################################################################################## ##################################################################################
# # # #

View File

@@ -593,8 +593,10 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies); nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies);
} }
else else {
// nonCombatEngine->addStrategy("pvp");
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies); nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies);
}
} }
} }
} }

View File

@@ -164,96 +164,33 @@ bool PlayerbotAIConfig::Initialize()
for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) 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; std::ostringstream os;
os << "AiPlayerbot.RandomClassSpecProbability." << cls << "." << spec; os << "AiPlayerbot.PremadeSpecName." << cls << "." << spec;
specProbability[cls][spec] = sConfigMgr->GetOption<uint32>(os.str().c_str(), 33); premadeSpecName[cls][spec] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "");
os.str(""); for (uint32 level = 0; level < MAX_LEVEL; ++level) {
os.clear(); std::ostringstream os;
os << "AiPlayerbot.DefaultTalentsOrder." << cls << "." << spec; os << "AiPlayerbot.PremadeSpecLink." << cls << "." << spec << "." << level;
std::string temp_talents_order = sConfigMgr->GetOption<std::string>(os.str().c_str(), ""); premadeSpecLink[cls][spec][level] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "");
defaultTalentsOrder[cls][spec] = ParseTempTalentsOrder(cls, temp_talents_order); parsedSpecLinkOrder[cls][spec][level] = ParseTempTalentsOrder(cls, premadeSpecLink[cls][spec][level]);
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) for (uint32 spec = 0; spec < 3; ++spec)
{ {
std::ostringstream os; std::ostringstream os;
os << "AiPlayerbot.RandomClassSpecProbability." << cls << "." << spec; os << "AiPlayerbot.RandomClassSpecProb." << cls << "." << spec;
specProbability[cls][spec] = sConfigMgr->GetOption<uint32>(os.str().c_str(), 33); randomClassSpecProb[cls][spec] = sConfigMgr->GetOption<uint32>(os.str().c_str(), 33);
os.str(""); os.str("");
os.clear(); os.clear();
os << "AiPlayerbot.DefaultTalentsOrderLowLevel." << cls << "." << spec; os << "AiPlayerbot.RandomClassSpecIndex." << cls << "." << spec;
std::string temp_talents_order = sConfigMgr->GetOption<std::string>(os.str().c_str(), ""); randomClassSpecIndex[cls][spec] = sConfigMgr->GetOption<uint32>(os.str().c_str(), spec + 1);
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<std::string>(os.str().c_str(), "", false);
// if (!specName.empty())
// {
// std::ostringstream os;
// os << "AiPlayerbot.PremadeSpecProb." << cls << "." << spec;
// uint32 probability = sConfigMgr->GetOption<int32>(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<std::string>(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(); botCheats.clear();
LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.BotCheats", "taxi"), botCheats); LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.BotCheats", "taxi"), botCheats);
@@ -561,7 +498,7 @@ static std::vector<std::string> split(const std::string &str, const std::string
std::vector<std::string> res; std::vector<std::string> res;
if(str == "") if(str == "")
return res; return res;
//在字符串末尾也加入分隔符,方便截取最后一段 // Also add separators to string connections to facilitate intercepting the last paragraph.
std::string strs = str + pattern; std::string strs = str + pattern;
size_t pos = strs.find(pattern); size_t pos = strs.find(pattern);
@@ -569,7 +506,7 @@ static std::vector<std::string> split(const std::string &str, const std::string
{ {
std::string temp = strs.substr(0, pos); std::string temp = strs.substr(0, pos);
res.push_back(temp); res.push_back(temp);
//去掉已分割的字符串,在剩下的字符串中进行分割 // Remove the split string and split the remaining string
strs = strs.substr(pos+1, strs.size()); strs = strs.substr(pos+1, strs.size());
pos = strs.find(pattern); pos = strs.find(pattern);
} }
@@ -584,7 +521,6 @@ std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempTalentsOrder(uint32
std::vector<std::string> tab_links = split(tab_link, "-"); std::vector<std::string> tab_links = split(tab_link, "-");
std::map<uint32, std::vector<TalentEntry const*>> spells; std::map<uint32, std::vector<TalentEntry const*>> spells;
std::vector<std::vector<std::vector<uint32>>> orders(3); std::vector<std::vector<std::vector<uint32>>> orders(3);
// orders.assign(3);
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{ {
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
@@ -623,37 +559,5 @@ std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempTalentsOrder(uint32
for (auto &order : orders) { for (auto &order : orders) {
res.insert(res.end(), order.begin(), order.end()); res.insert(res.end(), order.begin(), order.end());
} }
// for (std::vector<uint32> &p : sPlayerbotAIConfig->defaultTalentsOrder[bot->getClass()][specNo]) {
// uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3];
// uint32 talentID = -1;
// std::vector<TalentEntry const*> &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; return res;
} }

View File

@@ -6,6 +6,7 @@
#define _PLAYERBOT_PLAYERbotAICONFIG_H #define _PLAYERBOT_PLAYERbotAICONFIG_H
#include "Common.h" #include "Common.h"
#include "DBCEnums.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "Talentspec.h" #include "Talentspec.h"
@@ -22,6 +23,8 @@ enum class BotCheatMask : uint32
maxMask = 32 maxMask = 32
}; };
#define MAX_SPECNO 20
class PlayerbotAIConfig class PlayerbotAIConfig
{ {
public: public:
@@ -88,12 +91,17 @@ class PlayerbotAIConfig
std::string randomBotCombatStrategies, randomBotNonCombatStrategies; std::string randomBotCombatStrategies, randomBotNonCombatStrategies;
uint32 randomBotMinLevel, randomBotMaxLevel; uint32 randomBotMinLevel, randomBotMaxLevel;
float randomChangeMultiplier; float randomChangeMultiplier;
uint32 specProbability[MAX_CLASSES][10];
// [(tab, row, col, level)]
std::vector<std::vector<uint32>> defaultTalentsOrder[MAX_CLASSES][3]; // std::string premadeLevelSpec[MAX_CLASSES][10][91]; //lvl 10 - 100
std::vector<std::vector<uint32>> defaultTalentsOrderLowLevel[MAX_CLASSES][3]; // 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<std::vector<uint32>> 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 commandPrefix, commandSeparator;
std::string randomBotAccountPrefix; std::string randomBotAccountPrefix;
uint32 randomBotAccountCount; uint32 randomBotAccountCount;
@@ -192,8 +200,7 @@ class PlayerbotAIConfig
void log(std::string const fileName, const char* str, ...); void log(std::string const fileName, const char* str, ...);
void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel); void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel);
private: static std::vector<std::vector<uint32>> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order);
std::vector<std::vector<uint32>> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order);
}; };
#define sPlayerbotAIConfig PlayerbotAIConfig::instance() #define sPlayerbotAIConfig PlayerbotAIConfig::instance()

View File

@@ -180,18 +180,14 @@ void PlayerbotFactory::Randomize(bool incremental)
LOG_INFO("playerbots", "Initializing spells (step 1)..."); LOG_INFO("playerbots", "Initializing spells (step 1)...");
// bot->LearnDefaultSkills(); // bot->LearnDefaultSkills();
InitClassSpells(); InitClassSpells();
// bot->SaveToDB(false, false);
InitAvailableSpells(); InitAvailableSpells();
// bot->SaveToDB(false, false);
if (pmo) if (pmo)
pmo->finish(); pmo->finish();
LOG_INFO("playerbots", "Initializing skills (step 1)..."); LOG_INFO("playerbots", "Initializing skills (step 1)...");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1"); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1");
InitSkills(); InitSkills();
// bot->SaveToDB(false, false);
InitSpecialSpells(); InitSpecialSpells();
// bot->SaveToDB(false, false);
// InitTradeSkills(); // InitTradeSkills();
if (pmo) if (pmo)
@@ -200,7 +196,6 @@ void PlayerbotFactory::Randomize(bool incremental)
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents"); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents");
LOG_INFO("playerbots", "Initializing talents..."); LOG_INFO("playerbots", "Initializing talents...");
InitTalentsTree(); InitTalentsTree();
// bot->SaveToDB(false, false);
sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", 0); sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", 0);
if (botAI) { if (botAI) {
sPlayerbotDbStore->Reset(botAI); sPlayerbotDbStore->Reset(botAI);
@@ -213,7 +208,6 @@ void PlayerbotFactory::Randomize(bool incremental)
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2"); pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2");
LOG_INFO("playerbots", "Initializing spells (step 2)..."); LOG_INFO("playerbots", "Initializing spells (step 2)...");
InitAvailableSpells(); InitAvailableSpells();
// bot->SaveToDB(false, false);
if (pmo) if (pmo)
pmo->finish(); pmo->finish();
@@ -797,28 +791,141 @@ void PlayerbotFactory::InitSpells()
void PlayerbotFactory::InitTalentsTree(bool increment/*false*/, bool use_template/*true*/, bool reset/*false*/) void PlayerbotFactory::InitTalentsTree(bool increment/*false*/, bool use_template/*true*/, bool reset/*false*/)
{ {
uint32 specNo; uint32 specTab;
uint8 cls = bot->getClass(); uint8 cls = bot->getClass();
std::map<uint8, uint32> tabs = AiFactory::GetPlayerSpecTabs(bot); std::map<uint8, uint32> tabs = AiFactory::GetPlayerSpecTabs(bot);
uint32 total_tabs = tabs[0] + tabs[1] + tabs[2]; uint32 total_tabs = tabs[0] + tabs[1] + tabs[2];
if (increment && bot->GetFreeTalentPoints() <= 2 && total_tabs != 0) { if (increment && total_tabs != 0) {
specNo = AiFactory::GetPlayerSpecTab(bot); specTab = AiFactory::GetPlayerSpecTab(bot);
} else { } else {
uint32 point = urand(0, 100); uint32 point = urand(0, 100);
uint32 p1 = sPlayerbotAIConfig->specProbability[cls][0]; uint32 p1 = sPlayerbotAIConfig->randomClassSpecProb[cls][0];
uint32 p2 = p1 + sPlayerbotAIConfig->specProbability[cls][1]; uint32 p2 = p1 + sPlayerbotAIConfig->randomClassSpecProb[cls][1];
specNo = (point < p1 ? 0 : (point < p2 ? 1 : 2)); specTab = point < p1 ? 0 : (point < p2 ? 1 : 2);
} }
if (reset) { if (reset) {
bot->resetTalents(true); bot->resetTalents(true);
} }
// use template if can // use template if can
if (use_template && sPlayerbotAIConfig->defaultTalentsOrder[cls][specNo].size() > 0) { if (use_template) {
InitTalentsByTemplate(specNo); InitTalentsByTemplate(specTab);
} else { } else {
InitTalents(specNo); InitTalents(specTab);
if (bot->GetFreeTalentPoints()) 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<uint32, std::vector<TalentEntry const*> > 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<uint32> &p : sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][level]) {
uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3];
uint32 talentID = -1;
std::vector<TalentEntry const*> &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<std::vector<uint32>> parsedSpecLink, bool reset)
{
if (reset) {
bot->resetTalents(true);
}
uint32 classMask = bot->getClassMask();
std::map<uint32, std::vector<TalentEntry const*> > 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<uint32> &p : parsedSpecLink) {
uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3];
uint32 talentID = -1;
std::vector<TalentEntry const*> &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) { // if (sPlayerbotAIConfig->parsedSpecLinkOrder[bot->getClass()][specNo][80].size() == 0) {
return; // return;
} // }
uint32 cls = bot->getClass();
int startLevel = bot->GetLevel();
uint32 specIndex = sPlayerbotAIConfig->randomClassSpecIndex[cls][specTab];
uint32 classMask = bot->getClassMask(); uint32 classMask = bot->getClassMask();
std::map<uint32, std::vector<TalentEntry const*> > spells_row; std::map<uint32, std::vector<TalentEntry const*> > spells_row;
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
@@ -2142,10 +2252,14 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo)
spells_row[talentInfo->Row].push_back(talentInfo); spells_row[talentInfo->Row].push_back(talentInfo);
} }
while (startLevel > 1 && startLevel < 80 && sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][startLevel].size() == 0) {
// bot->SaveToDB(); startLevel--;
if (bot->GetLevel() < 80 && sPlayerbotAIConfig->defaultTalentsOrder[bot->getClass()][specNo].size() != 0) { }
for (std::vector<uint32> &p : sPlayerbotAIConfig->defaultTalentsOrderLowLevel[bot->getClass()][specNo]) { for (int level = startLevel; level <= 80; level++) {
if (sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][level].size() == 0) {
continue;
}
for (std::vector<uint32> &p : sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specIndex][level]) {
uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3]; uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3];
uint32 talentID = -1; uint32 talentID = -1;
@@ -2153,7 +2267,6 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo)
if (spells.size() <= 0) { if (spells.size() <= 0) {
return; return;
} }
// assert(spells.size() > 0);
for (TalentEntry const* talentInfo : spells) { for (TalentEntry const* talentInfo : spells) {
if (talentInfo->Col != col) { if (talentInfo->Col != col) {
continue; continue;
@@ -2167,38 +2280,11 @@ void PlayerbotFactory::InitTalentsByTemplate(uint32 specNo)
} }
talentID = talentInfo->TalentID; talentID = talentInfo->TalentID;
} }
assert(talentID != -1);
bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1); bot->LearnTalent(talentID, std::min(lvl, bot->GetFreeTalentPoints()) - 1);
if (bot->GetFreeTalentPoints() == 0) { if (bot->GetFreeTalentPoints() == 0) {
break; break;
} }
} }
}
for (std::vector<uint32> &p : sPlayerbotAIConfig->defaultTalentsOrder[bot->getClass()][specNo]) {
uint32 tab = p[0], row = p[1], col = p[2], lvl = p[3];
uint32 talentID = -1;
std::vector<TalentEntry const*> &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) { if (bot->GetFreeTalentPoints() == 0) {
break; break;
} }

View File

@@ -117,6 +117,8 @@ class PlayerbotFactory
static uint32 tradeSkills[]; static uint32 tradeSkills[];
static float CalculateItemScore(uint32 item_id, Player* bot); static float CalculateItemScore(uint32 item_id, Player* bot);
void InitTalentsTree(bool incremental = false, bool use_template = true, bool reset = false); 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<std::vector<uint32>> parsedSpecLink, bool reset);
void InitAvailableSpells(); void InitAvailableSpells();
void InitClassSpells(); void InitClassSpells();
void InitEquipment(bool incremental); void InitEquipment(bool incremental);

View File

@@ -18,6 +18,7 @@ struct TalentTabEntry;
#define ADDED_POINTS 2 #define ADDED_POINTS 2
#define REMOVED_POINTS -2 #define REMOVED_POINTS -2
// unused currently
class TalentSpec class TalentSpec
{ {
public: public:

View File

@@ -3,8 +3,10 @@
*/ */
#include "ChangeTalentsAction.h" #include "ChangeTalentsAction.h"
#include "AiFactory.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Event.h" #include "Event.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -18,312 +20,303 @@ bool ChangeTalentsAction::Execute(Event event)
if (!param.empty()) if (!param.empty())
{ {
// if (param.find("auto") != std::string::npos) if (param.find("help") != std::string::npos) {
// { out << TalentsHelp();
// AutoSelectTalents(&out); } else if (param.find("switch") != std::string::npos) {
// } if (param == "1") {
// else if (param.find("list ") != std::string::npos) bot->ActivateSpec(0);
// { out << "Active first talent";
// listPremadePaths(getPremadePaths(param.substr(5)), &out); } else if (param == "2") {
// } bot->ActivateSpec(1);
// else if (param.find("list") != std::string::npos) out << "Active second talent";
// { }
// listPremadePaths(getPremadePaths(""), &out); } else if (param.find("autopick") != std::string::npos) {
if (param == "1") { PlayerbotFactory factory(bot, bot->GetLevel());
bot->ActivateSpec(0); factory.InitTalentsTree(true);
} else if (param == "2") { out << "Auto pick talents";
bot->ActivateSpec(1); } 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<TalentPath*> 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 else
// { {
// uint32 specId = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo") - 1; uint32 tab = AiFactory::GetPlayerSpecTab(bot);
// std::string specName = ""; out << "My current talent spec is: " << "|h|cffffffff";
// TalentPath* specPath; out << chat->FormatClass(bot, tab) << "\n";
// if (specId) out << TalentsHelp();
// { }
// 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();
// }
botAI->TellMaster(out); botAI->TellMaster(out);
return true; return true;
} }
std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(std::string const findName) std::string ChangeTalentsAction::TalentsHelp()
{ {
std::vector<TalentPath*> ret; std::ostringstream out;
for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) out << "Talents usage: talents switch <1/2>, talents autopick, talents spec list, "
{ "talents spec <specName>, talents apply <link>.";
if (findName.empty() || path.name.find(findName) != std::string::npos) return out.str();
{
ret.push_back(&path);
}
}
return std::move(ret);
} }
std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(TalentSpec* oldSpec) std::string ChangeTalentsAction::SpecList()
{ {
std::vector<TalentPath*> ret; int cls = bot->getClass();
int specFound = 0;
for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) std::ostringstream out;
{ for (int specNo = 0; specNo < MAX_SPECNO; ++specNo) {
TalentSpec newSpec = *GetBestPremadeSpec(path.id); if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0) {
newSpec.CropTalents(bot->getLevel()); break;
if (oldSpec->isEarlierVersionOf(newSpec))
{
ret.push_back(&path);
} }
specFound++;
std::ostringstream out;
std::vector<std::vector<uint32>> parsed = sPlayerbotAIConfig->parsedSpecLinkOrder[cls][specNo][80];
std::unordered_map<int, int> 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());
} }
out << "Total " << specFound << " specs found";
return std::move(ret); return out.str();
} }
TalentPath* ChangeTalentsAction::getPremadePath(uint32 id) std::string ChangeTalentsAction::SpecPick(std::string param)
{ {
for (auto& path : sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath) int cls = bot->getClass();
{ int specFound = 0;
if (id == path.id) for (int specNo = 0; specNo < MAX_SPECNO; ++specNo) {
{ if (sPlayerbotAIConfig->premadeSpecName[cls][specNo].size() == 0) {
return &path; break;
}
if (sPlayerbotAIConfig->premadeSpecName[cls][specNo] == param) {
PlayerbotFactory::InitTalentsBySpecNo(bot, specNo, true);
std::ostringstream out;
out << "Picking " << sPlayerbotAIConfig->premadeSpecName[cls][specNo];
return out.str();
} }
} }
std::ostringstream out;
return &sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath[0]; out << "Spec " << param << " not found";
return out.str();
} }
void ChangeTalentsAction::listPremadePaths(std::vector<TalentPath*> paths, std::ostringstream* out)
std::string ChangeTalentsAction::SpecApply(std::string param)
{ {
if (paths.size() == 0) int cls = bot->getClass();
{ std::ostringstream out;
*out << "No predefined talents found.."; std::vector<std::vector<uint32>> parsedSpecLink = PlayerbotAIConfig::ParseTempTalentsOrder(cls, param);
if (parsedSpecLink.size() == 0) {
out << "Invalid link " << param;
return out.str();
} }
PlayerbotFactory::InitTalentsByParsedSpecLink(bot, parsedSpecLink, true);
*out << "|h|cffffffff"; out << "Applying " << param;
return out.str();
for (auto path : paths)
{
*out << path->name << " (" << path->talentSpec.back().FormatSpec(bot) << "), ";
}
out->seekp(-2, out->cur);
*out << ".";
} }
TalentPath* ChangeTalentsAction::PickPremadePath(std::vector<TalentPath*> paths, bool useProbability) // std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(std::string const findName)
{ // {
uint32 totProbability = 0; // std::vector<TalentPath*> ret;
uint32 curProbability = 0; // // 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 std::move(ret);
return paths[0]; // }
for (auto path : paths) // std::vector<TalentPath*> ChangeTalentsAction::getPremadePaths(TalentSpec* oldSpec)
{ // {
totProbability += useProbability ? path->probability : 1; // std::vector<TalentPath*> 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) // return std::move(ret);
{ // }
curProbability += (useProbability ? path->probability : 1);
if (curProbability >= totProbability)
return path;
}
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) // // return &sPlayerbotAIConfig->classSpecs[bot->getClass()].talentPath[0];
{ // return nullptr;
// Does the bot have talentpoints? // }
if (bot->getLevel() < 10)
{
*out << "No free talent points.";
return false;
}
uint32 specNo = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo"); // void ChangeTalentsAction::listPremadePaths(std::vector<TalentPath*> paths, std::ostringstream* out)
uint32 specId = specNo - 1; // {
std::string specLink = sRandomPlayerbotMgr->GetData(bot->GetGUID().GetCounter(), "specLink"); // if (paths.size() == 0)
// {
// *out << "No predefined talents found..";
// }
//Continue the current spec // *out << "|h|cffffffff";
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) << ")";
}
}
//Spec was not found or not sufficient // for (auto path : paths)
if (bot->GetFreeTalentPoints() > 0 || (!specNo && specLink.empty())) // {
{ // *out << path->name << " (" << path->talentSpec.back().FormatSpec(bot) << "), ";
TalentSpec oldSpec(bot); // }
std::vector<TalentPath*> paths = getPremadePaths(&oldSpec);
if (paths.size() == 0) //No spec like the old one found. Pick any. // out->seekp(-2, out->cur);
{ // *out << ".";
if (bot->CalculateTalentsPoints() > 0) // }
*out << "No specs like the current spec found. ";
paths = getPremadePaths(""); // TalentPath* ChangeTalentsAction::PickPremadePath(std::vector<TalentPath*> paths, bool useProbability)
} // {
// uint32 totProbability = 0;
// uint32 curProbability = 0;
if (paths.size() == 0) // if (paths.size() == 1)
{ // return paths[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) // for (auto path : paths)
*out << "Found " << paths.size() << " possible specs to choose from. "; // {
// 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) // return paths[0];
sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 1, specLink); // }
else
sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specLink", 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. // uint32 specNo = sRandomPlayerbotMgr->GetValue(bot->GetGUID().GetCounter(), "specNo");
TalentSpec* ChangeTalentsAction::GetBestPremadeSpec(uint32 specId) // uint32 specId = specNo - 1;
{ // std::string specLink = sRandomPlayerbotMgr->GetData(bot->GetGUID().GetCounter(), "specLink");
TalentPath* path = getPremadePath(specId);
for (auto& spec : path->talentSpec)
{
if (spec.points >= bot->CalculateTalentsPoints())
return &spec;
}
if (path->talentSpec.size()) // //Continue the current spec
return &path->talentSpec.back(); // 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<TalentPath*> 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) bool AutoSetTalentsAction::Execute(Event event)
{ {

View File

@@ -16,15 +16,19 @@ class ChangeTalentsAction : public Action
ChangeTalentsAction(PlayerbotAI* botAI, std::string const name = "talents") : Action(botAI, name) { } ChangeTalentsAction(PlayerbotAI* botAI, std::string const name = "talents") : Action(botAI, name) { }
bool Execute(Event event); bool Execute(Event event);
bool AutoSelectTalents(std::ostringstream* out); // bool AutoSelectTalents(std::ostringstream* out);
private: private:
std::vector<TalentPath*> getPremadePaths(std::string const findName); // std::vector<TalentPath*> getPremadePaths(std::string const findName);
std::vector<TalentPath*> getPremadePaths(TalentSpec* oldSpec); // std::vector<TalentPath*> getPremadePaths(TalentSpec* oldSpec);
TalentPath* getPremadePath(uint32 id); // TalentPath* getPremadePath(uint32 id);
void listPremadePaths(std::vector<TalentPath*> paths, std::ostringstream* out); // void listPremadePaths(std::vector<TalentPath*> paths, std::ostringstream* out);
TalentPath* PickPremadePath(std::vector<TalentPath*> paths, bool useProbability); // TalentPath* PickPremadePath(std::vector<TalentPath*> paths, bool useProbability);
TalentSpec* GetBestPremadeSpec(uint32 spec); // 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 class AutoSetTalentsAction : public ChangeTalentsAction