Skip to main content

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

ClassPurpose
QuestScriptableObject defining a quest's objectives, rewards, prerequisites, and metadata
ObjectiveSerializable class representing a single trackable task within a quest
QuestRewardSerializable class representing a reward granted on completion
QuestStatusRuntime state for a quest: progress counters, timestamps, completion/failure flags
QuestManagerSavableObject 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

FieldTypeDescription
IsMainQuestboolMain quests are critical for story progression
CategoryQuestCategoryOrganizes the quest in the quest log (see below)
DifficultyQuestDifficultyEasy, Normal, Hard, Expert -- shown in the UI

Quest Categories:

  • MainStory -- main storyline progression
  • SideQuest -- optional NPC quests
  • DailyTask -- resets every 24 hours
  • WeeklyChallenge -- resets every 7 days
  • Event -- limited-time event quests
  • Collection -- fill the MonsterDex, find all items, etc.

Quest Giver

FieldTypeDescription
QuestGiverCharacterDataThe NPC that assigns this quest

Requirements

FieldTypeDescription
PrerequisiteQuestsList<Quest>Quests that must be completed first
MinBadgesintMinimum badge count to accept (0 = none)
RecommendedLevelintShown in the UI, not enforced

Time and Repeat

FieldTypeDescription
TimeLimitSecondsintTime limit in seconds (0 = no limit). Quest auto-fails when expired
IsRepeatableboolWhether the quest can be restarted after completion
RepeatCooldownSecondsintCooldown 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)

TypeDescriptionKey Fields
TalkTalk to a specific NPCTargetNPC
DeliverDeliver an item to an NPCTargetNPC, TargetItem
DefeatDefeat trainers or wild monstersTargetMonster (null = any), TargetCount
CatchCatch a specific speciesTargetMonster, TargetCount
CollectCollect a quantity of an itemTargetItem, TargetCount
GoToTravel to a specific mapMapLocation
EscortEscort an NPC to a destinationTargetNPC, MapLocation
EvolveEvolve a monster of a speciesTargetMonster
HatchEggHatch a monster eggTargetMonster (null = any)
WinAtFacilityWin a battle at a specific facilityMapLocation
CustomTracked via a game variableCustomVariableKey, 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)

TypeFieldsExample
ItemItemReward, ItemQuantity5x Super Potion
MoneyMoneyAmount$5,000
ExperienceExpAmount2,000 EXP distributed to party
MonsterMonsterReward, MonsterLevelLv.20 Thundermane
GameVariableGameVariableKey, GameVariableValueSet HAS_BIKE = 1
UnlockCustomUnlockId"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

NodeDescription
StartQuestStart a quest with an optional initial objective index
CompleteQuestMark a quest as completed (grants rewards)
FailQuestMark a quest as failed
UpdateQuestObjectiveSet the current objective to a specific index
ProgressQuestObjectiveIncrement an objective's progress counter by a delta
UnlockGameCompletionPercentageMake the completion percentage visible to the player

Condition Nodes

NodeDescription
IfPlayerHasQuestBranch if the player has started (or completed) a quest
IfCompletedQuestBranch if a quest has been completed
IfQuestFailedBranch if a quest has been failed
IfCurrentQuestObjectiveBranch 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

  1. Create the Quest asset: Right-click in the Project window, select MCE > Quests > Quest
  2. Set classification: Choose category, difficulty, and whether it is a main quest
  3. Assign the quest giver: Drag the NPC's CharacterData into the Quest Giver field
  4. Define objectives: Add entries to the Objectives list. Set the type, target, and count for each
  5. Define rewards: Add entries to the Rewards list. Choose reward type and fill in the relevant fields
  6. Set prerequisites (optional): Drag other Quest assets into PrerequisiteQuests
  7. Configure time/repeat (optional): Set TimeLimitSeconds and/or IsRepeatable with a cooldown
  8. Register in WorldDatabase: Add the quest to WorldDatabase.Quests so it appears in availability queries
  9. Wire up CommandGraph: Use the quest nodes in your NPC's CommandGraph to start, track, and complete the quest