Skip to content

Quests

All · 15 min read · No code

What the player sees: an NPC with a "!" bubble offers a quest on a screen with its title, who is asking, the objectives and the reward. Accepting it puts it in the Quest Log and on the HUD tracker; the minimap marks what it still wants; and talking to the giver when it is done pays the reward under a "quest complete" banner.

A quest is a data asset: a title, some objectives, a reward, and optional conditions for when it may be offered. You make one by duplicating a sample quest and filling in its Details panel. The party's progress is remembered per quest asset, so the quest asset is the quest's identity: a quest keeps working when its giver is unloaded, the leader changes, or the game is saved and loaded.

What you can change

How it fits together

Piece Kind Job
Quests/DA_XenoCore_Quest_Collection01, DA_XenoCore_Quest_Monster01 Quest definitions (data assets) The two Gym sample quests
Quests/GaurPlain/DA_XenoCore_Quest_GP_* Quest definitions The seven quests of the Gaur Plain slice, given by NPCs placed in Maps/L_XenoCore_GaurPlain
Quest ledger Built in (on the player controller) Status, objective counts, who asked, which quest is tracked. Reach it in a Blueprint with Get Party Quests
Offer Quest Blueprint node with Accepted and Declined outputs Opens the offer screen, continues on Accepted or Declined
UserInterface/HUD/W_XenoCore_QuestOffer Screen Title, requester, summary, objectives, rewards, Accept/Decline
UserInterface/W_XenoCore_QuestLog Screen Every accepted and finished quest, from the menu
UserInterface/HUD/W_XenoCore_QuestTracker HUD plate The tracked quest and its outstanding objectives
UserInterface/HUD/W_XenoCore_QuestReward HUD plate The "quest complete" banner with what was paid
Quest UI nodes Blueprint nodes (XenoCore › Quest) Row info for the log, requester name, Open Quest Log

Every XenoCore Experience has the quest ledger; there is nothing to add to a map.

The sample NPCs are in Maps/L_XenoCore_Gym: NPC_QuestGiver gives DA_XenoCore_Quest_Collection01 and NPC_MonsterQuestGiver gives DA_XenoCore_Quest_Monster01. Characters/NPC/B_XenoCore_Npc_Sample also carries Collection01, as a ready-made example; the plain B_XenoCore_Npc gives no quest.

What the two sample quests do

  • Collection01 is a collect quest: one Collect Item objective for 2 ID_XenoCore_EtherCrystal, taken from the bag on turn-in, rewarding ID_XenoCore_BlueChain, 500 gold and 200 experience.
  • Monster01 is a kill quest: one Defeat Enemy objective for 2 B_XenoCore_Minion_Melee, rewarding ID_XenoCore_ScrapPlating, 300 gold and 400 experience. Every minion killed while the quest is active counts, including any child Blueprint of the minion. Its Party Level At Least gate is set to 1, so it never blocks: it is there as a worked example. Raise the level to see a gate work.

Lifecycle

A quest's status, shown on screen as the log's status column:

Status Meaning Offerable?
Unknown Never answered Yes
Declined Turned down once Yes, the player can come back
Active Accepted, objectives outstanding No
Ready To Turn In Every objective met No
Complete Turned in and paid. Final No
  1. Offer. The NPC's graph calls Offer Quest. If the quest is not offerable (already taken, or a gate does not hold) nothing opens. The screen pauses the conversation, which resumes on the answer. Exactly one of Accepted or Declined always fires, even if the screen is torn down.
  2. Accept. The status becomes Active and the counts are filled straight away from the bag. A collect quest for something you already carry can be Ready To Turn In the moment you accept it. The giver's name is recorded. If nothing is tracked yet, this quest becomes the tracked one.
  3. Progress.
    • Collect Item counts are recomputed from the bag every time the bag changes. They are never added up from pickups, so spending or selling the item lowers the count again.
    • Defeat Enemy counts go up by one per kill, only while the quest is Active. Kills before you accepted do not count. They cannot be recomputed, so they are what the save file keeps.
    • Talk To NPC counts when the party talks to the placed NPC whose Quest Id matches, before that NPC's own graph runs, so a last-step talk to the giver can hand in within the same conversation. Reach Location counts when the leader walks into the matching Quest Location (companions never count), once per visit for each quest.
    • When every objective is met the status moves to Ready To Turn In, and back to Active if a collected item leaves the bag.
  4. Turn in. The NPC's graph calls Turn In. It re-checks the bag first. If the quest is not really ready it returns false and stays Active. Otherwise it:
    • removes the collected items whose objective has Consume On Turn In ticked,
    • pays the gold, and experience to the whole roster (reserve members at the Reserve Experience Rate, 0 in the sample, see Progression),
    • adds the reward items to the party bag,
    • marks the quest Complete, moves tracking to another running quest, and shows the reward banner.

Gates are checked when a quest is offered, never again. A quest you already have is not taken away because the leader changed to a lower-level character.

The quest marker ("!" bubble) over a giver shows while the quest is offerable or ready to turn in, and hides while it is Active. A gated quest shows no marker at all.

Who asked. The offer screen and the tracker name the requester in this order: the quest's own Requester Name; otherwise the NPC offering it; otherwise the name recorded at Accept. The tracker has no NPC to ask, which is why the name is recorded. It reads "Return to name" when the quest is ready.

The minimap marks what the tracked quest still wants in blue: the enemies a Defeat Enemy objective needs, the NPC of a Talk To NPC step, the Quest Location of a Reach Location step, and the giver once the quest is ready. See Minimap.

