This is a full class that can be run as a state.
It works based on wowhead talent strings and talents are assigned "historically" meaning you have to give it different states of the talent tree depending on how you want talents to be assigned as you level up.
If you look at the code, it uses Lua to call the LearnTalent function with the index it calculates. You can also hard code this.
By default, these talent trees are for vanilla and TBC, the WoWVersion check deactivates this for WotLK.
public class TalentPoints : State
{
public override string DisplayName => "TalentPoints";
private static readonly Dictionary<WoWClass, List<string>> ClassTalents = new Dictionary<WoWClass, List<string>>
{
{
WoWClass.Mage, new List<string>
{
"--05003230", "--0501323010005", "--0501323010235", "--050132301023513", "--05023230102351301", "--05053230102351301", "230005--05053230102351301",
"23005500002--05053230102351301"
}
},
{
WoWClass.Druid, new List<string>
{
"-53020203", "-53020203002", "-53020203032001", "-53020203032021", "-5302020303222151", "-5302020303222151-05", "0140003-5302020303222151-05",
"014005301-5402020303222151-05"
}
},
{
WoWClass.Rogue, new List<string>
{
"-02", "-32005001", "-32005521000201", "-3200552100050110231", "005003-3200552100050110231", "3050031053-3200552100050110231"
}
},
{
WoWClass.Priest, new List<string>
{
"--50023001", "--50023221004", "--50023221014012", "--5002322103411241", "--5002322103411251", "05003213--5002522103511251"
}
},
{
WoWClass.Hunter, new List<string>
{
"55000001", "550002015", "5500020150201", "5500020150221", "5500020150521041", "5500020150521251-050514002"
}
},
{
WoWClass.Warlock, new List<string>
{
"05-00503", "05002-00503", "05002-20523", "050221001-20523", "050221301-20523", "05022230102-20523", "0502253010201-20523", "0502253010201-2052300122",
"0502253010201-2052300152", "0502253012201-2052300152", "2502253012201005-2052310152"
}
},
{
WoWClass.Paladin, new List<string>
{
"--052300012", "--052300512", "--0523025120001", "--0523025120031", "-052303512003151", "--052303512203151", "-5032010043-052303512203151"
}
},
{
WoWClass.Shaman, new List<string>
{
"-50050001", "-50252001050001", "-50252001050031", "-5025200115003151", "5-5025200115003151-50005301", "5-5025200125003151-50005301"
}
},
{
WoWClass.Warrior, new List<string>
{
"023230003", "02323020302", "0232502130201", "0232502135201", "023250213524100001", "023250213524100001-05053020005"
}
},
};
public override void Run()
{
var talentStrings = (PluginSettings.In.TalentStrings.IsNullOrEmpty() || PluginSettings.In.TalentStrings.All(string.IsNullOrWhiteSpace))
? ClassTalents[ObjectManager.Me.WowClass]
: PluginSettings.In.TalentStrings.ToList();
foreach (var talentString in talentStrings)
{
// "-545" results in "" and "545", "--545"
var trees = talentString.Split('-');
//spec every tree left to right
for (var i = 0; i < trees.Length; i++)
{
var talentsString = trees[i];
if (string.IsNullOrWhiteSpace(talentsString))
{
continue;
}
// Wow uses index starting at 1
var talentTree = i + 1;
List<uint> talents = talentsString.ToCharArray().Select(s => (uint) char.GetNumericValue(s)).ToList();
//Logger.Info($"{talentTree} {talentsString} {talents.Select(x => x.ToString()).Aggregate((s1, s2) => s1 + "," + s2)}");
// Talent points are meant to be spent by priority. Whenever a new point is available, we need to run the whole algorithm again
var successfullySpent = LearnTalents(talentTree, talents);
if (successfullySpent)
{
return;
}
}
}
}
private bool LearnTalents(int tree, List<uint> talents)
{
if (tree <= 0 || talents.IsNullOrEmpty())
{
return false;
}
// we iterate the talents from left to right as they are used in the talent calculator for each tree
return Lua.LuaDoString<bool>($@"
local tree = {tree};
local talents = {{ {talents.Select(u => u.ToString()).Aggregate((s1, s2) => s1 + ", " + s2)} }};
local talentIndex = 1;
for k, talent in pairs(talents) do
local name, iconPath, iconX, iconY, currentRank, maxRank = GetTalentInfo(tree, talentIndex);
--if name then print(name .. ' at index ' .. talentIndex .. ' and rank ' .. currentRank .. ' needs to be rank ' .. talent); end
if (name and currentRank < talent) then
--print(name .. ' ' .. currentRank .. ' needs to be ' .. talent);
LearnTalent(tree, talentIndex);
return true; -- we can't learn multiple talents at once, talent points are spent as if they were historically given one per level up
end
talentIndex = talentIndex + 1;
end
-- no talent points spent
return false;
");
}
// don't change this! just returning UnitCharacterPoints is bugged
public override bool NeedToRun => Conditions.InGameAndConnectedAndAliveAndProductStartedNotInPause && Helper.RealWowVersion < 12340 &&
Lua.LuaDoString<int>("local talents = UnitCharacterPoints('player'); return talents") > 0;
}