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