The tracker follows exactly one quest. Pick it in the Quest Log. Show or hide it with the quest tracker button (see Controls).

Saving. Every quest's status (by name), its counts, its recorded requester and the tracked quest are saved. On load, collect counts are recomputed from the restored bag; kill counts come from the file. See Save and front end.

Settings

On a quest definition:

Setting Where it lives What it does
Title XenoCore › Quest The quest's name on every screen
Kind XenoCore › Quest Collection, Material, Monster, Challenge, Search, Normal, Story. A label only: it titles the offer screen and sorts the log, and changes no behaviour
Area XenoCore › Quest Free text shown beside the quest in the log
Requester Name XenoCore › Quest Who is asking. Leave empty to use the NPC's Display Name
Requester Portrait XenoCore › Quest The face on the offer screen. Empty hides the frame
Summary XenoCore › Quest The paragraph under the requester
Objectives XenoCore › Quest What must be done (below)
Gates XenoCore › Quest Conditions before it is offered. All must hold. Empty means always offerable
Reward XenoCore › Quest Gold, Experience, and Items (one entry per item, so ten of a thing is ten entries)
Can Decline XenoCore › Quest Untick to show only Accept, and ignore Back

Each objective:

Setting What it does
Description The prose line on the offer screen and in the log
Counter Label The noun in "Name 0/2". Empty uses the item's own name
Kind Collect Item, Defeat Enemy, Talk To NPC or Reach Location
Item Target The item to hold (Collect Item)
Enemy Target The enemy class to defeat (Defeat Enemy). A parent class counts every child. A soft reference: the quest does not load the enemy Blueprint
Target Id Talk To NPC: the placed NPC's Quest Id. Reach Location: a placed XenoCore Quest Location's Location Id. Matched by name
Required Count How many
Consume On Turn In Take the items away on turn-in (Collect Item)
Icon Source, Icon Category, Icon Texture The icon beside this objective on the offer screen, log and tracker

Each gate is Party Level At Least (the leader's level) or Quest Completed (another quest must be turned in, not just accepted).

Talk and location steps match by name

A quest asset cannot point at an actor placed in a level, so Talk To NPC and Reach Location match the objective's Target Id against an NPC's Quest Id or a Quest Location's Location Id. Saving an objective with an empty Target Id reports an error. See Create a kill, talk or location quest.

Fails silently: a gate that can never pass

A quest whose gate never holds is simply never offered. There is no marker to notice missing, and nothing is logged. To check, run XenoQuestStatus in the console, or call Get Gate Requirement Text on Get Party Quests from a Blueprint: it returns the reason as player text. No shipped screen shows it yet.

Reordering objectives breaks existing saves

Saved counts are stored in objective order. Reorder a shipped quest's Objectives and a player's saved kill counts land on the wrong objective.

The screens' styling and spacing live on their Blueprints' class defaults under XenoCore › Quest: colours for the tracker and reward banner, the banner's duration, and so on.

Extending it

  • A new quest is a new data asset, not code: duplicate DA_XenoCore_Quest_Collection01 into Content/MyGame/Quests/, edit it, and set it as the Quest of a placed NPC. See Make a collection quest.
  • Custom quest flow (extra lines, a cutscene between accept and the first objective) goes in the NPC's On Interact graph around Offer Quest and Turn In. Use Get Lines For with Greeting, Accepted, Declined, In Progress or Turn In to pick the NPC's authored lines.
  • Accepting from script (a story quest with no screen): call Accept on Get Party Quests. Leave Giver empty; the tracker then says "Return to the quest giver".
  • A custom step with no objective kind of its own (pull a lever, win a minigame): use a Talk To NPC or Reach Location objective and advance it from any Blueprint with Notify Objective on Get Party Quests, passing its Kind and the objective's Target Id.
  • A new objective kind needs a programmer: the list of kinds is fixed in C++.
  • Reacting to quests from your own Blueprints: listen for XenoCore.Quest.Message.Changed and re-read the component, or XenoCore.Quest.Message.TurnedIn for the payout. See Events you can listen to.

Console command for checking the ledger: XenoQuestStatus prints every quest the party has touched.

For programmers: classes

Definition UXenoCoreQuestDefinition; ledger UXenoCoreQuestComponent (a controller component added by the plugin's GameFeatureData, XenoCore.uasset); Offer Quest is the latent node UXenoCoreOfferQuest; screens derive from UXenoCoreQuestOfferBase, UXenoCoreQuestLogBase, UXenoCoreQuestTrackerBase and UXenoCoreQuestRewardBase; UI helpers are UXenoCoreQuestUIStatics. A new objective kind is a value appended to EXenoCoreObjectiveKind (never reorder it) plus a listener in UXenoCoreQuestComponent for whatever advances it.

Why it's built this way

For programmers
  • On the controller, not a world subsystem. Quest state must outlive a map and be saved. The controller is also where Lyra and XenoCore keep other party-wide state, such as the bag.
  • Keyed by the definition. Same reason the progression component keys characters by their member definition: the NPC may be gone, and the asset outlives everything.
  • No "Offered" status. A state that exists only while a screen is up can be stranded by a crash or a level change. The screen's being open is the screen's business.
  • Counts recomputed from the bag. A running total drifts the first time anything changes the bag without the message it expects. Re-reading the bag is correct by construction.
  • Changed carries no detail; TurnedIn does. Every screen re-reads the component on Changed, so no copy can go stale. The turn-in payout is the exception: once paid, the gold is part of a running total and cannot be reconstructed by re-reading.
  • Kind is only a label. If code branched on it, adding a new kind would stop being data.

Next: Shops and trade · Interaction, NPCs and dialogue