Dungeons

Contributor7 min readUpdated

In short

Dungeon quest journal, pick-up and hand-in guides

The dungeon pages come from the Codex's instances (Toolchain, "Codex"): in a release build the Forever client's tables and data/forever/*.json; with --local-extras also dungeons.json (DungeonJournal).

The Dungeons section of the hub reads them through the Codex: codex build always runs tools/lib/codex/journal.js, which writes one page per Codex instance into the pack as Dungeons1.lua (a summary table per dungeon for the list, and the page as Lua source compiled only when opened): the quests the community quest database files under the instance's areas (the areas on the instance's map and the outdoor areas of its name, as the solo filter's instance classification reads them, tools/lib/sim/solo.js), whose objectives or starting item point into it, that the Forever web database's dungeon and raid quest lists place in it (quests.json's <web-db>.zone, counted only when the community quest database's Forever store has the quest, which keeps out <UNUSED>, <NYI> and retired quests), whose start item drops or lies inside one instance (that page too, even when the quest has an area), or that end its story (a follow-up with the same title, no objectives, taken where the quest ends: Hidden Enemies, The Lord of Blackrock); plus, with --local-extras, dungeons.json's. An objective item that is sold, crafted, or dropped or held outside every instance ties no quest to a dungeon (the false-positive rule: Murloc Poachers, Craftsman's Writs), nor does a stray drop, one only the web database's lists record and under 5% (The Ectoplasmic Distiller's Greater Eternal Essence from Gri'lek and Maexxna); a quest of a game event (the Era quest database's event: the Darkmoon Faire, the holidays, the war efforts) is on a page only where the community quest database or the web database files it (Copper Modulator, Rinling's Faire turn-in, is on none). What no rule can catch is in the cited table tools/lib/codex/journal-quests.json (Shards of the Felvine). Each quest has giver and ender and their positions, its objective facts (objectives: kind, NPC, item or object id, count and the English name; the escorts' and events' text), composed at run time into our own objective line in the client's language (Dungeons.ObjectiveText: L["Kill %d %s"], L["Collect %d %s"], L["Use %s"] with the names from Polestar.Names; an event's line is the quest's own objective summary from the names pack, kind objective), chain (every prerequisite and breadcrumb of the quest's side, all of pre and preAny, oldest first, at most 20), rewards (items with quality, count and choice from recordings and the leveling gear lists, else the web database's list rewards, choice versus fixed as the web database files them; XP from quests.json; money, else the web database's; reputation from the web database's rewards, its "+1" placeholders left out, never the standing a quest asks for) and, with --local-extras, DungeonJournal's audited shareability; bosses in kill order with the quests tied to them (an encounter's boss carries its DungeonEncounter id, encounter, for its name in every language); entrances from the Codex, else the client's Map table (the corpse point, placed on its zone); and the page's attunement list (below). No loot tables. The page also carries the instance's Map id (map): the list shows the dungeon's name in the client's language (Names.Instance) and its zone's (C_Map); attunement notes are our prose, read through L[note] (i18n keys lists them from tools/lib/codex/attunements.json). codex attune writes the local comparison with the the attunement data addon (tools/lib/codex/questaudit.js, tools/lib/consume/attune.js; data/local/dungeon-quests-audit.md and .json, then the attunements report). Runtime: addon/Polestar/Dungeons/Dungeons.lua (Polestar.Dungeons: List, Get, Entrance, Quests, Quest, ObjectiveText, Bosses, Open, GuideTo, GuideToPoint, ShowOnMap; SHOW_DUNGEON). dungeons build writes no guides.

Read the rest of this section1108 words

The pick-up guide is built in game (addon/Polestar/Dungeons/Pickup.lua): Dungeons.PickupPlan(key) takes the page's quests that apply to the character (faction, race and class masks through Lookup.QuestBlock, the page's class list), not done, not in the log (those are carried), not closed for good (a quest of the page's closedBy done or in the log: a breadcrumb whose quest is taken, such as Klockmort's Essentials once Essential Artificials is; each accept carries closedBy too, so the Engine passes it once taken on the way), open by max(level, the dungeon's lowest level), picked up outside from an NPC or object (not from an item, not inside), and not a follow-up of another quest of the page; each with its open prerequisites (Lookup.QuestChain: all of pre, one of preAny this character can take, in the order they are done). The giver is Dungeons.Giver(pq, from): the page keeps one (the Codex's first), so a quest several NPCs give goes to the one of the character's side nearest the player (Lookup.QuestEnd, which takes an NPC of the other side only when no other is known and marks it hostile; Tabetha's Task: the mage trainers of both sides), never to one of the other side; the quest card and the map's giver markers show the same giver. Dungeons.PickupGuide(key) orders them as the cheapest path by ns.TravelCost from where the player stands, through every stop, to the entrance (Dungeons.PlanStops(stops, from, finish, travel) -> order, cost: an exact search over the stops done and the last one, up to 12 stops; above that nearest-next, then single stops moved while the path gets shorter). A nearest-next walk with the entrance only appended left a city and came back to it (Thunder Bluff, Orgrimmar, the Undercity, back to Orgrimmar for Ragefire Chasm); the planned path goes Thunder Bluff, the Undercity, Orgrimmar and in. Stops: each prerequisite once, after the one before it in its chain (a full quest step, Lookup.QuestStep, from its giver nearest the player; the player then stands at its turn-in), and a giver once per set of prerequisites its quests wait on (one step with an accept per quest; the giver comes up again for a quest still waiting, and visits to the same giver in a row are one step). The last step lists the carried quests as notes, goes to the entrance and says where the hand-in guide is (a note naming /polestar dungeons <name>). Nothing to take: nil, "nothing". The route is kept per character (CharState().dungeonPickup[key], the stop keys in order) and used when the guide is rebuilt without a position (Dungeons.OrderStops(stops, from, finish, field, key), shared with the hand-in guide). It is a Lookup planner kind (Lookup.RegisterPlanner("pickup", build)): Dungeons.PickUp(key) -> Lookup.Guide("pickup", key) registers it as lookup/pickup/<key> (pack "lookup") and opens it in a new tab, and a saved tab of it is rebuilt at ADDON_LOADED like Lookup's own; it is gated by dungeons.enabled, not lookup.enabled.

The hand-in guide is the run's other half (addon/Polestar/Dungeons/Handin.lua, planner kind handin, lookup/handin/<key>, Dungeons.HandIn(key)). Dungeons.HandinPlan(key) sorts the page's quests in the log: hand (objectives done, by Compat.IsQuestReadyForTurnIn, or a delivery with no objectives; turned in outside at the page's ender, else the Codex ender nearest the player), unfinished, inside (turned in inside the dungeon) and unplaced; it searches no follow-ups, so the page can ask for it on every render. Dungeons.HandinFollowUps(plan) adds the quests the hand quests open (Codex.FollowUps(id): the quests whose pre or preAny name it, one scan of the quest records per id, kept until the quest chunks change): every pre done or handed in here and one of preAny likewise, takeable now (Lookup.QuestBlock: faction, race, class, level), not done or in the log, from the NPC or object a quest it waits on is turned in to or one within 60 seconds of it (ns.TravelCost). Dungeons.HandinGuide(key) makes a stop per turn-in place (its turn-ins, then the follow-ups that same NPC gives) and per other follow-up giver (after the turn-ins it waits on), ordered by Dungeons.OrderStops with no fixed end (CharState().dungeonHandin[key]); the last step lists the rest as notes ("Not finished yet: …", "Turned in inside the dungeon: …"). Nothing routable: nil, "nothing", and Dungeons.HandinText(plan) says why in one line. Dungeons.HandIn puts the guide in the tab of the dungeon's pick-up guide when that one is finished or at its last step (its job ends at the entrance), else in a new tab. A finished pick-up guide's "Guide complete" panel (UI/GuideFrame.lua) offers "Hand in the quests" while the dungeon has quests in the log.

Attunements and keys (addon/Polestar/Dungeons/Attune.lua, planner kind attune, lookup/attune/<key>:<id>). A page's attunement list (Codex, "Dungeons and raids": tools/lib/codex/attunements.js) is read by Dungeons.Attunements(key, faction) (faction "A" | "H" | nil: the entries of that side and the side-free ones). Dungeons.AttunementState(a) gives this character's state per step: a quest done, ready, log, open, locked (a step it waits on, after all, afterAny one, is not done), level, rep (the quest's standing, Compat.GetFactionStanding), na (faction, race or class through Lookup.QuestBlock) or skip (an alternative not taken: of any goals the one whose standing fits best, the highest first; a preAny sibling of a done one); a drop, chest or gift is done once its item is owned (Compat.GetItemCount(id, true), the bank included) or the quest it starts is taken; a standing once reached. The attunement is done when its item is owned (a key, the Drakefire Amulet, Aqual Quintessence) or, item-less, when its goals are done (one of them with any); goalDone with no item says the key was lost. Dungeons.AttuneGuide(key, id) makes a stop per quest still to do (Lookup.QuestStep, with any open prerequisite Lookup.QuestChain finds that the list lacks), each after the stops it waits on, ordered by Dungeons.OrderStops from where the player stands with no fixed end (CharState().dungeonAttune["<key>:<id>"]). Each quest step is whole (accept, objectives, turn-in): Lookup.QuestStep's opts.inside places a giver, target, chest or turn-in without a spawn at the entrance of the instance it is in (the Codex NPC's instance, else the attunement's inside from the cited table) and the step's note says what is inside where; without it such a quest would be a lone "First do the quest" note, which the Engine passes as done. An accept above the character's level stays, the Engine's detail adding "from level N". A drop or chest is a collect step at its NPC or object (inside an instance: at its entrance, with a note naming it), a standing a rep step, a gift a talk step, each after the quest before it in the list; the last step holds the note and the entrance. Nothing left: nil, "done"; the other side's attunement: nil, "nothing". Dungeons.Attune(key, id) opens it in a new tab.

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