Create Your First NPC Template
This guide creates a minimal NPC template and binds it to the Lua brain from the previous tutorial.
By the end, you will:
- create one mobile template JSON file
- validate it with
moongate-template - spawn the NPC in game with
.add_npc - confirm that the Lua brain is actually running
Before You Start
Finish this guide first:
That guide creates and registers the tutorial_cat_brain Lua table used below.
You also need:
- your shard root is
~/moongate moongate-templateis installed- your server is configured to run against
~/moongate - you can log in with an account that can run
.add_npcon your shard
Step 1: Create The Template File
Create this folder:
~/moongate/templates/mobiles/tutorial/
Inside it, create:
~/moongate/templates/mobiles/tutorial/first_npc.json
Step 2: Paste A Complete Minimal NPC Template
Put this content in the file:
[
{
"type": "mobile",
"id": "tutorial_cat",
"category": "tutorial",
"description": "My first scripted Moongate NPC.",
"tags": ["tutorial", "animals", "test"],
"ai": {
"brain": "tutorial_cat_brain",
"fightMode": "none",
"rangePerception": 16,
"rangeFight": 1
},
"name": "Tutorial Cat",
"title": "your first scripted NPC",
"variants": [
{
"appearance": {
"body": "0x00C9",
"skinHue": 779,
"hairHue": 0,
"hairStyle": 0
},
"equipment": []
}
]
}
]
This file is a JSON array with one mobile template object inside it. Keep the outer [ and ].
What the important fields mean:
type: this document contains mobile templatesid: the template id you will use with.add_npcai.brain: the Lua table name that will drive the NPC behaviorfightMode,rangePerception,rangeFight: standard AI fields used by current mobile templatesnameandtitle: the in-game name shown to playersvariants: appearance and equipment choices for the mobileappearance.body: the UO body idequipment: starting worn or carried equipment for that variant; empty is fine for a tutorial cat
If you later point a template at the guard brain, patrol stays opt-in and uses the same params shape documented in NPC Behaviors:
{
"params": {
"patrol_mode": { "type": "string", "value": "random_roam" },
"patrol_radius": { "type": "string", "value": "6" }
}
}
patrol_radius stays string-backed in template JSON because mobile params do not have a separate numeric param type.
The tutorial cat above does not use these settings, and the current production guard templates do not set them either.
Step 3: Validate The Template
Run:
moongate-template validate --root-directory ~/moongate
Expected result:
- validation completes successfully
If the validator fails, fix that before trying to spawn the NPC.
Step 4: Restart The Server
If the server is already running, restart it so both the template and the Lua brain are definitely loaded.
Step 5: Spawn The NPC In Game
Log in with an account that can run the in-game NPC spawn command and type:
.add_npc tutorial_cat
Then click a nearby ground tile.
Expected result:
- the NPC appears where you clicked
- after a few seconds, it says
Hello! My first Moongate brain is running. - if you say
hellonear it, it repliesHello back to you.
Common Mistakes
- Typo in
ai.brain - Forgetting to register the Lua brain in
~/moongate/scripts/ai/init.lua - Editing the wrong tree (
moongate_data/in the repo instead of~/moongate/in your shard root) - Forgetting the outer JSON array
Next Step
Once this works, move to the reference docs for deeper behavior work: