Quests

Contributor4 min readUpdated

In short

Quest database, markers, tooltips, quest levels

addon/Polestar/Quests/ loads the load-on-demand data addon Polestar_QuestDB through Data.Pack (≈ 1.3 MB of Lua, ≈ 6.4 MB resident) at login, and only while qol.questDB is on and at least one feature that needs it is (QuestDB.IsWanted(): map/minimap objectives, available quests, turn-ins, tooltips, nameplates); turning the first one on later loads it then, and a load refused in combat is retried when combat ends. It fires QUESTDB_LOADED, then QUESTDB_STARTED; QUESTDB_UPDATED follows every change to the tracked quest log. Record layouts: tools/lib/questdb/build.js. An entity's spawn clusters (70 yd) cover every known spawn on each map (the reference data's pts and more), with no cap on how many.

lua
Polestar.QuestDB.IsLoaded() / IsEnabled() / IsRunning() / IsWanted()
Polestar.QuestDB.GetQuest(id)  -> { id, title, level, minLevel, races, classes, faction, start = { npc, object, item },
                                    finish = { npc, object }, pre (any-of), preAll, excl, zone, skill, holiday,
                                    objectives = { { kind = "kill"|"item"|"object"|"event", id, count, map, x, y, f } } } | nil
Polestar.QuestDB.GetNpc(id) / GetObject(id) -> { id, name, spawns = { { map, x, y, r (yd), f } } } | nil
Polestar.QuestDB.GetItem(id)   -> { id, name, droppers = { { id, name, chance } }, objects = { ... }, vendors = { { id, name } } } | nil
Polestar.QuestDB.GetItemDroppers(itemID) -> { { id, name, chance }, ... } | nil   -- best chance first
Polestar.QuestDB.GetObjectiveMobs(questID, oi) -> { name, ... } | nil            -- kill target or item droppers
Polestar.QuestDB.CheckAvailable(id, ctx, isDone, isOn, opts) -> ok, reason      -- opts: lowLevel, levelAbove, skillRank
Polestar.QuestDB.EachAvailabilityRef(id, fn) -> needsSkill                       -- fn(q) per quest whose done/in-log state CheckAvailable reads
Polestar.QuestDB.GetAvailableQuests() -> { questID, ... } ; IsAvailable(q) ; WhyUnavailable(q) -> reason | nil
   -- reasons: "eligibility" (faction, race incl. Skyborne high bits, class, holiday), "done", "active", "level"
   -- (minLevel), "grey", "high" (beyond qol.questLevelWindow), "prerequisite", "exclusive", "skill"
Polestar.QuestDB.ObjectivesForNpc(id) / ObjectivesForItem(id) / ObjectivesForObject(id)
                               -> { { q, kind, id, name, cur, max, done, entry = { q, title, ready } }, ... } | nil  -- quests in the log
Polestar.QuestDB.GetMarkers(map [, "objectives"|"turnin"|"available"]) -> { pin, ... }
Polestar.QuestDB.IsGuideQuest(q) -> bool                                         -- in the active guide's current step
Read the rest of this section510 words

"Done" comes from C_QuestLog.GetAllCompletedQuestIDs (one call per available scan), else C_QuestLog.IsQuestFlaggedCompleted per quest. A scan rechecks every candidate only after a level-up, a skill change, a filter setting or without the bulk call; otherwise only the candidates that read a quest whose done or in-log state moved since the last scan (EachAvailabilityRef), plus those needing a profession skill.

Pins layers: quests.objectives, quests.turnin, quests.available, one pin per entity spawn cluster and layer (a mob two objectives need carries both under the higher-ranked glyph: kill > interact > collect > vendor). Objective clusters at least MIN_AREA (12 yd) wide carry their radius as area. Markers and the tooltip/nameplate indexes are rebuilt only when what they show changed (a quest came or went, got ready or changed title, an objective was done or undone); a progress count alone only fires QUESTDB_UPDATED, since tooltips and nameplates read counts live. A rebuild reuses the pin tables the last one kept for the same cluster, with their world position (c, wx, wy) worked out once, so Pins.SetLayer converts only new pins. Look is applied at publish: while a Polestar guide runs, pins of quests in its current step (Engine.GetGuide().steps[Engine.GetStepIndex()].goals[*].quest, re-read on STEP_CHANGED/GUIDE_CHANGED) are 1.3× inside an accent ring and on top; with qol.guideDim every other quest pin drops to 0.6 alpha (Q.DIM_ALPHA).

Tooltips go through Polestar.Hooks (owner "quests": UnitLines, ItemLines, ObjectLines, registered only while running) with the suite's quest line, Hooks.AddLine(tt, "<Quest>:", "<what> cur/max", quest, textDim | success): "Kill Kobold Vermin 3/10" on the target, "Large Candle 3/8" on a dropper, "3/8" on the item; quest-starting items get "Starts a quest: <title>". Quests/QuestLevels.lua prefixes "[12]" (and "+" for elite) to quest titles the client lists without one (gossip, greeting, details; camelot's own log and tracker already show it, so it adds there only when missing). (camelot is Forever's game type in Blizzard's UI source: the files the Forever client loads carry AllowLoadGameType camelot, and its own overrides sit in Camelot/ folders.)

Nameplate icons (qol.nameplateIcons): a mob an open objective still needs gets a 16px objective icon (14–20) 3px left of the health bar the player sees: EllesmereUI Nameplates' unit frame, Plater/ElvUI/oUF, KuiNameplates or Threat Plates when present, else the shown child of the base plate holding the largest status bar, else Blizzard's health bar, else the plate itself; parented to that frame so it follows its fading and scaling. Beside it, left, a font string of the icon frame (.count) shows the progress of the open objectives with a count above 1 (Q.ProgressText, by quest, joined with " · "), re-read on every QUESTDB_UPDATED; hidden when none has one. Every access is guarded; Quests.NameplateIcon(unit) returns the icon and Quests.NameplateCount(unit) the progress shown (tests).

Settings (qol.*, Questing → Quests; the markers under Map → Guide & quests → Quest markers): questDB, availableQuests, questLevelWindow (0–10, 10 = any; default 5), lowLevelQuests, mapObjectives, objectiveAreas, turnInMarkers, minimapObjectives, guideHighlight, guideDim, questTooltips, nameplateIcons, questLevels. The four marker layers (availableQuests, mapObjectives, turnInMarkers, minimapObjectives) and objectiveAreas default to off (Map → Guide & quests → Quest markers); guideHighlight only restyles markers those layers draw.

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