Skip to main content
This guide walks through creating a complete custom quest with map events, unlock conditions, and localization.

Overview

A quest in NONMP consists of:
  1. TbMapEvent - Defines the map marker and links to dialogue
  2. TbCondition - Controls when the event becomes available
  3. Yarn script - The actual dialogue and quest logic
  4. Localization - Translated strings for the quest

Complete Example

When you initialize a nonkit project, it creates a sample quest. Here’s what each file contains:

Step 1: Create the Yarn Script

scripts/Main.yarn
title: ModQuest_Example
---
<<close_all_view>>
<<back_creat bg-4 true 0.0 1 0.7>>
<<char_creat Lilith 1 3 true 0,-1200 0.7 0 0.3>>

Lilith: Welcome to the example quest! #line:modquest_welcome
Lilith: This demonstrates custom content creation. #line:modquest_intro

<<line_hide>>
<<char_remove Lilith true 0.7>>

<<event_end>>
<<next_period>>
<<open_view GuildView>>
===

Step 2: Define the Map Event

Create config/TbMapEvent.json:
config/TbMapEvent.json
[
  {
    "ID": 900001,
    "PlaceID": 9,
    "Title": "Example Quest",
    "Subtitle": "Custom Quest Demo",
    "BannerPath": "BG-4",
    "Desc": "This is a demonstration quest created with nonkit.",
    "MapEventType": "Special",
    "Recommend": "",
    "Difficulty": "",
    "UnlockCondition": 900001,
    "LockCondition": 0,
    "DialogID": "ModQuest_Example",
    "RequiredCharacters": "",
    "Duration": 0,
    "ExpRewards": 0,
    "AttributeReward": [],
    "ItemRewards": "",
    "ReputationReward": 0,
    "EnergyCost": 0,
    "OtherInfo": "",
    "Nonkit": {
      "IconSourceId": 10084
    }
  }
]

Step 3: Define Unlock Conditions

Create config/TbCondition.json:
config/TbCondition.json
[
  {
    "ID": 900001,
    "Name": "ModQuest_Example_Unlock",
    "Day": ">=1",
    "InWar": "false",
    "Period": "",
    "Event": "OnDayBegin",
    "YarnVariable": "",
    "Talent": [],
    "Lv": "",
    "PrimeAttribute": [],
    "Affection": "",
    "Item": []
  }
]
The condition above unlocks the quest from Day 1 onwards, when not in battle. The various fields allow filtering by time period, character level, talents, and more.

Step 4: Add Localization

Create config/TbLocalizationAutoGenerated.json:
config/TbLocalizationAutoGenerated.json
[
  {
    "Key": "MapEvent_900001_Title",
    "CH": "示例任务",
    "EN": "Example Quest",
    "Handled": true
  },
  {
    "Key": "MapEvent_900001_Desc",
    "CH": "这是使用nonkit创建的演示任务。",
    "EN": "This is a demonstration quest created with nonkit.",
    "Handled": true
  }
]

TbMapEvent Reference

FieldTypeDescription
IDnumberUnique identifier (use 900000+ for custom events)
PlaceIDnumberLocation where the event appears on the map
TitlestringDisplay name (or localization key)
DialogIDstringYarn node to run when event is triggered
UnlockConditionnumberTbCondition ID that must be true to show event
CompleteConditionnumberTbCondition ID that marks event as completed
Nonkit.IconSourceIdnumberExisting event ID to copy icon from

Icon Fallback System

Since custom events can’t add new icons, use Nonkit.IconSourceId to borrow an icon from an existing game event:
{
  "Nonkit": {
    "IconSourceId": 10084
  }
}
This copies the icon from event 10084 to your custom event.

TbCondition Reference

FieldTypeDescription
IDnumberUnique identifier
ConditionsstringExpression that evaluates to true/false

Condition Expressions

Conditions use the same expression syntax as Yarn scripts:
// Always available
"true"

// Check items (useful for quest tracking)
"get_item(12345) >= 1"

// Check gold
"get_gold() >= 100"

// Multiple conditions
"get_item(900001) >= 1 && get_gold() >= 100"

// Check event completion
"is_event_finished(10084)"

// Check time period
"get_global_value(\"CurrentPeriod\") == \"Morning\""
Functions like get_value, get_item, and is_event_finished take integer IDs, not string names. The IDs correspond to entries in the game’s internal data tables.

Place IDs

Common PlaceID values for map locations:
IDLocation
1Town Square
2Market
9Forest Clearing
12Castle Entrance
Place IDs are based on game analysis and may vary. Check game files for accurate mappings.

Loading Config

After creating or modifying config files, load them into the game:
  1. In VS Code, open the Command Palette (Ctrl+Shift+P)
  2. Run nonkit: Load Config Tables (or use nonkit: Load All to load everything)
  3. The plugin will inject the config data into the running game
Injecting config doesn’t immediately show new quests. The game only checks for available quests at certain points (like the start of a new day). After loading config, advance to the next day by resting to trigger a refresh. Your quest should then appear on the map.
  1. Make sure you’re on the guild view
  2. Run nonkit: Load All to inject scripts, localization, and config
  3. Rest or otherwise advance to the next day
  4. Check the map for your new quest (e.g., at the Forest location for PlaceID 9)
Config tables are identified by filename. TbMapEvent.json is recognized as the TbMapEvent table. Renaming the file changes which table it maps to.

Tips

Start custom IDs at 900000+ to avoid conflicts with game content.
Start with "Conditions": "true" to verify your event appears, then add actual conditions.
Use items as quest tokens via change_item and get_item to track quest progress and unlock subsequent events.
Always call <<event_end>> at the end of your dialogue to return control to the game.

Next Steps