Quest System
The quest system (Pro tier and above) provides a full quest lifecycle: creation, tracking, progression, completion, failure, rewards, prerequisites, time limits, and repeatable quests. All quest data is defined via ScriptableObjects and integrated with the save system and CommandGraph.
Architecture Overview
| Class | Purpose |
|---|---|
Quest | ScriptableObject defining a quest's objectives, rewards, prerequisites, and metadata |
Objective | Serializable class representing a single trackable task within a quest |
QuestReward | Serializable class representing a reward granted on completion |
QuestStatus | Runtime state for a quest: progress counters, timestamps, completion/failure flags |
QuestManager | SavableObject that tracks all quest states, handles lifecycle, and fires events |
Quest
Create a quest via MCE > Quests > Quest in the asset menu. Each Quest ScriptableObject has the following sections:
Classification
| Field | Type | Description |
|---|---|---|
IsMainQuest | bool | Main quests are critical for story progression |
Category | QuestCategory | Organizes the quest in the quest log (see below) |
Difficulty | QuestDifficulty | Easy, Normal, Hard, Expert -- shown in the UI |
Quest Categories:
MainStory-- main storyline progressionSideQuest-- optional NPC questsDailyTask-- resets every 24 hoursWeeklyChallenge-- resets every 7 daysEvent-- limited-time event questsCollection-- fill the MonsterDex, find all items, etc.
Quest Giver
| Field | Type | Description |
|---|---|---|
QuestGiver | CharacterData | The NPC that assigns this quest |
Requirements
| Field | Type | Description |
|---|---|---|
PrerequisiteQuests | List<Quest> | Quests that must be completed first |
MinBadges | int | Minimum badge count to accept (0 = none) |
RecommendedLevel | int | Shown in the UI, not enforced |
Time and Repeat
| Field | Type | Description |
|---|---|---|
TimeLimitSeconds | int | Time limit in seconds (0 = no limit). Quest auto-fails when expired |
IsRepeatable | bool | Whether the quest can be restarted after completion |
RepeatCooldownSeconds | int | Cooldown before re-accepting (86400 = daily, 604800 = weekly) |
Objective
Each quest contains a List<Objective> defining the tasks the player must complete. Objectives are ordered and can be advanced automatically.
Objective Types (11)
| Type | Description | Key Fields |
|---|---|---|
Talk | Talk to a specific NPC | TargetNPC |
Deliver | Deliver an item to an NPC | TargetNPC, TargetItem |
Defeat | Defeat trainers or wild monsters | TargetMonster (null = any), TargetCount |
Catch | Catch a specific species | TargetMonster, TargetCount |
Collect | Collect a quantity of an item | TargetItem, TargetCount |
GoTo | Travel to a specific map | MapLocation |
Escort | Escort an NPC to a destination | TargetNPC, MapLocation |
Evolve | Evolve a monster of a species | TargetMonster |
HatchEgg | Hatch a monster egg | TargetMonster (null = any) |
WinAtFacility | Win a battle at a specific facility | MapLocation |
Custom | Tracked via a game variable | CustomVariableKey, TargetCount |
Objective Fields
[Serializable]
public class Objective
{
public string LocalizationKey; // Localized description text
public ObjectiveType Type; // What the player must do
public SceneInfoAsset MapLocation; // Where (for GoTo, minimap marker)
public CharacterData TargetNPC; // Who (for Talk/Deliver/Escort)
public MonsterEntry TargetMonster; // Which species (null = any)
public ScriptableObject TargetItem; // Which item (Collect/Deliver)
public int TargetCount = 1; // How many needed
public bool IsOptional; // Bonus objective, not required
public bool HiddenUntilPrevious; // Hidden until prior objective completes
public string CustomVariableKey; // For Custom type tracking
}
Optional objectives do not block quest completion. Hidden objectives create a sense of discovery as the quest progresses.
QuestReward
Each quest has a List<QuestReward> granted automatically on completion.
Reward Types (6)
| Type | Fields | Example |
|---|---|---|
Item | ItemReward, ItemQuantity | 5x Super Potion |
Money | MoneyAmount | $5,000 |
Experience | ExpAmount | 2,000 EXP distributed to party |
Monster | MonsterReward, MonsterLevel | Lv.20 Thundermane |
GameVariable | GameVariableKey, GameVariableValue | Set HAS_BIKE = 1 |
Unlock | CustomUnlockId | "safari_zone_access" |
// Each reward has a human-readable description for UI
reward.GetDescription(); // "Super Potion x5", "$5,000", "2,000 EXP", etc.
QuestManager
QuestManager is a SavableObject (ScriptableObject with save/load support) that owns all quest runtime state. Create via MCE > Quests > Manager.
Quest Lifecycle
Not Started --> StartQuest() --> Active (tracking objectives)
|
+---------+-----+-----+---------+
| |
CompleteQuest() FailQuest()
| |
Completed Failed
|
(if IsRepeatable)
|
StartQuest() (after cooldown)
Starting a Quest
questManager.StartQuest(quest, startingObjective: 0);
This creates a QuestStatus entry, records the start timestamp, shows a notification, and sets the initial objective. If the quest is repeatable and on cooldown, the call is ignored with a warning.
Progressing Objectives
// Increment the progress counter for objective #0 by 1
questManager.UpdateObjectiveProgress(quest, objectiveIndex: 0, delta: 1);
When the progress reaches the objective's TargetCount, the system shows a notification and auto-advances to the next non-optional objective. If all required objectives are complete, the quest completes automatically.
You can also set the current objective directly:
questManager.SetQuestObjective(quest, objective: 2);
Completing and Failing
questManager.CompleteQuest(quest); // Marks complete, grants rewards, fires event
questManager.FailQuest(quest); // Marks failed, fires event
Time-Limited Quests
Call questManager.CheckTimeExpiry() periodically (e.g., from a MonoBehaviour's Update) to automatically fail quests whose time has expired:
long remaining = questManager.GetRemainingTime(quest); // seconds, or -1
Querying Quests
// All quests the player has interacted with
Dictionary<Quest, QuestStatus> all = questManager.GetAllQuests();
// Filtered queries
List<Quest> active = questManager.GetActiveQuests();
List<Quest> completed = questManager.GetCompletedQuests();
List<Quest> failed = questManager.GetFailedQuests();
// Filter by category, completion status, and/or failure status
// Signature: GetQuestsFiltered(QuestCategory? category = null, bool? completed = null, bool? failed = null)
List<Quest> dailies = questManager.GetQuestsFiltered(
category: QuestCategory.DailyTask,
completed: false,
failed: null
);
// Check prerequisites
bool canStart = questManager.ArePrerequisitesMet(quest);
// Get all quests available to start (prerequisites met, not already started)
List<Quest> available = questManager.GetAvailableQuests();
// Check if the player has a specific quest
bool has = questManager.HasQuest(quest);
Game Completion Percentage
The QuestManager tracks a game completion percentage based on completed quests. It can be calculated automatically (completed / total quests in the world database) or against a fixed denominator (QuestsForHundo). The percentage becomes visible to the player when VisibleGamePercentage is set to true.
float pct = questManager.GameCompletionPercentage; // 0.0 - 1.0
Events
questManager.OnQuestStarted += (Quest q) => { ... };
questManager.OnObjectiveProgressed += (Quest q, int objIdx, int newVal) => { ... };
questManager.OnObjectiveChanged += (Quest q, int newObjIdx) => { ... };
questManager.OnQuestCompleted += (Quest q) => { ... };
questManager.OnQuestFailed += (Quest q) => { ... };
questManager.OnRewardsGranted += (Quest q, List<QuestReward> rewards) => { ... };
Save / Load
QuestManager extends SavableObject and serializes all quest states to JSON via SavableQuestManager. Quest references are stored by name and resolved against the WorldDatabase on load.
CommandGraph Nodes (10)
The quest system provides 10 CommandGraph nodes for use in NPC scripts and event triggers:
Action Nodes
| Node | Description |
|---|---|
StartQuest | Start a quest with an optional initial objective index |
CompleteQuest | Mark a quest as completed (grants rewards) |
FailQuest | Mark a quest as failed |
UpdateQuestObjective | Set the current objective to a specific index |
ProgressQuestObjective | Increment an objective's progress counter by a delta |
UnlockGameCompletionPercentage | Make the completion percentage visible to the player |
Condition Nodes
| Node | Description |
|---|---|
IfPlayerHasQuest | Branch if the player has started (or completed) a quest |
IfCompletedQuest | Branch if a quest has been completed |
IfQuestFailed | Branch if a quest has been failed |
IfCurrentQuestObjective | Branch if the quest's current objective matches a specific index |
Example: NPC Quest Flow
[IfPlayerHasQuest] -- No --> [Dialog: "I need help!"] --> [StartQuest]
-- Yes --> [IfCompletedQuest] -- Yes --> [Dialog: "Thanks!"]
-- No --> [IfCurrentQuestObjective(1)]
-- Yes --> [Dialog: "Did you find it?"]
-- No --> [Dialog: "Keep looking!"]
Creating a Quest: Step by Step
- Create the Quest asset: Right-click in the Project window, select MCE > Quests > Quest
- Set classification: Choose category, difficulty, and whether it is a main quest
- Assign the quest giver: Drag the NPC's
CharacterDatainto the Quest Giver field - Define objectives: Add entries to the Objectives list. Set the type, target, and count for each
- Define rewards: Add entries to the Rewards list. Choose reward type and fill in the relevant fields
- Set prerequisites (optional): Drag other Quest assets into PrerequisiteQuests
- Configure time/repeat (optional): Set
TimeLimitSecondsand/orIsRepeatablewith a cooldown - Register in WorldDatabase: Add the quest to
WorldDatabase.Questsso it appears in availability queries - Wire up CommandGraph: Use the quest nodes in your NPC's CommandGraph to start, track, and complete the quest