NPCs & Path System
NPCs & Path System
Section titled “NPCs & Path System”Journey extends Cobblemon’s NPC system with MoLang scripting functions and an automated path walking system. Make NPCs play animations, spawn particles, say messages, and walk patrol routes — all without writing code.
NPC Scripting Functions
Section titled “NPC Scripting Functions”These functions are available in Cobblemon NPC dialogue scripts and interactions. Call them on the npc object.
Animation
Section titled “Animation”npc.play_animation('wave')npc.play_animation('point', 'player-uuid-here')| Function | Description |
|---|---|
npc.play_animation(name) | Play animation for all nearby players |
npc.play_animation(name, playerUuid) | Play animation for a specific player only |
Returns 1.0 on success, 0.0 on failure.
Chat Messages
Section titled “Chat Messages”npc.say('Hello there! I am %npc%!')npc.say('Welcome back, trainer!', 'player-uuid')| Function | Description |
|---|---|
npc.say(message) | Send message to all players within 64 blocks |
npc.say(message, playerUuid) | Send message to a specific player |
Use %npc% as a placeholder for the NPC’s name.
Distance
Section titled “Distance”npc.distance_to_player('player-uuid')Returns distance in blocks between the NPC and the specified player.
Path Walking Functions
Section titled “Path Walking Functions”Control NPC patrol routes from scripts.
| Function | Returns | Description |
|---|---|---|
npc.walk_path('path_id') | 1.0/0.0 | Start walking a path |
npc.stop_walking() | 1.0/0.0 | Stop the current path |
npc.pause_walking() | 1.0/0.0 | Pause (can resume later) |
npc.resume_walking() | 1.0/0.0 | Resume a paused path |
npc.is_walking_path() | 1.0/0.0 | Check if currently walking |
npc.walking_progress() | 0.0-100.0 | Progress percentage along path |
npc.assign_path('path_id') | 1.0 | Assign path (persists across restarts) |
npc.assign_path('path_id', 0.0) | 1.0 | Assign path without auto-starting |
npc.unassign_path() | 1.0 | Remove assigned path |
npc.has_assigned_path() | 1.0/0.0 | Check if a path is assigned |
npc.get_assigned_path() | String | Get assigned path ID (empty if none) |
Creating Paths
Section titled “Creating Paths”Paths are JSON files that define a sequence of waypoints for NPCs to walk.
File location: config/journey/paths/<name>.json
Path Structure
Section titled “Path Structure”{ "id": "guard_patrol", "name": "Guard Patrol Route", "nodes": [ { "position": {"x": 100, "y": 64, "z": 100}, "look_target": {"x": 100, "y": 64, "z": 110}, "script": "q.wait_seconds(2);" }, { "position": {"x": 120, "y": 64, "z": 100}, "look_target": {"x": 120, "y": 64, "z": 110}, "script": "q.wait_seconds(2);" }, { "position": {"x": 120, "y": 64, "z": 120}, "script": "q.wait(10);" } ], "loop": true, "speed_multiplier": 0.8, "description": "Rectangular patrol with 2-second pauses"}Path Fields
Section titled “Path Fields”| Field | Type | Default | Description |
|---|---|---|---|
id | String | Required | Unique identifier |
name | String | Required | Human-readable name |
nodes | Array | Required | List of waypoints (at least 1) |
loop | Boolean | false | Repeat from beginning after reaching the end |
speed_multiplier | Float | 1.0 | Movement speed (0.5 = slow, 2.0 = fast) |
description | String | "" | Optional description |
Node Fields
Section titled “Node Fields”| Field | Type | Required | Description |
|---|---|---|---|
position | {x, y, z} | Yes | World coordinates to walk to |
look_target | {x, y, z} | No | Coordinates NPC faces at this node |
script | String | No | MoLang to execute when NPC reaches this node |
If look_target is omitted, the NPC looks toward the next node.
Node Scripts
Section titled “Node Scripts”Scripts run when the NPC arrives at a node. Common uses:
{"script": "q.wait_seconds(5);"}{"script": "q.wait(20);"}{"script": ""}| Function | Description |
|---|---|
q.wait(ticks) | Pause for a number of ticks (20 ticks = 1 second) |
q.wait_seconds(seconds) | Pause for a number of seconds |
q.is_waiting() | Returns 1.0 if currently paused |
q.wait_remaining() | Remaining wait ticks |
Assigning Paths to NPCs
Section titled “Assigning Paths to NPCs”Via Config File
Section titled “Via Config File”File: config/journey/npc_paths.json
[ { "npc_uuid": "0af627fe-3254-48b0-9892-881a42512c43", "assigned_path_id": "guard_patrol", "auto_start": true, "current_index": 0, "is_complete": false, "is_paused": false, "reach_threshold": 0.9 }]| Field | Default | Description |
|---|---|---|
npc_uuid | Required | UUID of the Cobblemon NPC entity |
assigned_path_id | Required | Path ID to follow |
auto_start | true | Start walking when the NPC loads |
current_index | 0 | Current waypoint (auto-managed) |
is_complete | false | Whether the path finished (auto-managed) |
is_paused | false | Whether walking is paused |
reach_threshold | 0.9 | Blocks away to count as “arrived” at a node |
Via MoLang Script
Section titled “Via MoLang Script”npc.assign_path('guard_patrol')This persists across server restarts.
Movement Behavior
Section titled “Movement Behavior”| Multiplier | Feel |
|---|---|
0.5 | Slow, cautious |
0.8 | Patrol pace |
1.0 | Normal walking |
1.5 | Brisk walk |
2.0 | Running |
Reach Threshold
Section titled “Reach Threshold”How close the NPC must get before moving to the next node:
0.2-0.5— Precise positioning (tight spaces)0.9— Default (works for most paths)1.5-2.0— Forgiving (rough terrain)
Looping
Section titled “Looping”loop: true— Returns to the first node after reaching the last. Repeats forever. Use for patrols and circular routes.loop: false— Stops at the last node. Use for one-way deliveries or scripted movement.
Stuck Detection
Section titled “Stuck Detection”The system automatically handles stuck NPCs:
- If an NPC moves less than 0.05 blocks for 3 seconds, it’s considered stuck
- If close to the target node, it force-advances to the next node
- If far from the target, it gets a speed boost and gentle push toward the waypoint
Progress Persistence
Section titled “Progress Persistence”Path progress saves automatically:
- Every 10 seconds during normal walking
- When the path completes, is paused, or is cancelled
- When the NPC unloads
On server restart, NPCs resume from their saved position.
Path Visualization
Section titled “Path Visualization”Preview paths in-game using particle effects.
Enable via MoLang
Section titled “Enable via MoLang”q.player.toggle_path_visualization()q.player.show_path_visualization(true)q.player.preview_path('guard_patrol')Enable via GUI
Section titled “Enable via GUI”/journey pathmanagerOpens an interactive editor for creating, editing, and previewing paths.
What You See
Section titled “What You See”- END_ROD particles connect nodes in sequence
- ENCHANT particles show the loop connection (last node back to first)
- Circular markers at each waypoint
- Arrows showing look direction
- Visible up to 64 blocks away, updates every 0.5 seconds
Examples
Section titled “Examples”Traveling Merchant
Section titled “Traveling Merchant”{ "id": "merchant_route", "name": "Traveling Merchant Route", "nodes": [ { "position": {"x": 0, "y": 64, "z": 0}, "look_target": {"x": 5, "y": 64, "z": 0}, "script": "q.wait_seconds(30);" }, { "position": {"x": 100, "y": 64, "z": 0}, "script": "" }, { "position": {"x": 100, "y": 64, "z": 100}, "look_target": {"x": 105, "y": 64, "z": 105}, "script": "q.wait_seconds(30);" }, { "position": {"x": 0, "y": 64, "z": 100}, "script": "" } ], "loop": true, "speed_multiplier": 0.6, "description": "Merchant visits two towns, stays 30 seconds at each"}One-Way Messenger
Section titled “One-Way Messenger”{ "id": "messenger_delivery", "name": "Urgent Delivery", "nodes": [ {"position": {"x": 0, "y": 64, "z": 0}, "script": ""}, {"position": {"x": 50, "y": 64, "z": 50}, "script": "q.wait(10);"}, { "position": {"x": 100, "y": 64, "z": 0}, "look_target": {"x": 110, "y": 64, "z": 0}, "script": "q.wait_seconds(5);" } ], "loop": false, "speed_multiplier": 1.5, "description": "Fast one-way delivery"}Scripted NPC Behavior
Section titled “Scripted NPC Behavior”// In a Cobblemon dialogue script:npc.play_animation('greet');npc.say('Welcome, %npc% here!');
// Conditional message based on player stateq.player.has_flag('quest_available') ? npc.say('I have a quest for you!') : 0.0- Add intermediate nodes for smooth turns instead of sharp corners
- Space nodes 2-5 blocks apart for curved paths, 10-20 blocks for straight routes
- Match speed to the NPC’s role: guards patrol slowly (0.7-0.9), messengers run fast (1.3-1.8)
- Use
look_targetto point NPCs at interesting things (shops, signs, other NPCs) when they pause - Use descriptive path IDs:
town_guard_patrol_northis better thanpath_1 - Test paths with visualization before assigning to NPCs
- If an NPC gets stuck, try increasing
reach_thresholdto 1.5 or adding intermediate nodes