# Talents

> Talent plans

Page: https://polestar.guide/docs/contributors/architecture/talents (Polestar docs > Contributors > Architecture)

`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).

```
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`.

---

Next page: [Toolchain](https://polestar.guide/docs/contributors/architecture/toolchain.md) · Every docs page: https://polestar.guide/llms.txt · All docs in one file: https://polestar.guide/llms-full.txt
