# QoL

> Quality-of-life helpers

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

## Quest reward marks — QoL, reads Gear

One system marks the client's reward choices: `QoL/Rewards.lua`. Gear only
judges items (`Gear.IsUpgrade(link) -> upgrade, delta, pct`) and ranks
choices for the guide's own reward pick (`Gear.RankChoices`, used by
`Gear/Picks.lua`); it draws nothing on the reward panel.

```lua
Polestar.QoL.Rewards.ReadChoices(fromLog) -> { { index, link, itemID, count, value, upgrade, delta } }, complete
Polestar.QoL.Rewards.Rank(choices) -> { index, ... } (best first), "upgrade" | "value"
Polestar.QoL.Rewards.Mark() -> true | false | nil   -- draw the marks; whether the best was marked (nil: no best)
Polestar.QoL.Rewards.best, .reason                -- auto-pick's settled answer on QUEST_COMPLETE
```

- **Best** = the largest Gear upgrade (delta > 0, Gear enabled); with none,
  the highest vendor value (sell price × stack). Auto-pick
  (`qol.rewardAutoPick`, Shift suppresses, never when the quest costs money)
  takes it; the marks frame it.
- **Marks** (`qol.rewardHighlight`), on each `type == "choice"` button of
  `QuestInfoFrame.rewardsFrame.RewardButtons`, anchored to its `Icon`:
  `qol-upgrade` (success) on every upgrade in the icon's top-left corner,
  `qol-coin` (accent) in its top-right corner on the most valuable of two or
  more choices (every price known; ties all), a 2px accent frame with a shade keyline around
  the best of two or more. Drawn after `QuestInfo_Display` (detail, reward and
  quest-log pages), and redrawn on `GET_ITEM_INFO_RECEIVED`, `GEAR_UPDATED`
  and the setting; cleared on `QUEST_FINISHED`. An uncached choice is judged
  from its item ID; the best waits for complete data (or auto-pick's answer).
- **Tooltips**: the client's `SetQuestItem` / `SetQuestLogItem` run the item
  post-calls, so Gear's comparison line ("+12% upgrade · Head") shows on a
  hovered choice through `Polestar.Hooks`. Gear's "Best pick" line
  (`gear.pickTooltip`) appears only when its pick is an upgrade, so it never
  contradicts the coin. `gear.rewards` is the guide window's pick line only.

## Binding at the guide's inn — QoL, asks the Engine

`QoL/Bind.lua`, behind `qol.autoBind` (Quality of Life → Travel →
Hearthstone; off by default, as it binds for the player). It does one thing:
while the active tab's current step has an open `sethome` goal, it binds the
Hearthstone at the innkeeper that goal names, and nowhere else.

```lua
Polestar.QoL.Bind.Wanted(npc) -> bool        -- an open sethome goal of the current step binds at npc (Engine.IsSethomeInnkeeper), and the character is not bound at that innkeeper's inn (Nav.BoundInn)
Polestar.QoL.Bind.BinderOption(options) -> option | nil  -- the gossip's bind option: icon or overrideIconID 132052 (BinderGossipIcon)
Polestar.QoL.Bind.OnGossip() -> bool         -- GOSSIP_SHOW (Toggles.lua: after the flight helper, before skipGossip): picked the bind option
```

- **Gossip.** At such an innkeeper, the bind option is picked by its icon,
  never its text (`QoL.SelectGossip`: by `gossipOptionID`, else
  `orderIndex`). Not with Shift held, and not while the gossip has a quest to
  pick up or hand in (`QoL.HasQuestBusiness`, which the flight helper shares):
  the quest automation goes first and the gossip shows again after it.
- **Confirmation.** Picking the option fires `CONFIRM_BINDER(areaName)`,
  registered only while the setting is on (`QoL.WhileOn`). While the
  innkeeper (`"npc"`, else the last gossip's NPC: the client may have closed
  the gossip) is still `Wanted`, whether the helper or the player picked the
  option, and Shift was held neither at that gossip nor now, it answers as the
  popup's Accept does
  (`C_PlayerInteractionManager.ConfirmationInteraction(Enum.PlayerInteractionType.Binder)`,
  then `ClearInteraction(Binder)`; Blizzard_StaticPopup_Game
  GameDialogDefs.lua), closes the "CONFIRM_BINDER" popup on the next frame
  (`QoL.ClosePopup`, as for summons; left to the player under the gamepad
  interface style) and prints "Bound your Hearthstone to <area>.". The
  Engine completes the goal from the bind as it does for one by hand
  (`HEARTHSTONE_BOUND`).

## Guide level on the XP bar — QoL/XPMark

```lua
Polestar.QoL.XPMark.Label(level, target) -> text | nil   -- pure: "Guide: 11" (the next level), "Guide: 14 (4 levels)"; nil when target <= level
Polestar.QoL.XPMark.Refresh()                            -- show, move or hide the mark now
Polestar.QoL.XPMark.frame                                -- the mark, once made
```

- **Target** (`qol.xpTargetMark`, on by default; Quality of Life >
  Trackers > Experience): `Engine.LevelTarget(level)`, the level the guide
  holds you to before it moves on. Guide levels are whole levels (the
  compiler takes no fractions), so the mark is always the end of this
  level's bar: a 2px accent tick at the bar's right edge, standing 2px above
  and below it, with the label left of it in the accent colour (outlined
  `small` text). Nothing when the option is off, no guide is open, no `level`
  goal lies ahead above your level, or you are at the maximum level.
- **The game's bar is only read.** The experience bar is the one of
  `StatusTrackingBarManager.barContainers` whose
  `bars[StatusTrackingBarInfo.BarsEnum.Experience]` is shown
  (Blizzard_StatusTrackingBar). The mark is Polestar's own frame made under
  that bar through `CreateFrameUnder`, spanning its `StatusBar` one level
  above its `OverlayFrame` (MEDIUM strata, like the bar's own text), so it
  fades, hides and resizes with the bar and its gamepad width. It takes no
  mouse: the bar's tooltip stays. No scripts, methods or hooks on the bar;
  no bar shown (another addon replaced or hid it, the maximum level): no
  mark, and no error.
- **Updates**, coalesced to the next frame (after the game's bar and the
  engine took the same event): `PLAYER_XP_UPDATE` and
  `PLAYER_ENTERING_WORLD` while the option is on (`QoL.WhileOn`),
  `PLAYER_LEVEL_UP` (its level: `UnitLevel` can lag the event), step
  changes (`QoL.OnStep`), the setting, and the theme's accent.

---

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