Talents

Contributor3 min readUpdated

In short

Talent plans

addon/Polestar/Talents/ (Talents\Talents.xml, loaded after Rares\Rares.xml): Talents.lua (settings talents.*, the plan per character in PolestarCharDB.talents.build, progress, validation, the unspent-point reminder), Builds.lua (generated by talents build), Overlay.lua (the talent frame), Options.lua (Questing → Talents → Talent plan), View.lua (the hub section, order 40).

text
Polestar.Talents.Current() -> { data, build, live, valid, level, granted, state, staged } | nil, reason
Polestar.Talents.State(build, ranks, level, granted) -> { status, done, total, next, nodeNext, offPlan, spent, points, unspent, source }  -- pure
Polestar.Talents.Replay(data, build) -> errors              -- pure; the snapshot's rules
Polestar.Talents.Validate(data, live) -> { map, back, moved, missing, ok }
Polestar.Talents.Choose(key | "auto")                       -- per character; "auto" follows Gear's spec, else the column with most points
Polestar.Talents.Show()                                     -- SHOW_TALENTS; /pole talents

Client

Forever's talents are one C_Traits tree per class (Paladin: TraitTree 1100), three spec columns, tier gates on points spent in a column, seven arrows. Every call goes through Talents.Client (C_ClassTalents.GetActiveConfigID, C_Traits.GetTreeNodes, GetNodeInfo, GetEntryInfo, GetDefinitionInfo, GetTreeCurrencyInfo). Refreshes are queued to one per frame on TRAIT_CONFIG_UPDATED, TRAIT_NODE_CHANGED, TRAIT_TREE_CURRENCY_INFO_UPDATED, ACTIVE_TALENT_GROUP_CHANGED, PLAYER_TALENT_UPDATE and Gear's spec changes; TALENTS_UPDATED follows.

Classes

One plan file per class (talents/forever/<class>.json); talents build writes them all into Builds.lua, one T.Register per class, sorted by class. T.Register keeps only the player's class (UnitClass("player")): the other classes' plans are dropped unexpanded, so a character holds one class's plans, not all nine. The tool finds each class's tree by its class skill line (CLASSES in tools/lib/talents/build.js) and leaves out a stray copy of a talent far off the grid (1.60.1.70374 and 1.60.1.70450: Hunter node 104982, Lightning Reflexes again; Priest node 105865, Holy Specialization again).

Validation

Builds.lua carries the tree the plans were replayed on. At run time each node is matched by ID (same rank count and name), else by name and rank count (a moved ID); a planned talent not found makes the plan out of date: the section says so and the frame gets no marks.

Points

A plan is an ordered sequence of picks, not a schedule: the addon never assumes when a point arrives (a Legacy talent such as Talented (Adventure) grants them from level 5). Granted points (spent plus unspent) come from the tree's currency (C_Traits.GetTreeCurrencyInfo, as the Recorder reads it); one point a level from 10 is the fallback only when the client gives none. Whenever a point is unspent the next pick is marked and the reminder names it; nothing is muted for the level cap. Levels in a plan's notes are shown as approximate ("Around level N").

Rules

The source plans are written one point a level from 10 (the replay's order); a pick is the next rank of its talent; gates and arrows as the tree has them. Of several arrows into one talent any one opens it (the client's SufficientForAvailability edges: the Hunter's Intimidation, from Bestial Swiftness or Bestial Wrath); a line the client only draws (TraitEdge type 0) is no arrow. Whether an arrow needs its source at full rank or one rank is PREREQ_RULE in tools/lib/talents/build.js (default "full", unconfirmed in game); Builds.lua carries it as prereq and Talents.Replay follows it.

Overlay

Post-hooks only: the frame's OnShow and EventRegistry's TalentFrameBase.ButtonsUpdated / ConfigUpdated, and each button's OnEnter (HookScript) for the tooltip line. Marks are our own child frames: a ring on the next pick while a point is unspent, the pick number of each talent's next planned rank (an order, never a level), a flag on ranks off the plan; the tooltip line says "pick #N". Staged ranks count. Nothing is drawn while inspecting or for a loadout that is not the active one; in combat the redraw waits for PLAYER_REGEN_ENABLED.
Was this page helpful?

Start with, or act

  • PlayersInstall and first run
  • PlayersCommunity guides
  • PlayersFAQ
  • Guide authorsWriting a community guide
  • Guide authorsGuide format cheatsheet
  • ContributorsContributing
  • ActionCopy the AddOns folder (Windows)C:\Program Files (x86)\World of Warcraft\_classic_beta_\Interface\AddOns
  • ActionCopy the AddOns folder (macOS)/Applications/World of Warcraft/_classic_beta_/Interface/AddOns
  • ActionFind an optionEvery setting with its default; type its name here to jump to it.
  • ActionEvery slash command